目录
1.概述
2.基于Flash的标定
3.基于RAM的标定
4.AUTOSAR基于指针标定概念
5.小结
1.概述
最近有朋友问到是否用overlay标定完数据就直接写在Flash中,其实不然,是需要关闭overlay然后通过XCP Program指令集或者UDS刷进Flash。
从这里看出,之前文章对于标定的描述还是不够细致,导致出现了误会,因此这里再详细分析一下标定的概念。如有错误,请大家指正。
我们知道,标定参数(即Parameter)实际上对于ECU的控制算法来说是一个常数,最简单的例子,油门踏板开度影响喷油量,假设算法为y= ax+b。要在某个固定踏板开度(x)达到我们预期喷油量(y),要反复调整的只能是常数a和b。
因此,所谓参数的标定,就是通过技术手段保证在ECU的开发阶段能够调整paremeter的值。那么我们就来看看有哪些技术手段可以实现参数的调整。
2.基于Flash的标定
我们在开发的时候,对于常数其实会用修饰符进行限定的,如下:
const uint32 Parameter_A = 1;
在进行编译链接之后,编译器会把这个Parameter_A分配到Flash的区间(链接文件里的ROM段)并给定一个地址(通过Map文件可以查找),同时也从编译出来的hex的地址去找到这个值 1,如下图所示:
那么要修改这些参数,应该怎么办呢?有两个办法:
- 通过在源码中修改常数值,重新进行编译,然后刷进ECU里。这样很麻烦,遇到稍微大一点的工程,编译都得十几二十分钟,很显然这种方法是不符合现在的开发流程的。
- 通过FlashDriver对存放Paremeter_A的Flash空间进行重编程,这种方式比上述重新编译要好一点,但是还是实时性不够,并且目前的FLash特性是没有办法按照Byte进行擦除的,意味着要修改一个标定参数就必须擦掉整个Sector,重新刷写所有的标定参数,这显然是不可接受的。当然,如果ECU外挂的EEPROM,那么就不会存在这个问题了,但是访问速度和相应的开发成本也是阻碍参数的实时标定。
另外,还需要提一点的就是,如果编译器优化等级开的比较高,作为常量的Parameter_A有可能会被优化,直接作为一个数值出现嵌入到代码中,而不会出现在map文件里。因此我们在定义标定参数这种类型常量时,通常会按照如下定义:
volatile const uint32 Parameter_A = 1;
volatile可以有效防止被编译器优化;
此外,为了方便管理和能迅速定位到标定参数,我们通常也会在链接文件里定义一块单独的空间,在代码里使用#pragma把参数放到该空间里,如下:
#pragma section "Cal_Flash"const uint32 Parameter_A = 1;
这里我们简单讲了标定参数只在Flash里的时候应该如何修改,实际上这种方式并不能支持我们在ECU运行过程中动态修改,所以,我们能不能想个办法把这些参数搬到一段RAM中,在RAM里实时修改,修改完成后再把标好的参数重新刷进Flash。
显然这个想法是成立的。
3.基于RAM的标定
我们定义一个带初值的变量,如下图:
uint32 Parameter_A = 1;
编译器会给这个参数分配RAM空间地址,并且初值存放在Flash中。我做过一个试验,用英飞凌TC2xx系列,在不修改链接文件的情况下,编译器给标定参数分配一个RAM地址,但实际上存在Flash里,如下图:
这是怎么实现的呢?我们查看链接文件关于.data段的定义:
这行代码的含义就是加载运行在RAM(DSPR),但是初值存放在PFlash,上电时启动代码会将Flash中的值拷贝到RAM里。
控制算法去获取Parameter_A的值也是从RAM去拿值的,所以这种情况我们就可以在ECU运行过程中动态修改标定参数的值。
这个时候还不是完全体,通常我习惯是拿出一段单独的Flash空间方便标定数据的管理,借鉴上面链接文件的修改,就可以在RAM和Flash单独定义一块空间专门给标定使用,因此在链接文件里有了如下定义:
#pragma section "calDataOvc"const uint32 Parameter_A = 1;
但是这样又有一个问题,因为标定数据的地址是RAM地址,那么使用标定上位机导出的标定数据hex文件还是RAM的空间。这个时候我们想要把标定数据刷到Flash,还需要对hex文件做一个地址的偏移,最后通过UDS或者XCP自带编程指令集进行刷写。
这也比较麻烦,所以英飞凌、NXP均针对这个问题实现了memory overlay的功能。
4.AUTOSAR基于指针标定概念
在AUTOSAR RTE的SWS里,明确提出来标定和测量功能的支持,如下图:
在XCP文档里提出来基于指针标定的概念,其具体实现形式如下:
标定参数的访问地址和数据大小在启动阶段被收集到Pointer Table,最开始均是该Table中收集到的均是参数的Flash地址,并且通过软件给Flash里的参数分配RAM地址,但是此时RAM还是没有内容填充的。
注意,这个时候A2L文件里面标定量的地址为Flash地址,当它下发一个download命令后,在XCP Slave这一层首先会检查当前处于WP还是RP,如果是WP,那么此时就Pointer Table就选择使用该标定量对应的RAM地址(对用户不可见),然后进行填充,此时算法获取标定量就通过RAM,从而实现了标定动态修改参数的功能,如下:
这个方案的提出就是为了解决某些标定软件在A2L文件里只识别Flash地址的参数,但是确定很明显:多了一个Pointer Table增加了RAM消耗,同时为了防止内存泄露,本身装标定量的RAM空间也是需要空出来的。
目前,我还没有使用过这种方式。
5.小结
本文主要梳理了标定的概念,目前使用的比较多的还是基于RAM的标定,同时只要芯片支持overlay(Flash emulation),上位机可以直接使用标定参数的flash地址,在MCU内部硬件自动进行地址重映射,需要注意的是,即使使用Overlay功能,标定参数的修改始终针对是RAM里的值,如果想要固化到Flash里面,有两种方式:
- 上位机通过XCP 编程指令集进行刷写,ECU端需要关闭Overlay,保证访问的是Flash。CANape方便一点,INCA的话还需要自制ProF文件
- 通过上位机将标定数据导出为Hex,通过UDS直接刷写进Flash。