which algorithm to check STM32F4 CRC32
Moderators: RoccoMarco, lbednarz, tfAteba
which algorithm to check STM32F4 CRC32
It seems I can't find the right algorithm to check the CRC-32 I get from the STM32F4xx.
The use of the CRC register seems simple enough but I can't reproduce the result on my linux computer sending the data.
I'm sending 1280 bytes over USB to the STM32F4xx-Discover and if I do a simple sum-checksum I get the correct result (the board sends it back to the PC over USB)
so there is reason to believe the data is correct at least for debugging.
The use of the CRC register seems simple enough but I can't reproduce the result on my linux computer sending the data.
I'm sending 1280 bytes over USB to the STM32F4xx-Discover and if I do a simple sum-checksum I get the correct result (the board sends it back to the PC over USB)
so there is reason to believe the data is correct at least for debugging.
- Giovanni
- Site Admin
- Posts: 14892
- Joined: Wed May 27, 2009 8:48 am
- Has thanked: 1202 times
- Been thanked: 996 times
Re: which algorithm to check STM32F4 CRC32
Are the initial CRC value and polynomial the same?
Giovanni
Giovanni
Re: which algorithm to check STM32F4 CRC32
I've run into this issue before... It turns out they calculate the CRC a little differently than you would expect.
In order to get correct crc, you have to:
- reverse the bits before you write them to the data register
- reverse the bits and XOR them with 0xFFFFFFFF after you read from the data register to get the correct checksum.
http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/DM00068118.pdf
I don't think some of the register fields mentioned in the app not exist, but it does explain what you need to do in order to get the right checksum.
In order to get correct crc, you have to:
- reverse the bits before you write them to the data register
- reverse the bits and XOR them with 0xFFFFFFFF after you read from the data register to get the correct checksum.
http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/DM00068118.pdf
I don't think some of the register fields mentioned in the app not exist, but it does explain what you need to do in order to get the right checksum.
Re: which algorithm to check STM32F4 CRC32
Giovanni wrote:Are the initial CRC value and polynomial the same?
Giovanni
I start by enabling the clock and setting the CR-register bit and then writing to the (DR) register as the do in the STM32F4xx-library examples (or was it the code it self).
There seems to be some endianess issue with the polynomial (or something) so there are two takes on the same poly. Tried both but only the (Other)
polynomial (not the one given in the STM32F4xx docs beginning with 0x4...) gives reasonable results. Sorry for being this fuzzy.
Last edited by jarekl on Sun Oct 27, 2013 8:51 pm, edited 1 time in total.
Re: which algorithm to check STM32F4 CRC32
efuentes wrote:I've run into this issue before... It turns out they calculate the CRC a little differently than you would expect.
In order to get correct crc, you have to:
- reverse the bits before you write them to the data register
- reverse the bits and XOR them with 0xFFFFFFFF after you read from the data register to get the correct checksum.
http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/DM00068118.pdf
I don't think some of the register fields mentioned in the app not exist, but it does explain what you need to do in order to get the right checksum.
I follow exactly the steps on page 8 of that document (except steps 2,3,4 which don't apply to F4).
I did try your suggestion. Didn't work for me (yet
Re: which algorithm to check STM32F4 CRC32
efuentes wrote:Can you post some code of what you've tried?
Sure. Here goes,
Code: Select all
/*
* STM32 header files
*/
#include <stm32_rcc.h>
#include <stm32f4xx.h>
uint32_t
crc32(uint32_t *p, int len)
{
int i;
CRC_TypeDef *CReg;
CReg = (CRC_TypeDef *)CRC_BASE;
CReg->CR = (uint8_t)1;
for ( i = 0; i < len; i++)
CReg->DR = *(p+i);
return (CReg->DR);
}
Not longer sure which of the header contains the typedefs and #defines.
I've tried variations with
Code: Select all
for ( i = 0; i < len; i++)
CReg->DR = ~(*(p+i));
and
Code: Select all
return (~CReg->DR)^0xFFFFFFFF;
and also
Code: Select all
return (CReg->DR)^0xFFFFFFF;
The crc32 that is use on the host returns the same result as the crc32(1) command, but to be honest, I'm not sure that it uses the same poly which is why I ask. But I'm getting the impression that the poly implemented by the stm32f4xx is very common.
Re: which algorithm to check STM32F4 CRC32
I'm sorry, I wasn't very clear. When I meant reverse the bits, I meant swap the bits such that the least significant bit is now the most significant bit, the lsb + 1 is now msb - 1 etc...
I've defined these macro in my crc header file
__REV is a macro defined in the CMSIS (core_cminstr.h I think...). It is a wrapper around the rbit instruction.
Whenever you would write the the CRC->DR, call crcWrite. If you want to get the current CRC, call crc read.
Hopefully this works out for you.
Erick
I've defined these macro in my crc header file
Code: Select all
#define crcReset() (CRC->DR = 1)
#define crcRead() (__REV(CRC->DR) ^ 0xFFFFFFFF)
#define crcWrite(x) {CRC->DR = __REV(x)}
__REV is a macro defined in the CMSIS (core_cminstr.h I think...). It is a wrapper around the rbit instruction.
Whenever you would write the the CRC->DR, call crcWrite. If you want to get the current CRC, call crc read.
Hopefully this works out for you.
Erick
Re: which algorithm to check STM32F4 CRC32
I've defined these macro in my crc header fileCode: Select all
#define crcReset() (CRC->DR = 1)
#define crcRead() (__REV(CRC->DR) ^ 0xFFFFFFFF)
#define crcWrite(x) {CRC->DR = __REV(x)}
__REV is a macro defined in the CMSIS (core_cminstr.h I think...). It is a wrapper around the rbit instruction.
it makes no sense for the __REV to be a wrapper around rbit... It should be __RBIT(x)
Re: which algorithm to check STM32F4 CRC32
efuentes wrote:I've defined these macro in my crc header fileCode: Select all
#define crcReset() (CRC->DR = 1)
#define crcRead() (__REV(CRC->DR) ^ 0xFFFFFFFF)
#define crcWrite(x) {CRC->DR = __REV(x)}
__REV is a macro defined in the CMSIS (core_cminstr.h I think...). It is a wrapper around the rbit instruction.
it makes no sense for the __REV to be a wrapper around rbit... It should be __RBIT(x)
Here's what the code looks like right now,
Code: Select all
#define crcReset() (CRC->CR = 1)
#define crcRead() (__REV(CRC->DR) ^ 0xFFFFFFFF)
#define crcWrite(x) (CRC->DR = __REV(x))
uint32_t
crc32(uint32_t *p, int len)
{
int i;
crcReset();
for ( i = 0; i < len; i++)
crcWrite(p[i]);
return crcRead();
}
I had to change in crcReset(), CRC->DR to CRC->CR (typo i presume).
Code: Select all
#define crcWrite(x) {CRC->DR = __REV(x)}
Does not compile. Either I had to add ";" after REV(x) or remove the curly braces (same result).
Using __RBIT(x) i get
Code: Select all
Bad checksum 5F5C4353, FA3AC2CA, and __REV(x) gives,
Code: Select all
Bad checksum 92A01AC8, FA3AC2CA,The second number is the expected result. I'm computing the crc32 for an array of "1", 1280 elements long. This is the number that (also) comes out of the linux command crc32(1).
Maybe this is somehow related to my build environment. This is the result of "make clean; make"
Code: Select all
$ make
Compiler Options
arm-none-eabi-gcc -c -mcpu=cortex-m4 -O2 -ggdb -fomit-frame-pointer -falign-functions=16 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -fsingle-precision-constant -ffunction-sections -fdata-sections -fno-common -Wall -Wextra -Wstrict-prototypes -Wa,-alms=build/lst/ -DCORTEX_USE_FPU=TRUE -DTHUMB_PRESENT -mno-thumb-interwork -DTHUMB_NO_INTERWORKING -MD -MP -MF .dep/build.d -I. -I../../hsarm/ChibiOS-RT/os/ports/common/ARMCMx/CMSIS/include -I../../hsarm/ChibiOS-RT/os/ports/common/ARMCMx -I../../hsarm/ChibiOS-RT/os/ports/GCC/ARMCMx -I../../hsarm/ChibiOS-RT/os/ports/GCC/ARMCMx/STM32F4xx -I../../hsarm/ChibiOS-RT/os/kernel/include -I../../hsarm/ChibiOS-RT/os/hal/include -I../../hsarm/ChibiOS-RT/os/hal/platforms/STM32F4xx -I../../hsarm/ChibiOS-RT/os/hal/platforms/STM32 -I../../hsarm/ChibiOS-RT/os/hal/platforms/STM32/GPIOv2 -I../../hsarm/ChibiOS-RT/os/hal/platforms/STM32/I2Cv1 -I../../hsarm/ChibiOS-RT/os/hal/platforms/STM32/OTGv1 -I../../hsarm/ChibiOS-RT/os/hal/platforms/STM32/RTCv2 -I../../hsarm/ChibiOS-RT/os/hal/platforms/STM32/SPIv1 -I../../hsarm/ChibiOS-RT/os/hal/platforms/STM32/TIMv1 -I../../hsarm/ChibiOS-RT/os/hal/platforms/STM32/USARTv1 -I../../hsarm/ChibiOS-RT/boards/ST_STM32F4_DISCOVERY -I../../hsarm/ChibiOS-RT/os/various main.c -o main.oAnyhow, thank's for all your help. It is really appreciated. I'm total newbie with ChibiOS and ARM (but it's quite a rewarding learning experience).