3. 功能安全与信息安全概述
各位,安全机制不是堆砌功能,而是精准的防御。这一章我们聚焦三个核心武器:MPU、WDT 和 E2E。它们分别管空间、管时间、管逻辑。我做了这么多年功能安全,这三样东西几乎每天都在打交道。
3.1 内存保护(MPU)—— 给软件划地盘
MPU 说白了就是给每个任务或 OS 应用划定一个“活动范围”。你只能在你的地盘里读写,越界就触发异常。这在混合关键性系统里是底线。
核心原则: 隔离。ASIL-B 以上的软件模块,必须与 QM 软件物理隔离。
3.1.1 MPU 配置要点
- 区域划分: 每个安全相关任务独占一个 MPU 区域,包含代码段、数据段、堆栈。
- 权限控制: 代码段只读可执行,数据段读写不可执行,堆栈读写不可执行。
- 上下文切换: 每次任务切换时,MPU 配置必须同步更新。我见过一个项目,切换时忘了刷新 MPU,结果两个任务互相踩内存,查了三天。
我的习惯: 在 AUTOSAR 的 BSW 调度器里,我会在 Os_StartOS 之后立即做一次 MPU 完整性校验,确保所有区域配置与设计一致。
3.1.2 常见避坑
我曾经踩过的坑: 堆栈溢出检测。MPU 只能检测越界访问,但堆栈从高地址向低地址生长,如果只保护了堆栈底部,溢出到数据段是检测不到的。我后来强制在每个任务堆栈底部加一个 32 字节的“哨兵区”,并定期检查哨兵是否被改写。
3.2 时间保护(WDT)—— 别让程序死循环
时间保护的核心是看门狗。但功能安全里的 WDT 不是简单的“喂狗”,它要能检测出程序跑飞、死锁、甚至时钟故障。
3.2.1 两级看门狗架构
| 层级 | 位置 | 超时时间 | 触发后果 |
|---|---|---|---|
| 一级 WDT(内部) | MCU 内部独立定时器 | 10~100 ms | 触发中断,尝试软件恢复 |
| 二级 WDT(外部) | 外部独立看门狗芯片 | 100~1000 ms | 直接硬件复位 |
我建议一级 WDT 的喂狗点放在主循环的固定位置,二级 WDT 由安全关断路径直接控制。这样即使一级失效,二级还能兜底。
3.2.2 喂狗策略
- 分时喂狗: 每个安全任务执行完毕后,在固定窗口内喂狗。窗口太宽检测不到死锁,太窄容易误触发。
- 挑战-应答: 外部 WDT 芯片发送随机挑战码,MCU 必须在规定时间内返回正确应答。这能防止程序卡在某个固定循环里“假喂狗”。
关键指标: 喂狗窗口抖动应小于窗口宽度的 10%。我在项目中用逻辑分析仪抓过,发现中断优先级设置不当会导致喂狗延迟,后来把喂狗任务优先级提到最高才解决。
3.3 程序流监控(E2E)—— 数据在说话
E2E 保护的不是代码,而是数据。它确保从传感器到控制器再到执行器,数据在传输过程中没有被篡改、丢失或重复。
3.3.1 E2E 保护等级
| 等级 | 保护机制 | 适用场景 |
|---|---|---|
| E2E Profile 1 | CRC + 序列号 | 低速信号,如开关状态 |
| E2E Profile 2 | CRC + 序列号 + 超时监控 | 周期性信号,如车速 |
| E2E Profile 4 | CRC + 序列号 + 超时 + 数据ID | 跨 ECU 通信,如 CAN 报文 |
3.3.2 实现要点
- 发送端: 计算 CRC,递增序列号,打包发送。
- 接收端: 校验 CRC,检查序列号是否连续,检查是否超时。
- 错误处理: 连续 3 次 E2E 错误,进入安全状态。我习惯在错误计数里加一个“去抖”逻辑,防止偶发干扰导致误触发。
一个小技巧: 序列号不要从 0 开始。我见过一个项目,ECU 复位后序列号重置为 0,接收端误判为“重复报文”而丢弃。后来我改成从随机数开始,或者用上次保存的值加 1。
3.4 三种机制的协同
MPU、WDT、E2E 不是孤立的。它们共同构成一个纵深防御体系。下面这张图展示了它们的关系:
你看,E2E 在中间层,它保护的是应用层的数据流。MPU 和 WDT 在底层,一个管空间,一个管时间。硬件层在最下面兜底。这种分层设计,任何一层失效都不会导致系统完全失控。
我的经验: 在 AUTOSAR 架构里,我会把 E2E 的校验逻辑放在 RTE 层,这样应用层 SW-C 不需要关心通信细节。MPU 配置由 OS 管理,WDT 由 BSW 的 WdgM 模块统一调度。分工明确,各司其职。
3.5 本章小结
三种机制,三个维度:
- MPU: 空间隔离,防止越界访问。
- WDT: 时间监控,防止程序挂死。
- E2E: 数据完整性,防止通信错误。
它们不是可选项,而是功能安全的基本功。你想想看,如果连内存都保护不好,时间都控制不住,数据都信不过,那安全从何谈起?