'Usage fault exception' 在 ARM Cortex M 中

'Usage fault exception' in ARM Cortex M

我参加了一个关于 FreeRtos 和 Cortex M 的讲座,讲师建议如果不从 ISR 使用 API 的 ISR 安全版本,它可能会导致 使用错误异常 在 Cortex M processors.This 中会发生,因为这可能涉及从中断上下文(中断处理程序)到任务上下文(线程处理程序) 我的问题是为什么这个任务切换会被认为是非法的,这样的切换会产生什么影响?

在 Cortex-M 上(某些)当前上下文将存储在中断之前使用的堆栈中(在中断入口处),因此如果您在任务中并且它被中断,一些当前上下文将存储在任务堆栈中(通过 PSP)。中断本身总是在 MSP 上运行。如果中断没有 return 到它中断的任务,那么被中断的任务将有一个混乱的堆栈(因为它在退出时恢复存储的上下文)以及尝试为任务恢复不正确的上下文切换到.

在上下文切换(发生在中断中)时,一些上下文会自动存储在任务堆栈中,但 OS 也会将其余上下文存储在任务堆栈中。当它进行切换并退出中断时,OS 恢复它为任务存储的上下文,然后通过退出中断自动恢复上下文的其余部分。这是有效的,因为它确保堆栈以正确的格式保留。查看 Cortex-M4 通用用户指南中的中断进入/退出。

并非所有处理器都是这样工作的。

这个答案是通用的,不是 FreeRTOS 也不特定于 Cortex-M - 它适用于任何平台上的任何典型 RTOS:

RTOS API 导致调度程序 运行 的调用无法从中断服务例程中调用。例如,如果你给了一个信号量,通常调度程序 运行s 会切换到任何挂在该信号量上的任务;这在 ISR 中是不合适的,其中调度程序必须 运行 once 当中断上下文退出时;显然你不希望在中断完成之前进行上下文切换,并且可能有其他API调用或被更高优先级的中断抢占,导致不同的任务变为运行能;仅在上下文切换发生时进行一次评估可保持确定性行为。

ISR 特定版本的函数不会立即调用调度程序;相反,他们设置了一个标志来指示调度程序必须 运行 从中断上下文中退出。

通常,进行 RTOSAPI 调用的 ISR 必须具有 序言尾声;具体 enter/exit 中断 调用或宏。这个序言增加了一个在结语中递减的计数器;如果计数器为零并且设置了调度标志,则调度程序将 运行。该计数器用于防止调度程序在退出嵌套中断时 运行ning。这确保调度程序在退出时仅 运行s 形成最低优先级的挂起中断。

是否或为什么会出现 "uasge fault" 是 FreeRTOS 特定的实现细节,主要是学术性的。 RTOS 同样可以捕获 ISR 中非 ISR 安全调用的使用和 运行 更具体的错误处理程序,如果它不愿意这样做,那么由此产生的行为可能会触发使用错误;这似乎是一种有点粗糙的机制; 使用错误 是一个非常广泛的陷阱,可能由于多种原因而发生:

Usage Fault: detects execution of undefined instructions, unaligned memory access for load/store multiple. When enabled, divide-by-zero and other unaligned memory accesses are also detected.

一些 RTOS 没有特定于 ISR 的函数,而是导致调度的 API 调用在内部检测 ISR 上下文并在该上下文中表现不同 - 这对程序员来说更简单、更安全,但会带来少量开销来测试每次此类调用的上下文。在内部处理 ISR 安全的 API 也意味着调用可能自己进行 OS API 调用的函数更简单,因为这些函数本身不需要特定于 ISR。