2025-09-18 8:54 AM
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!
Solved! Go to Solution.
2025-10-21 6:55 AM
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.
2025-09-19 9:02 AM
Hello @j_filipe
You can implement a simple check in your bootloader code. Here’s how you can proceed:
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.
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
}
}2025-09-22 4:54 AM
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!
2025-09-24 7:14 AM
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.
2025-10-21 2:52 AM
@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!
2025-10-21 3:48 AM - edited 2025-10-21 4:04 AM
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;
2025-10-21 6:50 AM
@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?
2025-10-21 6:55 AM
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.
2025-10-21 7:39 AM
Thank you @Saket_Om
2025-10-24 2:30 AM
@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();