关于看门狗想必各位嵌入式软件开发的朋友应该都不会陌生的。在嵌入式软件开发中,看门狗常被用于监测cpu的程序是否正常在运行,如果cpu程序运行异常会由看门狗在达到设定的阈值时触发复位,从而让整个cpu复位重新开始运行。
看门狗的本质是一个计数器,一开始的时候配置其为一个特定的值,然后这个计数器就会一直运行倒数自减,自减到0就会引发系统复位。所以为了避免被复位,就需要隔一定的时间复位看门狗的计数值,也就是我们常说的 “喂狗” 。
这个 “喂狗” 的动作应当发生在看门狗引发复位的阈值的间隔中,否者超过或者达到这个阈值,会导致系统被复位,这是我们所不希望看到的。
关于看门狗在程序中使用,可以分两种情况去讨论:
1)裸机中使用看门狗;
2)RTOS环境中使用看门狗。
1、裸机中使用看门狗
在裸机中使用看门狗,由于裸机的编程和程序执行流的方式的影响,一般开发人员通常会在主循环中进行看门狗的“喂狗”操作。
这种时候是要开发人员很合理的评估自己所写代码的执行流程,能够估算整个主循环中最坏的执行时间的值,从而设定看门狗的阈值时间,保证最坏的情况下,看门狗不至于复位系统。
裸机中使用看门狗进行系统监测的常见的两种方式:
(1)在代码的执行流中插入喂狗
这是一种最简单的方式。开发的时候一般都是在程序执行流中插入看门狗的“喂狗”,特别是针对程序中需要较长时间占用执行的程序段中要加入“喂狗”操作。对于执行过程中占用时间较少的,可以在主循环流程中添加“喂狗”即可。
(2)用定时器进行定时“喂狗”
在裸机中也可以使用定时器的方式进行定时喂狗。这种方式相比在代码中多处插入“喂狗”操作要使代码看起来简洁一下,但是一般都需要占用硬件定时的硬件资源,还要多加定时器中断,如果程序本身就较为复杂的话,多加异常中断可能会给系统维护和稳定性带来一些不可预料的问题。
当然,还有其他的实现和使用的方式,对于裸机的看门狗“喂狗”,总体而言是比较简单的,需要考虑的东西相对少一些,实现起来更加简单。
2、RTOS中使用看门狗
在RTOS中使用看门狗就复杂很多,需要考虑的问题就较为多。因为RTOS中的多任务机制的存在,理论上程序越复杂,系统运行就越复杂,多任务的存在就可能会有更多的变化情况,有些可能还不好预料。
在多任务中,用看门狗的时候,我们希望可以实现看门狗监测整个系统每个任务的健康存活情况。假如系统中某个任务死掉了,能够通过看门狗进行系统复位,从而重新复位系统,以使系统重新开始运行。而每个任务都正常的时候,不要进行看门狗复位,从而不影响系统的正常执行。
浅显的讨论一下在RTOS下的看门狗 “喂狗” 的实现方式:
(1)在代码的执行流中插入“喂狗”
这种方式就是在每个任务的调度流中都插入“喂狗”操作,然后通过任务的调度执行实现“喂狗”的操作。这种方式就比较好理解也不复杂,只要开发者熟悉代码,知道代码的执行顺序流,然后在程序中插入“喂狗”操作即可。
这种方式有什么优缺点呢?
优点:
方便实现。只要在各个任务中调用“喂狗”操作即可,在占用cpu执行时间较长的程序段也要注意“喂狗”。
缺点:
不能实现监控每个任务的存活情况。因为当使用这种方式的时候,有多处地方可以进行喂狗操作,这个时候假如某个任务已经死掉了,它自身因为已经死掉不能在进行喂狗,但是其他的任务可以喂狗,整个系统依然不回被复位,也就不能知道某个任务是否出现问题。
(2)监视各个任务的存活状态进行喂狗
这种方式相比较于到处去调用喂狗操作更加实用,它是要在确认每个任务都正常存活的情况下才喂狗。如果某个任务因为故障不再运行了,就会导致超时不能喂狗,从而会导致系统被看门狗复位。
这种方式的实现有很多种手段,比如用事件标志组的方式就比较容易实现。
做法是:
1)创建一个“喂狗”的独立任务;
2)申请一个事件标志组,并为每个任务留一个标志位;
3)在每个单独的任务中执行的时候置位属于这个任务的标志位;
4)在“喂狗”的独立任务中检测这些所有的任务所关联的标志位,
如果所有的标志位都置位成立,说明所有的任务都正常,进行一次喂狗操作。反之则引发一次复位。
这种方式也有一个问题需要留意的:
其他的任务可以通过这个“喂狗”的独立任务进行监测,那这个独立的“喂狗”任务由谁来监测它呢?答案肯定是由看门狗进行监测啊。
在这个独立的“喂狗”任务中,它除了要监测其他任务的事件标志外,还要自身能够定时的进行“喂狗”的操作,防止长时间不“喂狗”导致系统复位。这样可以实现看门狗监测这个“喂狗”任务,而“喂狗”任务监测其他的任务的状态。
特别注意:因为RTOS环境下的软件开发毕竟与裸机开发不同,RTOS下的有阻塞、挂起、删除、恢复任务等的操作,所以对使用看门狗会有更多的难度,需要综合实际的使用场景进行考虑。
当然,文章里只是简单的分析了一些使用看门狗的思路,做法是多种多样的,如果有觉得文中分析的有误,还望指正!有更好的思路也望多多分享!!!