在多任务环境中为看门狗提供服务的策略

时间:2013-02-07 18:11:11

标签: embedded freertos

将一些嵌入式代码移到FreeRTOS之后,我对这个看门狗留下了一个有趣的困境。看门狗定时器是我们应用的必备条件。使用FreeRTOS对我们来说也是一个巨大的福音。当应用程序更加单一任务时,它会在其逻辑流程中及时为监督者提供信息,以便我们确保任务能够及时地完成逻辑进展。

虽然有多项任务,但这并不容易。由于某种原因,一项任务可能会受到限制,而不是取得进展,但另一项任务正在做得很好并取得足够的进展以保持看门狗的快乐。“

一种想法是仅仅为了给看门狗提供一个单独的任务,然后使用一些其他任务定期增加的计数器,当看门狗任务开始时,它将确保所有计数器看起来像是在进行所有其他任务,如果是,请继续为看门狗提供帮助。

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

4 个答案:

答案 0 :(得分:8)

监视所有其他任务状态的监视任务是一个很好的解决方案。但是,不要使用计数器,而是考虑为每个任务使用状态标志。状态标志应该有三个可能的值:UNKNOWN,ALIVE和ASLEEP。当周期性任务运行时,它将标志设置为ALIVE。阻止异步事件的任务应在阻止之前将其标志设置为ASLEEP,并在运行时将其设置为ALIVE。当监视程序监视器任务运行时,如果每个任务都是ALIVE或ASLEEP,它应该启动监视程序。然后看门狗监视器任务应将所有ALIVE标志设置为UNKNOWN。 (ASLEEP标志应该保持ASLEEP。)具有UNKNOWN标志的任务必须运行并将其标志设置为ALIVE或ASLEEP,然后监视器任务才会重新启动监视程序。

有关详细信息,请参阅本文的“多任务”部分:http://www.embedded.com/design/debug-and-optimization/4402288/Watchdog-Timers

答案 1 :(得分:2)

看门狗定时器确实是一个巨大的痛苦。

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

这有助于CPU循环完全崩溃和优先级较高的线程,但如果系统死锁则无效。幸运的是,我的消息传递设计没有死锁,(好吧,不管怎样,不管怎样:)。

答案 2 :(得分:2)

不要忘记处理删除任务或长时间处于休眠状态的可能情况。如果先前使用监视程序任务检入了这些任务,则还需要具有“检出”机制。

换句话说,监视任务负责的任务列表应该是动态的,并且应该对其进行组织,以便某些通配代码不能轻易地从列表中删除该任务。

我知道,说起来容易做起来......

答案 3 :(得分:0)

我使用FreeRTOS计时器设计解决方案:

  1. SystemSupervisor SW计时器为HW WD提供。 FreeRTOS失败 导致重置。
  2. 每个任务都会创建自己的"具有SystemReset功能的SW计时器。
  3. 每个任务负责"手动"在计时器到期之前重新加载它。
  4. SystemReset函数在提交suiside之前保存数据
  5. 这是一些伪代码列表:

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