Electronics > Microcontrollers

Same CRC routine returns different results... :o

(1/4) > >>

ricko_uk:
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:


--- Code: ---#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);
  }
}

--- End code ---



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 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;
        }

--- End code ---


Thank you :)

SiliconWizard:
Do you mean that the rc_crc32() on the PIC32 is the exact same code as the one used on Arduino?

oPossum:
Try this change on the Arduino...


--- Code: ---         rem ^= 0xedb88320ULL;

--- End code ---

ricko_uk:
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[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;
}


--- End code ---

Kjelt:
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.

Navigation

[0] Message Index

[#] Next page

There was an error while thanking
Thanking...
Go to full version