cmicrocontrollerstm32crc32

How to set STM32 to generate standard CRC32


I am trying to generate CRC with STM32L4 hardware modul. I would like to validate fatfs files so basically I have byte arrays. I am using this CRC generator.

Unfortunately I cannot figure out how to set STM32L4 to generate the same result. I need CRC32 and I have

configuration:

hcrc.Instance = CRC;

/* The default polynomial is not used. It is required to defined it in CrcHandle.Init.GeneratingPolynomial*/
hcrc.Init.DefaultPolynomialUse    = DEFAULT_POLYNOMIAL_DISABLE;
/* Set the value of the polynomial */
hcrc.Init.GeneratingPolynomial    = 0x4C11DB7;
//hcrc.Init.GeneratingPolynomial    = 0xFB3EE248;
hcrc.Init.CRCLength= CRC_POLYLENGTH_32B;
/* The default init value is used */
/* The default init value is not used */
hcrc.Init.DefaultInitValueUse     = DEFAULT_INIT_VALUE_ENABLE;

/* User init value is used instead */
//hcrc.Init.InitValue               = 0;
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
//hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE;
/* The input data are inverted by word */
//hcrc.Init.InputDataInversionMode  = CRC_INPUTDATA_INVERSION_WORD;

//hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE;
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
HAL_CRC_Init(&hcrc);

testing:

uint8_t test[] = {49,50,51,52};
uint32_t uwCRCValue = HAL_CRC_Calculate(&hcrc,(uint32_t *) test, 4);

result: A695C4AA

I am out of ideas. There is one way that I am succeeded with it to have uint32_t test[] and input is set to hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES; Unfortunately I have uint8_t...


Solution

  • Use the following code to calc cc32. CRC32 calc by STM32 CRC unit is not the same as our standard CRC32, it did use big endian, and it will not XOR with 0xFFFFFFFF.

    u32 CRC32_ForBytes(u8 *pData, u32 uLen);
    
    #define UNUSED(x) ((void)(x))
    
    /**
     * @brief  CRC functions
     */
    #define __HAL_RCC_CRC_CLK_ENABLE()   do { \
                                            __IO uint32_t tmpreg; \
                                            SET_BIT(RCC->AHBENR, RCC_AHBENR_CRCEN);\
                                            /* Delay after an RCC peripheral clock enabling */\
                                            tmpreg = READ_BIT(RCC->AHBENR, RCC_AHBENR_CRCEN);\
                                            UNUSED(tmpreg); \
                                          } while(0)
    
    #define __HAL_RCC_CRC_CLK_DISABLE()       (RCC->AHBENR &= ~(RCC_AHBENR_CRCEN))
    
    #define CRC32_POLYNOMIAL                        ((u32)0xEDB88320)  
    #define RCC_CRC_BIT                             ((u32)0x00001000)
    
    
    /**
     * @brief  Calc CRC32 for data in bytes
     * @param  pData Buffer pointer
     * @param  uLen  Buffer Length
     * @retval CRC32 Checksum
     */
    u32 CRC32_ForBytes(u8 *pData,u32 uLen)  
    {  
        u32 uIndex= 0,uData = 0,i;  
        uIndex = uLen >> 2;  
    
        __HAL_RCC_CRC_CLK_ENABLE();
    
        /* Reset CRC generator */  
        CRC_ResetDR();
    
        while(uIndex--)  
        {  
    #ifdef USED_BIG_ENDIAN    
            uData = __REV((u32*)pData);  
    #else
            ((u8 *)&uData)[0] = pData[0];
            ((u8 *)&uData)[1] = pData[1];
            ((u8 *)&uData)[2] = pData[2];
            ((u8 *)&uData)[3] = pData[3];
    #endif        
            pData += 4;  
            uData = revbit(uData);  
            CRC->DR = uData;  
        }  
        uData = revbit(CRC->DR);  
        uIndex = uLen & 0x03;  
        while(uIndex--)  
        {  
            uData ^= (u32)*pData++;  
            for(i = 0;i < 8;i++)  
              if (uData & 0x1)  
                uData = (uData >> 1) ^ CRC32_POLYNOMIAL;  
              else  
                uData >>= 1;  
        }
    
        __HAL_RCC_CRC_CLK_DISABLE();
    
        return uData^0xFFFFFFFF;  
    }
    
    static u32 revbit(u32 uData)
    {  
        u32 uRevData = 0,uIndex = 0;  
        uRevData |= ((uData >> uIndex) & 0x01);  
        for(uIndex = 1;uIndex < 32;uIndex++)  
        {  
            uRevData <<= 1;  
            uRevData |= ((uData >> uIndex) & 0x01);  
        }  
        return uRevData;  
    }
    

    Calc your CRC32 like this:

    u32 uwCRCValue = CRC32_ForBytes(&test, 4);