Same CRC routine returns different results... :o - Page 1
Forum section: electronics / general

author: ricko_uk
author_rank: Super Contributor
timestamp: July 23, 2021, 08:43:47 pm
content: Hi,this is a weird one...I have the same CRC routine (literally cut and paste) on a PIC32MZ and an Arduino Uno (which I am using just to check general functionality.On the arduino the CRC routine returns a number (which I can see on the bus with the logic analyser is correct) and when I parse the received data that value and the entire stream is also correct (the receive buffer on the PIC32 is an exact copy of the sent buffer from the Arduino).But when I calculate the CRC on the PIC32 using the same cut-and-paste routine using the same data input it returns a different value...For example:- this is the one calculated on the arduino... 0xCE9C3870- this is the one calculate don the PIC32.... 0x24637E70The only thing that is strange is that the least significant byte of the CRC is always calculated correctly on the PIC32 but only that byte, not the other 3.Any idea what could cause that?The Arduino sketch, including the CRC routine is this:Code:#include <SPI.h>const int SSpin = 10;const int SBusy = 9;#define SPI_CMD__LOAD_START 0x01SPISettings settingsA(100000, MSBFIRST, SPI_MODE2);uint8_t buffer = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};void setup() {// put your setup code here, to run once:pinMode (SSpin, OUTPUT);pinMode (SBusy, INPUT);SPI.begin();}uint32_t rc_crc32(uint32_t crc, const char *buf, size_t len){static uint32_t table;static int have_table = 0;uint32_t rem;uint8_t octet;int i, j;const char *p, *q;/* This check is not thread safe; there is no mutex. */if (have_table == 0) {/* Calculate CRC table. */for (i = 0; i < 256; i++) {rem = i; /* remainder from polynomial division */for (j = 0; j < 8; j++) {if (rem & 1) {rem >>= 1;rem ^= 0xedb88320;} elserem >>= 1;}table = rem;}have_table = 1;}crc = ~crc;q = buf + len;for (p = buf; p < q; p++) {octet = *p; /* Cast to unsigned octet. */crc = (crc >> 8) ^ table[(crc & 0xff) ^ octet];}return ~crc;}void loop() {uint32_t tmpCRC = 0;SPI.beginTransaction(settingsA);while (1){buffer = SPI_CMD__LOAD_START; //cmdbuffer = 0xAA; //cmd optionbuffer = 0x55; //cmd optionbuffer = 1; //data lengthbuffer = 'A'; //datatmpCRC = rc_crc32(0, (char*) buffer, 5);buffer = tmpCRC >> 3; //CRC1buffer = tmpCRC >> 2; //CRC2buffer = tmpCRC >> 1; //CRC3buffer = tmpCRC; //CRC4digitalWrite (SSpin, LOW);//SPI.transfer('A');SPI.transfer(buffer, 9);digitalWrite (SSpin, HIGH);delay(1000);}}The Pic32 code is below. The structParsedMessage.ui32_CRC corresponds to the sent CRC AND to the CRC I see on the SPI bus with the logic analyser:Code:case MESSAGE_RECEIVED:{structParsedMessage.ui32_CRC = aui8_RxBuffer[ui8_RxBufferBytesCount - 4];structParsedMessage.ui32_CRC = structParsedMessage.ui32_CRC << 8;structParsedMessage.ui32_CRC = structParsedMessage.ui32_CRC | aui8_RxBuffer[ui8_RxBufferBytesCount - 3];structParsedMessage.ui32_CRC = structParsedMessage.ui32_CRC << 8;structParsedMessage.ui32_CRC = structParsedMessage.ui32_CRC | aui8_RxBuffer[ui8_RxBufferBytesCount - 2];structParsedMessage.ui32_CRC = structParsedMessage.ui32_CRC << 8;structParsedMessage.ui32_CRC = structParsedMessage.ui32_CRC | aui8_RxBuffer[ui8_RxBufferBytesCount - 1];//check CRCuint32_t tmpCRC = rc_crc32(0, (char*) aui8_RxBuffer, 5); //(ui8_RxBufferBytesCount - 4));if (tmpCRC == structParsedMessage.ui32_CRC){//CRC match so message received correctly_nop();}else{//CRC did not match_nop();}break;}Thank you

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 23, 2021, 09:33:14 pm
content: Do you mean that the rc_crc32() on the PIC32 is the exact same code as the one used on Arduino?

author: oPossum
author_rank: Super Contributor
timestamp: July 23, 2021, 09:35:43 pm
content: Try this change on the Arduino...Code:rem ^= 0xedb88320ULL;

author: ricko_uk
author_rank: Super Contributor
timestamp: July 23, 2021, 09:36:22 pm
content: Thank you SiliconWizzard,It is included in the Arduino code (the first code snippet in the OP).It is this part:Code:uint32_t rc_crc32(uint32_t crc, const char *buf, size_t len){static uint32_t table;static int have_table = 0;uint32_t rem;uint8_t octet;int i, j;const char *p, *q;/* This check is not thread safe; there is no mutex. */if (have_table == 0) {/* Calculate CRC table. */for (i = 0; i < 256; i++) {rem = i; /* remainder from polynomial division */for (j = 0; j < 8; j++) {if (rem & 1) {rem >>= 1;rem ^= 0xedb88320;} elserem >>= 1;}table = rem;}have_table = 1;}crc = ~crc;q = buf + len;for (p = buf; p < q; p++) {octet = *p; /* Cast to unsigned octet. */crc = (crc >> 8) ^ table[(crc & 0xff) ^ octet];}return ~crc;}

author: Kjelt
author_rank: Super Contributor
timestamp: July 23, 2021, 09:40:25 pm
content: Not sure, no time to check but is the endianess of both uc's the same ?This has bitten me quite often with security algorithms in the past.

author: ricko_uk
author_rank: Super Contributor
timestamp: July 23, 2021, 09:41:27 pm
content: thank you oPossum,I tried that just now but the result is the same. Any other suggestions?

author: ricko_uk
author_rank: Super Contributor
timestamp: July 23, 2021, 09:44:38 pm
content: Thank you Kjelt,I checked and both Arduino Uno (ATMega 328P) and PIC32MZ are both little endian.

author: ricko_uk
author_rank: Super Contributor
timestamp: July 23, 2021, 09:45:51 pm
content: @SiliconWizzard,yes they are both the same code, literally cut and paste. That's why it doesn't make much sense that they return different results.

author: oPossum
author_rank: Super Contributor
timestamp: July 23, 2021, 09:46:45 pm
content: Is the generated CRC table the same on both?

author: ricko_uk
author_rank: Super Contributor
timestamp: July 23, 2021, 09:50:06 pm
content: @oPossum,Unfortunately on the Arduino there is no way to debug or see/output the table apart from the serial port but at the moment all the serial to USB I have are connected to running experiments I cannot stop.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 23, 2021, 09:52:59 pm
content: I don't understand this part:Code:buffer = tmpCRC >> 3; //CRC1buffer = tmpCRC >> 2; //CRC2buffer = tmpCRC >> 1; //CRC3buffer = tmpCRC; //CRC4It doesn't look right to me.

author: ricko_uk
author_rank: Super Contributor
timestamp: July 23, 2021, 10:03:09 pm
content: In front of the PC for almost 16 hours so maybe I am doing something really stupid... But the idea is to split 32-bit CRC into 4 bytes and load it into the buffer to be sent.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 23, 2021, 10:08:19 pm
content: Quote from: ricko_uk on July 23, 2021, 10:03:09 pmI thought that was the intent. But it won't work. You're right shifting the CRC by 3, then 2, then 1 bit, then 0 bit. Only the last (LSByte) will be right. I think this is your problem here.

author: ricko_uk
author_rank: Super Contributor
timestamp: July 23, 2021, 10:10:26 pm
content: I noticed that after posting it. I was about to reply how stupid that error was but u replied first.Thank you as always!

author: DavidAlfa
author_rank: Super Contributor
timestamp: July 23, 2021, 11:33:11 pm
content: You're overloading yourself! You need to close everything and go for a walk!My advice is to go to a nearby quarry and ask for 1-day job breaking stone with hand tools.After that, take a shower and a long nap. 2-3 days later you will wake up like new!

author: ricko_uk
author_rank: Super Contributor
timestamp: July 24, 2021, 12:44:30 pm
content: David,that sounds about right... it sounds like a holiday!

author: harerod
author_rank: Frequent Contributor
timestamp: July 25, 2021, 04:35:35 pm
content: So were you able to resolve the problem?My five cents would have been:Exactly the same source will yield different results, when compiler implementations vary.With C, a classic would be sizeof(int).Edit: grammar...

author: Siwastaja
author_rank: Super Contributor
timestamp: July 25, 2021, 05:57:54 pm
content: Sounds like the result was identical but readout of the result from the micro was buggy, no?

author: ricko_uk
author_rank: Super Contributor
timestamp: July 29, 2021, 08:50:17 pm
content: Siwastaja,yes