CRC calculation different for IC

I try to read out data from the AS5047U sensor (https://ams.com/documents/20143/36005/AS5047U_DS000637_1-00.pdf/8639418f-6c3a-1624-4e6f-18f52c962099) over SPI, but somehow my CRC is always different than that from the sensor. I can read out the correct position value and the crc value from the sensor and the crc stays the same for the same position value, so I think I got the right frame for crc.

I got for example the following values from my crc calculation and the crc given by the sensor (spi1.data is the received data over spi, spi.cmd is the sent data):

Any ideas what could be wrong here?

SPI crc processing:

rx_spi_16(&spi1.data[0],&spi1.cmd[0],2);

pos_sensor.crc = (spi1.data[1] >> 8);

uint8_t crc = crc8((uint8_t *)&spi1.data[0],2);


TX Command to send (16bit mode):

spi1.cmd[0] = 0x7FFF;
spi1.cmd[1] = 0;


CRC Calculation:

uint8_t crc8(uint8_t *message ,uint8_t length)
{
uint32_t crc;
int16_t i,bit;

crc = 0xff;
for ( i=0 ; i<length ; i++ )
{
crc ^= message[i];
for ( bit=0 ; bit<8 ; bit++)
{
if ( (crc & 0x80)!=0 )
{
crc <<= 1;
crc ^= 0x1D;
}
else
{
crc <<= 1;
}
}
}

return (~crc) & 0xFF;
}

• The polynomial is correct. What puzzles me is that the chip wants to transfer high byte first and low byte last in a 16-bit data frame. You have to know which order your MCU stores it in memory, when you address it as bytes. Standard ARM chips have the low byte at address 0. But it does not explain the difference. Check if the you should take most or least significant bit first, or mask out some non-data bits. – Justme Jul 12 '20 at 9:18
• I'm actually fighting the exact same chip for the exact same reason. I'm also going to echo @Justme in that I'm guessing you likely have byte endianness backwards. That said, even with correct byte endianness, the CRC coming back from the chip doesn't agree with my calculations. – Benjamin Riggs Jul 30 '20 at 4:34
• E.g. when returning 0x03 0xC2 (reading the DIA register) it computes a CRC of 0x2A, whereas the expected CRC is 0x65. – Benjamin Riggs Jul 30 '20 at 4:46

After a bit of brute-forcing, it turns out (as suspected), the datasheet lies. The AS5047U does use 0x1D as its polynomial, but, unlike J1850, the initial value is 0xB7 and the final xor value is 0x00. You can easily verify by entering those values here: http://www.sunshine2k.de/coding/javascript/crc/crc_js.html

Edit: Just got and code example from the vendor and it contains this lovely morsel:

    // The CRC Implementation of the device is not fully compatible to the CRC8_SAE_J1850-standard.
// It requires to put in 0x00 as first byte before the communication starts.
// So, the crc-initial value is crcLut[0 ^ 0xff] which is equal to 0xC4


What this comment (poorly) attempts to explain is the initial value is 0xC4, with a final value still of 0xFF. I've replied to the vendor with a strongly worded email.

• Thank you Benjamin, i knew something was wrong here ;) – HansPeterLoft Aug 1 '20 at 8:18

for your information, this was already changed in the AS5147U Datasheet. (same sensor just automotive qualified) It will be changed in the AS5047U asap.

Link to the AS5147U Datasheet: https://ams.com/documents/20143/36005/AS5147U_AS5247U_DS000639_4-00.pdf

regards J

• If you are saying that the data sheet is erroneous it would help if you could say so explicitly. Is there perhaps an errata which includes this? – Chris Stratton Dec 8 '20 at 3:11