1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-14 17:13:50 +01:00

cpu/stm32: implement reset to bootloader

The STM32 line of microcontrollers comes with a bootloader in the ROM.
It provides the option to flash the device firmware in DFU mode (USB)
or via UART or SPI.

To enter the bootloader we have to jump to a specific address in memory,
but before reset the CPU to make sure the system is in a known state.

This enables us to use the usb_board_reset module on all STM32 platforms.
This commit is contained in:
Benjamin Valentin 2020-05-22 21:35:53 +02:00 committed by Benjamin Valentin
parent e32c772eb4
commit 0819f0eb39
16 changed files with 293 additions and 1 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,3 @@
MODULE = bootloader_stm32
include $(RIOTBASE)/Makefile.base

View File

@ -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 <benpicco@googlemail.com>
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
*
* @}
*/
#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();
}

View File

@ -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
* @{

View File

@ -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
* @{

View File

@ -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
* @{

View File

@ -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 <hauke.petersen@fu-berlin.de>
*/
#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 */
/** @} */

View File

@ -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
* @{

View File

@ -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 <hauke.petersen@fu-berlin.de>
*
*/
#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 */
/** @} */

View File

@ -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
* @{

View File

@ -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
* @{

View File

@ -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
* @{

View File

@ -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 <francois-xavier.molina@inria.fr>
*
*/
#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 */
/** @} */

View File

@ -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
*