繁体   English   中英

在 ISR 中清除中断是必要的吗? (对于 Atmega644p uC)

[英]Clearing interrupt necessary inside an ISR? (for Atmega644p uC)

当中断服务程序正在执行时,是否需要清除全局中断(例如使用 cli(); 命令)以防止另一个 ISR 被执行或排队?

例如,如果正在执行外部中断 INT0,并且在执行时将再次触发同一外部中断。 该中断是否会在第一个中断完成后排队等待执行?

如果在当前中断期间执行以下代码,是否会阻止中断排队,或者我是否需要清除中断队列寄存器?

ISR(someISR_vect){
  cli();
  some code...
  sei();
}

不,您不需要手动执行此操作。 AVR 硬件已经为您禁用了中断,编译器不会在您的处理程序执行时重新启用中断(默认情况下)。


引用本页的“嵌套中断”部分(它没有锚点,CTRL + F“嵌套”):

AVR 硬件在进入中断向量之前清除 SREG 中的全局中断标志。 因此,通常中断将在处理程序内保持禁用状态,直到处理程序退出,此时 RETI 指令(由编译器发出,作为中断处理程序的正常 function 尾声的一部分)最终将重新启用进一步的中断。

ISR()宏定义了一个具有特殊名称的 function,并在 AVR 固件的中断表中生成对该 function 的调用。 此外,定义的 function 可能具有属性集。 您感兴趣的两个属性是interruptsignal 两者都将 function 声明为中断处理程序,这会导致return语句被替换为reti指令(从中断返回),还会导致编译器生成“适合在中断处理程序中使用的函数进入和退出序列”。

不同之处在于interrupt会自动生成sei指令,这会导致在处理程序执行期间启用中断,基本上会覆盖硬件设置的默认值。 另一方面, signal不会那样做。

剩下要做的唯一一件事就是检查ISR()默认设置了哪一个。 通过查阅 github 上的 avr-libc 代码,特别是interrupt.h文件,我们可以看到ISR()宏默认指定了__signal__属性(根据它是相同的属性)。 同时,可以作为参数传递给ISR()的宏ISR_BLOCK空白的。 同时, interrupt属性由下面几行ISR_NOBLOCK宏指定。 据此,您的中断处理程序的默认属性是signal ,它不会在您的处理程序执行时重新启用中断。 您可以通过查看在设置和不设置ISR_NOBLOCK的情况下编译的中断向量的反汇编来验证是否生成了sei指令。


至于全局中断标志被禁用时的中断行为,我将参考 Atmega644p 的手册,目前我在这里找到它(它似乎是从 2016 年开始的,但我怀疑从那时起在这方面有什么改变):

当使用 CLI 指令禁用中断时,中断将立即被禁用。 在 CLI 指令之后不会执行任何中断,即使它与 CLI 指令同时发生。 (...) 当使用 SEI 指令启用中断时,SEI 之后的指令将在任何挂起的中断之前执行,如本例所示。

当中断被禁用时,AVR 无法对中断进行排队。 发生的情况是,一旦中断发生,就会设置中断特定标志(与全局中断标志相反)。 如果中断被禁用,中断处理程序将不会执行。 这样一来,中断可能在挂起的 state 中,如上面引用的那样。 一个例子是 TC0(定时器 0 控制)寄存器中的 TOV(定时器溢出)标志(在手册的第 16.9.8 节中找到)。 当 Timer0 发生溢出时,标志将被设置为 1。如果中断被全局禁用,中断处理程序将不会运行,但标志将保持设置。 中断将在挂起的 state 中。如果在中断处理程序设法运行之前发生另一个相同类型的中断(timer0 溢出),它将丢失,因为每种中断类型只有一个标志位。 另一方面,在此期间可能会发生另一种中断类型,它有一个单独的标志。 由于它有一个单独的中断位标志,它不会受到 timer0 溢出中断在挂起的 state 中的影响。它也将被放入挂起的 state(标志将设置为 1,但在中断之前不会运行任何处理程序再次启用)。

这适用于基于标志的中断。 据我所知,AVR 中有一些中断不是基于标志的,它们的行为略有不同,但我没有这些经验,也不想传播有关它们的错误信息。 不过,我认为仍然不可能在待处理的 state 中对每个排队超过 1 个。

在 ISR 中使用cli是不必要的,因为 AVR 在进入 ISR 时会自动禁用中断。

在中断中使用sei实际上在理论上是非常危险的。 它允许其他中断在您的中断完成并释放它正在使用的堆栈空间之前运行。 因此,您可能有许多嵌套中断同时无限制地运行,可能会填满您的堆栈。

回答您的其他问题:使用clisei只会影响全局中断启用位。 来自外围设备的中断标志仍然可以为 1 或更改为 1,而不管该位的 state。 下一次全局启用中断并且外设的中断标志等于 1 时,AVR 将跳转到其中断服务程序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM