在预定的裸机嵌入式应用程序中使用内部硬件看门狗的最安全方法是什么(以及为什么)?

What (and why) is the most safe way to use a internal hardware watchdog in a scheduled bare-metal embedded app?

我已经在几个 OS-less 嵌入式应用程序(使用静态调度程序)中使用了内部硬件看门狗。

我做的是:

我认为这是一种极简主义但安全的方法。

有什么最佳实践吗? (个人经验或经过验证的来源)

我已经 heard/seen 人们做不同的事情,比如在不同的任务中不止一次踢狗,或者只在超时内调用所有任务时才踢,...

您的方法存在问题,您无法通过 运行 宁所有其他任务 运行 的最慢任务来保证。

并且作为多任务环境中的扩展,您通常会以一些高优先级任务结束,这些任务是确保功能和您并不真正关心的其他任务(IO、硬件监控等)所必需的。

所以你的看门狗只在重要的时候才需要,但你必须观察它们。为了确保您需要一个非常简单的解决方案,一个像这样的 运行ning 状态结构:

struct{
  bool task1HaRun;
  bool task2HasRun;
  bool task3HasRun;
};

周围有一个互斥体。每个任务都设置自己的 hasRunFlag 并检查是否也设置了所有其他任务。如果设置了所有其他设置,它将全部重置并触发看门狗。如果您不让每个任务自行检查,您可能会错过被阻止的任务。

有更优雅的方法来解决这个问题,但那个方法是可移植的,可以让您知道该怎么做。

你的问题有点主观,但是实时应用程序有一些行业事实上的标准,如下所示:

  • 指定系统允许的最大响应时间。比如,允许某些任务花费的最长时间。考虑 ISR 等。例如 1ms.
  • 将狗设置为比指定响应时间稍长的时间。
  • 从整个程序中的一个地方踢狗,最好是从 main() 循环或类似的合适位置(RTOS 没有关于在哪里执行此操作的标准,AFAIK)。

这是最严格的要求 - 理想情况下,狗对您的各种任务一无所知,但远离应用程序逻辑。

在实践中,这对某些系统来说可能很难做到——假设你有闪存引导加载程序和类似的东西,它们本质上必须花费很长时间。然后你可能不得不做一些肮脏的事情,比如将看门狗踢到特定的驱动程序中。但这是争取的最佳实践。

所以理想情况下,您在应用程序的最顶层拥有它:

void main (void)
{
  /* init stuff */

  for(;;)
  {
    kick_dog();
    result = execute();
    error_handler(result);
  }
}

作为此政策的副作用,它消除了 "talented" 人们最终从 ISR 内部踢狗的风险。