27.3.4.6 CRC Result
Reading the result of a CRC calculation depends on the selected operating mode.
In Alternate mode (MOD bit = 1
not available
on all devices), the result is available in the CRCWDAT registers when all the data in the
CRC FIFO buffer has been processed. Submitting dummy data to generate extra cycles is not
required.
In Legacy mode (MOD bit = 0
), the CRC module
requires (PLEN[4:0] + 1) extra peripheral clock cycles to finish the calculations. To
generate these additional cycles, the dummy data, with the width equal to the polynomial
order (length), must be loaded into the CRCDAT registers. After the shifts are finished,
the final CRC result can be read from the CRCWDAT registers.
To get the final CRC result after all data are loaded into the CRC module follow the procedure below..
If the data width (DWIDTH[4:0]) is more than the polynomial length (PLEN[4:0]):
- Wait for the data FIFO to empty (CRCEMPTY bit is set).
- Wait (DWIDTH[4:0] + 1) clock cycles to make sure that shifts from the shift buffer are finished.
- Change the data width to the polynomial length (DWIDTH[4:0] = PLEN[4:0]).
- Write one dummy data word to the CRCDAT registers.
-
Wait two peripheral clock cycles to move the data from the FIFO to
the shift buffer, plus (PLEN[4:0] + 1) clock cycles to shift out the result.
Alternatively, clear the CRC Interrupt Selection bit (CRCISEL =
0
) to get the interrupt when all shifts are done. Clear the CRC interrupt flag. Write dummy data in the CRCDAT registers and wait until the CRC interrupt flag is set. - Read the final CRC result from the CRCWDAT registers.
-
Restore the data width (DWIDTH[4:0] bits) for further calculations
(optional).
If the data width (DWIDTH[4:0]) is equal to, or less than, the polynomial length (PLEN[4:0]), the procedure to get the result can be different.
-
Clear the CRC Interrupt Selection bit (CRCISEL =
0
) to get the interrupt when all shifts are done. -
Suspend the calculation by setting CRCGO =
0
. - Clear the CRC interrupt flag.
- Write the dummy data with the total data length equal to the polynomial length in the CRCDAT registers.
-
Resume the calculation by setting CRCGO =
1
. - Wait until the CRC interrupt flag is set.
-
Read the final CRC result from the CRCWDAT registers.
When the CRC result is achieved, the CRC non-direct initial value should be written again into the CRCWDAT registers to clear/reset the shift buffer from the previously loaded dummy data to start a new calculation. Routine to Get the Final CRC Result in Legacy Mode (MOD bit = 0) shows the steps described above for the polynomial orders of 8, 16 and 32 bits.
Routine to Get the Final CRC Result in Legacy Mode (MOD bit = 0)
unsigned int GetCRC(unsigned char polynomialOrder, // valid values are 8,16,32
unsigned char currentDataWidth) // valid values are 8,16,32
{
unsignedintcrc = 0;
while(!CRCCON1bits.CRCMPT); // wait until data FIFO is empty
asmvolatile("repeat %0\n nop" : : "r"(currentDataWidth>>1)); // wait until previous data
// shifts are done
CRCCON2bits.DWIDTH = polynomialOrder-1; // set data width to polynomial length
CRCCON1bits.CRCISEL = 0; // interrupt when all shifts are done
_CRCIF = 0; // clear interrupt flag
switch(polynomialOrder)
{
case 8: // polynomial length is 8 bits
*((unsigned char*)&CRCDAT) = 0; // load byte
while(!_CRCIF); // wait until shifts are done
crc = CRCWDATL&0x00ff; // get crc
break;
case 16: // polynomial length is 16 bits
CRCDAT = 0; // load short
while(!_CRCIF); // wait until shifts are done
crc = CRCWDAT; // get crc
break;
case 32: // polynomial length is 32 bits
CRCDAT = 0;
while(!_CRCIF); // wait until shifts are done
crc = CRCWDAT; // get crc
break;
default:
;
}
CRCCON2bits.DWIDTH = currentDataWidth-1; // restore data width for further
// calculations
return crc; // return the final CRC value
}