STM32f42xx CRC stop/resume
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2019-08-21 10:26 PM
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
- Labels:
-
CRC
-
STM32F4 Series
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2019-08-22 5:44 AM
@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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2019-08-22 6:18 AM
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.
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2019-08-22 10:34 AM
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);
}
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2019-08-22 10:36 PM
Wow, that's amazing thank you very much!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2019-08-23 7:57 AM
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2019-08-23 8:35 AM
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.
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2019-08-23 8:52 AM
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)
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2019-08-23 9:17 AM
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));
}
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2019-08-23 10:22 AM
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
