有的同学在学习 uCOS 系统过程中,对看门狗任务的优先级产生了疑惑,到底该把喂狗任务优先级设置成最高还是最低好?
这里谈谈作者个人看法,首先给出结论,最低,甚至是在空闲任务运行(使用钩子函数)。
理由首先我们要知道看门狗的工作是什么?为什么要设置看门狗。
很多产品出厂时,都会开启看门狗,这是产品运行的最后保障,可以在出现软件 bug 时(如hardfault,死循环等),及时恢复运行,让产品可以重新继续工作下去,但这不意味着万事大吉,一旦发现了看门狗引起的复位问题(可以通过寄存器标志位查看因何复位),一定要找到问题根因,否则出现了一次,后面一定还会不停出现,用户体验相当不好。
那么我们应该怎么设置看门狗的功能呢?这个学员准备这么设计:
1、超时时间 1s ,喂狗时间 500ms
2、看门狗任务优先级最高
3、每个任务发送信号量给看门狗任务,看门狗任务判断是否收到了全部任务信号量,然后再决定是否喂狗。
看似合理,但其实有许多问题,接下来一个一个讨论。
超时时间?首先是超时时间问题,设计 1s 超时时间,500ms 喂狗,这对喂狗功能本身来说是没有问题的,但这显得过于严苛了,因为只要你某个任务运行超过了 1s,那很容易造成重启现象,虽然说一个任务持续运行 1 s 也算是个不大不小的问题,但你要知道,看门狗是应对极其严重问题下的紧急措施,这种运行缓慢只是体验不好,如果经常发生,在研发阶段就应该解决,如果是偶发的,那么对应客户来说,基本是感知不到的。
而这么短的时间就完成重启,你可能很难从外部现象分清到底是因为电源、复位引脚还是看门狗导致的重启,在没有日志情况下,增大排查范围。
如果我们能设置成10多秒的超时时间,那么我们很容易就能从表象发现,产品停止工作了,然后我们有足够的时间运用作者之前介绍的调试方法《BUG 终结者,现场抓获!|颠覆认知》抓取到现场环境,这对定位这种偶发性问题非常有效(目前所待的两个公司看门狗超时时间都设置在 10 s 以上)。
不过每种产品要求不同,对超时时间也不尽相同,所以自行决定即可(时间要求严格者,可考虑使用窗口看门狗)。
第二点,优先级最高?在作者看来,这绝对不行,这和把看门狗功能放在中断中执行没什么两样。
这里和第三点结合一起讨论。
通过每个任务设置信号量的方式,确实保证了每个任务都正常运行,但真的合适吗?
首先每个任务增加信号量,对系统资源是一大消耗,其次你能保证后续的开发人员在增加任务时能遵照你的设计要求写代码吗?不一定吧。
一旦增加新任务而未增加这个喂狗信号量,那么这个新任务的死活,看门狗可就无能为力了。因为看门狗任务优先级最高,只要现有信号量接收到了,就一定会喂狗,那么新任务可监控不了。
另外有些任务在设计时,可能就是很长时间才运行一次(如外部中断触发),那么这种任务肯定要因为你这个设计而不得不做出修改。
还有些任务走了异常分支,并没有释放CPU的行为(如delay),却能正常释放信号量,那么也是很难发现的。
而将看门狗任务优先级设计成最低(建议在空闲任务执行,这样它一定是最低的,不会被人为修改),那么不管后面的人怎么添加新任务,只要新任务死循环,不释放 CPU(低优先级任务无法运行,包括看门狗任务),那么一定会被感知到,从而使看门狗复位。
而为了保证一些关键代码一定会被执行,可以设计一个变量,每个 bit 是一处关键代码(在关键代码执行后置 1),这样只要在喂狗前判断这个变量相关位是否设置即可。就是要注意该变量的保护,如关中断。
这样通过低优先级+位域的方式,就保证了其它任务一定都能被执行到,并且对关键代码也做了进一步运行保证,使看门狗功能最大化。