Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

2.11 免于干扰(FFI)——血脑屏障的工程实现

场景

你的ECU上跑着两件事。

第一件事是一个Q-Classified(QM级,无安全要求)的信息娱乐系统任务。它渲染导航地图、播放蓝牙音乐、偶尔因为一个野指针错误把一块随机数据写到SRAM的某个地址里。你甚至不知道这个Bug存在:信息娱乐功能测试从来不会覆盖到内存越界,因为只要不Crash,谁会在意呢?

第二件事是一个ASIL-D的电动助力转向控制任务。它读取方向盘扭矩传感器、计算助力曲线、驱动三相BLDC电机。如果这个任务的计算结果被篡改哪怕一个字节:控制命令中的一个符号位反转:转向方向可能从“左转“变成“右转“。

它们运行在同一个MCU上,共享同一块SRAM,由同一个RTOS调度。

那么一个问题像针一样扎进你的脊背:信息娱乐任务的那个野指针Bug,能不能污染到转向控制任务的数据?

如果你回答“有可能“,那么你的系统是D级吗?不是:它根本不是一个ASIL系统,因为QM任务摧毁了ASIL任务的完整性。 如果你回答“不可能,我有免于干扰“,那你是怎么保证的?

ISO 26262 Part 6 Annex D给出了这道题的答案,并且它是用一种你无法讨价还价的方式给出的。

免于干扰(FFI)的定义

ISO 26262对免于干扰(Freedom From Interference, FFI)的定义是:一个要素的失效不会导致另一个要素违反安全要求。 关键词是“要素之间“。它不是保护一个软件模块免受自身缺陷的伤害,而是保护一个软件模块免受其他软件模块(尤其是低ASIL或无ASIL的模块)的伤害。

ISO 26262-6 Annex D把软件要素之间的干扰归纳为三大类别:

类别一:时序与执行(Timing and Execution)

这是关于“时间“的干扰。一个有问题的任务可以通过以下方式破坏安全关键任务的实时性:

  • 阻塞(Blocking):低优先级的QM任务持有一个互斥锁或自旋锁,导致高优先级的ASIL任务无法执行。
  • 死锁(Deadlock):两个任务互相等待对方持有的资源,导致系统停滞。
  • 活锁(Livelock):两个任务反复改变状态但都没有实质进展,比如两个任务在争抢总线访问权时不断冲突重试。
  • 执行时间分配错误(Incorrect Allocation of Execution Time):一个无安全要求的任务意外进入了死循环或有异常的长时间执行,耗尽了CPU时间预算,导致安全任务被延迟或跳过。
  • 同步错误(Incorrect Synchronization):两个任务之间的同步信号(信号量、事件标志)被错误地触发或丢失,导致安全任务的执行流程被打乱。

类别二:内存(Memory)

这是关于“空间“的干扰。一个任务可以:通过合法的内存访问或者Bug导致的非法访问:破坏另一个任务的内存空间:

  • 内容损坏(Corruption of Content):QM任务通过野指针或数组越界写入,覆写了ASIL任务的堆栈、全局变量或堆数据。
  • 读写一致性问题(Read/Write Inconsistency):QM任务正在写共享数据的中途,ASIL任务读取了不完整的数据:或者反过来。
  • 数据陈旧(Stale Data):共享数据的更新周期被QM任务异常拉长,ASIL任务使用了过期的值。
  • 栈溢出(Stack Overflow):一个任务的栈使用量超出分配边界,溢出部分侵入了相邻内存区域。而那个区域可能恰好属于另一个ASIL任务。
  • 未授权的内存访问(Unauthorized Access):QM任务绕过操作系统,直接通过绝对地址访问属于另一个任务的内存或外设寄存器。

类别三:信息交换(Exchange of Information)

