在工业控制/ 汽车电子/航空航天等需要高可靠性的系统中,为了防止“系统在异常情况下,受到干扰,MCU/CPU程序跑飞,导致系统长时间异常工作”,通常是引进看门狗,如果MCU/CPU不在规定的时间内按要求访问看门狗,就认为MCU/CPU处于异常状态,看门狗就会强迫MCU/CPU复位,使系统重新从头开始按规律执行用户程序。看门狗本质上是一种定时电路或者软件定时器机制。
看门狗,又叫 watchdog timer,是一个定时器电路,一般有一个输入,叫喂狗(kicking the dog or service the dog),一个输出到MCU的RST端,MCU正常工作的时候,每隔一段时间输出一个信号到喂狗端,给 WDT 清零,如果超过规定的时间不喂狗,(一般在程序跑飞时),WDT 定时超过,就会给出一个复位信号到MCU,使MCU复位, 防止MCU死机。看门狗的作用就是防止程序发生死循环,或者说程序跑飞。
工作原理:在系统运行以后也就启动了看门狗的计数器,看门狗就开始自动计数,如果到了一定的时间还不去清看门狗,那么看门狗计数器就会溢出从而引起看门狗中断,造成系统复位。所以在使用有看门狗的芯片时要注意清看门狗。
硬件看门狗是利用了一个定时器,来监控主程序的运行,也就是说在主程序的运行过程中,我们要在定时时间到之前对定时器进行复位如果出现死循环,或者说PC指针不能回来。那么定时时间到后就会使单片机复位。常用的WDT芯片如MAX813,5045,IMP 813等,价格4~10元不等。有些单片机内部已经集成看门狗定时器,如STC15系列,只需在使用时配置相应的看门狗寄存器即可
大体工作方式:硬件看门狗芯片会有接收单片机的置位信号和控制单片机复位的引脚。单片机可以根据看门狗芯片信号需求,可以通过io口进行喂狗;如果程序异常,看门狗会由于收不到单片机给的信号而发出单片机复位信号给单片机,让单片机进行复位。
软件看门狗技术的原理和这差不多,只不过是用软件的方法实现,我们还是以51系列来讲,我们知道在51单片机中有两个定时器,我们就可以用这两个定时器来对主程序的运行进行监控。我们可以对T0设定一定的定时时间,当产生定时中断的时候对一个变量进行赋值,而这个变量在主程序运行的开始已经有了一个初值,在这里我们要设定的定时值要小于主程序的运行时间,这样在主程序的尾部对变量的值进行判断,如果值发生了预期的变化,就说明T0中断正常,如果没有发生变化则使程序复位。
对于T1我们用来监控主程序的运行,我们给T1设定一定的定时时间,在主程序中对其进行复位,如果不能在一定的时间里对其进行复位,T1 的定时中断就会使单片机复位。在这里T1的定时时间要设的大于主程序的运行时间,给主程序留有一定的的余量。而T1的中断正常与否我们再由T0定时中断子程序来监视。这样就够成了一个循环,T0监视T1,T1监视主程序,主程序又来监视T0,从而保证系统的稳定运行。
在STM32单片机中,有两类看门狗,分别是独立看门狗和窗口看门狗,两者的区别有:
独立看门狗使用的是内部低速时钟,其频率为40kHz,但是这个40KHz不是准确的,其大致的范围是(30-60)KHz。该时钟与外设时钟无关,所以不受系统晶振影响。
窗口看门狗使用的是PCLK1的时钟,该时钟与晶振相关
独立看门狗喂狗时只要下限大于0就可以,上限是0xFFF.
窗口看门狗必须在一个区域内喂狗才可以,上限是0x7F,下限是0x40。
独立看门狗的计数器是12位递减的,即最大值是0xFFF。
窗口看门狗的计数器是7位递减的,即最大值是0x7F。
独立看门狗时,如果超时不喂狗,则直接产生复位,程序从头执行
窗口看门狗会在计数器到达0x40时产生中断,在0X3F时产生复位,所以可以把窗口看门狗看成是一种中断。
独立看门狗可以用来防止程序跑飞,在程序中开启看门狗,定时喂狗,尤其在通讯中使用广泛,当逻辑处理不当,使程序一直处于发送或接收状态不退出时,这时独立看门狗可以使程序复位,程序从头执行。
窗口看门狗可以产生中断,利用这一特点可以用来进行数据保存,当产生窗口看门狗中断时,可以用来保存数据。
栈或堆溢出,程序跑飞
某段程序异常无法返回或陷入死循环
强电磁干扰破坏数据导致系统异常,常工作在强电磁干扰环境中的电子系统容易出现故障
bug导致的系统宕机,或者死循环
多任务系统中死锁
……
看门狗定时器定时时间设置过短,则系统容易误判,可能会导致频繁复位或进入失效安全模式。因为任何一条安全链的好坏取决于它最薄弱的一环,如果选择一个太短的超时间隔。固件的循环时间是动态的,尤其外部的异步事件比较多,或者有中断嵌套的情况,则波动会比较大,所以需要考虑最坏情况,系统循环一次要多久。
一种方法是选择一个几秒钟长的间隔。当您仅尝试复位一个确实挂起的系统,但不希望对系统的时间进行详细研究时,可以采用此策略。这是一个健壮的方法。但有些系统需要快速恢复,这就造成故障诊断过慢的危害了,尤其在一些对安全要求极高的场合,比如核电系统,汽车电子系统、医疗器械系统等等。
通俗点来讲就是,系统如果进入死循环或宕机了,没有及时喂狗,但看门狗溢出时间还没到,就不能及时复位系统,对一些要及时恢复的系统来说,看门狗溢出时间不易太长
设计者必须清楚看门狗的溢出时间以决定在合适的时候,清看门狗。清看门狗也不能太过频繁否则会造成资源浪费。程序正常运行时,软件每隔一定的时间(小于定时器的溢出周期)给定时器置数,即可预防溢出中断而引起的误复位。
喂狗频率不好规定某个数值,因为不同的系统要求不同,对这一部分的介绍文章也较少,可能更多的是看工程师的经验吧
看门狗溢出时间 = ( 12 x Pre-scale x 32768)/ 振荡器频率
例如在晶振频率是11.0592MHz的单片机中,想让看门狗溢出时间为2.2755S,则PS2、PS1、PS0分别为1、0、1,对应的Pre-scale的值就是64,根据公式,溢出时间=(12 x 64 x32768)/11059200 = 2.2755 s
一个看门狗初始化函数,一个喂狗函数
/*
* @name Init
* @brief 看门狗初始化
* @param None
* @retval None
*/
static void Init()
{
WDT_CONTR = 0x3d; // 0011 1101 看门狗溢出时间 2.2755s ,空闲模式计数,喂狗、使能
WDT_CONTR |= 0x10; //喂狗
}
/*
* @name Feed
* @brief 喂狗
* @param None
* @retval None
*/
static void Feed()
{
WDT_CONTR |= 0x10; //喂狗
}
1.一定要注意并不是所有的系统都适合使用看门狗,比如说在我们的比较精密的控制系统,一旦我们程序除了一些小异常而导致芯片复位,可能会导致系统时续混乱而造成较大得设备损害!
2.对于看门狗一般用在,比如温控系统,显示系统等复位系统对整个系统影响不是很大的延时系统等!这样能够在系统异常后复位系统让系统继续运行。
3.对于部分MCU在看门狗复位之前会出发一个中断服务函数,给程序最后进行喂狗的机会。这个是系统给我们的机会,我们可以对当前MCU的状态进行保存等日志信息记录,供软件研发人员进行系统的分析。
4.同时对于喂狗每个人持有不同的态度,有些人认为需要在主程序中喂狗,有些则认为需要在中断里面喂狗;不过在中断里面喂狗存在一个问题是,对于MCU主程序处于死循环的时候,而我们的中断服务函数可以正常运行,这样无法出发看门狗复位。所以常用做法是,通过中断置位相关标志位,然后主程序检测标志位进行喂狗操作,至于更加强大的看门狗机制,我们需要在实际的项目中根据需求来制定相关策略。
参考:
https://zhuanlan.zhihu.com/p/147934002