diff --git a/src/command.h b/src/command.h index 0ff9960..c2083e3 100644 --- a/src/command.h +++ b/src/command.h @@ -2,6 +2,7 @@ #define __COMMAND_H #include // va_list +#include #include // uint32_t #include "ctr.h" // DECL_CTR diff --git a/src/stm32/Kconfig b/src/stm32/Kconfig index 9308386..b85f5e2 100644 --- a/src/stm32/Kconfig +++ b/src/stm32/Kconfig @@ -9,7 +9,7 @@ config STM32_SELECT select HAVE_GPIO_ADC select HAVE_GPIO_I2C if !(MACH_STM32F031 || MACH_STM32H7) select HAVE_GPIO_SPI if !MACH_STM32F031 - select HAVE_GPIO_HARD_PWM if MACH_STM32F1 || MACH_STM32F4 || MACH_STM32H7 + select HAVE_GPIO_HARD_PWM if MACH_STM32F1 || MACH_STM32F4 || MACH_STM32G0 || MACH_STM32H7 select HAVE_GPIO_BITBANGING if !MACH_STM32F031 select HAVE_STRICT_TIMING select HAVE_CHIPID @@ -64,15 +64,29 @@ choice bool "STM32F072" select MACH_STM32F0 select MACH_STM32F0x2 + config MACH_STM32G0B0 + bool "STM32G0B0" + select MACH_STM32G0 + select MACH_STM32G0Bx config MACH_STM32G0B1 bool "STM32G0B1" select MACH_STM32G0 + select MACH_STM32G0Bx + config MACH_STM32G431 + bool "STM32G431" if 0 + select MACH_STM32G4 + config MACH_STM32H723 + bool "STM32H723" if 0 + select MACH_STM32H7 config MACH_STM32H743 bool "STM32H743" if 0 select MACH_STM32H7 config MACH_STM32H750 bool "STM32H750" if 0 select MACH_STM32H7 + config MACH_STM32L412 + bool "STM32L412" if 0 + select MACH_STM32L4 endchoice config MACH_STM32F103x6 @@ -89,15 +103,21 @@ config MACH_STM32F4 bool config MACH_STM32G0 bool +config MACH_STM32G0Bx + bool +config MACH_STM32G4 + bool config MACH_STM32H7 bool config MACH_STM32F0x2 # F042, F072 series bool config MACH_STM32F4x5 # F405, F407, F429 series bool +config MACH_STM32L4 + bool config HAVE_STM32_USBFS bool - default y if MACH_STM32F0x2 || MACH_STM32G0 + default y if MACH_STM32F0x2 || MACH_STM32G0Bx || MACH_STM32L4 || MACH_STM32G4 default y if (MACH_STM32F103 || MACH_STM32F070) && !STM32_CLOCK_REF_INTERNAL config HAVE_STM32_USBOTG bool @@ -107,7 +127,9 @@ config HAVE_STM32_CANBUS default y if MACH_STM32F1 || MACH_STM32F2 || MACH_STM32F4x5 || MACH_STM32F446 || MACH_STM32F0x2 config HAVE_STM32_FDCANBUS bool - default y if MACH_STM32G0 + default y if MACH_STM32G0B1 || MACH_STM32H7 || MACH_STM32G4 +config HAVE_STM32_USBCANBUS + bool config MCU string @@ -122,9 +144,13 @@ config MCU default "stm32f407xx" if MACH_STM32F407 default "stm32f429xx" if MACH_STM32F429 default "stm32f446xx" if MACH_STM32F446 + default "stm32g0b0xx" if MACH_STM32G0B0 default "stm32g0b1xx" if MACH_STM32G0B1 + default "stm32g431xx" if MACH_STM32G431 + default "stm32h723xx" if MACH_STM32H723 default "stm32h743xx" if MACH_STM32H743 default "stm32h750xx" if MACH_STM32H750 + default "stm32l412xx" if MACH_STM32L412 config CLOCK_FREQ int @@ -136,31 +162,28 @@ config CLOCK_FREQ default 168000000 if MACH_STM32F4x5 default 180000000 if MACH_STM32F446 default 64000000 if MACH_STM32G0 + default 150000000 if MACH_STM32G431 default 400000000 if MACH_STM32H7 # 400Mhz is max Klipper currently supports - -config FLASH_START - hex - default 0x8000000 - -config FLASH_BOOT_ADDRESS - hex - default 0x8000000 + default 80000000 if MACH_STM32L412 config FLASH_SIZE hex default 0x4000 if MACH_STM32F031 default 0x8000 if MACH_STM32F042 default 0x20000 if MACH_STM32F070 || MACH_STM32F072 - default 0x10000 if MACH_STM32F103 # Flash size of stm32f103x8 (64KiB) - default 0x40000 if MACH_STM32F2 || MACH_STM32F401 + default 0x10000 if MACH_STM32F103 || MACH_STM32L412 # Flash size of stm32f103x8 (64KiB) + default 0x40000 if MACH_STM32F2 || MACH_STM32F401 || MACH_STM32H723 default 0x80000 if MACH_STM32F4x5 || MACH_STM32F446 - default 0x20000 if MACH_STM32G0B1 + default 0x20000 if MACH_STM32G0 || MACH_STM32G431 default 0x20000 if MACH_STM32H750 default 0x200000 if MACH_STM32H743 +config FLASH_BOOT_ADDRESS + hex + default 0x8000000 + config RAM_START hex - default 0x24000000 if MACH_STM32H743 default 0x20000000 config RAM_SIZE @@ -170,12 +193,13 @@ config RAM_SIZE default 0x4000 if MACH_STM32F070 || MACH_STM32F072 default 0x2800 if MACH_STM32F103x6 default 0x5000 if MACH_STM32F103 && !MACH_STM32F103x6 # Ram size of stm32f103x8 + default 0x8000 if MACH_STM32G431 + default 0xa000 if MACH_STM32L412 default 0x20000 if MACH_STM32F207 default 0x10000 if MACH_STM32F401 default 0x20000 if MACH_STM32F4x5 || MACH_STM32F446 - default 0x24000 if MACH_STM32G0B1 - default 0x20000 if MACH_STM32H750 - default 0x80000 if MACH_STM32H743 + default 0x24000 if MACH_STM32G0Bx + default 0x20000 if MACH_STM32H7 config STACK_SIZE int @@ -191,6 +215,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 @@ -224,7 +257,7 @@ choice config STM32_FLASH_START_4000 bool "16KiB bootloader (HID Bootloader)" if MACH_STM32F207 || MACH_STM32F401 || MACH_STM32F4x5 || MACH_STM32F103 || MACH_STM32F072 config STM32_FLASH_START_20000 - bool "128KiB bootloader (SKR SE BX v2.0)" if MACH_STM32H743 + bool "128KiB bootloader (SKR SE BX v2.0)" if MACH_STM32H743 || MACH_STM32H723 endchoice config FLASH_APPLICATION_ADDRESS hex @@ -260,6 +293,8 @@ choice bool "12 MHz crystal" config STM32_CLOCK_REF_16M bool "16 MHz crystal" + config STM32_CLOCK_REF_20M + bool "20 MHz crystal" config STM32_CLOCK_REF_25M bool "25 MHz crystal" config STM32_CLOCK_REF_INTERNAL @@ -268,6 +303,7 @@ endchoice config CLOCK_REF_FREQ int default 25000000 if STM32_CLOCK_REF_25M + default 20000000 if STM32_CLOCK_REF_20M default 16000000 if STM32_CLOCK_REF_16M default 12000000 if STM32_CLOCK_REF_12M default 1 if STM32_CLOCK_REF_INTERNAL @@ -297,7 +333,7 @@ choice select USBSERIAL config STM32_USB_PB14_PB15 bool "USB (on PB14/PB15)" - depends on MACH_STM32H7 + depends on MACH_STM32H743 || MACH_STM32H750 select USBSERIAL config STM32_SERIAL_USART1 bool "Serial (on USART1 PA10/PA9)" @@ -309,7 +345,10 @@ choice bool "Serial (on USART2 PA3/PA2)" if LOW_LEVEL_OPTIONS select SERIAL config STM32_SERIAL_USART2_ALT_PA15_PA14 - bool "Serial (on USART2 PA15/PA14)" if LOW_LEVEL_OPTIONS && MACH_STM32F0 + bool "Serial (on USART2 PA15/PA14)" if LOW_LEVEL_OPTIONS && (MACH_STM32F0 || MACH_STM32G4) + select SERIAL + config STM32_SERIAL_USART2_ALT_PB4_PB3 + bool "Serial (on USART2 PB4/PB3)" if LOW_LEVEL_OPTIONS && MACH_STM32G4 select SERIAL config STM32_SERIAL_USART2_ALT_PD6_PD5 bool "Serial (on USART2 PD6/PD5)" if LOW_LEVEL_OPTIONS && !MACH_STM32F0 @@ -334,36 +373,109 @@ choice bool "CAN bus (on PA9/PA10)" if LOW_LEVEL_OPTIONS depends on HAVE_STM32_CANBUS && MACH_STM32F042 select CANSERIAL - config STM32_CANBUS_PB8_PB9 + config STM32_CANBUS_PA11_PB9 + bool "CAN bus (on PA11/PB9)" + depends on HAVE_STM32_CANBUS || HAVE_STM32_FDCANBUS + select CANSERIAL + config STM32_MMENU_CANBUS_PB8_PB9 bool "CAN bus (on PB8/PB9)" if LOW_LEVEL_OPTIONS depends on HAVE_STM32_CANBUS || HAVE_STM32_FDCANBUS select CANSERIAL - config STM32_CANBUS_PI9_PH13 + config STM32_MMENU_CANBUS_PI9_PH13 bool "CAN bus (on PI9/PH13)" if LOW_LEVEL_OPTIONS depends on HAVE_STM32_CANBUS && MACH_STM32F4 select CANSERIAL - config STM32_CANBUS_PB5_PB6 + config STM32_MMENU_CANBUS_PB5_PB6 bool "CAN bus (on PB5/PB6)" if LOW_LEVEL_OPTIONS depends on HAVE_STM32_CANBUS && MACH_STM32F4 select CANSERIAL - config STM32_CANBUS_PB12_PB13 + config STM32_MMENU_CANBUS_PB12_PB13 bool "CAN bus (on PB12/PB13)" if LOW_LEVEL_OPTIONS depends on HAVE_STM32_CANBUS && MACH_STM32F4 select CANSERIAL - config STM32_CANBUS_PD0_PD1 + config STM32_MMENU_CANBUS_PD0_PD1 bool "CAN bus (on PD0/PD1)" if LOW_LEVEL_OPTIONS - depends on HAVE_STM32_CANBUS + depends on HAVE_STM32_CANBUS || HAVE_STM32_FDCANBUS select CANSERIAL - config STM32_CANBUS_PB0_PB1 + config STM32_MMENU_CANBUS_PB0_PB1 bool "CAN bus (on PB0/PB1)" depends on HAVE_STM32_FDCANBUS select CANSERIAL + config STM32_MMENU_CANBUS_PD12_PD13 + bool "CAN bus (on PD12/PD13)" + depends on HAVE_STM32_FDCANBUS + select CANSERIAL + config STM32_MMENU_CANBUS_PC2_PC3 + bool "CAN bus (on PC2/PC3)" + depends on HAVE_STM32_FDCANBUS + select CANSERIAL + config STM32_USBCANBUS_PA11_PA12 + bool "USB to CAN bus bridge (USB on PA11/PA12)" + depends on HAVE_STM32_USBCANBUS + select USBCANBUS endchoice +choice + prompt "CAN bus interface" if USBCANBUS + config STM32_CMENU_CANBUS_PB8_PB9 + bool "CAN bus (on PB8/PB9)" + config STM32_CMENU_CANBUS_PI9_PH13 + bool "CAN bus (on PI9/PH13)" + depends on HAVE_STM32_CANBUS && MACH_STM32F4 + config STM32_CMENU_CANBUS_PB5_PB6 + bool "CAN bus (on PB5/PB6)" + depends on HAVE_STM32_CANBUS && MACH_STM32F4 + config STM32_CMENU_CANBUS_PB12_PB13 + bool "CAN bus (on PB12/PB13)" + depends on HAVE_STM32_CANBUS && MACH_STM32F4 + config STM32_CMENU_CANBUS_PD0_PD1 + bool "CAN bus (on PD0/PD1)" + depends on HAVE_STM32_CANBUS || HAVE_STM32_FDCANBUS + config STM32_CMENU_CANBUS_PB0_PB1 + bool "CAN bus (on PB0/PB1)" + depends on HAVE_STM32_FDCANBUS + config STM32_CMENU_CANBUS_PD12_PD13 + bool "CAN bus (on PD12/PD13)" + depends on HAVE_STM32_FDCANBUS + config STM32_CMENU_CANBUS_PC2_PC3 + bool "CAN bus (on PC2/PC3)" + depends on HAVE_STM32_FDCANBUS +endchoice + + +config STM32_CANBUS_PB8_PB9 + bool + default y if STM32_MMENU_CANBUS_PB8_PB9 || STM32_CMENU_CANBUS_PB8_PB9 +config STM32_CANBUS_PI9_PH13 + bool + default y if STM32_MMENU_CANBUS_PI9_PH13 || STM32_CMENU_CANBUS_PI9_PH13 +config STM32_CANBUS_PB5_PB6 + bool + default y if STM32_MMENU_CANBUS_PB5_PB6 || STM32_CMENU_CANBUS_PB5_PB6 +config STM32_CANBUS_PB12_PB13 + bool + default y if STM32_MMENU_CANBUS_PB12_PB13 || STM32_CMENU_CANBUS_PB12_PB13 +config STM32_CANBUS_PD0_PD1 + bool + default y if STM32_MMENU_CANBUS_PD0_PD1 || STM32_CMENU_CANBUS_PD0_PD1 +config STM32_CANBUS_PB0_PB1 + bool + default y if STM32_MMENU_CANBUS_PB0_PB1 || STM32_CMENU_CANBUS_PB0_PB1 +config STM32_CANBUS_PD12_PD13 + bool + default y if STM32_MMENU_CANBUS_PD12_PD13 || STM32_CMENU_CANBUS_PD12_PD13 +config STM32_CANBUS_PC2_PC3 + bool + default y if STM32_MMENU_CANBUS_PC2_PC3 || STM32_CMENU_CANBUS_PC2_PC3 + ###################################################################### # Flash settings ###################################################################### +config FLASH_START + hex + default 0x8000000 + choice prompt "Application start offset" config STM32_APP_START_8000 diff --git a/src/stm32/Makefile b/src/stm32/Makefile index 87422d5..cbd7af4 100644 --- a/src/stm32/Makefile +++ b/src/stm32/Makefile @@ -25,7 +25,7 @@ CFLAGS_canboot.elf += -T $(OUT)src/generic/armcm_link.ld $(OUT)canboot.elf: $(OUT)src/generic/armcm_link.ld # Add source files -mcu-y = stm32/gpio.c stm32/flash.c stm32/clockline.c +mcu-y = stm32/gpio.c stm32/flash.c stm32/clockline.c stm32/dfu_reboot.c mcu-y += generic/armcm_irq.c generic/crc16_ccitt.c mcu-$(CONFIG_MACH_STM32F0) += ../lib/stm32f0/system_stm32f0xx.c mcu-$(CONFIG_MACH_STM32F0) += stm32/stm32f0.c stm32/stm32f0_timer.c diff --git a/src/stm32/dfu_reboot.c b/src/stm32/dfu_reboot.c new file mode 100644 index 0000000..dc92e1d --- /dev/null +++ b/src/stm32/dfu_reboot.c @@ -0,0 +1,19 @@ +// Reboot into stm32 ROM dfu bootloader +// +// Copyright (C) 2019-2022 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU GPLv3 license. + +#include "internal.h" // NVIC_SystemReset + +// Flag that bootloader is desired and reboot +void +dfu_reboot(void) +{ +} + +// Check if rebooting into system DFU Bootloader +void +dfu_reboot_check(void) +{ +} diff --git a/src/stm32/internal.h b/src/stm32/internal.h index f0535ab..b5971ed 100644 --- a/src/stm32/internal.h +++ b/src/stm32/internal.h @@ -14,8 +14,12 @@ #include "stm32f4xx.h" #elif CONFIG_MACH_STM32G0 #include "stm32g0xx.h" +#elif CONFIG_MACH_STM32G4 +#include "stm32g4xx.h" #elif CONFIG_MACH_STM32H7 #include "stm32h7xx.h" +#elif CONFIG_MACH_STM32L4 +#include "stm32l4xx.h" #endif // gpio.c @@ -36,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); diff --git a/src/stm32/serial.c b/src/stm32/serial.c index 5806eaa..19aa048 100644 --- a/src/stm32/serial.c +++ b/src/stm32/serial.c @@ -57,8 +57,11 @@ void USARTx_IRQHandler(void) { uint32_t sr = USARTx->SR; - if (sr & (USART_SR_RXNE | USART_SR_ORE)) + if (sr & (USART_SR_RXNE | USART_SR_ORE)) { + // The ORE flag is automatically cleared by reading SR, followed + // by reading DR. serial_rx_byte(USARTx->DR); + } if (sr & USART_SR_TXE && USARTx->CR1 & USART_CR1_TXEIE) { uint8_t data; int ret = serial_get_tx_byte(&data); diff --git a/src/stm32/stm32f0.c b/src/stm32/stm32f0.c index d40db7f..46e22f7 100644 --- a/src/stm32/stm32f0.c +++ b/src/stm32/stm32f0.c @@ -6,7 +6,9 @@ #include "autoconf.h" // CONFIG_CLOCK_REF_FREQ #include "board/armcm_boot.h" // armcm_main +#include "board/armcm_reset.h" // try_request_canboot #include "board/irq.h" // irq_disable +#include "board/misc.h" // bootloader_request #include "command.h" // DECL_CONSTANT_STR #include "deployer.h" // deployer_is_active #include "internal.h" // enable_pclock @@ -85,7 +87,7 @@ pll_setup(void) // Setup CFGR3 register uint32_t cfgr3 = RCC_CFGR3_I2C1SW; -#if CONFIG_USBSERIAL +#if CONFIG_USB // Select PLL as source for USB clock cfgr3 |= RCC_CFGR3_USBSW; #endif @@ -108,7 +110,7 @@ hsi48_setup(void) ; // Enable USB clock recovery - if (CONFIG_USBSERIAL) { + if (CONFIG_USB) { enable_pclock(CRS_BASE); CRS->CR |= CRS_CR_AUTOTRIMEN | CRS_CR_CEN; } @@ -128,6 +130,20 @@ hsi14_setup(void) ; } + +/**************************************************************** + * Bootloader + ****************************************************************/ + +// Handle reboot requests +void +bootloader_request(void) +{ + try_request_canboot(); + dfu_reboot(); +} + + /**************************************************************** * Startup ****************************************************************/ @@ -151,6 +167,7 @@ enable_ram_vectortable(void) void armcm_main(void) { + dfu_reboot_check(); SystemInit(); enable_pclock(SYSCFG_BASE); @@ -161,8 +178,7 @@ armcm_main(void) FLASH->ACR = (1 << FLASH_ACR_LATENCY_Pos) | FLASH_ACR_PRFTBE; // Configure main clock - if (CONFIG_MACH_STM32F0x2 && CONFIG_STM32_CLOCK_REF_INTERNAL - && CONFIG_USBSERIAL) + if (CONFIG_MACH_STM32F0x2 && CONFIG_STM32_CLOCK_REF_INTERNAL && CONFIG_USB) hsi48_setup(); else pll_setup(); diff --git a/src/stm32/stm32f0_serial.c b/src/stm32/stm32f0_serial.c index c214ed0..4f6495f 100644 --- a/src/stm32/stm32f0_serial.c +++ b/src/stm32/stm32f0_serial.c @@ -16,30 +16,68 @@ DECL_CONSTANT_STR("RESERVE_PINS_serial", "PA10,PA9"); #define GPIO_Rx GPIO('A', 10) #define GPIO_Tx GPIO('A', 9) - #define USARTx_FUNCTION GPIO_FUNCTION(1) + #define USARTx_FUNCTION GPIO_FUNCTION( \ + (CONFIG_MACH_STM32H7 | CONFIG_MACH_STM32G4) ? 7 : 1) #define USARTx USART1 #define USARTx_IRQn USART1_IRQn #elif CONFIG_STM32_SERIAL_USART1_ALT_PB7_PB6 DECL_CONSTANT_STR("RESERVE_PINS_serial", "PB7,PB6"); #define GPIO_Rx GPIO('B', 7) #define GPIO_Tx GPIO('B', 6) - #define USARTx_FUNCTION GPIO_FUNCTION(0) + #define USARTx_FUNCTION GPIO_FUNCTION( \ + (CONFIG_MACH_STM32H7 | CONFIG_MACH_STM32G4) ? 7 : 0) #define USARTx USART1 #define USARTx_IRQn USART1_IRQn #elif CONFIG_STM32_SERIAL_USART2 DECL_CONSTANT_STR("RESERVE_PINS_serial", "PA3,PA2"); #define GPIO_Rx GPIO('A', 3) #define GPIO_Tx GPIO('A', 2) - #define USARTx_FUNCTION GPIO_FUNCTION(1) + #define USARTx_FUNCTION GPIO_FUNCTION( \ + (CONFIG_MACH_STM32H7 | CONFIG_MACH_STM32G4) ? 7 : 1) #define USARTx USART2 #define USARTx_IRQn USART2_IRQn #elif CONFIG_STM32_SERIAL_USART2_ALT_PA15_PA14 DECL_CONSTANT_STR("RESERVE_PINS_serial", "PA15,PA14"); #define GPIO_Rx GPIO('A', 15) #define GPIO_Tx GPIO('A', 14) - #define USARTx_FUNCTION GPIO_FUNCTION(1) + #define USARTx_FUNCTION GPIO_FUNCTION(CONFIG_MACH_STM32G4 ? 7 : 1) #define USARTx USART2 #define USARTx_IRQn USART2_IRQn +#elif CONFIG_STM32_SERIAL_USART2_ALT_PB4_PB3 + DECL_CONSTANT_STR("RESERVE_PINS_serial", "PB4,PB3"); + #define GPIO_Rx GPIO('B', 4) + #define GPIO_Tx GPIO('B', 3) + #define USARTx_FUNCTION GPIO_FUNCTION(7) + #define USARTx USART2 + #define USARTx_IRQn USART2_IRQn +#elif CONFIG_STM32_SERIAL_USART2_ALT_PD6_PD5 + DECL_CONSTANT_STR("RESERVE_PINS_serial", "PD6,PD5"); + #define GPIO_Rx GPIO('D', 6) + #define GPIO_Tx GPIO('D', 5) + #define USARTx_FUNCTION GPIO_FUNCTION(7) + #define USARTx USART2 + #define USARTx_IRQn USART2_IRQn +#elif CONFIG_STM32_SERIAL_USART3 + DECL_CONSTANT_STR("RESERVE_PINS_serial", "PB11,PB10"); + #define GPIO_Rx GPIO('B', 11) + #define GPIO_Tx GPIO('B', 10) + #define USARTx_FUNCTION GPIO_FUNCTION(7) + #define USARTx USART3 + #define USARTx_IRQn USART3_IRQn +#elif CONFIG_STM32_SERIAL_USART3_ALT_PD9_PD8 + DECL_CONSTANT_STR("RESERVE_PINS_serial", "PD9,PD8"); + #define GPIO_Rx GPIO('D', 9) + #define GPIO_Tx GPIO('D', 8) + #define USARTx_FUNCTION GPIO_FUNCTION(7) + #define USARTx USART3 + #define USARTx_IRQn USART3_IRQn +#elif CONFIG_STM32_SERIAL_UART4 + DECL_CONSTANT_STR("RESERVE_PINS_serial", "PA1,PA0"); + #define GPIO_Rx GPIO('A', 1) + #define GPIO_Tx GPIO('A', 0) + #define USARTx_FUNCTION GPIO_FUNCTION(8) + #define USARTx UART4 + #define USARTx_IRQn UART4_IRQn #endif #if CONFIG_MACH_STM32F031 @@ -49,14 +87,23 @@ #endif #if CONFIG_MACH_STM32G0 - // The stm32g0 has slightly different register names - #define USART2_IRQn USART2_LPUART2_IRQn + // Some of the stm32g0 MCUs have slightly different register names + #if CONFIG_MACH_STM32G0B1 + #define USART2_IRQn USART2_LPUART2_IRQn + #endif #define USART_CR1_RXNEIE USART_CR1_RXNEIE_RXFNEIE #define USART_CR1_TXEIE USART_CR1_TXEIE_TXFNFIE #define USART_ISR_RXNE USART_ISR_RXNE_RXFNE #define USART_ISR_TXE USART_ISR_TXE_TXFNF #define USART_BRR_DIV_MANTISSA_Pos 4 #define USART_BRR_DIV_FRACTION_Pos 0 +#elif CONFIG_MACH_STM32G4 + #define USART_BRR_DIV_MANTISSA_Pos 4 + #define USART_BRR_DIV_FRACTION_Pos 0 +#elif CONFIG_MACH_STM32H7 + // The stm32h7 has slightly different register names + #define USART_ISR_RXNE USART_ISR_RXNE_RXFNE + #define USART_ISR_TXE USART_ISR_TXE_TXFNF #endif #define CR1_FLAGS (USART_CR1_UE | USART_CR1_RE | USART_CR1_TE \ @@ -66,7 +113,7 @@ void USARTx_IRQHandler(void) { uint32_t sr = USARTx->ISR; - if (sr & (USART_ISR_RXNE | USART_ISR_ORE)) + if (sr & USART_ISR_RXNE) serial_rx_byte(USARTx->RDR); if (sr & USART_ISR_TXE && USARTx->CR1 & USART_CR1_TXEIE) { uint8_t data; @@ -93,6 +140,7 @@ serial_init(void) uint32_t div = DIV_ROUND_CLOSEST(pclk, CONFIG_SERIAL_BAUD); USARTx->BRR = (((div / 16) << USART_BRR_DIV_MANTISSA_Pos) | ((div % 16) << USART_BRR_DIV_FRACTION_Pos)); + USARTx->CR3 = USART_CR3_OVRDIS; // disable the ORE ISR USARTx->CR1 = CR1_FLAGS; armcm_enable_irq(USARTx_IRQHandler, USARTx_IRQn, 0); diff --git a/src/stm32/stm32f0_timer.c b/src/stm32/stm32f0_timer.c index afbd84c..83f2e4a 100644 --- a/src/stm32/stm32f0_timer.c +++ b/src/stm32/stm32f0_timer.c @@ -5,6 +5,7 @@ // This file may be distributed under the terms of the GNU GPLv3 license. #include "board/armcm_boot.h" // armcm_enable_irq +#include "board/armcm_timer.h" // udelay #include "board/internal.h" // TIM3 #include "board/io.h" // readl #include "board/irq.h" // irq_disable @@ -17,14 +18,19 @@ ****************************************************************/ // Use 32bit TIM2 timer if available (otherwise use 16bit TIM3 timer) -#ifdef TIM2 -#define TIMx TIM2 -#define TIMx_IRQn TIM2_IRQn -#define HAVE_TIMER_32BIT 1 -#else -#define TIMx TIM3 -#define TIMx_IRQn TIM3_IRQn -#define HAVE_TIMER_32BIT 0 +#if defined(TIM2) + #define TIMx TIM2 + #define TIMx_IRQn TIM2_IRQn + #define HAVE_TIMER_32BIT 1 +#elif defined(TIM3) + #define TIMx TIM3 + #define TIMx_IRQn TIM3_IRQn + #define HAVE_TIMER_32BIT 0 +#endif + +// Some chips have slightly different register names +#if CONFIG_MACH_STM32G0B0 + #define TIM3_IRQn TIM3_TIM4_IRQn #endif static inline uint32_t @@ -40,12 +46,13 @@ timer_set(uint32_t next) TIMx->SR = 0; } + /**************************************************************** * 16bit hardware timer to 32bit conversion ****************************************************************/ // High bits of timer (top 17 bits) -static uint32_t timer_high = 0; +static uint32_t timer_high; // Return the current time (in absolute clock ticks). uint32_t __always_inline @@ -60,6 +67,7 @@ timer_read_time(void) return (th ^ cur) + (th & 0xffff); } + /**************************************************************** * Setup and irqs ****************************************************************/ diff --git a/src/stm32/stm32f1.c b/src/stm32/stm32f1.c index f3ad24b..9d3c3b9 100644 --- a/src/stm32/stm32f1.c +++ b/src/stm32/stm32f1.c @@ -1,13 +1,14 @@ // Code to setup clocks and gpio on stm32f1 // -// Copyright (C) 2019-2021 Kevin O'Connor +// Copyright (C) 2019-2022 Kevin O'Connor // // This file may be distributed under the terms of the GNU GPLv3 license. #include "autoconf.h" // CONFIG_CLOCK_REF_FREQ #include "board/armcm_boot.h" // VectorTable +#include "board/armcm_reset.h" // try_request_canboot #include "board/irq.h" // irq_disable -#include "board/usb_cdc.h" // usb_request_bootloader +#include "board/misc.h" // bootloader_request #include "internal.h" // enable_pclock #include "sched.h" // sched_main @@ -211,6 +212,46 @@ gpio_peripheral(uint32_t gpio, uint32_t mode, int pullup) } +/**************************************************************** + * Bootloader + ****************************************************************/ + +// Reboot into USB "HID" bootloader +static void +usb_hid_bootloader(void) +{ + irq_disable(); + RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN; + PWR->CR |= PWR_CR_DBP; + BKP->DR4 = 0x424C; // HID Bootloader magic key + PWR->CR &=~ PWR_CR_DBP; + NVIC_SystemReset(); +} + +// Reboot into USB "stm32duino" bootloader +static void +usb_stm32duino_bootloader(void) +{ + irq_disable(); + RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN; + PWR->CR |= PWR_CR_DBP; + BKP->DR10 = 0x01; // stm32duino bootloader magic key + PWR->CR &=~ PWR_CR_DBP; + NVIC_SystemReset(); +} + +// Handle reboot requests +void +bootloader_request(void) +{ + try_request_canboot(); + if (CONFIG_STM32_FLASH_START_800) + usb_hid_bootloader(); + else if (CONFIG_STM32_FLASH_START_2000) + usb_stm32duino_bootloader(); +} + + /**************************************************************** * Startup ****************************************************************/ diff --git a/src/stm32/stm32f4.c b/src/stm32/stm32f4.c index c741f13..a2060d7 100644 --- a/src/stm32/stm32f4.c +++ b/src/stm32/stm32f4.c @@ -6,8 +6,9 @@ #include "autoconf.h" // CONFIG_CLOCK_REF_FREQ #include "board/armcm_boot.h" // VectorTable +#include "board/armcm_reset.h" // try_request_canboot #include "board/irq.h" // irq_disable -#include "board/usb_cdc.h" // usb_request_bootloader +#include "board/misc.h" // bootloader_request #include "command.h" // DECL_CONSTANT_STR #include "internal.h" // enable_pclock #include "sched.h" // sched_main @@ -138,7 +139,7 @@ enable_clock_stm32f446(void) ; // Enable 48Mhz USB clock - if (CONFIG_USBSERIAL) { + if (CONFIG_USB) { uint32_t ref = (CONFIG_STM32_CLOCK_REF_INTERNAL ? 16000000 : CONFIG_CLOCK_REF_FREQ); uint32_t plls_base = 2000000, plls_freq = FREQ_USB * 4; @@ -185,6 +186,35 @@ clock_setup(void) ; } + +/**************************************************************** + * Bootloader + ****************************************************************/ + +// Reboot into USB "HID" bootloader +static void +usb_hid_bootloader(void) +{ + irq_disable(); + RCC->APB1ENR |= RCC_APB1ENR_PWREN; + RCC->APB1ENR; + PWR->CR |= PWR_CR_DBP; + RTC->BKP4R = 0x424C; // HID Bootloader magic key + PWR->CR &= ~PWR_CR_DBP; + NVIC_SystemReset(); +} + +// Handle reboot requests +void +bootloader_request(void) +{ + try_request_canboot(); + if (CONFIG_STM32_FLASH_START_4000) + usb_hid_bootloader(); + dfu_reboot(); +} + + /**************************************************************** * Startup ****************************************************************/ @@ -193,6 +223,8 @@ clock_setup(void) void armcm_main(void) { + dfu_reboot_check(); + // Run SystemInit() and then restore VTOR SystemInit(); SCB->VTOR = (uint32_t)VectorTable; diff --git a/src/stm32/stm32g0.c b/src/stm32/stm32g0.c index 967eb2a..41f7f6f 100644 --- a/src/stm32/stm32g0.c +++ b/src/stm32/stm32g0.c @@ -6,7 +6,9 @@ #include "autoconf.h" // CONFIG_CLOCK_REF_FREQ #include "board/armcm_boot.h" // armcm_main +#include "board/armcm_reset.h" // try_request_canboot #include "board/irq.h" // irq_disable +#include "board/misc.h" // bootloader_request #include "command.h" // DECL_CONSTANT_STR #include "internal.h" // enable_pclock #include "sched.h" // sched_main @@ -30,20 +32,41 @@ lookup_clock_line(uint32_t periph_base) uint32_t bit = 1 << ((periph_base - AHBPERIPH_BASE) / 0x400); return (struct cline){.en=&RCC->AHBENR, .rst=&RCC->AHBRSTR, .bit=bit}; } +#if defined(FDCAN1_BASE) || defined(FDCAN2_BASE) if ((periph_base == FDCAN1_BASE) || (periph_base == FDCAN2_BASE)) return (struct cline){.en=&RCC->APBENR1,.rst=&RCC->APBRSTR1,.bit=1<<12}; +#endif if (periph_base == USB_BASE) return (struct cline){.en=&RCC->APBENR1,.rst=&RCC->APBRSTR1,.bit=1<<13}; +#ifdef CRS_BASE if (periph_base == CRS_BASE) return (struct cline){.en=&RCC->APBENR1,.rst=&RCC->APBRSTR1,.bit=1<<16}; +#endif + if (periph_base == I2C3_BASE) + return (struct cline){.en=&RCC->APBENR1,.rst=&RCC->APBRSTR1,.bit=1<<23}; + if (periph_base == TIM1_BASE) + return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<11}; if (periph_base == SPI1_BASE) return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<12}; if (periph_base == USART1_BASE) return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<14}; + if (periph_base == TIM14_BASE) + return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<15}; + if (periph_base == TIM15_BASE) + return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<16}; + if (periph_base == TIM16_BASE) + return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<17}; + if (periph_base == TIM17_BASE) + return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<18}; if (periph_base == ADC1_BASE) return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<20}; - uint32_t bit = 1 << ((periph_base - APBPERIPH_BASE) / 0x400); - return (struct cline){.en=&RCC->APBENR1, .rst=&RCC->APBRSTR1, .bit=bit}; + if (periph_base >= APBPERIPH_BASE + && periph_base < APBPERIPH_BASE + 32*0x400) { + uint32_t bit = 1 << ((periph_base - APBPERIPH_BASE) / 0x400); + return (struct cline){.en=&RCC->APBENR1, .rst=&RCC->APBRSTR1, .bit=bit}; + } + // unknown peripheral. returning .bit=0 makes this a no-op + return (struct cline){.en=&RCC->APBENR1, .rst=NULL, .bit=0}; } // Return the frequency of the given peripheral clock @@ -101,6 +124,19 @@ clock_setup(void) } +/**************************************************************** + * Bootloader + ****************************************************************/ + +// Handle USB reboot requests +void +bootloader_request(void) +{ + try_request_canboot(); + dfu_reboot(); +} + + /**************************************************************** * Startup ****************************************************************/ @@ -125,8 +161,13 @@ armcm_main(void) RCC->APBENR1 = 0x00000000; RCC->APBENR2 = 0x00000000; - // Set flash latency - FLASH->ACR = (2<ACR = acr; // Configure main clock clock_setup();