I am testing nested interrupt recently on my STM32 dev board in order to ensure the relationships between nested interrupts are clear for me. I’ve read lots of sample codes online but never tried on my own since I only used systick and timer based encoder interrupt last year.
before set up the priority for interrupts, we need to determine the NVIC priority group first.
NVIC refers to nested vector interrupt controller, is a controller built in cortex arm M3 M4 processors, therefore this feature can also be found at some other brand’s arm M3 M4 processors other than stm32.
There are 2 different kinds of priorities: preemption priorities and sub priorities
Usually whoever has higher preemption priority can be executed first, this is always happening with nested interrupts. when 2 interrupts have same preemption priority, then the one who has higher sub priority will be execute first. If both interrupts both have same preemption priority and sub priority, the one comes first will be execute first(first come first serve).
Cortex Arm M3 M4 processors use 8 bits to store the priorities for preemption and sub priorities. In the header file core_CM3.h or core_CM4.h, it uses only 4 bits to store those values. If we use all 4 bits to store preemption priority, then there will be no bit left for sub priority, and vice versa, there will be no bit available for preemption priority when all 4bits are used for sub priority. This process is call priority grouping. There are 5 different groups we can set.
group0 0 bits for preemption, 4 bits for sub priority
group1 1 bits for preemption, 3 bits for sub priority
group2 2 bits for preemption, 2 bits for sub priority
group3 3 bits for preemption, 1 bits for sub priority
group4 4 bits for preemption, 0 bits for sub priority
thus, we can call function NVIC_PriorityGroupConfig to setup priority grouping now.
I choose group 4 since I only want different preemption priority in my micromouse between interrupts, so I call function as follow:
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); //4 bits for preemp priority 0 bit for sub priority
If you don’t set the priority grouping, the default grouping in ST library is group 2, which is 2 bits for preemption priority and 2 bits for sub priority
now we can go set the priorities for each peripheral interrupts.
For instance, I want to set the priority for TIM4 as 1 (lower number has higher priority), I call the code as follow:
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; //TIM4 IRQ Channel
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//Preemption Priority
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //Sub Priority
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
If you want to setup the priorities for other device, just replace ‘TIM4_IRQn’ to the one you want.
However, if you want to setup the priorities for those peripherals whose values for NVIC vector table are smaller than 0, the method we used above will be no long valid. The correct way is to call the function as follow(assume I want systick has highest priority):
NVIC_SetPriority(SysTick_IRQn, 0);//set systick interrupt priority, 0 is the highest for all
you might be confused here since this function didn’t specify the preemption and sub priories in parameter. In fact, they are both included. Since I mentioned stm32 uses 4 bits to store preemption and sub priorities, the high bits are for preemption and low bits are for sub priority. If the parameter for priority is 0 for the function above(that’s also what I had in the function), 0 is 0x00 in hex and 0000 in binary, since the default priority grouping for stm32 is group 2, which is 2 bits for preemption priority and 2 bits for sub priority, we get 00 for preemption and 00 for sub. If we change the input from 0 to 7 for the function, the binary form for 7 is 0111, so higher 2 bits is 01 which is 1 in decimal gives you preemption priority as 1, and the lower 2 bits is 11 which is 3 gives you sub priority as 3.
If your priority grouping is same as mine which is group 4, then there is no sub priority, the input in parameter in function NVIC_SetPriority only refers to your preemption priority in this case.
PS: never set your preemption and sub priorities out of range, it might work, but something unexpected may happen.