diff options
Diffstat (limited to 'tmk_core/common')
| -rw-r--r-- | tmk_core/common/chibios/bootloader.c | 84 | 
1 files changed, 69 insertions, 15 deletions
diff --git a/tmk_core/common/chibios/bootloader.c b/tmk_core/common/chibios/bootloader.c index 4cf5dae7e6..dceeaa6b19 100644 --- a/tmk_core/common/chibios/bootloader.c +++ b/tmk_core/common/chibios/bootloader.c @@ -3,28 +3,82 @@  #include "ch.h"  #include "hal.h" -#ifdef STM32_BOOTLOADER_ADDRESS -/* STM32 */ -  /* This code should be checked whether it runs correctly on platforms */ -#    define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0)) +#define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0)) +#define BOOTLOADER_MAGIC 0xDEADBEEF +#define MAGIC_ADDR (unsigned long *)(SYMVAL(__ram0_end__) - 4) + +#ifndef STM32_BOOTLOADER_DUAL_BANK +#    define STM32_BOOTLOADER_DUAL_BANK FALSE +#endif + +#if STM32_BOOTLOADER_DUAL_BANK + +// Need pin definitions +#    include "config_common.h" + +#    ifndef STM32_BOOTLOADER_DUAL_BANK_GPIO +#        error "No STM32_BOOTLOADER_DUAL_BANK_GPIO defined, don't know which pin to toggle" +#    endif + +#    ifndef STM32_BOOTLOADER_DUAL_BANK_POLARITY +#        define STM32_BOOTLOADER_DUAL_BANK_POLARITY 0 +#    endif + +#    ifndef STM32_BOOTLOADER_DUAL_BANK_DELAY +#        define STM32_BOOTLOADER_DUAL_BANK_DELAY 100000 +#    endif + +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); +#    if STM32_BOOTLOADER_DUAL_BANK_POLARITY +        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)); +#    endif + +        // Wait for a while for the capacitor to charge +        bootdelay(STM32_BOOTLOADER_DUAL_BANK_DELAY); + +        // Issue a system reset to get the ROM bootloader to execute, with BOOT0 high +        NVIC_SystemReset(); +    } +} + +#elif defined(STM32_BOOTLOADER_ADDRESS)  // STM32_BOOTLOADER_DUAL_BANK +  extern uint32_t __ram0_end__; -#    define BOOTLOADER_MAGIC 0xDEADBEEF -#    define MAGIC_ADDR (unsigned long *)(SYMVAL(__ram0_end__) - 4) -/** \brief Jump to the bootloader - * - * FIXME: needs doc - */  void bootloader_jump(void) {      *MAGIC_ADDR = BOOTLOADER_MAGIC;  // set magic flag => reset handler will jump into boot loader      NVIC_SystemReset();  } -/** \brief Enter bootloader mode if requested - * - * FIXME: needs doc - */  void enter_bootloader_mode_if_requested(void) {      unsigned long *check = MAGIC_ADDR;      if (*check == BOOTLOADER_MAGIC) { @@ -41,7 +95,7 @@ void enter_bootloader_mode_if_requested(void) {      }  } -#elif defined(KL2x) || defined(K20x) /* STM32_BOOTLOADER_ADDRESS */ +#elif defined(KL2x) || defined(K20x)  // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS  /* Kinetis */  #    if defined(KIIBOHD_BOOTLOADER)  | 
