This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Cortex-M4 interrupt priority dynamically change while in ISR

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.

Parents Reply Children
  • 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();

      __set_BASEPRI(0x2 << (8 - __NVIC_PRIO_BITS));

      // 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)

    {

    uint32_t last_basepri;

      // Run code A

      ...

      last_basepri = __get_BASEPRI();

      __set_BASEPRI(0x2 << (8 - __NVIC_PRIO_BITS));

      // Run code B at level 2

      ...

      __set_BASEPRI(last_basepri);

      return;

    }

    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.