Skip to main content
Associate
October 11, 2024
Question

problem w/ setting polynomial for CRC

  • October 11, 2024
  • 11 replies
  • 2751 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.

11 replies

Tesla DeLorean
Guru
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.

 

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Tesla DeLorean
Guru
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)));
}

//****************************************************************************

 

 

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Tesla DeLorean
Guru
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

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
STOne-32
ST 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.

 

 

 

Tesla DeLorean
Guru
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

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..