feat(stm32wl): add reboot-to-bootloader support via enter_dfu_mode_request (#10158)
This commit is contained in:
@@ -480,7 +480,7 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
|||||||
#if HAS_SCREEN
|
#if HAS_SCREEN
|
||||||
IF_SCREEN(screen->showSimpleBanner("Device is rebooting\ninto DFU mode.", 0));
|
IF_SCREEN(screen->showSimpleBanner("Device is rebooting\ninto DFU mode.", 0));
|
||||||
#endif
|
#endif
|
||||||
#if defined(ARCH_NRF52) || defined(ARCH_RP2040)
|
#if defined(ARCH_NRF52) || defined(ARCH_RP2040) || defined(ARCH_STM32WL)
|
||||||
enterDfuMode();
|
enterDfuMode();
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -4,6 +4,57 @@
|
|||||||
#include <stm32wle5xx.h>
|
#include <stm32wle5xx.h>
|
||||||
#include <stm32wlxx_hal.h>
|
#include <stm32wlxx_hal.h>
|
||||||
|
|
||||||
|
// ─── Bootloader redirect ──────────────────────────────────────────────────────
|
||||||
|
//
|
||||||
|
// Why .noinit + constructor instead of TAMP backup registers:
|
||||||
|
//
|
||||||
|
// The STM32duino startup sequence initialises clocks which may call
|
||||||
|
// __HAL_RCC_BACKUPRESET_FORCE/RELEASE when configuring the LSE oscillator,
|
||||||
|
// wiping the entire backup domain (including TAMP->BKP0R) before setup()
|
||||||
|
// ever runs. The backup-register approach therefore cannot reliably survive
|
||||||
|
// a soft reset in this toolchain.
|
||||||
|
//
|
||||||
|
// Solution: store the magic in a .noinit SRAM variable.
|
||||||
|
// - NVIC_SystemReset() does NOT clear SRAM.
|
||||||
|
// - The linker script skips zero-init for .noinit sections.
|
||||||
|
// - __attribute__((constructor)) fires before main()/HAL_Init(), so we can
|
||||||
|
// intercept and jump before anything disturbs peripheral state.
|
||||||
|
|
||||||
|
#define BOOTLOADER_MAGIC 0xD00DB007UL
|
||||||
|
#define SYS_MEM_BASE 0x1FFF0000UL
|
||||||
|
|
||||||
|
// Placed in .noinit — not zeroed at startup, survives NVIC_SystemReset().
|
||||||
|
__attribute__((section(".noinit"), used)) volatile uint32_t g_bootloaderMagic;
|
||||||
|
|
||||||
|
// Fires before main() / HAL_Init(). Must use only core Cortex-M registers.
|
||||||
|
__attribute__((constructor(101), used)) static void earlyBootCheck(void)
|
||||||
|
{
|
||||||
|
if (g_bootloaderMagic != BOOTLOADER_MAGIC)
|
||||||
|
return;
|
||||||
|
g_bootloaderMagic = 0;
|
||||||
|
|
||||||
|
SysTick->CTRL = 0;
|
||||||
|
SysTick->LOAD = 0;
|
||||||
|
SysTick->VAL = 0;
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
NVIC->ICER[i] = 0xFFFFFFFF;
|
||||||
|
NVIC->ICPR[i] = 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
__DSB();
|
||||||
|
__ISB();
|
||||||
|
SCB->VTOR = SYS_MEM_BASE;
|
||||||
|
__set_MSP(*(volatile uint32_t *)SYS_MEM_BASE);
|
||||||
|
((void (*)(void))(*(volatile uint32_t *)(SYS_MEM_BASE + 4)))();
|
||||||
|
while (1)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void enterDfuMode()
|
||||||
|
{
|
||||||
|
g_bootloaderMagic = BOOTLOADER_MAGIC;
|
||||||
|
HAL_NVIC_SystemReset();
|
||||||
|
}
|
||||||
|
|
||||||
void setBluetoothEnable(bool enable) {}
|
void setBluetoothEnable(bool enable) {}
|
||||||
|
|
||||||
void playStartMelody() {}
|
void playStartMelody() {}
|
||||||
|
|||||||
Reference in New Issue
Block a user