首页 文章

stm32 - 中断句柄

提问于
浏览
1

在外部中断功能中,我想通过调用main函数进行复位 . 但之后,如果我有一个新的中断触发器,MCU认为它正在处理中断功能而它不会再次调用中断功能 . 我的解决方案是什么? (在我的项目中,我不允许调用软复位功能)

3 回答

  • 4

    在任何情况下调用 main() 是一个坏主意,从中断处理程序调用它是一个非常糟糕的主意,因为你已经发现 .

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

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

    此外,如果跳转到 main() ,标准库将不会重新初始化;而不是重置向量 . 特别是,任何当前分配的动态内存都会立即泄漏并变得无法使用 . 实际上,将跳过所有C运行时环境初始化 - 例如在其最后状态中保留 static 和全局数据,而不是应用正确的初始化 .

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

  • 2

    Reset by calling main() is wrong . 链接器和C运行时插入的main前面的代码将通过这种软复位跳过 .

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

    SRAM得以维护 . 链接器脚本未初始化的任何值仍将存在 .

  • 2

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

    总是有一个初始化函数(实际上调用 Main() ),它位于一个中断向量中,通常可以通过调用函数_389318来触发该函数,请确保启用此中断以便软件触发 .

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

    • 启用中断内的中断并调用函数 NVIC_SystemReset(void)

    • 修改堆栈并按下函数 NVIC_SystemReset(void) 的方向,这样当你退出中断时就可以执行了 .

相关问题