2019/09/09 15:33:40
LJSteve
I am having trouble with the following DMA-CRC test function:



uint32 Time0;
uint32 Timef;
uint32 Timet;
volatile float TimeS;
char __attribute__((coherent))Test_str[64] = {"FIRMWARE_VERSION"};
char __attribute__((coherent))dump_str[64];
void CRC_Test() //CRC-16/AUG-CCITT (https://crccalc.com/)
{
uint32 nBytes, i;
volatile uint32 result;

nBytes = strlen(Test_str);
memset(dump_str, 0xFF, sizeof(dump_str));

IFS4CLR = 0x0003; // Make sure not interrupt flags are set.
DMACONbits.ON = 1; // Turn on the DMA system

// *******************
// *** 16-bit CRCs ***
// *******************
// DCRCCON=0x00000F81; // CRC enabled, polynomial length 16, append
// for(i=0; i<2; ++i){ // Append 2 0x00s for XorOut
// Test_str[nBytes++] = 0x00;
// }

// // CRC-16/XMODEM (works. Tested against https://crccalc.com/)
// DCRCXOR=0x1021; // Use the standard CCITT CRC 16 polynomial: X^16+X^12+X^5+1
// DCRCDATA=0x0000; // seed the CRC generator

// CRC-16/CCITT-FALSE (Does not work; results are good for CRC-16/AUG-CCITT)
// DCRCXOR=0x1021; // Use the standard CCITT CRC 16 polynomial: X^16+X^12+X^5+1
// DCRCDATA=0xFFFF; // seed the CRC generator

// CRC-16/AUG-CCITT (Does not work)
// DCRCXOR=0x1021; // Use the standard CCITT CRC 16 polynomial: X^16+X^12+X^5+1
// DCRCDATA=0x1D0F; // seed the CRC generator


// *******************
// *** 32-bit CRCs ***
// *******************
DCRCCON=0x00001F81; // CRC enabled, polynomial length 32, append
for(i=0; i<4; ++i){ // Append 4 0xFFs for XorOut
Test_str[nBytes++] = 0xFF;
}

// CRC-32/BZIP2 (Does not work)
DCRCDATA=0xffffffff; // seed the CRC generator
DCRCXOR=0x04C11DB7; // CRC 32 polynomial: ...



DCH1CON = 0x00000000; // Set DMA priority to min.
DCH1ECON = 0; // No interrupt trigger.
DCH1INT = 0x00000000; // Not using an DMA interrupts
DCH1SSA = KVA_TO_PA(&Test_str); // Source Address;
DCH1DSA = KVA_TO_PA(&dump_str); // Destination address.
DCH1SSIZ = nBytes; // Source size:
DCH1DSIZ = nBytes; // Destination size:
DCH1SPTR = 0; // Source pointer. (bytes past starting address.)
DCH1DPTR = 0; // Destination pointer. (bytes past starting address.)
DCH1CSIZ = nBytes; // Bytes transferred per event. (cell size)
DCH1INTCLR=0x00ff00ff; // DMA1: clear events, disable interrupts
DCH1CPTR = 0; // Number of bytes that have been transferred since the last event.
DCH1DAT = 0; // Pattern match data
IFS4CLR = 0x0003;
DCH1CONbits.CHEN = 1; // Channel 1 enabled

Time0 = _CP0_GET_COUNT();
DCH1ECONbits.CFORCE = 1; // Force a channel 1 event.
while((DCH1INT & 0x08) == 0); // Wait for channel 1 to complete.
Timef = _CP0_GET_COUNT(); // [TODO] Remove benchmarking

result = DCRCDATA; // Save the CRC

Timet = Timef - Time0;
TimeS = Timet;
TimeS /= 100;
}




The CRC-16/XMODEM settings work. CRC-16/CCITT-FALSE produces the results I expect from CRC-16/AUG-CCITT. CRC-16/AUG-CCITT doesn't seem to match anything. And CRC32 doesn't seem to match anything either.



I am checking against https://crccalc.com/ and https://www.lammertbies.n...o/crc-calculation.html



Does anyone see my mistake anywhere?
2019/09/09 19:52:16
newfound
I implemented the CRC-16/CCITT in assembler when I rewrote the PIC32 programming executives and did get it to work. This is my only experience with the DMA/CRC module so I will only talk about CRC-16/CCITT.
 
You need to initialize:
DCRCDATA = 0x84CF
DCRCXOR = 0x11021 // (I think 0x1021 may also work as it is only 16-bits)
 
After the CRC completes you need to do an additional one-word "dummy" CRC on a memory location holding 0x00000000. 
 
 
2019/09/10 06:35:23
Jim Nickerson
I posted something a while ago about getting PIC32MX DMA CRC working https://www.microchip.com/forums/FindPost/825019
2019/09/10 13:20:48
LJSteve
Thank you for the help. I got CRC-32/POSIX working. 
 
newfound, where did the 0x84CF come from?
2019/09/10 17:36:08
newfound
LJSteve
Thank you for the help. I got CRC-32/POSIX working. 
 
newfound, where did the 0x84CF come from?


I'm no expert on CRC but I learned that there are various algorithms that can produce the same result by tinkering with the initial values and post-processing (bit and byte swaps etc) the result.
 
I did come across the 0x84CF value on some blog post on CRC-CCITT16 and I also saw microchip had used it when I reversed engineered the hardware CRC code in the programming executive. 
2020/11/26 14:23:04
masterpic
LJSteve

Thank you for the help. I got CRC-32/POSIX working. 
 
newfound, where did the 0x84CF come from?




I am suspecting that the CRC is generating a CRC16 for an empty 0x000 word before you give a valid word to the input fifo. The easiest way (maybe the only practical way) to get the desired result is to back calculate from the initial value desired. Below is back calculation from 0xFFFF with 0x1021 polynomial (CCITT-FALSE):
 
                    | 1111 1111 1111 1111 <-- Work back from 0xFFFF init value.
                  1 | 0001 0000 0010 0001
                  --|--------------------
                  1 | 1110 1111 1101 1110
                 10 | 0010 0000 0100 001

                 ---|-------------------
                 11 | 1100 1111 1001 110
                100 | 0100 0000 1000 01
                ----|------------------
                111 | 1000 1111 0001 10
               1000 | 1000 0001 0000 1
               -----|-----------------
               1111 | 0000 1110 0001 0
             1 0001 | 0000 0010 0001
             -------|---------------
             1 1110 | 0000 1100 0000
      100 0100 0000 | 1000 01
      --------------|--------
      100 0101 1110 | 1000 10
     1000 1000 0001 | 0000 1
     ---------------| ------
     1100 1101 1111 | 1000 0
1000 1000 0001 0000 | 1
====================|==
1000 0100 1100 1111 | 0                   <-- Load with 0x84CF to get 0xFFFF.
 
Big thank you to newfound for the value! This saved me a lot of time trying to figure out what was going on.
 
Hopefully this helps anyone who needs a different initial value or polynomial.
 
 
UPDATE (If you don't want to hand calculate):
 
Use regular CRC16 calculation and reverse your polynomial.
 
I.e. 0x(1)1021 --> 0x(1)0811
 
Note the importance of the leading bit. Omitted, you would get 0x8408!
 
© 2021 APG vNext Commercial Version 4.5

Use My Existing Forum Account