on 2022-07-26 05:48 AM
(https://www.st.com/content/st_com/en/products/embedded-software/mcu-mpu-embedded-software/stm32-embedded-software/stm32-standard-peripheral-library-expansion/stsw-stm32an4187.html#overview).
Once you computed the CRC, append it to the message [data|CRC] and transmit everything. To check whether the received data is correct,
calculate the CRC over [data|CRC] and check whether the newly calculated CRC is 0 - in which case the data is intact.
(For the mathematically inclined: this follows from the idea of a CRC: "multiply" a "number" such that it can be "divided" by the polynom without remainder.)
Hi,
here is an example to show how the HAL_CRC_Calculate is working (STM32F407,STM32F107,...) and how to do the same calculation by yourself:
uint32_t Crc32(uint32_t Crc, uint32_t Data)
{
uint8_t i;
Crc = Crc ^ Data;
for(i=0; i<32; i++)
if (Crc & 0x80000000)
Crc = (Crc << 1) ^ 0x04C11DB7; // Polynomial used in STM32
else
Crc = (Crc << 1);
return(Crc);
}
void test_crc(void)
{
uint8_t i;
uint8_t amountofdata;
uint32_t data[4]={
0x12345678,
0x23456789,
0x3456789A,
0x456789AB,
};
uint32_t crc_polynom;
uint32_t crc_cal1 = 0;
uint32_t crc_cal2 = 0;
//---------------------------------------------------------------- 1x4bytes
amountofdata = 1;
crc_polynom = 0xFFFFFFFF;
crc_cal1 = HAL_CRC_Calculate(&hcrc, &data[0], amountofdata);
crc_cal2 = Crc32(crc_polynom, data[0]);
//crc_cal1 = crc_cal2 = 0xdf8a8a2b
if (crc_cal1 != crc_cal2)
Error_Handler();
//---------------------------------------------------------------- 2x4bytes
amountofdata = 2;
crc_polynom = 0xFFFFFFFF;
crc_cal1 = HAL_CRC_Calculate(&hcrc, &data[0], amountofdata);
for (i=0;i<amountofdata;i++)
crc_polynom = Crc32(crc_polynom, data[i]);
crc_cal2 = crc_polynom;
//crc_cal1 = crc_cal2 = 0x78151f4d
if (crc_cal1 != crc_cal2)
Error_Handler();
//---------------------------------------------------------------- 4x4bytes
amountofdata = 4;
crc_polynom = 0xFFFFFFFF;
crc_cal1 = HAL_CRC_Calculate(&hcrc, &data[0], amountofdata);
for (i=0;i<amountofdata;i++)
crc_polynom = Crc32(crc_polynom, data[i]);
crc_cal2 = crc_polynom;
//crc_cal1 = crc_cal2 = 0xf62cb9eb
if (crc_cal1 != crc_cal2)
Error_Handler();
//---------------------------------------------------------------- 2x4bytes
uint8_t rxbuff[8] = {
0x01,
0x02,
0x0c,
0x0a,
0x1a,
0x01,
0x03,
0x01,
};
amountofdata = 2;
crc_polynom = 0xFFFFFFFF;
crc_cal1 = HAL_CRC_Calculate(&hcrc, (uint32_t*)&rxbuff[0], amountofdata);
for (i=0;i<amountofdata*4;)
{
crc_polynom = Crc32(crc_polynom, *(uint32_t*)&rxbuff[i]);
i += 4;
}
crc_cal2 = crc_polynom;
//crc_cal1 = crc_cal2 = 0x50b5c7df
if (crc_cal1 != crc_cal2)
Error_Handler();
}
Hi, I am following a video to write a bootloader that transfers the application code serially into the STM32F446 controller. The video originally presents the STM32F7xx series controller, but I am applying it to the F4xxx series. I have modified the code as needed, such as assigning the proper flash areas for the bootloader and application code. See the GitHub link for this tutorial.
https://github.com/Embetronicx/STM32-Bootloader/tree/ETX_Bootloader_3.0/Bootloader_Example
This link also provides a PC tool that transfers the code from the host to the controller once the handshaking is complete.
What are the recommendations if I want to calculate the CRC32 on a PC that matches the CRC32 calculated on the STM32F446 using HAL_CRC_Calculate()?
My code gives 0x08b329c8 and host calculated CRC is 0x4e08bfb4?
For STM32H745IIKx I use:
void __MX_CRC_Init__(void)
{
/* USER CODE BEGIN CRC_Init 0 */
/* USER CODE END CRC_Init 0 */
/* USER CODE BEGIN CRC_Init 1 */
/* USER CODE END CRC_Init 1 */
hcrc.Instance = CRC;
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE;
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE;
//hcrc.Init.GeneratingPolynomial = 79764919;
hcrc.Init.CRCLength = CRC_POLYLENGTH_32B;
//hcrc.Init.InitValue = 0;
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_WORDS;
if (HAL_CRC_Init(&hcrc) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN CRC_Init 2 */
/* USER CODE END CRC_Init 2 */
}
Functioncall to calculate a CRC of internal FlashData:
test_CRC = HAL_CRC_Calculate(&hcrc, (uint32_t*)APL_BASE_ADDR, (BufferLength)/sizeof(uint32_t));
Hi, I am stuck with a problem that I am getting a same value from hal_crc_calculate, => 0x20020000
I changed inputs 0x05060708, but no change in crc calculation. Do you please help me to solve this issue? It looks to me that DR register is not resetting to 0xFFFFFFFF.
static inline uint32_t combine_bytes(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4) {
return ((uint32_t)byte1 << 24) | ((uint32_t)byte2 << 16) | ((uint32_t)byte3 << 8) | (uint32_t)byte4;
}
uint8_t data8bit[4] = {5,6,7,8};
uint32_t crcInput[0] = combine_bytes(data8bit[0], data8bit[1], data8bit[2], data8bit[3]);
printf("CRC Input 0x%08lx \n",crcInput[0]);//output = 0x05060708
//Calculate and verify the CRC
__HAL_CRC_DR_RESET(&hcrc);
cal_crc = HAL_CRC_Calculate( &hcrc,(uint32_t*)crcInput, 1);//ota_fw_total_size/4
printf("MCU CRC 0x%08lx \n",cal_crc);
Not sure I like zero dimension arrays
static inline uint32_t combine_bytes(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4)
{
return ((uint32_t)byte1 << 24) | ((uint32_t)byte2 << 16) | ((uint32_t)byte3 << 8) | (uint32_t)byte4;
}
{
uint32_t cal_crc;
uint8_t data8bit[4] = {5,6,7,8};
uint32_t crcInput = combine_bytes(data8bit[0], data8bit[1], data8bit[2], data8bit[3]);
printf("CRC Input 0x%08lx \n",crcInput);//output = 0x05060708
//Calculate and verify the CRC
__HAL_CRC_DR_RESET(&hcrc);
cal_crc = HAL_CRC_Calculate( &hcrc,(uint32_t*)&crcInput, 1);//ota_fw_total_size/4
printf("MCU CRC 0x%08lx \n",cal_crc);
}
https://github.com/cturvey/RandomNinjaChef/blob/main/stm32crc.c
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
uint32_t crc32(uint32_t crc, size_t size, uint32_t *buffer)
{
int i;
while(size--)
{
crc = crc ^ *buffer++;
for(i=0; i<32; i++)
if (crc & 0x80000000)
crc = (crc << 1) ^ 0x04C11DB7;
else
crc <<= 1;
}
return(crc);
}
int main(int argc, char **argv)
{
uint8_t data1[] = { 0x05,0x06,0x07,0x08 };
uint8_t data2[] = { 0x08,0x07,0x06,0x05 };
printf("%08X\n", crc32(0xFFFFFFFF, sizeof(data1)/sizeof(uint32_t), (uint32_t *)data1)); // 0xC9F6D629
printf("%08X\n", crc32(0xFFFFFFFF, sizeof(data2)/sizeof(uint32_t), (uint32_t *)data2)); // 0x72887319
return(1);
}