cancel
Showing results for 
Search instead for 
Did you mean: 

How to calculate CRC register values?

torsten2
Associate II
Posted on April 22, 2016 at 12:31

Hi,

I need to implement an existing circa algorithm [1]. I have a table driven C implementation, but I would like to use the STM32L4 CRC peripheral. I�ve read the chapter in the reference manual, and I know which parameters the peripheral allows, but unfortunately, I fail to map them to the �usual� definitions of CRC algorithms. Is there any application note, that describes the �CRC computation� block in more details (I�ve tried to use the st.com-search, but that results just in sql errors)?

Any hint on how I would have to map a CRC algorithm with the following parameters to the parameters, the CRC peripheral is using?

   bits:       8

   poly:       0x9c

   init:       0x5a

   xor:        0x00

   reverse:    false

   non-direct: false

This should result in 0x18 for the test input �123456789� [2]. That�s the code, where I�ve tried to implement that algorithm:

    std::uint8_t calc_checksum8( const std::uint8_t* start, std::size_t size )

    {

        RCC->AHB1ENR |= RCC_AHB1ENR_CRCEN;

        CRC->CR       = ( CRC->CR & ~CRC_CR_POLYSIZE ) | CRC_CR_POLYSIZE_1;

        CRC->INIT     = 0x5a;

        CRC->POL      = 0x9c;

        CRC->CR      |= CRC_CR_RESET;

        for ( const std::uint8_t* end = start + size ; start != end; ++start )

            CRC->DR = *start;

        const std::uint32_t result = CRC->DR;

        RCC->AHB1ENR &= (~RCC_AHB1ENR_CRCEN);

        return result;

    }

But this results in: 0xfc.

I had the very same problem in the other direction. How can I describe the default CRC32 algorithm implemented by the STM32 hardware when it contains the reset defaults?

Thank you for any help, pointer or idea,

Torsten

[1] Koopman https://users.ece.cmu.edu/~koopman/roses/dsn04/koopman04_crc_poly_embedded.pdf

[2] http://zorc.breitbandkatze.de/crc.html

#stm32 #crc
7 REPLIES 7
Posted on April 22, 2016 at 17:22

I'll run the numbers, but try this to write 8-bit values instead of 32-bit ones

        for ( const std::uint8_t* end = start + size ; start != end; ++start )

            *((volatile uint8_t *)&CRC->DR) = *start;

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
torsten2
Associate II
Posted on April 22, 2016 at 17:44

Hi Clive,

thank you very much. That helped a lot. I wonder from which part of the reference manual, you've got that information. Does this mean, I could speed up the calculation by writing 4 bytes at once?

cheers,

Torsten
Posted on April 22, 2016 at 19:23

Years of experience, and inferred behaviour..

I think it is documented as variable width, the only way to get the C compiler to write the non 32-bit version is to cast the write. They could of used a union I guess, but that can be a pain.

Yes, I think you can write four bytes at once, although the endian stuff might give you a head-ache. The unit is a bit awkward and inflexible.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on April 22, 2016 at 19:41

C:\MSVC\CRC>crc9C
crc=18 Slow
crc=18 Quick
crc=18 Fast

