diff --git a/cpu/stm32/Makefile b/cpu/stm32/Makefile index 3c379f1ec9..7cfdddf258 100644 --- a/cpu/stm32/Makefile +++ b/cpu/stm32/Makefile @@ -1,5 +1,5 @@ MODULE = cpu -DIRS = $(RIOTCPU)/cortexm_common periph stmclk vectors +DIRS = $(RIOTCPU)/cortexm_common periph stmclk vectors bootloader include $(RIOTBASE)/Makefile.base diff --git a/cpu/stm32/Makefile.dep b/cpu/stm32/Makefile.dep index 737767266e..07adf57c7f 100644 --- a/cpu/stm32/Makefile.dep +++ b/cpu/stm32/Makefile.dep @@ -8,4 +8,8 @@ ifneq (,$(filter periph_usbdev,$(FEATURES_USED))) USEMODULE += xtimer endif +ifneq (,$(filter bootloader_stm32,$(FEATURES_USED))) + USEMODULE += bootloader_stm32 +endif + include $(RIOTCPU)/cortexm_common/Makefile.dep diff --git a/cpu/stm32/Makefile.features b/cpu/stm32/Makefile.features index 88853e93c3..ebf0c8aa1e 100644 --- a/cpu/stm32/Makefile.features +++ b/cpu/stm32/Makefile.features @@ -1,5 +1,6 @@ include $(RIOTCPU)/stm32/stm32_info.mk +FEATURES_PROVIDED += bootloader_stm32 FEATURES_PROVIDED += cpu_stm32$(CPU_FAM) FEATURES_PROVIDED += periph_cpuid FEATURES_PROVIDED += periph_gpio periph_gpio_irq diff --git a/cpu/stm32/bootloader/Makefile b/cpu/stm32/bootloader/Makefile new file mode 100644 index 0000000000..ee7308dcfb --- /dev/null +++ b/cpu/stm32/bootloader/Makefile @@ -0,0 +1,3 @@ +MODULE = bootloader_stm32 + +include $(RIOTBASE)/Makefile.base diff --git a/cpu/stm32/bootloader/reset.c b/cpu/stm32/bootloader/reset.c new file mode 100644 index 0000000000..0a8e10c58f --- /dev/null +++ b/cpu/stm32/bootloader/reset.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2020 Benjamin Valentin + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup cpu_stm32 + * @{ + * + * @file + * @brief Trigger reset to the bootloader stored in the internal boot ROM + * memory. + * + * This will start the DFU/UART/SPI bootloader. + * See application note AN2606 for which options are available on + * your individual MCU. + * + * @author Benjamin Valentin + * @author Marian Buschsieweke + * + * @} + */ + +#include "cpu.h" +#include "periph_cpu.h" +#include "sched.h" + +/* repurpose the sched_context_switch_request variable to signal + * jump to bootloader after reset */ +#define MAGIC sched_context_switch_request +#define BOOTLOADER_MAGIC 0xB007AFFE + +/* called by reset_handler_default() before memory is initialized */ +void pre_startup(void) +{ + if (MAGIC != BOOTLOADER_MAGIC) { + return; + } + + /* clear magic */ + MAGIC = 0; + + /* enable SYSCFG clock */ +#if defined(RCC_APB2ENR_SYSCFGEN) + RCC->APB2ENR = RCC_APB2ENR_SYSCFGEN; +#elif defined(RCC_APB2ENR_SYSCFGCOMPEN) + RCC->APB2ENR = RCC_APB2ENR_SYSCFGCOMPEN +#endif + + /* remap ROM at zero */ +#if defined(SYSCFG_MEMRMP_MEM_MODE_0) + SYSCFG->MEMRMP = SYSCFG_MEMRMP_MEM_MODE_0; +#elif defined(SYSCFG_CFGR1_MEM_MODE_0) + SYSCFG->CFGR1 = SYSCFG_CFGR1_MEM_MODE_0; +#endif + + /* jump to the bootloader */ + __asm__ volatile( + "ldr r0, [%[btldr]] \n" + "mov sp, r0 \n" + "ldr r0, [%[btldr], #4] \n" + "mov pc, r0 \n" + : /* no outputs */ + : [btldr] "r" ((uintptr_t)STM32_BOOTLOADER_ADDR) + : "r0", "memory" + ); +} + +void __attribute__((weak)) usb_board_reset_in_bootloader(void) +{ + irq_disable(); + MAGIC = BOOTLOADER_MAGIC; + NVIC_SystemReset(); +} diff --git a/cpu/stm32/include/periph/f0/periph_cpu.h b/cpu/stm32/include/periph/f0/periph_cpu.h index c710966e8f..11d8f7b389 100644 --- a/cpu/stm32/include/periph/f0/periph_cpu.h +++ b/cpu/stm32/include/periph/f0/periph_cpu.h @@ -24,6 +24,23 @@ extern "C" { #endif #ifndef DOXYGEN + +/** + * @brief Starting address of the ROM bootloader + * see application note AN2606 + */ +#if defined(CPU_LINE_STM32F030x4) || defined(CPU_LINE_STM32F030x6) || \ + defined(CPU_LINE_STM32F030x8) || defined(CPU_LINE_STM32F031x6) || \ + defined(CPU_LINE_STM32F051x8) +#define STM32_BOOTLOADER_ADDR (0x1FFFEC00) +#elif defined(CPU_LINE_STM32F072xB) || defined(CPU_LINE_STM32F070xB) +#define STM32_BOOTLOADER_ADDR (0x1FFFC800) +#elif defined(CPU_LINE_STM32F030xC) || defined(CPU_LINE_STM32F091xC) +#define STM32_BOOTLOADER_ADDR (0x1FFFD800) +#elif defined(CPU_LINE_STM32F042x6) +#define STM32_BOOTLOADER_ADDR (0x1FFFC400) +#endif + /** * @brief Override ADC resolution values * @{ diff --git a/cpu/stm32/include/periph/f1/periph_cpu.h b/cpu/stm32/include/periph/f1/periph_cpu.h index 8ef83e2abf..184d33834a 100644 --- a/cpu/stm32/include/periph/f1/periph_cpu.h +++ b/cpu/stm32/include/periph/f1/periph_cpu.h @@ -23,6 +23,18 @@ extern "C" { #endif +#ifndef DOXYGEN + +/** + * @brief Starting address of the ROM bootloader + * see application note AN2606 + */ +#if defined(CPU_LINE_STM32F103xB) || defined(CPU_LINE_STM32F103xE) +#define STM32_BOOTLOADER_ADDR (0x1FFFF000) +#endif + +#endif /* ndef DOXYGEN */ + /** * @name Real time counter configuration * @{ diff --git a/cpu/stm32/include/periph/f2/periph_cpu.h b/cpu/stm32/include/periph/f2/periph_cpu.h index ac8cc0d065..656704f662 100644 --- a/cpu/stm32/include/periph/f2/periph_cpu.h +++ b/cpu/stm32/include/periph/f2/periph_cpu.h @@ -31,6 +31,13 @@ extern "C" { #define ADC_DEVS (2U) #ifndef DOXYGEN + +/** + * @brief Starting address of the ROM bootloader + * see application note AN2606 + */ +#define STM32_BOOTLOADER_ADDR (0x1FFF0000) + /** * @brief Override the ADC resolution configuration * @{ diff --git a/cpu/stm32/include/periph/f3/periph_cpu.h b/cpu/stm32/include/periph/f3/periph_cpu.h new file mode 100644 index 0000000000..d27950e935 --- /dev/null +++ b/cpu/stm32/include/periph/f3/periph_cpu.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2015-2016 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_stm32 + * @{ + * + * @file + * @brief STM32F3 CPU specific definitions for internal peripheral handling + * + * @author Hauke Petersen + */ + +#ifndef PERIPH_F3_PERIPH_CPU_H +#define PERIPH_F3_PERIPH_CPU_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef DOXYGEN + +/** + * @brief Starting address of the ROM bootloader + * see application note AN2606 + */ +#define STM32_BOOTLOADER_ADDR (0x1FFFD800) + +#endif /* ndef DOXYGEN */ + +#ifdef __cplusplus +} +#endif + +#endif /* PERIPH_F3_PERIPH_CPU_H */ +/** @} */ diff --git a/cpu/stm32/include/periph/f4/periph_cpu.h b/cpu/stm32/include/periph/f4/periph_cpu.h index 03cb4a1494..886c9e6178 100644 --- a/cpu/stm32/include/periph/f4/periph_cpu.h +++ b/cpu/stm32/include/periph/f4/periph_cpu.h @@ -37,6 +37,17 @@ extern "C" { #endif #ifndef DOXYGEN + +/** + * @brief Starting address of the ROM bootloader + * see application note AN2606 + */ +#if defined(CPU_LINE_STM32F423xx) +#define STM32_BOOTLOADER_ADDR (0x1FF00000) +#else +#define STM32_BOOTLOADER_ADDR (0x1FFF0000) +#endif + /** * @brief Override the ADC resolution configuration * @{ diff --git a/cpu/stm32/include/periph/f7/periph_cpu.h b/cpu/stm32/include/periph/f7/periph_cpu.h new file mode 100644 index 0000000000..401b6e2de0 --- /dev/null +++ b/cpu/stm32/include/periph/f7/periph_cpu.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2017 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_stm32 + * @{ + * + * @file + * @brief STM32F7 CPU specific definitions for internal peripheral handling + * + * @author Hauke Petersen + * + */ + +#ifndef PERIPH_F7_PERIPH_CPU_H +#define PERIPH_F7_PERIPH_CPU_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef DOXYGEN + +/** + * @brief Starting address of the ROM bootloader + * see application note AN2606 + */ +#define STM32_BOOTLOADER_ADDR (0x1FF00000) + +#endif /* ndef DOXYGEN */ + +#ifdef __cplusplus +} +#endif + +#endif /* PERIPH_F7_PERIPH_CPU_H */ +/** @} */ diff --git a/cpu/stm32/include/periph/l0/periph_cpu.h b/cpu/stm32/include/periph/l0/periph_cpu.h index 058b9a2593..589e1f650a 100644 --- a/cpu/stm32/include/periph/l0/periph_cpu.h +++ b/cpu/stm32/include/periph/l0/periph_cpu.h @@ -27,6 +27,13 @@ extern "C" { #endif #ifndef DOXYGEN + +/** + * @brief Starting address of the ROM bootloader + * see application note AN2606 + */ +#define STM32_BOOTLOADER_ADDR (0x1FF00000) + /** * @brief Override ADC resolution values * @{ diff --git a/cpu/stm32/include/periph/l1/periph_cpu.h b/cpu/stm32/include/periph/l1/periph_cpu.h index cced46363b..b2b1734d31 100644 --- a/cpu/stm32/include/periph/l1/periph_cpu.h +++ b/cpu/stm32/include/periph/l1/periph_cpu.h @@ -26,6 +26,13 @@ extern "C" { #endif #ifndef DOXYGEN + +/** + * @brief Starting address of the ROM bootloader + * see application note AN2606 + */ +#define STM32_BOOTLOADER_ADDR (0x1FF00000) + /** * @brief Override the ADC resolution configuration * @{ diff --git a/cpu/stm32/include/periph/l4/periph_cpu.h b/cpu/stm32/include/periph/l4/periph_cpu.h index 21fdf15889..78075b11b0 100644 --- a/cpu/stm32/include/periph/l4/periph_cpu.h +++ b/cpu/stm32/include/periph/l4/periph_cpu.h @@ -42,6 +42,13 @@ extern "C" { #endif #ifndef DOXYGEN + +/** + * @brief Starting address of the ROM bootloader + * see application note AN2606 + */ +#define STM32_BOOTLOADER_ADDR (0x1FFF0000) + /** * @brief Override ADC resolution values * @{ diff --git a/cpu/stm32/include/periph/wb/periph_cpu.h b/cpu/stm32/include/periph/wb/periph_cpu.h new file mode 100644 index 0000000000..0928df59e3 --- /dev/null +++ b/cpu/stm32/include/periph/wb/periph_cpu.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019 Inria + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_stm32 + * @{ + * + * @file + * @brief STM32WB CPU specific definitions for internal peripheral handling + * + * @author Francisco Molina + * + */ + +#ifndef PERIPH_WB_PERIPH_CPU_H +#define PERIPH_WB_PERIPH_CPU_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef DOXYGEN + +/** + * @brief Starting address of the ROM bootloader + * see application note AN2606 + */ +#define STM32_BOOTLOADER_ADDR (0x1FFF0000) + +#endif /* ndef DOXYGEN */ + +#ifdef __cplusplus +} +#endif + +#endif /* PERIPH_WB_PERIPH_CPU_H */ +/** @} */ diff --git a/cpu/stm32/include/periph_cpu.h b/cpu/stm32/include/periph_cpu.h index 00e6ca3107..5ceced1675 100644 --- a/cpu/stm32/include/periph_cpu.h +++ b/cpu/stm32/include/periph_cpu.h @@ -29,14 +29,20 @@ #include "periph/f1/periph_cpu.h" #elif defined(CPU_FAM_STM32F2) #include "periph/f2/periph_cpu.h" +#elif defined(CPU_FAM_STM32F3) +#include "periph/f3/periph_cpu.h" #elif defined(CPU_FAM_STM32F4) #include "periph/f4/periph_cpu.h" +#elif defined(CPU_FAM_STM32F7) +#include "periph/f7/periph_cpu.h" #elif defined(CPU_FAM_STM32L0) #include "periph/l0/periph_cpu.h" #elif defined(CPU_FAM_STM32L1) #include "periph/l1/periph_cpu.h" #elif defined(CPU_FAM_STM32L4) #include "periph/l4/periph_cpu.h" +#elif defined(CPU_FAM_STM32WB) +#include "periph/wb/periph_cpu.h" #endif #ifdef __cplusplus @@ -59,6 +65,14 @@ extern "C" { #error "error: LSI clock speed not defined for your target CPU" #endif +#ifdef Doxygen +/** + * @brief Starting address of the ROM bootloader + * see application note AN2606 + */ +#define STM32_BOOTLOADER_ADDR +#endif + /** * @brief Length of the CPU_ID in octets * diff --git a/tests/stm32_bootloader/Makefile b/tests/stm32_bootloader/Makefile new file mode 100644 index 0000000000..ea9ef31f44 --- /dev/null +++ b/tests/stm32_bootloader/Makefile @@ -0,0 +1,10 @@ +BOARD ?= nucleo-f411re +include ../Makefile.tests_common + +FEATURES_REQUIRED = bootloader_stm32 + +USEMODULE += shell +USEMODULE += shell_commands +USEMODULE += usb_board_reset + +include $(RIOTBASE)/Makefile.include diff --git a/tests/stm32_bootloader/main.c b/tests/stm32_bootloader/main.c new file mode 100644 index 0000000000..f61f9fc6b5 --- /dev/null +++ b/tests/stm32_bootloader/main.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2020 Benjamin Valentin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup tests + * @{ + * + * @file + * @brief Test application to activate the STM32 bootloader mode. + * + * @author Benjamin Valentin + * + * @} + */ + +#include +#include + +#include "shell.h" +#include "shell_commands.h" + +int main(void) +{ + char line_buf[SHELL_DEFAULT_BUFSIZE]; + + puts("STM32 bootloader test application."); + + /* bootloader command is provided by default */ + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); + + return 0; +}