@@ -95,33 +95,24 @@ WEAK void jumpToBootloaderIfRequested(void)
9595#ifdef USBCON
9696 USBD_reenumerate ();
9797#endif
98- void (* sysMemBootJump )(void );
9998
10099 uint32_t sys = bootloaderAddress ();
101100
102- /**
103- * Set jump memory location for system memory
104- * Use address with 4 bytes offset which specifies jump location
105- * where program starts
106- */
107- sysMemBootJump = (void (* )(void ))(* ((uint32_t * )(sysMem_addr + 4 )));
108-
109- /**
110- * Set main stack pointer.
111- * This step must be done last otherwise local variables in this function
112- * don't have proper value since stack pointer is located on different position
113- *
114- * Set direct address location which specifies stack pointer in SRAM location
115- */
116- __set_MSP (* (uint32_t * )sysMem_addr );
117-
118- /**
119- * Jump to set location
120- * This will start system memory execution
121- */
122- sysMemBootJump ();
123-
124- while (1 );
101+ // This is assembly to prevent modifying the stack pointer after
102+ // loading it, and to ensure a jump (not call) to the bootloader.
103+ // Not sure if the barriers are really needed, they were taken from
104+ // https://github.com/GrumpyOldPizza/arduino-STM32L4/blob/ac659033eadd50cfe001ba1590a1362b2d87bb76/system/STM32L4xx/Source/boot_stm32l4xx.c#L159-L165
105+ asm volatile (
106+ "ldr r0, [%[sys], #0] \n\t" // get address of stack pointer
107+ "msr msp, r0 \n\t" // set stack pointer
108+ "ldr r0, [%[sys], #4] \n\t" // get address of reset handler
109+ "dsb \n\t" // data sync barrier
110+ "isb \n\t" // instruction sync barrier
111+ "bx r0 \n\t" // branch to bootloader
112+ : : [sys ] "l" (sys ) : "r0"
113+ );
114+
115+ __builtin_unreachable ();
125116 }
126117}
127118
0 commit comments