~ruther/qmk_firmware

686a9d35ffe1cf834673be2991d7bf1025423ae6 — Nick Brassel 5 years ago b0335b2
Re-fix the STM32 dual-bank bootloader stuff. (#9738)

* Re-fix the dual-bank bootloader stuff.

* Use wait_ms() instead of using nop's for a delay, as ChibiOS is actually running at the time of bootloader jump.
1 files changed, 15 insertions(+), 31 deletions(-)

M tmk_core/common/chibios/bootloader.c
M tmk_core/common/chibios/bootloader.c => tmk_core/common/chibios/bootloader.c +15 -31
@@ 2,6 2,7 @@

#include "ch.h"
#include "hal.h"
#include "wait.h"

/* This code should be checked whether it runs correctly on platforms */
#define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))


@@ 31,45 32,28 @@

extern uint32_t __ram0_end__;

#    define bootdelay(loopcount)                  \
        do {                                      \
            for (int i = 0; i < loopcount; ++i) { \
                __asm__ volatile("nop\n\t"        \
                                 "nop\n\t"        \
                                 "nop\n\t");      \
            }                                     \
        } while (0)

void bootloader_jump(void) {
    *MAGIC_ADDR = BOOTLOADER_MAGIC;  // set magic flag => reset handler will jump into boot loader
    NVIC_SystemReset();
}

void enter_bootloader_mode_if_requested(void) {
    unsigned long *check = MAGIC_ADDR;
    if (*check == BOOTLOADER_MAGIC) {
        *check = 0;

        // For STM32 MCUs with dual-bank flash, and we're incapable of jumping to the bootloader. The first valid flash
        // bank is executed unconditionally after a reset, so it doesn't enter DFU unless BOOT0 is high. Instead, we do
        // it with hardware...in this case, we pull a GPIO high/low depending on the configuration, connects 3.3V to
        // BOOT0's RC charging circuit, lets it charge the capacitor, and issue a system reset. See the QMK discord
        // #hardware channel pins for an example circuit.
        palSetPadMode(PAL_PORT(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_PAD(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_MODE_OUTPUT_PUSHPULL);
    // For STM32 MCUs with dual-bank flash, and we're incapable of jumping to the bootloader. The first valid flash
    // bank is executed unconditionally after a reset, so it doesn't enter DFU unless BOOT0 is high. Instead, we do
    // it with hardware...in this case, we pull a GPIO high/low depending on the configuration, connects 3.3V to
    // BOOT0's RC charging circuit, lets it charge the capacitor, and issue a system reset. See the QMK discord
    // #hardware channel pins for an example circuit.
    palSetPadMode(PAL_PORT(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_PAD(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_MODE_OUTPUT_PUSHPULL);
#    if STM32_BOOTLOADER_DUAL_BANK_POLARITY
        palSetPad(PAL_PORT(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_PAD(STM32_BOOTLOADER_DUAL_BANK_GPIO));
    palSetPad(PAL_PORT(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_PAD(STM32_BOOTLOADER_DUAL_BANK_GPIO));
#    else
        palClearPad(PAL_PORT(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_PAD(STM32_BOOTLOADER_DUAL_BANK_GPIO));
    palClearPad(PAL_PORT(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_PAD(STM32_BOOTLOADER_DUAL_BANK_GPIO));
#    endif

        // Wait for a while for the capacitor to charge
        bootdelay(STM32_BOOTLOADER_DUAL_BANK_DELAY);
    // Wait for a while for the capacitor to charge
    wait_ms(100);

        // Issue a system reset to get the ROM bootloader to execute, with BOOT0 high
        NVIC_SystemReset();
    }
    // Issue a system reset to get the ROM bootloader to execute, with BOOT0 high
    NVIC_SystemReset();
}

void enter_bootloader_mode_if_requested(void) {}  // not needed at all, but if anybody attempts to invoke it....

#elif defined(STM32_BOOTLOADER_ADDRESS)  // STM32_BOOTLOADER_DUAL_BANK

extern uint32_t __ram0_end__;