From b417750116efc3d3a3e2e1db9617196a768c368f Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Wed, 16 Oct 2019 14:48:40 +0200 Subject: [PATCH] Jump to system memory boot from user application Fixes #706 Signed-off-by: Frederic Pillon --- cores/arduino/stm32/backup.h | 9 ++ cores/arduino/stm32/bootloader.c | 140 ++++++++++++++++++++++ cores/arduino/stm32/bootloader.h | 6 + cores/arduino/stm32/hw_config.c | 8 +- cores/arduino/stm32/usb/cdc/usbd_cdc_if.c | 3 + 5 files changed, 164 insertions(+), 2 deletions(-) diff --git a/cores/arduino/stm32/backup.h b/cores/arduino/stm32/backup.h index 72186c916a..89c970caa4 100644 --- a/cores/arduino/stm32/backup.h +++ b/cores/arduino/stm32/backup.h @@ -58,6 +58,15 @@ extern "C" { #endif /* HID_MAGIC_NUMBER_BKP_VALUE */ #endif /* BL_HID */ +#if !defined(SYSBL_MAGIC_NUMBER_BKP_INDEX) && defined(ENABLE_BACKUP_SUPPORT) +#define SYSBL_MAGIC_NUMBER_BKP_INDEX LL_RTC_BKP_DR2 +#else +#define SYSBL_MAGIC_NUMBER_BKP_INDEX 0 +#endif /* SYSBL_MAGIC_NUMBER_BKP_INDEX */ +#ifndef SYSBL_MAGIC_NUMBER_BKP_VALUE +#define SYSBL_MAGIC_NUMBER_BKP_VALUE 0x515B +#endif /* SYSBL_MAGIC_NUMBER_BKP_VALUE */ + /* Exported functions ------------------------------------------------------- */ static inline void resetBackupDomain(void) { diff --git a/cores/arduino/stm32/bootloader.c b/cores/arduino/stm32/bootloader.c index d7d86e968e..c8170295ea 100644 --- a/cores/arduino/stm32/bootloader.c +++ b/cores/arduino/stm32/bootloader.c @@ -2,7 +2,144 @@ #include "stm32_def.h" #include "backup.h" +#include "stm32yyxx_ll_system.h" +#include "usbd_if.h" +/* + * STM32 built-in bootloader in system memory support + */ +/* Private definitions to manage system memory address */ +#define SYSMEM_ADDR_COMMON 0xFFF + +typedef struct { + uint32_t devID; + uint32_t sysMemAddr; +} devSysMemAddr_str; + +devSysMemAddr_str devSysMemAddr[] = { +#ifdef STM32F0xx + {0x440, 0x1FFFEC00}, + {0x444, 0x1FFFEC00}, + {0x442, 0x1FFFD800}, + {0x445, 0x1FFFC400}, + {0x448, 0x1FFFC800}, + {0x442, 0x1FFFD800}, +#elif STM32F1xx + {0x412, 0x1FFFF000}, + {0x410, 0x1FFFF000}, + {0x414, 0x1FFFF000}, + {0x420, 0x1FFFF000}, + {0x428, 0x1FFFF000}, + {0x418, 0x1FFFB000}, + {0x430, 0x1FFFE000}, +#elif STM32F2xx + {0x411, 0x1FFF0000}, +#elif STM32F3xx + {SYSMEM_ADDR_COMMON, 0x1FFFD800}, +#elif STM32F4xx + {SYSMEM_ADDR_COMMON, 0x1FFF0000}, +#elif STM32F7xx + {SYSMEM_ADDR_COMMON, 0x1FF00000}, +#elif STM32G0xx + {SYSMEM_ADDR_COMMON, 0x1FFF0000}, +#elif STM32G4xx + {SYSMEM_ADDR_COMMON, 0x1FFF0000}, +#elif STM32H7xx + {0x450, 0x1FF00000}, +#elif STM32L0xx + {SYSMEM_ADDR_COMMON, 0x1FF00000}, +#elif STM32L1xx + {SYSMEM_ADDR_COMMON, 0x1FF00000}, +#elif STM32L4xx + {SYSMEM_ADDR_COMMON, 0x1FFF0000}, +#elif STM32WBxx + {SYSMEM_ADDR_COMMON, 0x1FFF0000}, +#else +#warning "No system memory address for this serie!" +#endif + {0x0000, 0x00000000} +}; + +uint32_t getSysMemAddr(void) +{ + uint32_t sysMemAddr = 0; + if (devSysMemAddr[0].devID == SYSMEM_ADDR_COMMON) { + sysMemAddr = devSysMemAddr[0].sysMemAddr; + } else { + uint32_t devId = LL_DBGMCU_GetDeviceID(); + for (uint32_t id = 0; devSysMemAddr[id].devID != 0; id++) { + if (devSysMemAddr[id].devID == devId) { + sysMemAddr = devSysMemAddr[id].sysMemAddr; + break; + } + } + } + return sysMemAddr; +} + +/* Request to jump to system memory boot */ +WEAK void jumpToBootloaderRequested(void) +{ + enableBackupDomain(); + setBackupRegister(SYSBL_MAGIC_NUMBER_BKP_INDEX, SYSBL_MAGIC_NUMBER_BKP_VALUE); + NVIC_SystemReset(); +} + +/* Jump to system memory boot from user application */ +WEAK void jumpToBootloader(void) +{ + enableBackupDomain(); + if (getBackupRegister(SYSBL_MAGIC_NUMBER_BKP_INDEX) == SYSBL_MAGIC_NUMBER_BKP_VALUE) { + setBackupRegister(SYSBL_MAGIC_NUMBER_BKP_INDEX, 0); + +#ifdef USBCON + USBD_reenumerate(); +#endif + void (*sysMemBootJump)(void); + + /** + * Get system memory address + * + * Available in AN2606 document: + * Table xxx Bootloader device-dependent parameters + */ + volatile uint32_t sysMem_addr = getSysMemAddr(); + if (sysMem_addr != 0) { +#ifdef __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH + /* Remap system Flash memory at address 0x00000000 */ + __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); +#endif + + /** + * Set jump memory location for system memory + * Use address with 4 bytes offset which specifies jump location + * where program starts + */ + sysMemBootJump = (void (*)(void))(*((uint32_t *)(sysMem_addr + 4))); + + /** + * Set main stack pointer. + * This step must be done last otherwise local variables in this function + * don't have proper value since stack pointer is located on different position + * + * Set direct address location which specifies stack pointer in SRAM location + */ + __set_MSP(*(uint32_t *)sysMem_addr); + + /** + * Jump to set location + * This will start system memory execution + */ + sysMemBootJump(); + + while (1); + } + } +} + +/* + * Legacy maple bootloader support + */ #ifdef BL_LEGACY_LEAF void dtr_togglingHook(uint8_t *buf, uint32_t *len) { @@ -17,6 +154,9 @@ void dtr_togglingHook(uint8_t *buf, uint32_t *len) } #endif /* BL_LEGACY_LEAF */ +/* + * HID bootloader support + */ #ifdef BL_HID void dtr_togglingHook(uint8_t *buf, uint32_t *len) { diff --git a/cores/arduino/stm32/bootloader.h b/cores/arduino/stm32/bootloader.h index 93931dfb46..ad1b967e08 100644 --- a/cores/arduino/stm32/bootloader.h +++ b/cores/arduino/stm32/bootloader.h @@ -14,6 +14,12 @@ extern "C" { #endif /* __cplusplus */ +/* Request to jump to system memory boot */ +void jumpToBootloaderRequested(void); + +/* Jump to system memory boot from user application */ +void jumpToBootloader(void); + #ifdef DTR_TOGGLING_SEQ /* DTR toggling sequence management */ void dtr_togglingHook(uint8_t *buf, uint32_t *len); diff --git a/cores/arduino/stm32/hw_config.c b/cores/arduino/stm32/hw_config.c index e5a8281d2e..1fa0a13718 100644 --- a/cores/arduino/stm32/hw_config.c +++ b/cores/arduino/stm32/hw_config.c @@ -35,10 +35,11 @@ * ****************************************************************************** */ -#include "stm32_def.h" +#include "bootloader.h" +#include "dwt.h" #include "hw_config.h" #include "usbd_if.h" -#include "dwt.h" +#include "stm32_def.h" #ifdef __cplusplus extern "C" { @@ -59,6 +60,9 @@ void hw_config_init(void) /* Initialize the HAL */ HAL_Init(); + /* Check if a jump to system memory boot requested */ + jumpToBootloader(); + /* Configure the system clock */ SystemClock_Config(); diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c index c596b899f4..2173ae63ac 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c @@ -168,6 +168,9 @@ static int8_t USBD_CDC_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length) linecoding.format = pbuf[4]; linecoding.paritytype = pbuf[5]; linecoding.datatype = pbuf[6]; + if (linecoding.bitrate == 1200) { + jumpToBootloaderRequested(); + } break; case CDC_GET_LINE_CODING: