Skip to main content
BPort.2
Associate II
Feb 16, 2021 4:55 PM UTC
Solved

Which 32 bit CRC does the CRC calculation unit on the stm32f429 calculate?

The documentation I have says the Ethernet calculation with 0x4C11DB7... but I don't get results matching what I get from any other calculator. To remove any endianess or mirroring questions I've tried 0x00000000 and 0x66666666 (e.g.). All calculators I have produce 2144_DF1C and E425_C810 for those 2 inputs. From the CRC unit I get 6904_BB59 and 7B91_8196 (which don't seem to be related by combinations -- on the final value -- of bit flipping and reflection).

Yes I asked what the results are -- because I can't imagine what I' don't see in the 1 -> CR; XXXX -> DR; Result <- DR sequence.

TIA,

Brett

This topic has been closed for replies.
Tesla DeLorean
Tesla DeLoreanBest answer
Guru
Feb 16, 2021 6:10 PM UTC
//****************************************************************************
//
// CRCSTM32 - Forward and Reverse CRC32 Computation on the ST Micro STM32
// Copyright (C) 2010-2021 C Turvey, All rights reserved
//
// sourcer32@gmail.com
//
//****************************************************************************
 
#include <windows.h>
 
#include <stdio.h>
#include <stdlib.h>
 
typedef unsigned long uint32_t;
 
//****************************************************************************
 
uint32_t Crc32(uint32_t Crc, uint32_t Data)
{
 int i;
 
 Crc = Crc ^ Data;
 
 for(i=0; i<32; i++)
 if (Crc & 0x80000000)
 Crc = (Crc << 1) ^ 0x04C11DB7; // Polynomial used in STM32
 else
 Crc = (Crc << 1);
 
 return(Crc);
}
 
//****************************************************************************
 
uint32_t Crc32Rev(uint32_t CurrentCrc, uint32_t DesiredCrc)
{
 uint32_t Data;
 int i;
 
 for(i=0; i<32; i++)
 if (DesiredCrc & 0x00000001)
#if 1
 DesiredCrc = ((DesiredCrc ^ 0x04C11DB7) >> 1) | 0x80000000; // Long form
#else // or
 DesiredCrc = (DesiredCrc >> 1) ^ 0x82608EDB; // Back feeding polynomial
#endif
 else
 DesiredCrc = (DesiredCrc >> 1);
 
 Data = DesiredCrc ^ CurrentCrc;
 
 return(Data); // Data Pattern to get Desired CRC from Current CRC
}
 
//****************************************************************************
 
int main(int argc, char **argv)
{
 printf("%08X (0x2608EDB8)\n\n",Crc32(0, 0x00000008)); // 0x2608EDB8
 
 printf("%08X (0x490D678D)\n\n",Crc32(0, 0x04C11DB7)); // 0x490D678D
 
 printf("%08X (0x00000000)\n\n",Crc32(0x04C11DB7, 0x04C11DB7));
 
 printf("%08X (0x2F69E5B4)\n\n",Crc32Rev(0xAAAAAAAA, 0x12345678));
 
 printf("%08X (0x12345678)\n\n",Crc32(0xAAAAAAAA, 0x2F69E5B4));
 
 printf("%08X (0x80E886A3)\n\n",Crc32(0, 0x66666666));
 
 printf("%08X (0x84299B14)\n\n",Crc32(1, 0x66666666));
 
 printf("%08X (0x47EC5BD8)\n\n",Crc32(0xFFFFFFFF, 0x66666666));
 
 printf("%08X (0xC704DD7B)\n\n",Crc32(0xFFFFFFFF, 0));
 
 printf("%08X (0x04C11DB7)\n\n",Crc32(0, 1));
 
 return(0);
}
 
//****************************************************************************

 __CRC_CLK_ENABLE();
 CRC->CR = 1;
 printf("%08X\n", CRC->DR);
 CRC->DR = 0x66666666;
 printf("%08X\n", CRC->DR);
FFFFFFFF
47EC5BD8

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

19 replies

Tesla DeLorean
Guru
Feb 16, 2021 5:45 PM UTC

The standard STM32 implementation is 32-bit at a time, MSB first, left-shifting. Awkward for sure..

0x00000000 into 0xFFFFFFFF should yield 0xC704DD7B

0x66666666 into 0xFFFFFFFF should yield 0x47EC5BD8

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
waclawek.jan
Super User
Feb 16, 2021 6:00 PM UTC
(gdb) set CRC->CR=1
(gdb) p /x *CRC
$7 = {DR = 0xffffffff, IDR = 0x0, RESERVED0 = 0x0, RESERVED1 = 0x0, CR = 0x0,
 RESERVED2 = 0x0, INIT = 0xffffffff, POL = 0x4c11db7}
(gdb) set CRC->DR=0x12345678
(gdb) p /x *CRC
$8 = {DR = 0xdf8a8a2b, IDR = 0x0, RESERVED0 = 0x0, RESERVED1 = 0x0, CR = 0x0,
 RESERVED2 = 0x0, INIT = 0xffffffff, POL = 0x4c11db7}
(gdb)

0693W000008GLGTQA4.pngJW

Tesla DeLorean
Tesla DeLoreanBest answer
Guru
Feb 16, 2021 6:10 PM UTC
//****************************************************************************
//
// CRCSTM32 - Forward and Reverse CRC32 Computation on the ST Micro STM32
// Copyright (C) 2010-2021 C Turvey, All rights reserved
//
// sourcer32@gmail.com
//
//****************************************************************************
 
#include <windows.h>
 
#include <stdio.h>
#include <stdlib.h>
 
typedef unsigned long uint32_t;
 
//****************************************************************************
 
uint32_t Crc32(uint32_t Crc, uint32_t Data)
{
 int i;
 
 Crc = Crc ^ Data;
 
 for(i=0; i<32; i++)
 if (Crc & 0x80000000)
 Crc = (Crc << 1) ^ 0x04C11DB7; // Polynomial used in STM32
 else
 Crc = (Crc << 1);
 
 return(Crc);
}
 
//****************************************************************************
 
uint32_t Crc32Rev(uint32_t CurrentCrc, uint32_t DesiredCrc)
{
 uint32_t Data;
 int i;
 
 for(i=0; i<32; i++)
 if (DesiredCrc & 0x00000001)
#if 1
 DesiredCrc = ((DesiredCrc ^ 0x04C11DB7) >> 1) | 0x80000000; // Long form
#else // or
 DesiredCrc = (DesiredCrc >> 1) ^ 0x82608EDB; // Back feeding polynomial
#endif
 else
 DesiredCrc = (DesiredCrc >> 1);
 
 Data = DesiredCrc ^ CurrentCrc;
 
 return(Data); // Data Pattern to get Desired CRC from Current CRC
}
 
//****************************************************************************
 
int main(int argc, char **argv)
{
 printf("%08X (0x2608EDB8)\n\n",Crc32(0, 0x00000008)); // 0x2608EDB8
 
 printf("%08X (0x490D678D)\n\n",Crc32(0, 0x04C11DB7)); // 0x490D678D
 
 printf("%08X (0x00000000)\n\n",Crc32(0x04C11DB7, 0x04C11DB7));
 
 printf("%08X (0x2F69E5B4)\n\n",Crc32Rev(0xAAAAAAAA, 0x12345678));
 
 printf("%08X (0x12345678)\n\n",Crc32(0xAAAAAAAA, 0x2F69E5B4));
 
 printf("%08X (0x80E886A3)\n\n",Crc32(0, 0x66666666));
 
 printf("%08X (0x84299B14)\n\n",Crc32(1, 0x66666666));
 
 printf("%08X (0x47EC5BD8)\n\n",Crc32(0xFFFFFFFF, 0x66666666));
 
 printf("%08X (0xC704DD7B)\n\n",Crc32(0xFFFFFFFF, 0));
 
 printf("%08X (0x04C11DB7)\n\n",Crc32(0, 1));
 
 return(0);
}
 
//****************************************************************************

 __CRC_CLK_ENABLE();
 CRC->CR = 1;
 printf("%08X\n", CRC->DR);
 CRC->DR = 0x66666666;
 printf("%08X\n", CRC->DR);
FFFFFFFF
47EC5BD8

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
BPort.2
BPort.2Author
Associate II
Feb 16, 2021 11:52 PM UTC
Thanks for the replies.
Apologies for my mis-reporting one of the values I have gotten – too many scraps of hex digit floating around.
Tesla (or do you prefer DeLorean :smiling_face_with_smiling_eyes:), thanks for the details and the code. I was pulled away from this issue all day today, but tonight I’ll try adding this calculation to the tool I’m assembling (which I hope will making the calculation that is needed outside the device simpler).
BTW, is this a (relatively) standard CRC, and is there a way I might have found it outside of asking ‘ST Community’ (documentation I have seems misleading, and searches are annoying and never get to the relevant info?
Tesla DeLorean
Guru
Feb 17, 2021 12:39 AM UTC

It is a standard polynomial, but I feel that is misapplied here, due to the shift direction, byte/endian order and width. Some of the other STM32 parts have a more programmable CRC, but again they've made a bit of a dogs-breakfast of the whole thing, making it slower and more complicated than necessary. I say this as a guy who did IC design, and has built CRC and Reed-Solomon ECC engines at the gate level, and with significantly less resources than ST Micro.

With a more intelligent design and polynomial choice they could have done CRC-32 properly in a byte centric form compatible with PKZIP, etc. We can use the STM32 one for that, but it requires bit-reversal, inversion, and special handling of trailing bytes. I've posted an example of that to prior iterations of the forum, but as you observe the search here is somewhat pitiful.

I did post an app to CRC binaries. I should probably put that on github. Here I tend to package binaries, compress, encrypt and sign, depending on what's needed.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
waclawek.jan
Super User
Mar 17, 2021 7:15 PM UTC

Without answering your final question - why would it be difficult to skip that one position while performing the checksumming?

JW

BPort.2
BPort.2Author
Associate II
Mar 17, 2021 7:28 PM UTC
That would almost certainly be the next best thing (the skip at runtime would be no problem), the scripts (batch files using srec_cat and related tool) is a bit messier at the moment – and not doing the entire job… but should be fixable.
waclawek.jan
Super User
Mar 17, 2021 10:20 PM UTC

With srecord, I believe you would need to use the -exclude filter, to exclude the CRC's position from calculation. I did not try,though.

JW

BPort.2
BPort.2Author
Associate II
Mar 25, 2021 6:53 PM UTC
These 2 lines of bash muck the hex file just right:
read c1 c2 < <(awk -n '/^[ ]*CHECKSUM / {printf "0x%X 0x%X\n", $2, $2+4}' $Build_Map)
srec_cat $Build_Hex -intel -exclude $c1 $c2 -STM32 $c1 -output wcrc.hex -intel
Would rather get the CHECKSUM from the executable – but the mapfile was just too handy.
srec_cat warns mightily that I could not really want to run the checksum over a file with a hole in it – but it
works just right. It is a well done tool… examples I’ve seen don’t get its flexibility – kind of understandable… a bit more of how-it-works documentation would help folks take better advantage.
I can’t say “well done�? about any of the Keil ARM toolchain – in this case the linker (and the documentation maybe more so) is sadly confused and confusing…. but I found the Load$$LR$$LR_IROM1$$xxxx names to give the load region boundaries to the embedded application code.
MGeri.1
Associate II
Apr 9, 2025 2:54 PM UTC

In order to use the generated code from CubeMX one has to configure the CRC peripheral accordingly:

Basic Parameters:
* Default Polynomial State: Enable
* Default Init Value State: Enable
Advanced Parameters:
* Input Data Inversion Mode: Byte
* Output Data Inversion Mode: Enable
* Input Data Format: Bytes

The you can use the following functions:

uint32_t crc32_ieee(const uint8_t* data, size_t len)
{
uint32_t crc;

crc = HAL_CRC_Calculate(&hcrc, (uint32_t*)data, len);

return ~crc;
}

uint32_t crc32_ieee_update(uint32_t crc, const uint8_t* data, size_t len)
{
crc = ~crc;

__HAL_CRC_INITIALCRCVALUE_CONFIG(&hcrc, __RBIT(crc));

crc = HAL_CRC_Accumulate(&hcrc, (uint32_t*)data, len);

return ~crc;
}