这是关于“通信“的干扰。两个任务通过共享内存、消息队列、IPC等方式交换数据时,会产生以下类型的错误:ISO 26262-6 Annex D.2.3列出了完整的八种:

  1. 重复(Repetition of Information):同一条消息被发送了两次,接收方执行了两次相同的指令。
  2. 丢失(Loss of Information):消息在传输过程中被覆盖或丢弃,ASIL任务没收到关键数据。
  3. 延迟(Delay of Information):消息到达时间晚于设计预期,超过了FTTI允许的范围。
  4. 插入(Insertion of Information):一个不应该出现在该通道中的消息被插入了。
  5. 伪装(Masquerade or Incorrect Addressing of Information):消息被错误地标记为另一个发送者的身份,接收方信任了一个不可信的消息源。
  6. 错误序列(Incorrect Sequence of Information):消息的正确内容按错误的顺序到达:例如“开窗再关窗“变成了“关窗再开窗“。
  7. 信息损坏(Corruption of Information):消息内容在传输或存储过程中被篡改,但CRC/E2E保护未能检测到。
  8. 不对称信息(Asymmetric Information):两个接收方从同一个发送方收到了不同的数据:可能是由于中间缓存的不一致刷新。

在进一步展开实现方案之前,ISO 26262-6 Annex D还有一个你不可忽视的“硬“要求:

对ASIL D的安全要求,如果软件分区依赖于硬件支持来实现免于干扰,则必须使用带有MPU(内存保护单元)或同等级别硬件保护机制的微控制器。

换言之,你不能仅凭“代码审查确保没有Bug的QM代码访问安全内存“来实现ASIL D的FFI。你需要硬件隔离

免疫系统的隐喻:血脑屏障

在进入工程实现之前,我们先建立最核心的类比。

人体有两种“通道“。一种是开放的:血液在全身流动,每个器官都能获取养分、排除废物。另一种是严防死守的:大脑和脊髓周围有一层血脑屏障(Blood-Brain Barrier, BBB)

血脑屏障不是“完全隔绝大脑和血液“,那是死路一条。血脑屏障做的是:只允许经过严格筛选的分子通过:氧气可以,葡萄糖需要转运蛋白,血清中的大部分蛋白质和大分子代谢废物、病原体、毒素一律拒之门外。

这是活的、有选择性的隔离。它同时解决了三个问题:

  • 时序问题:血液中的肾上腺素飙升不会立即改变神经元放电:BBB缓冲了化学信号的传递速率。
  • 内存问题:炎症因子可以充斥全身血液,但不能进入大脑:BBB实施了“访问控制“。
  • 通信问题:大脑可以和身体通信(通过神经递质和激素),但只是规定的几个通道和消息类型。而不是“血液里的任何化学信号都在脑细胞间广播“。

这就是免于干扰的生物学实现。 而ISO 26262-6 Annex D要求你在MCU上实现一个工程版本的血脑屏障。

工程实现:MPU与软件分区

分区(Partitioning)

分区是将不同的软件功能划分到独立的、互不干扰的执行环境中。在AUTOSAR架构中,分区以OS-Application的形式实现。每个OS-Application是一个独立的可调度实体集合,拥有自己的任务、中断服务例程和资源。

分区的第一步是ASIL分离:所有ASIL-D的任务、ISR属于一个分区;ASIL-B的属于另一个分区;QM的全部扔到第三个分区。它们之间的交互通道被严格限制:类似于大脑只通过特定的神经通路与身体通信。

ISO 26262-6第7.4.11节还有一个关键结论:OS本身必须按照所有分区中最高的ASIL等级来开发。 换句话说,如果你的系统里有一个ASIL-D的分区,即使还有一堆QM任务,你的OS必须是ASIL-D的。

这是有道理的。OS是所有分区的仲裁者。它管理上下文切换、中断分发、资源分配。如果OS本身有缺陷,“免于干扰“的所有上层机制都可能被OS绕过。这就好比血脑屏障本身如果漏了,脑细胞再健康也没用。

MPU配置

MPU(Memory Protection Unit)是ARM Cortex-R和Cortex-M系列MCU上的标准外设。它允许你定义多个内存区域,为每个区域指定访问权限(读/写/执行)和访问特权级别(特权模式/用户模式)。

