在多任务环境中喂养看门狗的策略
Posted
技术标签:
【中文标题】在多任务环境中喂养看门狗的策略【英文标题】:Strategy for feeding a watchdog in a multitask environment 【发布时间】:2013-01-23 08:40:37 【问题描述】:将一些嵌入式代码移至 FreeRTOS 后,我在看门狗方面遇到了一个有趣的难题。看门狗定时器对于我们的应用来说是必须的。使用 FreeRTOS 对我们来说也是一个巨大的福音。当应用程序更加单任务时,它会在其逻辑流中的及时点向看门狗提供信息,以便我们可以确保任务及时进行逻辑处理。
虽然有多项任务,但这并不容易。一项任务可能由于某种原因被绑定,没有取得进展,但另一项任务做得很好并且取得了足够的进展,可以让看门狗高兴地吃饱。
一个想法是单独启动一个单独的任务来喂养看门狗,然后使用其他任务定期递增的一些计数器,当看门狗任务滴答作响时,它会确保所有计数器看起来都在进行所有其他任务,如果是这样,继续喂看门狗。
我很好奇其他人在这种情况下做了什么?
【问题讨论】:
我们已经按照您所说的做了很多。有一个踢球者,并且具有已知周期的任务与踢球者一起检查。如果这些任务没有及时运行,那么 kicker 也不会运行。 kicker 应该是系统中优先级最低的线程,所以如果系统没有时间到达 kicker,那么设备将重置。 (这也可以保护踢球者本身。)我现在很忙,但稍后会尝试将更长的答案放在一起。 我似乎记得上个月左右有一个类似的问题,当然是嵌入式标签。 【参考方案1】:我使用 FreeRTOS 计时器设计了解决方案:
-
SystemSupervisor 软件计时器,为硬件 WD 提供数据。 FreeRTOS 失败
导致重置。
每个任务都使用 SystemReset 功能创建“自己的”软件计时器。
负责“手动”重新加载其计时器的每个任务在其到期之前。
SystemReset 功能保存数据在提交之前
这是一些伪代码清单:
//---------------------------------
//
// System WD
//
void WD_init(void)
HW_WD_Init();
// Read Saved Failure data, Send to Monitor
// Create Monitor timer
xTimerCreate( "System WD", // Name
HW_WD_INTERVAL/2, // Reload value
TRUE, // Auto Reload
0, // Timed ID (Data per timer)
SYS_WD_Feed);
void SYS_WD_Feed(void)
HW_WD_Feed();
//-------------------------
// Tasks WD
//
WD_Handler WD_Create()
return xTimerCreate( "", // Name
100, // Dummy Reload value
FALSE, // Auto Reload
pxCurrentTCB, // Timed ID (Data per timer)
Task_WD_Reset);
Task_WD_Reset(pxTimer)
TaskHandler_t th = pvTimerGetTimerID(pxTimer)
// Save Task Name and Status
// Reset
Task_WD_Feed(WD_Handler, ms)
xTimerChangePeriod(WD_Handler, ms / portTICK_PERIOD_MS, 100);
【讨论】:
【参考方案2】:不要忘记处理任务被删除或休眠较长时间的可能情况。如果这些任务之前是通过看门狗任务签入的,那么它们还需要有一个“签出”机制。
换句话说,看门狗任务负责的任务列表应该是动态的,并且应该组织起来,以便某些野代码无法轻易从列表中删除该任务。
我知道,说起来容易做起来难......
【讨论】:
【参考方案3】:监视所有其他任务状态的看门狗任务是一个很好的解决方案。但不要使用计数器,而是考虑为每个任务使用状态标志。状态标志应该具有三个可能的值:UNKNOWN、ALIVE 和 ASLEEP。当周期性任务运行时,它会将标志设置为 ALIVE。阻塞异步事件的任务应在阻塞前将其标志设置为 ASLEEP,并在运行时将其设置为 ALIVE。当看门狗监视器任务运行时,如果每个任务都处于活动状态或处于睡眠状态,它应该启动看门狗。然后看门狗监控任务应该将所有的 ALIVE 标志设置为 UNKNOWN。 (ASLEEP 标志应保持为 ASLEEP。)具有 UNKNOWN 标志的任务必须运行并将其标志再次设置为 ALIVE 或 ASLEEP,然后监视器任务将再次启动看门狗。
更多详情请参阅本文的“多任务处理”部分:http://www.embedded.com/design/debug-and-optimization/4402288/Watchdog-Timers
【讨论】:
【参考方案4】:这确实是看门狗定时器的一大痛。
我的电路板在 GPIO 线上有一个 LED,所以我在 while/sleep 循环中闪烁它,(750ms 开,250ms 关),在一个次低优先级线程中,(最低是空闲线程,它只是去在循环中进入低功耗模式)。我在 LED-flash 线程中放了一个 wdog 提要。
这有助于解决完全崩溃和 CPU 循环的更高优先级线程,但如果系统死锁则无济于事。幸运的是,我的消息传递设计没有死锁,(嗯,不经常,反正:)。
【讨论】:
以上是关于在多任务环境中喂养看门狗的策略的主要内容,如果未能解决你的问题,请参考以下文章