From ba865a4ae0a2cc02ba4bcc6bc685ae3c74fd3b19 Mon Sep 17 00:00:00 2001 From: Konrad Kosmatka Date: Sun, 28 Jul 2024 01:42:19 +0200 Subject: [PATCH] Add runtime bootloader switch for STM32 --- src/Platform/Stm32/Bootloader.cpp | 78 +++++++++++++++++++++++++++++ src/Platform/Stm32/Bootloader.hpp | 27 ++++++++++ src/Platform/Stm32/UsbCdcStream.cpp | 46 +++++++++++++++-- 3 files changed, 148 insertions(+), 3 deletions(-) create mode 100644 src/Platform/Stm32/Bootloader.cpp create mode 100644 src/Platform/Stm32/Bootloader.hpp diff --git a/src/Platform/Stm32/Bootloader.cpp b/src/Platform/Stm32/Bootloader.cpp new file mode 100644 index 0000000..e742460 --- /dev/null +++ b/src/Platform/Stm32/Bootloader.cpp @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * + * FM-DX Tuner + * Copyright (C) 2024 Konrad Kosmatka + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifdef ARDUINO_ARCH_STM32 +#include +#include + +void +Platform_Stm32_Bootloader(void) +{ + tud_disconnect(); + + HAL_NVIC_DisableIRQ(PendSV_IRQn); + HAL_NVIC_DisableIRQ(USB_IRQn); + __HAL_RCC_USB_CLK_DISABLE(); + + HAL_NVIC_DisableIRQ(DMA1_Channel1_IRQn); + HAL_NVIC_DisableIRQ(DMA1_Channel2_3_IRQn); + HAL_NVIC_DisableIRQ(DMA1_Channel4_5_6_7_IRQn); + __HAL_RCC_DMA1_CLK_DISABLE(); + + HAL_NVIC_DisableIRQ(SPI1_IRQn); + __HAL_RCC_SPI1_CLK_DISABLE(); + + HAL_NVIC_DisableIRQ(I2C1_IRQn); + __HAL_RCC_I2C1_CLK_DISABLE(); + + HAL_NVIC_DisableIRQ(USART1_IRQn); + HAL_NVIC_DisableIRQ(USART2_IRQn); + __HAL_RCC_USART1_CLK_DISABLE(); + __HAL_RCC_USART2_CLK_DISABLE(); + + HAL_NVIC_DisableIRQ(EXTI0_1_IRQn); + HAL_NVIC_DisableIRQ(EXTI2_3_IRQn); + HAL_NVIC_DisableIRQ(EXTI4_15_IRQn); + __HAL_RCC_GPIOA_CLK_DISABLE(); + __HAL_RCC_GPIOB_CLK_DISABLE(); + __HAL_RCC_GPIOC_CLK_DISABLE(); + __HAL_RCC_GPIOD_CLK_DISABLE(); + __HAL_RCC_GPIOE_CLK_DISABLE(); + __HAL_RCC_GPIOF_CLK_DISABLE(); + + HAL_GPIO_DeInit(GPIOA, 0xFF); + HAL_GPIO_DeInit(GPIOB, 0xFF); + HAL_GPIO_DeInit(GPIOC, 0xFF); + HAL_GPIO_DeInit(GPIOD, 0xFF); + + HAL_RCC_DeInit(); + + SysTick->CTRL = 0; + SysTick->LOAD = 0; + SysTick->VAL = 0; + + __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); + + const uint32_t addr = 0x1FFFC800; + __set_MSP(*(uint32_t *)addr); + + /* Jump to System Memory */ + void (*bootloader)(void) = (void (*)(void)) (*((uint32_t *)(addr + 4))); + bootloader(); + while(1); +} + +#endif /* ARDUINO_ARCH_STM32 */ diff --git a/src/Platform/Stm32/Bootloader.hpp b/src/Platform/Stm32/Bootloader.hpp new file mode 100644 index 0000000..e4b467b --- /dev/null +++ b/src/Platform/Stm32/Bootloader.hpp @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * + * FM-DX Tuner + * Copyright (C) 2024 Konrad Kosmatka + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef FMDX_TUNER_PLATFORM_STM32_BOOTLOADER_H +#define FMDX_TUNER_PLATFORM_STM32_BOOTLOADER_H +#ifdef ARDUINO_ARCH_STM32 + +#include + +void Platform_Stm32_Bootloader(void); + +#endif /* ARDUINO_ARCH_STM32 */ + +#endif /* FMDX_TUNER_PLATFORM_STM32_BOOTLOADER_H */ diff --git a/src/Platform/Stm32/UsbCdcStream.cpp b/src/Platform/Stm32/UsbCdcStream.cpp index 1f12066..51790fa 100644 --- a/src/Platform/Stm32/UsbCdcStream.cpp +++ b/src/Platform/Stm32/UsbCdcStream.cpp @@ -16,8 +16,9 @@ #ifdef ARDUINO_ARCH_STM32 #include +#include #include "UsbCdcStream.hpp" -#include "tusb.h" +#include "Bootloader.hpp" #define BUFF_SIZE 64 uint8_t rxBuff[BUFF_SIZE]; @@ -101,8 +102,8 @@ UsbCdcStream::readTx(void) return value; } -extern "C" -void tud_cdc_rx_cb(uint8_t itf) +extern "C" void +tud_cdc_rx_cb(uint8_t itf) { uint8_t value; while (tud_cdc_n_available(itf)) @@ -116,6 +117,45 @@ void tud_cdc_rx_cb(uint8_t itf) } } +extern "C" void +tud_cdc_line_state_cb(uint8_t itf, + bool dtr, + bool rts) +{ + constexpr unsigned long timeout = 500; + constexpr uint8_t count = 5; + + static unsigned long timer = 0; + static uint8_t state = 0; + + if (state == 0) + { + if (dtr == 1 && + rts == 0) + { + state = 1; + timer = millis(); + } + return; + } + + if ((millis() - timer) > timeout) + { + state = 0; + return; + } + + if ((dtr == 1 && rts == 0 && state % 2 == 0) || + (dtr == 0 && rts == 1 && state % 2 == 1)) + { + state++; + } + + if (state == count) + { + Platform_Stm32_Bootloader(); + } +} UsbCdcStream UsbCdcSerial;