cancel
Showing results for 
Search instead for 
Did you mean: 

CRC computation

lowpowermcu
Associate II
Posted on January 12, 2011 at 13:46

CRC computation

#stm-crc32 #stm32f2-crc
45 REPLIES 45
amtb1968
Associate II
Posted on July 18, 2014 at 13:38

Dear Clive1:

  Why the CRC value calculated from ST's CRC_CalcBlockCRC() is different from this one you provided here? We use to read a file and compare the result from each other.  The example is as below~

DWORD CRCValue;

FILE *file;

file = fopen(''file.bin'', ''rb'');

fseek(file, 0L, SEEK_END);

sz = ftell(file);

fseek(file, 0L, SEEK_SET);

Buffer = (char*)malloc(sz);

fread(Buffer, 1, sz, file);

CRCValue = 0xFFFFFFFF;

for(int i=0; i < sz/4; i+=4){

CRCValue = Crc32Fast(CRCValue, *(Buffer+i));

}

////////////////////////

BR

Alan

Posted on July 18, 2014 at 14:48

Probably because you're passing bytes not words

CRCValue = Crc32Fast(CRCValue, *((DWORD *)(Buffer+i)));
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
adam23
Associate II
Posted on July 18, 2014 at 15:54

Just to want to let you all know, that we made many attempts to calculate the same CRC in a software that STM32L CRC HW unit does, but all in vain, especially if you want the same results e.g. on Intel.

After all we tried, the only code that is working, we got from ST support upon our request there.
Posted on July 18, 2014 at 16:12

CRC's by their nature are sensitive to bit and sequence errors, if you screw up the math you're going to get the wrong numbers.

The polynomial, endian-ness, and 32-bit data width of the STM32 are difficult for some people to get their heads around, especially if they rely on web sources for their testing and knowledge.

