26

我有一个Arduino Uno(很棒的小设备!)。它有两个中断;我们称它们为 01attachInterrupt()我使用:http ://www.arduino.cc/en/Reference/AttachInterrupt将一个处理程序附加到中断 0 和一个不同的处理程序到中断 1 。

中断0被触发并调用其处理程序,该处理程序进行一些数字运算。如果在触发中断1时,中断0的处理程序仍在执行,会发生什么?

将中断1中断中断0,还是将中断1等到中断0的处理程序执行完毕?

请注意,这个问题特别与 Arduino 有关。

4

3 回答 3

28

在 Arduino(又名 AVR)硬件上,嵌套中断不会发生,除非您有意创造条件允许它发生。

来自 avr-lib:

AVR 硬件在进入中断向量之前清除 SREG 中的全局中断标志。因此,通常中断将在处理程序内部保持禁用状态,直到处理程序退出,其中 RETI 指令(由编译器作为中断处理程序的正常函数结尾的一部分发出)最终将重新启用进一步的中断。因此,中断处理程序通常不会嵌套。对于大多数中断处理程序来说,这是所需的行为,对于某些甚至需要它来防止无限递归中断(如 UART 中断或电平触发的外部中断)。在极少数情况下,尽管可能希望尽早在中断处理程序中重新启用全局中断标志,以免延迟任何其他中断超过绝对需要。

(来源: http: //linux.die.net/man/3/avr_interrupts

于 2011-02-24T22:44:58.513 回答
7

中断 1 会中断中断 0,还是中断 1 会等到中断 0 的处理程序执行完毕?

除非您在 ISR(中断服务程序)中专门重新启用中断,否则在处理下一个中断之前,当前运行的任何中断都会完成,再加上一条机器代码指令。

大多数中断在处理器内部设置一个标志,在指令之间检查该标志,以查看是否应该处理中断。标志按优先级顺序检查。在 Uno 上是:

 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)

(请注意,重置不能被屏蔽)。

可以想象,一个低级中断可能正在进行中(例如 TIMER0_OVF_vect)。当它忙于做它的事情时,可能会发生多个其他中断事件(并在 CPU 中设置相应的位)。它们将按照上述顺序进行服务,而不是按照它们实际发生的时间顺序。

可以写入硬件寄存器以取消挂起的中断 - 即清除标志。


提到“多一条机器代码指令”的原因是处理器被设计为保证当它从未启用的中断转换到启用的中断时,总是执行多一条指令。

这使您可以编写如下代码:

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

没有它,在进入睡眠之前可能会发生中断。这意味着您永远不会醒来,因为您依赖于睡眠期间发生的中断,而不是之前发生的中断。


飞思卡尔和爱特梅尔都使用相同的指令名称,但含义相反,真是太愚蠢了

这就是为什么我更喜欢的助记符,interrupts因为noInterrupts那里的意图非常明确。这些由核心包含文件中的定义实现。

于 2016-03-07T06:47:25.147 回答
1

文档提到 Arduino 中断具有优先权:

如果您的草图使用多个 ISR,则一次只能运行一个。其他中断将在当前中断完成后执行,顺序取决于它们的优先级。

它还提供了附加信息的链接:

有关中断的更多信息,请参阅Nick Gammon 的注释

根据章节什么是中断优先级?中断被禁用时是否会发生中断?,我们可以得出结论:

  1. 中断基于标志列表。当事件发生时,会设置相应的标志。
  2. 如果 ISR 现在无法触发,则可以在以后随时调用它,因为标志已保存。
  3. 有一个所有可用中断的列表,它通常取决于芯片。列表越高,优先级越高。

所以,不同的中断不会相互中断。它们将根据其优先级执行。

于 2016-02-03T08:42:58.183 回答