
通信:跨Core读取信号,Signal值偶发反转
汽车嵌入式中,通信功能扮演着"地基"一样的角色,没有通信功能,也就无从谈论诊断、网络管理、标定等其他功能。其中,算法(Functional algorithm)对通信的依赖,就好比鱼和水。同时,算法对通信信号质量的要求也非常高,如果通信信号异常,将极大的影响着算法信号输出,进而影响车辆功能。输入信号和Functional algorithm关系示意如下:
所以,工程上的通信问题,不可掉以轻心。本文分享一个工程通信问题:Signal信号值偶发反转。
1、问题现象
工程开发,各层或者各模块之间需要信息交互,正确的信息交互是功能正常的前提。本文问题中,发现:底层软件(BSW:Basic Software Modules)与上层(ASWC:Application Software Components)接口交互时,出现Signal反转问题。BSW与ASWC接口交互过程示意如下:
1. 首先,BSW接收总线(BSW)发送的信号(Signal A)并缓存到BSW缓存区(BSWBuffer);
2. 之后将BSW缓存的数据Copy到ASWC缓存区(ASWCBuffer),即:BSWBuffer->ASWCBuffer,这也就是我们常说的接口交互;
3. ASWC从ASWCBuffer获取Signal A进行算法运算处理。
提示:标准的Autosar架构中,BSW和ASWC通过RTE(Run-Time Environment)交互。目前,一些项目,为了沿用之前的模型,并未完全采用Autosar模式开发,因此,信号交互会手动处理,而手动处理可能就不如规范考虑的周全,存在一定漏洞,比如本文。
(一)问题现象
问题出现时,发现在某些时刻,BSW从总线获取的Signal A值与ASWC实际获取的值不匹配,如下所示:
而且,问题会偶发出现多次,如下所示:
2、原因分析
(一)信号字节序转换
根因分析之前,先回顾一下信号的传输。一个信号的长度可能在一个字节内,也可能跨字节。如下图,信号AgDataRawSafe_UB只占用一个bit,传输时不跨字节,而AgDataRawSafeRollRate信号长度16bit(2 Byte),传输时跨字节。
所以,当一个信号长度超过一个byte时,则需要考虑字节序(Byte Order)转换。在通信矩阵设计之初,每帧报文的每个信号字节序需要明确定义,即:Motorola(摩托罗拉格式)或者Intel(因特尔格式)。
- Intel模式也称为小端(Little-endian)模式,传输时,低字节在前,高字节在后;
- Motorola格式也称为大端(Big-endian)模式,传输时,高字节在前,低字节在后。
通信矩阵(*.dbc文件)中,Motorola信号格式设置如下:
(二)问题剖析
出现问题的信号长度(2 Byte)>1Byte,所以,当信号接收以后需要进行字节序转换。分析其中一个信号发现:BSW接收的信号值为5696(0x1640),而传递给上层时确实16406(0x4016),如下所示:
所以,问题定位到了信号字节序处理位置。进一步分析问题发现,工程中,Core2读取信号值(包括信号的Copy动作),Core0进行信号处理(包括信号接收、字节序转换)。
示意如下:
正常工况下:
1. Core0接收信号并缓存到驱动层,此时数据是原始数据(Raw Data),还未传输给目标上层;
2. Core0将信号传输给目标上层(eg:COM),读取信号时,本文的Com_ReceiveSignal()接口对Signal进行字节序转换处理,即:0x4016->0x1640;
3. Core0将信号处理后,Core2将处理后的数据Copy到缓存区(Copy的数据正常,0x1640);
4. Core2读取信号值在有效范围,算法正常处理,程序不出问题。
非正常工况下:
1. Core0接收信号并缓存到驱动层,此时数据是原始数据(Raw Data),还未传输给目标上层;
2. T1时刻,Core0将信号传输给目标上层(eg:COM),进行Signal字节序转换处理时,Core2恰好过来读取该信号值,由于此时Core0还未有对信号进行字节序处理,依然是原始值(eg:0x4016),Core2此时读取到的值为0x4016,而不是预期的0x1640。因此,算法识别到信号输入异常,进行异常处理,车辆功能受限。
思考:Core2除了可能读取到未经字节序转换的信号值,还可能读取到0值(中间临时变量)。本文的软件处理过程中,COM内部会有中间变量先缓存原始值,在缓存原始值之前会有清0动作,所以,数据异常可能出现0或者字节序未转换情况。
提示:每家Autosar软件供应商在实现Autosar规范时,可能存在一定差异,按照Autosar规范,Com_RxIndication()中进行信号字节序转换,如下图。而上述问题代码中,却是在Com_ReceiveSignal()接口中进行的字节序转换,和规范存在一定偏差。
3、解决措施
解决措施:增加缓冲区,确保Core2读取的数据经过字节序转换。
(一)如何理解增加缓冲区?
在Autosar架构中,ASWC在获取信号值时,最终会调用COM模块的Com_ReceiveSignal()接口获取信号值。而本文获取信号值的过程中,需要对信号字节序的转换,Com_ReceiveSignal()接口原型如下所示:
代码层面,一个uint16信号的字节序转换会移位操作,本文示例信号的移位动作如下:
而问题代码中,示意如下:
void Handler_Signal_Rx(void)
{
void)Com_ReceiveSignal(BSWBufferID_Rx, &BSW_Buffer);
}
如上代码,动作如下图:
如果BSW BUFFER恰好执行到字节序转换的位置,Core2上有Copy数据动作,那么,Core2获取的数据就是未经有效字节序转换的数据,出现上述问题。
为什么增加缓存就可以有效解决问题呢?增加缓存以后,数据Copy动作如下图,即:Core0只有将信号进行字节序转换后,再放入中间缓存区,而Core2每次Copy数据时,只从中间缓存区Copy转换后的数据,示意如下:
对应到代码实现如下所示:
void Handler_Signal_Rx(void)
{
uint16 temVal = 0x00;
(void)Com_ReceiveSignal(BSWBufferID_Rx, &temVal);
BSW_Buffer = temVal;
}
问题延申:
既然涉及到核间通信,使用Spinlock(自旋锁)不可以吗?答:需要根据项目实际。如果核间交互信号量小,使用spinlock未尝不可,但是,如果对上百个信号都使用spinlock,不仅增加了资源消耗,也会更影响CPU效率。
文章转载自公众号:开心果 Need Car
