3.1 看门狗——体温中枢的三重监督
晚上11点,整车验证实验室里只剩下服务器风扇的嗡鸣。你的域控制器已经在台架上连续跑了72小时高低温循环,CANoe的trace窗口在黑暗中幽幽发光。突然,屏幕上那条你盯了三天的绿色数据流集体冻结,EPS(电动助力转向)报文消失了。你抓起示波器探头戳到CAN收发器的TXD引脚上,只有杂乱的逻辑电平:没有ACK应答,没有错误帧,什么都没有。
你心跳加速,但经验告诉你这不是硬件故障。把调试器挂上去,PC停在0x08004F32,死锁。10ms周期的转向控制任务(OsTask_Steering)在GetResource(Mutex_CAN_Tx)上阻塞,而这个互斥锁被100ms的诊断任务(OsTask_DiagLog)持有。诊断任务又在等DMA传输完成中断……可DMA早已完成,只是中断被更高优先级的任务误清了。两个任务互相等待,彼此冻结。优先级天花板协议没配好,Osek OS的困惑在此刻暴露无遗。
如果你开的是这辆车,方向盘的转角指令将卡在最后的那个1.7°左转上,在高速公路上,这意味着不到两秒你就会撞上护栏。但你读到的这份故障记录里没有一例转向冻结导致的实车事故。为什么?因为在诊断任务阻塞的那一瞬间,一颗完全独立于Cortex-R5的RC振荡器已经在安静地计数。它不知道什么互斥锁,不关心什么OCDS,它只有一个任务:数到1000个时钟周期,然后拉低/RESET引脚。现在它已经数到第970个。还有30微秒,一切都会被拉回安全状态。
你的ECU根本没死机。它只是“高烧“了。而看门狗,就是整辆车最底层的体温中枢。
看门狗的本质:独立于意识的生存回路
人体有一套精密的温度调节机制:下丘脑持续监测血液温度,当体温超过设定点(大约37°C),它会触发散热反应,扩张皮肤血管、启动汗腺。这套机制有几个关键特征:它完全独立于你的意识(你无法用意念改变体温设定点),它有自己的传感器(下丘脑中分布着温度敏感神经元),它在身体所有其他系统之前优先运行。
看门狗在ECU中扮演的角色几乎完全一致。它使用一个完全独立于CPU的硬件定时器,通常由专用的RC振荡器驱动,不与系统时钟共享任何逻辑。这个定时器从某个初始值开始倒计数,每次软件“喂狗“(触发看门狗)时会重置计数器。如果软件因为任何原因未能及时喂狗,不管是因为死锁、死循环、中断风暴、电压跌落导致的指令执行错误:计数器就会减到零,然后硬件复位电路会直接将MCU拉回POR(Power-On Reset)状态。
用英飞凌AURIX TC3xx系列的具体实现来说明:每个TC3xx MCU包含一个独立的SWD(Safety Watchdog)模块。它的时钟源是一个片上RC振荡器,标称频率100kHz,精度±15%(比系统PLL的±1%差远了,但看门狗不需要精度,它只需要独立)。SWD的超时周期通过16位重载寄存器配置,以100kHz时钟计算,最长时间窗口约为655ms。这意味着你的软件最迟每655ms就得喂一次狗。
/* AURIX TC3xx SWD 触发看门狗的关键寄存器操作 */
#define SWD_BASE_ADDR 0xF0036000UL
#define SWD_SRR_BYTE (*(volatile uint32*)(SWD_BASE_ADDR + 0x00UL))
void Wdg_17_Scu_Trigger(void)
{
/* 写入反向密码序列以服务看门狗 */
SWD_SRR_BYTE = 0x000000BCUL; /* 步骤1: 写入访问码1 */
SWD_SRR_BYTE = 0x00000043UL; /* 步骤2: 写入访问码2,重载定时器 */
}
注意这两个值0xBC和0x43,它们是反转的比特模式(0xBC=10111100, 0x43=01000011),彼此是比特取反的关系。这不是巧合。SWD硬件要求两个连续写入值必须互为按位取反,否则写入被忽略。这个设计保护了看门狗不会被内存中的随机比特翻转(比如由单粒子效应导致的RAM跳变)意外喂狗。一段野指针写穿了内存,恰好把某个变量写成0xBC。这已经够巧的了;连续两次精准写出0xBC和0x43,概率远低于ASIL D对单点故障度量的要求。
这就是看门狗的第一个核心原则:硬件隔离。它和CPU之间唯一的接口就是那几个触发寄存器。你的电机控制算法可以计算出任何荒谬的转矩指令,你的通信栈可以发出任何非法的CAN报文。但看门狗不会在乎这些。它只看一件事:你是否在时间窗口内触发了它。
WdgM的三个监督维度:不止于“活着“
看门狗不仅是底层硬件驱动(Wdg Driver),更关键的是上层看门狗管理器(WdgM,Watchdog Manager)。WdgM提供了三种不同维度的监督机制。如果你只用了最基础的Alive Supervision,那你只发挥了看门狗10%的能力。
2.1 Alive Supervision:你还活着吗?
Alive Supervision解决一个最基本的命题:被监督的软件实体(Supervised Entity,SE)是否还在运行?
实现方式很简单:在被监督任务的主循环或周期性处理中设置Checkpoint(检查点)。WdgM会统计每个监控周期内报告了至少多少个Checkpoint。如果Checkpoint数量在配置的期望范围内(ExpectedAliveIndications ± MinMargin/MaxMargin),任务就是健康的。
在VECTOR的配置中,Alive Supervision的ARXML参数如下:
<WDGM-ALIVE-SUPERVISION>
<WDGM-EXPECTED-ALIVE-INDICATIONS>3</WDGM-EXPECTED-ALIVE-INDICATIONS>
<WDGM-MIN-MARGIN>0</WDGM-MIN-MARGIN>
<WDGM-MAX-MARGIN>1</WDGM-MAX-MARGIN>
<WDGM-CHECKPOINT-REFS>
<WDGM-CHECKPOINT-REF>SE_Steering_CP_Input</WDGM-CHECKPOINT-REF>
<WDGM-CHECKPOINT-REF>SE_Steering_CP_Compute</WDGM-CHECKPOINT-REF>
<WDGM-CHECKPOINT-REF>SE_Steering_CP_Output</WDGM-CHECKPOINT-REF>
</WDGM-CHECKPOINT-REFS>
</WDGM-ALIVE-SUPERVISION>
这里配置的含义是:在每一个监督周期内,WdgM期望收到恰好3个或4个Alive Indication。如果只收到2个(小于MinMargin)或收到5个(大于MaxMargin),都视为异常。注意MaxMargin的意义:如果任务莫名其妙跑得比预期快(比如定时器配置错误、中断频率翻倍),它也会被检测到。Alive Supervision不仅检测“跑不起来“,也检测“跑得太快“。
但Alive Supervision有两个根本局限。第一,它无法检测执行流是否走完了正确路径。任务可以跳过所有关键计算,只触发Checkpoint然后空转,Alive Supervision不会判定失败。第二,它对时间不敏感,只要在监督周期结束之前凑够Checkpoint数量就行。一个5ms周期的控制算法,哪怕单次执行用了4.9ms(正常应该是1ms),只要它在监督周期内完成了规定次数,就不会被触发。
这就是为什么你需要Deadline Supervision。
2.2 Deadline Supervision:你按时完成了吗?
Deadline Supervision测量两个Checkpoint之间的时间间隔,并检查它是否在配置的最小/最大门限之内。
在AUTOSAR OS的背景下,时间测量使用的是OS Counter。这是操作系统维护的一个硬件定时器刻度计数器。每个Supervised Entity可以定义多组Transition(转换),每组Transition指定一个Start Checkpoint和一个End Checkpoint,以及它们之间允许的时间窗口。
任务周期 = 10ms
┌──────────────────────────────────────────────────┐
│ │
▼ ▼
CP_Start ────────────────► CP_Finish
(t=0) 执行时间 (t≤5ms)
Deadline: 5000us
在VECTOR DaVinci配置中,Deadline Supervision的核心参数:
<WDGM-DEADLINE-SUPERVISION>
<WDGM-TRANSITIONS>
<WDGM-TRANSITION>
<WDGM-TRANSITION-ID>1</WDGM-TRANSITION-ID>
<WDGM-TRANSITION-SOURCE-REF>SE_Steering_CP_Start</WDGM-TRANSITION-SOURCE-REF>
<WDGM-TRANSITION-DESTINATION-REF>SE_Steering_CP_Finish</WDGM-TRANSITION-DESTINATION-REF>
<WDGM-DEADLINE-MIN unit="us">100</WDGM-DEADLINE-MIN>
<WDGM-DEADLINE-MAX unit="us">5000</WDGM-DEADLINE-MAX>
</WDGM-TRANSITION>
</WDGM-TRANSITIONS>
</WDGM-DEADLINE-SUPERVISION>
这个配置要求CP_Start到CP_Finish之间的时间必须在100μs到5000μs之间。如果你看到100μs的最小值,可能会觉得奇怪,为什么要求执行时间不能太短?因为当一个任务在100μs内就从CP_Start跑到CP_Finish,极有可能是执行路径被中断打乱了,或者某些关键计算被跳过。Deadline Supervision的最小门限保护的是“程序不能走捷径“。
在AUTOSAR内部,Deadline Supervision的实现依赖OS提供的GetCounterValue()接口。WdgM在CP_Start触发时记录当前的Counter值,在CP_Finish触发时再次读取Counter值,用差值(经过Tick到时间的转换)与配置的门限比较。
时间测量过程(以AURIX STM定时器作为OS Counter):
CP_Start: WdgM 读取 OsCounter = 0x0004A38F (311,183 ticks)
CP_Finish: WdgM 读取 OsCounter = 0x0004A5C7 (311,751 ticks)
差值: 568 ticks
假定 STM 频率 = 100MHz → 568 * 10ns = 5680ns = 5.68μs
判断: 5.68μs 在 [100μs, 5000μs] 窗口内 → OK
2.3 Logical Supervision:你的逻辑流程正确吗?
Alive和Deadline都没有回答一个问题:程序执行了正确的路径吗?
Logical Supervision(逻辑监督)引入了程序流图的概念。一个Supervised Entity在运行时会经过一系列Checkpoint,这些Checkpoint之间的转换关系构成一个有向图。WdgM维护一个Transition Table(转换表),定义了所有合法的转换。任何不在转换表中的转换发生,立即触发监督失败。
程序流程图示例:转向控制任务
┌─────────┐
│Idle │ ◄──────────────┐
└────┬─────┘ │
│ │
▼ │
┌─────────┐ │
│CP_Start │ (1) │
└────┬─────┘ │
│ │
▼ │
┌─────────┐ 正常路径 │
│CP_InpRd │ (2) ────────────┤
└────┬─────┘ │
│ │
▼ │
┌─────────┐ 数据异常 │
│CP_Comp │ (3) ────────────┘
└────┬─────┘
│
▼
┌─────────┐
│CP_OutWr │ (4)
└────┬─────┘
│
▼
┌─────────┐
│CP_End │ (5)
└─────────┘
对应的Transition Table:
| 源Checkpoint | 目标Checkpoint | Transition ID |
|---|---|---|
| CP_Start | CP_InpRd | 1 |
| CP_InpRd | CP_Comp | 2 |
| CP_InpRd | CP_Start | 3(数据异常,回退重读) |
| CP_Comp | CP_OutWr | 4 |
| CP_OutWr | CP_End | 5 |
| CP_End | CP_Start | 6(下个周期) |
任何不在上表中的转换(比如CP_Start→CP_OutWr,跳过了输入读取和计算),都会触发WdgM的Logical Supervision失败。这意味着即使你的任务在Alive和Deadline层面都是“正常“的,CPU在执行代码、时间也在窗口内,只要执行路径偏离了预期,WdgM就会抓住你。
结合这三个维度,WdgM形成了对软件的多层次立体监控:Alive确认任务还在跑,Deadline确认它没超时,Logical确认它没走错路。这三者合在一起,覆盖了一个软件组件几乎所有可以量化的健康指标。
硬件看门狗的底层真相
当你用C代码调用Wdg_17_Scu_Trigger()时,你以为自己在喂狗。真正发生的事情比你想象的复杂得多。
AURIX TC3xx的Safety Watchdog (SWD)内部结构如下:
┌─────────────────────────────────────────┐
100kHz RC OSC ──► 16位递减计数器 │
│ │
fSYS 禁用信号 ──► SWD 不会因系统时钟消失而失效 │
│ │
密码检查器 ◄──── SWD_SRR 寄存器(触发接口) │
│ │
│ 错误密码序列 → 超时直接触发复位 │
│ │
▼ │
┌──────────────┐ │
│ 窗口比较器 │ 开窗时间判定 │
│ │ │
│ 太早喂狗 ──► 复位 │
│ 太晚喂狗 ──► 复位 │
│ 窗口内喂狗─► 重载计数器 │
└──────────────┘ │
└─────────────────────────────────────────┘
看门狗有几种工作模式:
Timeout Mode(超时模式):最简单的模式。只要在计数器减到零之前喂狗就行。这种模式最常见,也最容易配置。
Window Watchdog(窗口看门狗):比超时模式严格得多。喂狗必须在指定的时间窗口内进行,既不能太早也不能太晚。想象一下:一个10ms周期的任务,你预期它应该在8-9ms时喂狗。如果它在3ms时喂狗(太早了,说明执行异常快,可能跳过了某些计算),窗口看门狗会拒绝并触发复位。如果它在11ms时喂狗(太晚了,说明任务执行超时),同样触发复位。
窗口看门狗时序图:
服务请求
允许 │ 禁止 │ 允许 │ 禁止
│ │ │
─────────┼─────────┼─────────────────────┼────────► 时间
0ms 2ms 4ms 10ms 12ms
│ │ │
太早触发 │ 太晚触发
→ 复位 │ → 复位
│
正确触发区间
为什么需要窗口?因为一个在3ms就完成所有工作的10ms任务,几乎一定跳过了某些东西,可能是传感器读取被跳过,可能是故障检测分支被绕过。窗口看门狗能够捕获这类“任务执行了但没做对“的故障。
Fail-Safe Mode(故障安全模式):当系统进入安全状态后,看门狗可以保持在一个“已触发但不复位“的状态,允许系统在受控条件下进入安全状态而非粗暴复位。
这几种模式对应着车载控制器的不同运行阶段:
- 正常行驶:窗口模式,严格监督
- 初始化阶段:超时模式,允许较长的启动时间
- 安全状态:故障安全模式,保持安全状态等待驾驶员接管
WdgM的全局状态与故障传播
WdgM维护一个全局状态机,汇聚所有被监督实体的局部状态:
WDGM_GLOBAL_STATUS_OK — 所有SE正常
WDGM_GLOBAL_STATUS_FAILED — 至少一个SE失败
WDGM_GLOBAL_STATUS_EXPIRED — 看门狗过期,准备复位
WDGM_GLOBAL_STATUS_STOPPED — 看门狗已停止(如调试模式)
WDGM_GLOBAL_STATUS_DEACTIVATED — 看门狗已停用(如休眠状态)
每个Supervised Entity也有自己的局部状态(WDGM_LOCAL_STATUS_OK/FAILED/EXPIRED/STOPPED)。这些状态通过回调函数传递给DEM(Diagnostic Event Manager),用于故障记录和DTC存储。
关键的故障传播路径:
SE_Steering → local FAILED
│
▼
WdgM Global Status → WDGM_GLOBAL_STATUS_FAILED
│
├──► DEM: 记录 DTC_Steering_WdgM_Failure
│
├──► EcuM: 请求受控关闭或复位
│
├──► RTE Mode Switch: 切换到降级模式
│
└──► WDGM_IMMEDIATE_RESET: 如果配置,直接复位
WDGM_IMMEDIATE_RESET是一个关键的配置选项。当它被启用且看门狗到期时,WdgM跳过所有Shutdown Hook,直接复位。在ASIL D系统中,通常为最高安全等级的SE启用此选项,因为在高安全完整性等级下,任何试图“优雅关闭“的代码本身就可能已经损坏。当你已经确定一个ASIL D任务失败了,你最不应该做的事情就是把CPU交给另一个可能同样损坏的ASIL D恢复逻辑。
RTE Mode Switch集成是另一个重要特性。当某个SE失败时,WdgM可以触发AUTOSAR模式机切换到降级模式。例如,如果EPS主控制SE失败,Mode Switch可以将转向系统切换到机械直连模式(或液压备份模式),同时通过组合仪表点亮警告灯。这种模式依赖监督使得系统可以在不触发整车复位的情况下进入降级安全状态,对于转向和制动系统尤其重要。
看门狗本质上是时序约束担保机制。它不检查逻辑正确性,只检查时间维度上的约束是否被满足。在嵌入式实时控制系统中,任何软件逻辑错误最终都会体现为时序异常:死锁表现为不触发Checkpoint,死循环表现为Deadline超时,代码跳转错误表现为Logical Supervision的非法转换。时序是所有故障的最终公共路径。
但它也有盲区:不改变时序的逻辑错误(例如算成了相反方向),这种错误看门狗完全看不到。这需要E2E保护(3.5节)和传感器冗余(3.2节)。
配置看门狗的核心挑战在于:在“过早触发导致误复位“和“过晚触发导致漏检“之间找到平衡。这个平衡点需要基于WCET分析、调度分析和极限工况测试来确定。
本篇小结
- 看门狗是独立于CPU的硬件定时器,使用专用RC振荡器,不受系统时钟影响,是芯片最底层的生存回路。
- WdgM提供三层监督:Alive Supervision(确认任务在运行)、Deadline Supervision(确认执行时间在窗口内)、Logical Supervision(确认执行路径合法)。
- 窗口看门狗(Window Watchdog)既能检测“太晚喂狗“也能检测“太早喂狗“,防止任务跳过关键计算后提前触发。
- 喂狗密码序列(0xBC/0x43互为比特取反)防止内存随机翻转意外触发喂狗,满足ASIL D单点故障度量要求。
- WdgM全局状态机将故障逐级传播至DEM(DTC记录)、EcuM(复位请求)和RTE Mode Switch(降级模式),高安全等级下可直接硬件复位。
【下集预告】: 看门狗管的是“程序还在运行吗“,但它管不了“程序算得对不对“。如果CPU执行了错误的计算路径但没死机,看门狗不会触发——它只看喂狗时间,不看计算结果。锁步核填补了这个盲区:两颗相同的Cortex-R5做同一道题,逐拍比对每一个时钟周期的输出。如果一颗CPU的ALU算出了0x0000A43F,另一颗算出0x0000A42F,CCU比较器在5纳秒内就能揪出那一位的翻转。