在外部中断功能中,我想通过调用main函数进行复位。但之后,如果我有一个新的中断触发器,MCU认为它处理中断功能并且它不会再次调用中断功能。我的解决方案是什么? (在我的项目中,我不允许调用软复位功能)
答案 0 :(得分:4)
在任何情况下调用main()
都是一个坏主意,从中断处理程序调用它是你发现的真的坏主意。
你真正需要的是修改堆栈和链接寄存器,以便当中断上下文退出时,它会返回"到main()
,而不是从那里来的。这是一项非常重要的任务,可能需要一些汇编代码或编译器内在函数。
您必须意识到硬件不会恢复到其重置状态;您可能至少需要禁用所有中断以防止它们在系统重新初始化时发生。
此外,如果跳转到main()
,标准库将不会重新初始化;而不是重置向量。特别是,任何当前分配的动态内存都会立即泄漏并变得无法使用。实际上,将跳过C运行时环境初始化的所有 - 例如static
和全局数据保留在其最后状态,而不是应用正确的初始化。
简而言之,这是危险的,容易出错的,针对具体的目标,以及根本不好的做法。在调用 main()
之前执行的启动代码中已经完成了使其工作所需要执行的大部分操作,因此调用它会更加简单。这与强制真正复位(通过看门狗或AICR)之间的区别在于片上外设状态保持不变(除了在启动时明确完成的任何初始化)。根据我的经验,如果你使用更复杂的外围设备,如USB,安全地重启系统而没有真正的重置是很难安全实现的(或者至少很难确定如何安全地进行)并且几乎不值得努力。
答案 1 :(得分:2)
Reset by calling main() is wrong。链接器和C运行时插入的main前面的代码将通过这种软复位跳过。
相反,请致电NVIC_SystemReset()
或启用IWDG并重置while(1){}
HAL应该有看门狗定时器的示例文件。
保持SRAM。链接器脚本未初始化的任何值仍将存在。
答案 2 :(得分:2)
如果您没有重置堆栈并设置初始值,则从代码的任何位置调用Main()
是错误的。
在中断向量中总有一个初始化函数(实际上调用Main()
),通常可以通过调用函数NVIC_SystemReset(void)
来触发此函数,请确保启用此中断所以它可以是软件触发的。
据我所知,当进入内部并中断代码时,其他中断被禁止,我正在考虑两种不同的选择:
NVIC_SystemReset(void)
NVIC_SystemReset(void)
的方向,这样当你退出中断时就可以执行了。