System Workbench for STM32

Bootloader and Application Code


I recently started with a small project. The idea is to have the first few KB of the memory reserved for the bootloader and after that, the application code:

Bootloader: 0x08000000 - 0x08010000
Application: 0x08012000 - 0x0803FFF

The bootloader and the application are two different projects. When the bootloader is exited the following code is executed:

typedef void (*pFunction)(void);
volatile pFunction SysMemBootJump;

void jump_to (volatile uint32_t memoryAddress)
if ((memoryAddress < MEMORY_START_ADDRESS) || (memoryAddress > MEMORY_END_ADDRESS)) return; // Check if valid address

volatile uint32_t stackPointer = (*(volatile uint32_t *)memoryAddress);

// Init boot jump
SysMemBootJump = (void(*)(void)) (*((volatile uint32_t *) (memoryAddress+4u)));
// reset

SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;

__disable_irq(); // disable interrupt
__set_MSP(stackPointer); // set stack pointer
SysMemBootJump(); // jump

while (1); // should never be reached

In the application code I put the following lines:

/* Memories definition */
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
ROM (rx) : ORIGIN = 0x8012000, LENGTH = 128K-0x12000

  1. define VECT_TAB_OFFSET 0x00012000U /*!< Vector Table base offset field. This value must be a multiple of 0x200. */

After the jump is done, the system locks up and does not run any code of the application.
Both the application and the bootloader are present (I checked with the STM32 Link Utility)

Am I doing an obvious mistake or am I missing something?
I know this topic has been discussed a few times already, but I could not find any solution.

Thanks in advance

Hi Luca,

Did you try to do instruction-level single-step execution over the last lines of jump_to ? You should especially check that the value in SysMemBootJump is odd (as this is Thumb code, this should be OK) and that you are currently using the MSP stack pointer (check the CONTROL register: it must be 0).

Also at which exact instruction does it crash? and does it just jump in some infinite empty loop (meaning you hit some exception) or does is locks up?

Currently I don’t have any way to test your code but it looks reasonable.

Hope this helps,

Bernard (Ac6)

Hi Luca,

I have recently made this work.
Before jumping you have to set SCB->VTOR (vector table offset) to the application vector table address.

In my case I also needed to disable the data and instruction caches.
CMSIS functions SCB_DisableICache() and SCB_DisableDCache()

Hope this helps

Thank you for your answers

Sadly I still can’t figure it out.
I included before the jump is executed:
SCB->VTOR = memoryAddress;

When I step through the jump_to function everything seems to be fine.
Just before the SysMemBootJump() it looks like this:

MSP: 0x20010000
PSP: 0x4ef1c2ac
SCB->VTOR: 0x8012000
SysMemBootJump(): 0x0801C509

And the memory at address 0x0812000:


The application should flash an led after the jump is completed but it doesn’t.
It does not lock up but it is stuck in an infinite loop. I disassembled the instructions and it looks like this:

0x8012dfc: mov sp, r7
0x8012dfe: pop {r7}
0x8012e00: bx lr
0x801a1f0: mov r3, r0
0x801a1f2: and.w r3, r3, #512  ; 0x200
0x801a1f6: cmp r3, #0
0x801a1f8: beq.n 0x801a1ea
0x801a1ea: ldr r0, pc, #20  ; (0x801a200)
0x801a1ec: bl 0x8012dec
0x8012dec: push {r7}
0x8012dee: sub sp, #12
0x8012df0: add r7, sp, #0
0x8012df2: str r0, r7, #4
0x8012df4: ldr r3, r7, #4
0x8012df6: ldr r3, r3, #40  ; 0x28
0x8012df8: mov r0, r3
0x8012dfa: adds r7, #12
0x8012dfc: mov sp, r7

Notice that the last command is also the first.
I’m not sure if this helps.

I am using an STM32F107, I don’t know if and how I can disable the data and instruction caches.

Thanks again for your help


I don’t know exactly what washappening, but th ecode you are looping in seems to be that you are looking at an I/O device (its address seems to be in memory at address 0x801a200) waiting for bit 9 (0x200) of register at offset 40 (0x28) in this device to be set and, as this bit is never set, you loop indefinitly.

Now without more information, nobody can help you...

Anyway, does your application works correctly if started through the debugger?

Bernard (Ac6)

I think the error occurs during the initialization of the application. The processor receives an unexpected interrupt and goes in an infinite loop.
I attached my initialization code to this message.
On line 148 the init process begins. The led_blink_sequence is never reached.

Just two thoughts:

  1. If you get stuck in an unexpected interrupt, you should look at the value in the 9 LSB of the program status register: they give the number of the exception you are in; if it’s greater than 16 (what I think) subtract 16 and you’ll get the IRQn of the interrupt: knowing which unexpected interrupt you got will probably allow you to know what the problem is.Maybe an interrupt programmed by the bootloader code and not reset before sarting your application?
  2. You try to blink your LED a bit too fast in my opinion: blinking at 10Hz (10 times per second) i shardly seen as blinking but just as a half-lighetd LED... You should probably set BLINK_DURATION_MS to at least 100 or 200.

Bernard (Ac6)

Thanks for the succession.
First of all the application and bootloader work fine when executed after a system reset. (Also when the application is placed at the memory address 0x08012000 and debugged from AC6)

1. The IPSR is 0 when running in the infinite loop. Sadly I have not figured out yet how to step through the program after the jump. When I step into the SysMemBootJump(); function the program starts running...
Is there a way to efficiently debug this sequence?

2. The LED does not turn on after the jump is complete and I like to have it that fast in the boot up sequence.