看门狗定时器 (WDT) 是一种硬件,它监视代码的执行情况,以在软件崩溃时重置处理器。多年来,嵌入式世界一直在激烈争论它们的重要性。不少工程师认为 WDT 是不必要的。他们声称,更好的解决方案是编写不会崩溃的固件。这是一种崇高的情操,因为完美是一个崇高而令人钦佩的目标。
然而,很少有产品能达到这样的质量水平。随着软件规模的扩大,即使是对质量毫不妥协的关注也很难达到完美。一个百万行的程序,如果代码的正确率达到 99.99%(这个数字远远高于绝大多数组织所达到的数字),就会有 100 个潜伏的错误。其中任何一个都可能使系统崩溃或更糟——将其置于危险的操作模式。(唉,一般的嵌入式系统只删除了所有错误的 95% 。1
错误不是唯一的问题。完美设计和构建的硬件在其上执行完美代码仍然可能失败。
宇宙射线越来越多地在数字系统中引起问题。它们主要由来自太空的高能质子组成,可以与 IC 上的晶体管和翻转位相互作用。在微处理器的早期,这些威胁比今天要小得多,因为工艺几何尺寸很大——需要大量能量来实现位翻转。如今,由于 45 nm 的几何形状是常规的,而 28 nm 并不少见,并且每年都会出现较小的节点,因此问题变得更加严重。
在 1990 年代,IBM 发现一台典型的计算机每个月每 256 MB 的 RAM 都会遇到一次由宇宙射线引起的错误。2从那时起,几何形状已经缩小了很多,所以问题可能变得更糟了。
英特尔认为,未来宇宙射线可能会成为越来越多的计算机错误来源。他们的专利 7,309,866 使用 MEMS 传感器来检测进入的宇宙射线,然后向电路发出信号以采取纠正措施。3
H. Kobayashi 等人。发现宇宙射线和其他粒子的误差在 180 nm 几何结构的设备中是 250 nm 几何结构的两倍多。4
Tezzaron Semiconductor 2004 年的一篇论文表明,SRAM 和逻辑是宇宙射线扰动的主要受害者。5作者声称,具有 1 GB SRAM 的系统每两周会出现一次软错误,而丹佛的问题比海平面的问题严重十倍。
令人惊讶的是,一个只有 10 飞库仑电荷的粒子有足够的能量来翻转 SRAM 位。6十年前,较大的细胞需要五倍的能量。
底线:即使是完美编写的代码也可能崩溃。只有看门狗定时器可以帮助崩溃的系统恢复。
出色的 WDT
由于 WDT 是最后一道防线,因此其设计必须预见到任何故障模式。有人可能会问,“伟大的看门狗有什么特点?”
首先,WDT 必须独立于 CPU。无论处理器发现自己处于何种奇怪模式,看门狗定时器都必须正常工作。此外,一旦在初始化时设置,处理器所做的任何事情都不能禁用或重新编程看门狗。否则,流氓程序可能会意外禁用此保护机制,使其无用。
WDT 必须始终在任何情况下(除非可能出现硬件故障)使系统恢复运行。这意味着向 CPU 发出硬复位。没有其他选择可以保证让崩溃的处理器起死回生。
一些 WDT 发出不可屏蔽的中断而不是复位。这个想法是 NMI 的服务例程可以对堆栈进行快照并记录调试信息。唉,没有理由相信处于任意功能失调模式的 CPU 会响应任何中断。在调用服务例程之前需要进行大量处理。在许多处理器上,如果堆栈指针具有奇数或未对齐的地址,则不会启动中断服务程序;实际上,它们可能会进入双总线故障模式,其中 CPU 关闭,只有硬复位才能恢复操作。
然而,NMI 方法很有趣。有时使用的一种替代方法是发出 NMI,并启动计时器。几毫秒后,计时器将复位 CPU。然后,如果 NMI 服务例程有效,它会记录调试信息,但不可避免的硬重置可确保设备恢复运行。
当系统控制危险硬件时,看门狗独立于可能受损的 CPU 将系统置于安全状态是至关重要的。移动机械、危险辐射等必须禁用、停放或以其他方式脱离,因为如果硬件故障导致处理器崩溃,重置可能无法工作。
当今的嵌入式系统通常具有非常复杂的外围设备;在某些情况下,I/O 可能比微处理器复杂得多。WDT 复位序列必须确保这些设备恢复到已知状态。当代码崩溃时,它可能会向外围设备发出奇怪的数据流。如果外围设备的设计使得 CPU 并不总是能够将设备置于已知的正确状态,则这些设备需要从 WDT 进行硬复位。
最后,如果可能的话,最好留下调试面包屑。前面提到的 NMI/deferred-reset 就是一个例子。将堆栈和其他关键参数保存到开发人员可以访问的非易失性内存区域中。不幸的是,重置会破坏所有处理器状态信息,但通常有特定于应用程序的数据可以帮助诊断问题,例如指向状态机表的指针。在重置后初始化它们之前,请保存它们。如果有实时时钟,还要保存复位时间。
内部 WDT
看门狗可分为两大类:处理器芯片上的看门狗和硬件设计人员添加的外部设备。大多数微控制器都有一个内部看门狗,尽管它们的功效差异很大。
一个例子是美心(nee Dallas) DS80C320 / DS80C323,一个 8031 变种,已经存在了很长一段时间。这部分在看门狗中有两个非常好的功能。首先,可以对其进行编程以产生中断,但 512 个周期后它将重置 CPU,因此调试面包屑很容易保存。此外,可以限制对 WDT 寄存器的访问;必须背靠背执行两个特定的移动指令,然后只有一个三周期的窗口可以进行 WDT 寄存器访问。这极大地降低了恶意代码禁用保护机制的机会。然而,人们想知道如果在这些指令之间发生中断会发生什么。大概不会发生 WDT 访问,因此无法启用该功能。显然,软件工程师在执行此序列时必须禁用中断。
飞思卡尔的 MCF520x系列则完全不同。要给看门狗发痒,必须向看门狗服务寄存器发出两次写操作,但在这些操作之间可能会发生任意数量的指令。如果 CPU 崩溃并运行随机代码,这可能会破坏可靠操作。从好的方面来说,复位状态寄存器确实记录了先前的复位是由于外部硬件信号还是由于 WDT 超时,这是重新启动后记录错误的有用方法。可以对看门狗进行编程以产生复位或中断;后者是一个非常糟糕的主意。如果堆栈因错误或恶意代码而变得奇怪,系统将进入双总线故障。中断不会使 CPU 恢复正常运行;只有重置会。
意法半导体新系列STM32F4Cortex™-M4 CPU 有两个独立的看门狗。一个从它自己的内部 RC 振荡器运行。这意味着各种事情都可能在 CPU 中崩溃,而 WDT 仍然会触发。还有一个“窗口看门狗”(WWDT),它要求代码经常对它进行挠痒痒,但不要太频繁。这是一种非常有效的方法,可以确保随机写入保护机制的崩溃代码不会导致 WDT 抖动,并且 WWDT 可以在复位被断言之前不久产生中断。
有趣的是,其中一些部件还包括一个“模拟看门狗”,如果 A/D 的输入超过编程限制,它会触发中断。可以监控电源并检测掉电。在控制危险硬件的系统中,这种早期警告可用于在电源超出操作限制之前将系统置于安全状态。Microchip 的
许多PIC24F系列都具有 WWDT,NXP 的一些部件(例如LPC18xx和LPC43xx系列)也是如此。NXP 的部件可以配置为,一旦启用,软件就不可能关闭 WDT,从而提供更多保护,防止代码运行异常。
这些处理器都没有向外界发出超时发生的信号。如果软件不能保证正确的重新初始化,设计人员可能必须断言一个并行 I/O 位来复位外部硬件。
外部 WDT
很少有微处理器(与微控制器相反)具有内部看门狗定时器,而且在许多情况下,内部 WDT 不能提供特定应用所需的可靠性。在这些情况下,设计应该增加外部硬件,以监控系统操作并在需要时发出复位。
在使用两个或更多 CPU 的系统中,让每个处理器监视另一个处理器的操作是合理的。
有许多 WDT 芯片可用。通常,它们的操作不受软件控制,因此崩溃的程序无法禁用它们的功能。此外,它们还在上电期间断言复位,从而无需这些外部组件。
Maxim 的 MAX6751 是一种外部WWDT。它有一个 WWDT,其超时由电容器控制,如图 1 所示。
图 1:MAX6751 的超时时间由一对电容器设置(由 Maxim 提供)。Texas Instruments 的TPS3126 类似于没有窗口功能的 WWDT。它们适用于各种电源电压和延迟时间,价格低廉,采用 SOT-23 封装。图 2 概述了它们的配置。
图 2:TI 的 TPS3126 监控电源并具有 WDT(德州仪器提供)。TI 还拥有包括TPS386000
在内的一系列部件,可监控四个独立的电源轨并包括一个具有固定延迟的 WDT。其中一个电压监视器可以处理负电源。如果有任何超出公差,则激活单独的“RESET”输出。作为开漏,它们可以被线或在一起。或者,可以将这些连接到输入引脚,以便 CPU 知道哪个电源低,并采取适当的措施,如图 3 所示
图 3:TPS386000 监控四个电源(由 Texas Instruments 提供)。
Analog Devices 的ADM699是一款简单的 WDT,它还可以监控一个电源。图 4 显示了它的实现。
图 4:ADM699 的设计非常简洁(由 Analog Devices 提供)。
现在一些微处理器对复位输入非常挑剔,只允许相对较快的转换速率和信号电平。开漏驱动只能通过使用非常低值的上拉电阻来满足这些要求,这会增加功耗。ADI 公司有多个组件,例如ADM6316,它们使用推挽输出来满足这些严格的要求。图 5 显示了该部件的框图。
图 5:ADM6316 具有推挽式驱动器(由 Analog Devices 提供)。
软件考虑
如果代码构造不正确,即使是最好的看门狗电路也只是一个很差的安全机制。唉,在大多数系统中,开发人员在没有考虑设计的情况下在整个代码中撒上看门狗的痒痒。
最重要的考虑是确保所有代码都正确运行,而不仅仅是其中的一部分。因此,永远不要在中断服务例程中放置 WDT 滴答声,也永远不要将 RTOS 任务用于此活动。如果主代码使中断甚至 RTOS 的调度程序崩溃,它可能会继续运行,因此看门狗永远不会超时。
在单线程设计中,使用类似状态机的架构。示例代码如图 6 所示。
图 6:处理非多任务 WDT 的代码。
这里的主循环首先将变量“state”设置为 0x5555。它调用 wdt_a() 检查值是否正确;如果没有,它会停止并且 WDT 重置系统。否则,“状态”中的值会通过添加偏移量来更改。请注意,看门狗没有被挠痒痒。
在循环结束时(我们已经执行了所有代码),再次调整“状态”并调用 wdt_b()。现在,如果“状态”没有正确地循环遍历它的所有更改——表明我们确实运行了整个循环——代码停止并且 CPU 被重置。否则看门狗会被触发并且“状态”设置为零。请注意,如果代码崩溃并进入 wdt_b(),“状态”将不正确并且会发生重置。
在多任务应用程序中,每个任务每次启动时都会在数据结构中增加一个与任务相关联的值。低优先级任务偶尔会检查数据结构并检查以确保数据合理。如果一个任务经常运行,数量会很大;相反,慢任务的数量会很少。如果一切正常,任务会触发 WDT,将值归零,然后返回。否则它会停止并启动重置。
如果存在代码无法处理或恢复的异常(例如,被零除或 malloc() 失败),请编写一个禁用中断和暂停的处理程序。看门狗将使系统恢复活力。
结论
看门狗定时器是防止代码崩溃的最后一道防线,因此必须精心设计和实施。如今,许多微控制器都包含非常复杂的 WDT,并且能够抵御异常运行的程序的欺骗。或者,使用外部 WDT;可能最安全的选择是支持窗口化。此外,请仔细构建代码,以使错误的软件不会落入 tickle 例程中,并防止计时器重置 CPU。
评论
查看更多