ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

ISO 26262功能安全实战:从ASIL分解到故障注入测试

ISO 26262功能安全实战:从ASIL分解到故障注入测试

1. 功能安全到底管什么:ISO 26262不是"加个保险丝"那么简单

做汽车嵌入式开发的兄弟,应该都有过这种经历:硬件上电调试一切正常,跑几百小时不出错,结果一到整车环境就出幺蛾子——某个传感器偶发失效,控制器没来得及切换到安全状态,电机直接堵转。这种问题最头疼,因为你没法靠"多写几个if判断"来解决,它本质上是一个系统级的风险控制问题。ISO 26262就是干这个的:它给汽车电子电气系统定义了一套从概念到报废的完整安全开发框架,告诉你哪些风险必须管、管到什么程度、用什么方法证明你管住了。

我第一次接触ISO 26262时,第一反应是"又是一个文档驱动的东西"。真做完一个项目后才发现,这个标准最有价值的不是那一摞文档,而是它逼着你用工程化的方式回答三个问题:系统失效会造成什么后果?这个后果有多严重?你有没有足够的证据证明风险已经被控制住?说白了,功能安全不是加个保险丝、设个看门狗那么简单,它是把"安全"从一句口号拆解成可分析、可设计、可测试、可审计的工程活动。

这篇内容适合刚接手功能安全项目的嵌入式工程师、测试开发,以及想了解ISO 26262实际落地流程的团队管理者。我踩过的坑不少,下面尽量按实际项目的推进顺序来讲,从标准框架、开发流程、测试策略到审核实战,一次性把关键点捋清楚。

1.1 ISO 26262的核心思想:安全生命周期与安全案例

ISO 26262的全称是"Road vehicles - Functional safety",它脱胎于工业领域的IEC 61508,但针对汽车行业做了大量定制。整份标准现在包含十二个部分,覆盖管理、开发、生产、运维、退役全阶段,其中大家最关心的是第3~6部分(概念、系统、硬件、软件)和第10部分(指南)。

很多人刚接触时容易陷入细节出不来,我建议先抓住两个主线:

  • 安全生命周期:从item definition(项定义)开始,经过HARA(危害分析与风险评估)、安全目标制定、功能安全需求、技术安全需求、硬件/软件实现、集成测试、安全确认,一直到生产发布后的安全监控。这是一条贯穿始终的链条,每步都有明确输入和输出。
  • 安全案例(Safety Case):不是一张证书,而是一整套论证材料。它回答的问题是:凭什么说这个系统是功能安全的?凭据包括需求追溯表、设计说明、测试报告、分析记录、评审纪要。所有这些文档共同构成安全论证的证据链。

把这两条主线理解了,ISO 26262就不再是一堆条款,而是一条带检查点的流水线。做项目时你只需要回答:我现在处于哪个阶段,这个阶段要求哪些产出,产出是否满足下一阶段的输入要求。

1.2 ASIL:四个等级,风险有多大,要求就有多高

ASIL(Automotive Safety Integrity Level)是ISO 26262的"灵魂参数",分A、B、C、D四个等级,D级最高(比如安全气囊、线控转向这类系统),A级最低(比如车窗升降这类功能)。ASIL评级由三个维度决定:

维度含义等级
S(Severity)驾驶员或乘客受伤害的严重程度S0~S3
E(Exposure)车辆处于危险场景的概率E0~E4
C(Controllability)驾驶员或其他人员能避免伤害的能力C0~C3

三个维度组合,查HARA标准表得到ASIL等级。举个例子:一个驻车辅助系统,最坏情况是低速碰撞(S1),但在拥挤停车场触发频率很高(E4),驾驶员完全可以通过刹车避让(C2),最终评级往往在ASIL A或QM(Quality Management,即普通质量管理即可)。而一个高速下自动变道的辅助系统,如果误激活可能导致严重碰撞(S3),触发不可控(C3),驾驶员几乎无法干预(C3),那就直接奔着ASIL D去了。

