汽车ECU软件测试是确保汽车电子系统安全、可靠运行的关键环节。本文以ISO26262标准为指导,通过一个自适应巡航控制(ACC)功能的实际案例,详细介绍了汽车ECU软件测试的全过程。首先,根据系统需求编写软件需求,明确软件应满足的功能和性能指标。然后进行软件设计,确定软件模块的接口和数据流。接下来是单元测试,包括静态测试(如MISRA规则检查)和动态测试,确保每个模块的代码质量。单元测试通过后,进行软件集成测试,验证各个模块之间的接口和数据交互是否正确。集成测试通常在PC仿真环境下进行,使用工具如Cantata等。软件集成测试完成后,进行硬件在环测试(HIL),在实际硬件环境中验证软件的功能和性能。HIL测试使用实际的汽车零部件和测试台架,通过发送真实的CAN信号来测试ECU。整个测试过程遵循V型开发流程,从需求分析到设计、编码、测试,每一步都紧密相连,确保软件的质量和可靠性。通过严格的测试,可以及时发现并修复潜在的缺陷,提高汽车电子系统的安全性和稳定性。总之,汽车ECU软件测试是一个系统性、多层次的过程,涉及需求分析、设计、编码、测试等多个环节。通过遵循ISO26262等标准,采用专业的测试工具和方法,可以有效地提高软件质量,保障汽车电子系统的安全运行。
这篇文章简单聊一聊汽车ECU软件的测试。无论你是从事汽车软件工程的哪一个职位,都应该对软件测试的基本概念和流程有一定的了解。所以我想感兴趣的同学应该会不少吧。
我们就以ISO26262软件部分描述的V型开发流程为线索,举一个实际例子来说明。
1
先编一个需求
假设现在我写了一个系统级的需求(SystemRequirement),也就是图1里的“TechnicalSafetyConcept”:(这里多说一句和测试无关的话,所有的TechincalSafetyConcept都是系统级需求,不是软件需求,面试的时候别搞混了)SystemRequirementTheAdaptiveCruiseControl(ACC)functionshallonlybeactivewhentheego-vehicleistravelingbetween30kphand120kph.[ACC-SysReq001]OnceACCdeactivated,itcannotresumeautomatically.[ACC-SysReq002]这家车企比较怂,它的自适应巡航功能只能在30公里到120公里每小时之间激活,并且一旦退出后不可再自动激活。为了简单起见,我们先不管第二条需求了,只看第一条。下面我把这个系统需求写成软件需求(SoftwareRequirement):SoftwareRequirementThesignalACCActiveStateshallbesettoREADYifthefollowingconditionsarefulfilled[ACC-Req001]:
ThesignalACCActiveStateshallbesettoSUPPRESSEDifthefollowingconditionsarefulfilled[ACC-Req002]:
再接下来软件设计文档里,也就是图2的ArchitectualDesign里可以写:DesignRequirementAcc_ActStshallequaltoREADYif:
Acc_ActStshallequaltoSUPPRESSEDif:
好了,这就是个最简单的需求例子。根据这个需求,你写了几行代码来实现。我们假设用C代码,在原有的C文件acc.c中加入了:
有同学可能会说,你有病啊写成这样,第一个if语句写完了直接写else不就完了嘛。对,但是我也不知道客户以后会怎么改这个需求,也许会对其他速度段增加新的状态,所以我就先写个elseif在这里,方便以后扩展。到这一步,”V”模型的左半边你就做完了,现在我们开始来测试。
2
单元测试
写完代码编译成功以后,先开始进行单元测试,也就是图中的“SoftwareUnitVerification”。顾名思义,就是把你这个新编写或者修改过的单元(单独的C文件,在本例中是acc.c)与整个工程隔离开,单独测试其输入输出。
图3.单元测试只关心某个具体的软件单元汽车行业呢,首先就是做MISRA规则测试。MISRA测试是静态测试的一种,用来检验代码是否符合一系列具体的编程规则。这里我们假设用的测试工具是QAC。就我写的这段,估计啊会报出一个warning,因为“else”这个分枝事实上是无法触发的,而MISRA的其中一个规则就是所有代码都必须可触发,所谓“Accessible”。当然啦,这里我是有意为之,所以可以注释一下就放过去了。下一个步骤是动态测试,这里我们假设选用的工具是Polyspace。Polyspace可以帮助判断算法在计算过程中,会不会产生诸如数组index超范围、overflow、被除数是零之类的bug。我们这个例子中只有逻辑判断,所以其实不需要做动态测试。接下来进行功能测试。在功能测试中,我们要:
编写测试集的一个基本原则是要把所有的代码都覆盖到,并且尽量测试所有判断逻辑。上面所示的例子非常简单,只有一个输入变量SafeVehSpd和一个输出变量Acc_ActSt。我们需要把输入变量按判断逻辑分成若干个EquivalentClass。在这个例子中,(假设SafeVehSpd是Unsignedint型,速度范围的上限是500kph)输入信号SafeVehSpd就可以分成三个EquivalentClass:
于是在这三个EquivalentClass里随机各取一个值,就能测试所有代码逻辑了。但是实际测试中,我们往往还进一步要求进行边界测试,也就取每个EquivalentClass的两端的值来进行测试。这就涉及到精度问题了。假设这段代码是定点运算,车速数值由10bit表示,前述车速上限是500,于是车速的精度就是500/(2^10)=0.48828125。所以严格来说,测试集需要测试的输入变量SafeVehSpd的值有6个,分别是0,29.5117188,30,120,120.48828125,500。当然,现在很多工具支持自动生成测试集,所以不用程序员费劲巴力的去算这些破玩意儿了。需要说明的是,就算进行了完善的功能测试,也并不能保证功能就没有bug….因为实际工程中中各种输入信号的组合是无穷无尽的,再加上时序等等因素,功能测试不可能穷尽所有的实际情况,我们只是尽力而为。汽车行业比较流行的单元测试工具有Cantata、VectorCAST等等。
3
软件集成测试
单元测试完成以后,就要把测试好的软件单元放到整个工程里来测试。这一步对应了图1中的“softwareverificationandintegration”。
图4.集成测试关注整个系统的输入输出
在单元测试中,我们通过直接改变SafeVehSpd的值来进行测试。而事实上,SafeVehSpd数值的源头,来自CAN总线上的车轮轮速数据。
假设如图3所示,从轮速传感器,由CAN总线传来的原始车轮轮速信号WheelSpdRaw先经过通信接口模块COM_IF.c处理,再经过车速计算模块VehSpd.c计算以后,才得到信号SafeVehSpd。那么在集成测试中,我们需要通过更改WheelSpdRaw这个信号的数值来对acc.c中的代码进行测试。
这是为了验证acc.c模块和其他模块的接口是否正确以及各个模块之间是否有冲突。进行软件集成测试的时候,图示的三个模块其实合并在了一起形成了一个“黑盒”,我们只关心最初的输入信号WheelSpdRaw和最终的输出信号Acc_ActSt之间的逻辑。在实际工程中,COM_IF.c、VehSpd.c和Acc.c三个模块很可能是由三个工程师在同时并行开发的,这就可能导致任何一个模块单独进行集成测试都通过不了。
这时候就需要由项目经理或者productowner提前进行沟通协调,确保所有功能都更新以后,三个模块一起进行集成测试。软件集成测试流行的工具和单元测试一样,也是Cantata之流。软件单元测试和软件集成测试都可以被称为软件在环测试(Softwareintheloop,SIL)。
4
硬件在环测试(HIL)
软件在环测试完成以后,下一个步骤就是硬件在环测试(Hardwareintheloop,HIL),对应了图1中的“Testingofembeddedsoftware”。
有一些企业在HIL之前还会进行一次PIL(Processorintheloop)测试,这里就不讨论了。HILtest也是集成测试的一种。
前面说的软件集成测试,是运行在PC仿真环境中的,而实际ECU无论是算力、内存、各种硬件性能等等方面和PC环境都有很大的不同,所以相同的功能还要继续在实际硬件环境中再测试一遍。也就是说,HILtest与软件集成测试最大的不同在于,前者运行于实际硬件中,而后者只是运行在计算机仿真环境下。
硬件在环测试的主要工具是实际的零部件。比如测试ACC功能的话可以是ADAS控制器,或者是集成了ACC功能的毫米波雷达、摄像头等。除此之外还要有一个实验台架提供必要的运行环境、电力供应和总线接口。
常用的HILtest工具比如dspace的那些死贵死贵的测试环境,dspacecontroldesk。
和软件集成测试一样,HILtest也是改变原始的CAN信号(例子中的WheelSpdRaw)来进行测试,只不过,这一次不是直接改变WheelSpdRaw在内存中的数值,而是通过HILtest台架真的向ECU通过CAN发送真实的WheelSpdRaw信号。
HILtest的测试集,也就是测试用例(testcase)需要和软件需求SoftwareRequirement严格对应,可以是一对一,一对多或者多对一都可以。所有的HILtestcase都必须根据一条对应的SoftwareRequirement写出,但是条件就没有单元测试时候那么苛刻了。
比如为了测试需求ACC-Req001,HILtestcase可以写成:
TurnECUon;
需要把trigger和recover的情况都覆盖到。事实上这个测试用例也可以用来测试ACC-Req002,这就是“一对多”的情况。
素材来源:汽车电子与软件
文章内容由网络素材及资料整理,如有涉及版权纠纷请告知
以上内容由58汽车提供。如有任何买车、用车、养车、玩车相关问题,欢迎在下方表单填写您的信息,我们将第一时间与您联系,为您提供快捷、实用、全面的解决方案。
原创文章,作者:58汽车,如若转载,请注明出处:https://car.58.com/7018647/