Re-enabling interrupts inside an ISR (Mega0, xTiny, etc)

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The new AVRs with dual/triple-priority interrupts no longer clear the global Interrupt Enabled flags in the CPU status register when you enter an ISR, or re-set it when the RETI instruction is done.  Instead, there is a new register CPUINT.STATUS that has bits for each level of interrupt, and entry/RETI sets/resets those.

 

However, CPUINT.STATUS is described as READ-ONLY.  Does that mean that there is no "convenient" way to re-enabled interrupts within an ISR?  (yes, I know that that's not a particularly good idea.  I also know that it is occasionally done anyway...)

 

See https://forum.arduino.cc/t/you-c...

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

//irq back on inside an isr (need a reti to clear lvl0ex)

//naked, as we only want the reti, noinline so is a call, inline so can be in a header
[[ using gnu : naked, noinline ]] inline void isrIrqOn(){ asm("reti"); }

 

ISR(some){

    isrIrqOn(); //a call and a reti

    //this lvlex bit now clear

}

 

 

or the C version (but probably want it in a source file, like same file as isr)-

 

__attribute(( naked, noinline )) static void isrIrqOn () { asm("reti"); }

 

 

Oddly enough, in C++ you can make that function both inline and noinline- the noinline so becomes a call, and the inline means that you only get one function generated if used more than once (and do not get complaints if not used at all), and can live in a header file.

Last Edited: Thu. Jul 1, 2021 - 12:48 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

This is from the 4809 datasheet (DS40002173B).   Why not sei(), cli() from avr/interrupt.h?

It seems  a design note on the interrupt architecture would be nice.

 

 

Last Edited: Thu. Jul 1, 2021 - 12:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

>  Why not sei(), cli() from avr/interrupt.h?

 

Because the global interrupt bit is already set, and remains set when an isr fires. They cannot disable interrupts on isr entry as that would exclude a higher priority interrupt from running in the current isr, which defeats the purpose of interrupt levels. So they use bits to keep track of the current priority level, which get set when an isr is jumped from the vector table and cleared with a reti. The only way to clear these bits is via a reti, so a simple call to a reti does the job of clearing the bit, and you are now one priority level lower than before the call.