cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F446RE CRC mismatch

FShah.1
Associate III

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?

10 REPLIES 10

So posted three times on this topic.

STM32's standard algo operates on whole 32-bit words, in a right shifting word sense, which is not normative for little-endian platforms. See my code here

https://github.com/cturvey/RandomNinjaChef/blob/main/stm32crc.c

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

@Tesla DeLorean 

Thank you for your response. I appreciate all the work done by community members, when I see a useful and understandable post, I add my question.

Should I use the code you linked on the host to calculate the CRC? Sorry if I'm asking a simple question!

Well, I'd start with your test pattern to affirm the calculation on PC vs the one you've got on the STM32

Most on-line calculators use more normative byte-wise computations.

On the F4 the CRC peripheral has a fixed form, which is 32-bit words. You can use the code to compute the equivalent for word aligned / word length multiples.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Appreciated, I check and let you know. Thanks

Hi, I got 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);

 

 

UART Terminal output

CRC Input 0x05060708
MCU CRC 0x20020000

Sounds like an address on the Stack, I'd avoid zero sized arrays.

Lacking some context to be able to compile the fragment, suggest you look at the answer here

https://community.st.com/t5/stm32-mcus/how-is-crc-value-calculated-how-to-determine-crc-algorithm-in/tac-p/748893#M1184

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

 

Hi,

I appreciate your prompt response. I found the issue in my code, and now the CRC is working correctly.

However, another problem has arisen. As you know, I am working on a bootloader program. My application code is successfully transferred from the source to the controller via the serial port. But when the code attempts to set the reset handler and jump to the application code, it is failing.

I am using the STM32F446 microcontroller.

First, I copied the code to memory address 0x08040000. Then, bootloader copied to the application memory address, which is 0x08020000. The CRC of the application on the host side, the CRC at address 0x08040000, and the CRC at address 0x08020000 are all the same.

I checked the memory locations, and they have the same data. However, the jump_to_application function is not successful.

Blink LED Application: I changed the Flash address in linker file

/* Memories definition */

MEMORY

{

RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K

FLASH (rx) : ORIGIN = 0x08020000, LENGTH = 128K

}

 

/*!< Uncomment the following line if you need to relocate the vector table

anywhere in Flash or Sram, else the vector table is kept at the automatic

remap of boot address selected */

#define USER_VECT_TAB_ADDRESS

 

#if defined(USER_VECT_TAB_ADDRESS)

/*!< Uncomment the following line if you need to relocate your vector Table

in Sram else user remap will be done in Flash. */

/* #define VECT_TAB_SRAM */

#if defined(VECT_TAB_SRAM)

#define VECT_TAB_BASE_ADDRESS SRAM_BASE /*!< Vector Table base address field.

This value must be a multiple of 0x200. */

#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.

This value must be a multiple of 0x200. */

#else

#define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field.

This value must be a multiple of 0x200. */

#define VECT_TAB_OFFSET 0x00020000U /*!< Vector Table base offset field.

This value must be a multiple of 0x200. */

#endif /* VECT_TAB_SRAM */

#endif /* USER_VECT_TAB_ADDRESS */

 

 

Bootloader: jump_to_application function:

static void goto_application(void)
{
 
printf("Gonna Jump to Application\r\n");
 
 
 
// Set the Vector Table Offset Register (VTOR) to the address of the application
SCB->VTOR = ETX_APP_FLASH_ADDR;
// Get the application reset handler address
void (*app_reset_handler)(void) = (void*)(*((volatile uint32_t*) (ETX_APP_FLASH_ADDR + 4U)));//Application starting address
// Optionally turn off the LED
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
 
/* Reset the Clock */
HAL_RCC_DeInit();
HAL_DeInit();
__set_MSP(*(volatile uint32_t*) ETX_APP_FLASH_ADDR);
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
 
/* Jump to application */
app_reset_handler();    //call the app reset handler
}
Kindly advise on how to solve this problem. I am very close to the finish line, but something I am doing seems to be wrong! Please help. Thank you
FShah.1
Associate III

I checked the memory regions where the code is being written and identified an issue with how the data was being written to the flash memory—specifically, little-endian / big-endian issue. After addressing this, the application is now successfully loading and working.

Thanks for being responsive. I will reach out to you for assistance with other parts of the bootloader process during my development.

Thanks again,
FS

I'd have the destination app set it's own SP explicitly in Reset_Handler / startup.s, this saves the caller from the responsibility of messing up their own stack frame.

Have SystemInit() manage SCB->VTOR, perhaps using g_pfnVectors symbol directly, so it follows where the code is built/linked against.

extern uint32_t *g_pfnVectors;

SCB->VTOR = (uint32_t)&g_pfnVectors[0]; // ?

Also, you don't need to reset everything if you manage the hand-over and who own's what.

For example you tear-down the interrupts you've stood up, but you keep the clocks, pll, external memory that are already up and functional, and hand over the system in a viable state.

Peripherals w/interrupts are hard to carry over due to the different RAM usage/contexts, and completely different handlers and callback expectations. But a functional UART at 115200 baud will continue to function on the HW side unless you go off an break everything.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..