What are valid values of `HAL_NVIC_SetPriority()` when using STM32 and FreeRTOS?

panther3001 wrote on Wednesday, May 09, 2018:

After a rather difficult process of learning some things about interrupt priority, I am still a bit stuck trying to understand what values I am allowed to call for HAL_NVIC_SetPriority() on the SysTick_IRQn (which is the ISR calling the FreeRTOS scheduler every 1 ms). Part of me thinks that anything between HAL_NVIC_SetPriority(SysTick_IRQn, 15 ,0U) (lowest priority possible) and HAL_NVIC_SetPriority(SysTick_IRQn, 10 ,0U) (a bit higher) are allowed, and part of me thinks that anything between HAL_NVIC_SetPriority(SysTick_IRQn, 15 ,0U) (lowest priority possible) and HAL_NVIC_SetPriority(SysTick_IRQn, 5 ,0U) (quite a bit higher) is allowed. This is assuming that configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY in FreeRTOSConfig.h is set to 5. The confusion lies in the fact that in FreeRTOS, higher numbers are higher priority, but in STM32, higher numbers are lower priority, and the documentation is pretty challenging to understand.

Deleted links to other forums - its not helpful to readers of this forum to split threads across different forums on different sites - especially when this site is archived.

rtel wrote on Wednesday, May 09, 2018:

It sounds like you are confusing interrupt priorities and task priorities.

Interrupts are controlled by hardware and the hardware tires to confuse you by making high numbers mean low priority (https://www.freertos.org/RTOS-Cortex-M3-M4.html). FreeRTOS can have no effect on how the hardware defines or executes interrupts.

Task priorities are controlled in software, the FreeRTOS kernel to be more specific. FreeRTOS uses 0, as the smallest possible unsigned value, to mean the lowest possible priority. That is the same across all architectures - most non ARM architectures also using low numbers to mean low priorities.

Just as when writing any software, be it using an RTOS or not, non interrupt software will only execute if there are no interrupts executing, no matter what priority is assigned to the software tasks or the hardware interrupts.

Interrupt safe FreeRTOS functions can only be called from an interrupt that is logically between the lowest possible priority on the hardware, and configMAX_SYSCALL_INTERRUPT_PRIORITY - on ARM it happens that configMAX_SYSCALL_INTERRUPT_PRIORITY has a lower numeric (but higher logical) value than the lowest possible priority. The page I’ve linked to above attempts to explain this - but yes the hardware makes this complex, unfortunately.

Now to your other point about the SysTick interrupt. The kernel sets the systick priority, you should not set it at all. Normally it would be the lowest possible priority, but in the case of using the STM32 HAL it sometimes has to be the highest possible priority because the STM32 HAL interrupts poll the systick value, which cannot change if the interrupt doing the polling is blocking the interrupt that changes the systick value - that is generally not a good idea though as interrupts should be as short as possible.