来自 cortex-m0 上的 ISR 的 kill 函数

Posted

技术标签:

【中文标题】来自 cortex-m0 上的 ISR 的 kill 函数【英文标题】:kill function from ISR on cortex-m0 【发布时间】:2015-08-23 05:43:23 【问题描述】:

我正在使用带有裸机实现(无操作系统)的 Cortex-M0 处理器。我们有一个固件应用程序,我们希望允许第三方编写一个 C 函数,该函数将与固件的其余部分分开构建并加载到内存中(有点像 DLL),并在检测到时由主固件调用。

我遇到的问题是我想在受保护的环境中运行这个外部函数,这样如果它产生故障异常或执行时间过长,它就不会破坏主固件。所以我想做的是,从硬故障 ISR(用于故障异常)或计时器滴答 ISR(用于执行时间问题),操纵堆栈以终止外部函数并将执行返回到主固件。我意识到这在 RTOS 中是直截了当的,但主要固件已经开发完成,此时切换它需要花费大量精力。

我查看了在 c++ 中使用 try-catch,但编译器似乎不支持它。所以我看到的另一个选择是在调用外部函数之前编写一些程序集来保存堆栈指针,并从 ISR 恢复 SP 和上下文,并分支到主固件中的返回点。任何人都可以就如何最好地做到这一点给出任何指示,或者有没有更简单的方法来完成这个?

【问题讨论】:

使用 RTOS 不会更容易,因为它们没有动态加载/执行的规定。您仍然必须为该功能提供自己的包装器。问题不在于捕获异常并回滚堆栈,而在于防止该函数链接 RAM。 MPU是否足够完全取决于您的内存布局以及您希望允许的功能。例如,如果它不仅有自己的堆栈,它可能会破坏堆栈。 是否有机会使用小型解释语言而不是本机代码来防止 CPU/内存直接访问第 3 方代码? Brian - 我们确实做了一个初始实现,它使用了一种解释性的汇编语言,它使用 excel 作为汇编程序。然而,逻辑要求变得如此,用汇编程序编写是繁重的。因此我们决定切换到 C。第三部分将无法直接访问任何静态内存。他们将被赋予访问固定大小的控制值数组的功能。他们在堆栈上使用局部变量是一个问题。 Cortex-m0 确实有一个我可以使用的进程堆栈,但现在我认为我们将提供一些关于局部变量使用的规则。 我不认为 cortex-m0 有完整的保护,所以这个覆盖的应用程序可以丢弃包括保护你的东西在内的东西。我不认为 RTOS 可以发明一些你还没有的东西(保护)(除非你的芯片中有 PMSA,请参阅 arm 文档),但你实际上正在做的是创建一个操作系统。所以你可以对你的代码进行计时器检查,看看它是否有任何时间片等,或者用某种方法来检测程序是否丢失,但我认为一个表现不佳的程序通常会让你崩溃 【参考方案1】:

这是我最终使用的实现。我利用 CMSIS 内在函数 __get_MSP() 和 __set_MSP() 来访问 SP。在调用受保护的函数之前,我保存了当前的 SP。返回地址是函数压入堆栈的第一项,因此我将保存的 SP 增加一个位置,以便它指向返回地址以用于故障恢复情况。

计时器滴答 ISR 跟踪受保护函数运行了多长时间,如果超时或发生硬故障中断,则执行故障处理程序。需要的第一件事是退出中断上下文(否则您将从中断上下文执行主代码,防止进一步的中断),所以我确定了相对于 SP 的哪个堆栈位置保存 ISR 返回地址,并用故障恢复函数的地址。请注意,Timer Tick ISR 的优先级最低,因此返回地址将始终指向非中断代码。如果ISR优先级更高,可能不是这样,但我没有验证。

从任一 ISR 退出时,都会执行故障恢复功能。它需要两条指令:

__set_MSP( StackPtrSave );
__asm volatile ("pop pc");

这会将 SP 和 PC 恢复到正确的状态,就好像受保护的功能刚刚退出一样。但是,它不会恢复任何其他寄存器。如果返回点位于函数的末尾(并且编译器不会尝试内联它),那应该没问题。就我而言,我需要设置 StackPtrSave = 0,因为 ISR 就是这样知道受保护函数何时运行的。我尝试使用 volatile 指针强制编译器在恢复后将变量的地址重新加载到寄存器,但我无法让它工作。最后我设置了一个属性来禁用函数的优化,所以它总是会在写入 StackPtrSave 之前加载地址。

正如 cmets 中所述,这并不能提供完全受保护的环境。受保护的函数仍然可以使用指针来破坏静态变量或堆栈。我看不出有什么办法可以避免这种情况,因为 Cortex-m0 没有内存保护单元。就我而言,负责受保护功能的第三方确实对产品的功能有既得利益,因此我给出了指导方针,即他们的代码应避免使用指针或数组。我认为这提供了该平台所能提供的***别的保护。

【讨论】:

以上是关于来自 cortex-m0 上的 ISR 的 kill 函数的主要内容,如果未能解决你的问题,请参考以下文章

来自 ISR 的 FreeRTOS Sempahore 无法正常工作

未对齐的访问导致 ARM Cortex-M4 上的错误

在向量区域执行时,Cortex-m0弹出指令失败?

Cortex-m0之DualTimers定时器

LPC11xx Cortex-M0 FreeRTOS 硬故障

Cortex-M4 上的 Systick 定时器:它的预分频器是啥?