这里有个关键点:ASIL等级不是一次定死就完事。需求分解时可以按"ASIL分解"规则拆给冗余路径(比如D分解成D+D,或者D拆成A+B的组合),但前提是分解后的每条路径都有足够的独立性。很多项目在这个环节翻车,就是因为分解后独立性论证不充分,审核时被挑战。

2. 安全生命周期怎么落地:从HARA到软硬件开发的完整链条

很多人都问过我一个问题:"ISO 26262到底从项目哪个阶段开始介入?"答案是:从你决定"这个功能要不要做"的时候就开始了。早介入的成本远低于后期补救,这是所有做功能安全项目的人的共识。你可能觉得在一堆需求还没冻结时就引入安全流程很麻烦,但事实是,越早做,后面返工越少。

2.1 概念阶段:HARA、安全目标与功能安全需求

概念阶段的核心产出是HARA报告和安全目标。HARA的做法是:先定义系统在整车层面的功能(比如"自适应巡航在跟车模式下自动加减速"),然后穷举可能的失效场景(比如"前车减速时本车未减速"、"传感器误判前车距离"),对每个场景做S/E/C评级,得到对应的ASIL和SG(Safety Goal,安全目标)。

安全目标通常是"避免XX事故"的顶层表述,比如"避免车辆在非预期情况下加速"(ASIL C)。它还需要配上安全状态和容错时间间隔(FTTI)。安全状态是指发生故障后系统进入的、可接受的状态(比如切断动力输出、发出警告并允许司机接管);容错时间间隔是指从故障发生到进入安全状态之间允许的最大时间。这个时间参数直接影响你后续的硬件诊断策略和软件响应机制设计,很多控制器设计超时,回头一查都是FTTI定义不合理。

从安全目标往下,就是功能安全需求(Functional Safety Requirements,FSR)。FSR必须明确对应到具体功能行为,比如"ACC系统在自检发现雷达数据异常时,应在200ms内退出跟车模式并提醒驾驶员接管"。每条FSR都带ASIL属性、对应安全目标编号、以及验证标准。FSR和系统需求之间必须建立双向追溯关系,追溯断裂是审核时最常见的不符合项。

2.2 系统级与软硬件级开发:需求是怎么一步步"变细"的

安全目标定了之后,进入系统层面。系统级设计要把FSR细化成技术安全需求(Technical Safety Requirements,TSR),TSR会描述具体的实现手段,比如"使用双通道看门狗监测MCU程序流"、"当供电电压低于阈值时在50ms内切换到备用电源并触发复位"。

TSR进一步拆到硬件和软件层面。硬件这边要定义硬件架构、诊断覆盖率、失效模式、随机硬件失效的度量指标(比如PMHF,Probabilistic Metric for random Hardware Failures);软件这边要按ISO 26262-6开发软件安全需求(Software Safety Requirements,SSR),设计软件架构、单元设计、代码实现,并做相应的验证。

这个阶段最容易犯的错是:把TSR直接当成软件需求丢给开发,中间缺了SSR这一层。开发人员不清楚每条需求背后的安全意图,代码实现出来根本对不上。我的习惯是,每个SSR都要带一段"安全意图描述",说明这条需求是为了覆盖哪个失效模式、如果不满足会发生什么。哪怕只是两三句话,对后面做测试用例和故障注入都有巨大帮助。

2.3 V模型开发流程:左边写需求,右边做验证

ISO 26262推荐的开发模型是经典的V模型。左边从上到下是概念阶段、系统设计、硬件设计、软件设计、单元实现;右边从下到上是单元测试、软件集成测试、系统集成测试、整车验证、安全确认。左右两边一一对应,每一层的验证活动都直接验证左侧对应层的设计输入。

