4、看门狗与超时复位:硬件看门狗、软件看门狗、超时触发回滚

固件升级最怕什么?

怕写到一半卡死。怕新固件跑不起来。怕设备变砖。

看门狗,就是专门对付这些「死局」的。说白了,它就是一个倒计时器——你必须在它归零之前「喂狗」,否则它就帮你复位系统。

我个人习惯把看门狗分成两类:硬件看门狗和软件看门狗。两者各有各的脾气,用好了是救星,用不好反而添乱。

4.1 硬件看门狗:最后的防线

硬件看门狗是独立于CPU的定时器电路。它不依赖主芯片的时钟,哪怕CPU内部时钟跑飞了,它照样能计数。

我在项目中遇到过一件事:某款工业控制器,升级过程中主芯片突然死机,所有中断都不响应了。幸好硬件看门狗还在跑,8秒后自动复位,系统才捡回一条命。

核心原则:硬件看门狗必须在系统初始化时立即开启,且喂狗操作只能放在主循环或RTOS空闲任务中。不要在中断服务函数里喂狗——否则中断卡死时看门狗照样被喂,等于白设。

参数 典型值 说明
超时时间 1~30秒 升级过程通常较长,建议设为10秒以上
喂狗位置 主循环/空闲任务 确保系统整体健康时才喂
复位行为 全芯片复位 包括外设、寄存器、内存

注意:硬件看门狗一旦使能,有些芯片就无法在运行中关闭。所以升级前要确认看门狗的超时时间是否足够覆盖整个升级流程。我曾经见过一个案例,看门狗设了5秒,但固件包有2MB,串口波特率9600,光传输就要20分钟——结果每次升级都反复复位。

4.2 软件看门狗:灵活但不可靠

软件看门狗,本质上是利用系统定时器模拟的看门狗功能。它不需要额外硬件,成本低,配置灵活。

但说实话,软件看门狗有个致命弱点:如果CPU彻底死机,定时器中断也停了,软件看门狗就形同虚设。

那为什么还要用?

因为很多低成本的MCU根本没有硬件看门狗。这时候软件看门狗就是唯一的选择。我建议的做法是:

  • 用系统滴答定时器(SysTick)作为计数源
  • 在最高优先级的中断里递减计数器
  • 主循环定期重置计数器
  • 计数器归零时触发软件复位
// 软件看门狗示例(基于SysTick)
volatile uint32_t wdg_counter = 0;
#define WDG_TIMEOUT_MS 10000  // 10秒超时

void SysTick_Handler(void) {
    if (wdg_counter > 0) {
        wdg_counter--;
        if (wdg_counter == 0) {
            // 触发软件复位
            NVIC_SystemReset();
        }
    }
}

void wdg_feed(void) {
    wdg_counter = WDG_TIMEOUT_MS / portTICK_PERIOD_MS;
}

void main_loop(void) {
    while(1) {
        wdg_feed();
        // 执行升级流程...
    }
}

技巧:软件看门狗的超时时间建议比硬件看门狗短。比如硬件看门狗设15秒,软件看门狗设10秒。这样软件看门狗先触发,如果复位失败,硬件看门狗还能兜底。

4.3 超时触发回滚:升级失败的自动刹车

看门狗复位只是手段,不是目的。复位之后怎么办?

如果复位后继续执行升级,很可能再次卡死,陷入无限循环。这时候就需要「超时触发回滚」机制。

我设计的方案是这样的:

  1. 升级前:在备份区保存当前固件的启动次数计数器
  2. 升级中:每次喂狗时检查升级进度,如果长时间无进展,触发看门狗复位
  3. 复位后:Bootloader检查启动次数计数器,如果连续复位超过阈值(比如3次),自动回滚到备份固件

关键点:回滚触发条件要设置「防抖」机制。不要因为一次意外复位就回滚,但也不能让设备无限重启。我个人习惯用3次连续复位作为回滚阈值,每次复位后延迟5秒再启动,给用户一个拔电的机会。

为什么会这样设计?

你想想看,如果固件本身有bug,每次启动都崩溃,看门狗就会反复复位。如果没有回滚机制,设备就永远卡在「启动→崩溃→复位→启动」的死循环里。有了回滚,至少能回到上一个稳定版本。

看门狗与超时回滚流程图 开始升级 启动看门狗 执行固件写入 看门狗超时复位 升级完成 检查复位次数 正常运行 回滚到备份固件 说明: 看门狗超时后,Bootloader检查 连续复位次数,超过阈值则回滚

4.4 避坑指南

这些年我踩过的坑不少,挑几个典型的说说:

  • 喂狗位置不对:我曾经把喂狗放在一个耗时很长的循环里,结果循环卡住了,看门狗也被卡住。后来改成只在主循环喂狗,问题解决。
  • 超时时间太短:升级过程中要擦除Flash、写入数据,这些操作耗时不稳定。我建议把超时时间设为正常耗时的3倍以上。
  • 忘记关闭看门狗:有些芯片进入低功耗模式前必须关闭看门狗,否则会不断复位。嗯,这个坑我至少踩过两次。

重要:回滚操作本身也要有看门狗保护。如果回滚过程中也卡死了,那就真的变砖了。我通常会在回滚代码里单独开一个更短的看门狗,确保回滚过程也能被监控。

最后说一句:看门狗不是万能的,但没有看门狗是万万不能的。尤其是做OTA升级,设备不在你手边,出了问题只能靠看门狗和回滚机制自救。把这两样东西做好,升级失败至少还有退路。