2

首先要说我已经读过这个并且无法理解或得到明确的答案。我是一个试图学习 ARM 的 AVR 人。我正在对 ATMEL 的 ATSAM4LC2AA 进行编程。当我遇到 ISR 处理程序时,我应该禁用全局中断吗?如果是这样,这是正确的代码吗?

void USARTx_Handler(void)
{
    /* Disable interrupts */
    irqflags_t flags = cpu_irq_save();

    /* Read USART Status. */
    Do_small_task();

    /* Enable interrupts */
    cpu_irq_restore(flags);
}
4

2 回答 2

2

链接答案的基本要点是“在 ARM M-profile 架构中,您通常不需要做任何事情”。接受任何异常会自动屏蔽任何其他具有相同或更低优先级的异常。从异常处理程序返回会自动恢复之前的状态。如果您发现自己想在较低优先级的处理程序中屏蔽较高优先级的异常,请首先考虑您是否已正确设置优先级 - 偶尔会有这样做的正当理由,但如果您不这样做已经知道你为什么需要,你不需要。

于 2016-11-01T00:42:28.953 回答
1

cpu_irq_save() 通常不会禁用中断,它只是返回标志的状态。当前和所有较低优先级的中断已被禁用。cpu_irq_restore(flags),恢复标志。我不确定为什么需要这些调用,除非 USARTx_Handler() 正在改变标志的状态。通常有一些内核(操作系统)代码在调用 USARTx_Handler() 之前已经保存了“上下文”。

如果这不是嵌套中断,则 ARM 从线程模式更改为处理程序模式以处理中断。USARTx_Handler() 之外处理实际中断(异常)的典型内核(操作系统)代码调用 USARTx_Handler(),然后当 USARTx_Handler(void) 返回时,内核代码会将 ARM 恢复到之前的状态,通常是返回到线程模式(除非它处于嵌套中断状态)。

在多线程内核(如某些版本的 RTOS)的情况下,它可能包含可以从中断处理程序调用的函数,这些函数最终会在中断函数返回时导致上下文切换到不同的线程。

更新- 根据 Tedi 的评论, cpu_irq_save() 也在禁用中断(显然在禁用中断之前保存标志)。函数名本来可以更好,cpu_irq_save_and_disable_irq(),但可能太长了。只要文档显示这些功能应该如何工作,名称就不是那么重要。

这会在调用 USARTx_Handler() 之后但在 cpu_irq_disable 实际禁用中断之前的任何时间创建时序窗口,更高优先级的中断可以抢占 USARTx_Handler()。此外,在 cpu_irq_restore() 启用中断之后(假设此处)的任何时间,但在 USARTx_Handler() 返回之前,更高优先级的中断也可以抢占 USARTx_Handler()。但至少您知道在 cpu_irq_save() 和 cpu_irq_restore() 之间禁用了中断。

如果您不希望 USARTx_Handler() 禁用更高优先级的中断怎么办?是否需要任何特殊呼叫?

由于我对这里使用的内核/RTOS 一无所知,因此我不确定以这种方式实现中断处理程序的含义。一个问题是内核是否支持嵌套中断能够调用内核函数,例如当中断链从处理程序模式返回线程模式时导致上下文切换的内核函数。

还有如何处理 NMI(不可屏蔽中断)的问题。一些 RTOS 不处理这个问题,因此解决方案是让嵌入式设备在 NMI 处理程序中设置一个特殊的基于硬件的中断 (IRQ),然后从 NMI 中返回,其中特殊的中断处理程序完成由NMI。其他 RTOS 可以处理来自嵌套 IRQ 和/或 NMI 的系统调用。

于 2016-11-01T01:39:10.477 回答