我实现的大多数CRC都是将计算出的CRC值附加到消息(有效载荷)中,并在所有字节(包括CRC值)通过CRC寄存器后在接收器处检查零结果。显然,这是一种相当标准的方法。
现在我想使用一种不同的方法:
- 根据有效载荷计算一个值
- 在消息字节(有效载荷)通过CRC寄存器馈送使得有效载荷的最后一个字节之后的结果将为零
做到这一点的最佳方法是什么?一个人是否有一个好主意或一些可以深入挖掘的线索?
ps:我为什么要这么做?在一些应用程序(ROM)中,我无法附加数据,因为数据存储在ROM地址空间的末尾。所以我想预加载CRC寄存器或将值预加载到消息中。
我现在已经为上述问题编程了一个解决方案,它比我最初想象的更容易。
我发现了几篇关于如何伪造CRC的文章。这意味着如何修补数据,使计算出的CRC值具有预定义的价值
使用这种方法,我只需要使用实际有效载荷作为CRC值,这是非常明显的。
最后,我只需要使用我的有效载荷数据来计算"反向"CRC。此计算的结果是当计算CRC。
当我在一个内存非常有限的系统上工作时,我减少了具有256个条目(CRC32为1024字节)的CRC表到16个条目(64个字节),现在分两步处理每个字节仍然比移位比特快得多。
// Reverse CRC table for Castagnoli polynomial (0x1EDC6F41)
static const unsigned long crc32c_revTable[16] =
{
0x00000000L, 0x05EC76F1L, 0x0BD8EDE2L, 0x0E349B13L,
0x17B1DBC4L, 0x125DAD35L, 0x1C693626L, 0x198540D7L,
0x2F63B788L, 0x2A8FC179L, 0x24BB5A6AL, 0x21572C9BL,
0x38D26C4CL, 0x3D3E1ABDL, 0x330A81AEL, 0x36E6F75FL
};
unsigned long calcReverseCRC32C(unsigned long crc32c,
const unsigned char* pData,
unsigned long len)
{
while (len--)
{
crc32c = (crc32c << 4) ^ crc32c_revTable[crc32c >> 28];
crc32c = (crc32c << 4) ^ crc32c_revTable[crc32c >> 28];
crc32c ^= *pData--;
}
return crc32c;
}
用法:
{
// This array contains test data with 4 bytes CRC appended
// The result of CRC-32C calculation using this data is zero
unsigned char arr[] = {'1', '2', '3', '4', '5', '6', '7', '8', '9',
0x7c, 0x6d, 0xf9, 0x1c};
unsigned long expectedResultOfCRC = 0;
unsigned long init = calcReverseCRC32C(expectedResultOfCRC,
&arr[sizeof(arr) -1],
sizeof(arr) );
}