From a416b2793f30ffa14cf8272ad0e0c409439d48ad Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Mon, 28 Sep 2020 15:57:01 +0200 Subject: [PATCH] cpu/stm32: add basic support for stm32l5 --- cpu/stm32/Makefile.features | 2 +- cpu/stm32/cpu_common.c | 17 +- cpu/stm32/cpu_init.c | 3 +- cpu/stm32/include/cpu_conf.h | 11 +- cpu/stm32/include/cpu_conf_stm32_common.h | 7 +- cpu/stm32/include/periph/l5/periph_cpu.h | 42 +++ cpu/stm32/include/periph_cpu.h | 19 +- cpu/stm32/periph/Makefile | 2 +- cpu/stm32/periph/gpio_all.c | 15 +- cpu/stm32/periph/i2c_1.c | 2 +- cpu/stm32/periph/pm.c | 14 +- cpu/stm32/periph/uart.c | 21 +- cpu/stm32/stm32_info.mk | 2 + cpu/stm32/stm32_mem_lengths.mk | 4 + cpu/stm32/stmclk/Makefile | 2 + cpu/stm32/stmclk/stmclk_common.c | 5 +- cpu/stm32/stmclk/stmclk_l5.c | 348 ++++++++++++++++++++++ 17 files changed, 475 insertions(+), 41 deletions(-) create mode 100644 cpu/stm32/include/periph/l5/periph_cpu.h create mode 100644 cpu/stm32/stmclk/stmclk_l5.c diff --git a/cpu/stm32/Makefile.features b/cpu/stm32/Makefile.features index 2bed71dcef..9286fbc746 100644 --- a/cpu/stm32/Makefile.features +++ b/cpu/stm32/Makefile.features @@ -25,7 +25,7 @@ endif # Not all F4 and L0 parts implement a RNG. CPU_MODELS_WITHOUT_HWRNG = stm32f401% stm32f411% stm32f446% stm32l031% stm32l011% -ifneq (,$(filter $(CPU_FAM),f2 f4 f7 g4 l0 l4 wb)) +ifneq (,$(filter $(CPU_FAM),f2 f4 f7 g4 l0 l4 l5 wb)) ifeq (,$(filter $(CPU_MODELS_WITHOUT_HWRNG),$(CPU_MODEL))) FEATURES_PROVIDED += periph_hwrng endif diff --git a/cpu/stm32/cpu_common.c b/cpu/stm32/cpu_common.c index b236812449..8820f2cdf3 100644 --- a/cpu/stm32/cpu_common.c +++ b/cpu/stm32/cpu_common.c @@ -68,7 +68,7 @@ void periph_clk_en(bus_t bus, uint32_t mask) switch (bus) { case APB1: #if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined(CPU_FAM_STM32G4) + defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32L5) RCC->APB1ENR1 |= mask; #elif defined(CPU_FAM_STM32G0) RCC->APBENR1 |= mask; @@ -82,7 +82,7 @@ void periph_clk_en(bus_t bus, uint32_t mask) break; #endif #if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined(CPU_FAM_STM32G4) + defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32L5) case APB12: RCC->APB1ENR2 |= mask; break; @@ -105,7 +105,8 @@ void periph_clk_en(bus_t bus, uint32_t mask) break; #elif defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4) || \ defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32F7) || \ - defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) + defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) || \ + defined(CPU_FAM_STM32L5) case AHB1: RCC->AHB1ENR |= mask; break; @@ -132,7 +133,7 @@ void periph_clk_dis(bus_t bus, uint32_t mask) switch (bus) { case APB1: #if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined(CPU_FAM_STM32G4) + defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32L5) RCC->APB1ENR1 &= ~(mask); #elif defined(CPU_FAM_STM32G0) RCC->APBENR1 &= ~(mask); @@ -146,7 +147,7 @@ void periph_clk_dis(bus_t bus, uint32_t mask) break; #endif #if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined(CPU_FAM_STM32G4) + defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32L5) case APB12: RCC->APB1ENR2 &= ~(mask); break; @@ -169,7 +170,8 @@ void periph_clk_dis(bus_t bus, uint32_t mask) break; #elif defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4) || \ defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32F7) || \ - defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) + defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) || \ + defined(CPU_FAM_STM32L5) case AHB1: RCC->AHB1ENR &= ~(mask); break; @@ -194,7 +196,8 @@ void periph_clk_dis(bus_t bus, uint32_t mask) } } -#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32G4) +#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32G4) || \ + defined(CPU_FAM_STM32L5) void periph_lpclk_en(bus_t bus, uint32_t mask) { switch (bus) { diff --git a/cpu/stm32/cpu_init.c b/cpu/stm32/cpu_init.c index d8f82bcab3..8a70680eff 100644 --- a/cpu/stm32/cpu_init.c +++ b/cpu/stm32/cpu_init.c @@ -39,7 +39,8 @@ #include "periph/init.h" #include "board.h" -#if defined (CPU_FAM_STM32L4) || defined (CPU_FAM_STM32G4) +#if defined (CPU_FAM_STM32L4) || defined (CPU_FAM_STM32G4) || \ + defined(CPU_FAM_STM32L5) #define BIT_APB_PWREN RCC_APB1ENR1_PWREN #elif defined (CPU_FAM_STM32G0) #define BIT_APB_PWREN RCC_APBENR1_PWREN diff --git a/cpu/stm32/include/cpu_conf.h b/cpu/stm32/include/cpu_conf.h index bf5e4f64fc..75e0798e51 100644 --- a/cpu/stm32/include/cpu_conf.h +++ b/cpu/stm32/include/cpu_conf.h @@ -58,6 +58,9 @@ #elif CPU_FAM_STM32L4 #include "stm32l4xx.h" #include "irqs/l4/irqs.h" +#elif CPU_FAM_STM32L5 +#include "stm32l5xx.h" +#include "irqs/l5/irqs.h" #elif CPU_FAM_STM32WB #include "stm32wbxx.h" #include "irqs/wb/irqs.h" @@ -86,7 +89,7 @@ extern "C" { * @brief Flash page configuration * @{ */ -#if defined(CPU_FAM_STM32WB) +#if defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32L5) #define FLASHPAGE_SIZE (4096U) #elif defined(CPU_LINE_STM32F091xC) || defined(CPU_LINE_STM32F072xB) \ || defined(CPU_LINE_STM32F030xC) || defined(CPU_LINE_STM32F103xE) \ @@ -110,7 +113,8 @@ extern "C" { * However, the erase block is always FLASHPAGE_SIZE. */ #if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32G0) + defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32G0) || \ + defined(CPU_FAM_STM32L5) #define FLASHPAGE_RAW_BLOCKSIZE (8U) #elif defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1) #define FLASHPAGE_RAW_BLOCKSIZE (4U) @@ -119,7 +123,8 @@ extern "C" { #endif #if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32G0) + defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32G0) || \ + defined(CPU_FAM_STM32L5) #define FLASHPAGE_RAW_ALIGNMENT (8U) #else /* Writing should be always 4 bytes aligned */ diff --git a/cpu/stm32/include/cpu_conf_stm32_common.h b/cpu/stm32/include/cpu_conf_stm32_common.h index 2839660951..37b2917ccf 100644 --- a/cpu/stm32/include/cpu_conf_stm32_common.h +++ b/cpu/stm32/include/cpu_conf_stm32_common.h @@ -31,7 +31,7 @@ extern "C" { defined(CPU_FAM_STM32F7) || defined(CPU_FAM_STM32L0) || \ defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32L4) || \ defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) || \ - defined(CPU_FAM_STM32G0) + defined(CPU_FAM_STM32G0) || defined(CPU_FAM_STM32L5) /** * @brief Timing register settings @@ -41,7 +41,8 @@ extern "C" { static const i2c_timing_param_t timing_params[] = { #if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F7) || \ defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32G0) + defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32G0) || \ + defined(CPU_FAM_STM32L5) [ I2C_SPEED_NORMAL ] = { .presc = 0xB, .scll = 0x13, /* t_SCLL = 5.0us */ @@ -112,7 +113,7 @@ static const i2c_timing_param_t timing_params[] = { #endif /* CPU_FAM_STM32F0 || CPU_FAM_STM32F3 || CPU_FAM_STM32F7 || CPU_FAM_STM32L0 || CPU_FAM_STM32L4 || CPU_FAM_STM32WB || - CPU_FAM_STM32G4 || CPU_FAM_STM32G0 */ + CPU_FAM_STM32G4 || CPU_FAM_STM32G0 || CPU_FAM_STM32L5 */ #ifdef __cplusplus } diff --git a/cpu/stm32/include/periph/l5/periph_cpu.h b/cpu/stm32/include/periph/l5/periph_cpu.h new file mode 100644 index 0000000000..0c3a214a1a --- /dev/null +++ b/cpu/stm32/include/periph/l5/periph_cpu.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 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 STM32L5 CPU specific definitions for internal peripheral handling + * + * @author Alexandre Abadie + * + */ + +#ifndef PERIPH_L5_PERIPH_CPU_H +#define PERIPH_L5_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 (0x0BF90000) + +#endif /* ndef DOXYGEN */ + +#ifdef __cplusplus +} +#endif + +#endif /* PERIPH_L5_PERIPH_CPU_H */ +/** @} */ diff --git a/cpu/stm32/include/periph_cpu.h b/cpu/stm32/include/periph_cpu.h index 80b1954848..36ef560477 100644 --- a/cpu/stm32/include/periph_cpu.h +++ b/cpu/stm32/include/periph_cpu.h @@ -46,6 +46,8 @@ #include "periph/l1/periph_cpu.h" #elif defined(CPU_FAM_STM32L4) #include "periph/l4/periph_cpu.h" +#elif defined(CPU_FAM_STM32L5) +#include "periph/l5/periph_cpu.h" #elif defined(CPU_FAM_STM32WB) #include "periph/wb/periph_cpu.h" #endif @@ -65,7 +67,7 @@ extern "C" { #elif defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4) || \ defined(CPU_FAM_STM32F7) || defined(CPU_FAM_STM32L4) || \ defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) || \ - defined(CPU_FAM_STM32G0) + defined(CPU_FAM_STM32G0) || defined(CPU_FAM_STM32L5) #define CLOCK_LSI (32000U) #else #error "error: LSI clock speed not defined for your target CPU" @@ -171,7 +173,8 @@ typedef enum { APB1, /**< APB1 bus */ APB2, /**< APB2 bus */ #if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32G0) + defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32G0) || \ + defined(CPU_FAM_STM32L5) APB12, /**< AHB1 bus, second register */ #endif #if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32G0) @@ -182,7 +185,8 @@ typedef enum { AHB, /**< AHB bus */ #elif defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4) || \ defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32F7) || \ - defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) + defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) || \ + defined(CPU_FAM_STM32L5) AHB1, /**< AHB1 bus */ AHB2, /**< AHB2 bus */ AHB3, /**< AHB3 bus */ @@ -669,7 +673,8 @@ typedef struct { #endif #endif #if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L4) || \ - defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) + defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) || \ + defined(CPU_FAM_STM32L5) uart_type_t type; /**< hardware module type (USART or LPUART) */ uint32_t clk_src; /**< clock source used for UART */ #endif @@ -720,7 +725,8 @@ typedef enum { #if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3) || \ defined(CPU_FAM_STM32F7) || defined(CPU_FAM_STM32L0) || \ defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32G0) + defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32G0) || \ + defined(CPU_FAM_STM32L5) I2C_SPEED_FAST_PLUS, /**< fast plus mode: ~1Mbit/s */ #endif } i2c_speed_t; @@ -754,7 +760,8 @@ typedef struct { #if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3) || \ defined(CPU_FAM_STM32F7) || defined(CPU_FAM_STM32L0) || \ defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32G0) + defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32G0) || \ + defined(CPU_FAM_STM32L5) /** * @brief Structure for I2C timing register settings * diff --git a/cpu/stm32/periph/Makefile b/cpu/stm32/periph/Makefile index c5b1e81c91..9b171e154c 100644 --- a/cpu/stm32/periph/Makefile +++ b/cpu/stm32/periph/Makefile @@ -2,7 +2,7 @@ MODULE = periph # Select the specific implementation for `periph_i2c` ifneq (,$(filter periph_i2c,$(USEMODULE))) - ifneq (,$(filter $(CPU_FAM),f0 f3 f7 g0 g4 l0 l4 wb)) + ifneq (,$(filter $(CPU_FAM),f0 f3 f7 g0 g4 l0 l4 l5 wb)) SRC += i2c_1.c else # f1/f2/f4/l1 SRC += i2c_2.c diff --git a/cpu/stm32/periph/gpio_all.c b/cpu/stm32/periph/gpio_all.c index ebb58285f5..f95c83799d 100644 --- a/cpu/stm32/periph/gpio_all.c +++ b/cpu/stm32/periph/gpio_all.c @@ -45,7 +45,8 @@ static gpio_isr_ctx_t isr_ctx[EXTI_NUMOF]; #endif /* MODULE_PERIPH_GPIO_IRQ */ #if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32G0) + defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32G0) || \ + defined(CPU_FAM_STM32L5) #define EXTI_REG_RTSR (EXTI->RTSR1) #define EXTI_REG_FTSR (EXTI->FTSR1) #define EXTI_REG_PR (EXTI->PR1) @@ -92,7 +93,7 @@ static inline void port_init_clock(GPIO_TypeDef *port, gpio_t pin) #elif defined (CPU_FAM_STM32L0) || defined(CPU_FAM_STM32G0) periph_clk_en(IOP, (RCC_IOPENR_GPIOAEN << _port_num(pin))); #elif defined (CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined (CPU_FAM_STM32G4) + defined (CPU_FAM_STM32G4) || defined(CPU_FAM_STM32L5) periph_clk_en(AHB2, (RCC_AHB2ENR_GPIOAEN << _port_num(pin))); #ifdef PWR_CR2_IOSV if (port == GPIOG) { @@ -158,7 +159,7 @@ void gpio_init_analog(gpio_t pin) #elif defined (CPU_FAM_STM32L0) || defined(CPU_FAM_STM32G0) periph_clk_en(IOP, (RCC_IOPENR_GPIOAEN << _port_num(pin))); #elif defined (CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined (CPU_FAM_STM32G4) + defined (CPU_FAM_STM32G4) || defined(CPU_FAM_STM32L5) periph_clk_en(AHB2, (RCC_AHB2ENR_GPIOAEN << _port_num(pin))); #else periph_clk_en(AHB1, (RCC_AHB1ENR_GPIOAEN << _port_num(pin))); @@ -236,7 +237,9 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, gpio_init(pin, mode); /* enable global pin interrupt */ -#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32L0) || \ +#if defined(CPU_FAM_STM32L5) + NVIC_EnableIRQ(EXTI0_IRQn + pin_num); +#elif defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32L0) || \ defined(CPU_FAM_STM32G0) if (pin_num < 2) { NVIC_EnableIRQ(EXTI0_1_IRQn); @@ -264,7 +267,7 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, EXTI_REG_FTSR &= ~(1 << pin_num); EXTI_REG_FTSR |= ((flank >> 1) << pin_num); -#if defined(CPU_FAM_STM32G0) +#if defined(CPU_FAM_STM32G0) || defined(CPU_FAM_STM32L5) /* enable specific pin as exti sources */ EXTI->EXTICR[pin_num >> 2] &= ~(0xf << ((pin_num & 0x03) * 8)); EXTI->EXTICR[pin_num >> 2] |= (port_num << ((pin_num & 0x03) * 8)); @@ -286,7 +289,7 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, void isr_exti(void) { -#if defined(CPU_FAM_STM32G0) +#if defined(CPU_FAM_STM32G0) || defined(CPU_FAM_STM32L5) /* only generate interrupts against lines which have their IMR set */ uint32_t pending_rising_isr = (EXTI->RPR1 & EXTI_REG_IMR); uint32_t pending_falling_isr = (EXTI->FPR1 & EXTI_REG_IMR); diff --git a/cpu/stm32/periph/i2c_1.c b/cpu/stm32/periph/i2c_1.c index 6c88498cf2..80b365fb40 100644 --- a/cpu/stm32/periph/i2c_1.c +++ b/cpu/stm32/periph/i2c_1.c @@ -17,7 +17,7 @@ * @file * @brief Low-level I2C driver implementation * - * This driver supports the STM32 F0, F3, F7, L0, L4 & WB families. + * This driver supports the STM32 F0, F3, F7, L0, L4, L5 & WB families. * @note This implementation only implements the 7-bit addressing polling mode * (for now interrupt mode is not available) * diff --git a/cpu/stm32/periph/pm.c b/cpu/stm32/periph/pm.c index 52288973aa..5425aec391 100644 --- a/cpu/stm32/periph/pm.c +++ b/cpu/stm32/periph/pm.c @@ -46,7 +46,8 @@ #elif defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1) /* Enable ultra low-power and clear wakeup flags */ #define PM_STOP_CONFIG (PWR_CR_LPSDSR | PWR_CR_ULP | PWR_CR_CWUF) -#elif defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32G4) +#elif defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32G4) || \ + defined(CPU_FAM_STM32L5) #define PM_STOP_CONFIG (PWR_CR1_LPMS_STOP1) #elif defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G0) #define PM_STOP_CONFIG (PWR_CR1_LPMS_0) @@ -66,7 +67,8 @@ */ #if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1) #define PM_STANDBY_CONFIG (PWR_CR_PDDS | PWR_CR_CWUF | PWR_CR_CSBF | PWR_CR_ULP) -#elif defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32G4) +#elif defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32G4) || \ + defined(CPU_FAM_STM32L5) #define PM_STANDBY_CONFIG (PWR_CR1_LPMS_STANDBY) #elif defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G0) #define PM_STANDBY_CONFIG (PWR_CR1_LPMS_0 | PWR_CR1_LPMS_1) @@ -78,7 +80,8 @@ #endif #if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32G0) + defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32G0) || \ + defined(CPU_FAM_STM32L5) #define PWR_CR_REG PWR->CR1 #define PWR_WUP_REG PWR->CR3 /* Allow overridable SRAM2 retention mode using CFLAGS */ @@ -104,14 +107,15 @@ void pm_set(unsigned mode) PWR_CR_REG &= ~(PM_STOP_CONFIG | PM_STANDBY_CONFIG); PWR_CR_REG |= PM_STANDBY_CONFIG; #if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined(CPU_FAM_STM32G4) + defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32L5) #if STM32L4_SRAM2_RETENTION PWR->CR3 |= PWR_CR3_RRS; #else PWR->CR3 &= ~PWR_CR3_RRS; #endif #endif -#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32G4) +#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32G4) || \ + defined(CPU_FAM_STM32L5) /* Clear flags */ PWR->SCR |= PWR_SCR_CSBF; #endif diff --git a/cpu/stm32/periph/uart.c b/cpu/stm32/periph/uart.c index 170dd7c342..2dadad0fb0 100644 --- a/cpu/stm32/periph/uart.c +++ b/cpu/stm32/periph/uart.c @@ -34,7 +34,8 @@ #include "periph/gpio.h" #include "pm_layered.h" -#if defined(CPU_LINE_STM32L4R5xx) || defined(CPU_FAM_STM32G0) +#if defined(CPU_LINE_STM32L4R5xx) || defined(CPU_FAM_STM32G0) || \ + defined(CPU_FAM_STM32L5) #define ISR_REG ISR #define ISR_TXE USART_ISR_TXE_TXFNF #define ISR_RXNE USART_ISR_RXNE_RXFNE @@ -60,9 +61,9 @@ #define RDR_REG DR #endif -#if defined(CPU_LINE_STM32L4R5xx) || defined(CPU_FAM_STM32G0) +#if defined(CPU_LINE_STM32L4R5xx) || defined(CPU_FAM_STM32G0) || \ + defined(CPU_FAM_STM32L5) #define RXENABLE (USART_CR1_RE | USART_CR1_RXNEIE_RXFNEIE) -#define USART_ISR_RXNE (USART_ISR_RXNE_RXFNE) #else #define RXENABLE (USART_CR1_RE | USART_CR1_RXNEIE) #endif @@ -96,7 +97,8 @@ static inline USART_TypeDef *dev(uart_t uart) static inline void uart_init_usart(uart_t uart, uint32_t baudrate); #if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L4) || \ - defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) + defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) || \ + defined(CPU_FAM_STM32L5) #ifdef MODULE_PERIPH_LPUART static inline void uart_init_lpuart(uart_t uart, uint32_t baudrate); #endif @@ -189,7 +191,8 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) dev(uart)->CR3 = 0; #if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L4) || \ - defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) + defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) || \ + defined(CPU_FAM_STM32L5) switch (uart_config[uart].type) { case STM32_USART: uart_init_usart(uart, baudrate); @@ -301,7 +304,13 @@ static inline void uart_init_usart(uart_t uart, uint32_t baudrate) } #if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L4) || \ - defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) + defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) || \ + defined(CPU_FAM_STM32L5) +#ifdef CPU_FAM_STM32L5 +#define RCC_CCIPR_LPUART1SEL_0 RCC_CCIPR1_LPUART1SEL_0 +#define RCC_CCIPR_LPUART1SEL_1 RCC_CCIPR1_LPUART1SEL_1 +#define CCIPR CCIPR1 +#endif #ifdef MODULE_PERIPH_LPUART static inline void uart_init_lpuart(uart_t uart, uint32_t baudrate) { diff --git a/cpu/stm32/stm32_info.mk b/cpu/stm32/stm32_info.mk index 80022dbb8d..04175f25e7 100644 --- a/cpu/stm32/stm32_info.mk +++ b/cpu/stm32/stm32_info.mk @@ -32,6 +32,8 @@ else ifeq (f7,$(CPU_FAM)) CPU_CORE = cortex-m7 else ifneq (,$(filter $(CPU_FAM),g0 l0)) CPU_CORE = cortex-m0plus +else ifneq (,$(CPU_FAM),l5) + CPU_CORE = cortex-m33 else $(error Not supported CPU family: 'stm32$(CPU_FAM)') endif diff --git a/cpu/stm32/stm32_mem_lengths.mk b/cpu/stm32/stm32_mem_lengths.mk index 7b4bc9626e..9fcba4afd1 100644 --- a/cpu/stm32/stm32_mem_lengths.mk +++ b/cpu/stm32/stm32_mem_lengths.mk @@ -263,6 +263,10 @@ else ifeq ($(STM32_TYPE), L) else ifeq ($(STM32_MODEL2), R) RAM_LEN = 640K endif + else ifeq ($(STM32_FAMILY), 5) + ifneq (, $(filter $(STM32_MODEL2), 5 6)) + RAM_LEN = 256K + endif endif else ifeq ($(STM32_TYPE), W) ifeq ($(STM32_FAMILY), B) diff --git a/cpu/stm32/stmclk/Makefile b/cpu/stm32/stmclk/Makefile index 6a77ec3984..8203ca23ef 100644 --- a/cpu/stm32/stmclk/Makefile +++ b/cpu/stm32/stmclk/Makefile @@ -10,6 +10,8 @@ else ifneq (,$(filter $(CPU_FAM),l0 l1)) SRC += stmclk_l0l1.c else ifneq (,$(filter $(CPU_FAM),l4 wb)) SRC += stmclk_l4wb.c +else ifneq (,$(filter $(CPU_FAM),l5)) + SRC += stmclk_l5.c else ifneq (,$(filter $(CPU_FAM),g0 g4)) SRC += stmclk_gx.c endif diff --git a/cpu/stm32/stmclk/stmclk_common.c b/cpu/stm32/stmclk/stmclk_common.c index 7862c830f9..70ed5dea1e 100644 --- a/cpu/stm32/stmclk/stmclk_common.c +++ b/cpu/stm32/stmclk/stmclk_common.c @@ -25,7 +25,7 @@ #if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32F7) || \ defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) || \ - defined(CPU_FAM_STM32G0) + defined(CPU_FAM_STM32G0) || defined(CPU_FAM_STM32L5) #define REG_PWR_CR CR1 #define BIT_CR_DBP PWR_CR1_DBP #else @@ -49,6 +49,9 @@ #define RCC_CSR_LSIRDY RCC_CSR_LSI1RDY #endif +#if defined(CPU_FAM_STM32L5) +#define RCC_CFGR_SWS_HSI RCC_CFGR_SWS_0 +#endif void stmclk_enable_hsi(void) { diff --git a/cpu/stm32/stmclk/stmclk_l5.c b/cpu/stm32/stmclk/stmclk_l5.c new file mode 100644 index 0000000000..d233e99fd1 --- /dev/null +++ b/cpu/stm32/stmclk/stmclk_l5.c @@ -0,0 +1,348 @@ +/* + * Copyright (C) 2017 Freie Universität Berlin + * 2017 OTA keys S.A. + * 2017 HAW-Hamburg + * 2020 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 Implementation of STM32 clock configuration for L5 family + * + * @author Hauke Petersen + * @author Nick van IJzendoorn + * @author Vincent Dupont + * @author Michel Rottleuthner + * @author Francisco Molina + * @author Alexandre Abadie + * @} + */ + +#include "cpu.h" +#include "stmclk.h" +#include "periph_conf.h" + +/* map CMSIS defines not present in wb and l5 families */ +#define RCC_PLLCFGR_PLLSRC_HSE (RCC_PLLCFGR_PLLSRC_1 | RCC_PLLCFGR_PLLSRC_0) +#define RCC_PLLCFGR_PLLSRC_HSI (RCC_PLLCFGR_PLLSRC_1) +#define RCC_PLLCFGR_PLLSRC_MSI (RCC_PLLCFGR_PLLSRC_0) +#define RCC_CFGR_SW_MSI (0x00000000U) +#define RCC_CFGR_SW_HSI (RCC_CFGR_SW_0) +#define RCC_CFGR_SW_HSE (RCC_CFGR_SW_1) +#define RCC_CFGR_SW_PLL (RCC_CFGR_SW_1 | RCC_CFGR_SW_0) +#define RCC_CFGR_SWS_MSI (0x00000000U) +#define RCC_CFGR_SWS_HSI (RCC_CFGR_SWS_0) +#define RCC_CFGR_SWS_HSE (RCC_CFGR_SWS_1) +#define RCC_CFGR_SWS_PLL (RCC_CFGR_SWS_1 | RCC_CFGR_SWS_0) + +/* PLL configuration */ +/* figure out which input to use */ +#if IS_ACTIVE(CONFIG_CLOCK_PLL_SRC_MSI) +#define PLL_SRC RCC_PLLCFGR_PLLSRC_MSI +#elif IS_ACTIVE(CONFIG_CLOCK_PLL_SRC_HSE) && IS_ACTIVE(CONFIG_BOARD_HAS_HSE) +#define PLL_SRC RCC_PLLCFGR_PLLSRC_HSE +#elif IS_ACTIVE(CONFIG_CLOCK_PLL_SRC_HSI) +#define PLL_SRC RCC_PLLCFGR_PLLSRC_HSI +#else +#define PLL_SRC 0 +#endif + +/* check configuration and get the corresponding bitfields */ +#if (CONFIG_CLOCK_PLL_M < 1 || CONFIG_CLOCK_PLL_M > 16) +#error "PLL configuration: PLL M value is out of range" +#endif +#define PLL_M ((CONFIG_CLOCK_PLL_M - 1) << RCC_PLLCFGR_PLLM_Pos) + +#if (CONFIG_CLOCK_PLL_N < 8 || CONFIG_CLOCK_PLL_N > 86) +#error "PLL configuration: PLL N value is out of range" +#endif +#define PLL_N (CONFIG_CLOCK_PLL_N << RCC_PLLCFGR_PLLN_Pos) + +#if (CONFIG_CLOCK_PLL_R == 2) +#define PLL_R (0) +#elif (CONFIG_CLOCK_PLL_R == 4) +#define PLL_R (RCC_PLLCFGR_PLLR_0) +#elif (CONFIG_CLOCK_PLL_R == 6) +#define PLL_R (RCC_PLLCFGR_PLLR_1) +#elif (CONFIG_CLOCK_PLL_R == 8) +#define PLL_R (RCC_PLLCFGR_PLLR_1 | RCC_PLLCFGR_PLLR_0) +#else +#error "PLL configuration: PLL R value is invalid" +#endif + +#if (CONFIG_CLOCK_PLL_Q == 2) +#define PLL_Q (0) +#elif (CONFIG_CLOCK_PLL_Q == 4) +#define PLL_Q (RCC_PLLCFGR_PLLQ_0) +#elif (CONFIG_CLOCK_PLL_Q == 6) +#define PLL_Q (RCC_PLLCFGR_PLLQ_1) +#elif (CONFIG_CLOCK_PLL_Q == 8) +#define PLL_Q (RCC_PLLCFGR_PLLQ_0 | RCC_PLLCFGR_PLLQ_1) +#else +#error "PLL configuration: PLL Q value is invalid" +#endif + +/* Define MSI range bitfields */ +#if CONFIG_CLOCK_MSI == KHZ(100) +#define CLOCK_MSIRANGE (0) +#elif CONFIG_CLOCK_MSI == KHZ(200) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_0) +#elif CONFIG_CLOCK_MSI == KHZ(400) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_1) +#elif CONFIG_CLOCK_MSI == KHZ(800) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_1 | RCC_CR_MSIRANGE_0) +#elif CONFIG_CLOCK_MSI == MHZ(1) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_2) +#elif CONFIG_CLOCK_MSI == MHZ(2) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_2 | RCC_CR_MSIRANGE_0) +#elif CONFIG_CLOCK_MSI == MHZ(4) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_2 | RCC_CR_MSIRANGE_1) +#elif CONFIG_CLOCK_MSI == MHZ(8) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_2 | RCC_CR_MSIRANGE_1 | RCC_CR_MSIRANGE_0) +#elif CONFIG_CLOCK_MSI == MHZ(16) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_3) +#elif CONFIG_CLOCK_MSI == MHZ(24) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_3 | RCC_CR_MSIRANGE_0) +#elif CONFIG_CLOCK_MSI == MHZ(32) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_3 | RCC_CR_MSIRANGE_1) +#elif CONFIG_CLOCK_MSI == MHZ(48) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_3 | RCC_CR_MSIRANGE_1 | RCC_CR_MSIRANGE_0) +#else +#error "Invalid MSI clock" +#endif + +/* Configure 48MHz clock source */ +#define CLOCK_PLLQ ((CLOCK_PLL_SRC / CONFIG_CLOCK_PLL_M) * CONFIG_CLOCK_PLL_N) / CONFIG_CLOCK_PLL_Q + +#if CLOCK_PLLQ == MHZ(48) +#define CLOCK48MHZ_USE_PLLQ 1 +#elif CONFIG_CLOCK_MSI == MHZ(48) +#define CLOCK48MHZ_USE_MSI 1 +#else +#define CLOCK48MHZ_USE_PLLQ 0 +#define CLOCK48MHZ_USE_MSI 0 +#endif + +#if IS_ACTIVE(CLOCK48MHZ_USE_PLLQ) +#define CLOCK48MHZ_SELECT (RCC_CCIPR1_CLK48MSEL_1) +#elif IS_ACTIVE(CLOCK48MHZ_USE_MSI) +#define CLOCK48MHZ_SELECT (RCC_CCIPR1_CLK48MSEL_1 | RCC_CCIPR1_CLK48MSEL_0) +#else +#define CLOCK48MHZ_SELECT (0) +#endif + +/* Configure the AHB and APB buses prescalers */ +#define CLOCK_AHB_DIV (0) + +#if CONFIG_CLOCK_APB1_DIV == 1 +#define CLOCK_APB1_DIV (0) +#elif CONFIG_CLOCK_APB1_DIV == 2 +#define CLOCK_APB1_DIV (RCC_CFGR_PPRE1_2) +#elif CONFIG_CLOCK_APB1_DIV == 4 +#define CLOCK_APB1_DIV (RCC_CFGR_PPRE1_2 | RCC_CFGR_PPRE1_0) +#elif CONFIG_CLOCK_APB1_DIV == 8 +#define CLOCK_APB1_DIV (RCC_CFGR_PPRE1_2 | RCC_CFGR_PPRE1_1) +#elif CONFIG_CLOCK_APB1_DIV == 16 +#define CLOCK_APB1_DIV (RCC_CFGR_PPRE1_2 | RCC_CFGR_PPRE1_1 | RCC_CFGR_PPRE1_0) +#endif + +#if CONFIG_CLOCK_APB2_DIV == 1 +#define CLOCK_APB2_DIV (0) +#elif CONFIG_CLOCK_APB2_DIV == 2 +#define CLOCK_APB2_DIV (RCC_CFGR_PPRE2_2) +#elif CONFIG_CLOCK_APB2_DIV == 4 +#define CLOCK_APB2_DIV (RCC_CFGR_PPRE2_2 | RCC_CFGR_PPRE2_0) +#elif CONFIG_CLOCK_APB2_DIV == 8 +#define CLOCK_APB2_DIV (RCC_CFGR_PPRE2_2 | RCC_CFGR_PPRE2_1) +#elif CONFIG_CLOCK_APB2_DIV == 16 +#define CLOCK_APB2_DIV (RCC_CFGR_PPRE2_2 | RCC_CFGR_PPRE2_1 | RCC_CFGR_PPRE2_0) +#endif + +/* Only periph_hwrng requires 48MHz for the moment */ +#if IS_USED(MODULE_PERIPH_HWRNG) +#if !IS_ACTIVE(CLOCK48MHZ_USE_PLLQ) && !IS_ACTIVE(CLOCK48MHZ_USE_MSI) +#error "No 48MHz clock source available, HWRNG cannot work" +#endif +#define CLOCK_ENABLE_48MHZ 1 +#else +#define CLOCK_ENABLE_48MHZ 0 +#endif + +/* Check if PLL is required + - When used as system clock + - When PLLQ is used as 48MHz clock source +*/ +#if IS_ACTIVE(CONFIG_USE_CLOCK_PLL) || \ + (IS_ACTIVE(CLOCK_ENABLE_48MHZ) && IS_ACTIVE(CLOCK48MHZ_USE_PLLQ)) +#define CLOCK_ENABLE_PLL 1 +#else +#define CLOCK_ENABLE_PLL 0 +#endif + +/* Check if HSE is required: + - When used as system clock + - When used as PLL input clock +*/ +#if IS_ACTIVE(CONFIG_USE_CLOCK_HSE) || \ + (IS_ACTIVE(CLOCK_ENABLE_PLL) && IS_ACTIVE(CONFIG_CLOCK_PLL_SRC_HSE)) +#define CLOCK_ENABLE_HSE 1 +#else +#define CLOCK_ENABLE_HSE 0 +#endif + +/* HSE cannot be enabled if not provided by the board */ +#if IS_ACTIVE(CLOCK_ENABLE_HSE) && !IS_ACTIVE(CONFIG_BOARD_HAS_HSE) +#error "HSE is required by the clock configuration but is not provided by the board." +#endif + +/* Check if HSI is required: + - When used as system clock + - When used as PLL input clock +*/ +#if IS_ACTIVE(CONFIG_USE_CLOCK_HSI) || \ + (IS_ACTIVE(CLOCK_ENABLE_PLL) && IS_ACTIVE(CONFIG_CLOCK_PLL_SRC_HSI)) +#define CLOCK_ENABLE_HSI 1 +#else +#define CLOCK_ENABLE_HSI 0 +#endif + +/* Check if MSI is required + - When used as system clock + - When used as PLL input clock +*/ +#if IS_ACTIVE(CONFIG_USE_CLOCK_MSI) || \ + (IS_ACTIVE(CLOCK_ENABLE_PLL) && IS_ACTIVE(CONFIG_CLOCK_PLL_SRC_MSI)) || \ + (IS_ACTIVE(CLOCK_ENABLE_48MHZ) && IS_ACTIVE(CLOCK48MHZ_USE_MSI)) +#define CLOCK_ENABLE_MSI 1 +#else +#define CLOCK_ENABLE_MSI 0 +#endif + +/* Deduct the needed flash wait states from the core clock frequency */ +#if CLOCK_AHB <= MHZ(20) +#define FLASH_WAITSTATES FLASH_ACR_LATENCY_0WS +#elif CLOCK_AHB <= MHZ(40) +#define FLASH_WAITSTATES FLASH_ACR_LATENCY_1WS +#elif CLOCK_AHB <= MHZ(60) +#define FLASH_WAITSTATES FLASH_ACR_LATENCY_2WS +#elif CLOCK_AHB <= MHZ(80) +#define FLASH_WAITSTATES FLASH_ACR_LATENCY_3WS +#elif CLOCK_AHB <= MHZ(100) +#define FLASH_WAITSTATES FLASH_ACR_LATENCY_4WS +#elif CLOCK_AHB <= MHZ(110) +#define FLASH_WAITSTATES FLASH_ACR_LATENCY_5WS +#endif + +void stmclk_init_sysclk(void) +{ + /* disable any interrupts. Global interrupts could be enabled if this is + * called from some kind of bootloader... */ + unsigned is = irq_disable(); + RCC->CIER = 0; + + /* enable HSI clock for the duration of initialization */ + stmclk_enable_hsi(); + + /* use HSI as system clock while we do any further configuration and + * configure the AHB and APB clock dividers as configured by the board */ + RCC->CFGR = (RCC_CFGR_SW_HSI | CLOCK_AHB_DIV | CLOCK_APB1_DIV | CLOCK_APB2_DIV); + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) {} + + /* configure flash wait states */ + FLASH->ACR = FLASH_WAITSTATES; + + /* disable all active clocks except HSI -> resets the clk configuration */ + RCC->CR = RCC_CR_HSION; + + /* Enable the HSE clock only when it's used */ + if (IS_ACTIVE(CLOCK_ENABLE_HSE)) { + RCC->CR |= (RCC_CR_HSEON); + while (!(RCC->CR & RCC_CR_HSERDY)) {} + } + + /* Enable the MSI clock only when it's used */ + if (IS_ACTIVE(CLOCK_ENABLE_MSI)) { + RCC->CR |= (RCC_CR_MSION | CLOCK_MSIRANGE | RCC_CR_MSIRGSEL); + while (!(RCC->CR & RCC_CR_MSIRDY)) {} + } + + /* Enable the PLL clock only when it's used */ + if (IS_ACTIVE(CLOCK_ENABLE_PLL)) { + if (IS_ACTIVE(CONFIG_CLOCK_PLL_SRC_MSI) && IS_ACTIVE(CONFIG_BOARD_HAS_LSE)) { + /* configure the low speed clock domain */ + stmclk_enable_lfclk(); + /* now we can enable the MSI PLL mode to enhance accuracy of the MSI */ + RCC->CR |= RCC_CR_MSIPLLEN; + while (!(RCC->CR & RCC_CR_MSIRDY)) {} + } + + /* configure and start the PLL */ + RCC->PLLCFGR = (PLL_SRC | PLL_M | PLL_N | PLL_R | PLL_Q); + + if (IS_ACTIVE(CONFIG_USE_CLOCK_PLL)) { + /* Enable PLLCLK if PLL is used as system clock */ + RCC->PLLCFGR |= RCC_PLLCFGR_PLLREN; + } + + if (IS_ACTIVE(CLOCK48MHZ_USE_PLLQ)) { + /* Enable PLLQ if PLL is used as 48MHz source clock */ + RCC->PLLCFGR |= RCC_PLLCFGR_PLLQEN; + } + + RCC->CR |= (RCC_CR_PLLON); + while (!(RCC->CR & RCC_CR_PLLRDY)) {} + } + + /* Configure SYSCLK */ + if (!IS_ACTIVE(CONFIG_USE_CLOCK_HSI)) { + RCC->CFGR &= ~RCC_CFGR_SW; + } + + if (IS_ACTIVE(CONFIG_USE_CLOCK_HSE)) { + /* Select HSE as system clock */ + RCC->CFGR |= RCC_CFGR_SW_HSE; + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSE) {} + } + else if (IS_ACTIVE(CONFIG_USE_CLOCK_MSI)) { + /* Select MSI as system clock */ + RCC->CFGR |= RCC_CFGR_SW_MSI; + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_MSI) {} + } + else if (IS_ACTIVE(CONFIG_USE_CLOCK_PLL)) { + if (CLOCK_AHB > MHZ(80)) { + /* Divide HCLK by 2 before enabling the PLL */ + RCC->CFGR |= RCC_CFGR_HPRE_3; + } + + /* Select main PLL as system clock */ + RCC->CFGR |= RCC_CFGR_SW_PLL; + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) {} + + if (CLOCK_AHB > MHZ(80)) { + /* Wait 1us before switching back to full speed */ + /* Use volatile to prevent the compiler from optimizing the loop */ + volatile uint8_t count = CLOCK_CORECLOCK / MHZ(1); + while (count--) {} + RCC->CFGR &= ~RCC_CFGR_HPRE_3; + } + } + + if (!IS_ACTIVE(CLOCK_ENABLE_HSI)) { + /* Disable HSI only if not used */ + stmclk_disable_hsi(); + } + + if (IS_ACTIVE(CLOCK_ENABLE_48MHZ)) { + /* configure the clock used for the 48MHz clock tree (USB, RNG) */ + RCC->CCIPR1 = CLOCK48MHZ_SELECT; + } + + irq_restore(is); +}