26

What happens if an ISR is running, and another interrupt occurs? Does the first interrupt get interrupted? Will the second interrupt get ignored? Or will it fire when the first ISR is done?

EDIT I forgot to include it in the question (but I included it in the tags) that I meant to ask how this worked on Atmel AVR's.

Jon Ericson
  • 19,534
  • 11
  • 93
  • 140
BenjiWiebe
  • 1,885
  • 3
  • 20
  • 39

2 Answers2

34

Normally, an interrupt service routine proceeds until it is complete without being interrupted itself in most of the systems. However, If we have a larger system, where several devices may interrupt the microprocessor, a priority problem may arise.

If you set the interrupt enable flag within the current interrupt as well, then you can allow further interrupts that are higher priority than the one being executed. This "interrupt of an interrupt" is called a nested interrupt. It is handled by stopping execution of the original service routine and storing another sequence of registers on the stack. This is similar to nested subroutines. Because of the automatic decrementing of the stack pointer by each interrupt and subsequent incrementing by the RETURN instruction, the first interrupt service routine is resumed after the second interrupt is completed, and the interrupts are serviced in the proper order. Interrupts can be nested to any depth, limited only by the amount of memory available for the stack.

For example, In the following diagram, Thread A is running. Interrupt IRQx causes interrupt handler Intx to run, which is preempted by IRQy and its handler Inty. Inty returns an event causing Thread B to run; Intx returns an event causing Thread C to run.

enter image description here Image Ref

For hardware interrupts, Priority Interrupt Controller Chips (PIC's) are hardware chips designed to make the task of a device presenting its own address to the CPU simple. The PIC also assesses the priority of the devices connected to it. Modern PIC's can also be programmed to prevent the generation of interrupts which are lower than a desired level.

UPDATE: How Nested Interrupt Works on Atmel AVRs

The AVR hardware clears the global interrupt flag in SREG before entering an interrupt vector. Therefore, normally interrupts remain disabled inside the handler until the handler exits, where the RETI instruction (that is emitted by the compiler as part of the normal function epilogue for an interrupt handler) will eventually re-enable further interrupts. For that reason, interrupt handlers normally do not nest. For most interrupt handlers, this is the desired behaviour, for some it is even required in order to prevent infinitely recursive interrupts (like UART interrupts, or level-triggered external interrupts).

In rare circumstances though nested interrupts might be desired by re-enabling the global interrupt flag as early as possible in the interrupt handler, in order to not defer any other interrupt more than absolutely needed. This could be done using an sei() instruction right at the beginning of the interrupt handler, but this still leaves few instructions inside the compiler-generated function prologue to run with global interrupts disabled. The compiler can be instructed to insert an SEI instruction right at the beginning of an interrupt handler by declaring the handler the following way:

ISR(XXX_vect, ISR_NOBLOCK)
{
  ...
}

where XXX_vect is the name of a valid interrupt vector for the MCU type.

Also, have a look at this Application Note for more info on interrupts on Atmel AVRs.

gbudan
  • 819
  • 6
  • 17
  • 2
    This reminds me of an annoying bug we had on a Z80-based system. We'd hooked an RTC up to the NMI pin to get real time counting. Problem is, the RTC emits 50% mark and 50% space *per second*. Coupled with the fact that the non-maskable interrupt is non-maskable, *even by itself*, that 0.5s of mark quickly amount to a stack crash and a system hang :/ – slugonamission May 25 '14 at 16:41
  • 1
    I think this answer would be more helpful if you distinguished what is done by the CPU, what is done by the interrupt controller and what is done in software. – Gilles 'SO- stop being evil' May 25 '14 at 20:53
  • The link to the Application Note has [changed](http://ww1.microchip.com/downloads/en/AppNotes/Atmel-8468-Using-External-Interrupts-for-megaAVR-Devices_ApplicationNote_AVR1200.pdf) – Armin J. Feb 13 '19 at 09:08
6

The way interrupts work:

  1. The code sets the "Global Interrupt Enable" bit; without it, no interrupts will occur.

  2. When something happens to cause an interrupt, a flag is set.

  3. When the interrupt flag is noticed, the "Global Interrupt Enable" bit is cleared.

  4. The appropriate ISR is run.

  5. The "Global Interrupt Enable" bit is re-set.

  6. Things now go back to step 2, unless an interrupt flag is already set during the ISR; then things go back to step 3.

So to answer the question: When the first ISR is finished, the second ISR will be run.

Hope this helps!

BenjiWiebe
  • 1,885
  • 3
  • 20
  • 39
  • 4
    That may be true for some processors, but many processors these days have multiple interrupt priorities and in that cases higher-priority interrupts will preempt lower priority interrupts in much the same way as interrupts preempt normal tasks. – Jim May 25 '14 at 06:05
  • 2
    Your description is very specific to the 8-bit Microchip PIC chips. – Wouter van Ooijen May 25 '14 at 07:21
  • 1
    @WoutervanOoijen Really? It also applies to 8-bit Atmel MCU's. – BenjiWiebe May 26 '14 at 12:16