Skip to content

Commit

Permalink
Add dual-bank STM32 bootloader support, given GPIO toggle on BOOT0 to…
Browse files Browse the repository at this point in the history
… charge RC circuit. (qmk#8778)
  • Loading branch information
tzarc authored and drashna committed Sep 30, 2020
1 parent b3363f4 commit 2d37b79
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 15 deletions.
84 changes: 69 additions & 15 deletions tmk_core/common/chibios/bootloader.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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)
Expand Down
1 change: 1 addition & 0 deletions tmk_core/protocol/chibios/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP
// Change this to be TRUE once we've migrated keyboards to the new init system
// Remember to change docs/platformdev_chibios_earlyinit.md as well.
# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP FALSE
#endif

Expand Down

0 comments on commit 2d37b79

Please sign in to comment.