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]):

  1. Wait for the data FIFO to empty (CRCEMPTY bit is set).
  2. Wait (DWIDTH[4:0] + 1) clock cycles to make sure that shifts from the shift buffer are finished.
  3. Change the data width to the polynomial length (DWIDTH[4:0] = PLEN[4:0]).
  4. Write one dummy data word to the CRCDAT registers.
  5. 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.

  6. Read the final CRC result from the CRCWDAT registers.
  7. 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.

  8. Clear the CRC Interrupt Selection bit (CRCISEL = 0) to get the interrupt when all shifts are done.
  9. Suspend the calculation by setting CRCGO = 0.
  10. Clear the CRC interrupt flag.
  11. Write the dummy data with the total data length equal to the polynomial length in the CRCDAT registers.
  12. Resume the calculation by setting CRCGO = 1.
  13. Wait until the CRC interrupt flag is set.
  14. 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
}