|
摘要: 在遵循ISO 26262三层安全架构下,汽车控制器位于第二层的扭矩监控功能软件开发中,对参与计算的输入/输出变量提出更高的安全要求。底层接口是基于安全内存开发的定点接口,上层基于Simulink开发的浮点数扭矩监控模型生成的C代码,在二者进行软件集成时会发生冲突。通过几种解决方案的对比,优选出一种通过修改TLC脚本控制TRW代码生成的解决方案,从而实现了对Simulink建模开发工程师无任何额外工作的负担,满足ISO 26262对安全功能的要求,同时成功解决底层软件与控制策略层开发的矛盾,在项目中获得了良好的应用效果。
关键词: 定点数;浮点数;ISO 26262;安全内存
Abstract: There are more rigorous safety requirements on input and output variables when developing automotive controller torque monitor function to meet the second level requirement of the 3 level safety structure defined in ISO 26262. Low level software only supports fixedpoint variable input, and C code generated by torque monitor algorithm model developed via Simulink only supports the floatingpoint variable. There is a conflict when compiling the two parts to generate the executable file. One method that rewrites the TLC scripts to control the generated code by Simulink RTW tools is selected after comparing several solutions. A big progress that the solution has not any extra work to Simulink modeling engineer, meets ISO 26262 safety function requirements, at the same time successfully solves the conflict of low level software and algorithm models.
Key words: fixed-point; floating-point; ISO 26262; safety RAM
引言
在现代的汽车电子控制器开发中,普遍采用了国际知名供应商开发的硬件控制器和包括Bootloader、符合OSEK标准的实时操作系统,以及底层硬件驱动等底层软件,并提供相应的软件接口层给上层控制策略应用软件。但根据底层软件因不同的硬件设计而不同的特点,以及考虑到代码执行效率的原因,多采用定点手写代码来完成。
而随着微电子技术的不断进步和电子芯片价格的不断下降,越来越多的控制器已支持32位带浮点数运算单元的解决方案,这就为基于模型的控制算法的开发提供了广阔空间。
1 ISO 26262三层安全架构
1.1 架构简介
在最新的ISO 26262(汽车行业功能安全标准)中对控制器的三层安全架构要求如下:
① Level1实现动力系统管理功能,如转换动力系统请求扭矩、零部件监控、输入/输出变量诊断及在错误确认时控制系统响应。
② Level2负责监控Level1功能软件缺陷,如监控计算的扭矩值或车辆的加速度值,如果检测到此类错误将触发系统错误。
③ Level3监控模块独立于Level2和Level1,通过应答机制监控Level2和Level1层软件是否正常运行,如错误发生将触发独立于功能控制器的系统错误。
1.2 ISO 26262在扭矩监控软件的应用
根据ISO 26262三层安全架构的阐述,第二层负责监控第一层与安全相关的功能,与安全相关的输入变量的值在被第一层软件读取的同时也要被第二层监控软件读取,且要有冗余备份。例如,通过监控计算的或车辆加速时的扭矩输出,当第二层监控模块计算扭矩与第一层功能层计算扭矩不一致时,会引起控制系统故障响应。
根据以上安全相关需求,在设计扭矩监控模块TQM时,极大地提高了对参与计算的输入/输出变量的安全性的要求,由此引入了安全内存(Safety RAM)。下面首先介绍底层软件中基于定点数的安全内存的实现原理。
2 基于定点数的安全内存应用
2.1 安全内存工作原理
与安全有关的RAM中的数据在防止信息丢失、读写能力的保护等方面需要额外的保护。基于这个原因,将双倍的RAM内存区用于软件比较和读/写测试可大幅提高数据的安全性。地址空间在两个内存区域复制,原始数据存储在第一个内存区域,第二个内存包含补充信息,将与第一块内存区并行访问。在输出时比较两块内存的数值,如果发现任何偏差,会产生一个复位。为了检测特定类型的位错误,在第二个内存区域的数据存储采用二进制补码的形式。一般安全内存支持访问下列类型:不受中断保护的访问类型、写入或读取的安全内存数据、中断保护的访问类型。需要写入或读取相关数据的安全保护。
在当前的底层,基于定点数接口说明如下:存储到安全内存区变量定义,分为变量的源地址定义与补码地址定义,分别存放在两处非相邻内存区;读取存储在安全内存区的变量参与逻辑运算的接口RdSafetyRam32(&Var),当这个接口被调用时与存储在源码区与补码区的值进行比较,如发现任何不一致将导致系统错误发生;存储变量到安全内存区接口函数为WrSafetyRam32(&Var,com_var),通用内存区变量com_var的当前值将分别存放到Safety RAM区变量var的源码地址区和补码地址区。
2.2 安全内存接口典型应用
/*定义存储到安全内存区变量源址定义*/
#define SECTION SAFRAM
uint32 Var1;
/* 定义存储到安全内存区变量二进制补码地址定义*/
#define SECTION SAFRAM_CPL
uint32 Var1Cpl;
/*典型应用*/
/*读经过校验的uint32安全内存变量*/
Saf_var1 = RdSafetyRam32(&Var1);
Saf_var1 = Saf_var1 + val;
/* 写安全内存变量 */
WrSafetyRam32(&Var1,Saf_var1);
在关于安全内存典型应用的示例中,Var1为定义到安全内存区的变量,同时在安全内存补码区定义了相同变量名,即用后缀Cpl加以区分的补码。RdSaftyRam32(&Var)和WrSafetyRam32(&Var,Common_Var)两个函数分别为读32位变量和写32位变量的接口函数。在读写两个函数中完成变量Var的源码与补码的效验以确保示例中变量Var1的安全,从而提高整个扭矩监控算法的安全等级。
3 针对Simulink浮点扭矩监控模块的解决方案
目前的实际情况是,底层软件提供的接口API函数只支持uint8、uint16、uint32三种数据类型,对于定点数的操作完全没有问题。可是对于基于Simulink模型生成的基于浮点数的C代码,主要应用single的数据类型就没有办法直接应用安全内存的接口函数了,以下是针对这个问题的几个解决方案的比较。
3.1 强制类型转换
single A=32.235;
uin32 B;
强制类型转换为:
B=(uint32)A;
结果会导致B精度损失,不能满足工程需要。
3.2 使用union数据类型
union SafetyRAM_Signal_Type_tag {
uint32 IntegerValue;
real32 Value;
} SafetyRAM_Signal_Type;
SafetyRAM_Signal_Type Val_A;
SafetyRAM_Signal_Type Val_2;
/* 声明安全内存变量Var32Val_A */
#define SECTION SAFRAM
uint32 Var32Val_A;
#define SECTION SAFRAM_CPL
uint32 Var32Val_ACpl;
/*读取安全内存变量 Var32Val_A*/
Val_A.IntegerValue=RdSafteyRam32 (&Var32Val_A);
Val_2.Value=Val_A.Value + 5;
/*写安全内存变量 Var32Val_A */
WrSafetyRam32(&Var32Val_A,Val_2.IntegerValue);
上述代码对应的Matlab模型如图1所示。
图1
该方法通过应用Simulink的SFunction,并通过修改相应的代码生成时的TLC脚本来实现。利用联合体共享数据空间的方式来实现浮点数与定点数的转换。但使用过程中需要定义大量的联合体类型数据,且这些变量经RTW代码生成后为全局变量常驻内存,占用大量的内存空间,且代码可读性差,不适合应用于量产控制器中。同时,因为其变量类型定义也不够灵活,比如定义32位数据类型需要定义一个联合体,16位和8位数据类型则需要重新定义新的联合体,给应用Simulink完成算法开发的工程师带来不便。
3.3 修改TLC代码生成脚本
应用Simulink data store、data read、data write修改相应的TLC代码生成脚本。
/*安全内存区变量声明*/
#define SECTIONSAFRAM
uint32 A;
#define SECTIONSAFRAM_CPL
uint32 ACpl;
/* 从DataStoreRead模块读取安全内存变量A */
Val_A=(Rd Safety Ram32 (&A),*(real32_T *)&A);
Val_2=Val_A + K;
/* 通过DataStoreWrite模块写安全内存变量A */
WrSafetyRam32 (&A,*(uint32 *)&Val_2)
代码对应的Matlab模型如图2所示。
图2
3.4 三种方案优劣比较
对比方案3生成的代码与安全内存接口应用的典型代码,可以发现以下优点:
典型代码只能直接读取uint32类型变量,而由方案3模型生成的代码首先调用底层接口函数,验证定义到安全内存区的变量A的源码与二进制补码是否一致,接下来运用C语言逗号运算法将采用指针取地址的方式把定点数A转换成浮点数赋给变量Val_A。
典型代码把变量写入32位的接口时只能接受uint32的数据类型,而由方案3模型生成的代码则是通过指针取地址的方式把浮点数Val_2转换成定点数赋值给定义到Safety RAM区的变量A,从而保证了变量精度没有任何损失。
方案3通过修改RTW的TLC脚本来控制data store、data read、data write生成代码,从而实现底层定点数和上层策略浮点数的结合,对于开发控制算法的工程师为透明的。同时,对于模型中用到的数据类型无任何限制,可根据开发的需要随意修改,而相对于产生的C代码数据类型定义,则体现为uint32、uint16、uint8 三种数据类型。
方案创新地应用了C语言中的逗号运算符和取地址的方法,解决了数据安全性问题,同时在存储浮点数到定点数,及读取定点数到浮点数的过程中,变量无任何精度损失,很好地解决了上层基于浮点数的模型生成代码和底层基于定点数接口的结合问题,更重要的是解决了扭矩监控功能模块的数据安全性问题。
该方法对建模工程师和负责底层软件与上层控制策略模型的工程师均无任何额外工作,提高了工作效率。
目前该方法已在两个项目中得到应用,并取得了很好的应用效果,可在类似的开发中借鉴。
结语
越来越多的国内OEM厂商已不满足完全委托国际知名供应商开发电子控制系统,而是逐渐开始组建开发团队开发控制器的控制策略,同时委托国际知名供应商开发硬件和底层软件。但开发过程中很可能遇到底层软件提供的接口与上层控制策略模型不匹配的情况,如本文遇到的扭矩监控模型生成代码为浮点数而底层软件接口为定点数的情况。在这种情况下就需要工程师们用创新的方法来解决这一矛盾,以保证后续开发得以顺利进行。
参考文献
[1] Brian W Kernighan,Dennis M Ritchie.C程序设计语言[M].北京:机械工业出版社,2004.
[2] 黄永安, 马路,刘慧敏.MATLAB 7.0/Simulink 6.0建模仿真开发与高级工程应用[M].北京:清华大学出版社,2005.
[3] 国际标准组织(ISO).ISO26262规范汽车行业功能安全标准,2010. |
|