C 如何在RTOS中使用看门狗定时器?
假设我在嵌入式环境中有一个协作调度器。我有许多进程正在运行。我想利用看门狗定时器,这样我就可以检测进程何时因任何原因停止运行,并重置处理器 在没有RTO的简单应用程序中,我总是从主循环触摸看门狗,这总是足够的。然而,这里有许多进程可能会挂起。在确保每个过程处于良好状态的同时,定期触摸看门狗定时器的清洁方法是什么C 如何在RTOS中使用看门狗定时器?,c,embedded,rtos,watchdog,C,Embedded,Rtos,Watchdog,假设我在嵌入式环境中有一个协作调度器。我有许多进程正在运行。我想利用看门狗定时器,这样我就可以检测进程何时因任何原因停止运行,并重置处理器 在没有RTO的简单应用程序中,我总是从主循环触摸看门狗,这总是足够的。然而,这里有许多进程可能会挂起。在确保每个过程处于良好状态的同时,定期触摸看门狗定时器的清洁方法是什么 我在想,我可以为每个进程提供一个回调函数,这样它就可以让另一个监视所有进程的函数知道它还活着。回调将传递一个参数,该参数将是任务的唯一id,以便监督者可以确定谁在回调 传统的方法是让看门
我在想,我可以为每个进程提供一个回调函数,这样它就可以让另一个监视所有进程的函数知道它还活着。回调将传递一个参数,该参数将是任务的唯一id,以便监督者可以确定谁在回调 传统的方法是让看门狗进程具有尽可能低的优先级
PROCESS(watchdog, PRIORITY_LOWEST) { while(1){reset_timer(); sleep(1);} }
实际的硬件定时器可能每3或5秒重置一次CPU
跟踪单个进程可以通过反向逻辑实现:每个进程将设置一个计时器,其回调将向看门狗发送“停止”消息。然后,每个进程都需要取消以前的计时器事件,并在“从队列接收事件/消息”循环中的某个位置设置一个新的计时器事件
PROCESS(watchdog, PRIORITY_LOWEST) {
while(1) {
if (!messages_in_queue()) reset_timer();
sleep(1);
}
}
void wdg_callback(int event) {
msg = new Message();
send(&msg, watchdog);
};
PROCESS(foo, PRIORITY_HIGH) {
timer event=new Timer(1000, wdg_callback);
while (1) {
if (receive(msg, TIMEOUT)) {
// handle msg
} else { // TIMEOUT expired
cancel_event(event);
event = new Timer(1000,wdg_callback);
}
}
}
一种常见的方法是将看门狗踢腿授权给特定任务(通常是最高优先级或最低优先级,每种方法的权衡/动机),然后让所有其他任务“签入”该任务 这样:
- 如果中断被挂起(100%CPU),kicker任务将不会运行,您需要重置
- 如果kicker任务挂起,则重置
- 如果另一个任务被挂起,kicker任务未看到签入,kicker任务不触发WDG,则重置
- 希望被检查的每个线程都显式地向看门狗线程注册其回调,看门狗线程维护一个此类回调的列表李>
- 当看门狗被调度时,它可以迭代已注册任务的列表
- 每个回调本身都会被迭代调用,直到返回正常状态李>
- 在列表的末尾,硬件看门狗被踢了
回调函数本身的设计取决于特定任务及其行为和周期。每个功能都可以根据任务的需要和特点进行定制。高周期性的任务可能只是增加一个计数器,当调用回调时,计数器被设置为零。如果输入时计数器为零,则自上次看门狗检查以来任务未计划。具有低或非周期行为的任务可能会在其调度上加上时间戳,如果任务未在指定的时间段内调度,则回调可能会返回失败。任务和中断处理程序都可以通过这种方式进行监视。此外,由于线程负责向看门狗注册,因此可能有一些线程根本不注册。每个任务都应该有自己的模拟看门狗。只有在所有模拟看门狗都没有超时的情况下,真正的看门狗才由高优先级的实时任务馈送 i、 e:
void taskN_handler()
{
watchdog*wd=watchdog_create(100);/*创建一个超时为100毫秒的模拟看门狗*/
/*开始*/
while(task1\u应该运行)
{
看门狗喂食(wd);/*喂食它*/
/*做事*/
}
看门狗销毁(wd);/*不再需要时销毁*/
}
无效看门狗任务
void taskN_handler()
{
watchdog *wd = watchdog_create(100); /* Create an simulated watchdog with timeout of 100 ms */
/* Do init */
while (task1_should_run)
{
watchdog_feed(wd); /* feed it */
/* do stuff */
}
watchdog_destroy(wd); /* destroy when no longer necessary */
}
void watchdog_task_handler()
{
int i;
bool feed_flag = true;
while(1)
{
/* Check if any simulated watchdog has timeout */
for (i = 0; i < getNOfEnabledWatchdogs(); i++)
{
if (watchogHasTimeout(i)) {
feed_flag = false;
break;
}
}
if (feed_flag)
WatchdogFeedTheHardware();
task_sleep(10);
}