2025-09-09 4:58 AM
Hi,
I’m working on an STM32F767 custom bootloader with two application slots:
Main Application Slot → starts at 0x08040000
Backup (Factory) Slot → starts at 0x08100000
I have written a bootloader that checks both slots and jumps to the valid application:
SCB->VTOR = app_base; // Set vector table offset
__set_MSP(*(uint32_t*)app_base); // Set initial stack pointer
void (*app_reset_handler)(void) = (void*)(*(uint32_t*)(app_base + 4));
app_reset_handler(); // Jump to reset handler
I tested two scenarios:
I built one binary with FLASH start = 0x08040000.
I program the same binary into both slots:
Slot 1 → 0x08040000
Slot 2 → 0x08100000
Result:
Main slot works :white_heavy_check_mark:
Backup slot fails :cross_mark: — the application does not start.
The binary built for 0x08040000 fails when executed from 0x08100000?
Is there a way to make one application binary run from both flash addresses?
2025-09-09 5:34 AM
Have you set correctly the VTOR for the apps? It has to change when you run the app from the second bank
2025-09-09 6:15 AM
You can use position independent code, which is not common. You will still need to set VTOR correctly.
You can use bank remapping if it's placed at the same position within each bank.
2025-09-09 8:02 AM
Hello @MADHU2
The recommended method for dual-slot booting is to build two separate application binaries; each linked to a different flash start address using distinct linker scripts—one for the main slot at 0x08040000 and another for the backup slot at 0x08100000. This ensures that each binary’s vector table and all absolute addresses are correctly aligned with its designated flash region. During firmware updates, both binaries are included in the update package, and the bootloader is responsible for checking the validity of each slot and jumping to the appropriate application.
2025-09-09 9:48 PM - last edited on 2025-09-10 4:03 AM by Andrew Neil
Hello @Saket_Om,
Thank you for the response. I tried an experiment to better understand the behavior:
I created two separate application binaries using two different linker scripts:
App_Main → Start address 0x08040000
App_Backup → Start address 0x08100000
When I flash the App_Backup binary into both slots (0x08040000 and 0x08100000), the application runs perfectly from both slots.
However, if I take the App_Main binary (linked at 0x08040000) and flash it into both slots (0x08040000 and 0x08100000):
It runs correctly from 0x08040000
But it fails to run from 0x08100000
My question is:
1.Why does the backup-linked binary (built with 0x08100000) work fine when placed in both slots, but the main-linked binary (built with 0x08040000) fails when placed in the backup slot?
2. It is possible to achieve dual-slot booting using a single linker script for the application and manage both slots
For reference, below is the application jump function for the main slot and backup slot.
static void goto_application(void)
{
printf("Gonna Jump to Application\n");
// uint32_t crc_recheck_flash = Compute_CRC32_For_Flash(FLASH_SECTOR_5_ADDR, 26864);
// printf("CRC (file) = 0x%08lX\r\n", crc_recheck_flash);
void (*app_reset_handler)(void) = (void*)(*((volatile uint32_t*) (0x08040000 + 4U)));
//__set_MSP(*(volatile uint32_t*) 0x08040000);
// Turn OFF the Green Led to tell the user that Bootloader is not running
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET ); //Green LED OFF
/* Reset the Clock */
HAL_RCC_DeInit();
HAL_DeInit();
// __disable_irq();
__set_MSP(*(volatile uint32_t*) 0x08040000);
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
// actually alignment is implementation dependent — flash sector alignment is fine if app is placed properly)
SCB->VTOR = 0x08040000;
/* Jump to application */
app_reset_handler(); //call the app reset handler
}
static void goto_Factory_firmware(void)
{
printf("Boot from Factory firmware Application\n");
void (*app_reset_handler)(void) = (void*)(*((volatile uint32_t*) (0x08100000 + 4U )));
//__set_MSP(*(volatile uint32_t*) 0x08100000);
// Turn OFF the Green Led to tell the user that Bootloader is not running
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET ); //Green LED OFF
/* Reset the Clock */
HAL_RCC_DeInit();
HAL_DeInit();
// __disable_irq();
__set_MSP(*(volatile uint32_t*) 0x08100000);
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
SCB->VTOR = 0x08100000;
/* Jump to application */
app_reset_handler(); //call the app reset handler
}
Edited to apply source code formatting - please see How to insert source code for future reference.