C++ 嵌入式任务监视器

任务监视器适用于嵌入式系统,包括运行轻量级 RTOS(例如,FreeRTOS)的小型微控制器环境。任务监视器确保所有其他任务在系统中按预期运行。如果某项特定任务出现故障,则任务监视器可以根据用户想要执行的操作采取措施。默认为 ASSERT 并允许看门狗失效以重置设备。但是,它可以很容易地更新以重新启动违反的任务。

介绍

在多线程环境中工作时,拥有任务监视器是实现稳健性、安全性和稳定性的最有用和最关键的组件之一。本质上,任务监视器确保系统中的所有其他任务都按预期正常工作。如果任务停止使用任务监视器签入,任务监视器可以识别违规并执行各种操作。一个非常基本的操作是允许看门狗超时并重置设备。

我从事的几乎每一个产品都包含某种类型的任务监视器,并且在各种项目和多年的工作中改进了实施,我觉得这对社区很有用。

背景

许多操作系统都内置了用于任务监控的功能(例如 linux)。然而,许多较小的实时操作系统(例如,FreeRTOS)没有此功能。此实现旨在用于可能没有内置功能的小型嵌入式系统。

特征

  • 监控任意数量的任务
  • 每个任务可以有一个唯一的超时时间
  • 任务监视器将发送一条消息让任务响应
  • 或者任务可以随时向任务监视器发送消息,而无需响应特定消息
  • 任务监视器自动确定正在签入的任务(无需跟踪或发送任务 ID)
  • 看门狗只需要在一个地方进行管理
  • 事件驱动和消息驱动任务的理想选择
  • 占地面积小
  • 可用于非常小的嵌入式系统(例如,如果需要,可以在 8 位微上使用 FreeRTOS)
  • 与 RTOS 无关(可与任何带有少量更新的 RTOS 一起使用)
  • 在该任务超时期间,消息只会在每个周期发出一次(例如,任务超时为 100 毫秒,然后发出的消息最多每 100 毫秒发生一次,无论收到响应的速度有多快)
  • 接收到任务签入的主动消息将自动重置时间,因此消息不会不必要地发送给任务

使用代码

使用现有任务/线程中的功能只需要两个基本功能。

首先,任务需要向任务监视器注册自己。这应该作为任务/线程初始化的一部分,或在任务/线程开始时完成。

  • 第一个参数是任务监视器将等待来自任务的响应(来自签入请求)的最长时间。
  • 第二个参数是指向检查调用的函数指针,任务监视器用于在发出检查请求时向任务发送消息。
C++
<span style="color:#111111"><span style="background-color:#ffffff"><span style="color:#000000"><span style="background-color:#fbedbb">TaskMonitor::Register(TIMEOUT, &TaskCheckin);</span></span></span></span>

另一个主要功能是在需要时使用任务监视器进行检查。

C++
<span style="color:#111111"><span style="background-color:#ffffff"><span style="color:#000000"><span style="background-color:#fbedbb">TaskMonitor::TaskCheckin();</span></span></span></span>

本文链接的代码显示了以不同方式使用任务监视器的四个不同任务的示例用法。任务可以响应签入请求,或根据需要抢先签入。

任务监视器将在每个超时时间段(注册期间提供的时间)向已注册任务发送一次请求TIMEOUT。如果已注册的任务在任务监视器发送请求之前向任务监视器发布签入,则计时器将重置并且任务监视器将不会发送请求,直到另一个完整的超时时间过去。

任务监控任务

任务监视器功能依赖于使用的操作系统,并且需要有自己的任务/线程来操作。因此,开发人员需要创建和启动任务监视器任务作为其余系统任务初始化的一部分。例如,在 FreeRTOS 中:

C++
<span style="color:#111111"><span style="background-color:#ffffff"><span style="color:#000000"><span style="background-color:#fbedbb"><span style="color:#0000ff">void</span> StartTaskMonitor(<span style="color:#0000ff">void</span> *argument)
{
    TaskMonitor taskMon;
    taskMon.Initialize();
    taskMon.Run();
}

<span style="color:#0000ff">void</span> app_main(<span style="color:#0000ff">void</span>)
{
    TaskHandle_t taskHandle = <span style="color:#0000ff">nullptr</span>;

    <span style="color:#008000"><em>// Task monitor
</em></span>    xTaskCreate(&StartTaskMonitor, <span style="color:#800080">"</span><span style="color:#800080">TaskMonitor"</span>, TASK_MONITOR_STACK_SIZE, 
                NULL, TASK_MONITOR_PRIORITY, &taskHandle);
}</span></span></span></span>

操作系统移植

任务监视器也使用一些操作系统调用来操作。因此,创建TargetPort.hppTargetPort.cpp是为了轻松移植到正在使用的不同操作系统。用于移植的主要项目是消息队列操作、任务识别操作和看门狗操作。

违规行为

当任务监视器确定任务违反了签入的时间限制时,它会采取行动。默认操作是执行以下操作:

C++
<span style="color:#111111"><span style="background-color:#ffffff"><span style="color:#000000"><span style="background-color:#fbedbb"><span style="color:#008000"><em>// check for expired task checkins... if there was a violation, 
</em></span><span style="color:#008000"><em>// we can print the name of the violator and then wait until the watchdog bites
</em></span><span style="color:#0000ff">if</span> (monInfo.elapsedTimeWaitingForResponse <span style="color:#0000ff">></span> monInfo.timeout)
{
   LOG_ERROR(<span style="color:#800080">"</span><span style="color:#800080">TaskMonitor"</span>, <span style="color:#800080">"</span><span style="color:#800080">Task: %s - Exceeded Checkin Time. 
              Elapsed time %u ms, Timeout %u ms"</span>,
              GetTaskName(taskId), monInfo.elapsedTimeWaitingForResponse, 
              monInfo.timeout);

   <span style="color:#0000ff">while</span>(<span style="color:#000080">1</span>) {}
}</span></span></span></span>

while(1) {} 允许任务永远旋转,直到看门狗重置设备。可以更新此代码以执行用户想要的任何操作:

C++
<span style="color:#111111"><span style="background-color:#ffffff"><span style="color:#000000"><span style="background-color:#fbedbb"><span style="color:#008000"><em>// Designers can also replace the above with their own logic that can reset tasks, 
</em></span><span style="color:#008000"><em>// end tasks, or take other actions
</em></span><span style="color:#008000"><em>// based on violations. Example below:
</em></span><span style="color:#008000"><em>// if (monInfo.elapsedTimeWaitingForResponse > monInfo.timeout)
</em></span><span style="color:#008000"><em>// {
</em></span><span style="color:#008000"><em>//    // Do action, such as restart the task that violated the timeout
</em></span><span style="color:#008000"><em>// }</em></span></span></span></span></span>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值