3、看门狗与复位:启动的第一道关卡

各位工程师,咱们接着聊。上一章我们把时钟树理清了,但时钟配置得再好,如果复位和看门狗没处理好,启动照样会翻车。这一章,我们就来啃下这两个硬骨头。

说实话,我在刚接触C2000那会儿,觉得看门狗就是个“定时炸弹”,动不动就复位,烦得很。后来才明白,不是它烦,是我没搞懂它的脾气。你想想看,一个系统跑在工业现场,电磁干扰、电源波动、程序跑飞,这些都是家常便饭。没有看门狗,芯片挂了都没人知道。

3.1 看门狗定时器:系统的“心跳监护仪”

看门狗定时器(WDT)说白了就是一个递减计数器。它不停地从某个初始值往下数,数到0就触发复位。你的任务就是在它数到0之前,给它“喂狗”——也就是重新装载计数值。

为什么叫“喂狗”?我习惯这么理解:狗饿了就会叫(复位),你按时喂它(清看门狗),它就乖乖的。你要是忙忘了,它就咬你一口(系统复位)。

核心要点:看门狗不是用来“防止”复位的,而是用来“检测”系统是否还在正常运行的。正常运行时,你会定期清狗;如果程序卡死或跑飞,没人清狗,系统就会自动复位,把控制权拉回来。

C2000的看门狗有几个关键寄存器,我列个表,大家对照着看:

寄存器 功能 我踩过的坑
WDCNTR 看门狗计数器,递减 读它的时候要注意,读操作本身不会影响计数值
WDKEY 喂狗寄存器,写入特定序列 必须按0x55→0xAA的顺序写,顺序错了直接复位
WDCR 控制寄存器,配置分频和模式 修改WDCR前,要先解锁,否则写不进去
WDFLAG 看门狗复位标志位 启动时一定要检查这个位,判断上次复位是不是看门狗干的

喂狗的正确姿势:我个人习惯在main函数的主循环里喂狗,而不是在中断里。为什么?因为如果中断还能响应,说明CPU至少没完全死掉,但主循环可能已经卡住了。在主循环喂狗,能更真实地反映系统状态。

3.2 复位源分析:到底是谁动了我的芯片?

系统启动时,第一件事就是搞清楚:这次复位是谁引起的?C2000主要有三个复位源:POR、XRS和WDRST。我一个个说。

3.2.1 POR:上电复位

POR(Power-On Reset)是芯片上电时自动产生的复位。它是最彻底的复位,所有寄存器都会回到默认值。我记得有一次调试,发现芯片上电后某些外设配置没生效,查了半天,原来是POR后时钟默认是内部振荡器,而我以为它用的是外部晶振。

POR的特点:

  • 发生在VDD上升到阈值电压时
  • 复位所有寄存器到默认状态
  • 复位持续时间由内部定时器决定,约几个毫秒
  • 启动后必须重新配置时钟和所有外设

3.2.2 XRS:外部复位

XRS引脚是外部复位输入,低电平有效。你可以在XRS引脚上接一个按键,或者接一个外部复位监控芯片。当XRS被拉低时,芯片立即复位。

这里有个细节要注意:XRS引脚是双向的。它不仅能接收外部复位信号,还能输出内部复位状态。也就是说,当看门狗复位发生时,XRS引脚也会被拉低,告诉外部设备“芯片复位了”。

曾经踩过的坑:我在一个项目里,把XRS引脚直接连到了外部复位芯片的输出上。结果发现,看门狗复位时,XRS被拉低,外部复位芯片检测到低电平,以为是自己触发了复位,也跟着输出复位信号。两个复位源互相干扰,系统反复重启。后来我在XRS引脚上加了一个隔离电阻才解决。

3.2.3 WDRST:看门狗复位

WDRST是看门狗定时器溢出产生的复位。它和POR、XRS最大的区别是:WDRST不会复位所有寄存器。有些寄存器在WDRST后仍然保持原来的值,比如某些外设的控制寄存器。

为什么会这样?TI的设计意图是:看门狗复位通常是因为程序跑飞,但外设的配置可能是正确的。如果全部复位,重新配置外设需要时间,反而可能错过一些实时性要求高的操作。所以WDRST只复位CPU核心和一些关键寄存器,外设配置尽量保留。

我列个对比表,大家一目了然:

复位源 触发条件 复位范围 启动时间 典型应用
POR 上电 全部寄存器 最长(约3-5ms) 首次上电
XRS 外部引脚拉低 全部寄存器 中等(约1-2ms) 手动复位、外部监控
WDRST 看门狗溢出 部分寄存器 最短(约0.5ms) 程序跑飞恢复

3.3 复位时序:启动抖动的“元凶”

好,现在我们知道复位源了。但为什么复位会影响启动抖动?

原因在于:不同的复位源,启动时序不一样。POR启动时,内部振荡器需要稳定时间,PLL需要锁定时间,这些都需要等待。而WDRST启动时,很多时钟配置可能还保留着,启动路径更短。

我画了一张流程图,展示不同复位源下的启动路径差异:

C2000复位源启动路径对比 不同复位源启动路径对比 POR 上电复位 XRS 外部复位 WDRST 看门狗复位 内部振荡器稳定 内部振荡器稳定 跳过(保留配置) PLL锁定(等待) PLL锁定(等待) 跳过(PLL已锁定) Boot ROM执行 Boot ROM执行 Boot ROM执行 用户代码入口 POR/XRS路径长,WDRST路径短

从这张图可以看得很清楚:WDRST跳过了振荡器稳定和PLL锁定这两个耗时最长的阶段,所以启动时间比POR和XRS短得多。这个时间差,就是启动抖动的来源之一。

3.4 实战:如何消除复位引起的启动抖动

知道了问题在哪,解决方案就呼之欲出了。我总结了三条经验:

  1. 启动时检查复位标志:在main函数的第一行代码,读取复位状态寄存器,判断是哪种复位。如果是WDRST,可以跳过一些耗时的初始化步骤。
  2. 统一启动路径:如果你发现系统对启动时间有严格要求,可以考虑在WDRST后也执行完整的初始化流程,但用更快的时钟配置来缩短时间。
  3. 喂狗时机要合理:不要在中断里喂狗,也不要在初始化完成前喂狗。我习惯在进入主循环后,先完成所有关键初始化,再开启看门狗。

代码片段:检查复位标志

// 启动时检查复位源
void CheckResetSource(void)
{
    uint16_t resetFlag = SysCtrlRegs.RESC.bit.POR;
    
    if(resetFlag == 1)
    {
        // POR复位,需要完整初始化
        FullInit();
    }
    else if(SysCtrlRegs.RESC.bit.XRS == 1)
    {
        // XRS复位,也需要完整初始化
        FullInit();
    }
    else if(SysCtrlRegs.RESC.bit.WDRST == 1)
    {
        // WDRST复位,可以跳过部分初始化
        QuickInit();
    }
    
    // 清除复位标志
    SysCtrlRegs.RESC.all = 0xFFFF;
}