1. 功能安全架构设计的整体思路拆解
1.1 从“失效可运行”说起:为什么架构设计是功能安全的核心战场
做功能安全这几年,我越来越觉得,真正决定一个系统能不能过ASIL D、能不能在整车厂那边顺利验收的,不是某个单点技术有多先进,而是架构设计阶段有没有把“失效”这件事想透。功能安全的架构设计(六)这个系列走到第六篇,其实已经进入了深水区——前面几篇聊了概念阶段的HARA分析、安全目标定义、FSR技术安全需求分解,到了架构设计这一层,核心问题就变成了:当系统真的出问题了,它还能不能体面地活着?
这就是“失效可运行”(Fail-Operational)要解决的事。传统的Fail-Safe思路是出问题就切到安全状态,比如断电、停机、降级到最小功能集。但自动驾驶不一样,你没法在高速上跑到120km/h的时候突然说“对不起我失效了,请驾驶员接管”——如果驾驶员在睡觉呢?如果接管时间不够呢?所以自动驾驶的功能安全架构必须做到Fail-Operational,也就是部分失效后系统仍然能维持最低限度的安全运行,直到驾驶员接管或者车辆安全停车。
这个目标听起来简单,落到架构上就是一连串硬核决策:冗余怎么做、冗余到什么程度、切换逻辑怎么设计、故障检测覆盖率够不够、共因失效怎么防。每一个决策背后都是成本、复杂度、可靠性的三角博弈。我见过太多项目在架构阶段偷懒,结果到了集成测试阶段发现单点故障根本绕不过去,回头改架构的代价是前期投入的十倍不止。
1.2 冗余不是万能药:双冗余、三冗余的选型逻辑
热词里出现了“双冗余”,这确实是功能安全架构设计里最常被提到的方案。但我想先泼一盆冷水:冗余不是越多越好,关键看你的安全目标要求多高的容错能力。
先看一个基本的计算逻辑。假设单通道的失效率是λ,那么双通道冗余(假设完全独立)的失效率大约是λ²。如果λ是10⁻⁵/h,双冗余就是10⁻¹⁰/h,看起来提升巨大。但现实是,两个通道不可能完全独立——它们可能共享电源、共享时钟、共享通信总线,这些共享资源就是共因失效(Common Cause Failure)的温床。所以实际的双冗余系统,失效率往往在10⁻⁷到10⁻⁸/h之间,比理论值差了两三个数量级。
那三冗余呢?三取二(2oo3)架构的容错能力确实更强,单通道失效后系统仍然能正常运行,而且还能通过多数表决来识别哪个通道出了问题。但代价是什么?三个通道的硬件成本、三个通道的同步开销、三个通道的功耗和散热,还有更复杂的故障检测和隔离逻辑。我个人的经验是:对于ASIL D的自动驾驶系统,如果安全目标要求“单点故障后仍能维持运行”,双冗余是底线;如果要求“单点故障后仍能维持运行且能识别并隔离故障通道”,三冗余更稳妥。但具体选哪个,还要看你的失效模式分析(FMEA)结果和共因失效的量化评估。
还有一个容易被忽略的点:异构冗余 vs 同构冗余。同构冗余就是两个通道用同样的硬件、同样的软件,好处是开发成本低,坏处是共因失效风险高——同一个软件bug可能同时干掉两个通道。异构冗余则是用不同的硬件平台、不同的软件实现,甚至不同的算法,共因失效风险大大降低,但开发成本和验证复杂度直线上升。我参与过的一个项目,最终选择了“同构硬件+异构软件”的折中方案:两个通道用同样的芯片,但一个跑基于规则的控制算法,另一个跑基于学习的控制算法,这样既控制了硬件成本,又避免了软件层面的共因失效。
1.3 从HARA到架构:安全需求如何驱动设计决策
很多刚入行的朋友会问:架构设计到底从哪里开始?我的答案是:从HARA(危害分析与风险评估)的输出开始。HARA会给你每个危害事件的ASIL等级和安全目标,安全目标再分解成功能安全需求(FSR),FSR再分解成技术安全需求(TSR),TSR才是架构设计的直接输入。
举个例子。假设HARA分析发现“车辆在高速行驶中失去转向能力”这个危害事件的ASIL是D,安全目标是“防止车辆在非预期情况下失去转向能力”。这个安全目标分解到FSR层面可能是“系统应在转向系统单点故障时仍能提供至少50%的转向扭矩”。再分解到TSR层面就是“转向系统应采用双冗余架构,每个通道应能独立提供至少50%的转向扭矩,且故障检测时间应小于100ms”。
你看,到了TSR这一层,架构设计的约束条件已经非常明确了:冗余度、性能下限、故障检测时间。架构师要做的就是在这个约束空间里找到最优解。我见过一些团队跳过HARA直接拍脑袋定架构,结果要么冗余过度导致成本爆炸,要么冗余不足导致安全目标无法达成,最后返工重来。
2. 核心细节解析与实操要点
2.1 故障检测与切换逻辑:架构设计中最容易翻车的环节
冗余架构搭好了,不代表系统就安全了。真正决定系统安全性的,是故障检测的覆盖率和切换逻辑的可靠性。我见过太多项目,硬件冗余做得很漂亮,但故障检测覆盖率只有60%,剩下的40%故障根本检测不到,系统带着故障继续跑,最后出了事才知道。
故障检测的核心指标是诊断覆盖率(Diagnostic Coverage, DC)。ISO 26262对ASIL D的要求是DC ≥ 99%,也就是说99%的故障必须被检测到。这个数字听起来很吓人,但拆解下来就是:单点故障、潜伏故障、共因故障,每一类都要有对应的检测机制。
具体怎么做?我总结了几条实操经验:
- 电源监控:每个冗余通道的供电电压、电流都要独立监控,欠压、过压、纹波异常都要能检测到。我通常会用一颗独立的监控芯片,而不是依赖主控芯片的ADC,因为主控芯片本身也可能失效。
- 时钟监控:双通道的时钟频率偏差超过阈值就要报警。有些方案会用第三个独立时钟源来做交叉校验,成本不高但效果很好。
- 通信监控:CAN、以太网、FlexRay这些总线,要有CRC校验、超时监控、序列号检查。我特别想强调的是端到端保护(E2E Protection),ISO 26262 Part 6里有详细规定,但很多团队为了省事只做CRC,不做序列号和超时,结果通信故障检测覆盖率上不去。
- 计算监控:双通道的计算结果要交叉比对,偏差超过阈值就触发切换。这里有个坑:比对逻辑本身也可能失效,所以比对逻辑最好放在独立的监控通道里,而不是放在主计算通道里。
切换逻辑的设计更是一门艺术。理想情况下,故障检测到切换完成的时间应该尽可能短,但太短了容易误切换,太长了又来不及。我的经验值是:对于自动驾驶的转向和制动系统,故障检测到切换完成的时间应控制在100ms以内;对于动力系统,可以放宽到200ms。这个时间预算要分解到每个环节:传感器采样时间、故障检测算法执行时间、切换决策时间、执行器响应时间,每一环都要留够余量。
还有一个容易被忽略的点:切换后的状态确认。切换完成了不代表切换成功了,系统需要确认备用通道真的接管了,而且接管后的性能满足要求。我通常会设计一个“切换后验证窗口”,比如切换后50ms内持续监控备用通道的输出,如果输出异常就触发降级到安全状态。
2.2 共因失效分析:冗余架构的隐形杀手
共因失效(Common Cause Failure, CCF)是冗余架构最大的敌人。两个通道同时失效的概率虽然低,但一旦发生就是灾难性的。ISO 26262 Part 9里专门有一章讲CCF的分析方法,但很多团队只是走个形式,没有真正把CCF分析结果反馈到架构设计里。
CCF的来源主要有几类:
- 共享资源:电源、时钟、散热、通信总线、机械结构。两个通道共用同一个电源模块,电源模块失效两个通道一起挂。
- 环境应力:温度、湿度、振动、EMC。两个通道在同一块PCB上,局部过热可能同时影响两个通道。
- 设计缺陷:软件bug、硬件设计错误、制造工艺问题。同一个软件版本的两个通道,同一个bug可能同时触发。
- 人为因素:维护操作、装配错误、测试遗漏。
针对每一类CCF,架构设计都要有对应的缓解措施。我通常会用一张CCF检查表来逐项确认:
| CCF来源 | 缓解措施 | 验证方法 |
|---|---|---|
| 共享电源 | 独立电源模块,或电源模块冗余 | 故障注入测试 |
| 共享时钟 | 独立时钟源,或时钟交叉校验 | 频率偏差测试 |
| 共享通信 | 独立通信通道,或E2E保护 | 总线故障注入 |
| 环境应力 | 物理隔离,或降额设计 | 环境应力测试 |
| 设计缺陷 | 异构冗余,或独立验证 | 独立V&V |
| 人为因素 | 防错设计,或操作确认 | 过程审核 |
这张表看起来简单,但每一项都要有具体的量化指标和验证方法。比如“物理隔离”,隔离距离是多少?隔离材料是什么?隔离效果怎么验证?这些都要在架构设计文档里写清楚。
2.3 安全机制的设计原则:简单、独立、可验证
安全机制(Safety Mechanism)是功能安全架构的执行单元。我见过很多安全机制设计得过于复杂,结果验证的时候根本测不过来。我的原则是:安全机制要简单、独立、可验证。
简单,意味着安全机制的逻辑要尽可能简单,最好是“if-then”这种确定性逻辑,不要引入复杂的算法。我见过一个项目用机器学习来做故障检测,结果训练数据偏差导致误报率居高不下,最后不得不换回基于阈值的简单检测。
独立,意味着安全机制不能依赖被监控的功能本身。比如你不能用主控芯片的ADC去监控主控芯片的电源,因为主控芯片失效了ADC也失效了。安全机制应该有独立的传感器、独立的计算单元、独立的执行路径。
可验证,意味着安全机制本身也要能被测试和验证。ISO 26262要求安全机制本身也要有足够的诊断覆盖率,不能出现“监控者谁来监控”的问题。我通常会在架构设计阶段就定义好每个安全机制的验证方法,比如故障注入测试、边界测试、长时间运行测试。
3. 实操过程与核心环节实现
3.1 从需求到架构:一个双冗余转向系统的设计实例
光说理论太虚,我拿一个实际做过的双冗余转向系统来拆解。这个项目的安全目标是ASIL D,要求“单点故障后仍能提供至少50%的转向扭矩,故障检测时间小于100ms”。
第一步:定义架构边界。我们把转向系统分成三个域:传感域、计算域、执行域。传感域包括扭矩传感器、角度传感器、车速传感器;计算域包括主控芯片和监控芯片;执行域包括电机和驱动电路。
第二步:冗余分配。传感域采用双冗余:两套独立的扭矩传感器和角度传感器,信号通过不同的路径进入计算域。计算域采用双通道:主控芯片跑控制算法,监控芯片跑安全监控和故障检测。执行域采用双绕组电机:两个独立的绕组,分别由两个独立的驱动电路控制。
第三步:故障检测设计。每个传感器都有独立的信号调理电路,输出通过SPI和CAN两条总线进入计算域。主控芯片和监控芯片交叉比对传感器数据,偏差超过5%就触发故障计数。电机电流和位置反馈也做交叉比对,偏差超过10%触发切换。
第四步:切换逻辑设计。故障检测到切换的流程是这样的:监控芯片检测到故障后,通过独立的GPIO线向主控芯片发送切换请求;主控芯片收到请求后,在10ms内完成控制权移交;备用通道在20ms内接管执行器;切换后50ms内持续监控备用通道的输出,确认切换成功。
第五步:共因失效缓解。两个通道的电源来自不同的电源模块,时钟来自不同的晶振,通信走不同的总线。PCB布局上,两个通道的走线物理隔离,间距大于5mm。软件层面,主控芯片和监控芯片的代码由不同的团队独立开发,避免共因软件bug。
这个架构最终通过了ASIL D的认证,故障检测覆盖率做到了99.2%,切换时间实测在80ms左右。但过程中也踩了不少坑,后面会详细说。
3.2 关键参数计算:故障检测覆盖率和切换时间预算
故障检测覆盖率(DC)的计算不是拍脑袋,要有量化依据。ISO 26262 Part 5给出了DC的计算方法:DC = λdd / (λdd + λdu),其中λdd是可检测的危险失效速率,λdu是不可检测的危险失效速率。
假设我们的转向系统单通道的危险失效速率是10⁻⁶/h,其中可检测的占99%,不可检测的占1%,那么DC = 0.99。但如果考虑共因失效,两个通道同时失效的速率大约是10⁻⁹/h,这个值要单独计算并纳入整体安全分析。
切换时间预算的分解更考验经验。以100ms的总预算为例:
- 传感器采样和信号调理:10ms
- 故障检测算法执行:20ms
- 切换决策和通信:15ms
- 执行器响应:30ms
- 切换后验证:25ms
每一环都要留20%的余量,因为实际运行中会有各种抖动和延迟。我见过一个项目把预算卡得太死,结果高温环境下执行器响应变慢,切换时间超标,不得不重新设计。
3.3 实操现场记录:一次故障注入测试的完整过程
故障注入测试是验证功能安全架构的终极手段。我记录了一次典型的测试过程:
测试目标:验证主控芯片失效后,系统能否在100ms内切换到备用通道并维持50%的转向扭矩。
测试方法:用故障注入设备在主控芯片的电源线上注入电压跌落,模拟电源失效。
测试步骤:
- 系统正常运行,转向扭矩输出100%。
- 注入电压跌落,主控芯片在5ms内检测到欠压。
- 监控芯片在10ms内确认故障,发送切换请求。
- 主控芯片在15ms内完成控制权移交。
- 备用通道在35ms内接管执行器,转向扭矩输出50%。
- 切换后验证窗口内,备用通道输出稳定,切换成功。
测试结果:总切换时间42ms,满足100ms的要求。但测试中也发现了一个问题:切换瞬间转向扭矩有大约5%的抖动,虽然不影响安全,但驾驶员能感觉到。后来我们在切换逻辑里加了一个平滑过渡算法,抖动降到了1%以内。
4. 常见问题与排查技巧实录
4.1 故障检测误报和漏报:两个极端都要防
故障检测最怕两个极端:误报和漏报。误报会导致不必要的切换,影响可用性;漏报会导致故障未被发现,影响安全性。
误报的常见原因:
- 阈值设置过紧,正常波动被当成故障。
- 传感器噪声大,信号调理不到位。
- 环境应力(温度、EMC)导致信号漂移。
漏报的常见原因:
- 诊断覆盖率不足,某些故障模式没覆盖到。
- 故障检测算法执行周期太长,故障发生后没及时检测到。
- 共因失效导致检测机制本身失效。
我的排查技巧是:先做FMEA,把所有可能的故障模式列出来,然后逐一确认检测机制是否覆盖。对于误报,我会用实际路测数据来调整阈值,而不是拍脑袋定。对于漏报,我会用故障注入测试来验证,确保每个故障模式都能被检测到。
4.2 切换失败和切换抖动:切换逻辑的调试经验
切换失败通常有几个原因:
- 切换请求没送达:通信总线故障,或者GPIO线接触不良。
- 切换决策没执行:主控芯片死机,或者切换逻辑有bug。
- 备用通道没准备好:备用通道本身有故障,或者初始化没完成。
切换抖动通常是切换瞬间的控制不连续导致的。我的解决方案是:在切换逻辑里加入平滑过渡算法,让备用通道的输出逐渐接管,而不是瞬间切换。具体做法是,切换后的前50ms内,备用通道的输出从0逐渐增加到目标值,同时主控通道的输出从当前值逐渐减小到0。这样虽然切换时间稍微长一点,但驾驶体验好很多。
4.3 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决方案 |
|---|---|---|---|
| 故障检测误报 | 阈值过紧、噪声大 | 路测数据分析 | 调整阈值、增加滤波 |
| 故障检测漏报 | DC不足、周期太长 | 故障注入测试 | 增加检测机制、缩短周期 |
| 切换失败 | 通信故障、逻辑bug | 切换过程日志分析 | 冗余通信、逻辑审查 |
| 切换抖动 | 控制不连续 | 切换瞬间数据分析 | 平滑过渡算法 |
| 共因失效 | 共享资源、设计缺陷 | CCF分析、故障注入 | 独立资源、异构冗余 |
| 诊断覆盖率不达标 | 故障模式未覆盖 | FMEA审查 | 补充检测机制 |
4.4 独家避坑技巧:从实际项目中总结的经验
坑一:不要忽视潜伏故障。潜伏故障是指那些不会立即导致失效,但会降低系统安全裕度的故障。比如备用通道的电源模块性能下降,平时看不出来,但主通道失效时备用通道也撑不住。我的做法是:定期对备用通道做自检,确保它随时处于可用状态。
坑二:不要过度依赖软件监控。软件监控本身也可能失效,所以关键的安全机制最好有硬件备份。比如电源监控,我通常会用独立的监控芯片,而不是只靠软件ADC。
坑三:不要忽略切换后的状态确认。切换完成了不代表切换成功了,一定要有切换后验证机制。我见过一个项目切换后没有验证,结果备用通道其实没接管,系统带着故障继续跑,最后出了事。
坑四:不要低估共因失效的威力。两个通道用同一个供应商的芯片,同一个批次的芯片可能有相同的制造缺陷。我的做法是:关键芯片用不同供应商的,或者至少用不同批次的。
坑五:不要忘记人为因素。维护操作、装配错误、测试遗漏都可能导致共因失效。我的做法是:关键操作要有防错设计,比如连接器防插反、软件版本防错刷。
5. 架构设计的扩展思考:从功能安全到预期功能安全
功能安全解决的是“系统失效”导致的风险,但自动驾驶还有另一类风险:系统没失效,但功能不足或性能局限导致的风险。这就是预期功能安全(SOTIF)要解决的问题。
举个例子。功能安全关注的是“摄像头坏了怎么办”,SOTIF关注的是“摄像头没坏,但逆光条件下识别率下降怎么办”。这两个问题的架构设计思路完全不同:功能安全靠冗余和故障检测,SOTIF靠场景覆盖和性能边界定义。
我在实际项目中的体会是:功能安全和SOTIF的架构设计要协同考虑,不能割裂。比如冗余架构的设计,不仅要考虑故障后的切换,还要考虑切换后的性能是否满足SOTIF的要求。如果备用通道的性能本身就处于边界状态,切换过去也没用。
还有一个趋势是端到端自动驾驶对功能安全架构的冲击。传统的模块化架构,每个模块都有明确的安全需求和接口定义,功能安全设计相对容易。但端到端架构是一个黑盒,输入是传感器数据,输出是控制指令,中间的过程不可解释。这种情况下,功能安全架构怎么设计?我的看法是:端到端架构需要更强的运行时监控和形式化验证。你没法在架构层面保证端到端模型的安全性,但你可以通过运行时监控来检测异常输出,通过形式化验证来证明某些关键属性。
最后再分享一个小技巧:架构设计文档不要写得太抽象,要具体到每个安全机制的实现细节。我见过太多架构文档,满篇都是“应采用冗余设计”“应保证故障检测覆盖率”,但具体怎么做、参数是多少、怎么验证,一个字都没有。这种文档到了开发阶段就是废纸。我的做法是:架构文档里每个安全机制都要有明确的输入输出、参数定义、验证方法,最好配上时序图和状态机图,让开发人员一看就知道怎么实现。
这个系列写到第六篇,其实还有很多可以展开的地方,比如多核锁步架构的设计、安全岛的实现、OTA升级对功能安全的影响等等。后面有机会再慢慢聊。