cancel
Showing results for 
Search instead for 
Did you mean: 

Dual-slot Bootloader: Same Application Binary in Two Different Flash Sectors on STM32F7

MADHU2
Associate III

 

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

Problem

I tested two scenarios:

 Using app_main.ld (FLASH origin = 0x08040000)

  • 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.


Question

The binary built for 0x08040000 fails when executed from 0x08100000?

Is there a way to make one application binary run from both flash addresses?

4 REPLIES 4
vaualbus
Associate II

Have you set correctly the VTOR for the apps? It has to change when you run the app from the second bank 

TDK
Super User

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.

If you feel a post has answered your question, please click "Accept as Solution".
Saket_Om
ST Employee

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. 

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om

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.