英文:
How to match CRC32 algorithms working on various data sizes
问题
我有一个设备,它向发送的数据添加CRC32校验和。它是使用查找表计算的,如下所示:
uint32_t CrcFromBuffer(uint8_t* buffer, uint16_t length) {
uint32_t crc32 = 0xffffffff;
if (buffer == NULL) {
return 0;
} else {
while (length != 0) {
uint8_t crc32_table_index = ((uint8_t)(crc32) ^ (*buffer));
crc32 = crc32 >> 8;
crc32 = crc32_table[crc32_table_index] ^ crc32;
buffer++;
length--;
}
}
return ~crc32;
}
我正在使用STM32F401微控制器,它具有硬件支持,可以使用相同的多项式计算CRC,但只能处理32位输入数据大小。如果数据长度是4字节的倍数,它可以正常工作。这是一个示例:
bool eight_bytes_random_crc() {
uint8_t array8[8] = {0xAB, 0x21, 0x32, 0x47, 0x01, 0xFF, 0x00, 0x99};
uint32_t array32[2] = {__RBIT(0x473221AB), __RBIT(0x9900FF01)}; // 需要反转位顺序
uint32_t hard_crc = __RBIT(~HAL_CRC_Calculate(&hcrc, array32, 2)); // 再次反转位并取反结果
uint32_t soft_crc = CrcFromBuffer(array8, 8);
return hard_crc == soft_crc;
}
如何使用STM32硬件CRC支持非4字节倍数长度的数据数组?
我尝试通过蛮力搜索一个值,该值会为单字节产生相同的CRC,但在给定0xAB输入的情况下,找不到明显的方法来获得该值:
uint32_t one_byte_crc() {
uint8_t array8[1] = {0xAB};
uint32_t soft_crc = CrcFromBuffer(array8, 1);
for (uint32_t i = 0; i <= 0xFFFFFFFF; i++ ) {
uint32_t array32[1] = {__RBIT(i)};
uint32_t hard_crc = __RBIT(~HAL_CRC_Calculate(&hcrc, array32, 1));
if (hard_crc == soft_crc) {
return i; // 得到0xF7D1D97E
}
}
}
如何在数据数组的长度不是4字节倍数的情况下使用STM32硬件CRC?
英文:
I have a device that adds a CRC32 checksum to data it sends. It is calculated using a lookup table as follows:
uint32_t CrcFromBuffer(uint8_t* buffer, uint16_t lenght) {
uint32_t crc32 = 0xffffffff;
if (buffer == NULL) {
return 0;
} else {
while (lenght != 0) {
uint8_t crc32_table_index = ((uint8_t)(crc32) ^ (*buffer));
crc32 = crc32 >> 8;
crc32 = crc32_table[crc32_table_index] ^ crc32;
buffer++;
lenght--;
}
}
return ~crc32;
}
I'm using an STM32F401 microcontroller, which has hardware support for calculating CRC with the same polynomial but only with a 32-bit input data size. It works fine if the data length is a multiple of 4 bytes. Here's an example:
bool eight_bytes_random_crc() {
uint8_t array8[8] = {0xAB, 0x21, 0x32, 0x47, 0x01, 0xFF, 0x00, 0x99};
uint32_t array32[2] = {__RBIT(0x473221AB), __RBIT(0x9900FF01)}; // need to reverse bit order
uint32_t hard_crc = __RBIT(~HAL_CRC_Calculate(&hcrc, array32, 2)); // again reverse bits and negate the result
uint32_t soft_crc = CrcFromBuffer(array8, 8);
return hard_crc == soft_crc;
}
How can I use the STM32 hardware CRC support for data arrays with a length that is not a multiple of 4 bytes?
I tried a brute-force search for a value that would produce the same CRC for a single byte but couldn't find an obvious way to get that value, given only the 0xAB input:
uint32_t one_byte_crc() {
uint8_t array8[1] = {0xAB};
uint32_t soft_crc = CrcFromBuffer(array8, 1);
for (uint32_t i = 0; i <= 0xFFFFFFFF; i++ ) {
uint32_t array32[1] = {__RBIT(i)};
uint32_t hard_crc = __RBIT(~HAL_CRC_Calculate(&hcrc, array32, 1));
if (hard_crc == soft_crc) {
return i; // gives 0xF7D1D97E
}
}
}
Any suggestions on how to use STM32 hardware CRC for non-multiple of 4 byte length data arrays?
答案1
得分: 4
你唯一能做的就是要么a)使用硬件来计算你的数据的CRC直到四字节的倍数,然后使用软件来完成CRC,处理剩下的0到3字节,或者b)使用硬件来计算所有数据的CRC,用零填充到四字节的倍数,然后使用逆CRC表来取消CRC中的最后0到3个零。最高效的可能是如果剩下0或1个字节,就选择a),如果剩下3个字节,就选择b),这样可以取消1个字节的计算。如果剩下2个字节,你会选择更快的方法,但我不确定哪种方法更快。可能两种方法都可以。
英文:
The only thing you can do is either a) use the hardware to calculate the CRC up to a multiple of four bytes of your data, and then use software to finish up the CRC with the last 0 to 3 bytes, or b) use the hardware to calculate the CRC of all of your data padded out to a multiple of four with zeros, and then use a reverse CRC table to un-calculate the last 0 to 3 zeros from the CRC.
The most efficient might be to use a) if there are 0 or 1 bytes left, and b) if there are 3 bytes left, so un-calculating 1 byte. For 2 bytes left, you'd pick the faster one, but I'm not sure which one that would be. Could go either way.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论