// 8-bit CRC Model - sourcer32@gmail.com
#include <
windows.h
>
#include <
stdio.h
>
#include <
stdlib.h
>
#define POLY 0x9C // # 0x9c = x^8 +x^5 +x^4 +x^3 +1 (0x139) <=> (0x9c; 0x139)
unsigned char Slow_CRC_Cal8Bits(unsigned char crc, int Size, unsigned char *Buffer)
{
int i;
while(Size--)
{
crc = crc ^ *Buffer++;
for(i=0; i<
8
; i++)
{
if (crc & 0x80)
crc = (crc << 1) ^ POLY;
else
crc = (crc << 1);
}
}
return(crc);
}
unsigned char Quick_CRC_Cal8Bits(unsigned char crc, int Size, unsigned char *Buffer)
{
static const unsigned char CrcTable[] = {
0x00,0x9C,0xA4,0x38,0xD4,0x48,0x70,0xEC,
0x34,0xA8,0x90,0x0C,0xE0,0x7C,0x44,0xD8 };
while(Size--)
{
crc
= crc ^ *Buffer++;
crc = (crc << 4) ^ CrcTable[(crc >> 4) & 0xF];
crc = (crc << 
4
) ^ CrcTable[(crc >> 4) & 0xF];
}
return(crc);
}
unsigned char Fast_CRC_Cal8Bits(unsigned char crc, int Size, unsigned char *Buffer)
{
static const unsigned char CrcTable[] = {
0x00,0x9C,0xA4,0x38,0xD4,0x48,0x70,0xEC,
0x34,0xA8,0x90,0x0C,0xE0,0x7C,0x44,0xD8,
0x68,0xF4,0xCC,0x50,0xBC,0x20,0x18,0x84,
0x5C,0xC0,0xF8,0x64,0x88,0x14,0x2C,0xB0,
0xD0,0x4C,0x74,0xE8,0x04,0x98,0xA0,0x3C,
0xE4,0x78,0x40,0xDC,0x30,0xAC,0x94,0x08,
0xB8,0x24,0x1C,0x80,0x6C,0xF0,0xC8,0x54,
0x8C,0x10,0x28,0xB4,0x58,0xC4,0xFC,0x60,
0x3C,0xA0,0x98,0x04,0xE8,0x74,0x4C,0xD0,
0x08,0x94,0xAC,0x30,0xDC,0x40,0x78,0xE4,
0x54,0xC8,0xF0,0x6C,0x80,0x1C,0x24,0xB8,
0x60,0xFC,0xC4,0x58,0xB4,0x28,0x10,0x8C,
0xEC,0x70,0x48,0xD4,0x38,0xA4,0x9C,0x00,
0xD8,0x44,0x7C,0xE0,0x0C,0x90,0xA8,0x34,
0x84,0x18,0x20,0xBC,0x50,0xCC,0xF4,0x68,
0xB0,0x2C,0x14,0x88,0x64,0xF8,0xC0,0x5C,
0x78,0xE4,0xDC,0x40,0xAC,0x30,0x08,0x94,
0x4C,0xD0,0xE8,0x74,0x98,0x04,0x3C,0xA0,
0x10,0x8C,0xB4,0x28,0xC4,0x58,0x60,0xFC,
0x24,0xB8,0x80,0x1C,0xF0,0x6C,0x54,0xC8,
0xA8,0x34,0x0C,0x90,0x7C,0xE0,0xD8,0x44,
0x9C,0x00,0x38,0xA4,0x48,0xD4,0xEC,0x70,
0xC0,0x5C,0x64,0xF8,0x14,0x88,0xB0,0x2C,
0xF4,0x68,0x50,0xCC,0x20,0xBC,0x84,0x18,
0x44,0xD8,0xE0,0x7C,0x90,0x0C,0x34,0xA8,
0x70,0xEC,0xD4,0x48,0xA4,0x38,0x00,0x9C,
0x2C,0xB0,0x88,0x14,0xF8,0x64,0x5C,0xC0,
0x18,0x84,0xBC,0x20,0xCC,0x50,0x68,0xF4,
0x94,0x08,0x30,0xAC,0x40,0xDC,0xE4,0x78,
0xA0,0x3C,0x04,0x98,0x74,0xE8,0xD0,0x4C,
0xFC,0x60,0x58,0xC4,0x28,0xB4,0x8C,0x10,
0xC8,0x54,0x6C,0xF0,0x1C,0x80,0xB8,0x24 };
while(Size--)
{
crc = crc ^ *Buffer++;
crc = CrcTable[crc & 0xFF];
}
return(crc);
}
int main(int argc, char **argv)
{
unsigned char crc;
unsigned char test[] = ''123456789'';
/* The expected CRC value of test[] using the polynomial 0x9C is 0x18, when initialized with 0x5A */
printf(''crc=%02X Slow
'', Slow_CRC_Cal8Bits(0x5A, (sizeof(test) - 1), test));
printf(''crc=%02X Quick
'', Quick_CRC_Cal8Bits(0x5A, (sizeof(test) - 1), test));
printf(''crc=%02X Fast
'', Fast_CRC_Cal8Bits(0x5A, (sizeof(test) - 1), test));
return(1);
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on April 22, 2016 at 19:46

See also 'STM32 CRC Test App' for 32-bit example

CRC Thread

https://community.st.com/0D50X00009XkbNMSAZ

https://community.st.com/0D50X00009XkbNMSAZ#comment-67168

Edit: Fixed DEADLINK

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
torsten2
Associate II
Posted on April 22, 2016 at 20:48

From: clive1

See also ''STM32 CRC Test App'' for 32-bit example

[DEAD LINK /public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/CRC%20computation&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=1034]CRC Thread

I found that already some weeks ago (again, thanks a lot). Well, have a look at this comment, from our projects code base:

/*

 * crc32 code that does the same as the default configured STM crc periperhal

 * shamles stolen from clive1 from the ST forum.

 */

I really appreciate your help and I owe you a Beer 😉
Posted on April 20, 2017 at 14:30

 ,

 ,

 , ?