在实际工程配置中,你为每个OS-Application定义它“合法拥有“的内存范围:

  • ASIL-D转向分区:拥有0x2000_0000到0x2000_7FFF的SRAM区域(32KB),特权模式可读写,用户模式只读。
  • ASIL-B诊断分区:拥有0x2000_8000到0x2000_BFFF(16KB),访问规则相同。
  • QM信息娱乐分区:拥有0x2000_C000到0x2000_FFFF(16KB)。

任何分区中的任何代码尝试访问不属于它的内存地址,MPU立刻触发MemManage异常(对于ARM架构),硬件层面的保护反应在纳秒级:不需要软件检测,不需要看门狗超时。

这意味着即使QM分区的代码中跑了一个数组越界的“疯狂指针“,它最多只能摧毁QM分区自己:MPU在硬件层面拦截了所有跨界访问。

时序保护

在某些支持Temporal Protection的RTOS(如AUTOSAR OS)中,你可以为每个任务配置:

  • 执行时间预算(Execution Budget):任务单次运行的最大CPU时间
  • 锁定时间预算(Lock Budget):任务持有所有锁的总最长时间
  • 到达率(Arrival Rate):任务被激活的最小间隔

如果一个QM任务试图超出它的执行时间预算,OS的定时器中断触发时可以看到“这个任务还没退出“,然后时钟保护机制可以直接挂起或终止这个任务,把CPU还给调度器。

这就是防止时序干扰的机制:不是靠QM代码自觉,而是靠OS拿着定时器强行介入。

共享资源管理

分区之间如果需要通信怎么办?不能“禁止一切通信“:就像血脑屏障也不能禁止葡萄糖进入大脑。你需要的是受控的、被验证的、受保护的通信通道

AUTOSAR提供IOC(Inter-OS-Application Communicator)机制。两个分区通过专门配置的共享内存区域交换数据,这个区域的访问由OS控制:写入和读取是原子的(或受中断锁保护),数据格式在编译时确定,并且可以附加E2E保护(端到端保护,CRC + 序列号 + 超时检测)来覆盖那八种通信故障模式。

关键区别:不是让两个任务直接“看到“对方的内存,而是通过一个第三方(OS/IOC)作为中介。 这个中介自己是被验证过的(ASIL-D OS),所以你可以信任它不会传错数据。

软件分区对ASIL D的硬件要求

ISO 26262-6 Annex D 明确:对于ASIL D而言,如果软件分区的FFI依赖硬件支持,那么硬件必须提供MPU或等效机制。

这是一个“硬“门槛。如果你的MCU没有MPU(比如一些低成本的Cortex-M0器件),那你就不能在同一个MCU上混合运行ASIL D任务和QM任务:不是“不推荐“,是“标准不允许你用纯软件手段来达到ASIL D的免于干扰水平“。你需要要么换一个有MPU的MCU,要么把ASIL D功能放到一个独立的MCU上:物理隔离。

这也解释了为什么在真实的量产项目中,很多Tier-1会为ASIL-D转向功能单独部署一颗MCU,而不是跟信息娱乐系统跑在同一颗SoC上:即使SoC理论上支持MPU。工程实践中有太多不确定性,物理隔离是最彻底的FFI。

本篇小结

  1. 免于干扰(FFI)是ASIL分解和软件混合关键度部署的前提条件
  2. ISO 26262-6 Annex D将软件间干扰归纳为三大类别:时序与执行、内存、信息交换
  3. ASIL D系统的FFI依赖于硬件MPU、OS级的分区和时序保护、受控的IOC通信通道
  4. OS自身必须按所有分区中最高的ASIL等级开发

【下集预告】: 血脑屏障挡住了跨分区的干扰,但每个分区内部的代码呢?下一节从一段50行的“正常C“代码开始——用了malloc、用了goto、有全局指针——然后逐行对照ISO 26262-6 Table 6,发现它踩了十项中的八项红线。MISRA C要做的不是把C语言变得更安全,而是砍掉所有“行为不确定“的部分,让每一行代码都可被静态分析、可被证明正确。