We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hello,
I am using STM32F407ZGT6 Cortex-M4 microcontroller. I am interested in changing the priority of a certain interrupt while servicing the same interrupt. Is that possible?
More elaborately, lets say I have an interrupt which has a priority of 4. The interrupt has arrived and I am currently in the ISR servicing that interrupt. After running a certain code (in the ISR), I want to run the remaining code (in the ISR) to run at higher priority (say 2). And when I was about to leave the ISR, I again change its priority to 4. Is this possible?
Currently, I have achieved this by calling a higher priority interrupt inside the lower priority interrupt.
Thanking in anticipation for your time and help.
I simply practically implemented the following code:
IRQHandler_4
{
// priority = 4
Code A // needs to run at priority 4
Change IRQHandler_4 to higher priority 2
Code B // needs to run at priority 2
Change back IRQHandler_4 to lower priority 4
}
And it runs perfectly. Code A runs at lower priority 4 and Code B at higher priority 2.
Thus, in ARM Cortex-M4, the interrupt priority can be dynamically changed anywhere, even inside the interrupt handler (which is servicing the interrupt)
Sorry for delay of my reply.
Glad to know that you have find the answer. Yes, Cortex-M3 and Cortex-M4 supports dynamic changing of the priority level.
Please note that this is not supported in ARMv6-M (Cortex-M0/M0+/M1). For ARMv6-M, you should only change the priority level of a interrupt when it is inactive and ideally disable it first, change the priority level, and then reenable it.
Normally we expect users to use BASEPRI to block the lower priority level interrupts.
For example, when you change the priority level of IRQHandler_4 to 2:
NVIC_SetPriority(PORT0_4_IRQn, 0x2);
You can get the same effect by:
__set_BASEPRI(0x2 << (8 - __NVIC_PRIO_BITS));
But at the end of the ISR, when you set the priority level back to 4:
NVIC_SetPriority(PORT0_4_IRQn, 0x4);
If you are using BASEPRI, you should be restoring it to orginal value (e.g. 0). Otherwise it could block other lower priority level interrupts.
for example, your ISR could look like:
void IRQ4_Handler(void)
uint32_t last_basepri;
// Run code A
...
last_basepri = __get_BASEPRI();
// Run code B
__set_BASEPRI(last_basepri);
return;
Comparing between using IRQ priority level and BASEPRI, there is one difference:
The function code using BASEPRI (function_X below) can be used by both an IRQ handler as well as in Thread, and can be shared by multiple IRQ handlers:
void function_X(void)
// Run code B at level 2
Change the priority level of an active IRQ cannot work in Thread (because the IRQ isn't active at that stage), and if the code need to be shared by multiple ISRs, you need to detect which IRQ it is serving to change the right priority level setting.
Hope this helps.
regards,
Joseph
Thanks a lot for the detailed reply. It has cleared up many confusions.