cancel
Showing results for 
Search instead for 
Did you mean: 

Jump from Openbootloader to the Application

j_filipe
Senior

Greetings! 
So, I used the OpenBootloader project, and then flashed a GPIO_IOToggle firmware in other area of the flash, close to the example in the video Introduction to Open Bootloader, Part 3: Loading an Application.  In that example the CubeProgrammer flashes through the DFU and check "run after programming". When I unplug the board and turn it back on, the OpenBootloader starts (as expected). 
What I want to do is, as soon as I flash the application, when I turn off the board and turn it on again, the application starts to run and not the bootloader, OR, it starts the bootloader, it checks if there's any application installed, and if yes, it jumps to the application immediately. 
Any clue on how to do that?
Thank you! 

1 ACCEPTED SOLUTION

Accepted Solutions

Hello @j_filipe 

I provided an example of a linker file for an IAR project. If you are working with an STM32CubeIDE project, you should have a .ld linker script file instead.

STM32CubeU5/Projects/B-U585I-IOT02A/Examples/GPIO/GPIO_IOToggle/STM32CubeIDE/STM32U585AIIXQ_FLASH.ld at main · STMicroelectronics/STM32CubeU5

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

View solution in original post

19 REPLIES 19
Saket_Om
ST Employee

Hello @j_filipe 

 

You can implement a simple check in your bootloader code. Here’s how you can proceed:


1. Define the Application Start Address

Decide on the flash address where your application will be located (for example, 0x08008000). Make sure your application is built to start from this address by configuring your linker script or project settings accordingly.


2. Add Application Check in Bootloader

In your bootloader’s main function, add code to verify if a valid application is present at the specified address. If so, the bootloader can jump to the application’s entry point. Here’s a typical example for STM32 devices:

#define APP_ADDRESS 0x08008000U

typedef void (*pFunction)(void);

void jumpToApplication(void) {
    uint32_t appStack = *(__IO uint32_t*)APP_ADDRESS;
    uint32_t appEntry = *(__IO uint32_t*)(APP_ADDRESS + 4);

    // Check if stack pointer is in RAM (valid application)
    if ((appStack >= RAM_START) && (appStack < RAM_END)) {
        __disable_irq();
        __set_MSP(appStack);
        pFunction appMain = (pFunction)appEntry;
        appMain();
    }
}

int main(void) {
    HAL_Init();
    // Bootloader initialization...

    // Check for valid application and jump if present
    jumpToApplication();

    // If no valid application, stay in bootloader
    while (1) {
        // Bootloader main loop
    }
}
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

I still need to test it... 
What would it be the RAM_START and RAM_END for STM32U585? Why do you do the appEntry = APP_ADDRESS+4 ? 
What is appMain, the main function? 
Thank you! 

 

Hello @j_filipe 

The line appEntry = *(uint32_t*)(APP_ADDRESS + 4) retrieves the address of the application's reset handler (the entry point), which is always stored at offset +4 from the application start. The appMain variable is a function pointer to this reset handler, so when you call appMain(), you are transferring control to the 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
j_filipe
Senior

@Saket_Om thank you for your response. 
One more thing, what is RAM_START and RAM_END? I'm using a STM32U585 MCU. 
Thank you! 

The RAM_START and RAM_END are defined in your linker file. For example, it in the stm32u585xx_flash.icf file on the B-U585I-IOT02A examples it is defined as below.

define symbol __ICFEDIT_region_RAM_start__     = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__       = 0x200BFFFF;

Saket_Om_0-1761043265713.png

 

 

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

@Saket_Om  
I do not have any stm32u585xx_flash.icf  file in my project... 
Can I set:
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__ = 0x200BFFFF;
in my main.c file? 

Hello @j_filipe 

I provided an example of a linker file for an IAR project. If you are working with an STM32CubeIDE project, you should have a .ld linker script file instead.

STM32CubeU5/Projects/B-U585I-IOT02A/Examples/GPIO/GPIO_IOToggle/STM32CubeIDE/STM32U585AIIXQ_FLASH.ld at main · STMicroelectronics/STM32CubeU5

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
j_filipe
Senior

Thank you @Saket_Om 

j_filipe
Senior

@Saket_Om 
So tried to do the function you showed me previously, I did it more or less like this, but it doesn't give the jump, it stays in while(1)...

#define APP_START_ADDRESS   ((uint32_t)0x0800C000)   
#define RAM_START	    ((uint32_t)0x20000000)	
#define RAM_END		    ((uint32_t)0x200C0000)

typedef void (*pFunction)(void);

void jumpToApplication(void)
{
	uint32_t appStack = *(__IO uint32_t*)APP_START_ADDRESS;
	uint32_t appEntry = *(__IO uint32_t*)(APP_START_ADDRESS + 4);

	//Check if stack pointer is in RAM (valid application)
	if((appStack >= RAM_START) && (appStack < RAM_END))
	{
		__disable_irq();
		__set_MSP(appStack);
		pFunction appMain = (pFunction)appEntry;
		appMain();
	}
}

// Called the function before the main while(1)
 jumpToApplication();