Nested __enable_irq / __disable_irq

13 Feb 2012

Hi,

Does anyone know if the enable_irq / disable_irq functions take care of nested calls or do I have to do this manually? That is, if enable_irq is called twice, do the interrupts re-enable after 1 or 2 calls of disable_irq? The ARM Compiler Reference Guide (http://www.keil.com/support/man/docs/armccref/armccref_CJAFBCBB.htm) suggests it needs to be done manually, assuming these are the same functions. Might be useful info to add to the Working with Interrupts Handbook (http://mbed.org/handbook/Working-with-Interrupts).

14 Feb 2012

I think you have to take care of it manually as the reference you cited indicates.

I tried out the following piece of code with the online compiler:

#include <mbed.h>

void EnableIRQTwice()
{
    __enable_irq();
    __enable_irq();
}

void DisableIRQTwice()
{
    __disable_irq();
    __disable_irq();
}

int main() 
{
    printf("EnableIRQTwice():  %X\n", (unsigned int)EnableIRQTwice & ~1);
    printf("DisableIRQTwice(): %X\n", (unsigned int)DisableIRQTwice & ~1);
    
    printf("Done\n");
    for(;;)
    {
    }
}

This code generated the following output showing the addresses of the function which use these intrinsics:

EnableIRQTwice():  1AC
DisableIRQTwice(): 1B0
Done

When I disassembled the functions at these addresses, I see:

rearm ~/Downloads/IRQTest_LPC1768.bin --start 0x1AC --size 8
EnableIRQTwice:
000001AC  B662       CPSIE i
000001AE  4770       BX LR
DisableIRQTwice:
000001B0  B672       CPSID i
000001B2  4770       BX LR

This output shows two things of interest.

  • These irq related compiler intrinsics just resolve down to the corresponding CPSIE and CPSID assembler instructions. There is no nesting level check.
  • The optimizer in the compiler was even smart enough to remove the redundant call to these IRQ related compiler intrinsics.

Hope that helps,

Adam