@@ -95,33 +95,24 @@ WEAK void jumpToBootloaderIfRequested(void)
95
95
#ifdef USBCON
96
96
USBD_reenumerate ();
97
97
#endif
98
- void (* sysMemBootJump )(void );
99
98
100
99
uint32_t sys = bootloaderAddress ();
101
100
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 ();
125
116
}
126
117
}
127
118
0 commit comments