2011-01-12 04:46 AM
2014-07-18 04:38 AM
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)); }////////////////////////BRAlan2014-07-18 05:48 AM
Probably because you're passing bytes not words
CRCValue = Crc32Fast(CRCValue, *((DWORD *)(Buffer+i)));2014-07-18 06:54 AM
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.2014-07-18 07:12 AM
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);
}
2014-07-18 07:37 AM
// 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);
}
//****************************************************************************
2014-07-20 07:52 PM
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 DWORDInput: u32 data -- the inputOutput: 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 DWORDOutput: 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;};//========================================2015-05-14 08:55 AM
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?2015-05-14 09:21 AM
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
2015-08-31 08:10 AM
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.2015-11-21 05:07 AM
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