// STM32 CRC32 Test App - sourcer32@gmail.com
#include <
windows.h
>
#include <
stdio.h
>
DWORD Crc32(DWORD Crc, DWORD 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);
}
DWORD Crc32Fast(DWORD Crc, DWORD Data)
{
static const DWORD 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);
}
void test(void)
{
BYTE vector[12] = { 0x02,0x07,0x02,0x00,0x18,0x8A,0xD0,0x23,0x25,0x2B,0x09,0x00 };
DWORD Crc;
int i;
for(i=0; i<12; i++)
printf(''%02X '',vector[i]);
putchar('
');
Crc = 0xFFFFFFFF; // Initial state
for(i=0; i<12; i+=4)
{
Crc = Crc32Fast(Crc, *((DWORD *)&vector[i]) ); // 4-bytes at a time
}
printf(''%08X test
'',Crc);
}
int main(int argc, char **argv)
{
printf(''%08

X'',Crc32(0xFFFFFFFF, 0x12345678)); // 0xDF8A8A2B
printf(''%08

X'',Crc32Fast(0xFFFFFFFF, 0x12345678)); // 0xDF8A8A2B
test();
return(1);
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on July 18, 2014 at 16:37

// STM32 CRC32 Test App - sourcer32@gmail.com
#include <
windows.h
>
#include <
stdio.h
>
#include <
stdlib.h
>
//****************************************************************************
DWORD Crc32(DWORD Crc, DWORD 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);
}
//****************************************************************************
DWORD Crc32Block(DWORD Crc, DWORD Size, DWORD *Buffer) // 32-bit units
{
while(Size--)
Crc
= 
Crc32
(Crc, *Buffer++);
return(Crc);
}
//****************************************************************************
DWORD Crc32Fast(DWORD Crc, DWORD Data)
{
static const DWORD 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);
}
//****************************************************************************
DWORD Crc32FastBlock(DWORD Crc, DWORD Size, DWORD *Buffer) // 32-bit units
{
while(Size--)
Crc = Crc32Fast(Crc, *Buffer++);
return(Crc);
}
//****************************************************************************
void test(void)
{
BYTE vector[12] = { 0x02,0x07,0x02,0x00,0x18,0x8A,0xD0,0x23,0x25,0x2B,0x09,0x00 }; // ACD7E298
DWORD Crc;
int i;
for(i=0; i<
sizeof
(vector); i++)
printf(''%02X '',vector[i]);
putchar('
');
Crc
= 
0xFFFFFFFF
; // Initial state
for(
i
=
0
; i<sizeof(vector); i+=4)
{
Crc
= 
Crc32Fast
(Crc, *((DWORD *)&vector[i]) ); // 4-bytes at a time
}
printf(''%08X %08X test
'',Crc, Crc32FastBlock(0xFFFFFFFF, sizeof(vector)/4, (void *)vector));
}
//****************************************************************************
void TestFile(char *Filename)
{
FILE *f;
DWORD Size;
BYTE *Buffer;
f
= 
fopen
(Filename, ''rb'');
if (f)
{
fseek(f, 0, SEEK_END);
Size
= 
ftell
(f);
fseek(f, 0, SEEK_SET);
if (Size & 3)
printf(''WARNING: File must be multiple of 4 bytes (32-bit) for valid results
'');
Buffer
= 
malloc
(Size);
fread(Buffer, Size, 1, f);
fclose(f);
printf(''crc=%08X Slow
'', Crc32Block(0xFFFFFFFF, Size >> 2, (void *)Buffer));
printf(''crc=%08X Fast
'', Crc32FastBlock(0xFFFFFFFF, Size >> 2, (void *)Buffer));
free(Buffer);
}
else
printf(''ERROR: Unable to open file '%s'
'', Filename);
}
//****************************************************************************
int main(int argc, char **argv)
{
printf(''STM32CRC Test

Usage: STM32CRC [<
file
>]

'');
if ((Crc32(0xFFFFFFFF, 0x12345678) != 0xDF8A8A2B) ||
(Crc32Fast(0xFFFFFFFF, 0x12345678) != 0xDF8A8A2B))
{
printf(''ERROR: Internal Sanity Check Failed
'');
}
if (argc > 1)
TestFile(argv[1]);
else
test();
return(1);
}
//****************************************************************************

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
amtb1968
Associate II
Posted on July 21, 2014 at 04:52

Dear Adam:

  Thanks for your kindly help. According to you and Clive1's suggestion, we try to find the discussion from web and we try some examples for both STM and PC side. We found one matching calculation. Because the calculation on ST is not the standard way for CRC32, it needs to modify to match the standard calculation. Below is the example for reference, hope it can help others. By the way, thanks Adam and Clive1.

//====== PC side====================

//--------CRC32.c---------------------------------------

ULONG Table[256];

ULONG CRC;

ULONG Reflect(ULONG ref, char ch)

{

    ULONG value = 0;

    // Swap bit 0 for bit 7

    // bit 1 for bit 6, etc.

    for(int i = 1; i < (ch + 1); i++)

    {

        if (ref & 1)

            value |= 1 << (ch - i);

        ref >>= 1;

    }

    return value;

}

void CRC_32()

{

    // This is the official polynomial used by CRC-32 

    // in PKZip, WinZip and Ethernet. 

    ULONG ulPolynomial = 0x04C11DB7;

    // 256 values representing ASCII character codes.

    for (int i = 0; i <= 0xFF; i++)

    {

        Table[i] = Reflect(i, 8) << 24;

        for (int j = 0; j < 8; j++)

            Table[i] = (Table[i] << 1) ^ (Table[i] & (1 << 31) ? ulPolynomial : 0);

        Table[i] = Reflect(Table[i], 32);

    }

}

void CRC32_Calculate(const LPBYTE buffer, UINT size, ULONG &CRC)

{   // calculate the CRC

    LPBYTE pbyte = buffer;

    while (size--)

        CRC = (CRC >> 8) ^ Table[(CRC & 0xFF) ^ *pbyte++];

}

//--------main.c--------------------------------------------

CRC_32();

CRC = 0xFFFFFFFF;

CRC32_Calculate((LPBYTE)Buffer, sz, CRC);

CRC ^= 0xFFFFFFFF;

//========== STM32F side===========

/**********************

reverse bits of DWORD

Input:

  u32 data -- the input

Output:

  u32 data -- the output

**********************/

uint32_t revbit(uint32_t data)

{

  asm(''rbit r0,r0'');

  return data;

};

/**********************

Calculate CRC32 of DWORD data array.

Input:

  u32 *dworddata -- the array point

  u32 dwordcount -- the data len in DWORD

Output:

  u32 CRC32 -- the result

**********************/

uint32_t CalcCRC32(uint32_t *dworddata,uint32_t dwordcount)

{

  uint32_t ui32;

  for(;dwordcount>0;dwordcount--)

  {

    ui32=*dworddata;

    dworddata++;

    ui32=revbit(ui32);

    CRC->DR=ui32;

  }

  ui32=CRC->DR;

  ui32=revbit(ui32);

  ui32^=0xffffffff;

  return ui32;

};

//========================================

hospodar
Associate III
Posted on May 14, 2015 at 17:55

Hi clive,

is it possible to use CRC unit in STM32F1 (which compute 32 bit CRC) to compute just 16 bit CRC for Modbus protocol? If yes, how?

Posted on May 14, 2015 at 18:21

Hi Ivan,No the F1 implementation has a fixed polynomial and bit width, with software bit reversal it can do the equivalent to the 'PKZIP' style computation.MODBUS requires different hardware support. See my thread related to the F3 doing MODBUS in hardware.

https://community.st.com/0D50X00009XkgXtSAJ

 

Edit: Fixed DEADLINK, original post from 14-May-2015

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
tba10596
Associate II
Posted on August 31, 2015 at 17:10

Full hardware method works with this caveat:

instead of using  asm('' rbit r0,r0'');  I used  return  __RBIT(value); which is a CMSIS intrinsic that will work with my compiler.

myidsas
Associate
Posted on November 21, 2015 at 14:07

Hi scaldov.miroslav,

thanks for Ur conclusion and summarizing...

the function is working well if buffer length will more than 4-byte but it does not work correct if buffer length will less than 4-byte.

I believe that it is because of initial value of variable in function.

if U or any one could fix it, I'll appreciate.

Best Regards