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 interrupts behaviour when same interrupt vector has multiple interrupts

Hello,


I am using STM32F407ZGT6 Cortex-M4 microcontroller. This controller has same interrupt vector for 5 external interrupts i.e., NVIC (EXTI9_5) for EXTI5, EXTI6, EXTI7, EXTI8 and EXTI9 interrupts. They all have the same ISR EXTI9_5_IRQHandler interrupt service routine. So, one has to check the independent flags of each external interrupt to determine the source of the interrupt.

I am confused about how the service routine is called in case multiple interrupts arrived. Lets say, an interrupt due to EXTI5 has arrived, its interrupt handler is called and the interrupt is servicing. Meanwhile, EXTI6 interrupt is detected. Now, will the interrupt handler be called again when the EXTI5 interrupt is fully serviced or since it is already in the interrupt handler, it will not be called again?

In short, which method should I write among the following two styles:

void EXTI9_5_IRQHandler (void)

{

     if EXTI5 happens

     {

          EXTI5 ISR

     }

     if EXTI6 happens

     {

          EXTI6 ISR

     }

     if EXTI7 happens

     {

          EXTI7 ISR

     }

     if EXTI8 happens

     {

          EXTI8 ISR

     }

     if EXTI9 happens

     {

          EXTI9 ISR

     }

}

OR

void EXTI9_5_IRQHandler (void)

{

     if EXTI5 happens

     {

          EXTI5 ISR

     }

     else if EXTI6 happens

     {

          EXTI6 ISR

     }

     else if EXTI7 happens

     {

          EXTI7 ISR

     }

     else if EXTI8 happens

     {

          EXTI8 ISR

     }

     else if EXTI9 happens

     {

          EXTI9 ISR

     }

}

Thanking in anticipation for your time and help.

Parents
  • Excellent question.

    This is how I understand what happens (simplified slightly):

    1: A "pending bit" will be set for your interrupt.

    2: When the priority level is lower than your interrupt's priority level, the priority level is set to the one that matches your interrupt; your interrupt will be invoked.

    3: You interrupt reads the pending bits; eg. those bits that caused the interrupt, perhaps a new pending bit will be set just after you've read the bits.

    4: Clear the pending bits that you've just read. The one that's set just after you read the bits will not be cleared.

    5: Process the bits you have in your variable you've read.

    6: Return. The priority level is now restored.

    7: Because there's now a pending bit, your interrupt will be invoked again.

    Here's an example...

    void TIMER0_IRQHandler(void)

    {

        uint32_t pendingBits;

        pendingBits = INTERRUPT_REGISTER;

        INTERRUPT_REGISTER = pendingBits;  /* this clears the bits that are set in the variable 'pendingBits'. */

        if(pendingBits & (1 << 0))

        {

            /* handle interrupt for bit 0 */

        }

        if(pendingBits & (1 << 1))

        {

          /* handle interrupt for bit 1 */

        }

        /* ... */

        if(pendingBits & (1 << 31))

        {

          /* handle interrupt for bit 31 */

        }

    }

    ... As I am not aware what your interrupt register is named, I've made up a name for it. It should work the same on all Cortex-M as far as I understand.

    So if you follow the above mentioned model, you should never 'miss' an interrupt, not even if a pending bit is set right after you've read the value into the pendingBits, and before you're writing the bit-mask to clear.

    Also, you should avoid using 'else if', so you'll process all the pending bits, otherwise you'll only process one.

    jyiu - please correct me if I'm wrong.

    Correction: I just learned something new, so I renamed the above interrupt routine, in order to be a more correct example; by not featuring the EXTI*_IRQHandler interrupts.

    I think this method should work for other kinds of interrupts, where you get multiple pending bits per interrupt vector. That could be timer-interrupts, for instance.

    Please refer to Joseph's answer, which should clarify the EXTI* interrupts.

Reply
  • Excellent question.

    This is how I understand what happens (simplified slightly):

    1: A "pending bit" will be set for your interrupt.

    2: When the priority level is lower than your interrupt's priority level, the priority level is set to the one that matches your interrupt; your interrupt will be invoked.

    3: You interrupt reads the pending bits; eg. those bits that caused the interrupt, perhaps a new pending bit will be set just after you've read the bits.

    4: Clear the pending bits that you've just read. The one that's set just after you read the bits will not be cleared.

    5: Process the bits you have in your variable you've read.

    6: Return. The priority level is now restored.

    7: Because there's now a pending bit, your interrupt will be invoked again.

    Here's an example...

    void TIMER0_IRQHandler(void)

    {

        uint32_t pendingBits;

        pendingBits = INTERRUPT_REGISTER;

        INTERRUPT_REGISTER = pendingBits;  /* this clears the bits that are set in the variable 'pendingBits'. */

        if(pendingBits & (1 << 0))

        {

            /* handle interrupt for bit 0 */

        }

        if(pendingBits & (1 << 1))

        {

          /* handle interrupt for bit 1 */

        }

        /* ... */

        if(pendingBits & (1 << 31))

        {

          /* handle interrupt for bit 31 */

        }

    }

    ... As I am not aware what your interrupt register is named, I've made up a name for it. It should work the same on all Cortex-M as far as I understand.

    So if you follow the above mentioned model, you should never 'miss' an interrupt, not even if a pending bit is set right after you've read the value into the pendingBits, and before you're writing the bit-mask to clear.

    Also, you should avoid using 'else if', so you'll process all the pending bits, otherwise you'll only process one.

    jyiu - please correct me if I'm wrong.

    Correction: I just learned something new, so I renamed the above interrupt routine, in order to be a more correct example; by not featuring the EXTI*_IRQHandler interrupts.

    I think this method should work for other kinds of interrupts, where you get multiple pending bits per interrupt vector. That could be timer-interrupts, for instance.

    Please refer to Joseph's answer, which should clarify the EXTI* interrupts.

Children