1010/*
1111 * STM32 built-in bootloader in system memory support
1212 */
13- /* Private definitions to manage system memory address */
14- #define SYSMEM_ADDR_COMMON 0xFFF
1513
1614static bool BootIntoBootloaderAfterReset ;
1715
18- typedef struct {
19- uint32_t devID ;
20- uint32_t sysMemAddr ;
21- } devSysMemAddr_str ;
22-
23- devSysMemAddr_str devSysMemAddr [] = {
24- #ifdef STM32F0xx
25- {0x440 , 0x1FFFEC00 },
26- {0x444 , 0x1FFFEC00 },
27- {0x442 , 0x1FFFD800 },
28- {0x445 , 0x1FFFC400 },
29- {0x448 , 0x1FFFC800 },
30- #elif STM32F1xx
31- {0x412 , 0x1FFFF000 },
32- {0x410 , 0x1FFFF000 },
33- {0x414 , 0x1FFFF000 },
34- {0x420 , 0x1FFFF000 },
35- {0x428 , 0x1FFFF000 },
36- {0x418 , 0x1FFFB000 },
37- {0x430 , 0x1FFFE000 },
38- #elif STM32F2xx
39- {0x411 , 0x1FFF0000 },
40- #elif STM32F3xx
41- {SYSMEM_ADDR_COMMON , 0x1FFFD800 },
42- #elif STM32F4xx
43- {SYSMEM_ADDR_COMMON , 0x1FFF0000 },
44- #elif STM32F7xx
45- {SYSMEM_ADDR_COMMON , 0x1FF00000 },
46- #elif STM32G0xx
47- {SYSMEM_ADDR_COMMON , 0x1FFF0000 },
48- #elif STM32G4xx
49- {SYSMEM_ADDR_COMMON , 0x1FFF0000 },
50- #elif STM32H7xx
51- {0x450 , 0x1FF00000 },
52- #elif STM32L0xx
53- {SYSMEM_ADDR_COMMON , 0x1FF00000 },
54- #elif STM32L1xx
55- {SYSMEM_ADDR_COMMON , 0x1FF00000 },
56- #elif STM32L4xx
57- {SYSMEM_ADDR_COMMON , 0x1FFF0000 },
58- #elif STM32WBxx
59- {SYSMEM_ADDR_COMMON , 0x1FFF0000 },
60- #else
61- #warning "No system memory address for this serie!"
62- #endif
63- {0x0000 , 0x00000000 }
64- };
65-
66- uint32_t getSysMemAddr (void )
67- {
68- uint32_t sysMemAddr = 0 ;
69- if (devSysMemAddr [0 ].devID == SYSMEM_ADDR_COMMON ) {
70- sysMemAddr = devSysMemAddr [0 ].sysMemAddr ;
71- } else {
72- uint32_t devId = LL_DBGMCU_GetDeviceID ();
73- for (uint32_t id = 0 ; devSysMemAddr [id ].devID != 0 ; id ++ ) {
74- if (devSysMemAddr [id ].devID == devId ) {
75- sysMemAddr = devSysMemAddr [id ].sysMemAddr ;
76- break ;
77- }
78- }
79- }
80- return sysMemAddr ;
81- }
82-
8316/* Request to jump to system memory boot */
8417WEAK void jumpToBootloaderRequested (void )
8518{
@@ -93,14 +26,54 @@ WEAK void jumpToBootloaderRequested(void)
9326void Reset_Handler ()
9427{
9528 // Jump to the bootloader if needed.
96- jumpToBootloader ();
29+ jumpToBootloaderIfRequested ();
9730
9831 // Continue with regular startup by calling the original reset handler
9932 Original_Reset_Handler ();
10033}
10134
35+ /* Figure out where the bootloader lives, remapping memory if needed,
36+ * and return its address. The returned address should point to the
37+ * bootloader's interrupt vector table, so to a SP to load followed by
38+ * an address to jump to.
39+ */
40+ WEAK uint32_t bootloaderAddress ()
41+ {
42+ #ifdef __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH
43+ /* Remap system Flash memory at address 0x00000000 */
44+ __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH ();
45+ // Make the variable volatile to prevent the compiler from seeing a
46+ // null-pointer dereference (which is undefined in C) and generating
47+ // an UDF (undefined) instruction instead of just loading address 0.
48+ return 0 ;
49+ #elif defined(STM32F1xx ) && (defined (STM32F101xG ) || defined (STM32F103xG ))
50+ // From AN2606, table 136 "Bootloader device-dependent parameters"
51+ // STM32F10xxx XL-density, aka 768K-1M flash, aka F and G flash size codes
52+ return 0x1FFFE000 ;
53+ #elif defined(STM32F1xx ) && defined (STM32F105xC ) || defined (STM32F107xC )
54+ // STM32F105xx/107xx from AN2606, table 136 "Bootloader device-dependent parameters"
55+ return 0x1FFFB000 ;
56+ #elif defined (STM32F100xB ) || defined (STM32F100xE ) || defined (STM32F101x6 ) || \
57+ defined (STM32F101xB ) || defined (STM32F101xE ) || defined (STM32F102x6 ) || \
58+ defined (STM32F102xB ) || defined (STM32F103x6 ) || defined (STM32F103xB ) || \
59+ defined (STM32F103xE )
60+ // STM32F10xxx from AN2606, table 136 "Bootloader device-dependent parameters"
61+ // This does not check for STM32F1xx, to prevent catching
62+ // STM32F105xx/STM32F107xx or XL-density chips that are introduced later.
63+ // Defines from system/Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f1xx.h
64+ return 0x1FFFF000 ;
65+ #elif defined(STM32F7xx ) || defined(STM32H7xx )
66+ // From AN2606, table 136 "Bootloader device-dependent parameters"
67+ // TODO: Reference manual for has a different value...
68+ return 0x1FF00000 ;
69+ #else
70+ #error "System flash address unknown for this CPU"
71+ #endif
72+ }
73+
74+
10275/* Jump to system memory boot from user application */
103- WEAK void jumpToBootloader (void )
76+ WEAK void jumpToBootloaderIfRequested (void )
10477{
10578 // Boot into bootloader if BootIntoBootloaderAfterReset is set.
10679 // Note that BootIntoBootloaderAfterReset is a noinit variable, so it
@@ -114,54 +87,38 @@ WEAK void jumpToBootloader(void)
11487 BootIntoBootloaderAfterReset = false;
11588
11689 if (doBootloader ) {
90+ __HAL_RCC_CLEAR_RESET_FLAGS ();
91+
11792#ifdef USBCON
11893 USBD_reenumerate ();
11994#endif
12095 void (* sysMemBootJump )(void );
12196
122- __HAL_RCC_CLEAR_RESET_FLAGS ();
97+ uint32_t sys = bootloaderAddress ();
98+
99+ /**
100+ * Set jump memory location for system memory
101+ * Use address with 4 bytes offset which specifies jump location
102+ * where program starts
103+ */
104+ sysMemBootJump = (void (* )(void ))(* ((uint32_t * )(sysMem_addr + 4 )));
123105
124106 /**
125- * Get system memory address
107+ * Set main stack pointer.
108+ * This step must be done last otherwise local variables in this function
109+ * don't have proper value since stack pointer is located on different position
126110 *
127- * Available in AN2606 document:
128- * Table xxx Bootloader device-dependent parameters
111+ * Set direct address location which specifies stack pointer in SRAM location
129112 */
130- volatile uint32_t sysMem_addr = getSysMemAddr ();
131- /*
132- * If the system address is not not referenced in 'devSysMemAddr' array,
133- * does not do anything
113+ __set_MSP (* (uint32_t * )sysMem_addr );
114+
115+ /**
116+ * Jump to set location
117+ * This will start system memory execution
134118 */
135- if (sysMem_addr != 0 ) {
136- #ifdef __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH
137- /* Remap system Flash memory at address 0x00000000 */
138- __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH ();
139- #endif
119+ sysMemBootJump ();
140120
141- /**
142- * Set jump memory location for system memory
143- * Use address with 4 bytes offset which specifies jump location
144- * where program starts
145- */
146- sysMemBootJump = (void (* )(void ))(* ((uint32_t * )(sysMem_addr + 4 )));
147-
148- /**
149- * Set main stack pointer.
150- * This step must be done last otherwise local variables in this function
151- * don't have proper value since stack pointer is located on different position
152- *
153- * Set direct address location which specifies stack pointer in SRAM location
154- */
155- __set_MSP (* (uint32_t * )sysMem_addr );
156-
157- /**
158- * Jump to set location
159- * This will start system memory execution
160- */
161- sysMemBootJump ();
162-
163- while (1 );
164- }
121+ while (1 );
165122 }
166123}
167124
0 commit comments