cancel
Showing results for 
Search instead for 
Did you mean: 

jump to another app explanation

JCuna.1
Senior

I have this code:

void bootloader_jump_to_app(void){
	pFunction Jump;
	uint32_t  JumpAddress;
 
	HAL_RCC_DeInit();
	HAL_DeInit();
 
	JumpAddress = *(__IO uint32_t*)(APP_ADDRESS + 4);
	Jump = (pFunction)JumpAddress;
 
	__set_MSP(*(__IO uint32_t*)APP_ADDRESS);
	Jump();
 
	SCB->VTOR = FLASH_BASE | 0x00008000;
}

For me, does not make sense the last line as in theory this is not called after jump application, however, commenting this line make a hard fault handler after jump function execution.

3 REPLIES 3
JCuna.1
Senior

making more testing, I realized that changing the line SCB->VTOR = FLASH_BASE | 0x00008000; for asm("nop"); still making the code work. So problem is related if there is no last line of code in the function.

Here is the asm code:

419       	HAL_RCC_DeInit();
          bootloader_jump_to_app:
080006a8:   push    {r3, lr}
080006aa:   bl      0x800212c <HAL_RCC_DeInit>
420       	HAL_DeInit();
080006ae:   bl      0x8001990 <HAL_DeInit>
422       	JumpAddress = *(__IO uint32_t*)(APP_ADDRESS + 4);
080006b2:   ldr     r3, [pc, #16]   ; (0x80006c4 <bootloader_jump_to_app+28>)
080006b4:   ldr     r2, [pc, #16]   ; (0x80006c8 <bootloader_jump_to_app+32>)
080006b6:   ldr     r3, [r3, #0]
425       	__set_MSP(*(__IO uint32_t*)APP_ADDRESS);
080006b8:   ldr     r2, [r2, #0]
 333        __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : );
080006ba:   msr     MSP, r2
426       	Jump();
080006be:   blx     r3
428       	asm("nop");
080006c0:   nop     
080006c2:   pop     {r3, pc}
080006c4:   strh    r4, [r0, #0]
080006c6:   lsrs    r0, r0, #32
080006c8:   strh    r0, [r0, #0]
080006ca:   lsrs    r0, r0, #32

and here the asm code, when there is no instruction after jump();

419       	HAL_RCC_DeInit();
          bootloader_jump_to_app:
080006a8:   push    {r4, lr}
080006aa:   bl      0x800212c <HAL_RCC_DeInit>
420       	HAL_DeInit();
080006ae:   bl      0x8001990 <HAL_DeInit>
422       	JumpAddress = *(__IO uint32_t*)(APP_ADDRESS + 4);
080006b2:   ldr     r3, [pc, #16]   ; (0x80006c4 <bootloader_jump_to_app+28>)
080006b4:   ldr     r2, [pc, #16]   ; (0x80006c8 <bootloader_jump_to_app+32>)
080006b6:   ldr     r3, [r3, #0]
425       	__set_MSP(*(__IO uint32_t*)APP_ADDRESS);
080006b8:   ldr     r2, [r2, #0]
 333        __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : );
080006ba:   msr     MSP, r2
426       	Jump();
080006be:   ldmia.w sp!, {r4, lr}
080006c2:   bx      r3
080006c4:   strh    r4, [r0, #0]
080006c6:   lsrs    r0, r0, #32
080006c8:   strh    r0, [r0, #0]
080006ca:   lsrs    r0, r0, #32

Looks like ldmia.w sp!, {r4, lr} is causing the problem. This is making an increment stack pointer after loading process is stack pointer, and in consequence, changing the recent assignation of main stack pointer before to jump to the app. Optimization process (actually using -oS optimization) is adding this instruction. So adding a nop instruction avoid to make this optimizations.

Piranha
Chief II

When changing the stack pointer, software must use an ISB instruction immediately after the MSR instruction. This ensures that instructions after the ISB instruction execute using the new stack pointer. See ISB

https://developer.arm.com/documentation/dui0552/a/the-cortex-m3-processor/programmers-model/core-registers

If the program updates the value of the VTOR, use a DSB instruction to ensure that the new vector table is used for subsequent exceptions.

https://developer.arm.com/documentation/dui0662/b/The-Cortex-M0--Processor/Memory-model/Software-ordering-of-memory-accesses