2021-02-16 08:55 AM
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
Solved! Go to Solution.
2021-02-16 10:10 AM
//****************************************************************************
//
// 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
2021-02-16 09:45 AM
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
2021-02-16 10:00 AM
(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)
JW
2021-02-16 10:10 AM
//****************************************************************************
//
// 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
2021-02-16 03:52 PM
2021-02-16 04:39 PM
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.
2021-03-15 03:17 PM
2021-03-15 06:16 PM
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
2021-03-16 02:13 AM
> 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:
Also, when writing your program, be aware of this gotcha.
JW
2021-03-16 05:36 AM