您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 
 订阅
两万字阐述汽车视觉功能安全

 
作者:孙鲁毅
   次浏览      
 2022-8-26
 
编辑推荐:
本文主要探讨如何用功能安全的思想去指导系统开发,减少和避免系统的设计缺陷,改善项目开发的效率,降低开发成本,尝试找到可操作可重用的方法(Best Practice)。。希望对你的学习有帮助。
本文来自于知乎,由火龙果软件Linda编辑、推荐。

1、前言

芯片之争,在中国汽车市场从来没有像现在这样火热。各大车厂纷纷都在规划和展示自己的辅助驾驶、自动驾驶等计划。新造车势力更加着力于宣传更加智能更加安全的概念,由此带动了产业链更新换代的浪潮。在领先企业特别是Tesla,Nvidia,Intel等的引领下,大家看到了汽车市场智能化的巨大潜力和商机,国内外芯片企业都纷纷推出针对汽车市场智能驾驶的AI芯片。

当这些芯片用于ADAS和自动驾驶的时候,“功能安全等级”, “车规”,“AEC-Q100”, “ISO26262”,“ASIL”等关键词反复被提起。对于“功能安全”概念的介绍和解读的专业文章很多,相关的功能安全评级公司也有很多相关的培训。我们通过参与相关培训可以了解到ISO26262的功能安全要求侧重使用量化方法和指标对于硬件元器件的失效分析,以及针对于这些硬件失效应该如何进行系统设计以提高系统可靠性。

汽车功能安全的开发可以遵循严格的流程,采用标准的工具,方法,开发硬件,软件,并且按照功能安全的要求进行测试。并把流程,文档,测试结果交给专业的功能安全认证机构去审阅,评估和认证。本文主要探讨如何用功能安全的思想去指导系统开发,减少和避免系统的设计缺陷,改善项目开发的效率,降低开发成本,尝试找到可操作可重用的方法(Best Practice)。我在这里把这些叫做“功能安全实践”。其中对功能安全的解读纯属个人观点,难免有错误和遗漏,欢迎行业专家和有相关经验的朋友交流指正。

2、功能安全方法的基本概念

2.1 专业名词浅析

故障(FAULT),错误(ERROR), 失效(FAILURE), 缺陷(DEFECT)这几个词的含义对于不了解功能安全的可能并不容易分清,但这些并不是ISO26262首创的,而是可靠性工程行业的一些基本概念,也是功能安全标准的基础。这些在ISO26262-1文档有很好的描述,我也做下简单的解读:

 

从上述列表分析来看,单点故障(SPF)和残余故障(RF)是最为致命的故障。不容易被发现和觉察的潜伏故障(LF)也会留下隐患。

2.2 ISO26262标准和方法

对于ISO26262的流程,提出了著名的“V模型“,几乎是汽车行业人所共知的这个模型:

图:ISO26262 V模型

汽车功能安全行业标准里的ISO 26262-2018版本是目前最新的版本,共有12个章节,对于功能安全的管理,概念,硬件,软件,系统,方法,制造等方面都提出了很有价值的参考意见。其中和研发工程师最为紧密相关的是:26262-4(系统需求和测试),26262-5(硬件),26262-6(软件),26262-9(ASIL分析),其它的内容和项目管理,流程管理,质量管理等关系更大一些,本文侧重于从系统研发的角度来分析和提出可操作的建议。

ISO26262的分析更侧重于分析硬件的各种故障,而软件的任何缺陷也就是Bug都是系统级故障,这些是要求完全避免的。这一点也使得ISO26262的方法更容易应用在单纯的硬件模块或者软件相对简单的系统比如单片机,也同样使得ISO26262的量化分析方法较不容易应用于非常复杂的软件。

下面这张故障分析流程图来自理光的网站,是基于ISO26262-5对于硬件单元发生的故障做了分析,根据各种条件做出判断,最后走到SPF, RF,LF 则会引起系统安全目标失败。

SPFM (Single-Point Fault Metric),也称为“单点故障指标”,是算1减去单点和残余故障占总故障的比率。单点和残余故障比率越低, SPFM越接近于100%,这意味着单个故障因子在绝大多数情况都已经被检测和处理,而更加不易导致系统安全目标失败。

LFM (Latent-Fault Metric),也称为“潜伏故障指标”,是算1减去潜伏故障和所有多点故障的比率。这意味着要提高LFM,就要尽可能检测到或者觉察到多点故障。PMHF(Probabilistic Metric for random Hardware Failure),也称为“随机硬件失效指标” 这一指标计算较为复杂,FIT数字相当于平均每10亿小时发生多少次导致系统安全目标失效的故障数目。ASIL-B所要求的PMHF指标100FIT,也就是相当于平均连续工作1142年左右发生一次安全目标失败。注意,PMHF是一个安全目标失败的指标,而不是硬件的故障率。这个指标看上去如此的高,但考虑到量产产品的巨大数量,100FIT也并不是很高。这是因为FIT是用于衡量随机失效,1FIT对应的10亿小时,可以解释为1个设备10亿小时,也可以解释为1百万个设备的1000小时。

2.3 使用FMEA, FTA进行失效分析

ISO26262-10推荐采用FMEA(Failure Mode and Effects Analysis,失效模式和效果分析)和FTA(Fault Tree Analysis,故障树分析)的方法进行系统失效分析。

FMEA是一种从底层向上的方法,最早诞生于1950年代的可靠性工程。它通过分析每一个元器件的不同失效模式(Failure mode),找到失效原因,研究单个元器件的功能失效对于系统失效的影响。FMEA在工业界被广泛使用,并不局限于ISO26262。另有一个相近的名词DFMEA,是指在设计环节对子系统,接口,零部件等做FMEA分析。本文对这两者不做区别。在下面的基于视觉感知的ADAS系统中,如果CMOS图像传感器受外部输入的异常静电影响而死掉(不工作),就是一种失效模式。

如果没有图像输入的故障被视觉感知系统检测到,并因此进入安全状态,同时报错给AEB控制系统,这时AEB控制将不使用视觉感知系统的输入,而使用其它冗余系统比如雷达输入并且报错。视觉感知系统也将尝试故障处理,比如重启CMOS sensor。经过这个分析我们了解到系统中需要错误处理并重置CMOS的设计。同样的系统,如果汽车正在开的时候,突然ADAS摄像头附近的前风挡玻璃被落叶或者鸟粪遮挡(视频遮挡故障),这时候,CMOS图像传感器工作正常,但图像因为遮挡不能反映真实世界的场景,如果视觉感知系统没有这种故障检测,可能输出错误的结果比如认为前方道路没有障碍物,如果正好这时候雷达也没有发现有小孩突然骑自行车闯入道路,就可能发生AEB控制失效。经过这个分析,我们了解到系统需要增加对于视频输入遮挡的检测。如果视觉感知系统发现传感器被遮挡而主动报错,就可以使得系统进入安全状态而避免失效。

