Skip to main content
christophe239955_stm1
Associate II
January 20, 2010
Question

CRC calculation unit initialize

  • January 20, 2010
  • 8 replies
  • 3447 views
Posted on January 21, 2010 at 00:51

CRC calculation unit initialize

    This topic has been closed for replies.

    8 replies

    christophe239955_stm1
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 13:38

    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.

    clive2
    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 13:38

    >>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

    QED

    good2dog
    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 13:38

    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.

    regards

    Tesla DeLorean
    Guru
    May 17, 2011
    Posted on May 17, 2011 at 13:38

    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

    }

    -Clive
    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    clive2
    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 13:38

    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

    }

    -Clive

    Tesla DeLorean
    Guru
    May 17, 2011
    Posted on May 17, 2011 at 13:38

    ''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

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    good2dog2
    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 13:38

    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.

    Tesla DeLorean
    Guru
    May 17, 2011
    Posted on May 17, 2011 at 13:38

    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);

    }

    -Clive
    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..