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 and PA14 pins from being available. Selecting this option
disables SWD at startup and thus makes these pins available. 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 # 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 $(OUT)klipper.elf: $(OUT)src/generic/armcm_link.ld
# Add source files # 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-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) += ../lib/stm32f0/system_stm32f0xx.c
src-$(CONFIG_MACH_STM32F0) += generic/timer_irq.c stm32/stm32f0_timer.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); void enable_pclock(uint32_t periph_base);
int is_enabled_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 // stm32??.c
struct cline { volatile uint32_t *en, *rst; uint32_t bit; }; struct cline { volatile uint32_t *en, *rst; uint32_t bit; };
struct cline lookup_clock_line(uint32_t periph_base); struct cline lookup_clock_line(uint32_t periph_base);

View File

@ -134,39 +134,12 @@ hsi14_setup(void)
* Bootloader * 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 // Handle reboot requests
void void
bootloader_request(void) bootloader_request(void)
{ {
try_request_canboot(); try_request_canboot();
usb_reboot_for_dfu_bootloader(); dfu_reboot();
} }
@ -193,7 +166,7 @@ enable_ram_vectortable(void)
void void
armcm_main(void) armcm_main(void)
{ {
check_usb_dfu_bootloader(); dfu_reboot_check();
SystemInit(); SystemInit();
enable_pclock(SYSCFG_BASE); enable_pclock(SYSCFG_BASE);

View File

@ -204,30 +204,6 @@ usb_hid_bootloader(void)
NVIC_SystemReset(); 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 // Handle reboot requests
void void
bootloader_request(void) bootloader_request(void)
@ -235,7 +211,7 @@ bootloader_request(void)
try_request_canboot(); try_request_canboot();
if (CONFIG_STM32_FLASH_START_4000) if (CONFIG_STM32_FLASH_START_4000)
usb_hid_bootloader(); usb_hid_bootloader();
usb_reboot_for_dfu_bootloader(); dfu_reboot();
} }
@ -247,7 +223,7 @@ bootloader_request(void)
void void
armcm_main(void) armcm_main(void)
{ {
check_usb_dfu_bootloader(); dfu_reboot_check();
// Run SystemInit() and then restore VTOR // Run SystemInit() and then restore VTOR
SystemInit(); SystemInit();

View File

@ -128,36 +128,12 @@ clock_setup(void)
* Bootloader * 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 // Handle USB reboot requests
void void
bootloader_request(void) bootloader_request(void)
{ {
try_request_canboot(); try_request_canboot();
usb_reboot_for_dfu_bootloader(); dfu_reboot();
} }
@ -185,7 +161,7 @@ armcm_main(void)
RCC->APBENR1 = 0x00000000; RCC->APBENR1 = 0x00000000;
RCC->APBENR2 = 0x00000000; RCC->APBENR2 = 0x00000000;
check_usb_dfu_bootloader(); dfu_reboot_check();
// Set flash latency, cache and prefetch; use reset value as base // Set flash latency, cache and prefetch; use reset value as base
uint32_t acr = 0x00040600; uint32_t acr = 0x00040600;

View File

@ -139,36 +139,11 @@ clock_setup(void)
* Bootloader * 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 // Handle USB reboot requests
void void
bootloader_request(void) bootloader_request(void)
{ {
usb_reboot_for_dfu_bootloader(); dfu_reboot();
} }
@ -180,7 +155,7 @@ bootloader_request(void)
void void
armcm_main(void) armcm_main(void)
{ {
check_usb_dfu_bootloader(); dfu_reboot_check();
// Run SystemInit() and then restore VTOR // Run SystemInit() and then restore VTOR
SystemInit(); SystemInit();

View File

@ -208,38 +208,12 @@ clock_setup(void)
* Bootloader * 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 // Handle reboot requests
void void
bootloader_request(void) bootloader_request(void)
{ {
try_request_canboot(); try_request_canboot();
usb_reboot_for_dfu_bootloader(); dfu_reboot();
} }
@ -259,7 +233,7 @@ armcm_main(void)
RCC->D3CCIPR = 0x00000000; RCC->D3CCIPR = 0x00000000;
SCB->VTOR = (uint32_t)VectorTable; SCB->VTOR = (uint32_t)VectorTable;
check_usb_dfu_bootloader(); dfu_reboot_check();
clock_setup(); clock_setup();

View File

@ -139,36 +139,11 @@ clock_setup(void)
* Bootloader * 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 // Handle USB reboot requests
void void
bootloader_request(void) bootloader_request(void)
{ {
usb_reboot_for_dfu_bootloader(); dfu_reboot();
} }
@ -180,7 +155,7 @@ bootloader_request(void)
void void
armcm_main(void) armcm_main(void)
{ {
check_usb_dfu_bootloader(); dfu_reboot_check();
// Run SystemInit() and then restore VTOR // Run SystemInit() and then restore VTOR
SystemInit(); SystemInit();