这里有三个地方我想特别提醒:

  • 安全确认(Safety Validation)不是在开发结束后才开始。它的输入是安全目标和HARA场景,验证的是"在真实或接近真实的整车环境下,系统是否真的能避免危害"。这意味着你要在整车里做大量场景测试,包括坏路、电磁干扰、极端温度、驾驶员行为异常等。这些测试需要提前规划资源,不能等样车出来再看。
  • V模型的左右两侧不是时间上的先后,而是并行的。需求分析的时候,测试人员就要开始设计验证方案;软件开发的同时,测试人员就在写测试用例。等代码写完才开始想怎么测,根本来不及覆盖完所有安全需求。
  • 需求变更管理贯穿整个V模型。任何一条安全目标的变动,都可能引发下游所有文档和测试的联动更新。没有配置管理工具(比如专门的需求追溯平台),纯靠Excel维护追溯关系,项目后期一定是一团乱麻。

3. 核心细节实操:ASIL分解、安全机制、FMEA/FTA与诊断覆盖率

功能安全项目推进过程中,最考验功力的不是写文档,而是做分析。分析做得好,后面的设计缺陷能提前暴露;分析做得糙,问题全堆到测试阶段爆发。

3.1 ASIL分解:如何合理地"降级"

ASIL分解允许把一条安全需求(假设ASIL D)拆成两条独立需求(比如D(D)+D(D),或ASIL C(D)+ASIL A(D)),拆出来的每条子需求可以按较低或相同等级去实现。但前提是:两条实现路径必须足够独立,否则不能用分解来降低开发严苛度。

我在项目中常用的一种分解方式是这样的:

  • 主路径:传感器输入 + 主控制器 + 执行器,负责正常功能,软件按ASIL C(D)开发;
  • 监控路径:独立诊断通道 + 独立的参考计算逻辑 + 安全关断输出,软件按ASIL A(D)开发;
  • 主路径和控制路径共用同一个MCU时,必须通过空间隔离(不同核)、时间隔离(不同任务周期)、以及内存保护机制来论证独立性。

审核时被问得最多的问题就是:"你这两条路径共用电源吗?共用晶振吗?共用地线吗?共用中断控制器吗?"每共用一处,你都得说明为什么这不影响独立性论证。我踩过坑的是共用CAN收发器:主路径发故障报文,监控路径同时也要发安全状态报文,结果收发器坏了两个通道都失效。后来改成监控路径走独立CAN通道,才算真正把独立性立住。

3.2 安全机制与诊断覆盖率

安全机制是ISO 26262里用来"检测、控制、缓解"故障的具体手段。常见的有:程序流监控(看门狗)、内存校验(RAM自检、Flash CRC)、信号范围检查、冗余计算比较、通信CRC/序列号校验、供电电压监控、时钟监控等。

诊断覆盖率(Diagnostic Coverage,DC)描述的是某个安全机制能检测出多少比例的失效模式。ISO 26262把覆盖率分为低(<60%)、中(60%~90%)、高(90%~99%)和超高(>99%)。你要根据ASIL等级来选合适的安全机制组合,比如ASIL D的硬件随机失效指标达到PMHF < 10^-8/h(每小时失效率低于十亿分之一),光靠一种诊断手段是不够的,通常要多个层次互补。

我在设计中常用且实测有效的一组组合:

  • CPU自检:软件自检(如寄存器测试、RAM March算法测试 + 程序流监控)。RAM自检推荐用March C-或March CW,速度快且覆盖率高,但要注意有些MCU的RAM在运行中不能全局断电测试,得划分区间错峰测。
  • 信号路径:传感器信号合理性检查(范围、变化率、与另一信号交叉校验)+ 对执行器反馈的闭环监测。
  • 通信链路:报文CRC + 序列号 + 超时监测。光有CRC不够,攻击或失效场景下序列号能有效防报文重放/重复。
  • 供电时钟:电源电压窗口比较器(内部/外部比较器) + 时钟频率监测。之前做过一个项目,外部晶振在低电压起振受影响,频率漂移但电压检测没触发,后来加了频率监测才兜住。

