2024-11-26 10:18 PM - last edited on 2024-11-26 11:24 PM by SofLit
Hi all,
I have been developing a bootloader to facilitate OTA updates on an STM32F446 device. The OTA update works such that, when the device is powered on, it runs the bootloader, which is written at address 0x08000000 in the flash memory. I keep two copies of the firmware on the board, storing the version and location of the firmware using RTC backup registers.
When the bootloader starts, it checks the backup registers to determine if a new update is available (the update is downloaded by the firmware). If no updates are found, the bootloader jumps to the firmware located at either address 0x08020000 or 0x08040000 in the flash memory, depending on which storage contains the latest firmware. The bootloader switches to the firmware using the following function:
void bootloader_jump_to_user_app(uint32_t base_address)
{
void (*app_reset_handler) (void);
uint32_t msp_value = *(volatile uint32_t *) base_address;
uint32_t resethandler_address = *(volatile uint32_t *) (base_address + 4);
SCB->VTOR = base_address;
__set_MSP(msp_value);
app_reset_handler = (void*) resethandler_address;
app_reset_handler();
}
In this function, the address of the firmware is passed on to this function.
On the initial boot, the device successfully jumps to the firmware. However, when a new update is detected, the firmware downloads the update using a SIM800C module, breaking the firmware into frames of 256 bytes. The new firmware is downloaded to address 0x08060000 in the flash memory. Once the update is complete, the backup register is updated (using a magic pattern) and the system resets via HAL_NVIC_SystemReset();.
After the reset, the bootloader detects the new update. The firmware is then copied to the location where the older version is stored, and HAL_NVIC_SystemReset(); is called again after the firmware file is successfully copied.
During this second boot, the base address changes after the update, but the bootloader fails to jump to the application. This issue occurs when the board is reset via software, but not when it is reset via hardware—where it correctly jumps to the new application.
How can I switch to the new application using a software reset?
I have already tried methods like deinitializing peripherals and interrupts using:
HAL_RCC_DeInit();
HAL_DeInit();
__disable_irq();