stm32: Move dfu reboot logic to new dfu_reboot.c file

Move the stm32 DFU reboot logic to a new dfu_reboot.c file.  This
simplifies the per-chip code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2022-12-15 11:23:28 -05:00
parent b6cd77f6e3
commit 4af8786587
10 changed files with 84 additions and 164 deletions

View File

@ -220,6 +220,15 @@ config STM32F103GD_DISABLE_SWD
and PA14 pins from being available. Selecting this option
disables SWD at startup and thus makes these pins available.
config STM32_DFU_ROM_ADDRESS
hex
default 0 if !USB
default 0x1fffc400 if MACH_STM32F042
default 0x1fffc800 if MACH_STM32F072
default 0x1fff0000 if MACH_STM32F4 || MACH_STM32G0 || MACH_STM32G4 || MACH_STM32L4
default 0x1ff09800 if MACH_STM32H7
default 0
######################################################################
# Bootloader

View File

@ -31,7 +31,8 @@ CFLAGS_klipper.elf += -T $(OUT)src/generic/armcm_link.ld
$(OUT)klipper.elf: $(OUT)src/generic/armcm_link.ld
# Add source files
src-y += stm32/watchdog.c stm32/gpio.c stm32/clockline.c generic/crc16_ccitt.c
src-y += stm32/watchdog.c stm32/gpio.c stm32/clockline.c stm32/dfu_reboot.c
src-y += generic/crc16_ccitt.c
src-y += generic/armcm_boot.c generic/armcm_irq.c generic/armcm_reset.c
src-$(CONFIG_MACH_STM32F0) += ../lib/stm32f0/system_stm32f0xx.c
src-$(CONFIG_MACH_STM32F0) += generic/timer_irq.c stm32/stm32f0_timer.c

57
src/stm32/dfu_reboot.c Normal file
View File

@ -0,0 +1,57 @@
// Reboot into stm32 ROM dfu bootloader
//
// Copyright (C) 2019-2022 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU GPLv3 license.
#include "internal.h" // NVIC_SystemReset
#include "board/irq.h" // irq_disable
// Many stm32 chips have a USB capable "DFU bootloader" in their ROM.
// In order to invoke that bootloader it is necessary to reset the
// chip and jump to a chip specific hardware address.
//
// To reset the chip, the dfu_reboot() code sets a flag in memory (at
// an arbitrary position that is unlikely to be overwritten during a
// chip reset), and resets the chip. If dfu_reboot_check() sees that
// flag on the next boot it will perform a code jump to the ROM
// address.
// Location of ram address to set internal flag
#if CONFIG_MACH_STM32H7
#define USB_BOOT_FLAG_ADDR (0x24000000 + 0x8000) // Place flag in "AXI SRAM"
#else
#define USB_BOOT_FLAG_ADDR (CONFIG_RAM_START + CONFIG_RAM_SIZE - 1024)
#endif
// Signature to set in memory to flag that a dfu reboot is requested
#define USB_BOOT_FLAG 0x55534220424f4f54 // "USB BOOT"
// Flag that bootloader is desired and reboot
void
dfu_reboot(void)
{
if (!CONFIG_STM32_DFU_ROM_ADDRESS)
return;
irq_disable();
uint64_t *bflag = (void*)USB_BOOT_FLAG_ADDR;
*bflag = USB_BOOT_FLAG;
#if CONFIG_MACH_STM32H7
SCB_CleanDCache_by_Addr((void*)bflag, sizeof(*bflag));
#endif
NVIC_SystemReset();
}
// Check if rebooting into system DFU Bootloader
void
dfu_reboot_check(void)
{
if (!CONFIG_STM32_DFU_ROM_ADDRESS)
return;
if (*(uint64_t*)USB_BOOT_FLAG_ADDR != USB_BOOT_FLAG)
return;
*(uint64_t*)USB_BOOT_FLAG_ADDR = 0;
uint32_t *sysbase = (uint32_t*)CONFIG_STM32_DFU_ROM_ADDRESS;
asm volatile("mov sp, %0\n bx %1"
: : "r"(sysbase[0]), "r"(sysbase[1]));
}

View File

@ -40,6 +40,10 @@ void gpio_peripheral(uint32_t gpio, uint32_t mode, int pullup);
void enable_pclock(uint32_t periph_base);
int is_enabled_pclock(uint32_t periph_base);
// dfu_reboot.c
void dfu_reboot(void);
void dfu_reboot_check(void);
// stm32??.c
struct cline { volatile uint32_t *en, *rst; uint32_t bit; };
struct cline lookup_clock_line(uint32_t periph_base);

View File

