目录
3.1 firstCall中初次调用(1)和后续调用(0)的区别:
0 前言
因为之前喜欢偷懒直接用CAPL的内置CRC函数来做计算,但是最近发现这个函数有些鸡肋的地方,拿出来记录一下,分享给大家。
1 CRC函数简介
在CAPL中,有以下的CRC函数可以选择,每个函数具体根据的是哪个多项式在Help文档中都可以看到。
比如说Crc_CalculateCRC8()函数用的是AUTOSAR Profile1的多项式来进行计算的,实际根据项目自行选择所需要的函数。
2 抛出问题
以Crc_CalculateCRC8()为例,其语法主要如下所示:
long Crc_CalculateCRC8 (byte data[], dword dataSize, dword dataOffset, dword crcLength, dword crcStartValue, dword firstCall, dword& crcCalculated);
使用CAPL的内置函数Crc_CalculateCRC8做计算,为什么算出来的结果和我直接使用AUTOSAR Profile 1里的算法结果算出来是不一样的,代码及结果如下图所示
从图中可以看到CRC和CRC1的结果并不一样,需要提前说明的是0x37是正确的结果。 而是用Crc_CalculateCRC8函数算出来的0x4B是错误的。这是为什么呢?
3 解决问题
这是因为在Autosar Proile1中CRC有两种算法,分别是CRC-8-SAE J1850和 CRC-8-SAE J1850 zero,来源如下图:两者的初始值与异或值是不同的。为了分辨,将初始值和异或值为0x00的多式定义为CRC-8-SAE J1850 zero。Crc_CalculateCRC8()一般默认为CRC-8-SAE J1850的多项式。
如果想使用Crc_CalculateCRC8()来实现CRC-8-SAE J1850 zero的多项式,需要设置参数crcStartValue为0xFF,firstCall为false,最后再和0xFF进行异或。如果感兴趣为什么要这么做的朋友可以直接调到3.2节。按照这个方法生成的CRC就是0x37了。
on key 'c'
{
long retval;
dword crc;
byte data[9] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};
const dword firstcall =1;
const dword subsequentcall =0;
retval = Crc_CalculateCRC8(data, elcount (data), 0, elcount (data) , 0xff, subsequentcall, crc);
crc = crc^0xff;
write("CRC of data: 0x%X", crc);
}
函数主要参数如下图所示:
data | Payload data for which the checksum is to be calculated. |
dataSize | Length of data block to be calculated in bytes. |
dataOffset | Start index for the calculation of the CRC in the payload data. |
crcLength | The length of the data for the CRC is calculated. |
crcStartValue | CRC initial value depending on whether it is the first call or a subsequent call. Value is ignored if firstCall is 1. |
firstCall | Flag for first call or a subsequent call. Possible values are 0 (subsequent call) or 1 (first call). |
crcCalculated | Calculated CRC8 value. |
上述的 firstCall和crcStartValue含义需要做重点了解,因为这是转换多项式的关键。
3.1 firstCall中初次调用(1)和后续调用(0)的区别:
二者的区别演示如下图所示:
First call分为first call和subsequent call两种模式
First Call:
- CRC计算从初始值开始,通常由正在使用的CRC标准指定(例如,0x00或0xFF)。
- 对输入的数据进行处理,并根据初始值计算CRC值。
Subsequent Calls:
- 如果继续使用新数据进行CRC计算,该函数将使用上一次计算的CRC值作为起点。
- 这允许CRC积累多个数据块,确保连续性的CRC计算。。
- 本质上,First Call:用初始化CRC计算,而Subsequent Calls根据先前的结果累积CRC值
参数crcStartValue是否作为初始值生效取决于First cal,如果是subsequent_call,就生效,如果是first call,start value默认是0:
3.2 函数Crc_CalculateCRC8定义的多项式
它的初始值和异或值都是0xFF,如果想实现CRC-8-SAE J1850 zero的多项式,就需要将初始值和异或值都变为0x00,就不能将frist call参数设置为1,因为这样的话初始值0xFF就会被使用,因此frist call应该被设置为0。crcStartValue 参数这时派上用场。crcStartValue 设置为0xFF, firstCall = false,得到新的初始值0x00。然后对crc的结果与0xFF进行异或,以取消之前的0xFF异或,使最终结果为0x00的异或。
简单来说:
1.firstCall = false和crcStartValue=0xFF,以便获得0x00的实际初始值
2.对函数调用的结果应用0xFF异或,以撤销CRC_Calculate8的最终异或
如果有那里不足还请各位大佬多多指正,最后打个广告,如果有需要加入HIL自动化测试群的小伙伴们欢迎评论或私信我,大家一起多多交流多多进步。