NVIC User Interrupt Priority - freertos

Im using FreeRTOX V9.0.0 on a Cortex M3 (Silicon Labs EFM32GG380F1024).
I get a assert failure when i use the TaskResumeFromISR via the GPIO Irq Handler.
The assert fails here in port.c (GCC ARM CM3) in function "void vPortValidateInterruptPriority( void )"
on line "configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );"
The values are: ucCurrentPriority is 0 and ucMaxSysCallPriority is 160.
// NVIC CORTEX M3
#define configPRIO_BITS 3
// FreeRTOS Config
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ( 0x05 )
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
// port.c
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; // ( ( 0x05 ) << (8 - ( 3 )) ) & 224 = 160
In the user code, when i read the interrupt priority (where i currently use default "0") i get all interrupt priorities are zero except the 2
that are set up by the kernel (PendSV and Systick) which are 7.
// user code
prio = hal::nvic::getPriority(NonMaskableInt_IRQn); // =0
prio = hal::nvic::getPriority(HardFault_IRQn); // =0
prio = hal::nvic::getPriority(MemoryManagement_IRQn); // =0
prio = hal::nvic::getPriority(BusFault_IRQn); // =0
prio = hal::nvic::getPriority(UsageFault_IRQn); // =0
prio = hal::nvic::getPriority(SVCall_IRQn); // =0
prio = hal::nvic::getPriority(DebugMonitor_IRQn); // =0
prio = hal::nvic::getPriority(PendSV_IRQn); // =7
prio = hal::nvic::getPriority(SysTick_IRQn); // =7
prio = hal::nvic::getPriority(GPIO_EVEN_IRQn); // =0
prio = hal::nvic::getPriority(GPIO_ODD_IRQn); // =0
prio = hal::nvic::getPriority(USART1_RX_IRQn); // =0
prio = hal::nvic::getPriority(USART1_TX_IRQn); // =0
prio = hal::nvic::getPriority(LETIMER0_IRQn); // =0
prio = hal::nvic::getPriority(RTC_IRQn); // =0
prio = hal::nvic::getPriority(BURTC_IRQn); // =0
As soon as i define my interrupt priority 7 or higher, i have no more trouble.
When i now define each priority for each interrupt, what values can i use (where lower is higher priority and i should go bigger
than 7 since my interrupts should have lower prio than the kernel).
So should i start at 8 and go up until where??
Thank you

The lower the interrupt priority number the higher the actual priority. So 0 is the highest priority.
I think on the EFM32GG there are only 3 priority bits so priorities available are 0 to 7. (If there are 4 priority bits the available priorities are 0 to 15).
This priority bits are left shifted into the top bits. Therefore the available priorities are:
0 << 5 (0) - Highest.
1 << 5 (32)
2 << 5 (64)
3 << 5 (96)
4 << 5 (128)
5 << 5 (160)
6 << 5 (192)
7 << 5 (224) - Lowest
Sometimes the 5 unused bits are padded with zero's. So for example 224 is the same priority as 255 as the lowest 5 bits make no difference to the operation of the processsor (however they will affect the asserts).
You cannot make FreeRTOS API calls from interrupts that have a higher priority than configMAX_SYSCALL_INTERRUPT_PRIORITY. However you can change the value of this to suit your needs.

Related

Round negative values to zero in influx query?

I'm trying to set a lower bounds of zero on my influx query result so that negative values are replaced with zero in the result. e.g. For the query:
SELECT x from measurement
If my raw response is
time x
---- -
1632972969471900180 0
1632972969471988621 -130
1632972969472238055 803
then i want to alter the query so that the result is:
time x'
---- -
1632972969471900180 0
1632972969471988621 0
1632972969472238055 803
My solution was to use the ABS absolute value function, adding the absolute value to the original value and dividing by 2. This maps negative values to zero and leaves posiive (and zero) values unchanged. e.g.
SELECT (x + ABS(x)) / 2 from measurement
time x x'
---- - -
1632972969471900180 0 = 0 + 0 / 2 = 0
1632972969471988621 -130 = -130 + 130 / 2 = 0
1632972969472238055 803 = 803 + 803 / 2 = 803

256 possible values in a 8 bits

