Search code examples
c++interruptavr

May I use cli() and sei() in the interrupt?


May I use cli() and sei() like this:

ISR(EXT_INT0_vect)
{
    cli();
    MyFunction();
    sei();
}

I heard that it is forbidden. Is it or I can use cli() and sei() like above?


Solution

  • Calling cli() and sei() manually (like in your example) is redundant if you want normal interrupt behavior. That is, because AVR automatically clears the global interrupt flag before the ISR is executed. There are rare use cases for nested interrupts, where you may want to manually re-enable interrupts using sei() within the ISR.

    From Nested interrupts:

    Normally, the AVR hardware clears the global interrupt flag (in SREG) before entering an interrupt. This means other interrupts are disabled inside the running handler until the handler finishes and exits.

    The RETI instruction is the normal function epilogue for an interrupt handler, and thus re-enables interrupts (just like executing an SEI instruction). For this reason, normally, interrupt handlers can not be nested.

    For most interrupt handlers, this is the desired behavior. For some its even required in order to prevent infinitely recursive interrupts. Recursion could easily exceed the available stack space and crash the running program. In rare circumstances it might be desirable to re-enable the global interrupt flag as early as possible inside the interrupt handler, allowing recursive interrupt handling. Carefully.

    This could be accomplished by inserting an sei() instruction right at the beginning of the interrupt handler, but this still leaves a few instructions inside the (compiler-generated) interrupt prologue to run with global interrupts disabled. [...]