每个安全机制都要写进FMEA/FTA分析,并且在实际测试中用故障注入证明它真的"在预期的时间内检测并处置故障"。只设计不验证,在审核时等于没做。

3.3 FMEA、FTA与故障注入:三种手段互相印证

FMEA(失效模式与影响分析)自下而上,从每个器件、每个软件模块的失效模式出发,分析它对上一层的影响,最后看是否有安全机制覆盖。FTA(故障树分析)自上而下,从顶层危害事件出发,逐层往下找所有可能的原因组合。这两种方法各有侧重,需要结合使用。

做FMEA时我习惯先建一个器件清单,然后逐个列出失效模式(短路、开路、漂移、卡滞等),再标出检测手段和覆盖率。给人感觉工作量很大,但这是后面所有设计决策的依据。

FTA则适合用来找组合原因。比如"安全气囊误爆"这个顶事件,底下可能是"加速度传感器误触发"和"冗余检测逻辑失效"同时发生。一画故障树你就明白哪些地方该加独立冗余,哪些地方需要故障注入重点验证。

故障注入本身也是验证安全机制有效性的核心手段。注入点包括:

  • 硬件层:引脚短路/开路、供电电压拉偏、时钟频率拉偏、内存位翻转(通过调试接口改写RAM)。
  • 软件层:修改传感器返回值、篡改校验和、模拟报文丢失/超时、堆栈溢出等。

我通常的做法是,每个安全机制至少设计一条"标准故障用例"和若干条"边界故障用例"。标准用例用来证明机制有效;边界用例用来验证容错时间间隔和临界值。例如,电源电压监控阈值是10.5V,我会注入10.6V和10.4V两种情况,确认只有低于阈值才触发安全状态。边界用例的效果是标准用例替代不了的,很多机制在临界点"时灵时不灵",问题就出在没做边界扫描。

4. 测试策略与验证实战:到底怎么证明"足够安全"

功能安全的测试和普通功能测试最大的区别在于:普通测试回答"功能对不对",安全测试回答"故障来临时系统是否按预期进入安全状态"。这两个问题的测试设计逻辑完全不同,这也是为什么很多从传统嵌入式测试转过来的同学,一开始写出的测试用例总被安全评审打回来。

4.1 测试分级:从单元级到整车级的验证矩阵

按V模型,测试活动通常分成五层:

层级验证对象典型方法覆盖重点
单元测试单个软件函数/模块白盒测试、语句/分支/MC/DC覆盖代码逻辑、边界条件、异常处理
软件集成测试模块间接口、任务调度接口测试、时序分析、压力测试数据流正确性、任务超时、资源竞争
系统集成测试软硬件联合(HIL)实时注入、总线仿真、负载测试软硬件接口、时序、诊断触发
整车验证实车环境场景测试、电磁兼容、环境耐久断路/短路/电源波动等实车故障
安全确认安全目标与HARA场景整车危险场景演练危害是否被有效避免

单元级和软件集成级是成本最低、发现问题最早的阶段,一定要做扎实。我见过不少团队把大量资源砸在整车阶段才做安全确认,结果发现是底层软件处理时序有问题,改起来牵一发动全身,成本高得吓人。

4.2 软件测试的四大金刚:静态分析、单元测试、背靠背测试、鲁棒性测试

