# How does the Arduino NANO deal with simultaneous external interrupts?

I am a beginner with Arduino NANO and this is something I've been trying to figure out for a few hours now. Say, in setup(), I have the following snippet of code:

pinMode(2, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2), do_this, RISING);
pinMode(3, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(3), do_that, RISING);


and there are two ISR functions do_this() and do_that() that are called when two push-button switches are pressed. I understand how the program is supposed to behave when the switches are pushed and released separately. But, what if the RISING action happens, hypothetically, at the same point in time? (Actually, if digital pin 2 and 3 are connected to the same push-button then the 'stimulus', so to speak, will occur at the exact same moment). Which one of the ISRs, if any, will take precedence in this case? I have checked the ATMega328 datasheet, but have not been able to come up with anything satisfactory.

Edit: Thanks for the detailed insights. I understand that the ISRs have priorities and even if the change is triggered at the same time, the ISRs will be executed one after another depending according to the said priority.

As for the push-button part of the question, I came to the conclusion that when the two interrupt pins are connected together through the push-button, pressing the switch does not trigger any change because one of the External Interrupt Flags gets cleared by the other. I know that's a rough conclusion and I am probably missing a lot of technical nuances but is that idea at least correct? Many thanks

• Page 10 of the datasheet - "The lower the interrupt vector address, the higher the priority" Jul 24 '20 at 13:07
• @Finbarr Can I ask what datasheet this is? I checked the ATMega328 datasheet and page 10 is just the index. Chapter 10 is Power Management and Sleep Modes-- nothing about interrupts Jul 24 '20 at 13:11
– Codo
Jul 24 '20 at 13:15
• Always go straight to the manufacturer for the datasheet... Jul 24 '20 at 13:48
• As per your edit, no that is not correct. If a push button is connected to two external interrupt pins, they both trigger simultaneously, and you have both interrupts pending, they are just executed one after another due to their priorities. The two interrupt pins have each their own flags and interrupts. Jul 25 '20 at 6:12

Contrary to anther answer, two interrupts can happen at exactly the same time as far as the microcontroller is concerned. This is because the MCUs concept of time is its clock signal. Anything that happens after one clock edge and before the next clock edge happened at the exactly the same time as far as the MCU is concerned.

What happens when two sources fire simultaneously depends on the microcontrollers interrupt handler design, and whether or not it is doing something else.

In the case of an AVR, if two different interrupt sources happen at the same time, the one that gets processed first depends on its hardware priority. This is typically whichever comes first in the interrupt vector table. The first interrupt handler will be called, any other interrupts will still set their corresponding hardware flag, but will not immediately trigger their interrupt handler (unless you call sei in an ISR, which is bad for many reasons).

Once the current ISR returns (reti instruction), the hardware flag for that interrupt source will be cleared. This means that if, say, while INT0 was being handled INT0 happened again, it would be ignored, because the flag gets cleared on return.

If after the ISR has returned, one or more hardware interrupt flag for other sources are set, the same process will repeat, with the source being executed whichever has the highest hardware priority.

In the case of the Arduino Nano, Digital 2 corresponds to INT0, whilst Digital 3 corresponds to INT1. In the ATMega328, INT0 has priority over INT1, so if both sources occurred during the exact same clock cycle, then do_this would happen first.

If however INT1 occurred a clock cycle before INT0, then do_that would in theory happen first. However as there are other interrupts at play, such as the timer 0 interrupt used for the millis() function which complicates things. If INT1 happened before INT0, but both happened whilst the ISR for Timer 0 was being handled, then do_this would happen first because on return from the timer ISR, it would have priority.

Each interrupt has a priority and they are processed in order. That order is mentioned in the datasheet. There are two external interrupts and three pin change interrupts. Each pin change interrupt covers all 8 pins of an IO port. Depending on which pins on which port those pins actually are, and are they configured as external or pin change interrupt, they can trigger only one pin change int, or two pin change ints, or pin change and external int, or two external ints. If two different interrupts are triggered, then two interrupt vectors are run in the predetermined priority order where the order is EXTI 0,1 and PCINT 0,1,2.

If the pins are on same PCINT group then only one interrupt triggers.

What Arduino libraries do with the priorities when two pins in the same group are triggered at same time can be read from Arduino code or documentation, it has nothing to do with the AVR chip itself.

Edit: It seems that the Arduino function you use only supports EXTI0 and EXTI1 interrupts, not pin change interrupts. So as the vector for EXTI0 has priority over EXTI1 and it will run first, if the two interrupts are triggered simultaneously.

One of them will always fire first, and while you're in its ISR, interrupts are disabled for atmega328, so the other button will be ignored. If you're asking WHAT IF INTERRUPTS OCCUR AT THE SAME TIME - they don't. They just don't. Your little MCU does exactly one operation at a time, it can't do anything completely at the same time. You can look up in the dasheet how long it takes to detect an interrupt event, your interrupt triggering event should be detected, 1 picosend pulse won't trigger anything (again, all info in the datasheet). MAYBE it will trigger a random one, but only one (whichever event it checks for interrupt event first).

There is such a thing as interrupt priority, it's an ability of MCU to receive higher priority interrupt while executing ISR of lower priority interrupt. Usually you disable interrupts in ISR because this kind of thing is hard to track. You don't want other interrupts fire while you're in some ISR from another interrupt, it can make program flow confusing and you never know how much of ISR completed before it was interrupted by another one, stuff gets confusing. Unless you have a specific reason to do that. As far as I know tho, Arduino Uno/Nano and their Atmega328 rid you of this problem, they have only interrupts of one and only level, so one interrupt doesn't interrupt another interrupt. Sorry for interrupt.

• *at least there are no priorities if you use the arduino command, I haven't looked into datasheet to check if there are interrupt priorities governed by registers that you could control directly
– Ilya
Jul 24 '20 at 13:16
• Priorities are fixed, not controllable beyond being enabled or disabled. Jul 24 '20 at 13:18