cancel
Showing results for 
Search instead for 
Did you mean: 

STM32f42xx CRC stop/resume

stucmath
Associate II

Hello

Since the STM32f42xx series has no intial value for the CRC I'm wondering if there is a way to stop a crc calculation (store the DR value) and resume it by writing the DR register with the stored value and some calculation??

Something like this:

crcvalue1 = HAL_CRC_Calculate(&CRCType, &byte_array_hex[0], 37000);
__HAL_CRC_DR_RESET(&CRCType);
CRCType.Instance->DR = crcvalue1;
crcvalue2 = HAL_CRC_Accumulate(&CRCType, &byte_array_hex[37000], 13000);

The goal is to interrupt a ongoing CRC calculaton with a higher prioritized calculation and afterwards resume to the lower priority again.

Kind regards

Mathias

17 REPLIES 17

@Community member​ is the expert in the field; see for examle https://community.st.com/s/question/0D50X00009XkbxTSAR/crc-calculation-unit-initialize (misformatting courtesy of failed forum software conversions).

JW

The F4 lacks access to the register, setting 0xFFFFFFFF or 0x00000000 is relatively easy/cheap, other values require a computation.

Bit of a design oversight in my opinion, could have been implemented trivially.

I can probably generate a more efficient table driven version.

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

Ok, there was a restartable table driven version too

https://community.st.com/s/global-search/0x82608EDB

crcvalue1 = HAL_CRC_Calculate(&CRCType, &byte_array_hex[0], 37000);
//...
__HAL_CRC_DR_RESET(&CRCType);
//...
if (CRCType.Instance->DR != crcvalue1) // ... Some Time Later
  CRCType.Instance->DR = ReverseCRC32(CRCType.Instance->DR, crcvalue1);
 
crcvalue2 = HAL_CRC_Accumulate(&CRCType, &byte_array_hex[37000], 13000);
 
 
 
static uint32_t ReverseCRC32(uint32_t currentCRC, uint32_t desiredCRC)
{
  static const uint32_t CrcTable[16] = { // For 0x04C11DB7 Reverse Polynomial  sourcer32@gmail.com
    0x00000000, 0xB2B4BCB6, 0x61A864DB, 0xD31CD86D, 0xC350C9B6, 0x71E47500, 0xA2F8AD6D, 0x104C11DB,
    0x82608EDB, 0x30D4326D, 0xE3C8EA00, 0x517C56B6, 0x4130476D, 0xF384FBDB, 0x209823B6, 0x922C9F00 };
 
  if (desiredCRC == 0) // Optimization, applying CRC to self will clear
    return(currentCRC);
 
  desiredCRC = (desiredCRC >> 4) ^ CrcTable[desiredCRC & 0x0F];
  desiredCRC = (desiredCRC >> 4) ^ CrcTable[desiredCRC & 0x0F];
  desiredCRC = (desiredCRC >> 4) ^ CrcTable[desiredCRC & 0x0F];
  desiredCRC = (desiredCRC >> 4) ^ CrcTable[desiredCRC & 0x0F];
  desiredCRC = (desiredCRC >> 4) ^ CrcTable[desiredCRC & 0x0F];
  desiredCRC = (desiredCRC >> 4) ^ CrcTable[desiredCRC & 0x0F];
  desiredCRC = (desiredCRC >> 4) ^ CrcTable[desiredCRC & 0x0F];
  desiredCRC = (desiredCRC >> 4) ^ CrcTable[desiredCRC & 0x0F]; 
 
  return(desiredCRC ^ currentCRC);
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
stucmath
Associate II

Wow, that's amazing thank you very much!

stucmath
Associate II

Since you ar the expert on this topic.

Is there a way to convert a CRC32b to CRC32 value?

My problem is: With the STM32F4 I have to get the same CRC value as the Fujitsu FM3 CRC (MB9BF416N) calculates (for retro compatibilty).

Configuration of the Fujitsu FM3 CRC:

void CRC_crcInit()
{
   bFM3_CRC_CRCCR_FXOR   = 1;               // XOR Result       : 0 = None,       1 = Yes
   bFM3_CRC_CRCCR_CRCLSF = LSB_FIRST;       // Result Bitorder  : 0 = MSB First,  1 = LSB First
   bFM3_CRC_CRCCR_CRCLTE = LITTLE_ENDIAN;   // Result Byteorder : 0 = Big endian, 1 = Little Endian
   bFM3_CRC_CRCCR_LSBFST = LSB_FIRST;       // Input Bit-order  : 0 = MSB First,  1 = LSB First
   bFM3_CRC_CRCCR_LTLEND = LITTLE_ENDIAN;   // Input Byteorder  : 0 = Big endian, 1 = Little Endian
   bFM3_CRC_CRCCR_CRC32  = 1;               // Mode             : 0 = CRC16,      1 = CRC32
}

I calculated the CRC on both uC.

Input value: 0x12345678

STM result: 0xdf8a8a2b

Fujitsu result: 0xaf6d87d2

I think the STM uC works with the CRC32b algorithm while the Fujitsu works with the CRC32.

What do you think? Is there a chance to get the same result without changing the CRC settings from the fujitsu controller?

Kind regards

Mathias

The CRC on the STM32 (F1/F2/F4) is fixed and awkward, done 32-bit at a time, with the wrong endianess.

Later STM32 designs had a programmable CRC peripheral, but the design could have been executed far better.

The FM3 seems to use the same polynomial (0x04C11DB7), the byte order is probably correct.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
stucmath
Associate II

Yes thats right, the FM3 has the same polynomial.

I did some testing with the FM3 uC. I changed the CRC Input Byteorder from little endian to big endian and I received this crc value:

0x4A090E98

On the STM uC I did an XOR calculation the the result value:

0xDF8A8A2B^0xFFFFFFFF = 0x207575D4

Then I check these two values with an online CRC calculator (https://crccalc.com)

0690X00000AAD43QAH.png

But I have no Idea what the difference between these two calculations are.

Is there a way to get from one to the other value with a calculation?

 crc = Crc32(0xFFFFFFFF, revbit(0x12345678));

 crc = ~revbit(crc); // 0xAF6D87D2

 printf("%08X\n", crc);

Intrinsic is __RBIT

uint32_t revbit(uint32_t data) // IAR
{
  asm("rbit r0,r0");
  return data;
}
 
__asm uint32_t revbit(uint32_t data) // KEIL
{
  rbit r0, r0
  bx lr
}
 
uint32_t revbit(uint32_t data) // C
{
  int i;
  uint32_t rev = 0;
 
  for(i=0; i<32; i++)
    rev |= ((data >> i) & 1) << (31 - i);
 
  return rev;
}
 
uint32_t CalcCRC32FM3(uint32_t *buffer, uint32_t count) // sourcer32@gmail.com
{
  while(count--)
    CRC->DR = revbit(*buffer++); // rbit r0,r0
 
  return(~revbit(CRC->DR));
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
    static const uint32_t testArray[] = {0x12345678, };
    static volatile uint32_t result;
 
    CRC->CR = CRC_CR_RESET;
    __asm("nop \n\t nop \n\t nop"); // to avoid the HW bug described in https://community.st.com/s/feed/0D50X00009XkW6NSAV
 
    uint32_t i;
    for (i = 0; i < sizeof(testArray) / sizeof(testArray[0]); i++) {
      CRC->DR = __RBIT(testArray[i]);
    }
 
    result = __RBIT(CRC->DR) ^ 0xFFFFFFFF;
    // (gdb) p /x result
    // $14 = 0xaf6d87d2

JW