Skip to content

Commit c6edf2b

Browse files
matthijskooijmanfpistm
authored andcommitted
Simplify system flash address detection
On most CPUs, detecting the system flash address is not needed, since they can remap the system flash onto adress 0x0 and the bootloader reset vector can be read from there. This approach also more closely mimics a bootloader start using the BOOTx pins. For CPUs that cannot remap flash, this hardcodes the address of system flash and jumps there instead. For H7 and F7, this is also how it works when using the BOOT pins. For F1, remapping can be done using the BOOT pins, but not from software, resulting in a difference with a BOOT-activated bootloader. This puts the code that figures out where the bootloader lives back in a separate function. This makes the code easier to read, and makes it easier to jump to custom bootloaders (e.g. in normal flash instead of in system flash). TODO: Check value for H7, AN2606 and reference manual disagree
1 parent 93de06d commit c6edf2b

File tree

2 files changed

+64
-107
lines changed

2 files changed

+64
-107
lines changed

cores/arduino/stm32/bootloader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ extern "C" {
1818
void jumpToBootloaderRequested(void);
1919

2020
/* Jump to system memory boot from user application */
21-
void jumpToBootloader(void);
21+
void jumpToBootloaderIfRequested(void);
2222

2323
#ifdef DTR_TOGGLING_SEQ
2424
/* DTR toggling sequence management */

libraries/SrcWrapper/src/stm32/bootloader.c

Lines changed: 63 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -10,76 +10,9 @@
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

1614
static 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 */
8417
WEAK void jumpToBootloaderRequested(void)
8518
{
@@ -93,14 +26,54 @@ WEAK void jumpToBootloaderRequested(void)
9326
void 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

Comments
 (0)