cancel
Showing results for 
Search instead for 
Did you mean: 

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

BPort.2
Associate II

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

1 ACCEPTED SOLUTION

Accepted Solutions
//****************************************************************************
//
// 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
Up vote any posts that you find helpful, it shows what's working..

View solution in original post

18 REPLIES 18

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
Up vote any posts that you find helpful, it shows what's working..
(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

//****************************************************************************
//
// 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
Up vote any posts that you find helpful, it shows what's working..
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?

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
Up vote any posts that you find helpful, it shows what's working..
Hi,
I got pulled away – just after you guys replied.
I implemented the algorithm you shared, and I get results which match those that your and Jan shared for all the simple cases that you showed. But, they are not what I get out of the stm32f429 that I’m running. For example:
* For 0x12345678 I see 0x877bb728 instead of df8a8a2b
* For 0x0 I see 0x6904bb59 from the CRC unit
Tomorrow, I’ll write code to run it JIC there is something odd about how I’m running it from the Keil debugger – (from the peripherals -> System Viewer -> CRC I check the CR box to reset DR to f-s, enter a value into the DR input and hit return) but I’m fairly certain I tried from compiled code before.

On a F429, like last time

  __CRC_CLK_ENABLE();
	
  CRC->CR = 1;
  CRC->DR = 0x66666666;
  printf("%08X\n", CRC->DR);
	putchar('\n');
	
  CRC->CR = 1;
  CRC->DR = 0x12345678;
  printf("%08X\n", CRC->DR);
	putchar('\n');
	
  CRC->CR = 1;
  CRC->DR = 0;
  printf("%08X\n", (volatile)CRC->DR);
	putchar('\n');
47EC5BD8
 
DF8A8A2B
 
C704DD7B

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

> there is something odd about how I’m running it from the Keil debugger

There is something odd about how Keil debugger runs it - apparently, it writes twice:

0693W000008x0TSQAY.pngAlso, when writing your program, be aware of this gotcha.

JW

> there is something odd about how I’m running it from the Keil debugger
There is something odd about how Keil debugger runs it - apparently, it writes twice:
Yes – that is what I’m seeing. Thanks (I guess I hadn’t checked with code – at least not since having the right expectation).
In poking around previously – I saw the gotcha. Will CR actually read back a 1 if read immediately after setting (or perhaps just trying to, takes long enough anyway – can ignore the result).