From 3d8253add0d0763f144eb3b3158e85f48d7fbc4e Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 26 Jan 2026 13:12:09 -0600 Subject: [PATCH] Fix STM32H7 DFU mode entry via CLI command The CLI 'dfu' command on STM32H743/H750 targets was failing to enter DFU bootloader mode. The board would reboot but return as a VCP device instead of entering DFU mode for firmware flashing. Root cause: Bootloader request check was happening too late in the boot sequence, after clock and peripheral initialization. The H7 bootloader requires the RTC backup register check to occur before any system configuration. Solution: Move checkForBootLoaderRequest() from systemInit() to SystemInit(), which is called by CMSIS startup code before any hardware initialization. Also enable SYSCFG clock before jumping to bootloader, matching the working Betaflight implementation for H7. Changes: - src/main/target/system_stm32h7xx.c: Call checkForBootLoaderRequest() early in SystemInit() before clock configuration - src/main/drivers/system_stm32h7xx.c: Remove late call from systemInit() - src/main/drivers/system.c: Add H7-specific bootloader jump code that enables SYSCFG clock before jumping Tested on DAKEFPVH743PRO - CLI 'dfu' command now successfully enters DFU mode for firmware flashing. Fixes issue present in 7.1.2, 8.0.0, and 9.0.0 releases. --- src/main/drivers/system.c | 16 ++++++++++++++++ src/main/drivers/system_stm32h7xx.c | 2 -- src/main/target/system_stm32h7xx.c | 3 +++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/main/drivers/system.c b/src/main/drivers/system.c index 18a569857e2..f5c28cdadf0 100644 --- a/src/main/drivers/system.c +++ b/src/main/drivers/system.c @@ -104,6 +104,7 @@ void systemResetToBootloader(void) systemResetRequest(RESET_BOOTLOADER_REQUEST_ROM); } + typedef void resetHandler_t(void); typedef struct isrVector_s { @@ -119,14 +120,29 @@ void checkForBootLoaderRequest(void) if (bootloaderRequest != RESET_BOOTLOADER_REQUEST_ROM) { return; } + + // Clear the reset reason before jumping persistentObjectWrite(PERSISTENT_OBJECT_RESET_REASON, RESET_NONE); +#if defined(STM32H7) + + // Enable SYSCFG clock (required for bootloader) + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + // Jump to bootloader volatile isrVector_t *bootloaderVector = (isrVector_t *)systemBootloaderAddress(); __set_MSP(bootloaderVector->stackEnd); bootloaderVector->resetHandler(); + while (1); +#else + // On F4/F7, jump to bootloader + volatile isrVector_t *bootloaderVector = (isrVector_t *)systemBootloaderAddress(); + __set_MSP(bootloaderVector->stackEnd); + bootloaderVector->resetHandler(); while (1); +#endif } #define SHORT_FLASH_DURATION 50 diff --git a/src/main/drivers/system_stm32h7xx.c b/src/main/drivers/system_stm32h7xx.c index af3ea72e2a2..000fe74d828 100644 --- a/src/main/drivers/system_stm32h7xx.c +++ b/src/main/drivers/system_stm32h7xx.c @@ -62,8 +62,6 @@ uint32_t systemBootloaderAddress(void) void systemInit(void) { - checkForBootLoaderRequest(); - // Configure NVIC preempt/priority groups HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITY_GROUPING); diff --git a/src/main/target/system_stm32h7xx.c b/src/main/target/system_stm32h7xx.c index cc580320b5a..6ec0d1c4002 100644 --- a/src/main/target/system_stm32h7xx.c +++ b/src/main/target/system_stm32h7xx.c @@ -584,6 +584,9 @@ void SystemInit (void) initialiseMemorySections(); + // Check for bootloader request BEFORE any clock/peripheral configuration + checkForBootLoaderRequest(); + // FPU settings #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); // Set CP10 and CP11 Full Access