2024-07-16 12:29 PM
MCU: STM32F411CEU6
So, I am having a weird issue. I created a bootloader for my application to accommodate OTA updates. Bootloader makes decision when it has new firmware inside external flash(the application code tells it), then bootloader loads that otherwise it simply jumps to existing firmware in internal flash. Now issue arise when it jumps to firmware for example I have simply given the command to my application code to reset the mcu, now the mcu goes to bootloader first and then bootloader makes the jump to the firmware in this the jump is successful sometimes and most of the time it fails and the mcu get stuck, and sometimes it keeps working perfectly
now when I send the new firmware to application code it saves it into external flash and then resets it, the bootloader reads special header and so it knows that it needs to download new firmware to the mcu, so instead of jumping to internal flash firmware it erases it and loads the new firmware from external flash and then jumps to it, the success rate for this which I tested is almost 100per and the mcu never get stucks and always successfully goes to new firmware.
The issue only arises if application resets the mcu and most of the time the bootloader fails to jump.
Here is my bootloader code
void flash_jump_to_app(uint32_t address)
{
/* Function pointer to the address of the user application. */
fnc_ptr jump_to_app;
jump_to_app = (fnc_ptr)(*(volatile uint32_t*) (address+4u));
HAL_DeInit();
HAL_RCC_DeInit();
/* Change the main stack pointer. */
__set_MSP(*(volatile uint32_t*)address);
jump_to_app();
}
void app_main()
{
imghdr_t *ipFlaPar;
ipFlaPar = (imghdr_t*) Img_Hdr_Start_Address_Internal_Flash;
/*first we read if external flash has valid image */
SPIF_ReadAddress(&handle_ext_flash,Img_Start_Address_External_Flash,(uint8_t *)&imgFixedhdr,sizeof(imghdr_t));
if(imgFixedhdr.imgVld == Img_Header_valid_bytes )
{
/*now we read the external header in external flash to judge if this image needs to be copied into flash*/
SPIF_ReadSector(&handle_ext_flash, Img_Header_Start_Sector, (uint8_t *)&imgExternalhdr, sizeof(imghdr_t), 0);
if(imgExternalhdr.imgVld == Img_Header_valid_bytes)
{
if(imgExternalhdr.imgCpStat == 1) //needs copy
{
if(copy_img_external_to_internal(&handle_ext_flash,imgExternalhdr.imgExternalStartAdr
,imgExternalhdr.imgHdrStartAdr,imgExternalhdr.imgtotalsize,1024) == 1)
{
imgExternalhdr.imgCpStat = 0; //tell bootloader valid image and copy it
//imgExternalhdr.restartCount = imgExternalhdr.restartCount + 1;
SPIF_EraseSector(&handle_ext_flash, Img_Header_Start_Sector);
SPIF_WriteSector(&handle_ext_flash, Img_Header_Start_Sector, (uint8_t *)&imgExternalhdr, sizeof(imghdr_t), 0);
flash_jump_to_app(imgExternalhdr.prgEntry);
}
}
}
}
/*This tells us there is already an image in internal flash */
if(ipFlaPar->imgVld == Img_Header_valid_bytes )
{
flash_jump_to_app(ipFlaPar->prgEntry);
}
while(1);
}
2024-07-17 02:57 AM
I.m.h.o. the best way is to have a switch at the very beginning of the startup code to jump to the bootloader after a reset. Trigger a reset, when bootloader entry is wanted and check for warm boot in that code.
2024-07-17 03:52 AM
sorry I did not understand what do you mean by this, can you eloborate
and btw with my further testing when I removed
HAL_RCC_DEINIT()
HAL_DeInit()
these two from my flash_jumo_to_app function, now it seems to be working correctly. I am giving it multiple resets and it always lands on application, but I am still testing it, so cant say if it is fixed or not
2024-07-17 03:58 AM
Interesting that removing the De-Inits makes it work...
Because I just wanted to answer that it helped my application to de-init all of the used peripherals in the bootloader before jumping (on a H7xx).
2024-07-17 05:42 AM
I think so the reason for that is, I am already deiniting everything in start of application. So my guess is something cause issue if you deinit twice, but I will surely test this behavior and come back with my findings.
2024-07-17 05:48 AM
It somehow seems "cleaner" to me, when the part that's using stuff then de-inits it before jumping.
So bootloader de-inits everything it used, application de-inits everything it used (in case it can jump to the bootloader).
That way you can keep them independent of each other.
2024-07-17 11:06 AM
@Uwe Bonnes proposes the cleanest solution It does not init anything and does not need to deinit anything.