PIC32, DMA, CRC(32) - Page 1
Forum section: electronics / general

author: TomS_
author_rank: Frequent Contributor
timestamp: November 30, 2020, 10:03:35 am
content: Hi all,Thought I might try my luck here. Ive also posted on the Microchip forum itself, but this seems to be a very seldom touched subject over there from what I can (cant?) find by searching.I am trying to use the DMA and CRC modules of a PIC32MX450F256H to calculate the CRC32 of a simple string of text (without the quotes): "hello"Every online tool I can find, and every example I can find for Python, gives me the result of 0x3610A686, but I cannot seem to reproduce this using the CRC module of the PIC.I am wondering if anyone has done this successfully before and can help me out with some pointers to what Im doing wrong?FWIW I can implement a software CRC32 routine that gives me the same (seemingly correct) result, but I was really hoping to do this using the built in hardware.Below is the code I have been testing with. The loop at the bottom just CRCs extra 0's, which I saw as a suggestion for someone who was having issues with a 16 bit CRC, but no matter how many extra 0's I CRC in I cant reproduce the same value as above. Ive tried a variety of different settings but nothing seems to be working. The example in the PIC32 DMA reference manual seems pretty straight forward, and there dont seem to be any mentions of doing anything particularly special before or after...Code:voidmain(void){uint32_t crc = 0;uint32_t crc2 = 0;const uint8_t crc_in[] = {'h', 'e', 'l', 'l', 'o'};const uint8_t crc_aug[] = {0, 0, 0, 0};IEC2CLR = _IEC2_DMA0IE_MASK; /* Disable int and clear flag */IFS2CLR = _IFS2_DMA0IF_MASK;DMACONbits.ON = 1; /* Enable DMA controller */DCRCDATA = 0xFFFFFFFF;DCRCXOR = 0x04C11DB7;DCRCCONbits.CRCAPP = 1; /* Append mode */DCRCCONbits.PLEN = (31 & 0x1f); /* 32 bit polynomial */DCRCCONbits.BITO = 1; /* Reflected input */DCRCCONbits.CRCEN = 1;DCH0CON = 0;DCH0ECON = 0;/* First do a CRC on the data itself */DCH0INT = 0;DCH0SSA = KVA_TO_PA((void *)&crc_in);DCH0DSA = KVA_TO_PA((void *)&crc);DCH0SSIZ = 5;DCH0DSIZ = 4;DCH0CSIZ = 5;DCH0CONbits.CHEN = 1;DCH0ECONbits.CFORCE = 1;while (DCH0INTbits.CHBCIF == 0);crc2 = DCRCDATA ^ 0xFFFFFFFF;/** Ideally at this point, crc2 contains the CRC32 for the input data.** All other examples give me 0x3610A686, but in the above configuration I* get:** DCRCDATA = 0xA8D1FCDC* crc2 = 0x572E0323** with BITO = 0; or** DCRCDATA = 0xB7B11BA8* crc2 = 0x484EE457** with BITO = 1*//* Then do a CRC on some extra zeroes */uint8_t ctr = 0; /* Breakpoint here to check crc2 above */while (true) {DCH0INT = 0;DCH0SSA = KVA_TO_PA((void *)&crc_aug);DCH0DSA = KVA_TO_PA((void *)&crc);DCH0SSIZ = 3;DCH0DSIZ = 4;DCH0CSIZ = 3;DCH0CONbits.CHEN = 1;DCH0ECONbits.CFORCE = 1;while (DCH0INTbits.CHBCIF == 0);crc2 = DCRCDATA ^ 0xFFFFFFFF;ctr++; /* Breakpoint here to check crc2 after each zero CRCd */}while (true);return;}

author: dmendesf
author_rank: Frequent Contributor
timestamp: November 30, 2020, 10:17:07 pm
content: Not a user of this particular chip but I've implemented CRC32 from scratch a few times so I'll give you some general pointers:There's 3 things you must get right: the initial condition of the data register, the polynomial and sometimes there's an extra XOR with another constant at the end. Do it by hand, on paper, for a single byte (for example just the "h"), then compare with the output of your software and hardware implementation. Usually this is enough to find what's wrong. Iterate for 2, then 3, then 4 bytes (the state is 4 bytes long so if you get 4 right then you can get as many as you want right after that).Sorry for not being very helpful with the exact problem but that's how I managed to make it work...

author: HwAoRrDk
author_rank: Super Contributor
timestamp: November 30, 2020, 11:26:00 pm
content: There are two common CRC32 variants - make sure you are checking your results against the right one.There's 'plain' CRC32, as used by GZIP, ZMODEM, PNG to name a few, but also CRC32-POSIX, used by the Unix/Linux cksum utility. They differ by polynomial, bit order, and initial value.CRC32Polynomial: 0xEDB88320Bit order: reversedInitial value: 0xFFFFFFFFXOR out: 0xFFFFFFFFCRC32-POSIXPolynomial: 0x04C11DB7Bit order: normalInitial value: 0x00000000XOR out: 0xFFFFFFFF

author: TomS_
author_rank: Frequent Contributor
timestamp: December 01, 2020, 09:02:41 am
content: I did indeed get an answer from the Microchip forum.I had suspicions, but someone there confirmed that I needed a "magic number" other than 0xFFFFFFFF as the initial value: 0x46AF6449Using this with a polynomial of 0x04C11DB7, reversed input and a simple for loop to reverse the CRC bits at the end followed by inverting all bits is giving me the "correct" result now. So I dunno, thats some kind of hybrid between CRC32 and CRC32-POSIX... I need to read more about this and figure out what Im actually doing, but I am getting a "compatible" result now...