stm32 - 中断句柄

stm32 - Interrupt handle

在外部中断函数中,我想通过调用main函数来复位。但是之后,如果我有一个新的中断触发器,MCU 认为它在中断函数中处理并且它不会再次调用中断函数。我的解决方案是什么? (在我的项目中,不允许调用soft Reset函数)

在任何情况下调用 main() 都是一个坏主意,从中断处理程序调用它是一个 确实 坏主意,正如您所发现的。

你真正需要的是修改堆栈和link寄存器,这样当中断上下文退出时,它"returns"到main(),而不是它从哪里来。这是一项非常重要的任务,可能需要一些汇编代码或编译器内在函数。

您必须意识到硬件不会恢复到其重置状态;您可能至少需要禁用所有中断以防止它们在系统重新初始化时发生。

此外,如果您跳转到main(),标准库将不会重新初始化;而不是复位向量。特别是,任何当前分配的动态内存都会立即泄漏并变得不可用。事实上 all 的 C 运行 时间环境初始化将被跳过 - 例如 static 和全局数据处于其最后状态而不是应用正确的初始化.

简而言之,它是危险的、容易出错的、目标特定的,并且从根本上来说是糟糕的做法。使它工作所需要做的大部分工作已经在 main() 被调用之前执行的启动代码中完成,因此它会简单得多调用它。这与强制真正复位(通过看门狗或 AICR)之间的区别在于片上外围状态保持不变(除了在启动时明确完成的任何初始化)。根据我的经验,如果您使用 USB 等更复杂的外围设备,那么在没有真正重置的情况下安全地重启系统很难安全地实现(或者至少很难确定如何安全地进行)并且几乎不值得付出努力。

。链接器和 C 运行时插入的 main 前面有代码,您将通过此类软重置跳过这些代码。

相反,请调用 NVIC_SystemReset() 或启用 IWDG 并 while(1){} 进行重置。
HAL 应该有看门狗定时器的示例文件。

SRAM 得到维护。链接描述文件未初始化的任何值仍将存在。

如果您不重置堆栈并设置初始值,则从代码的任何位置调用 Main() 都是错误的想法。

在中断向量中总是有一个初始化函数(实际调用Main()),通常这个函数可以通过调用函数NVIC_SystemReset(void)来触发,一定要启用它中断,因此可以由软件触发。

据我所知,当进入中断代码时,其他中断被禁止,我正在考虑两种不同的选择:

  • 在中断中启用中断并调用函数NVIC_SystemReset(void)
  • 修改堆栈,将函数的方向压入NVIC_SystemReset(void),这样当你脱离中断的时候就可以执行了。