15
15
#define BANK_2_ADDRESS 0x08100000
16
16
#define SD_BOOTLOADER_ADDRESS 0x08032000
17
17
18
+ // Other software (like retro-go) should set this value
18
19
#define BOOTLOADER_MAGIC 0x544F4F42 // "BOOT"
20
+
21
+ // Intended for internal-use only; bypasses other checks
22
+ #define BOOTLOADER_MAGIC_FORCE 0x45435246 // "FRCE"
23
+
19
24
#define BOOTLOADER_MAGIC_ADDRESS ((uint32_t *)0x2001FFF8)
20
25
#define BOOTLOADER_JUMP_ADDRESS ((uint32_t **)0x2001FFFC)
26
+
21
27
static void __attribute__((naked )) start_app (void (* const pc )(void ), uint32_t sp ) {
22
28
__asm(" \n\
23
29
msr msp, r1 /* load r1 into MSP */\n\
@@ -26,7 +32,7 @@ static void __attribute__((naked)) start_app(void (* const pc)(void), uint32_t
26
32
}
27
33
28
34
static inline void set_bootloader (uint32_t address ){
29
- * BOOTLOADER_MAGIC_ADDRESS = BOOTLOADER_MAGIC ;
35
+ * BOOTLOADER_MAGIC_ADDRESS = BOOTLOADER_MAGIC_FORCE ;
30
36
* BOOTLOADER_JUMP_ADDRESS = (uint32_t * )address ;
31
37
}
32
38
@@ -38,13 +44,57 @@ static inline void set_bootloader(uint32_t address){
38
44
* So to run that app, set those values and execute a reset.
39
45
*/
40
46
void bootloader (){
47
+ if (* BOOTLOADER_MAGIC_ADDRESS == BOOTLOADER_MAGIC_FORCE ) {
48
+ * BOOTLOADER_MAGIC_ADDRESS = 0 ;
49
+ uint32_t sp = (* BOOTLOADER_JUMP_ADDRESS )[0 ];
50
+ uint32_t pc = (* BOOTLOADER_JUMP_ADDRESS )[1 ];
51
+ start_app ((void (* const )(void )) pc , (uint32_t ) sp );
52
+ }
53
+
54
+ HAL_Init ();
55
+
56
+ HAL_PWR_EnableBkUpAccess ();
57
+ __HAL_RCC_RTC_ENABLE ();
58
+ __HAL_RCC_GPIOC_CLK_ENABLE ();
59
+
60
+ RTC_HandleTypeDef hrtc = {0 };
61
+ hrtc .Instance = RTC ;
62
+ // Note: Don't need to call HAL_RTC_Init() since we're just reading backup register
63
+
64
+ GPIO_InitTypeDef GPIO_InitStruct = {0 };
65
+ GPIO_InitStruct .Pin = BTN_GAME_Pin ;
66
+ GPIO_InitStruct .Mode = GPIO_MODE_INPUT ;
67
+ GPIO_InitStruct .Pull = GPIO_PULLUP ; // Button connects to GND.
68
+ GPIO_InitStruct .Speed = GPIO_SPEED_FREQ_LOW ;
69
+
70
+ HAL_GPIO_Init (BTN_GAME_GPIO_Port , & GPIO_InitStruct );
71
+
72
+ if (HAL_GPIO_ReadPin (BTN_GAME_GPIO_Port , BTN_GAME_Pin ) == GPIO_PIN_RESET ) {
73
+ // If GAME is pressed: reset all triggers that might cause us to dual-boot.
74
+ * BOOTLOADER_MAGIC_ADDRESS = 0 ;
75
+ HAL_RTCEx_BKUPWrite (& hrtc , RTC_BKP_DR0 , 0 );
76
+ }
77
+
41
78
if (* BOOTLOADER_MAGIC_ADDRESS == BOOTLOADER_MAGIC ) {
42
79
* BOOTLOADER_MAGIC_ADDRESS = 0 ;
43
80
uint32_t sp = (* BOOTLOADER_JUMP_ADDRESS )[0 ];
44
81
uint32_t pc = (* BOOTLOADER_JUMP_ADDRESS )[1 ];
45
82
start_app ((void (* const )(void )) pc , (uint32_t ) sp );
46
83
}
47
84
85
+
86
+ if (HAL_RTCEx_BKUPRead (& hrtc , RTC_BKP_DR0 ) == BOOTLOADER_MAGIC ){
87
+ #if SD_BOOTLOADER
88
+ uint32_t sp = * ((uint32_t * )SD_BOOTLOADER_ADDRESS );
89
+ uint32_t pc = * ((uint32_t * )SD_BOOTLOADER_ADDRESS + 1 );
90
+ #else
91
+ uint32_t sp = * ((uint32_t * )BANK_2_ADDRESS );
92
+ uint32_t pc = * ((uint32_t * )BANK_2_ADDRESS + 1 );
93
+ #endif
94
+
95
+ start_app ((void (* const )(void )) pc , (uint32_t ) sp );
96
+ }
97
+
48
98
start_app (stock_Reset_Handler , * (uint32_t * ) MSP_ADDRESS );
49
99
while (1 );
50
100
}
@@ -101,16 +151,19 @@ gamepad_t read_buttons() {
101
151
NVIC_SystemReset ();
102
152
}
103
153
#endif
154
+
104
155
#if CLOCK_ONLY
105
156
if (gamepad & GAMEPAD_GAME ){
106
157
#else
107
158
if ((gamepad & GAMEPAD_LEFT ) && (gamepad & GAMEPAD_GAME )){
108
159
#endif
160
+
109
161
#if SD_BOOTLOADER
110
162
set_bootloader (SD_BOOTLOADER_ADDRESS );
111
163
#else
112
164
set_bootloader (BANK_2_ADDRESS );
113
165
#endif
166
+
114
167
NVIC_SystemReset ();
115
168
}
116
169
@@ -208,7 +261,6 @@ gnw_mode_t get_gnw_mode(){
208
261
}
209
262
#endif
210
263
211
-
212
264
void NMI_Handler (void ) {
213
265
__BKPT (0 );
214
266
}
0 commit comments