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?