Skip to main content
Visitor II
March 25, 2025
Question

Calculate CRC-8-ATM with Hardware CRC Unit of STM32F7

  • March 25, 2025
  • 2 replies
  • 725 views

How can you calculate a CRC-8-ATM using the CRC unit of a STM32F7?

I want to check the CRC of the output of an ADC ADS127L11 which is transmitted via SPI. The user manual says the CRC calculation is based on CRC-8-ATM. The output is an 8-bit CRC, and the polynomial is X^8+X^2+X^1+X^0. I cannot configure this in the CRC unit of my STM32F7.

Does anybody know if and how you can use the embedded CRC unit for CRC-8-ATM calculation?

    This topic has been closed for replies.

    2 replies

    Graduate II
    March 25, 2025

    So an 0x07 polynomial value.

    You want to use the CRC unit built into the SPI, or the stand-alone CRC unit of the STM32?

    Do you have some example test vectors?

    Have you checked it with a software implementation?

    Generally on the SPI, I'd expect you run the pattern through the reception, with the CRC polynomial set up, and if correct the CRC register/check will zero out.

    Flo25Author
    Visitor II
    May 22, 2025

    Thanks for your answer. Basically, I was an ***.

     

    Here is an excerpt of my solution. Yes, I see there some weaknesses in returning how to return the values, it’s an excerpt. Maybe it helps someone.

    #include "stm32f756xx.h"
    
    #define CONFIG_COUNT 1u
    
    typedef enum
    {
     REV_IN_NOT_AFFECTED = 0uL, //!< 00: Bit order not affected
     REV_IN_BYTE = CRC_CR_REV_IN_0, //!< 01: Bit reversal done by byte
     REV_IN_HALF_WORD = CRC_CR_REV_IN_1, //!< 10: Bit reversal done by half-word
     REV_IN_WORD = CRC_CR_REV_IN //!< 11: Bit reversal done by word
    } InBitInversionMode_t;
    
    typedef enum {
     POLY_SIZE_32 = 0x0uL, //!< 32 Bit polynomial
     POLY_SIZE_16 = CRC_CR_POLYSIZE_0, //!< 16 Bit polynomial
     POLY_SIZE_8 = CRC_CR_POLYSIZE_1, //!< 8 Bit polynomial
     POLY_SIZE_7 = CRC_CR_POLYSIZE //!< 7 Bit polynomial
    } PolySize_t;
    
    typedef struct
    {
     bool isOutBitInverted; //!< Reversal of the bit order of the output data
     InBitInversionMode_t inBitInverted; //!< Reversal of the bit order of the input data
     PolySize_t polySize; //!< Size of the CRC polynomial
     uint32_t crcPoly; //!< Programmable CRC polynomial
     uint32_t crcInit; //!< Initial CRC value
    } CrcConfig_t;
    
    static const CrcConfig_t crcConfig[CONFIG_COUNT] =
    {
     { // HAL_CRC_ADC
     false,
     REV_IN_NOT_AFFECTED,
     POLY_SIZE_8,
     0x07uL, //!< CRC_8_ATM -> X^8 + X^2 + X^1 + X^0
     0xFFFFFFFFuL
     }
    }
    
    void HalCrc_Init(void)
    {
     RCC->AHB1ENR |= RCC_AHB1ENR_CRCEN; // Enable CRC clock
     CRC->CR = CRC_CR_RESET;
    }
    
    void HalCrc_Config(const HalCrc_Config_t config)
    {
     CRC->CR = CRC_CR_RESET;
     
     CRC->POL = (uint32_t)(crcConfig[config].crcPoly);
     CRC->INIT = (uint32_t)(crcConfig[config].crcInit);
     
     CRC->CR |= (crcConfig[config].isOutBitInverted) ? CRC_CR_REV_OUT: 0uL;
     CRC->CR |= (uint32_t)(crcConfig[config].inBitInverted);
     CRC->CR |= (uint32_t)(crcConfig[config].polySize);
    }
    
    void HalCrc_Calculate8(uint32_t* const crc, const uint8_t* data, const uint8_t length)
    {
     CRC->CR |= CRC_CR_RESET;
     for(uint8_t bytePos = 0; bytePos < length; bytePos++)
     {
     *(uint8_t*)(CRC_BASE) = data[bytePos]; // Write data to CRC data register
     }
     *crc = CRC->DR;
    }
    
    uint32_t HalCrc_Accumulate8(const uint8_t data)
    {
     *(uint8_t*)(CRC_BASE) = data; // Write data to CRC data register
     return CRC->DR;
    }