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

Posted on May 17, 2011 at 14:21

The CRC processes 32-bits at a time, applying them in a small-endian fashion. It is not performed byte wise in the manner most online testers use.

It can be computed on the STM32 or x86 PC with the following code. The nibble table method is a trade off between speed and space.

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);
 }
 
 {
  printf(''%08X\n\n'',Crc32(0xFFFFFFFF, 0x12345678)); // 0xDF8A8A2B
 
 printf(''%08X\n\n'',Crc32Fast(0xFFFFFFFF, 0x12345678)); // 0xDF8A8A2B
 }
 

 Edit: Cleaning up forum migration artifacts

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
trevor23
Associate III
Posted on May 17, 2011 at 14:21

@lowpowermcu

See this forum post (by mcuisp) on how to make STM32 calculate CRC same as x86 PC (by reversing the bits of the 32 bit values fed into the CRC hadrware).

https://my.st.com/public/STe2ecommunities/mcu/Lists/ARM%20CortexM3%20STM32/Flat.aspx?RootFolder=https://my.st.com/public/STe2ecommunities/mcu/Lists/ARM CortexM3 STM32/CRC calculation in software&FolderCTID=0x01200200770978C69A1141439FE559EB459D758000626BE2B829C32145B9EB5739142DC17E&currentviews=1773

Slightly off topic but does anyone know how to calculate CRC using STM32 hardware when number of bytes is not a multiple of 4?

Posted on May 17, 2011 at 14:21

Slightly off topic but does anyone know how to calculate CRC using STM32 hardware when number of bytes is not a multiple of 4?

 

Make one up and apply it consistently.

The way the register feeds is not conducive to byte level operation, or any ''standard'' method. Either pad the 32-bit word with zeros and perform a full 32-bit cycle, or shift your byte(s) to the high order end of the register, or perform a couple of byte wide computations in software.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
trevor23
Associate III
Posted on May 17, 2011 at 14:21

Hi Clive1,

 

 

Either pad the 32-bit word with zeros and perform a full 32-bit cycle, or shift your byte(s) to the high order end of the register

But wouldn't the extra zeros/padding change the CRC thus generating a CRC that is differient to how ''the other end'' will calculate it? I don't want to have a ''non-standard'' CRC imlementation at ''the other end''.

or perform a couple of byte wide computations in software.

 

Yes that would do it.

Posted on May 17, 2011 at 14:21

But wouldn't the extra zeros/padding change the CRC thus generating a CRC that is differient to how ''the other end'' will calculate it? I don't want to have a ''non-standard'' CRC imlementation at ''the other end''.

 

It doesn't feed correctly anyway for byte wise operation, so I'm not sure what ''standard'' you have in mind. The polynomial is one of a number classically used, but you'd need to endian swap the bytes on a little-endian machine, which is not happening here, for it to be generated normally.

So my point is if you pick a method, you have defined the ''standard'', and you apply the same computation at each end of the link.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
trevor23
Associate III
Posted on May 17, 2011 at 14:21

Only if you have control over the other end of the link. The STM32 hardware can calculate the most popular CRC32 (PKZIP, WINRAR, XVI hex editor etc. etc. ) if you reverse the bits as you feed it and reverse the bits at the end (as per link above). I may have a play with this but I suspect the approach of software CRCing the leftover bytes might be the only way to do this. As only 3 bytes max would need software CRCing this would have little speed impact. will report back my findings.

Thanks

Trevor

Posted on May 17, 2011 at 14:21

You'd have to do it in software, because the register only does the math 32-bits at a time, and you need to do 8, 16, or 24 bits

It's really a pity they didn't use a right-shifting model, rather than the left-shifting one.

So you'd need to bit-reverse all the 32-bit words, then read the CRC register, bit-reverse that, apply your remaining 0 to 3 bytes using a right-shifting model in software.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on May 17, 2011 at 14:21

Now I could probably reimplement with a table driven varient but this should prove the concept.

u32 revbit(u32 data)

{

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

  return data;

};

u32 CalcCRC32(u8 *buffer,u32 size)

{

  u32 i, j;

  u32 ui32;

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC,ENABLE);

  CRC->CR=1;

  asm(''NOP'');asm(''NOP'');asm(''NOP'');//delay for hardware ready

  i = size >> 2;

  while(i--)

  {

    ui32=*((u32 *)buffer);

    buffer += 4;

    ui32=revbit(ui32);//reverse the bit order of input data

    CRC->DR=ui32;

  }

  ui32=CRC->DR;

  ui32=revbit(ui32);//reverse the bit order of output data

  i = size & 3;

  while(i--)

  {

    ui32 ^= (u32)*buffer++;

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

      if (ui32 & 1)

        ui32 = (ui32 >> 1) ^ 0xEDB88320;

      else

        ui32 >>= 1;

  }

  ui32^=0xffffffff;//xor with 0xffffffff

  return ui32;//now the output is compatible with windows/winzip/winrar

};
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
lowpowermcu
Associate II
Posted on May 17, 2011 at 14:21

Hi all,

Thanks for everybody.

Now I need a clarification, the reverse operation before and after computing the CRC, is it related to little endian/big endian ?

I am looking for a tool with which I can validate the CRC computation but I can't find one that corresponds to STM32. What I find is using big endian. Do you have one ?

Thanks  again,

MCU Lüfter