@ -134,39 +134,12 @@ hsi14_setup(void)
* Bootloader
****************************************************************/
#define USB_BOOT_FLAG_ADDR (CONFIG_RAM_START + CONFIG_RAM_SIZE - 1024)
#define USB_BOOT_FLAG 0x55534220424f4f54 // "USB BOOT"
// Flag that bootloader is desired and reboot
static void
usb_reboot_for_dfu_bootloader(void)
{
irq_disable();
*(uint64_t*)USB_BOOT_FLAG_ADDR = USB_BOOT_FLAG;
NVIC_SystemReset();
}
// Check if rebooting into system DFU Bootloader
static void
check_usb_dfu_bootloader(void)
{
if (!CONFIG_USB || !CONFIG_MACH_STM32F0x2
|| *(uint64_t*)USB_BOOT_FLAG_ADDR != USB_BOOT_FLAG)
return;
*(uint64_t*)USB_BOOT_FLAG_ADDR = 0;
uint32_t *sysbase = (uint32_t*)0x1fffc400;
if (CONFIG_MACH_STM32F072)
sysbase = (uint32_t*)0x1fffc800;
asm volatile("mov sp, %0\n bx %1"
: : "r"(sysbase[0]), "r"(sysbase[1]));
}
// Handle reboot requests
void
bootloader_request(void)
{
try_request_canboot();
usb_reboot_for_dfu_bootloader();
dfu_reboot();
}
@ -193,7 +166,7 @@ enable_ram_vectortable(void)
void
armcm_main(void)
{
check_usb_dfu_bootloader();
dfu_reboot_check();
SystemInit();
enable_pclock(SYSCFG_BASE);

View File

@ -204,30 +204,6 @@ usb_hid_bootloader(void)
NVIC_SystemReset();
}
#define USB_BOOT_FLAG_ADDR (CONFIG_RAM_START + CONFIG_RAM_SIZE - 4096)
#define USB_BOOT_FLAG 0x55534220424f4f54 // "USB BOOT"
// Flag that bootloader is desired and reboot
static void
usb_reboot_for_dfu_bootloader(void)
{
irq_disable();
*(uint64_t*)USB_BOOT_FLAG_ADDR = USB_BOOT_FLAG;
NVIC_SystemReset();
}
// Check if rebooting into system DFU Bootloader
static void
check_usb_dfu_bootloader(void)
{
if (!CONFIG_USB || *(uint64_t*)USB_BOOT_FLAG_ADDR != USB_BOOT_FLAG)
return;
*(uint64_t*)USB_BOOT_FLAG_ADDR = 0;
uint32_t *sysbase = (uint32_t*)0x1fff0000;
asm volatile("mov sp, %0\n bx %1"
: : "r"(sysbase[0]), "r"(sysbase[1]));
}
// Handle reboot requests
void
bootloader_request(void)
@ -235,7 +211,7 @@ bootloader_request(void)
try_request_canboot();
if (CONFIG_STM32_FLASH_START_4000)
usb_hid_bootloader();
usb_reboot_for_dfu_bootloader();
dfu_reboot();
}
@ -247,7 +223,7 @@ bootloader_request(void)
void
armcm_main(void)
{
check_usb_dfu_bootloader();
dfu_reboot_check();
// Run SystemInit() and then restore VTOR
SystemInit();

View File

@ -128,36 +128,12 @@ clock_setup(void)
* Bootloader
****************************************************************/
#define USB_BOOT_FLAG_ADDR (CONFIG_RAM_START + CONFIG_RAM_SIZE - 1024)
#define USB_BOOT_FLAG 0x55534220424f4f54 // "USB BOOT"
// Flag that bootloader is desired and reboot
static void
usb_reboot_for_dfu_bootloader(void)
{
irq_disable();
*(uint64_t*)USB_BOOT_FLAG_ADDR = USB_BOOT_FLAG;
NVIC_SystemReset();
}
// Check if rebooting into system DFU Bootloader
static void
check_usb_dfu_bootloader(void)
{
if (!CONFIG_USB || *(uint64_t*)USB_BOOT_FLAG_ADDR != USB_BOOT_FLAG)
return;
*(uint64_t*)USB_BOOT_FLAG_ADDR = 0;
uint32_t *sysbase = (uint32_t*)0x1fff0000;
asm volatile("mov sp, %0\n bx %1"
: : "r"(sysbase[0]), "r"(sysbase[1]));
}
// Handle USB reboot requests
void
bootloader_request(void)
{
try_request_canboot();
usb_reboot_for_dfu_bootloader();
dfu_reboot();
}
@ -185,7 +161,7 @@ armcm_main(void)
RCC->APBENR1 = 0x00000000;
RCC->APBENR2 = 0x00000000;
check_usb_dfu_bootloader();
dfu_reboot_check();
// Set flash latency, cache and prefetch; use reset value as base
uint32_t acr = 0x00040600;

View File

@ -139,36 +139,11 @@ clock_setup(void)
* Bootloader
****************************************************************/
#define USB_BOOT_FLAG_ADDR (CONFIG_RAM_START + CONFIG_RAM_SIZE - 4096)
#define USB_BOOT_FLAG 0x55534220424f4f54 // "USB BOOT"
// Flag that bootloader is desired and reboot
static void
usb_reboot_for_dfu_bootloader(void)
{
irq_disable();
// System DFU Bootloader
*(uint64_t*)USB_BOOT_FLAG_ADDR = USB_BOOT_FLAG;
NVIC_SystemReset();
}
// Check if rebooting into system DFU Bootloader
static void
check_usb_dfu_bootloader(void)
{
if (!CONFIG_USB || *(uint64_t*)USB_BOOT_FLAG_ADDR != USB_BOOT_FLAG)
return;
*(uint64_t*)USB_BOOT_FLAG_ADDR = 0;
uint32_t *sysbase = (uint32_t*)0x1fff0000;
asm volatile("mov sp, %0\n bx %1"
: : "r"(sysbase[0]), "r"(sysbase[1]));
}
// Handle USB reboot requests
void
bootloader_request(void)
{
usb_reboot_for_dfu_bootloader();
dfu_reboot();
}
@ -180,7 +155,7 @@ bootloader_request(void)
void
armcm_main(void)
{
check_usb_dfu_bootloader();
dfu_reboot_check();
// Run SystemInit() and then restore VTOR
SystemInit();

View File

@ -208,38 +208,12 @@ clock_setup(void)
* Bootloader
****************************************************************/
#define USB_BOOT_FLAG_ADDR (0x24000000 + 0x8000) // Place flag in "AXI SRAM"
#define USB_BOOT_FLAG 0x55534220424f4f54 // "USB BOOT"
// Flag that bootloader is desired and reboot
static void
usb_reboot_for_dfu_bootloader(void)
{
irq_disable();
uint64_t *bflag = (void*)USB_BOOT_FLAG_ADDR;
*bflag = USB_BOOT_FLAG;
SCB_CleanDCache_by_Addr((void*)bflag, sizeof(*bflag));
NVIC_SystemReset();
}
// Check if rebooting into system DFU Bootloader
static void
check_usb_dfu_bootloader(void)
{
if (!CONFIG_USB || *(uint64_t*)USB_BOOT_FLAG_ADDR != USB_BOOT_FLAG)
return;
*(uint64_t*)USB_BOOT_FLAG_ADDR = 0;
uint32_t *sysbase = (uint32_t*)0x1FF09800;
asm volatile("mov sp, %0\n bx %1"
: : "r"(sysbase[0]), "r"(sysbase[1]));
}
// Handle reboot requests
void
bootloader_request(void)
{
try_request_canboot();
usb_reboot_for_dfu_bootloader();
dfu_reboot();
}
@ -259,7 +233,7 @@ armcm_main(void)
RCC->D3CCIPR = 0x00000000;
SCB->VTOR = (uint32_t)VectorTable;
check_usb_dfu_bootloader();
dfu_reboot_check();
clock_setup();

View File

@ -139,36 +139,11 @@ clock_setup(void)
* Bootloader
****************************************************************/
#define USB_BOOT_FLAG_ADDR (CONFIG_RAM_START + CONFIG_RAM_SIZE - 4096)
#define USB_BOOT_FLAG 0x55534220424f4f54 // "USB BOOT"
// Flag that bootloader is desired and reboot
static void
usb_reboot_for_dfu_bootloader(void)
{
irq_disable();
// System DFU Bootloader
*(uint64_t*)USB_BOOT_FLAG_ADDR = USB_BOOT_FLAG;
NVIC_SystemReset();
}
// Check if rebooting into system DFU Bootloader
static void
check_usb_dfu_bootloader(void)
{
if (!CONFIG_USB || *(uint64_t*)USB_BOOT_FLAG_ADDR != USB_BOOT_FLAG)
return;
*(uint64_t*)USB_BOOT_FLAG_ADDR = 0;
uint32_t *sysbase = (uint32_t*)0x1fff0000;
asm volatile("mov sp, %0\n bx %1"
: : "r"(sysbase[0]), "r"(sysbase[1]));
}
// Handle USB reboot requests
void
bootloader_request(void)
{
usb_reboot_for_dfu_bootloader();
dfu_reboot();
}
@ -180,7 +155,7 @@ bootloader_request(void)
void
armcm_main(void)
{
check_usb_dfu_bootloader();
dfu_reboot_check();
// Run SystemInit() and then restore VTOR
SystemInit();