2021-12-14 10:35 AM
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.
2021-12-14 10:42 AM
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
2021-12-14 10:51 AM
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.
2022-01-15 11:56 AM
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
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.