ARM Cortex-M Interrupts Priority and Priority Grouping
ARM Cortex-M provides a very flexible way of interrupts configuration and management. In ARM Cortex-M family the main controlling entity of interrupts and system exception is ARM on-core Nested Vector Interrupt Controller (NVIC), Figure-1. NVIC is a part of ARM Cortex-M core which means any SoC/Microcontroller based on ARM Cortex-M profile will inherent all the NVIC features. Examples includes TI Tiva-C Launchpad, STM32Fxxx, LPC17xx etc.
In the Cortex-M0, Cortex-M0+ and Cortex-M1 processors the NVIC supports up to 32 interrupt requests (IRQ), a non-maskable interrupt (NMI) and various system exceptions. On Cortex-M3/4/4F, the NVIC functionality has been tremendously enhanced. On Cortex M3/4/4F, the NVIC supports upto 256 different interrupt vectors. Out of these 256, there are 16 fixed on-core exceptions called system exceptions some of which have fixed priorities. The remaining 240 (265-16) are left to silicon vendors to connect/map their own module interrupt requests (IRQs) on these lines.
1. Interrupt Priority:
Interrupt Priority, a number (either +ive or -ive) that indicates relative importance of interrupts based upon an interrupt will be served first if multiple interrupts occurs simultaneously.
ARM Cortex-M profile NVIC implements “Reversed Priority” numbering scheme. Which means that higher the interrupt priority number the lower priority and subsequently lesser will be the relative importance of that interrupt. For example, in ARM Cortex-M Reset has fixed interrupt priority of -3 (highest priority).
The ARM Cortex-M profile NIVC categories interrupt priority into two level priorities controlled by 8-bits Interrupt Priority Configuration Register.
- Preempt Priorities
- Sub Priorities
Preempt Priorities: Preempt Priority is the main priority number that is considered for relative importance amongst multiple interrupts arriving NIVC simultaneously. If two or more interrupts arriving NVIC at the same time then the Interrupt with lower Preempt Priority number (Remember Reversed Priority mentioned earlier) gets the processor attention first and is served first.
Sub Priorities: Sub Priorities are used to determine relative importance amongst multiple interrupt arriving at NVIC at the same time AND they have same preempt priorities. In such cases where interrupts have same preempt priorities then the one with lower sub priority will be served first.
And last but not the least, when multiple interrupts having same preempt priorities and same sub priorities arrive at NVIC controller, then the interrupts are served under First come first serve Policy.
As we mentioned earlier, the NVIC Interrupt Priority Configuration Register is an 8-bits register. Which means that 2^8 = 256 interrupt priorities are available. Well YES but No. Due to power consumption and actual On-chip SoC Peripherals/Requirements, the 8-bits implementation is left to Silicon Manufacturers/Vendor.
However, the minimum number of interrupt priority bits that need to be implemented is 3 bits in ARM Cortex-M3/M4 i.e. above 3-bits the number of priority levels in the ARM Cortex-M3/M4 core is configurable, meaning that various silicon vendors can implement different number of priority bits in their chips. On contrast, the number of interrupt priority bits are fixed at 2 in ARM Cortex-M0/M0+.
For example TI Tiva Cortex-M4 implements 3-bits (2^3 = 8 Priority Levels)-Figure-2 while STM32F4xx implements 4-bits (2^4 = 16 Priority Levels) of NVIC Interrupt Priority Controller Register, Figure-3.
2. Priority Grouping:
Priority grouping is the assignment of bits that will be used for preempt priorities and sub priorities in 8-bits interrupt priority configuration register.
Priority grouping can be selected via 3 bits of Application Interrupt and Reset Control Register (AIRC) i.e. bits-8,9,10, Figure-4.
From ARM Cortex-M documentation, Table-1 shows priority grouping based on 3-bits on AIRC register .
As shown in Table-1, if we set AIRC PRIGROUP bits to binary-000 (row-1 of Table-1), the upper 7-bits of interrupt priority register will be used for preempt priority (128 priorities) and only least significant bit will be used for sub priority (0/1). Similarly if we set AIRC PRIGROUP bits are set to binary-111 (last row of Table-1), all the priority will be considered as sub priorities.
Lets take the example of STM32F4xx, which implements only upper 4-bits of interrupt priority controller register shown in Figure-3. From Figure-3, as the lower 4-bits are not implemented so selecting priority groups which consider the lower 4-bits of interrupt priority register is USELESS.
For example for STM32F4xx (4-bits priority implementation), if PRIGROUP is set to any value from first three rows of Table-1 (000,001,010), the result will be useless i.e. the bits are not implemented in STM32F4xx. This leaves the lower 5 rows of Table-1 from all preempt priorities to all sub priorities.
3. Setting interrupt Priority/Priority Grouping via CMSIS:
The ARM Cortex Microcontroller Software Interface Standard (CMSIS) provides a portable way of setting interrupts priority and selecting priority grouping.
To change priority grouping, use the following CMSIS portable API.
/* x = PRIGROUP 0 =< x >=7 */ NVIC_SetPriorityGrouping(xU);
Similarly to change interrupt priority itself, use the following CMSIS portable API.
/* IRQn: Interrupt number e.g. TIM2_IRQn, TIM3_IRQn- see IRQn_Type implementation for more details priority: Priority to set. */ void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority);
Two things should be kept in mind while using NVIC_SetPriority function.
Note-1: Only the lower N-bits (least significant bits) of parameter priority are used for setting interrupt priority. In CMSIS macro for N implementation is __NVIC_PRIO_BITS (e.g. in STM32 N = __NVIC_PRIO_BITS = 4). For example while using STM32F4xx if the priority parameter is set to 0b11110000, then only the lower 4-bits i.e. 0000 will be considered for setting interrupt priority as the implementation is 4-bits.
Note-2: The parameter priority includes sets both preempt priority and sub priority simultaneously as per the priority group selected. In fact it uses the lower __NVIC_PRIO_BITS bits of parameter priority to set the most significant __NVIC_PRIO_BITS bits of interrupt priority configuration register. This sets both the preempt priority and sub priority for the IRQn.
 – STM32F4-Discovery Board
 – STM32F407xx Datasheet
 – Reference manual-RM0090