【问题标题】:Do interrupts interrupt other interrupts on Arduino?中断会中断 Arduino 上的其他中断吗?
【发布时间】:2011-07-03 22:35:12
【问题描述】:

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

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

将中断1中断0,或者将中断1等到中断0的处理程序完成执行完毕?

请注意,这个问题专门与 Arduino 相关。

【问题讨论】:

  • 标题是绕口令,但问题仍然很大!
  • @gpcz 已经回答了,我只会补充一点,您可以选择,如果另一个中断将等待并在第一个中断之后处理或将被完全忽略...

标签: embedded microcontroller arduino interrupt interrupt-handling


【解决方案1】:

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

来自 avr-lib:

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

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

【讨论】:

  • 那段文字真的正确吗?我不知道 AVR 指令集,但它不应该是“cli”指令吗?又名“清除全局中断掩码”,而不是“sei”又名“设置全局中断掩码”。无论如何,这就是它在飞思卡尔 MCU 上的工作方式,它们也在使用这两个 asm 指令。
  • SEI = 设置全局中断标志。这将全局启用中断。 (来源(PDF 警告):atmel.com/dyn/resources/prod_documents/doc0856.pdf 第 132 页)
  • 好的。飞思卡尔和爱特梅尔都使用相同的指令名称,但含义相反:)
  • 请注意,这与我处理过的每个 CPU 的情况类似——中断在进入 ISR 时被禁用。如果软件想要允许嵌套 IRQ 处理,软件必须明确地重新启用它们,并且软件需要在重新启用中断之前正确准备硬件/堆栈/任何东西以使嵌套 IRQ 工作。
  • @Lundin 你在抱怨飞思卡尔文档的那个?当FAR令人发指的Bit Order问题有问题时?飞思卡尔并非最重要的位使用SMALLER数字,它们开始ONE!! !!! 所以我的(明智的)31-0 位图被飞思卡尔记录为 1-32 抱歉,CLI飞思卡尔的问题最少...
【解决方案2】:

中断 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

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


飞思卡尔和爱特梅尔都使用相同的指令名称,但含义相反

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

【讨论】:

    【解决方案3】:

    The documentation 提到 Arduino 中断具有优先权:

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

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

    有关中断的更多信息,请参阅Nick Gammon's notes

    根据什么是中断优先级?可以在中断被禁用时发生中断吗?部分,我们可以得出以下结论:

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

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

    【讨论】:

      猜你喜欢
      • 2016-12-02
      • 1970-01-01
      • 2012-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-27
      • 1970-01-01
      相关资源
      最近更新 更多