软件层级的验证,ISO 26262明确推荐了若干方法,虽然标准没说"必须做哪些",但如果你的方法集里连一个动态测试都没有,审核时很难通过。我常用的组合是:

  • 静态代码分析。用工具检查MISRA C规则、数据流异常、未初始化变量、空指针解引用等。静态分析不是万能的,但它在早期能滤掉大部分低级问题。建议在每次代码提交时就跑增量分析,而不是到最后才全量跑,否则几千条告警根本看不过来。
  • 单元测试:每个软件安全需求至少对应一个单元测试用例。安全相关的函数建议做到语句覆盖100%、分支覆盖100%、MC/DC(修正条件判定覆盖)按ASIL等级尽量达到(ASIL D要求MC/DC,A/B级要求较低)。MC/DC难做,但它能暴露条件表达式里的逻辑漏洞。有的编译器支持自动生成MC/DC用例,但自动生成的用例往往只追求覆盖率数字,对安全语义的覆盖不足,我一般会在生成后人工补几条关键用例。
  • 背靠背测试(Back-to-back):一种需求层面的一致性测试方法,把同样的输入交给"参考模型"和实际代码,比较输出。我们经常用Simulink生成的参考代码作为基准,再用手工代码去做交叉验证。这种测试能抓到手写代码与设计模型之间的偏差,比单纯review代码更可靠。
  • 鲁棒性测试:输入非法数据、异常时序、错误状态跳转,确认系统不会进入危险状态。我常做的有:通信报文丢帧一半、传感器数据跳变、任务堆栈压到95%以上、看门狗喂狗时间抖动等。安全系统必须做到"再恶劣的输入也不至于失效",而不是"输入正常时表现良好"。

4.3 故障注入测试实例:一条"雷达信号超时"用例的完整拆解

下面用一个具体例子说明故障注入测试怎么做。假设我们的自适应巡航系统(ACC)有一条安全机制:当雷达数据超时超过150ms时,系统应在200ms内退出跟车控制,提醒驾驶员接管。

测试设计步骤如下:

  1. 在HIL(硬件在环)环境里,搭建雷达信号模拟器,正常发送目标车数据,确认ACC正常跟车。
  2. 启动故障场景:模拟器在t=0时刻停止发送雷达报文。此时必须记录:
    • 报文丢失被软件检测到的时间点(假设t=50ms时检测到报文超时);
    • 软件内状态切换时间点(t=80ms时进入"雷达失效"状态);
    • 执行器响应时间点(t=120ms时退出跟车并输出提醒)。
  3. 验证以上时间点是否满足"报文丢失后200ms内进入安全状态"。注意,这个200ms是从雷达失效开始算,不是从检测到失效开始算。很多团队只测检测时刻,忽略了从失效到检测之间的延迟,导致实际FTTI超差。
  4. 再补充边界测试:报文超时设为149ms、150ms、151ms,确认只有超过150ms才触发退出。
  5. 最后做异常测试:报文缺失和报文校验错误同时发生,确认不会被当作正常数据使用。

这套用例跑完后,出具测试报告时,把每个时间点的测量截图附上,并标注对应的需求追溯到哪条SSR和安全目标。审核人员看测试报告时,最关注的就是"需求是否追溯到用例、用例是否追溯到结果"。

4.4 工具链与确认:怎么让IDE编译器"辅助"你干活

ISO 26262对软件开发工具也有要求:凡是可能影响安全相关代码/验证结果的工具,都要做工具可信度评估(Tool Confidence Level,TCL)。TCL评估主要看两点:工具出错的概率,以及工具出错是否可能被其他手段发现。一个简单的判断是:如果一款编译器几乎不会出bug,且生成的代码通过的测试能覆盖它的潜在错误,那TCL等级就低,不需要额外措施;如果工具错误可能性大、且不容易被下游发现,就必须提高TCL等级,加额外的验证活动。

实操中,我对代码生成工具(如从模型生成C代码)通常采取"全量测试"策略来弥补工具置信度的不足:仿真模型生成的代码与实际代码做背靠背回归测试,测试用例尽量覆盖输入范围和分支边界。这里特别不要省时间,因为工具链升级带来的回归影响极大,我们曾因为更换编译器版本后出现浮点精度差异导致两个安全机制误触发,排查了两周。后来所有工具链变更都按变更管理流程走:走TCL评估 -> 跑全量回归 -> 审核确认 -> 发布。

