STM32独立看门狗调试
看门狗的作用
程序意外跑飞(死机)的时候可以给系统复位,回到一个确定的状态。在程序的主循环中,必须每隔一个固定周期喂狗,即重置计数器,如果程序跑飞,看门狗就不会得到重置,从而计到阈值触发复位。
为什么叫独立看门狗?
因为它的时钟源是LSI,内部RC振荡器,频率约为32KHz,独立于系统时钟,以和WWDG(窗口看门狗)相区别。
优点:即便主时钟没起来,看门狗也能正常工作。
缺点:LSI是RC振荡器,频率不稳定,受温度影响很大,需要校准补偿。
如何启动计数?
向IWDG_KR寄存器写0x0000CCCC
如何喂狗?
向IWDG_KR寄存器写0x0000 AAAA
如何设置计数周期?
1. 设置预分频比。IWDG的计数时钟就是LSI经过预分频以后得到的,取值范围为0~256.
2. 设置计数值。多少个计数时钟后超时。
比如要想1秒钟以内喂狗,否则复位。那么就可以将预分频比设为32,计数值设为1000.
ST官方例程解析
主循环中,每隔0.99s喂狗并闪一下LED灯。
按键触发外部中断,在中断服务程序中向地址0x00040001写入0xFF,因为0x00040001正好位于STM32G071地址空间的未定义区域(如下图):
操作该地址会被MCU视为“非法操作”,跳转到Hard_Fault(硬件错误)。通过这种方式可以模拟“意外情况”。看门狗复位后,若检测到复位来源为“IWDG”,就亮灯4秒。
考虑到LSI频率不准,所以在初始化阶段就用定时器TIM16采集一次LSI信号,计算出频率,根据算得的结果来初始化独立看门狗。
由于笔者并未使用ST官方开发板NUCLEO-G071RB,硬件电路不同,所以对程序做了简单的移植:
1. 按键中断由PC13改为PC7。NUCLEO-G071RB上PC13有4.7K上拉电阻,但笔者的板子上PC7未上拉,为了有一个确定的初始状态,将其设置为内部上拉。
2. 加入了UART打印,更好地查看程序运行状态。
主程序的流程基本未变,如下:
(1)初始化Flash和Systick
(2)初始化时钟
(3)初始化GPIO和USART,此处按照官方例程使能中断,非法操作在外部中断服务程序中模拟。
(4)打印“**********IWDG Test*************”
(5)查看复位源。若确认为看门狗复位,就亮灯4秒。
(6)计算并打印LSI频率
(7)初始化IWDG。执行完这一步后IWDG开始计数。计数时钟频率为1KHz,计数周期1s。
(8)进入主循环。每隔990ms喂狗并翻转一次LED。
调试过程中碰到的问题
有时手不小心碰到按键电路时会导致死机,尽管触发了中断后执行了非法操作并导致复位,但复位后程序却卡了“**********IWDG Test*************”这一步。
原因分析
IO内部上拉电阻较弱,阻值为25KΩ~55KΩ,容易受外部干扰。人手是导体,会改变电路周围的分布参数,使得IO输入端出现扰动,引发外部中断。
分析主程序流程不难发现,在看门狗初始化之前,外部中断就被使能了,而如果在这段时间干扰信号注入引发“非法操作”,程序还未在看门狗起作用之前就死机了,自然得不到复位。
解决办法
注释掉GPIO初始化函数中的中断使语句,将其拷贝至看门狗初始化语句和主循环之间。实测发现,即便误触按键电路也不会引起死机。