Skip to main content
Explorer
October 11, 2024
Question

problem w/ setting polynomial for CRC

  • October 11, 2024
  • 3 replies
  • 2688 views

I'm trying to set the polynomial for the CRC block and having some difficulty. I want to set the CRC block to compute a CRC-32K (Reversed Koopman) over my data.

Here are the details

CRC-32K (reversed Koopman polynomial) - 0xEB31D82E

Input data - 0x31, 0x32, . . ., 0x39

I expect the resulting CRC to be 0x2D3DD0AE

How I setup my STMh755 CRC block

 

 

#define CRC_POLYNOMIAL_32B 0xeb31d82e
static const uint8_t aDataBuffer[] = {
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39
};

/*##-1- Configure the CRC peripheral #######################################*/
CrcHandle.Instance = CRC;

/* The default polynomial is not used. It is required to defined it in CrcHandle.Init.GeneratingPolynomial*/
CrcHandle.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE;

/* Set the value of the polynomial */
CrcHandle.Init.GeneratingPolynomial = CRC_POLYNOMIAL_32B;

/* The user-defined generating polynomial generates a
8-bit long CRC */
CrcHandle.Init.CRCLength = CRC_POLYLENGTH_32B;

/* The default init value is used */
CrcHandle.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE;

/* The input data are not inverted */
CrcHandle.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;

/* The output data are not inverted */
CrcHandle.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;

/* The input data are 32-bit long */
CrcHandle.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;