I am confused when I read the details section that says 1 byte which is 8 bits gives us a potential of 2^8 or 256 possible values. (https://en.wikipedia.org/wiki/8-bit_computing)
If i am doing the math correctly
2^0 = 1
2^1 = 2
2^2 = 4
2^3 = 8
2^4 = 16
2^5 = 32
2^6 = 64
2^7 = 128
Total = 255
The way i see it there is total or possible 255 values.
0 is also a value so for 8 bits, the value range is 0-255.
00000000 is the lowest and 11111111 (255) is the highest.
2^x gives you the total number of possible values for x bits. You should be using 2^x to get the number of possible combinations only where x > 0. If x = 0, it points to a no-bit scenario which is irrelevant.
For your case, it is not correct to sum values from 2^0 to 2^7. The correct approach should be just calculating 2^8, which is 256.

What exactly are the transaction metrics reported by NVPROF?

I'm trying to figure out what exactly each of the metrics reported by "nvprof" are. More specifically I can't figure out which transactions are System Memory and Device Memory read and writes. I wrote a very basic code just to help figure this out.
#define TYPE float
#define BDIMX 16
#define BDIMY 16
#include <cuda.h>
#include <cstdio>
#include <iostream>
__global__ void kernel(TYPE *g_output, TYPE *g_input, const int dimx, const int dimy)
{
__shared__ float s_data[BDIMY][BDIMX];
int ix = blockIdx.x * blockDim.x + threadIdx.x;
int iy = blockIdx.y * blockDim.y + threadIdx.y;
int in_idx = iy * dimx + ix; // index for reading input
int tx = threadIdx.x; // thread’s x-index into corresponding shared memory tile
int ty = threadIdx.y; // thread’s y-index into corresponding shared memory tile
s_data[ty][tx] = g_input[in_idx];
__syncthreads();
g_output[in_idx] = s_data[ty][tx] * 1.3;
}
int main(){
int size_x = 16, size_y = 16;
dim3 numTB;
numTB.x = (int)ceil((double)(size_x)/(double)BDIMX) ;
numTB.y = (int)ceil((double)(size_y)/(double)BDIMY) ;
dim3 tbSize;
tbSize.x = BDIMX;
tbSize.y = BDIMY;
float* a,* a_out;
float *a_d = (float *) malloc(size_x * size_y * sizeof(TYPE));
cudaMalloc((void**)&a, size_x * size_y * sizeof(TYPE));
cudaMalloc((void**)&a_out, size_x * size_y * sizeof(TYPE));
for(int index = 0; index < size_x * size_y; index++){
a_d[index] = index;
}
cudaMemcpy(a, a_d, size_x * size_y * sizeof(TYPE), cudaMemcpyHostToDevice);
kernel <<<numTB, tbSize>>>(a_out, a, size_x, size_y);
cudaDeviceSynchronize();
return 0;
}
Then I run nvprof --metrics all for the output to see all the metrics. This is the part I'm interested in:
Metric Name Metric Description Min Max Avg
Device "Tesla K40c (0)"
Kernel: kernel(float*, float*, int, int)
local_load_transactions Local Load Transactions 0 0 0
local_store_transactions Local Store Transactions 0 0 0
shared_load_transactions Shared Load Transactions 8 8 8
shared_store_transactions Shared Store Transactions 8 8 8
gld_transactions Global Load Transactions 8 8 8
gst_transactions Global Store Transactions 8 8 8
sysmem_read_transactions System Memory Read Transactions 0 0 0
sysmem_write_transactions System Memory Write Transactions 4 4 4
tex_cache_transactions Texture Cache Transactions 0 0 0
dram_read_transactions Device Memory Read Transactions 0 0 0
dram_write_transactions Device Memory Write Transactions 40 40 40
l2_read_transactions L2 Read Transactions 70 70 70
l2_write_transactions L2 Write Transactions 46 46 46
I understand the shared and global accesses. The global accesses are coalesced and since there are 8 warps, there are 8 transactions.
But I can't figure out the system memory and device memory write transaction numbers.
It helps if you have a model of the GPU memory hierarchy with both logical and physical spaces, such as the one here.
Referring to the "overview tab" diagram:
gld_transactions refer to transactions issued from the warp targetting the global logical space. On the diagram, this would be the line from the "Kernel" box on the left to the "global" box to the right of it, and the logical data movement direction would be from right to left.
gst_transactions refer to the same line as above, but logically from left to right. Note that these logical global transaction could hit in a cache and not go anywhere after that. From the metrics standpoint, those transaction types only refer to the indicated line on the diagram.
dram_write_transactions refer to the line on the diagram which connects device memory on the right with L2 cache, and the logical data flow is from left to right on this line. Since the L2 cacheline is 32 bytes (whereas the L1 cacheline and size of a global transaction is 128 bytes), the device memory transactions are also 32 bytes, not 128 bytes. So a global write transaction that passes through L1 (it is a write-through cache if enabled) and L2 will generate 4 dram_write transactions. This should explain 32 out of the 40 transactions.
system memory transactions target zero-copy host memory. You don't seem to have that so I can't explain those.
Note that in some cases, for some metrics, on some GPUs, the profiler may have some "inaccuracy" when launching very small numbers of threadblocks. For example, some metrics are sampled on a per-SM basis and scaled. (device memory transactions are not in this category, however). If you have disparate work being done on each SM (perhaps due to a very small number of threadblocks launched) then the scaling can be misleading/less accurate. Generally if you launch a larger number of threadblocks, these usually become insignificant.
This answer may also be of interest.

PGMidi changing pitch sendBytes example

I'm trying the second day to send a midi signal. I'm using following code:
int pitchValue = 8191 //or -8192;
int msb = ?;
int lsb = ?;
UInt8 midiData[] = { 0xe0, msb, lsb};
[midi sendBytes:midiData size:sizeof(midiData)];
I don't understand how to calculate msb and lsb. I tried pitchValue << 8. But it's working incorrect, When I'm looking to events using midi tool I see min -8192 and +8064 max. I want to get -8192 and +8191.
Sorry if question is simple.
Pitch bend data is offset to avoid any sign bit concerns. The maximum negative deviation is sent as a value of zero, not -8192, so you have to compensate for that, something like this Python code:
def EncodePitchBend(value):
''' return a 2-tuple containing (msb, lsb) '''
if (value < -8192) or (value > 8191):
raise ValueError
value += 8192
return (((value >> 7) & 0x7F), (value & 0x7f))
Since MIDI data bytes are limited to 7 bits, you need to split pitchValue into two 7-bit values:
int msb = (pitchValue + 8192) >> 7 & 0x7F;
int lsb = (pitchValue + 8192) & 0x7F;
Edit: as #bgporter pointed out, pitch wheel values are offset by 8192 so that "zero" (i.e. the center position) is at 8192 (0x2000) so I edited my answer to offset pitchValue by 8192.

How can I use a page table to convert a virtual address into a physical one?

Lets say I have a normal page table:
Page Table (Page size = 4k)
Page #: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Page Frame #: 3 x 1 x 0 x 2 x 5 x 7 4 6 x x x
How can I convert an arbitrary logical address like 51996 into a physical memory address?
If I take log base 2 (4096), I get 12. I think this is how many bits I'm suppose to use for the offset of my address.
I'm just not sure. 51996 / 4096 = 12.69. So does this mean it lay on page#12 with a certain offset?
How do I then turn that into the physical address of "51996"?
To determine the page of a given memory address, take the first P bits (of the N bit) number.
P = lg2(numberOfPages)
In your example, P=lg2(16)=4
So the first 4 bits of a given memory address will tell us the page. That means the rest should be the offset from the start of that page.
Your example address, 51996, is 1100101100011100 in binary. I.e. [1100:101100011100].
1100 (12 in decimal) is the page number
101100011100 (2844 in decimal) is the offset
Now we need to find where page 12 is in memory.
Looking at your frame table, it appears that page 12 is resident in the 6th frame. In a system where all memory is pageable (i.e. no memory mapped IO) the 6th page frame will be at (entriesPerPage*frameNum)-1
In this case, 4000*6-1 = 23999 (The "-1" is needed since memory is 0-indexed.)
In this case, 4096*6-1 = 24575 (The "-1" is needed since memory is 0-indexed.)
Now all we have to do is add the offset and we have the physical memory address:
23999 + 2844=26843 = 0x68DB
24575 + 2844 = 27419 = 0x6B1B
Done!
Hope this (edit) was helpful XD
Edit:
Thanks to Jel for catching my mistake :)
Thanks to user8 for catching my other mistake! (frameNum instead of pageNum).
If I understand your question correctly (I probably don't), you want to know how to find the physical address from the virtual address using the page table structures. In that case, pretend you are the processor. Use the 10 most significant bits of the address to find the page table in the page directory (the top level page table). The next 10 bits are the index into the page table (the lower level page table). Use the address in that page table entry to find the physical page address. The last ten bits are the byte address into the page.
By the way, you would probably find a lot more people who would understand this type of question at an OS oriented site such as OSDev. I couldn't really go into much detail in this answer because I haven't done this type of stuff in years.
This is might help:
import java.util.Arrays;
import java.util.Scanner;
public class Run {
private static Scanner input = new Scanner(System.in);
public static void main(String[] args) {
System.out.println("////////// COMMANDS //////////");
System.out.println("Snapshot: S(enter)r, S(enter)m, S(enter)x, S(enter)p, S(enter)d, S(enter)c");
System.out.println("time: t");
System.out.println("Terminate: T#");
System.out.println("Kill: K#");
System.out.println("Start process: A");
System.out.println("Quit program: quit");
System.out.println("Deletes device: delete");
System.out.println ("//////////////////////////////");
OS myComputer;
int hdd, cdd, printer, cpu, mem, page;
hdd = cdd = printer = cpu = 20;
mem = 1;
page = 1;
System.out.println("");
System.out.println("|||| SYS GEN ||||");
System.out.println("");
mem = 0;
System.out.println("Number of Hard-Drives:");
while (hdd > 10) {
String inpt = input.next();
while (Asset.isInt(inpt) == false)
inpt = input.next();
hdd = Integer.parseInt(inpt);
if (hdd > 10)
System.out.println("Try something smaller (less than 10)");
}
System.out.println("Number of CD-Drives: ");
while (cdd > 10) {
String inpt = input.next();
while (Asset.isInt(inpt) == false)
inpt = input.next();
cdd = Integer.parseInt(inpt);
if (cdd > 10)
System.out.println("Try something smaller (less than 10)");
}
System.out.println("Number of Printers:");
while (printer > 10) {
String inpt = input.next();
while (Asset.isInt(inpt) == false)
inpt = input.next();
printer = Integer.parseInt(inpt);
if (printer > 10)
System.out.println("Try something smaller (less than 10)");
}
System.out.println("Amount of Memory:");
while (mem <= 0) {
String inpt = input.next();
if (Asset.isInt(inpt))
mem = Integer.parseInt(inpt);
if (mem<=0)
System.out.println("The memory size must be greater than zero.");
else
break;
}
Integer[] factors = Asset.factors(mem);
System.out.println("Enter a page size: "+Arrays.toString(factors));
while (true) {
String inpt = input.next();
while (Asset.isInt(inpt) == false)
inpt = input.next();
if (Asset.inArray(factors, Integer.parseInt(inpt))) {
page = Integer.parseInt(inpt);
break;
} else {
System.out.println("Page size must be one of these -> "+Arrays.toString(factors));
}
}
System.out.println("Number of CPUs (max10):");
while (cpu > 10) {
String inpt = input.next();
while (Asset.isInt(inpt) == false)
inpt = input.next();
cpu = Integer.parseInt(inpt);
if (cpu > 10)
System.out.println("Try something smaller (less than 10)");
}
myComputer = new OS(cpu, hdd, cdd, printer, mem, page);
myComputer.Running();
}
}
first step : 51996 / 4000 = 12 -> p , remain= 3996 -> d (offset).
now look at the table p(12) = 6
second step : (6*4000) + 3996 : 27996
the physical address is 27996.
The following page table is for a system with 16-bit virtual and physical addresses and with 4,096-byte pages. The reference bit is set to 1 when the page has been referenced. Periodically, a thread zeroes out all values of the reference bit. A dash for a page frame indicates the page is not in memory. The page-replacement algorithm is localized LRU, and all numbers are provided in decimal.
Page Page Frame Reference Bit
0 9 0
1 1 0
2 14 0
3 10 0
4 - 0
5 13 0
6 8 0
7 15 0
8 0 0
9 - 0
10 5 0
11 4 0
12 - 0
13 3 0
14 - 0
15 2 0
a. Convert the following virtual addresses (in hexadecimal) to the equivalent physical addresses (provide answers in hexadecimal AND decimal). Also set the reference bit for the appropriate entry in the page table. (3)
i. 0xBC2C
ii. 0x00ED
iii. 0xEA14
iv. 0x6901
v. 0x23A1
vi. 0xA999

Resources