I want to implement CRC8 generator. CRC8-ATM works without problems. However, when using the polynomial of CRC8-MAXIM, the calculation result is different. Did I calculate the wrong way?
==============================
CRC8-ATM
dat: "AB" = 01000001 01000010
ply: 0x107 = 100000111
res: 0x87
==============================
01000001 01000010 00000000
1000001 11
----------------------------
10000010 00000000
10000011 1
----------------------------
1 1000000
1 00000111
----------------------------
my_res: 10000111 => 0x87 (OK)
==============================
CRC8-MAXIM
dat: "AB" = 01000001 01000010
ply: 0x131 = 100110001
res: 0xA5
==============================
01000001 01000010 00000000
1001100 01
----------------------------
1101 00000010 00000000
1001 10001
----------------------------
100 10001010 00000000
100 110001
----------------------------
1001110 00000000
1001100 01
----------------------------
10 01000000
10 0110001
----------------------------
my_res : 00100010 => 0x22 (Must be 0xA5)
For the calculation results, refer to the site below.
If anyone is familiar with the implementation of CRC8, please help.
CodePudding user response:
Yes, there is.
Regular CRC-8 and CRC-8/MAXIM have different RefIn
and RefOut
configurations :
RefIn
parameter indicates if the data byte should be reversed before being used.RefOut
parameter indicates if the computed CRC should be reversed before appling the finalXorOut
operation.
Here is a piece of code computing CRC8 algorithms:
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
uint8_t uint8_reverse(uint8_t val)
{
uint8_t ret = 0;
for (size_t i = 0; i < 8; i )
{
if (val & 0x80)
{
ret |= (1 << i);
}
val <<= 1;
}
return ret;
}
uint8_t crc8(uint8_t const * data, size_t data_size, uint8_t poly, uint8_t init,
bool refin, bool refout, uint8_t xor_out)
{
uint8_t crc = init;
for (size_t i = 0; i < data_size; i )
{
crc = crc ^ (refin ? uint8_reverse(data[i]) : data[i]);
for (size_t j = 0; j < 8; j )
{
if (crc & 0x80)
{
crc = (crc << 1) ^ poly;
}
else
{
crc <<= 1;
}
}
}
return (refout ? uint8_reverse(crc) : crc) ^ xor_out;
}
int main(void)
{
printf("--- Check data ---\n");
const uint8_t check[9] = "123456789";
printf("crc8: 0xx\n", crc8(check, 9, 0x07, 0x00, 0, 0, 0x00));
printf("crc8-cdma2000: 0xx\n", crc8(check, 9, 0x9b, 0xff, 0, 0, 0x00));
printf("crc8-darc: 0xx\n", crc8(check, 9, 0x39, 0x00, 1, 1, 0x00));
printf("crc8-itu: 0xx\n", crc8(check, 9, 0x07, 0x00, 0, 0, 0x55));
printf("crc8-maxim: 0xx\n", crc8(check, 9, 0x31, 0x00, 1, 1, 0x00));
printf("--- 'AB' data ---\n");
const uint8_t ab_data[2] = "AB";
printf("crc8: 0xx\n", crc8(ab_data, 2, 0x07, 0x00, 0, 0, 0x00));
printf("crc8-itu: 0xx\n", crc8(ab_data, 2, 0x07, 0x00, 0, 0, 0x55));
printf("crc8-maxim: 0xx\n", crc8(ab_data, 2, 0x31, 0x00, 1, 1, 0x00));
return 0;
}
It outputs:
--- Check data ---
crc8: 0xf4
crc8-cdma2000: 0xda
crc8-darc: 0x15
crc8-itu: 0xa1
crc8-maxim: 0xa1
--- 'AB' data ---
crc8: 0x87
crc8-itu: 0xd2
crc8-maxim: 0xa5
Note that most of the time RefIn
and RefOut
have the same value, and code optimization is possible (i.e. avoiding all byte reversing operations).
CodePudding user response:
As noted by @lrntgr, the CRC-8/MAXIM defintion has the input bits and the resulting CRC bits reflected. Re-doing your notation with the input and output reflected:
==============================
CRC8-MAXIM
dat: "AB" reflected = 10000010 01000010
ply: 0x131 = 100110001
res: 0xA5
==============================
10000010 01000010 00000000
10011000 1
----------------------------
11010 11000010 00000000
10011 0001
----------------------------
1001 11010010 00000000
1001 10001
----------------------------
1011010 00000000
1001100 01
----------------------------
10110 01000000
10011 0001
----------------------------
101 01010000
100 110001
----------------------------
1 10010100
1 00110001
----------------------------
my_res : 10100101 => reflected 10100101 = 0xA5
For this particular example, 0xA5
reflected is 0xA5
! So, unfortunately, you cannot see that the final reflection of the CRC is needed. But, it is. Do another example to see that.
Also as noted, the actual calculation does not need to reflect the input and output bits, but instead can have the exact same effect by instead reflecting the polynomial and shifting down instead of up. The code then is:
unsigned crc8maxim(unsigned char const *dat, size_t len) {
unsigned crc = 0;
for (size_t i = 0; i < len; i ) {
crc ^= dat[i];
for (unsigned k = 0; k < 8; k )
crc = crc & 1 ? (crc >> 1) ^ 0x8c : crc >> 1;
}
return crc;
}
where the 0x8c
is the reflection of 0x31
, the polynomial bits excluding x8.