python-3.xraspberry-picrccrc32simplicity-studio

CRC-32 values not matching


I am using SPI communication to communicate between Raspberry Pi and a microcontroller. I am sending a value of "32" (a 32-bit integer) or "0x00000020" with CRC value calculated by the microcontroller as "2613451423". I am running CRC32 on this 32-bit integer. Polynomial being used on MCU is "0x04C11DB7". Below is the snippet of code I am using on microcontroller:

GPCRC_Init_TypeDef initcrc = GPCRC_INIT_DEFAULT;
initcrc.initValue = 0xFFFFFFFF; // Standard CRC-32 init value
initcrc.reverseBits = true; 
initcrc.reverseByteOrder =true; //Above line and this line converts data from big endian to little endian

/*********other code here**************/

for(int m=0;m<1;m++){
   data_adc = ((uint8_t *)(StartPage+m));//reading data from flash memory,StartPage is the address from where to read (data stored as 32bit integers),here reading only a byte 
   ecode = SPIDRV_STransmitB(SPI_HANDLE, data_adc, 4, 0);//transmitting 4 bytes (32-bit value) through SPI over to RPi
        
   GPCRC_Start(GPCRC); //Set CRC parameters such as polynomial  
   for(int i=0;i<1;i++){
      GPCRC_InputU32(GPCRC,((uint32_t *)(StartPage+i)));//generating crc for the same 32 bit value
   }

   //I also tried using below code:
   /*for(int i=0;i<4;i++){
      GPCRC_InputU8(GPCRC,((uint8_t *)(StartPage+i)));//generating crc for the same 32 bit value
     }*/

   checksum[0] = ~GPCRC_DataRead(GPCRC); //CRC value inverted and stored in array
   ecode = SPIDRV_STransmitB(SPI_HANDLE, checksum, 4, 0);//sending this value through SPI (in chunks of 4 bytes) 

On RPi, I am collecting this value (i.e. "32", I receive the value correct) but the CRC calculated by RPi is "2172022818". I am using "zlib" to calculate CRC32. I have added a code snippet as well:

import datetime
import os
import struct
import time
import pigpio
import spidev
import zlib

bus = 0
device = 0
spi = spidev.SpiDev()
spi.open(bus, device)
spi.max_speed_hz = 4000000
spi.mode = 0

pi.set_mode(25, pigpio.INPUT)

rpi_crc=0
 
def output_file_path():
    return os.path.join(os.path.dirname(__file__),
               datetime.datetime.now().strftime("%dT%H.%M.%S") + ".csv")
 
def spi_process(gpio,level,tick):
    print("Detected")
    data = bytes([0]*4)
    crc_data = bytes([0]*4)
    spi.xfer2([0x02])
    with open(output_file_path(), 'w') as f:
        t1=datetime.datetime.now()
        for x in range(1):
            recv = spi.xfer2(data)
            values = struct.unpack("<" +"I"*1, bytes(recv))
            print(values)
            rpi_crc = zlib.crc32(bytes(recv))
            print('RPis own CRC generated:') 
            print(rpi_crc)
            f.write("\n")
            f.write("\n".join([str(x) for x in values]))
        mcu_crc_bytes = spi.xfer2(crc_data)
        mcu_crc = struct.unpack("<"+"I"*1,bytes(mcu_crc_bytes))
        mcu_crc_int = int(''.join(map(str,mcu_crc)))
        print('MCU sent this CRC:')
        print(mcu_crc_int)
        if (rpi_crc != mcu_crc_int):
            spi.xfer([0x03])
        t2=datetime.datetime.now()
        print(t2-t1)

input("Press Enter to start the process ")
spi.xfer2([0x01])

cb1=pi.callback(25, pigpio.RISING_EDGE, spi_process)

while True:
    time.sleep(1)

From this forum itself I got to know that it might be the issue of endianness so, I tried playing around with the endianness of one value and compare it with other but it still produces different values. For ex: Value sent by RPi is:2172022818 (in decimal) Changing it to Hex: 0x81767022 Changing the endianness: 0x22707681

Value sent by microcontroller is:2613451423 (in decimal) Changing it to Hex: 0x9BC61A9F

As you can see both the values in bold are not same. Please let me know if I am doing something wrong or what could be going on here. Thanks!

EDIT: Added more code to provide better overview of certain aspects which were missing before. Datasheet for microcontroller (CRC on Pg. 347): https://www.wless.ru/files/ZigBee/EFR32MG21/EFR32xG21_reference_manual.pdf


Solution

  • I was able to figure out the issues. I used this https://crccalc.com/?crc=C5&method=crc32&datatype=hex&outtype=0 to confirm CRC values that I was getting on microcontroller and RPi.

    First issue was on microcontroller, where I was not even performing the CRC on the data, instead I was performing on the address where that data was stored.

    Second issue was that MCU was performing CRC on the value which was stored in the little-endian form. On RPi also, CRC was being performed on values stored in little-endian form. Hence, since the endianness was same on both the devices, I did not have to reverse the bits or bytes.

    After doing these changes, I was able to get correct and same CRC values on both RPi and microcontroller.