Skip to content

Commit 4a429e2

Browse files
committed
builder patch & minor improvements
the builder patch is now auto-applied using a fork of the Arduino_Core_STM32 github. TOTALB_funcs.h is similar, but functions are templated (sothat you can jump back to the bootloader if you really want)
1 parent 45dd13e commit 4a429e2

File tree

4 files changed

+481
-36
lines changed

4 files changed

+481
-36
lines changed

Diff for: TOTALB_funcs.h

+33-10
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ LL_RCC_ClearResetFlags(); clears reset flags (Note: try to find, see if weak res
4242
#ifndef TOTALB_FUNCS_h // include only once
4343
#define TOTALB_FUNCS_h
4444

45-
#ifndef TOTALB_PROGRAM_START
46-
#error("TOTALB_funcs.h error: TOTALB_PROGRAM_START not defined! Only include this header if this is bootloader code")
47-
#endif
45+
// #ifndef TOTALB_PROGRAM_START
46+
// #error("TOTALB_funcs.h error: TOTALB_PROGRAM_START not defined! Only include this header if this is bootloader code")
47+
// #endif
4848

4949
#include <Arduino.h> // used for Serial (for debugging)
5050

@@ -55,6 +55,7 @@ namespace TOTALB {
5555
//// there is some variant-specific code below:
5656
#ifdef ARDUINO_P_NUCLEO_WB55RG // Note: alternative defines: STM32WB55xx
5757
#include <lock_resource.h> // for undo_SystemClock_Config()
58+
// #include <shci.h> // from STM32duinoBLE library, for SHCI_C2_Reinit() (to reset CPU2 (BLE) before jump). Commented out because i don't want to include STM32duinoBLE
5859

5960
/// @brief undoes what SystemClock_Config() did (see variant_P_NUCLEO_WB55RG.cpp) to bring clocks to a state similar to just-after-reset
6061
/// @param leave_LSE_same leaves LSE as it is (NOTE: might cause niche issues, BUT it does save ~124ms of re-initialization time after jump)
@@ -136,24 +137,33 @@ namespace TOTALB {
136137

137138
/// @brief check whether jumping to TOTALB_PROGRAM_START is (likely to be) safe
138139
/// @return true if it looks safe enough, false if you should ABSOLUTELY NOT jump there
139-
bool checkJumpLocation() {
140+
template<uint32_t __PROGRAM_START>
141+
bool _checkJumpLocation() {
140142
//// first and foremose, check if the flash
141-
const uint32_t* userAppStartPtr = (uint32_t*)(FLASH_BASE + TOTALB_PROGRAM_START); // (a pointer to) the place in flash where the actual app starts
143+
const uint32_t* userAppStartPtr = (uint32_t*)(FLASH_BASE + __PROGRAM_START); // (a pointer to) the place in flash where the actual app starts
142144
const uint32_t resetHandlerAddress = *(userAppStartPtr + 1); // find the reset handler function (2nd 32bit value) in the app's vector table (Note +1=+4_bytes=+(sizeof(ptr)))
143145
uint32_t newStackAddress = *userAppStartPtr; // read new stack pointer from flash (1st value of program) (usually it's 0x20030000)
144146
if(((newStackAddress == 0xFFFFFFFF) || (newStackAddress == 0x00000000))
145147
|| ((resetHandlerAddress == 0xFFFFFFFF) || (resetHandlerAddress == 0x00000000))) { return(false); } // the stack pointer should not look like empty flash
146148
//// similarly, you could check if you're about to jump into restricted space (like CPU2's Secure Flash)
147149
uint32_t SFSA = getSecureFlashStartAddr(); // obtain SFSA from option bytes (this is where CPU2's restricted territory begins)
148-
if((FLASH_BASE + TOTALB_PROGRAM_START) >= SFSA) { return(false); } // absolutely DO NOT jump to areas that CPU1 has no business in
150+
if((FLASH_BASE + __PROGRAM_START) >= SFSA) { return(false); } // absolutely DO NOT jump to areas that CPU1 has no business in
149151
//// else
150152
return(true);
151153
}
152154

153-
/// @brief de-initialize clocks & peripherals and attempt to start user-application
155+
#ifdef TOTALB_PROGRAM_START
156+
/// @brief check whether jumping to TOTALB_PROGRAM_START is (likely to be) safe
157+
/// @return true if it looks safe enough, false if you should ABSOLUTELY NOT jump there
158+
bool checkJumpLocation() { return(_checkJumpLocation<TOTALB_PROGRAM_START>()); }
159+
#endif
160+
161+
/// @brief (semi-private template version (not recommended)) de-initialize clocks & peripherals and attempt to start program at <__PROGRAM_START>
154162
/// @param leave_LSE_same leaves LSE as it is (NOTE: might cause niche issues, BUT it does save ~124ms of re-initialization time after jump)
155-
void jumpToProgram(bool leave_LSE_same=false) {
163+
template<uint32_t __PROGRAM_START>
164+
void _jumpTo(bool leave_LSE_same=false) {
156165
//// before jumping to the new app's reset handler, the system needs to be brought to reset-like state
166+
/* NOTE: call SHCI_C2_Reinit() from the STM32duinoBLE library (or Cube FW?) for resetting CPU2 (in case BLE was used before jump)*/
157167
//// the most important factor is resetting the clock & oscillator configs (without this step, it would crash so hard that it takes JTAG debuggers down with it)
158168
if(undo_SystemClock_Config(leave_LSE_same) != HAL_OK) { return; } // should always return HAL_OK
159169
//// repeated initialization of peripherals like the USART will also result in a nice silent crash..., so we're resetting all the peripherals next:
@@ -172,12 +182,12 @@ void jumpToProgram(bool leave_LSE_same=false) {
172182
+ DWT is for debugging (JTAG?), so it can be left on
173183
+ IPclock can be ignored (left enabled?), i think(?)
174184
*/
175-
const uint32_t* userAppStartPtr = (uint32_t*)(FLASH_BASE + TOTALB_PROGRAM_START); // (a pointer to) the place in flash where the actual app starts
185+
const uint32_t* userAppStartPtr = (uint32_t*)(FLASH_BASE + __PROGRAM_START); // (a pointer to) the place in flash where the actual app starts
176186
uint32_t newStackAddress = *userAppStartPtr; // read new stack pointer from flash (1st value of program) (usually it's 0x20030000)
177187
typedef void (*fct_t)(void);
178188
fct_t app_reset_handler = (fct_t) *(userAppStartPtr + 1); // find the reset handler function (2nd 32bit value) in the app's vector table (Note +1=+4_bytes=+(sizeof(ptr)))
179189
//// you can do some last-minute reassuring checks here, like: (Note: the clocks and peripherals have been disabled though, so debug printing is not easy)
180-
if(!checkJumpLocation()) { return; } // the stack pointer should not look like empty flash
190+
// if(!checkJumpLocation()) { return; } // the stack pointer should not look like empty flash
181191
//// now jump to the app:
182192
SCB->VTOR = (volatile uint32_t) userAppStartPtr; // set the Vector table pointer to the app's one
183193
__set_MSP(newStackAddress); // switch stack address pointer to the app's one (1st 32bit value in the vector table) (which is the stack pointer address) (probably the same as current)
@@ -191,6 +201,19 @@ void jumpToProgram(bool leave_LSE_same=false) {
191201
__WFI(); // 'wait for interrupt'
192202
}
193203

204+
#ifdef TOTALB_PROGRAM_START
205+
/// @brief de-initialize clocks & peripherals and attempt to start user-application (@ TOTALB_PROGRAM_START)
206+
/// @param leave_LSE_same leaves LSE as it is (NOTE: might cause niche issues, BUT it does save ~124ms of re-initialization time after jump)
207+
void jumpToProgram(bool leave_LSE_same=false) { _jumpTo<TOTALB_PROGRAM_START>(leave_LSE_same); }
208+
#endif
209+
210+
/// @brief check whether jumping to the bootloader is (likely to be) safe (it ABSOLUTELY SHOULD BE, BTW)
211+
/// @return true if it looks safe enough, false if you should ABSOLUTELY NOT jump there
212+
bool checkBootloaderLocation() { return(_checkJumpLocation< 0 >()); }
213+
/// @brief (not recommended, software-reset is preferred) de-initialize clocks & peripherals and attempt to start bootloader (again)
214+
/// @param leave_LSE_same leaves LSE as it is (NOTE: might cause niche issues, BUT it does save ~124ms of re-initialization time after jump)
215+
void jumpToBootloader(bool leave_LSE_same=false) { _jumpTo< 0 >(leave_LSE_same); } // bootloader starts at FLASH_BASE, so offset == 0
216+
194217
} // namespace TOTALB
195218

196219
#endif // TOTALB_FUNCS_h

0 commit comments

Comments
 (0)