5. 常见问题与排查技巧实录:踩过的坑、走过的弯路

做功能安全项目这几年,遇到的坑五花八门。我把典型的几类整理成速查表,都是实战里反复出现的,希望能帮你少走弯路。

5.1 问题速查表:从追溯断裂到安全状态定义不清

现象根因分析解决方案
审核时追溯表大量空缺初期未建立需求追踪机制,靠后期人工补项目启动即引入工具链,需求/设计/测试关联入库,变更时同步更新
安全状态定义模糊只写了"退出并提醒",没有明确执行器状态和退出条件安全状态必须精确到具体信号/设备状态,如"电机转矩指令为0,故障灯点亮,禁止恢复"
容错时间间隔超差只测了检测时间,漏掉检测前故障潜伏时间FTTI必须从故障发生时刻起算,分析每个检测点延迟并留出余量,设计时按80%余量规划
诊断覆盖率不足安全机制只覆盖单一失效模式,组合失效没有考虑FMEA中每个失效模式至少对应一个安全机制,组合失效靠FTA识别并补充机制
工具链更换后行为变化编译器/代码生成器版本差异引入未预期行为工具变更走TCL评估和全量回归,任何工具升级都不能"偷偷换"

5.2 审核前最容易被挑战的几个细节

独立于开发方做审核时,审核员最爱从以下几个角度切入:

  • 独立性:硬件和软件开发人员是否与验证/确认人员职责分离?如果不是,SM(Safety Manager)的独立监督是怎么做的?这一点在国内团队尤其容易栽,因为人手不足,常常开发自己测自己。对策是至少做到"不同人写测试计划和执行测试",哪怕同一个人负责开发和测试,也要用不同的评审记录来证明"他做了独立验证"。
  • 配置管理:安全相关的文档、代码、工具链是否纳入配置管理?出问题时能否追溯到当时用的版本?常见问题是"代码更新了但需求文档没同步"或"测试报告用的固件版本和发布版本不一样"。
  • 变更分析:每次变更是否重新评估了安全影响?哪怕只是改了一个日志打印,也要问:这个改动是否会影响诊断路径?是否影响时序?我建议建立"芝麻大小变更也登记"的制度,审核时宁愿变更记录多,也不能有遗漏。
  • 测试环境有效性:HIL台架是否校准过传感器和执行器?测试环境是否真实反映整车接口?审核员真的会看你的台架搭建图纸和校准记录。

5.3 实操心得:文档不是负担,而是团队共识的载体

最后一点,我想聊聊对"文档工作"的心态。很多人觉得ISO 26262就是无穷无尽的文档,占用了大量开发时间。做久了你会明白,那些文档其实是在倒逼团队把模糊的设计决策摆到台面上,让"我以为"变成"白纸黑字的共识"。

我现在的习惯是:每开一次设计评审会,一定当场记录决定事项,散会后24小时内更新到需求库和配置管理里。别等一周后再补,那时候细节早忘光了。文档写的不是"结果",而是"过程"。审核时能拿出完整的过程记录,比事后解释一百遍都管用。

如果你刚开始做功能安全项目,我建议先从一条ASIL B或C级别的功能链路开始,把整个生命周期走一遍,而不是试图一步到位覆盖全部系统。走完一条链路,你对安全目标、需求分解、设计验证、测试报告之间的咬合关系会有非常具体的感知,再扩展其他功能就顺很多。

最后再分享一个小技巧:找一个有经验的第三方,在你的开发中期做一次"预评审"。别等到正式审核才发现问题,预评审的整改成本通常只有正式评审的十分之一。我们当时预评审抓出来最大的问题,不是技术方案,而是几条安全需求与测试用例之间的追溯关系没说明白。这种问题技术上不难改,但正式审核时就是一条不符合项。提前让人挑刺,比事后补救划算太多了。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进