2024-10-11 11:16 AM
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.
2024-10-11 12:17 PM
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.
2024-10-11 12:59 PM - edited 2024-10-11 01:04 PM
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)));
}
//****************************************************************************