2019-02-07 08:37 AM
I am developing a serial comms protocol between two STM32F407s.
I am using the hardware CRC module to generate checksums for some of the data.
I am also writing a test script in python to aid development.
All has gone well until now.
Now I need my test script to generate a checksum that agrees with the F4's CRC module.
I have been unsuccessful.
Reading around, it seems that all I should need to do is reverse the bit order going in and reverse and invert the bits read out.
I have done this in my script and in the firmware. No joy.
I have tried 7 variants on CRC32 in my script, using crccheck lib. No joy.
I have tried implementing my own CRC32 function using the flow chart in Application Note AN4187. No joy.
I have systematically inverted and reversed bits, byte wise, word wise, and swapped endianness before, after and both, and compared against inverted, reversed and endianness swapped checksums with each of the above 8 algorithms, even fed the CRC modules byte by byte (2224 combinations). No fricking joy.
The source data was simply 0x01020304
F4's CRC output was: 0xA18723BA
bits reversed and inverted: 0xA02843B5
Does anyone have a proven concrete software implementation of the F4's hardware CRC module, either in c-like or python, that I can use to validate the firmware's output and complete my test script?
Or if not, check that your own F4 produces the same output for the source data?
Cheers
(Here's my attempted implementation:)
def dothething(inbytes, le=True, rr=False, xx=False, init=0xffffffff):
POLY = 0x4c11db7
crc = init
inbytes = bytes(inbytes)
for n in range(0,len(inbytes),4):
if le:
x = inbytes[n]<<0 | inbytes[n+1]<<1 | inbytes[n+2]<<2 | inbytes[n+3]<<3
else:
x = inbytes[n]<<3 | inbytes[n+1]<<2 | inbytes[n+2]<<1 | inbytes[n+3]<<0
if rr:
x = rev_bits_in_word(x)
crc = crc^x
for n in range(32):
crc = (crc<<1)
if crc&(1<<31):
crc = crc^POLY
crc=crc&0xffffffff #clamp to 32 bits
if rr:
crc = rev_bits_in_word(crc)
if xx:
crc = crc^0xffffffff
return crc
Solved! Go to Solution.
2019-02-07 08:56 AM
>>Does anyone have a proven concrete software implementation of the F4's hardware CRC module, either in c-like or python, that I can use to validate the firmware's output and complete my test script?
I've posted dozens of working examples over the years
//****************************************************************************
//
// STM32TST - CRC32 Computation on the ST Micro STM32 Test Module
// Copyright (C) 2014-2018, All rights reserved
//
// sourcer32@gmail.com
//
//****************************************************************************
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
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 Crc32Fast(uint32_t Crc, uint32_t Data)
{
static const uint32_t CrcTable[16] = { // Nibble lookup table for 0x04C11DB7 polynomial
0x00000000,0x04C11DB7,0x09823B6E,0x0D4326D9,0x130476DC,0x17C56B6B,0x1A864DB2,0x1E475005,
0x2608EDB8,0x22C9F00F,0x2F8AD6D6,0x2B4BCB61,0x350C9B64,0x31CD86D3,0x3C8EA00A,0x384FBDBD };
Crc = Crc ^ Data; // Apply all 32-bits
// Process 32-bits, 4 at a time, or 8 rounds
Crc = (Crc << 4) ^ CrcTable[Crc >> 28]; // Assumes 32-bit reg, masking index to 4-bits
Crc = (Crc << 4) ^ CrcTable[Crc >> 28]; // 0x04C11DB7 Polynomial used in STM32
Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
return(Crc);
}
//****************************************************************************
uint32_t Crc32FastBlock(uint32_t Crc, uint32_t Size, uint32_t *Data)
{
while(Size--)
Crc = Crc32Fast(Crc, *Data++); // 32-bit at a time
return(Crc);
}
//****************************************************************************
int main(int argc, char **argv)
{
uint32_t test[] = { 0x11223344, 0xB14257CC };
printf("%08X (0xB14257CC) Slow\n",Crc32(0xFFFFFFFF, 0x11223344)); // 0xB14257CC
printf("%08X (0xB14257CC) Fast\n",Crc32Fast(0xFFFFFFFF, 0x11223344)); // 0xB14257CC
printf("%08X (0x00000000) Block\n", Crc32FastBlock(0xFFFFFFFF, sizeof(test)/sizeof(uint32_t), test) );
// B14257CC (0xB14257CC) Slow
// B14257CC (0xB14257CC) Fast
// 00000000 (0x00000000) Block
return(0);
}
//****************************************************************************
2019-02-07 08:56 AM
>>Does anyone have a proven concrete software implementation of the F4's hardware CRC module, either in c-like or python, that I can use to validate the firmware's output and complete my test script?
I've posted dozens of working examples over the years
//****************************************************************************
//
// STM32TST - CRC32 Computation on the ST Micro STM32 Test Module
// Copyright (C) 2014-2018, All rights reserved
//
// sourcer32@gmail.com
//
//****************************************************************************
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
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 Crc32Fast(uint32_t Crc, uint32_t Data)
{
static const uint32_t CrcTable[16] = { // Nibble lookup table for 0x04C11DB7 polynomial
0x00000000,0x04C11DB7,0x09823B6E,0x0D4326D9,0x130476DC,0x17C56B6B,0x1A864DB2,0x1E475005,
0x2608EDB8,0x22C9F00F,0x2F8AD6D6,0x2B4BCB61,0x350C9B64,0x31CD86D3,0x3C8EA00A,0x384FBDBD };
Crc = Crc ^ Data; // Apply all 32-bits
// Process 32-bits, 4 at a time, or 8 rounds
Crc = (Crc << 4) ^ CrcTable[Crc >> 28]; // Assumes 32-bit reg, masking index to 4-bits
Crc = (Crc << 4) ^ CrcTable[Crc >> 28]; // 0x04C11DB7 Polynomial used in STM32
Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
return(Crc);
}
//****************************************************************************
uint32_t Crc32FastBlock(uint32_t Crc, uint32_t Size, uint32_t *Data)
{
while(Size--)
Crc = Crc32Fast(Crc, *Data++); // 32-bit at a time
return(Crc);
}
//****************************************************************************
int main(int argc, char **argv)
{
uint32_t test[] = { 0x11223344, 0xB14257CC };
printf("%08X (0xB14257CC) Slow\n",Crc32(0xFFFFFFFF, 0x11223344)); // 0xB14257CC
printf("%08X (0xB14257CC) Fast\n",Crc32Fast(0xFFFFFFFF, 0x11223344)); // 0xB14257CC
printf("%08X (0x00000000) Block\n", Crc32FastBlock(0xFFFFFFFF, sizeof(test)/sizeof(uint32_t), test) );
// B14257CC (0xB14257CC) Slow
// B14257CC (0xB14257CC) Fast
// 00000000 (0x00000000) Block
return(0);
}
//****************************************************************************
2019-02-07 12:08 PM
>The source data was simply 0x01020304
>F4's CRC output was: 0xA18723BA
How *exactly* did you produce that?
Besides Clive's program, the srecord package embeds also a STM32 CRC calculation (arguably it's not the easiest to use though). This is my favourite CRC online calculator http://www.zorc.breitbandkatze.de/crc.html with Clive's data (note the tickboxes' settings):
and your data:
One way how to check if your CRC calculation is not completely failed is to append the result to the checksummed data and perform the CRC again; the result should be 0 - this is what Clive did in hist last example.
JW
2019-02-07 12:22 PM
printf("%08X (B5E8B5CD) Slow\n",Crc32(0xFFFFFFFF, 0xF407A5C2)); // 0xB5E8B5CD AM I STM32 TEST
2019-02-08 02:05 AM
Awesome, thankyou. Apparently I lost my mind yesterday :)
2019-02-08 02:15 AM
"One way how to check if your CRC calculation is not completely failed is to append the result to the checksummed data and perform the CRC again; the result should be 0 - this is what Clive did in hist last example."
Thankyou, I'd completely forgotten about this!
I was able to prove my CRC function was in error, and then located the fault in fairly short order. (It was a daft typo mucking up the last word of the input data. Yesterday was a no brain day.)
2019-02-08 06:09 AM
> daft typo
Sometimes, those are the hardest to find. And there's also nobody to blaim! :)
JW
2019-02-09 04:44 PM
Also, note how the parameter x in your python function is destroyed before use...
-- pa
2019-02-11 02:16 AM
Thanks. Yes, I completely lost the plot and had two variables with the same name. :)
Also, param x should be false to match STM32CRC.
Corrected.
Though now the code I use looks like this:
from crccheck import crc
def crc32stm(inbytes):
inbytes = rev_bits_in_words(inbytes) #words bit reversed
crc32 = crc.Crc32.calc(inbytes)^0xffffffff
crc32 = rev_bits_in_word(crc32)
return crc32
Must have been Thursday. Never could get the hang of Thursdays.