Search code examples
cstm32crc32

STMF0 CRC Issue


I am using the STM32F0 using register level coding and am having problems with the CRC module. Basically I cant get the results to agree with online calculators.

I've stripped it right back to as simple as possible. If I just reset the CRC then read the Data Register out I get 0xFFFFFFFF which I would expect as that's the initial value. Even if I write zero in though and get the result it does not agree with other tools. The STM outputs 0xC704DD7B and the online tools give 0xF4DBDF21.

As far as I can see all the parameters are the same (I have not tried to hand calculate it!).

My bare bones code is (and I am reading the result in the debugger from the register)...

// Reset the CRC.
SET_BIT(CRC->CR, CRC_CR_RESET_Pos);

// Write 0.
CRC->DR, 0;


Solution

  • I am not really sure, but maybe this helps:

    I once had the same problem and i tried to figure out how to get the "correct" CRC32. Unfortunately there is not "one" type how CRC32 could be calculated, but several of ways. See https://crccalc.com/

    I allways leave the settings of the CRC peripheral on default:

    • Default Polynomial state -> Enable
    • Default Init Value State -> Enable
    • Enable Input Data Inversion Mode -> None
    • None Output Data Inversion Mode -> Disable

    Except "Input Data Format", which I set to "Words".

    When sending data to the peripheral, I revert the words "word-wise". The Result is reverted word-wise again. This leads to an CRC32 which can be verified as CRC32/MGPE2

    I have a function, that tests, if If I have configured the CRC Peripheral correctly, so I get "the correct" CRC32/MPEG2:

    uint8_t CRC32Test(void) {
        // @brief   test if CRC32 Module is configured correctly
        // @params  none, void
        // @return  u8 status: 1 = OK, 0 = NOK (not configured correctly)
    
        // Test if CRC Module is configured correctly.
        // If YES, these data must return the CRC32 0x07 D4 12 72 (Big Endian)
        // or - 0x72 12 d4 07 (little Endian)
        uint8_t retval = 0;
    
        uint8_t testdata[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x00, 0x00};
        uint32_t CRCdataU32[3] = {0,};
        uint32_t* pCRCdata = (uint32_t*)testdata;
        uint32_t dataSz = 3;
    
        CRCdataU32[0] = __REV(*pCRCdata++);
        CRCdataU32[1] = __REV(*pCRCdata++);
        CRCdataU32[2] = __REV(*pCRCdata++);
    
        uint32_t testCRC32 = HAL_CRC_Calculate(&hcrc, CRCdataU32, dataSz);
        testCRC32 = __REV(testCRC32);
    
        if(testCRC32 == 0x7212d407) retval = 1;
    
        return(retval);
    }
    

    I verified this, using crccalc.com

    crccalc.com Output

    This is most probably not the most elegant code, but it works for me. I use it for data transfer between the MCU and a PC over RS232/RS485. I don't care much which special CRC32 I use. I just need both to create the same results on the receiver and the sender. And I archieve that with that code.