2009-09-05 05:24 AM
CRC calculation in software
2011-05-17 04:17 AM
I spent a *large* amount of time recently determining this. The trouble is that the web is full of ''CRC programs'' and many produce different but valid results. The issue is that CRC's are bit based but programmers typically operate on bytes or words.
My advice, to all, is to read (and understand) this paper on the subjecthttp://www.ross.net/crc/download/crc_v3.txt
This contains C source code that parameterizes all the variant ways of calculating CRC's (unlike most stuff you'll find with Google). I wrote my own program, using crcmodel.c & crcmodel.h from the above file, to calculate CRC's the same (undocumented) way that the STM32 CRC unit does. Here it is for the benefit of all :)Code:
<BR>////////////////////////////////////////////////////////////////////////// <BR>// <BR>// FUNCTION NAME : <BR>// CRC_CalcBlockCRC <BR>// <BR>// <BR>// FUNCTIONAL DESCRIPTION : <BR>// Calculate a CRC the same way as the STM32F10x hardware generator. <BR>// <BR>// <BR>// FORMAL INPUT PARAMETERS : <BR>// buffer - pointer to series of 32-bit words (NOT bytes). <BR>// words - count of 32-bit words to do. <BR>// <BR>// <BR>// FORMAL OUTPUT PARAMETERS : <BR>// None <BR>// <BR>// <BR>// RETURN VALUE : <BR>// 32-bit CRC value as per the STM32F10x CRC generator. <BR>// <BR>// <BR>// IMPLICIT INPUTS AND OUTPUTS : <BR>// None <BR>// <BR>// <BR>// IMPORTED FUNCTIONS AND MACROS : <BR>// cm_ini(), cm_nxt(), cm_crc() <BR>// <BR>// <BR>////////////////////////////////////////////////////////////////////////// <BR> <BR>static crc32_t CRC_CalcBlockCRC(ulword *buffer, ulword words) <BR>{ <BR>cm_t crc_model; <BR>ulword word_to_do; <BR>ubyte byte_to_do; <BR>int i; <BR> <BR> // Values for the STM32F generator. <BR> <BR> crc_model.cm_width = 32; // 32-bit CRC <BR> crc_model.cm_poly = 0x04C11DB7; // CRC-32 polynomial <BR> crc_model.cm_init = 0xFFFFFFFF; // CRC initialized to 1's <BR> crc_model.cm_refin = FALSE; // CRC calculated MSB first <BR> crc_model.cm_refot = FALSE; // Final result is not bit-reversed <BR> crc_model.cm_xorot = 0x00000000; // Final result XOR'ed with this <BR> <BR> cm_ini(&crc_model); <BR> <BR> while (words--) <BR> { <BR> // The STM32F10x hardware does 32-bit words at a time!!! <BR> <BR> word_to_do = *buffer++; <BR> <BR> // Do all bytes in the 32-bit word. <BR> <BR> for (i = 0; i < sizeof(word_to_do); i++) <BR> { <BR> // We calculate a *byte* at a time. If the CRC is MSB first we <BR> // do the next MS byte and vica-versa. <BR> <BR> if (crc_model.cm_refin == FALSE) <BR> { <BR> // MSB first. Do the next MS byte. <BR> <BR> byte_to_do = (ubyte) ((word_to_do & 0xFF000000) >> 24); <BR> word_to_do <<= 8; <BR> } <BR> else <BR> { <BR> // LSB first. Do the next LS byte. <BR> <BR> byte_to_do = (ubyte) (word_to_do & 0x000000FF); <BR> word_to_do >>= 8; <BR> } <BR> <BR> cm_nxt(&crc_model, byte_to_do); <BR> } <BR> } <BR> <BR> // Return the final result. <BR> <BR> return (cm_crc(&crc_model)); <BR>} <BR>
Edit: BTW the above was written to be endian independent--that is it should work on big or little endian machines. [ This message was edited by: swhite on 16-07-2009 20:35 ]2011-05-17 04:17 AM
Hi everyone,
once again, does someone know, where to find software algorithm for CRC calculation that works in the same way like the hardware CRC calculation unit. I want to write a tool which creates a .bin-file from the linker output hex-file and calculates the CRC32 in the same way as the STM32 does. Is there anyone, who tried CRC calculation unit in STM32 family??2011-05-17 04:17 AM
Hi Friends,
See my post here with full C code : Cheers, STOne-32. [ This message was edited by: STOne-32 on 16-07-2009 23:09 ]2011-05-17 04:17 AM
STOne-32,
I saw your code in a previous post, but with respect it doesn't document clearly *how* the STM32 calculates CRC's. That's why I posted my code and why I used generic CRC calculation code (from crc_v3.txt). In short the STM32: Calculates MSB (most significant bit first)--that is bit 32 - bit 0. (and hence 32-bit words go in the order MS-LS byte). Most PC software out there is byte-oriented and hence (since 80x86's are little endian) won't calculate the same result even if everything else is equal. The end result is NOT inverted as per CRC-32.2011-05-17 04:17 AM
Hello swhite,
:p :p Respect !! You are really the first one who writes a C-code that produces the same CRC32 as the hardware unit of the STM32 does! My tests with your code were successful. Thank´s again Reinhard2011-05-17 04:17 AM
Quote:
The end result is NOT inverted as per CRC-32.
What do you mean by ''CRC-32'' there? Without qualification, ''CRC-32'' just tells us that the CRC result has 32 bits; it says nothing about the alrogithm used to generate that 32-bit result - ie, the initial condition, polynomial, byte order, final operations (such as inversion), etc, etc. As you said initially,Quote:
the web is full of ''CRC programs'' and many produce different but valid results
Which does, of course, back-up your point that the STM32's hardware CRC unit is pretty useless when its algorithm is not completely documented! :| [ This message was edited by: st7 on 18-07-2009 10:31 ]2011-05-17 04:17 AM
2011-05-17 04:17 AM
It is such a shame that the polynomial is not configurable for the CRC32 hardware. For this reason I (and many others) cannot use it and must do it in software. On that note be aware that the code above uses the slower non-table method to calculate CRCs. The table method is much faster if speed is an issue. The table fits in 1k of program memory or if program memory is scarce (as it often is in a bootloader) you can generate the table in 1k of RAM (bootloaders usually have lots of spare RAM).
[ This message was edited by: trevor on 18-07-2009 13:48 ]2011-05-17 04:17 AM
Many thanks to swhite for his fine work here.
I've needed this also, since I'm working on a system where an ARM-7 needs to communicate with a Cortex M3, which is using its hardware CRC for messages. Been using ST-One's algorithm until now, which works, but it is quite slow (no offense). I've implemented the table-driven version, the code is attached, for those who just want to get it working. Note that (like the STM hardware) it works on 32-bit words, NOT bytes. Code is in the attached TXT file - a couple of #defines, the lookup table, and a crc generator function. It expects uint8_t and uint32_t types, which are unsigned 8/32 bit variables. Replace these with whatever you're using. cheers, Brian