Embedded 在多任务环境中喂饲看门狗的策略

Embedded 在多任务环境中喂饲看门狗的策略,embedded,freertos,Embedded,Freertos,在将一些嵌入式代码迁移到FreeRTOS之后,我就陷入了一个关于看门狗的有趣的两难境地。看门狗定时器对于我们的应用程序来说是必须的。使用FreeRTOS对我们来说也是一大福音。当应用程序是单任务时,它会在逻辑流中的及时点向看门狗提供信息,这样我们就可以确保任务以及时的方式进行逻辑处理 但是,要完成多个任务,这并不容易。一项任务可能因为某种原因而无法完成,但另一项任务做得很好,并且取得了足够的进展,让看门狗能够快乐地进食 一种想法是启动一个单独的任务来为看门狗提供反馈,然后使用其他任务定期增加的一

在将一些嵌入式代码迁移到FreeRTOS之后,我就陷入了一个关于看门狗的有趣的两难境地。看门狗定时器对于我们的应用程序来说是必须的。使用FreeRTOS对我们来说也是一大福音。当应用程序是单任务时,它会在逻辑流中的及时点向看门狗提供信息,这样我们就可以确保任务以及时的方式进行逻辑处理

但是,要完成多个任务,这并不容易。一项任务可能因为某种原因而无法完成,但另一项任务做得很好,并且取得了足够的进展,让看门狗能够快乐地进食

一种想法是启动一个单独的任务来为看门狗提供反馈,然后使用其他任务定期增加的一些计数器,当看门狗任务滴答作响时,它将确保所有计数器看起来像是在所有其他任务上取得进展,如果是这样,继续为看门狗提供反馈


我很好奇其他人在这种情况下做了什么?

这确实是看门狗定时器的一大难题

我的主板在GPIO线上有一个LED,所以我在一个while/sleep循环中(750ms打开,250ms关闭)闪烁,在一个仅次于最低优先级的线程中(最低优先级是空闲线程,在循环中进入低功耗模式)。我在LED闪烁线程中添加了一个wdog提要


这有助于解决完全崩溃和CPU循环的高优先级线程,但在系统死锁时没有帮助。幸运的是,我的消息传递设计没有死锁(嗯,无论如何也不经常死锁)。

监视所有其他任务状态的看门狗任务是一个很好的解决方案。但是代替计数器,考虑为每个任务使用状态标志。状态标志应该有三个可能的值:未知、活动和休眠。当周期性任务运行时,它会将标志设置为活动。在异步事件上阻塞的任务应在阻塞前将其标志设置为“睡眠”,在运行时将其标志设置为“活动”。当看门狗监视器任务运行时,如果每个任务都处于活动状态或休眠状态,它应该踢看门狗。然后,看门狗监视器任务应将所有活动标志设置为未知。(休眠标志应保持休眠。)具有未知标志的任务必须运行并再次将其标志设置为“活动”或“休眠”,然后监视器任务才会再次触发监视程序


有关更多详细信息,请参阅本文的“多任务处理”部分:

不要忘记处理任务被删除或休眠更长时间的可能情况。如果这些任务以前是通过看门狗任务签入的,那么它们还需要一个“签出”机制

换句话说,看门狗任务负责的任务列表应该是动态的,并且应该进行组织,以便一些通配符不能轻易地从列表中删除任务


我知道,说起来容易做起来难…

我已经使用FreeRTOS定时器设计了解决方案:

  • SystemSupervisor SW定时器,为HW WD馈电。弗里特斯故障 导致重置
  • 每个任务都会创建具有系统重置功能的“自己的”软件计时器
  • 每个任务负责在计时器过期之前“手动”重新加载计时器
  • 系统重置功能在提交数据之前保存数据
  • 下面是一些伪代码列表:

    //---------------------------------
    //
    // 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);
    }
    

    你说的我们都做了。有一个kicker,具有已知周期的任务与kicker一起签入。如果这些任务没有及时执行,踢球者也不会执行。kicker应该是系统中优先级最低的线程,因此如果系统没有时间到达kicker,那么设备将重置。(这也给了你对踢球者本身的保护。)我现在很忙,但稍后会尝试给出一个较长的答案。我似乎记得上个月左右有一个类似的问题,当然有嵌入的标签。