diff --git a/cores/arduino/stm32/backup.h b/cores/arduino/stm32/backup.h index 72186c916a..c0ac48ea7a 100644 --- a/cores/arduino/stm32/backup.h +++ b/cores/arduino/stm32/backup.h @@ -58,6 +58,13 @@ extern "C" { #endif /* HID_MAGIC_NUMBER_BKP_VALUE */ #endif /* BL_HID */ +#if !defined(SYSBL_MAGIC_NUMBER_BKP_INDEX) +#define SYSBL_MAGIC_NUMBER_BKP_INDEX LL_RTC_BKP_DR2 +#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..955def51b4 100644 --- a/cores/arduino/stm32/bootloader.c +++ b/cores/arduino/stm32/bootloader.c @@ -1,7 +1,7 @@ #include "bootloader.h" - #include "stm32_def.h" #include "backup.h" +#include "usbd_if.h" #ifdef BL_LEGACY_LEAF void dtr_togglingHook(uint8_t *buf, uint32_t *len) @@ -37,3 +37,60 @@ void dtr_togglingHook(uint8_t *buf, uint32_t *len) } } #endif /* BL_HID */ + +/* Request to jump to system memory boot */ +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 */ +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 116. Bootloader device-dependent parameters + */ + volatile uint32_t sysMem_addr = 0x1FFF0000; + + /* Remap system Flash memory at address 0x00000000 */ + __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); + + /** + * 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); + } +} diff --git a/cores/arduino/stm32/bootloader.h b/cores/arduino/stm32/bootloader.h index 93931dfb46..907aff06a1 100644 --- a/cores/arduino/stm32/bootloader.h +++ b/cores/arduino/stm32/bootloader.h @@ -19,6 +19,12 @@ extern "C" { void dtr_togglingHook(uint8_t *buf, uint32_t *len); #endif +/* Request to jump to system memory boot */ +void jumpToBootloaderRequested(void); + +/* Jump to system memory boot from user application */ +void jumpToBootloader(void); + #ifdef __cplusplus } #endif /* __cplusplus */ 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: