中断是否会中断Arduino上的其他中断?

Chr*_*nte 22 embedded microcontroller arduino interrupt interrupt-handling

我有一个Arduino Uno(很棒的小装置!).它有两个中断; 我们称他们为01.我使用attachInterrupt():http://www.arduino.cc/en/Reference/AttachInterrupt将一个处理程序连接到中断0,另一个处理程序用于中断1 .

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

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

请注意,这个问题与Arduino有关.

gpc*_*pcz 25

在Arduino(aka AVR)硬件上,除非您有意创建允许它发生的条件,否则不会发生嵌套中断.

来自avr-lib:

在进入中断向量之前,AVR硬件清除SREG中的全局中断标志.因此,通常中断将在处理程序内保持禁用,直到处理程序退出,其中RETI指令(由编译器作为中断处理程序的正常函数结尾的一部分发出)最终将重新启用进一步的中断.因此,中断处理程序通常不会嵌套.对于大多数中断处理程序,这是所需的行为,对于某些行为甚至是必需的,以防止无限递归中断(如UART中断或电平触发的外部中断).在极少数情况下,虽然可能希望在中断处理程序中尽可能早地重新启用全局中断标志,但是为了不推迟任何其他中断而不是绝对需要.这可以在中断处理程序的开头使用sei()指令来完成,但是这仍然会在编译器生成的函数序言中留下很少的指令,以便在禁用全局中断的情况下运行.

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

  • 好.飞思卡尔和爱特梅尔使用相同的指令名称,但具有倒置意义:) (5认同)
  • 请注意,这与我处理的每个CPU类似 - 在进入ISR时禁用中断.如果软件想要允许嵌套的IRQ处理,则必须明确地重新启用它们,并且软件需要在重新启用中断之前正确地准备硬件/堆栈/嵌套IRQ的任何工作. (4认同)
  • SEI =设置全局中断标志.这将全局启用中断.(来源(PDF警告):http://www.atmel.com/dyn/resources/prod_documents/doc0856.pdf第132页) (2认同)
  • @Lundin您在抱怨飞思卡尔文档的“那”吗?当对位顺序的“更远”问题感到不安时?飞思卡尔不是**仅**将**小****号用于**最显着的位**,而是**从** ONE **开始** !!!! **所以我(明智的)`31`很抱歉,-0位图由飞思卡尔记录为**`1`-`32` **,但是“ CLI”是飞思卡尔问题的“最少” ... (2认同)

Nic*_*mon 6

中断 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)
Run Code Online (Sandbox Code Playgroud)

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

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

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


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

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

  interrupts ();             // guarantees next instruction executed
  sleep_cpu ();              // sleep now
Run Code Online (Sandbox Code Playgroud)

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


飞思卡尔和爱特梅尔都使用相同的指令名称,但含义相反,这是多么愚蠢的事情

这就是为什么我喜欢的助记符interruptsnoInterrupts因为其目的也非常明确。这些由核心包含文件中的定义实现。