Add dual-bank STM32 bootloader support, given GPIO toggle on BOOT0 to charge RC circuit. (#8778)
This commit is contained in:
committed by
Drashna Jael're
parent
b3363f407b
commit
2d37b79534
@@ -3,28 +3,82 @@
|
|||||||
#include "ch.h"
|
#include "ch.h"
|
||||||
#include "hal.h"
|
#include "hal.h"
|
||||||
|
|
||||||
#ifdef STM32_BOOTLOADER_ADDRESS
|
|
||||||
/* STM32 */
|
|
||||||
|
|
||||||
/* This code should be checked whether it runs correctly on platforms */
|
/* 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))
|
||||||
extern uint32_t __ram0_end__;
|
|
||||||
#define BOOTLOADER_MAGIC 0xDEADBEEF
|
#define BOOTLOADER_MAGIC 0xDEADBEEF
|
||||||
#define MAGIC_ADDR (unsigned long *)(SYMVAL(__ram0_end__) - 4)
|
#define MAGIC_ADDR (unsigned long *)(SYMVAL(__ram0_end__) - 4)
|
||||||
|
|
||||||
/** \brief Jump to the bootloader
|
#ifndef STM32_BOOTLOADER_DUAL_BANK
|
||||||
*
|
# define STM32_BOOTLOADER_DUAL_BANK FALSE
|
||||||
* FIXME: needs doc
|
#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__;
|
||||||
|
|
||||||
void bootloader_jump(void) {
|
void bootloader_jump(void) {
|
||||||
*MAGIC_ADDR = BOOTLOADER_MAGIC; // set magic flag => reset handler will jump into boot loader
|
*MAGIC_ADDR = BOOTLOADER_MAGIC; // set magic flag => reset handler will jump into boot loader
|
||||||
NVIC_SystemReset();
|
NVIC_SystemReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \brief Enter bootloader mode if requested
|
|
||||||
*
|
|
||||||
* FIXME: needs doc
|
|
||||||
*/
|
|
||||||
void enter_bootloader_mode_if_requested(void) {
|
void enter_bootloader_mode_if_requested(void) {
|
||||||
unsigned long *check = MAGIC_ADDR;
|
unsigned long *check = MAGIC_ADDR;
|
||||||
if (*check == BOOTLOADER_MAGIC) {
|
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 */
|
/* Kinetis */
|
||||||
|
|
||||||
# if defined(KIIBOHD_BOOTLOADER)
|
# if defined(KIIBOHD_BOOTLOADER)
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP
|
#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP
|
||||||
// Change this to be TRUE once we've migrated keyboards to the new init system
|
// 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
|
# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP FALSE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user