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.... 0x24637E70
The 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:
#include <SPI.h>
const int SSpin = 10;
const int SBusy = 9;
#define SPI_CMD__LOAD_START 0x01
SPISettings settingsA(100000, MSBFIRST, SPI_MODE2);
uint8_t buffer[10] = {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[256];
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;
} else
rem >>= 1;
}
table[i] = 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[0] = SPI_CMD__LOAD_START; //cmd
buffer[1] = 0xAA; //cmd option
buffer[2] = 0x55; //cmd option
buffer[3] = 1; //data length
buffer[4] = 'A'; //data
tmpCRC = rc_crc32(0, (char*) buffer, 5);
buffer[5] = tmpCRC >> 3; //CRC1
buffer[6] = tmpCRC >> 2; //CRC2
buffer[7] = tmpCRC >> 1; //CRC3
buffer[8] = tmpCRC; //CRC4
digitalWrite (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:
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 CRC
uint32_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