2010-01-20 03:51 PM
CRC calculation unit initialize
2011-05-17 04:38 AM
As described in the reference manual, the initial-value (reset) cannot be set to something else than 0xFFFFFFFF. This leads into a problem if you want to build the CRC over the whole flash memory and cannot do this without making some breakes in between. If you use the CRC unit in such a break for other things (interface, RAM-check, etc.), there is no possibility to restore the old CRC value and resume the flash-check.
Theoretically it should be possible to calculate (reverse CRC?) a value upon the old CRC. This value can then be written into the CRC_DR unit and as a result there will be the old CRC value in CRC_DR. In other words: A initializing function for the CRC based upon a given value and the init-value 0xFFFFFFFF. The function could look like this:Code:
CRC_Init(Init_Value)
{ uint32_t RevCRC; CRC_ResetDR(); //Reset the CRC data register (reset-value 0xFFFFFFFF) RevCRC = ... //Do reverse CRC based on Init_Value and reset-value CRC_CalcCRC(RevCRC); //after this step: CRC->DR == Init_Value } Has someone done this already? Any tips would be great.2011-05-17 04:38 AM
hi,
it may be useful a function that clear CRC to 0x00000000 , starting from the reset value 0xFFFFFFFF : CRC_ResetDR(); //Reset the CRC data register (reset-value 0xFFFFFFFF) CRC_CalcCRC(RevCRCclear); //after this step: CRC->DR == 0X00000000 then it's easy to initialise CRC at any value you want, calling CRC_CalcCRC(any_init_value_you_want) that's all. now I'm going to calculate magic number RevCRCclear. regards2011-05-17 04:38 AM
>>now I'm going to calculate magic number RevCRCclear
Wouldn't you just use 0xFFFFFFFF ? Seeing as it XOR's a bit and feeds it back to the remaining taps? -Clive CRC FFFFFFFF - Before CRC_CalcCRC(0xFFFFFFFF); CRC 00000000 - After QED2011-05-17 04:38 AM
To zero in any condition the following should work
CRC_CalcCRC(CRC_GetCRC()); To get to some other arbitary value CRC_CalcCRC(Crc32Rev(CRC_GetCRC(),0x12345678)); Where the forward and reverse functions are implemented as follow. These are simple serial implementations for illustration. Source for Win32 testing is attached. typedef unsigned long DWORD; DWORD Crc32(DWORD Crc, DWORD Data) { int i; Crc = Crc ^ Data; for(i=0; i if (Crc & 0x80000000) Crc = (Crc << 1) ^ 0x04C11DB7; // Polynomial used in STM32 else Crc = (Crc << 1); return(Crc); } DWORD Crc32Rev(DWORD CurrentCrc, DWORD DesiredCrc) { DWORD Data; int i; for(i=0; i if (DesiredCrc & 0x00000001) #if 1 DesiredCrc = ((DesiredCrc ^ 0x04C11DB7) >> 1) | 0x80000000; // Long form #else // or DesiredCrc = (DesiredCrc >> 1) ^ 0x82608EDB; // Back feeding polynomial #endif else DesiredCrc = (DesiredCrc >> 1); Data = DesiredCrc ^ CurrentCrc; return(Data); // Data Pattern to get Desired CRC from Current CRC } -Clive2011-05-17 04:38 AM
Well the conversion to the new forum dumped the attachment, and messed with the formatting.
See paper clip icon in upper right for attachment 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 Crc32Rev(DWORD CurrentCrc, DWORD DesiredCrc) { DWORD Data; int i; for(i=0; i<32; i++) if (DesiredCrc & 0x00000001) #if 1 DesiredCrc = ((DesiredCrc ^ 0x04C11DB7) >> 1) | 0x80000000; // Long form #else // or DesiredCrc = (DesiredCrc >> 1) ^ 0x82608EDB; // Back feeding polynomial #endif else DesiredCrc = (DesiredCrc >> 1); Data = DesiredCrc ^ CurrentCrc; return(Data); // Data Pattern to get Desired CRC from Current CRC } -Clive2011-05-17 04:38 AM
Here is a parallel implementation of the STM32 CRC function in software. By doing 4-bits at a time we only need 16 table entries, this could be done 8-bits at a time, but that would require 256 table entries (1KB). A Thumb2 version would be faster and more compact.
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); } -Clive2011-05-17 04:38 AM
it may be useful a function that clear CRC to 0x00000000 , starting from the reset value 0xFFFFFFFF :
CRC_ResetDR(); //Reset the CRC data register (reset-value 0xFFFFFFFF) CRC_CalcCRC(RevCRCclear); //after this step: CRC->DR == 0X00000000 then it's easy to initialise CRC at any value you want, calling CRC_CalcCRC(any_init_value_you_want) now I'm going to calculate magic number RevCRCclear.2011-05-17 04:38 AM
''it should be 0xC704DD7B, regards''
What, care to elaborate? The function of this code has been verified on an STM32. crc Initializing CRC Unit CRC FFFFFFFF (0xFFFFFFFF) CRC_CalcCRC(0xFFFFFFFF) CRC 00000000 (0x00000000) crcreset 12345678 CRC 00000000 CRC_CalcCRC(0x85C34F1E) CRC 12345678 -Clive