10
10
/*
11
11
* STM32 built-in bootloader in system memory support
12
12
*/
13
- /* Private definitions to manage system memory address */
14
- #define SYSMEM_ADDR_COMMON 0xFFF
15
13
16
14
static bool BootIntoBootloaderAfterReset ;
17
15
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
-
83
16
/* Request to jump to system memory boot */
84
17
WEAK void jumpToBootloaderRequested (void )
85
18
{
@@ -93,14 +26,54 @@ WEAK void jumpToBootloaderRequested(void)
93
26
void Reset_Handler ()
94
27
{
95
28
// Jump to the bootloader if needed.
96
- jumpToBootloader ();
29
+ jumpToBootloaderIfRequested ();
97
30
98
31
// Continue with regular startup by calling the original reset handler
99
32
Original_Reset_Handler ();
100
33
}
101
34
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
+
102
75
/* Jump to system memory boot from user application */
103
- WEAK void jumpToBootloader (void )
76
+ WEAK void jumpToBootloaderIfRequested (void )
104
77
{
105
78
// Boot into bootloader if BootIntoBootloaderAfterReset is set.
106
79
// Note that BootIntoBootloaderAfterReset is a noinit variable, so it
@@ -114,54 +87,38 @@ WEAK void jumpToBootloader(void)
114
87
BootIntoBootloaderAfterReset = false;
115
88
116
89
if (doBootloader ) {
90
+ __HAL_RCC_CLEAR_RESET_FLAGS ();
91
+
117
92
#ifdef USBCON
118
93
USBD_reenumerate ();
119
94
#endif
120
95
void (* sysMemBootJump )(void );
121
96
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 )));
123
105
124
106
/**
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
126
110
*
127
- * Available in AN2606 document:
128
- * Table xxx Bootloader device-dependent parameters
111
+ * Set direct address location which specifies stack pointer in SRAM location
129
112
*/
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
134
118
*/
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 ();
140
120
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 );
165
122
}
166
123
}
167
124
0 commit comments