上面对这种失效带来的影响,以及系统应该如何应对,就是FMEA的分析过程。FMEA分析侧重于定性分析,毕竟,比如鸟粪遮挡镜头的概率是多少是难以预测的;如果系统中可以提供元器件或子系统的失效率,FMEA也可以定量分析。FMEA不仅仅是一种方法,而且也是一种设计理念。

至于FTA,则是一种故障树分析。和FMEA从单个元器件的由下而上相反,FTA是一种从顶层向下的分析过程,源自1962年贝尔实验室,如今也是广泛用于航天,汽车等高可靠工程,可以作为FMEA方法的互补。FTA是要求形成系统最终失效结果,是各个元素之间的逻辑运算(AND和OR等)形成的一个树状结构。

如下图:

我们来看一个小的FTA分析的例子:

假设有个车用嵌入式系统存在概率性无法正常启动,而且是很早期就死在bootloader阶段。我们列举一下可能的原因,大致有这几种:

a.可能系统板级硬件故障,比如电源,内存不稳定或者其它损坏 (系统)

b.可能是主芯片的缺陷,正好这块芯片有故障 (硬件)

c.可能软件代码存在缺陷,比如启动过程的上电时序没遵守要求 (软件)

d.可能工作环境温度超过了主芯片允许的范围 (环境)

e.可能是软件匹配错误,比如操作员升级了错误的固件 (人)

以上五个因素是属于OR的关系。其中每类又可以分为不同的OR和AND。比如硬件故障导致启动失败,是 “DRAM错” OR “NAND错”OR “电源错” OR “其它硬件错....”其中“NAND错”又可以分解为“NAND 读发生bit错误” AND “这种异常没有被NAND控制器ECC算法纠正”两个因素的叠加。

FTA分析的好处是以逻辑的方式展示,容易找到关键环节,包含人的因素比如误操作,并有利于提出改进方案。FTA分析的不足之处是对大系统,这个逻辑图会扩展到多个级别,变得极为难懂。而且FTA分析是从可以想到或观测到的单个最顶层失效开始,并不容易考虑多种顶层失效。在扩展树的时候也不容易发现共因失效。

正因为FMEA和FTA各有所长,ISO26262规范建议结合两者的优势进行互补,既做从顶层而下的FTA,又做从单个元器件底层向上的FMEA。关于功能安全的失效分析还有HAZOP(HAZard and OPerability analysis)等方法,主要关注状态指标超过了设计范围,系统可能处于危险状态,从而导致故障发生。所以HAZOP安全分析侧重于观测系统状态的变化和预防。

2.4 SOTIF标准和其改进

SOTIF(Safety of the intended functionality),也就是“预期功能安全”,也叫ISO/PAS 21448标准,是2019年才新推出的新的汽车功能安全标准,SOTIF标准关注没有预料到的功能失效,未知风险的可能,功能的误用等。具体一些的话,哪些是ISO26262标准覆盖的部分,而哪些是SOTIF覆盖的呢?

SOTIF的核心理念是把场景划分为已知安全,已知不安全,未知安全,和未知不安全四种类型。如下图:

SOTIF标准的目标是,增大已知安全场景,同时减小已知不安全场景和未知不安全场景。这将改善系统功能安全。

对于已知不安全场景,SOTIF标准通过技术措施提升功能,或者限制性能和使用,从而把已知不安全,变为已知安全。比如公开城市道路上实现自动驾驶并不容易,但如果限制汽车的速度和场地,就有可能实现园区内的自动驾驶。

未知不安全可能出现在未预知的场景,如果通过场景检测而知道不安全,就可以把未知不安全变成已知不安全。

因为已知不安全可以如上,通过限制使用,这样就可以进行风险规避。举例,如果发生大雾而造成可见距离降低,这时候自动驾驶系统可以进行限速或者在超过速度限值的时候给予警告,以降低因为可见距离太低,即使发现障碍也不能保证及时刹停的风险。

SOTIF的实践需要我们增强系统的能力以扩大已知安全,通过适度限制使用性能以降低已知不安全,以及尝试和设计和模拟各种特殊场景以减小未知不安全。正因为SOTIF标准尝试检测未知场景,和探索系统性能的限制,这些需要更多的数据积累和采用系统模拟化的方法去创造不太可能出现的场景,以及各种边角案例(corner case)。

ADAS系统中的前向碰撞检测,通常关注的是本车道正前方的车辆的距离和相对速度,驾驶员侧通常是较容易发现超车车辆,即使强行切入人工干预也相对容易。但如果在另一侧有车辆违章超车,可能处于驾驶员盲区,ADAS即使发现,也不一定来得及避免前向碰撞。这种场景需要侧向摄像头或者雷达提前发现侧向超车,以使得系统尽早点做出响应。

ADAS和自动驾驶企业包括Mobileye和特斯拉,都在收集大量的corner case来丰富算法对于未知场景的覆盖。对于corner case的考虑除了进行收集以外,还可以采用场景模拟器来生成虚拟场景,虚拟场景可能包含随机生成的复杂道路以及违章车辆,异常事故和天气等。这些虚拟场景可以大大增加场景测试的丰富性,从而发现原有系统设计中未考虑的复杂性。

特斯拉汽车发生在台湾的一起交通事故中,基于视觉算法的Autopilot系统没能识别横向倒下的大卡车这种场景,对于原本的算法来说属于“未知不安全”,如果按SOTIF标准来考虑这个问题,要么需要增加系统冗余,依靠雷达或者双目立体视觉来补充单目视觉感知算法的不足,或者改进单目视觉感知算法并增加场景检测,在发现场景属于“未知”的时候及时减速,并把大卡车判断成为“障碍物”而避免严重事故的发生。

SOTIF标注对于系统的风险特别是未知不安全很难通过形式化方法量化,所以使用“风险发生次数/测试里程数”会是一个比较容易操作的量化评价标准。

2.5形式化方法和轻量化功能安全

