17.08.2016 15:49

STM32 interrupt priorities confusion

...also called NVIC and SCB story. The NVIC (nested vector interrupt controler) is modified in STM32 compared to ARM and includes the EXTI controller for "external" interrupts - enhancement to allow interrupts from GPIOs etc. This is described in most important document called "Referrence Manual". However such important thing like setting of NVIC itself and SCB (system control block) is for some reason in separate document called "Programming Manual". This would not be that bad, if the Programming Manual is not somewhat weak regarding interrupt priorities setup.


Interrupt system is complicated enough to make it work correctly even with a good documentation. Let's make it worse with bad documentation. Especially because ST is deviating from ARM specification of this. This makes a real mess of it.

First compare the SCB PRIGROUP setup that defines how priority bits are divided between pre-emption and subpriorities (sometimes called group priorities and subpriorities).

Let's compare the ARM and ST doc here:

PRIGROUPBinary point [a]Group priority bitsSubpriority bitsGroup prioritiesSubpriorities

Now ST (this is for F1, F2 latest version as of today:

Here comes the first part of confusion.
1. the default reset value of PRIGROUP bits in SCB AIRCR register is 0b000 - well that is then the default division of priority bits in STM32? You may find the F4 spec has a first row with
0b0xx - ohooo, somebody spotted in latest version of F4 doc, that this is a very essential info to include.
2. you may see the STM32 doc is having somewhat less bit per priority. Yes it does - only 4 in UPPER half of SCB register SHPR* with PRI_* fields. This means that if you write to a low part of byte you silently set no interrupt priority leaving to to 0.
3. last but not least typo in the doc sometimes state e.g. bits [7:3] or [7:0] or nothing instead [7:4] depending on the version of doc you hit...

Now you may find all over the net various examples that set NVIC_PriorityGroupConfig (STM32) or NVIC_SetPriorityGrouping (CMSIS). Each example is fiddling with group priority, but this is WRONG as it completely changes the meaning of priorities already set in SHPR registers. You have to set it once for whole application and not that every library sets it at its own.

Also make sure you use STM specific functions here as CMSIS relies on ARM spec.This way you may end up with interrupt system set the way that all interrupts have priority 0 and are in the same "group" - i.e. preemption = there is no preemption at all.

Refs.: Cutting Through the Confusion with ARM Cortex-M Interrupt Priorities

Email comment