Do interrupts interrupt other interrupts on Arduino?

后端 未结 3 1990
别跟我提以往
别跟我提以往 2021-02-06 23:51

I have an Arduino Uno (awesome little device!). It has two interrupts; let\'s call them 0 and 1. I attach a handler to interrupt 0 and a differ

相关标签:
3条回答
  • 2021-02-07 00:25

    On Arduino (aka AVR) hardware, nested interrupts don't happen unless you intentionally create the conditions to allow it to happen.

    From avr-lib:

    The AVR hardware clears the global interrupt flag in SREG before entering an interrupt vector. Thus, normally interrupts will 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 it might be desired to re-enable 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.

    (source: http://linux.die.net/man/3/avr_interrupts )

    0 讨论(0)
  • 2021-02-07 00:30

    The documentation mention that Arduino interrupts have priority:

    If your sketch uses multiple ISRs, only one can run at a time. Other interrupts will be executed after the current one finishes in an order that depends on the priority they have.

    It also provides a link for additional information:

    For more information on interrupts, see Nick Gammon's notes.

    According to sections What is interrupt priority? and Can interrupts occur while interrupts are disabled?, we can conclude that:

    1. Interrupts are based on the list of flags. When an event occurs the corresponding flag is set.
    2. If the ISR can't fire right now, it can be called at any time later because the flag is saved.
    3. There is a list of all available interrupts, and it generally depends on the chip. The higher up the list, the higher the priority.

    So, different interrupts will not interrupt each other. They will be executed according to their priority.

    0 讨论(0)
  • 2021-02-07 00:34

    Will interrupt 1 interrupt interrupt 0, or will interrupt 1 wait until interrupt 0's handler is done executing?

    Unless you specifically re-enable interrupts inside an ISR (Interrupt Service Routine) then whatever interrupt is currently running completes, plus one more machine code instruction, before the next interrupt is serviced.

    Most interrupts set a flag inside the processor, which is checked between instructions, to see if the interrupt should be serviced. Flags are checked in priority order. On the Uno that is:

     1  Reset 
     2  External Interrupt Request 0  (pin D2)          (INT0_vect)
     3  External Interrupt Request 1  (pin D3)          (INT1_vect)
     4  Pin Change Interrupt Request 0 (pins D8 to D13) (PCINT0_vect)
     5  Pin Change Interrupt Request 1 (pins A0 to A5)  (PCINT1_vect)
     6  Pin Change Interrupt Request 2 (pins D0 to D7)  (PCINT2_vect)
     7  Watchdog Time-out Interrupt                     (WDT_vect)
     8  Timer/Counter2 Compare Match A                  (TIMER2_COMPA_vect)
     9  Timer/Counter2 Compare Match B                  (TIMER2_COMPB_vect)
    10  Timer/Counter2 Overflow                         (TIMER2_OVF_vect)
    11  Timer/Counter1 Capture Event                    (TIMER1_CAPT_vect)
    12  Timer/Counter1 Compare Match A                  (TIMER1_COMPA_vect)
    13  Timer/Counter1 Compare Match B                  (TIMER1_COMPB_vect)
    14  Timer/Counter1 Overflow                         (TIMER1_OVF_vect)
    15  Timer/Counter0 Compare Match A                  (TIMER0_COMPA_vect)
    16  Timer/Counter0 Compare Match B                  (TIMER0_COMPB_vect)
    17  Timer/Counter0 Overflow                         (TIMER0_OVF_vect)
    18  SPI Serial Transfer Complete                    (SPI_STC_vect)
    19  USART Rx Complete                               (USART_RX_vect)
    20  USART, Data Register Empty                      (USART_UDRE_vect)
    21  USART, Tx Complete                              (USART_TX_vect)
    22  ADC Conversion Complete                         (ADC_vect)
    23  EEPROM Ready                                    (EE_READY_vect)
    24  Analog Comparator                               (ANALOG_COMP_vect)
    25  2-wire Serial Interface  (I2C)                  (TWI_vect)
    26  Store Program Memory Ready                      (SPM_READY_vect)
    

    (Note that Reset cannot be masked).

    Conceivably a low-level interrupt might be in progress (eg. TIMER0_OVF_vect). While that is busy doing its stuff multiple other interrupt events might occur (and set the corresponding bits in the CPU). They will be serviced in the above order, not in the order in which they actually occur in time.

    There are hardware registers that can be written to, to cancel a pending interrupt - that is, to clear the flag.


    The reason for mentioning "one more machine code instruction" is that the processor is designed to guarantee that when it transitions from interrupts not enabled, to interrupts enabled, one more instruction is always executed.

    This lets you write code like this:

      interrupts ();             // guarantees next instruction executed
      sleep_cpu ();              // sleep now
    

    Without that, an interrupt might occur before going to sleep. Which means you never wake, because you were relying upon the interrupt occuring during sleep, not before it.


    How wonderfully moronic of Freescale and Atmel to both use the very same instruction names, but with inverted meanings

    That is why I prefer the mnemonics of interrupts and noInterrupts because the intent there is very clear. These are implemented by defines in the core include files.

    0 讨论(0)
提交回复
热议问题