2011-01-12 04:46 AM
2011-05-17 05:21 AM
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
2011-05-17 05:21 AM
@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¤tviews=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?2011-05-17 05:21 AM
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.
2011-05-17 05:21 AM
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.
2011-05-17 05:21 AM
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.
2011-05-17 05:21 AM
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 Trevor2011-05-17 05:21 AM
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.2011-05-17 05:21 AM
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 };2011-05-17 05:21 AM
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