1 WatchDog介绍
WatchDog,中文名称为“看门狗”,全称“WatchDog timer”。从字面上可知它属于一种定时器,然而它与平常所说的定时器在作用上又有所不同。普通的定时器一般起计时作用,计时超时 (timer out)则引起一个中断,例如触发一个系统时钟中断。WatchDog本质上是一种定时器,那么普通定时器所拥有的特征它也应该具备,当它计时超时时也会引起事件的发生,只是这个事件除了可以是系统中断外,还可以是一个系统重启信号(reset signal)。可以理解为,能发送系统重启信号的定时器就称为“WatchDog”。
2 WatchDog的工作描述
看门狗定时器包含一个数字计数器,该计数器可以从一个事先设置好的数开始以不变的速度减到0。计数器的速度是由一个时钟电路控制的[1]。如果计数器在系统恢复之前减到0,它就会向指定的电路发送信号,通知它执行相应的动作。当一个硬件系统开启了WatchDog功能时,运行在这个硬件系统之上的软件必须在规定的时间间隔内向WatchDog发送一个信号(这个行为简称为“喂狗”),以免WatchDog计时超时引发系统重启。但是必须清楚看门狗的溢出时间(定时器的溢出周期),以决定在合适的时候“喂狗”。“喂狗”不能过于频繁,否则会造成资源浪费。
例如笔者在开发中使用的S3C2410的WatchDog,根据PCLK、Prescaler Value、Clock Select会产生一个WatchDog自己的工作周期。WatchDog在一个周期结束时会产生一个计数递减信号,每当这个信号产生时,看门狗计数寄存器WTCNT中的值便减1。若在WTCNT递减为0(timer out)时软件层还没有重新往WTCNT中写入数值(这个行为便是上文提到的“喂狗”),则WatchDog触发reset signal,系统重启。
3 WatchDog存在的意义
开启了WatchDog之后软件必须定时向它发信息,这不仅麻烦且耗费资源。其实,这个行为是软件向硬件报告自身运行状态的一种手法。一个软件运行良好,那么它应该可以在规定的时间间隔内向WatchDog发送信息,这等同于软件每隔一段时间就告诉硬件运行正常。若软件由于某个不当的操作或者程序出现冲突,或者在操作系统中出现内存管理的问题时而进入死循环(也就是俗称的“死机”),则它就无法向 WatchDog发送信息了,WatchDog将发生计时超时,从而引起硬件重启。如果没有WatchDog的存在,程序已经死掉了,但用户还以为系统正在进行大规模的运算而耐心地等待着。
4 WatchDog失效现象
只要在程序中能证明程序正常运行的地方插入看门狗复位指令,程序运行就能得到很好的监控。然而,这样一个理想的“地方”并非总能找到。WatchDog的监督也并非总是有效。下面列举说明一些WatchDog的失效现象,并对其机理及对策进行探讨。
4.1 看门狗启动失败
WatchDog失效多见于许多ARM核内自带看门狗电路和开发目标板的情况。ARM核复位时将自带看门狗电路禁止,只有当程序访问该电路时(即使能看门狗控制寄存器使能位时)电路启动。能够修改看门狗控制寄存器使能位的值禁止看门狗,是为了适应用户程序开发阶段的需要,但同时给看门狗启动和运行失败留下了后门,在看门狗启动时或启动前遇干扰而使程序跑飞,则看门狗启动失败,无法行使监控职能。
4.2 程序跑飞
程序跑飞,看门狗失效又可分很多情况,以下介绍几种常见情况。
(1) 程序跑飞,看门狗未觉察到
所谓“未觉察到”,是指程序跑飞后,看门狗仍能收到有效的喂狗信号,即在溢出前能被复位。这时又可分为两种情况:
① 看门狗的复位指令放置位置不当,程序运行至此并不能很好地代表程序是正常运行的。如将其放在中断子程序中,一般来说,只要中断屏蔽寄存器中的相应位开放,中断程序就能正常响应中断,所以中断子程序中喂狗有时是不能正常起作用的。
② 程序跑飞后,在重构的“程序”运行时,仍能在每次看门狗溢出前产生有效的看门狗访问。这多见于片外看门狗。
(2) 因程序跑飞,看门狗被禁止
ARM核内看门狗、所有的片外看门狗芯片均具有禁止看门狗的操作,甚至只要一条指令,如S3C2410 WatchDog只要通过“rWTCON|=05”修改看门狗控制寄存器使能位的值就能禁止[2]。这一点风险很大,写程序时应予以重视。也许当程序跑飞时,错误指令修改了ARM核内看门狗控制寄存器的使能位,看门狗就会被禁止。
(3) 程序跑飞,看门狗时钟消失
看门狗时钟消失情况多见于片内看门狗,大多ARM核内看门狗与CPU共用时钟源,但有些单片机可以禁止时钟以省电待机。程序跑飞时可能会出现时钟被禁止的现象,如果片外看门狗依赖此时钟(如用ALE作为看门狗时钟时),则无法正常工作。
4.3 部分程序跑飞或异常
对于运行于多进程、多线程环境的系统[3],笔者尚未发现有硬件上能支持多线程级别的监控的,这一点往往未能引起开发人员的重视。而实际上应对运行在一个操作系统上所有进程的所有线程进行同时监控,只要有一个线程工作异常,就应控制计算机进入异常处理程序或重新启动计算机。
4.4 部分程序永远运行不到
WatchDog定时周期过短,致使部分功能无法完成或根本未运行到就已溢出,复位后又重复这一过程。有时这种现象比较隐蔽,如只在某特定条件下这部分功能才有表现,不易发现。一般情况下,只要在调试时,注意测试复位引脚有无复位脉冲,就能发现。但是,也可能只在需要运行这部分功能的条件具备时,才出现WatchDog溢出现象,这时就要通过分析程序,较精确地计算出一个合适的WatchDog定时周期值,并人为创造这种“最不利”条件来测试它。
4.5 恢复失败和硬件损坏
有些应用中,不必通过复位恢复程序功能,如部分功能失效、程序死锁等,只需通过非屏蔽中断(NMI)触发错误处理程序即可恢复正常;但当恢复必需的参数被破坏时,恢复失败。这时错误处理程序自动通过死锁等待复位信号到来,使程序全部恢复,所以硬件复位信号是必要的。
由于看门狗电路硬件损坏,造成WatchDog不起作用也是WatchDog失效的原因之一。
5 失效解决方案
解决WatchDog失效的问题可以从两个方面着手:其一为软件,这主要是针对片内WatchDog失效问题,考虑“喂狗”频率以及“喂狗”语句所放的位置(即看门狗的复位指令放置位置),以及看门狗监控的范围,等等,这是一种经济、方便、可行的方法,许多文献中对此作了大量探讨;其二,硬件方法,改进看门狗电路,比如可以利用CPLD方便地构造多个WatchDog,以实现对多模块或多线程的监视,这主要是针对片外WatchDog电路失效的问题。
结语
不论是在嵌入式开发还是工业控制中,WatchDog对保持系统和程序的稳定、可靠都起着非常重要的作用。程序失效多源自恶劣的现场环境,用于测量、控制用途的计算机必须设有WatchDog,以保证其程序失效后的可靠恢复;但有了WatchDog并不能说明系统的失效恢复就是可靠的了,本文就提到了很多会引起WatchDog失效的原因。值得注意的是,WatchDog是系统可靠运行的最后一道防线,频繁出现WatchDog溢出而使系统复位的系统,是不可靠的,实际应用中是不允许的。所以,尽管有了可靠的WatchDog,但是,还必须在电路设计和软件编程等方面注意加强抗干扰措施,从根本上提高系统抗干扰能力。