if (HAL_CRC_Init(&CrcHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}

/*##-2- Compute the CRC of "aDataBuffer" ###################################*/

uwCRCValue = HAL_CRC_Calculate(&CrcHandle, (uint32_t *)&aDataBuffer, BUFFER_SIZE);

 

 

 

A couple of issues:

1 - I get a return error from HAL_CRC_Init(). Why does HAL layer only allow ODD parity polynomials?

 

 

 /* Ensure that the generating polynomial is odd */
 if ((Pol & (uint32_t)(0x1U)) == 0U)
 {
 status = HAL_ERROR;
 }

 

 

2 - Am I missing something in setting up the CRC block?

Thanks.

 

 

 

    This topic has been closed for replies.

    3 replies

    Graduate II
    October 11, 2024

    Mechanically I'm not sure the hardware has this limitation, it shouldn't need too.

    Did some hackery that suggests it's not, where I did a 15-bit CRC/Polynomial

    https://github.com/cturvey/RandomNinjaChef/blob/main/STM32_CRC15_CRC_CAN.c

    The hardware is LEFT shifting

    The initial value would be 0xFFFFFFFF and the result inverted to get the solution, right shifting.

    // Related to musings here
    // https://community.st.com/t5/stm32-mcus-products/problem-w-setting-polynomial-for-crc/td-p/730403
    
    // CRC-32K (reversed Koopman polynomial) - 0xEB31D82E
    // Input data - 0x31, 0x32, . . ., 0x39
    // I expect the resulting CRC to be 0x2D3DD0AE
    
    // Copyright (C) 2024 Clive Turvey (aka Tesla DeLorean, sourcer32@gmail.com)
    // All Rights Reserved
    
    //******************************************************************************
    
    #include <windows.h>
    #include <stdio.h>
    
    typedef unsigned char uint8_t;
    typedef unsigned int uint32_t;
    
    //******************************************************************************
    
    uint8_t data[] = {
     0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39 };
    
    //******************************************************************************
    
    uint32_t crc32k(uint32_t crc, size_t size, uint8_t *buffer)
    {
     int i;
     while(size--)
     {
     crc ^= (uint32_t)*buffer++;
     for(i=0; i<8; i++)
     if (crc & 0x00000001)
     crc = (crc >> 1) ^ 0xEB31D82E;
     else
     crc >>= 1;
     }
    
     return(crc);
    }
    
    //******************************************************************************
    
    int main(int argc, char **argv)
    {
     uint32_t crc;
    
     crc = crc32k(0xFFFFFFFF, sizeof(data), data);
     printf("%08X %08X\n", crc, ~crc);
    
     return(1);
    }
    
    //******************************************************************************

    Is suspect I can make the hardware work, but will take the polynomial being reversed, byte input reversed, answer reversed and inverted.

     

    Graduate II
    October 11, 2024

    I made the magic happen on a STM32G031 to hand..

    In ST-Speak inversion means bit-reversal

    CRC-32-K 2D3DD0AE TEST 2D3DD0AE ?

     

    //****************************************************************************
    
    void TestCRC(void) // sourcer32@gmail.com PayPal accepted.. gauge by man-hours saved
    {
     uint8_t test[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39 }; // 0x2D3DD0AE
    
     /* CRC handler declaration */
     CRC_HandleTypeDef CrcHandle = {0};
    
     /* CRC Peripheral clock enable */
     __HAL_RCC_CRC_CLK_ENABLE();
    
     /*##-1- Configure the CRC peripheral #######################################*/
     CrcHandle.Instance = CRC;
    
     /* The default polynomial is not used. It is required to defined it in CrcHandle.Init.GeneratingPolynomial*/
     CrcHandle.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE; // ST double-negative, use user supplied
    
     /* Set the value of the polynomial */
     CrcHandle.Init.GeneratingPolynomial = 0x741B8CD7; // 32-bit CRC-32-K, bit reversed 0xEB31D82E, hw left shifts, always
    
     /* The user-defined generating polynomial generates a 32-bit long CRC */
     CrcHandle.Init.CRCLength = CRC_POLYLENGTH_32B;
    	
     /* The default init value is not used */
     CrcHandle.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_DISABLE; // ST double-negative
    
     /* The used-defined initialization value */
     CrcHandle.Init.InitValue = 0xFFFFFFFF; // 32-bit all set
    
     /* The input data is inverted (bit-reversed) */
     CrcHandle.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE; // Bit swap byte end-to-end
    
     /* The output data is inverted (bit-reversed)*/
     CrcHandle.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE;// Bit swap word end-to-end
    
     /* The input data are 8-bit long */
     CrcHandle.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
    
     if (HAL_CRC_Init(&CrcHandle) != HAL_OK)
     {
     /* Initialization Error */
     Error_Handler(__FILE__, __LINE__);
     }
    
     /* Note that I negate the response the hardware spins end-to-end */
     printf("CRC-32-K %08X TEST 2D3DD0AE ?\n", ~HAL_CRC_Calculate(&CrcHandle, (uint32_t *)test, sizeof(test)));
    }
    
    //****************************************************************************

     

     

    Graduate II
    October 11, 2024

    @STOne-32 @STTwo-32 "Why does HAL layer only allow ODD parity polynomials?"

    https://community.st.com/t5/stm32-mcus-security/can-the-stm32-crc-peripheral-be-abused-into-doing-crc-24q-or/m-p/65228

    stm32crc_only_odd.jpg

    Case in point I can also do 24-bit and 15-bit CRC's where I do ALL the work in the high-order bits

    Technical Moderator
    October 12, 2024

    Dear @Tesla DeLorean  @BradWalker ,

    Thank you for the interesting exchanges, the main is reason is simply because our specification / manual say it.

    here an example of our reference manual for STM32G4 series : STM32G4 series advanced Arm<Sup>®</Sup>-based 32-bit MCUs - Reference manual  ,

    Go to Page 456/2138 from Manual revision 8.

     

     

    STOne32_1-1728741309832.png

    I fully understand it might work perfectly at your end , but from our side, we do not support the behavior or results as it could be never tested/verified as at industry level  Odd Polynomials are the mostly used.

    Hope it helps to clarify the topic. 

    STOne-32.

     

     

     

    Graduate II
    October 12, 2024

    Ok, but LFSR's and CRC methods have been a staple of DfT (Design for Test) / BiST (Built in Self Test) for over 4 decades.

    I'm not sure of your CRC implementation here, but it's usually a net of feed back terms and flip-flops, gated by a latched polynomial pattern in this case, it should be able to be validated "by-design". Do you test all the other 2^(32-1) patterns for a polynomial that would be ODD? I'd wager serious money you do not, or come remotely close.

    The CRC-24 implementation should be able to provide some robust test-patterns / test-vectors that could be applied at the DESIGN stages to exercise the gate level implementation. And prove robustly that the ODD rule is patently nonsense.

    For the CRC-32-K I reversed the polynomial to deal with the left-shifting implementation, and that does make it ODD at the LSB.

    But in the case of the 15-bit and 24-bit CRC that I've expressly demonstrated here, all the low order bits of the polynomial registers are zero, as I've left aligned them, whilst the CRC-24 itself is in the form x^24 + ... + 1

    Pretty sure I can demonstrate 4 and 5-bit exploits of the hardware too.

    Need to dig out an STM32G4