Skip to content

Commit

Permalink
Re-fix the STM32 dual-bank bootloader stuff. (qmk#9738)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
tzarc authored and noroadsleft committed Aug 29, 2020
1 parent 224b2d9 commit 829e4a1
Showing 1 changed file with 15 additions and 31 deletions.
46 changes: 15 additions & 31 deletions tmk_core/common/chibios/bootloader.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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__;
Expand Down

0 comments on commit 829e4a1

Please sign in to comment.