FreeRTOS and NVIC Interrupt Nesting

maeikel wrote on Thursday, October 20, 2011:


I have a question about how FreeRTOS kernel and NVIC Interrupt nesting  work together.
I’m running FreeRTOS on the STM3210E-Eval-Board.
I would like to know how the priorities are according to each other.
Therefore, I made the following definitions within FreeRTOSConfig.h:

#define configKERNEL_INTERRUPT_PRIORITY (15 << (8-configPRIO_BITS)) /* equivalent to NVIC priority 15 */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY (3 << (8-configPRIO_BITS)) /* equivalent to NVIC priority  3 */

where configPRIO_BITS was defined as 4 and the number of priority levels was chosen to 5.

Furthermore, I have two tasks running. One is just doing some stupid work (togeling an LED and incrementing a counter), whereas the other task blocks on a binary semaphore which is activated over a button-press isr call to the EXTI15_10_IRQHandler (stm32f10x_it.c)

Now I wanted to test whether I can put the NVIC Priorities such that whatever interrupt occurs, my highest priority 5 task is not disturbed. For me the logical consequence would be that interrupts with NVIC Priority of (configMAX_SYSCALL_INTERRUPT_PRIORITY+1) and higher would never interrupt my highest priority task.

So setting a priority of 5 for both tasks (LED toggling and Button Task) with a NVIC Priority of configMAX_SYSCALL_INTERRUPT_PRIORITY+1 for the button-interrupt, the LED toggling task get’s still interrupted. Even if I set the NVIC pririty of the button interrupt to 0x0F (lowest priority for NVIC_PriorityGroup_4).

Does anyone know, what I missunderstand? Because my basic problem I wanted to face with this little test setup is that I’m reading from 2 SPI busses parallelly in two different tasks. The reading itself (setting the chip selects and reading spi data) I want to prevent from being disturbed, as I have other parallel tasks running and the data I get up to now is not reliable.

I tried out mutual exclusion. This at least prevents my two spi tasks to read from the same spi at the time. But it’s not assured that this section is not interrupted though by some other higher priority tasks or any kind of NVIC interrupt (as it seems to me after my little test). Or does one use critical sections in this case? But this critical sections disable the NVIC interrupts at all, but what I want is that the NVIC interrupts are though handled, but after my Priority 5 Tasks have finished.

Thank you for your help



And what is the “configLIBRARY_KERNEL_INTERRUPT_PRIORITY” good for?!

edwards3 wrote on Thursday, October 20, 2011:

Your post is very confused. Risking a statement of the obvious - you do know that interrupt priorities and task priorities are completely different? Interrupt priorities are set by hardware, task priorities are set by software and tasks only ever run when no interrupts are running.

Cortex-M3 cores have a maximum of 8 bits used for setting interrupt priorities. Most only implement a subset of these. configPRIO_BITS sets the number actually used. The used bits are shifted into the most significant bits of the 8 bit priority. A library function that sets an interrupt priority might want its priority specified with the bits shifted into their correct places or with the bits in the least significant of the 8 total bits. In the latter case, the library function does the shift itself. configLIBRARY_KERNEL_INTERRUPT_PRIORITY holds the unshifted priority, for cases where this is needed because that is how the library function wants it.

Are you confused? You should be, everybody else is. The cortex-m3 designer was obviously taking crack cocaine.

maeikel wrote on Friday, October 21, 2011:


Thx for you quick reply. It is indeed very confusing to me and I agree that the designer must have taken crack cocaine, for sure:)

Hmm… let me put it this way:

Say I want a section within a task prevent from being interupted (no matter whether by a hardware interrupt or by a higher priority task). But this section is held very short. If a higher priority task is pending, then it should be served after leaving this critical section. How do I need to implement this savety? There is no way of checking whether my critical section got interrupted or not, right?



rtel wrote on Friday, October 21, 2011:

You don’t actually need to do anything.  Consider the scenario:

1) You are in a task and call taskENTER_CRITICAL(), before executing a short piece of code.

2) Before calling taskEXIT_CRITICAL(), an interrupt occurs.  The interrupt cannot execute as interrupts are masked in the hardware, so instead it is held pending.

3) Your task calls taskEXIT_CRITICAL().  That un-masks the interrupt that is already pending, so the hardware interrupts your task and processes the interrupt automatically.