ISO26262的标准流程属于Formal Methods,中文叫做“形式化方法”。这种理念是需要采用严格的数学模型去描述硬件和软件的工作和根据这种方法去设计。和其它的方法有所不同的是,形式化方法采用数学模型计算和模拟的方法去验证一个系统的功能,对应ISO26262采用失效率计算的方法来验证系统是否达到对应的功能安全等级。采用计算失效率,而不是采用“测试法”证明系统有效,是和ISO26262以及IEC61508来自于德国有关。在德国,“产品责任法”需要产品生产者保证已经采用所有已知方法去避免在产生开发和生产中犯错误。这使得产品开发者必须通过文档来详细记录和分析各种措施,形式化方法所需要的大量文档因此被创建出来。据统计,严格按照功能安全流程和准则开发的费用,是常规开发流程的2~3倍。

(参见:MARTIN HEININGER “Functional Safety and Pragmatism is that possible”)卡内基梅隆大学的Michael Collins教授在“可靠嵌入式系统”课程中谈到形式化方法。“纪律性”和“精确”是这种方法明显的优点。采用形式化方法,使得工程师需要仔细思考每一个环节,为了证明正确性,需要严格的目标和规范,比起传统方法,有利于更早发现系统故障的根本原因。形式化方法需要清晰定义的目标和过程,消除模棱两可。而形式化方法也有缺点,在于“昂贵”,“缺少计算模型”,和“难于使用”。(https://users.ece.cmu.edu/~koopman/des_s99/formal_methods/)“昂贵”指的是形式化方法的开发初期成本较高,以及严格要求带来的工程量增加。至于软件的可维护性和后期开发调试复杂度,Michael并没有提及,但严格按照ISO26262开发将不允许需求的随意变更,以及软件接口的反复修改,这一点对于新颖技术的开发的确会是一个挑战。“缺少计算模型”指的是难以用数学模型精确描述。比如数学模型较难以描述系统输入带来的某些副作用,偏离常规的情形,现实世界的复杂性,元器件实际输出和理想模型有差异等,都使得靠统一数学模型进行失效率分析变得困难。“难于使用”指的也是尝试通过包罗万象的统一方法描述系统会带来难以想象的复杂性。

因为以上的原因,鼓吹严格意义上的形式化方法有时带来项目的失败,所以使得人们考虑采用“轻量化”(lightweight approach)形式化方法,发挥它的优势,但是又不为它的复杂性所困。AUTOSAR (AUTomotive Open System Architecture) 就是这样一个运用ISO26262功能安全核心思想,但并不完全兼容的经典案例。很多汽车行业的朋友都认为AUTOSAR是兼容ISO26262功能安全的设计,但这种说法并不正确。AUTOSAR的目的是为了实现硬件和软件的分层设计,降低模块单元之间的耦合度,使得不同供应商之间可以按照一套框架分别独立设计生产可以重用的软件和硬件,从而有利于降低整个行业的研发成本。如今,AUTOSAR包括Classic AUTOSAR和Adaptive AUTOSAR,已经成为整个汽车行业软件架构的最流行的实践标准。

AUTOSAR的设计包含了功能安全的思想,比如自带硬件故障检测,运行时软件故障检测,内存分区,通讯时的冗余校验,程序流监控,使用CPU特权模式和用户模式,但AUTOSAR并不支持所有的ISO26262的功能安全措施,详细请参见AUTOSAR官方文档“Overview of Functional Safety Measures in AUTOSAR”,比如不支持形式化方法所需要的系统化和结构化的风险分析和管理,也没有ASIL分级概念,并且也不支持进行ISO26262相关的审计和兼容测试。

所以学习功能安全的思想,用于指导系统设计可以有效地提高产品质量,降低安全风险,但也不适合教条主义,吹毛求疵而忽视其它基本要素。

3、功能安全中ASIL分解和安全冗余

3.1 ASIL 分解的原理

在系统开发实践中,除了比较简单的系统相对容易进行形式化分析以外,复杂系统可以借用V模型的开发流程,从整体到单元,从单元到整体的过程,以及把复杂系统分解成较简单子系统的ASIL分解思路。

ASIL分解是一种有价值的思想,因为低功能安全的系统的需求更容易实现。把高ASIL等级的系统进行分解以后,通常有利于降低系统的总成本,并且仍然可以维持系统的高可靠性。

比如下图中,通过ASIL分解,可以把一个功能安全需求为ASIL-D的系统安全目标,分解为ASIL-D + QM, 或ASIL-C + ASIL-A, 或ASIL-B + ASIL-B。

图片来自于ISO26262-9

ASIL分解思想的来源是随机失效率的计算,两个互不相关的子系统如果单独发生随机失效的概率是P1和P2的话,同时发生随机失效的概率就是P1*P2,如果P1和P2都很小的话,结果就更加的小。这个计算可以成立的前提是两个子系统的的随机失效是相互独立的,也就是不存在共因失效。ASIL分解特别是ASIL-D的系统分成两个互不影响的ASIL-B子系统的叠加,本质也是一种完全冗余设计。

3.2 基于ASIL的系统冗余设计

冗余(redundancy)是可靠性工程设计的和新方法之一。冗余设计依靠重复核心元器件或者功能,以及重复信息来提高系统的可靠性。经常用于元件或者信息备份以自动防止故障。

很多高可靠性系统采用完全双重冗余,给所有核心元器件都做双重备份,如果发生故障,备份部分还可以继续维持系统工作。而安全关键类型的系统,比如电传飞行(fly-by-wire)系统的某些核心控制器需要做到三重备份。在做了多重备份设计以后,系统还需要有比较器或者仲裁器,来判断这几套完全冗余系统之间是否一致,并最后选择哪套系统的输出结果。

简单把核心系统复制两遍的冗余并不一定是可采纳的解决方案。其主要原因在于冗余设计本身也增加了系统的复杂度,比如成本和功耗都至少翻倍,增加量产的难度。如果对于一种特定输入会导致系统必然逻辑错误的话,采用双重冗余并没有帮助。这种冗余设计主要是为了防止随机故障对系统的影响。

比起简单的完全冗余,有时候信息的冗余纠错码(ECC, CRC等)可以起到很好的作用。在实际芯片和电路设计中,不理想的因素比如外界干扰,电源噪声,信号完整性,长期使用老化,因震动导致松动等因素都有可能产生信息传输错误,这时候。冗余纠错码的检测,有利于发现信息传递中的错误,从而根据结果丢弃,纠正或者忽略错误数据。

除了硬件设计冗余备份和信息冗余,CPU、DSP等在执行软件环节也可以采用执行冗余。ISO26262-5定义了使用两条软件通路执行相同的工作,并且相互对比结果。采用这种方法也可以在不同的硬件单元,甚至不同构的硬件单元执行相同的算法。

图片来自于ISO26262-5

这种方法可以用两个相同的芯片,做两个对等的系统然后比较,特斯拉的FSD的设计属于这种。

图为特斯拉FSD的双重冗余系统,不仅仅是主处理器冗余,还有电源设计冗余和多摄像机视角冗余 硬件支持的双核锁步执行也是一种冗余设计。同一个处理器上两个对等的核执行相同的代码,并且时间上稍有差别,通过相互比较以发现错误。锁步执行的方法可以很好地检测出瞬态故障。锁步执行对硬件要求比较高,所以一般用于高安全等级的处理器,如在安全岛上的设计。

除了上述采用同样处理器运行同样算法的同构冗余,还有采用不同处理器运行不同算法的异构冗余。采用不同硬件,传感器,算法做异构冗余,有利于发挥不同硬件设计的长处和弥补短板。比如采用摄像头和毫米波雷达融合实现1V1R的ADAS系统,就是一种异构冗余设计。要注意的是,不同硬件的数据丰富程度有差异,如果要做数据融合的话,尽量还是要选择相互之间功能有较大重叠度而且互补的系统。

以Intel/Mobileye的ADAS产品举例,如果功能安全要求是ASIL-B(100FIT),相当于每10的7次方小时内只有一次导致系统安全目标失效的故障,这个要求是非常高的。现有基于单个纯视觉的算法无法做到这样的高的可靠度,而是最多可以大约做到10的4次方小时内不超过一次安全目标失效故障(见Amnon Shashua教授在CES2020上发表的演讲)

L2级别的ADAS常常要使用多传感器融合的冗余设计,比如视觉子系统和毫米波雷达融合来降低系统安全目标的失败率。如果通过互不相关的几个视觉算法进行独立检测,并对结果进行融合来实现算法冗余,也有助于降低系统最终的故障率。使用以上的多传感器冗余加多种算法冗余,最后可以使得系统的综合输出功能安全达到10的17次方小时单次安全故障的等级(100FIT)。

3.3 通过MCU扩展实现系统功能安全

视觉感知系统的核心主要是以下的结构:

在以上的模块内,CMOS sensor提供图像采集,输出给视觉感知SoC。ISP模块负责图像处理包括色彩空间转换,Tone mapping, 降噪,图像缩放等,输出图像给NPU。NPU模块负责运行基于神经网络的ADAS(高级辅助驾驶)算法,输出结果到内存。CPU模块负责整个算法和流程的调度。

这个系统通常很难做到ASIL-B或者更高的功能安全等级,这是因为这些模块有着复杂的数据处理过程,并包含多种失效模式。CMOS sensor首先要保证选用ASIL-B或者以上级别的。视觉SoC的内部多个单元模块也要实现各种错误检测和汇报机制,以实现ASIL级别的需要。如果其CPU使用ARM A系列的处理器,除非进行锁步执行,很难达到ASIL-B功能安全等级。

至于视觉算法所使用的神经网络技术,因为其结构设计并不容易用逻辑推断来描述,其参数比如分类器是基于训练得到而不是确定性逻辑得出,无法用形式化方法分析其失效率(不能计算SPF, LF, PMHF),所以也无法得到ASIL级别。即使采用传统的机器视觉算法,手动设定分类器加上训练,也一样存在大量经验性而不可以保证其对未知场景有正确响应。

基于Mobileye EyeQ3和EyeQ4设计的ADAS处理器在行业已经广泛应用,但据悉,也并不能独立实现视觉感知功能的ASIL-B。那么如何提升视觉感知系统的功能安全呢?行业里的较为普遍的做法,是使用ASIL-B级别以上的安全岛,或者独立的ASIL-B以上级别的Safety MCU,来实现系统级功能安全。

通过增加一个具有ASIL-B或更高安全等级的MCU,并且软件实现视觉感知SoC向Safety MCU输出结果,并且接收Safety MCU的监控和控制,这样这个系统就有可能实现“系统级功能安全”,最终视觉感知结果,具备功能安全ASIL-B或更高等级。这个系统也相当于

:系统级ASIL-B = QM (Vision SoC) + ASIL-B (Safety MCU)

要证明这个ASIL分解成立,我们首先要看这两个子系统是否存在共因失效。如果Safety MCU的电源设计具备冗余,并且其和视觉SoC之间的I/O具有Failsafe保护,那么并不存在一种外部故障,可以让Safety MCU和Vision SoC同时失效。

其次因为Vision SoC的失效如果不被Safety MCU检查出来,则会被传导到最终输出,这种将会导致ASIL分解不成立。如果Vision SoC的失效是可以被Safety MCU检查出来的,那么Safety MCU可以在最终信息输出标识系统进入安全状态,并且可以控制包括重置Vision SoC子系统进行错误修复,这时Vision SoC的失效不会导致系统失效,ASIL分解成立。所以关键点在于Vision SoC的失效是否可以被检查出。

为了更好地检查Vision SoC的失效,我们可以采用ISO26262推荐的方法,包括但不限于:启动时自检,运行时的周期性自检,程序流监控,和视觉感知关键数据时间检测,硬件和软件出错汇报,监测CPU异常,操作系统异常,内存数据异常,I/O报错,中断异常,状态偏离(比如CPU越来越忙,空闲内存逐渐减少),CMOS传感器数据校验,周期任务执行超时,输出数据超时等。这些监测的目标是使得Vision SoC尽可能汇报可以检测到的各种错误,包括图像输入故障,卡滞和处理错误,如果因为异常而停止向Safety MCU输出,则会产生超时错误也一并被监测到。

经过上述的努力,我们有希望把视觉感知系统提到接近于ASIL-B的安全目标。但这样的系统通常也被认为不能达到ASIL-B,其主要原因是其采用的视觉感知算法目前尚不能被ISO26262认可。也有观点认为单独使用ASIL-B Safety MCU不能做到充分的冗余,但通过增加一条数据通路,使得Safety MCU也可以监控CMOS sensor的输出状态和信息,可以实现更为充分的冗余而达到系统级ASIL-B。这种设计在Veoneer的Traffic Jam Pilot系统里已经实现量产 (视觉SoC QM级别 + Safety MCU ASIL-B级别)。

那么,如果要达到更为严格意义上的ASIL-B,是否可以做到呢?市场现行的解决方案是增加可替代视觉感知的冗余,特别是增加毫米波雷达感知系统。增加了雷达以后,以上的系统框图变为:

这个系统需要摄像头的覆盖角度的关键部分如当前车道,和毫米波雷达的覆盖角度相重叠,这样来自两个不同传感器的异构冗余可以改善系统的功能安全。毫米波雷达系统可以做到符合ASIL-B,随后在ASIL-B或更高级别的Safety MCU进行视觉+雷达做数据融合,并根据融合数据做出算法判断,最终的输出结果可达到ASIL-B或更高级别。

3.4 选择安全MCU扩展还是单芯片

这里我们可能面临一个问题,如果有一颗SoC能够把Vision SoC和Safety MCU合并进去,是不是等价方案?既可以实现高性能的算法,同时又可以做到功能安全需求。这样系统的框图类似下面。Performance core是性能核,也就是原来Vision SoC的部分,Safety Core就是原来的Safety MCU的部分。现在放到一起以后,两部分可以通过共享内存和相互发送中断进行通信。

上面这种SoC集成了安全岛的设计,在车用智能驾驶SoC里越来越流行,但我们并不能得出这种集成设计一定好于前面的分离设计,其原因在于:

集成设计的两个部分在一个芯片内部,根据不同芯片设计的差异,可能存在相互影响和资源依赖,而产生共因失效,比如电源和重置部分是否可以做到完全独立。

性能可能相互影响而造成风险,如果Performance Core过于繁忙,占用内存带宽过多,可能影响Safety Core上运行融合算法的时间确定性。反过来也是一样。如果Safety Core也运行安全性要求非常高的任务比如AEB控制,则时间确定性变得更为重要。

Safety Core部分的CPU运算性能,功能安全等级不一定好于分离式里的单独的Safety MCU。同样,Performance Core部分的视觉感知性能,也不一定好于分离式里单独的Vision SoC。

所以在实际系统设计的时候,需要根据需求进行分析,并不能得出分离式系统的功能安全不如集成式系统这一结论。下图是能够支持L3级别自动驾驶的奥迪A8的智能驾驶域控制器的设计:

图来自https://systemplus.fr对于Audi A8拆解报告,公开内容以及https://www.eetasia.com/teardown-lessons-learned-from-audi-a8/

其中包含四个主要芯片:NVIDIA Tegra K1, Mobileye EyeQ3, Altera Cyclone FPGA, Infineon Aurix Tricore MCU。其中TK1和EyeQ3负责自动驾驶中的视觉感知,包括交通标识牌识别,行人检测,碰撞预警,光线检测,车道线检测,360度环视等功能。Altera FPGA负责目标融合,地图融合,停车辅助,碰撞预防,图像前处理等功能。而Infineon Aurix负责交通拥堵导航,辅助系统,矩阵大灯,路线图等功能,并且负责系统的安全监控和底盘控制。也就是说,这个四个芯片的复杂系统是TK1和EyeQ3两颗QM芯片加上一颗ASIL-B等级的Altera FPGA,再加上一颗ASIL-D等级的Infineon Aurix Tricore来共同实现。

这个例子很好的说明了如果设计合理的话,分离式功能安全设计是可行的,同时也说明了单颗甚至两颗芯片实现这样复杂的系统功能是非常困难的。再反过来看看前面提到的特斯拉FSD的完全双重冗余,也许特斯拉的设计更清晰明朗,虽然其并不是典型的ISO26262设计理念。

4、功能安全对软件开发与测试的要求

4.1 代码规范,静态检查和审查

了解过ISO26262的软件编程要求的朋友,都会知道,ISO26262标准对于编码规范有比较强的要求。一些ISO26262的培训和代码静态检查工具都提到MISRA C规范。所以这方面有不少指导意见,比如:是不是要符合ISO26262,软件就不能使用内存动态分配?是否要在C语言里限制使用指针?绝对不能使用goto语句? 是否要通过MISRA C检查并且解决所有不兼容的问题?

在ISO26262-6规范里我们确实可以看到对软件设计和编码的要求:

这些ISO26262的软件编码要求和嵌入式一般的要求并没有太大差别。一般对安全性有要求的嵌入式软件,和桌面操作系统Windows/Desktop Linux的编码要求有所不同,通常更为严格。所以对于这些指导性要求,除了限制使用指针以外,其它的条目和嵌入式编程规范比较接近。我们用指针的使用和动态分配内存两件事情来谈一下编程规范。

指针和地址是C语言的基本功能,正是因为方便传递地址而不是复制数据,使得一个进程内部不同模块之间的通信效率非常高。首先,我们不建议对于指针类型做强制类型转换,至少是不能把随便一个u8 * 类型的指针转换成u32 *或者一个结构体指针,因为字节对齐的关系。反过来,把其它类型的指针转换成void *是可以的。至于不同进程之间如果共享数据的话,本来也不能用指针,要么用Unix Domain Socket或者MessageQueue,要么在共享同一块物理内存的时候尽量传offset,而不传指针。另外设计API的时候,对于输入和输出的指针都要检查其是否为空。如果是C++做应用程序的话,可以用引用代替部分指针的功能。关于指针的话题还有很多,但如果指针都不够熟悉的话,还如何开发嵌入式程序呢?这是C/C++的最基础的内容了,是每个嵌入式程序员必备的基本功。

至于代码静态检查内存是否可以动态分配,通过malloc/new。简单的说,除非你的应用非常简单而且固定,比如实现一个MCU上的代码,全部都用静态分配是可行的。但如果是比较复杂的SoC,而需要动态加载和卸载驱动,或者动态根据输入解析命令执行程序,支持根据需要创建线程之类,根据需求加载不同算法或者配置等,都需要动态分配内存。如果是C++的程序,使用STL来实现高效率的数据结构的,都会有动态分配内存。所以这个问题其实变成不是能不能动态分配内存的问题,而是如何动态分配内存?嵌入式里对于这个问题有很多解决方案。比如创建内存池,然后在内存池内分配。对于支持虚拟内存的系统比如Linux,还可以在用户空间分配物理不连续但虚拟地址连续的内存块。所以传统MCU上可能动态内存分配导致的很多问题都不存在。

因为MISRA C规范当初制定的时候,汽车ECU还是采用简单的单片机,往往没有操作系统,也没有多线程,所以那个时候的编程规范还相对简单和局限。事实上,现今的嵌入式编程规范,比MISRA C更严格,但却没有MISRA C的局限。比如MISRA C除了不允许前面说的动态分配内存,也不允许使用C语言函数的可变参数,这就使得printf/printk这样的函数在MISRA C里是不被允许的。符合MISRA C的print,就需要写一堆替代比如print0, print1, print2,然后函数参数也需要固定化。过多的局限性关注于一些不重要的环节,而并非关注于真正有价值的部分。

细心的朋友可发现,MISRA C的要求仅在ISO26262的notes和examples里出现。根据解释,MISRA C是一种可以参考的编程规范,但并不会说MISRA C是必须要被遵守的一种规范,简单说,如果有更好的规范作为替代,并非要严格遵循MISRA C。对此ISO26262明确作出了说明,如下:

General requirementsInformative content, including notes and examples, is only for guidance in understanding, or for clarification of the associated requirement, and shall not be interpreted as a requirement itself or as complete or exhaustive.

Notes和examples只是为了方便理解或者阐释需求,不能被解释为需求本身,或者认为是充分的需求。

MISRA C仅仅是编程规范的一种,它无法做真正好的静态代码检查。那么我们用什么静态代码检查呢?根据我们的经验高版本的GCC加上严格的编译选项(-DFORTIFY_SOURCE),使能开各种静态编译警告,使能AddressSanitizer,使能Full RELRO等,并且把所有的警告都转为错误,比如未初始化变量,数组可能越界,变量定义了没有使用,数据可能被截断等非常多有价值的警告,比起MISRA C检查工具可以更有效地检查出代码的隐患。免费C/C++静态检查工具Cppcheck也很好用,实际开发中作为必要的检查项目,有利于提高代码质量。

要注意的是,再高级的代码检查工具也代替不了设计中的审查和代码审查。常见的检查工具不会关注你的函数返回值是不是符合预期,也不会关心函数执行时间是否优化,也不会关心你是否在应该采用atomic类型变量的时候没有使用,也不会关心你的线程同步或者信号量是否正确。各种静态工具规则就像学校里自习课上老师来视察看看是不是大家都在学习一样,只能看到大家的动作是不是违规,却不能检查每一本书是不是都是学习相关的内容。

代码人工审查的最佳的工具之一是Gerrit(Code Review),搭配git做软件配置管理。软件项目要做到每次新添加代码都有人审阅,都有人测试。每个提交都可测试通过否则拒绝提交。这些现代软件工程的工具,才更有利于多人协作提交高质量代码,才有利于静态检查中间避免潜在隐患,而不是等着测试结果去发现隐患。

4.2 代码的运行时检查,测试和迭代式开发

前面提到的动态分配内存可能导致的内存泄露,通过静态检查可以发现部分,但对于复杂的软件,比如 C++ STL,使用静态检查发现内存泄露是比较困难的。解决内存泄漏是一个软件编程技术可以解决的问题,比如通过引用计数等方法,可以做到内存块不在被引用的时候被释放。这种方法可以被拓展成为智能指针对象,可以在堆栈上生成,然后脱离函数作用域以后自动释放。

即使不使用引用计数,也可以通过严格的编程习惯和代码审查做到对于动态内存的管理,也可以通过测试工具来发现。也可以有一些工具比如“memory sanitizer”可以用来动态检查代码段中分配的内存在退出的时候有没有被释放,如果没有的话会报错。

代码的运行态可发生的错误之中,很多都是来自于对于软件工程的不理解,不懂软件开发的一般方法,以为只是写代码(coding)。现如今的软件工程领域的书和实践方法,更多的是讲软件项目管理,软件可靠性测试,软件复杂度比如多少行代码换算成多少人月之类的,写这一类书的人,不一定都熟悉编程,所以对于软件的复杂度的估计可能也会有偏差,比如认为1000万行的代码复杂度比100万行的代码复杂度大很多。软件编程首先是一项技能(craftsmanship),然后是一项工程技术(engineering),然后这些都是基于计算机科学(computer science)。如果对这些科学,工程技术,技能把握程度不深,而导致设计不合理,通常就不是简单通过工具分析而进行解决的。实用的方法,是靠测试驱动开发,靠功能测试,性能测试来观察实际功能的偏差,从而逐步重构,取代已经有的软件模块。

我们看到汽车软件架构也随着从早期多个MCU的复杂性,逐渐过渡到由一个或几个域控制器,彼此之间通过高速总线比如汽车千兆网相互连接。模块之间的通信采用SOME/IP,DOIP等面向消息传递和处理的方式,实现SOA(Service Oriented Architecture) 而不是面向具体硬件ECU的方式。模块内部,则采用专用的SoC,DSP, FPGA等实现功能,并以AUTOSAR等方式提供外部接口。本文主要关心的还是模块内部的嵌入式设计。

运行态的测试可以遵循类似于ISO26262 V模型的方式,先从单元测试开始,然后进行单元整合测试,最后产品层面测试。具体测试的方法,除了基本的功能测试,还包括老化测试,压力测试,对于逻辑单元模块还可以采用对比数学模型进行测试,如果这个单元和其它模块之间有交互通信还可进行交互性测试,如果软件模块要符合某种通用协议还需要进行兼容性测试,等等。对于单元提供出来的接口,可以进行审查,尽量把不必要暴露出来的接口隐藏在模块内部,同时要检查软件模块的API是否符合通行的API定义规范,其接口是否存在可扩展性,单元设计的时候,模块是否有对应的版本号和对其它模块的版本依赖,模块设计是否需要或者应该考虑对于老系统的向后兼容性。这些都是可以测试的内容。

ISO26262对于软件开发还是基于传统的“瀑布”模型,认为需求在项目开始的时候是“已知”的,实际项目可能并非如此。实际项目往往大的需求项目已经树立,但是细节并没有可能提前预知,甚至主要元器件选择比如摄像头模组需要在项目立项以后再进行对比选择。这样的实际工程给系统开发团队更大的挑战,在软件开发环节就需要进行几次迭代,才有可能达到量产时的质量要求。软件迭代和增量式开发成为实际项目开发的常态。这相当于ISO26262的一个大V成为多个小V的串联。敏捷过程(Agile Development)定义了软件开发中的多次迭代。

实际在每个迭代过程都有自己设定的硬件和软件要实现的目标,测试规格,期待值,每个迭代过程都有一个时间周期。所以经过设立这样的小的“可实现的目标”,系统可以经过几次迭代,逐渐逼近最后性能和规格都达到要求的“量产版。”

在每个迭代中,关键性错误都是必须要解决而不能带入下一个迭代的。如果碰到不可解决的问题,就需要仿照V模型,退回初始状态,进行设计更改。比如更换硬件元器件或者修改软件模块设计,甚至调整系统架构。

4.3 代码的错误处理和错误注入

根据墨菲定律,如果事情有变坏的可能,不管这种可能性有多小,它总会发生。所以说软件故障是不可能完全消失的,尤其当这个软件系统相当复杂。我们并不非要等测试出现问题以后才回头看软件设计本身的缺陷。软件本身设计环节就需要提前做好返回值检查,错误处理的工作。简单的说,调用任何带有返回值的函数,都需要检查返回值。并且返回值检查和处理要包含所有可能的情况,即使不能进行枚举,也要进行if/else以实现全覆盖。

函数返回值检查是最基本的,如果返回错误值属于已知的故障类型,则需要考虑按照ISO26262的需求进行故障汇报,故障容错以及故障处理。ISO26262给出了一些参考的错误处理方法,包括通过重试修复,如果可行的话跳过,使用完全冗余来覆盖(ASIL-C以上),修复,还有适度降级等。

图来自于ISO26262-6

在实际汽车的嵌入式项目,这种错误处理还要根据客户的需求而定。

持续系统测试并等待错误发生是低效率的,所以在系统整合测试中,错误注入(error injection)是非常有帮助的一种测试方法,以使得在尽可能短的时间取得最大的测试覆盖率。比如假设读取图像数据卡死,图像没有输出,一定会影响算法模块不能执行,但如果不这样测试,如何知道算法模块不会因为软件设计缺陷而产生其它的异常呢?

这里通过做错误注入就可以了,通过提供一个API,让读取图像数据模块停止输出,然后观察系统的表现,就是一种错误注入方法。我们来仔细分析一下,如果这样并不能模拟CMOS sensor死掉的情况,只能模拟读取数据的环节。所以我们还可以在底层提供一个API,直接控制CMOS sensor让它停止工作,观察后面系统是否能有效地处理这个错误,而不导致其它不应该有的行为(比如中间件或算法崩溃)。推而广之,几乎所有的模块都应该提供模拟错误的API,甚至包括有意为之的错误输出,而不仅仅是停止工作。这种复杂性让软件的每一层都不得不更加关注所调用层的错误输出,或者通过系统级API观察系统底层的错误输出。

这种错误注入的过程在分类上属于白盒测试,而且工作者需要对系统的细节和薄弱环节非常了解。所以经过这一轮测试以后,我们有理由对系统软件的功能安全有了更深层的信心。

5、功能安全的探索

5.1 机器视觉方法是否可靠

SOTIF标准里针对基于图像机器视觉方法做了讨论。路面上做行人检测的同时,还有算法做行人的速度检测,如果速度不合理的话,会拒绝这个是行人。另外一个例子里,通过检测路面上印的小孩的图,可能会误触发是行人,结合光流算法,有机会判断出来这个不是真实的小孩,所以避免误触发。这两个例子实际仅仅是引发我们思考是否可以引入更多的因素来加强判断的准确性。因为任何的误判的后果都是灾难性的,即使过度谨慎立刻刹车也可能会引发后车的追尾。所以“找到解决方法”比如“神经网络算法和光流算法的结合”是远远不够的,还需要通过实际的量化数据证明这种真的是一种解决方法。

针对路上行人判断我们来思考一下,不同的视觉感知算法是否可以相互冗余?答案是不一定的,如果图像来源就不是很清楚而无法判断,比如雨天里面一个穿雨衣的人?如果还可以识别,那么雾天呢?对于因为原始图像就缺少相关信息的场景,我们需要采用图像领域的技术,比如HDR,去补足信息,而不是单纯依靠算法。如下图:

左图是CMOS传感器运行图像线性输出模式,右图是同款CMOS传感器加ISP高级HDR模式

凭借更好的HDR技术,我们可以拓展图像的动态范围,使得暗部和高亮部的细节可见。这将从源头解决数据的问题而提升机器学习包括神经网络技术的目标检测及识别准确度。反过来,对于暗部区域,如果你用两种不同类型的视觉感知算法也无法做出有价值的冗余。

这种HDR的处理技术并不是靠简单买芯片就可以做到,它还需要针对具体图像传感器的调试校准和需要相关的ISP技术支持。所以到了靠机器视觉辅助驾驶的时代,ISP硬件和相关的图像处理算法变得对功能安全更加重要了。

对于SOTIF标准提出的两个识别行人的问题,如果采用更好的图像输入,采用深度学习做行人检测叠加目标跟踪,会有更好的效果。但如果这样还是不能得出高置信的结论,还是建议采用降低车速来减小“已知不安全”的风险。我们自己开车的时候,不是也有时被高速公路路肩上的“假警察”和“假警车”迷惑吗?

传统的机器学习(Machine Learning)的方法和基于神经网络的深度学习,哪一种更适合功能安全需求呢?一般来说深度学习更好。深度学习从本质上是采用大数据训练的方法去得到特征,而代替传统的手工挑选的特征,所以更容易泛化,更不容易局限于有限数量样本得来的片面性。就单纯物体识别来言,某些深度学习算法在面对测试数据集的识别率甚至高过了人类。

深度学习常规的算法较多采用卷积神经网络(CNN)的方式,其主要特征是在于用多个训练生成的模板去抽取图像的特征,并且在不同层采用不同的模板卷积抽取不同层面的特征,再经过激活,池化等传递给下一层。神经网络的工作原理非常接近于人脑。理论上一个设计的层数足够多,足够精妙的神经网络经过大数据训练以后可以模拟各种数据处理。如果说神经网络算法是否可靠不可计算,那么人类驾驶员面对路面交通也有同样问题。比如没有经过驾校充分培训的驾驶员也是“马路杀手”,是不可以独自上路的,这和目前L4自动驾驶需要一个安全员的道理相同。

所以经过充分训练的神经网络,理论上需要通过测试,了解是否具有识别道路重要目标的能力,包括车道线,行人,车辆,自行车,交通标识牌,交通灯,限速牌等。如果有相关的大数据集进行随机挑选测试内容,然后对算法进行测试,就可以得到一个评分标准。这种评分标准虽然并不依据ISO26262标准,但对于SOTIF标准里的,减少已知的不安全,会有帮助。

提升深度学习算法的准确度,有利于增大已知安全区域。要做到这一条,需要采用更高算力的处理器,运行更先进的AI算法,并且采集更多的数据,覆盖各种场景。这里要说的是,当视觉感知器采用神经网络算法来实现时,其内部包含了一对矛盾:既要尽可能地最大限度的捕捉场景信息,以帮助神经网络从原始数据里提取特征;又要防止过度拟合(overfitting),也就是伊隆马斯克说的“Local Maximum”,要通过采集各种场景下尽可能多样化的数据集,并采用数据增强等方法来降低过渡拟合。目前业界正在采用各种先进技术来做到这些,需要的是更多时间,和更多的实践。前面提到的制造虚拟场景来虚构未知场景,也是从SOTIF的思路去尽可能降低未知不安全的场合。

让我们感到欣慰的是,基于深度学习的视觉感知技术是当前的热点,这一技术发展很快,所以准确度和可靠性的提升都非常可期待。如果以视觉感知技术为主,辅助以雷达做冗余,也可以找到市场及功能安全标准也可以接受的方案。因为这种机器视觉的方法因为并不采纳ISO26262的形式化方法计算失效率,所以我们只能寄希望于SOTIF标准或未来其它标准把这种更贴近人眼和人脑的方法纳入安全评价体系。

5.2 软件OTA

软件的迭代开发和OTA(Over-the-air, 在线升级)如今已经成为大多数汽车厂商认可的趋势了。那么OTA和功能安全是否有联系呢?我们一方面希望OTA可以解决已经有的技术问题,增加新功能,同时又希望OTA不要带来新的问题,特别是严重的安全问题。这将使得问题的难度再次升级。

以下我简单谈谈为了功能安全OTA有哪些设计要点:

避免OTA本身失败使得产品变砖

软件升级的过程,会涉及到固件的重新写入。当我们平时升级手机固件的时候,通过被提示插电升级以确保在关键环节写入的时候不要因为掉电而导致失败。嵌入式系统升级,特别是IHU车机更新的时候也有类似的原则。首先固件升级要保证写入非核心数据比如启动代码的时候,即使掉电也可以检测到错误,下次启动以后继续。其次对于绝对不可以掉电的核心数据,硬件需要有冗余设计,保证在写入环节保持系统不掉电。

设计这个功能还需要保证有可靠的最小系统,即使主操作系统因为意外不能启动,也可以由最小系统重新恢复系统。

避免OTA升级未被授权的固件或者版本回退

如果OTA升级了未被授权的固件,比如黑客攻击加入了木马,导致各种如电脑里所现的安全隐患?这种情况在实际良好的系统里基本不可能发生。

方法就是OTA过程需要进入首先对升级的固件做数字签名(digital signature)校验,基于非对称加密算法(比如RSA等)的特点,如果黑客手里不能掌握私钥则无法伪造数字签名。其次,对于升级完成的固件,在下次系统启动的环节还会进行安全启动过程的数字签名校验,失败的话,会退回前一次启动正常的版本。系统的硬件安全保护机制,也可以校验固件的版本,并且拒绝升级(回退)到老的固件版本(anti-rollback)。

2019年10月,中国通过了新版的《密码法》。新版法律采用了开放的态度,并不局限于使用国密算法,也可以使用同行业国际最先进的加密,签名,认证等相关技术。

OTA对于开发环节的需求

OTA需要最大可能的可靠,也需要尽可能小的开发包,以加快升级速度,保证系统安全,也尽可能不要打断正常运行。比如一辆车停在大街上因为OTA而无法正常驾驶是会有安全问题的。

如何做到又小又安全的OTA?简单的说,需要对软件功能做到尽可能模块化,分层化,不同功能的模块尽可能的解耦,接口的定义尽可能保持不变和向后兼容,功能的实现尽可能紧密地放在尽可能少的局域内。比如说如果核心算法通过升级神经网络模型压缩包,或者更换动态链接库(.so)就可以完成升级的话,就是一个文件替换的工作,而不需要上传整个固件。如果要做成这样,软件开发的时候就要想到做到接口和实现的分离。

不受干扰 (Freedom from Interference)

更新功能模块而不影响其它的功能,对于功能安全评级是一个重要要求。如果软件每周都有推送,还有时间每个版本都做完整的功能安全审计吗?

解决这个矛盾的可能方法就是按照功能安全ISO26262-6提到的“不受干扰”(Freedom from interference)原则。需要分析软件模块的更改,是否会对其它系统功能造成影响,进行定性分析和定量分析。

有的方面比如CPU,内存占用因为新的改变带来的影响,是一定可以通过测试发现的。所以不受干扰原则,需要解决的更多是靠系统分析发现,潜在的,低概率的,靠测试不容易发现的风险。

从功能的角度,需要在分析和测试中,找出单个因素的改变是否足以产生新的风险,比如基于摄像头的传感器中,如果前端图像参数的细微调整,哪些可能引起算法的结果不同,影响的程度有多大,是可以通过分析和测试得到证明的。

从设计分离的角度,采用适度的执行权限,内存保护,地址分离,或者数据依赖性分离,以及采用更合理的解耦的软件设计框架,是可以很大程度避免软件模块的深度耦合的。在这一点上,使用POSIX操作系统的通用编程模式,内存保护,线程同步,任务队列消息驱动等方法,比起传统的RTOS使用静态优先级和确定时间片同时也缺乏内存保护,会大大免除受到更新干扰的影响。

5.3 结语

系统功能安全是一个最终结果,任何和功能相关的模块不正常工作,都会潜在地影响功能安全。一个刹车失效,甚至可能是一行代码中的错误造成,源于一个函数调用的错误返回值没有处理。这种不可预期性随着系统的复杂性变得更难于捕捉。最好的防范就是严谨的分析,设计和测试。

实际软件工程中,做好自动测试,然后每天来一次整个系统的daily test是非常有必要的。绝大多数软件错误的发现都不需要高超的技术,而在于年复一年,日复一日的严谨态度和小进步。不积跬步无以至千里,不积小流无以成江海。看看Linux, GCC这些非常成功的开源软件项目经历无数版本升级如何发展壮大,就可以预见汽车行业的系统设计在未来如何一步步提升质量,实现更好的功能安全。

路漫漫其修远兮,吾将上下而求索。

 

 

 
   
次浏览       
相关文章

手机软件测试用例设计实践
手机客户端UI测试分析
iPhone消息推送机制实现与探讨
Android手机开发(一)
相关文档

Android_UI官方设计教程
手机开发平台介绍
android拍照及上传功能
Android讲义智能手机开发
相关课程

Android高级移动应用程序
Android系统开发
Android应用开发
手机软件测试

最新活动计划
C++高级编程 12-25 [线上]
白盒测试技术与工具实践 12-24[线上]
LLM大模型应用与项目构建 12-26[特惠]
需求分析最佳实践与沙盘演练 1-6[线上]
SysML建模专家 1-16[北京]
UAF架构体系与实践 1-22[北京]
 
 
最新文章
简述Matplotlib
Python三维绘图--Matplotlib
Python数据清洗实践
PyTorch实战指南
Python爬虫与数据可视化
最新课程
Python应用开发最佳实践
Python+数据分析+tensorflow
Python 编程方法和应用开发
人工智能+Python+大数据
Python及数据分析
更多...   
成功案例
某通信设备企业 Python数据分析与挖掘
某银行 人工智能+Python+大数据
某领先数字地图提供商 Python数据分析与机器学习
北京 Python及数据分析
某金融公司 Python编程方法与实践培训
更多...