From 0745cc4a992b893d3698822c8815df4392b079b4 Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Wed, 26 Aug 2020 18:56:04 +0200 Subject: [PATCH] cpu: boards: smt32l4: rework clock configuration --- .../stm32/include/l4/cfg_clock_default.h | 188 ++++++++++---- cpu/stm32/stmclk/stmclk_l4wb.c | 229 +++++++++++++----- 2 files changed, 308 insertions(+), 109 deletions(-) diff --git a/boards/common/stm32/include/l4/cfg_clock_default.h b/boards/common/stm32/include/l4/cfg_clock_default.h index 127906d645..7e3197de1a 100644 --- a/boards/common/stm32/include/l4/cfg_clock_default.h +++ b/boards/common/stm32/include/l4/cfg_clock_default.h @@ -12,14 +12,14 @@ * @{ * * @file - * @brief Configure STM32L4 clock using 80MHz core clock and LSE (32.768kHz) + * @brief Default STM32L4 clock configuration * * @author Hauke Petersen * @author Alexandre Abadie */ -#ifndef L4_CFG_CLOCK_80_1_H -#define L4_CFG_CLOCK_80_1_H +#ifndef L4_CFG_CLOCK_DEFAULT_H +#define L4_CFG_CLOCK_DEFAULT_H #include "periph_cpu.h" @@ -31,55 +31,153 @@ extern "C" { * @name Clock system configuration * @{ */ -/* 0: no external high speed crystal available - * else: actual crystal frequency [in Hz] */ -#define CLOCK_HSE (0) +#ifndef CONFIG_USE_CLOCK_PLL +#if IS_ACTIVE(CONFIG_USE_CLOCK_HSE) || IS_ACTIVE(CONFIG_USE_CLOCK_HSI) || \ + IS_ACTIVE(CONFIG_USE_CLOCK_MSI) +#define CONFIG_USE_CLOCK_PLL (0) +#else +#define CONFIG_USE_CLOCK_PLL (1) /* Use PLL by default */ +#endif +#endif /* CONFIG_USE_CLOCK_PLL */ -/* 0: no external low speed crystal available, - * 1: external crystal available (always 32.768kHz) - */ -#define CLOCK_LSE (1) +#ifndef CONFIG_USE_CLOCK_MSI +#define CONFIG_USE_CLOCK_MSI (0) +#endif /* CONFIG_USE_CLOCK_MSI */ -/* 0: enable MSI only if HSE isn't available - * 1: always enable MSI (e.g. if USB or RNG is used)*/ -#define CLOCK_MSI_ENABLE (1) +#ifndef CONFIG_USE_CLOCK_HSE +#define CONFIG_USE_CLOCK_HSE (0) +#endif /* CONFIG_USE_CLOCK_HSE */ -/* 0: disable Hardware auto calibration with LSE - * 1: enable Hardware auto calibration with LSE (PLL-mode) - * LSE is mandatory for MSI/LSE-trimming to work */ -#define CLOCK_MSI_LSE_PLL (1) +#ifndef CONFIG_USE_CLOCK_HSI +#define CONFIG_USE_CLOCK_HSI (0) +#endif /* CONFIG_USE_CLOCK_HSI */ -/* give the target core clock (HCLK) frequency [in Hz], maximum: 80MHz */ -#define CLOCK_CORECLOCK (80000000U) -/* PLL configuration: make sure your values are legit! - * - * compute by: CORECLOCK = (((PLL_IN / M) * N) / R) - * with: - * PLL_IN: input clock, HSE or MSI @ 48MHz - * M: pre-divider, allowed range: [1:8] - * N: multiplier, allowed range: [8:86] - * R: post-divider, allowed range: [2,4,6,8] - * - * Also the following constraints need to be met: - * (PLL_IN / M) -> [4MHz:16MHz] - * (PLL_IN / M) * N -> [64MHz:344MHz] - * CORECLOCK -> 80MHz MAX! - */ -#define CLOCK_PLL_M (6) -#define CLOCK_PLL_N (20) -#define CLOCK_PLL_R (2) -/* peripheral clock setup */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 -#define CLOCK_AHB (CLOCK_CORECLOCK / 1) -#define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV4 -#define CLOCK_APB1 (CLOCK_CORECLOCK / 4) -#define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV2 -#define CLOCK_APB2 (CLOCK_CORECLOCK / 2) -/** @} */ +#if CONFIG_USE_CLOCK_PLL && \ + (CONFIG_USE_CLOCK_MSI || CONFIG_USE_CLOCK_HSE || CONFIG_USE_CLOCK_HSI) +#error "Cannot use PLL as clock source with other clock configurations" +#endif + +#if CONFIG_USE_CLOCK_MSI && \ + (CONFIG_USE_CLOCK_PLL || CONFIG_USE_CLOCK_HSI || CONFIG_USE_CLOCK_HSE) +#error "Cannot use MSI as clock source with other clock configurations" +#endif + +#if CONFIG_USE_CLOCK_HSE && \ + (CONFIG_USE_CLOCK_PLL || CONFIG_USE_CLOCK_MSI || CONFIG_USE_CLOCK_HSI) +#error "Cannot use HSE as clock source with other clock configurations" +#endif + +#if CONFIG_USE_CLOCK_HSI && \ + (CONFIG_USE_CLOCK_PLL || CONFIG_USE_CLOCK_MSI || CONFIG_USE_CLOCK_HSE) +#error "Cannot use HSI as clock source with other clock configurations" +#endif + +#ifndef CONFIG_BOARD_HAS_HSE +#define CONFIG_BOARD_HAS_HSE (0) +#endif +#ifndef CLOCK_HSE +#define CLOCK_HSE MHZ(8) +#endif +#if CONFIG_BOARD_HAS_HSE && (CLOCK_HSE < MHZ(4) || CLOCK_HSE > MHZ(48)) +#error "HSE clock frequency must be between 4MHz and 48MHz" +#endif + +#ifndef CONFIG_BOARD_HAS_LSE +#define CONFIG_BOARD_HAS_LSE (0) +#endif +#if CONFIG_BOARD_HAS_LSE +#define CLOCK_LSE (1) +#else +#define CLOCK_LSE (0) +#endif + +#define CLOCK_HSI MHZ(16) + +#ifndef CONFIG_CLOCK_MSI +#define CONFIG_CLOCK_MSI MHZ(48) +#endif + +/* The following parameters configure a 80MHz system clock with PLL as input clock */ +#ifndef CONFIG_CLOCK_PLL_SRC_MSI +#if IS_ACTIVE(CONFIG_CLOCK_PLL_SRC_HSE) || IS_ACTIVE(CONFIG_CLOCK_PLL_SRC_HSI) || \ + CONFIG_BOARD_HAS_HSE +#define CONFIG_CLOCK_PLL_SRC_MSI (0) +#else +#define CONFIG_CLOCK_PLL_SRC_MSI (1) /* Use MSI an input clock by default */ +#endif +#endif /* CONFIG_CLOCK_PLL_SRC_MSI */ +#ifndef CONFIG_CLOCK_PLL_SRC_HSE +#if CONFIG_BOARD_HAS_HSE +#define CONFIG_CLOCK_PLL_SRC_HSE (1) +#else +#define CONFIG_CLOCK_PLL_SRC_HSE (0) +#endif +#endif +#ifndef CONFIG_CLOCK_PLL_SRC_HSI +#define CONFIG_CLOCK_PLL_SRC_HSI (0) +#endif +#ifndef CONFIG_CLOCK_PLL_M +#define CONFIG_CLOCK_PLL_M (6) +#endif +#ifndef CONFIG_CLOCK_PLL_N +#define CONFIG_CLOCK_PLL_N (20) +#endif +#ifndef CONFIG_CLOCK_PLL_R +#define CONFIG_CLOCK_PLL_R (2) +#endif + +#if CONFIG_USE_CLOCK_HSI +#define CLOCK_CORECLOCK (CLOCK_HSI) + +#elif CONFIG_USE_CLOCK_HSE +#if CONFIG_BOARD_HAS_HSE == 0 +#error "The board doesn't provide an HSE oscillator" +#endif +#define CLOCK_CORECLOCK (CLOCK_HSE) + +#elif CONFIG_USE_CLOCK_MSI +#define CLOCK_CORECLOCK (CONFIG_CLOCK_MSI) + +#elif CONFIG_USE_CLOCK_PLL +#if CONFIG_CLOCK_PLL_SRC_MSI +#define CLOCK_PLL_SRC (CONFIG_CLOCK_MSI) +#elif CONFIG_CLOCK_PLL_SRC_HSE +#define CLOCK_PLL_SRC (CLOCK_HSE) +#else /* CONFIG_CLOCK_PLL_SRC_ */ +#define CLOCK_PLL_SRC (CLOCK_HSI) +#endif +#define CLOCK_CORECLOCK \ + ((CLOCK_PLL_SRC / CONFIG_CLOCK_PLL_M) * CONFIG_CLOCK_PLL_N) / CONFIG_CLOCK_PLL_R +#ifndef CLOCK_CORECLOCK_MAX +#define CLOCK_CORECLOCK_MAX MHZ(80) +#endif +#if CLOCK_CORECLOCK > CLOCK_CORECLOCK_MAX +#if CLOCK_CORECLOCK_MAX == MHZ(64) +#error "SYSCLK cannot exceed 64MHz" +#elif CLOCK_CORECLOCK_MAX == MHZ(80) +#error "SYSCLK cannot exceed 80MHz" +#elif CLOCK_CORECLOCK_MAX == MHZ(120) +#error "SYSCLK cannot exceed 120MHz" +#else +#error "invalid SYSCLK" +#endif +#endif /* CLOCK_CORECLOCK > CLOCK_CORECLOCK_MAX */ +#endif /* CONFIG_USE_CLOCK_PLL */ + +#define CLOCK_AHB CLOCK_CORECLOCK /* max: 80MHz */ + +#ifndef CONFIG_CLOCK_APB1_DIV +#define CONFIG_CLOCK_APB1_DIV (4) +#endif +#define CLOCK_APB1 (CLOCK_CORECLOCK / CONFIG_CLOCK_APB1_DIV) /* max: 80MHz */ +#ifndef CONFIG_CLOCK_APB2_DIV +#define CONFIG_CLOCK_APB2_DIV (2) +#endif +#define CLOCK_APB2 (CLOCK_CORECLOCK / CONFIG_CLOCK_APB2_DIV) /* max: 80MHz */ #ifdef __cplusplus } #endif -#endif /* L4_CFG_CLOCK_80_1_H */ +#endif /* L4_CFG_CLOCK_DEFAULT_H */ /** @} */ diff --git a/cpu/stm32/stmclk/stmclk_l4wb.c b/cpu/stm32/stmclk/stmclk_l4wb.c index edecda4c96..9b9a196c56 100644 --- a/cpu/stm32/stmclk/stmclk_l4wb.c +++ b/cpu/stm32/stmclk/stmclk_l4wb.c @@ -27,17 +27,6 @@ #include "stmclk.h" #include "periph_conf.h" -/* make sure we have all needed information about the clock configuration */ -#ifndef CLOCK_HSE -#error "Please provide CLOCK_HSE in your board's perhip_conf.h" -#endif -#ifndef CLOCK_LSE -#error "Please provide CLOCK_LSE in your board's periph_conf.h" -#endif -#if !defined(CLOCK_PLL_M) || !defined(CLOCK_PLL_N) || !defined(CLOCK_PLL_R) -#error "Please provide the PLL configuration in your board's periph_conf.h" -#endif - /* map CMSIS defines not present in stm32wb55xx.h */ #if defined(CPU_FAM_STM32WB) #define RCC_PLLCFGR_PLLSRC_HSE (RCC_PLLCFGR_PLLSRC_0 | RCC_PLLCFGR_PLLSRC_1) @@ -57,39 +46,39 @@ * @{ */ /* figure out which input to use */ -#if (CLOCK_HSE) -#define PLL_IN CLOCK_HSE +#if CONFIG_CLOCK_PLL_SRC_MSI +#define PLL_SRC RCC_PLLCFGR_PLLSRC_MSI +#elif CONFIG_CLOCK_PLL_SRC_HSE && CONFIG_BOARD_HAS_HSE #define PLL_SRC RCC_PLLCFGR_PLLSRC_HSE #else -#define PLL_IN (48000000) /* MSI @ 48MHz */ -#define PLL_SRC RCC_PLLCFGR_PLLSRC_MSI +#define PLL_SRC RCC_PLLCFGR_PLLSRC_HSI #endif /**check configuration and get the corresponding bitfields */ -#if (CLOCK_PLL_M < 1 || CLOCK_PLL_M > 8) +#if (CONFIG_CLOCK_PLL_M < 1 || CONFIG_CLOCK_PLL_M > 8) #error "PLL configuration: PLL M value is out of range" #endif -#define PLL_M ((CLOCK_PLL_M - 1) << RCC_PLLCFGR_PLLM_Pos) +#define PLL_M ((CONFIG_CLOCK_PLL_M - 1) << RCC_PLLCFGR_PLLM_Pos) -#if (CLOCK_PLL_N < 8 || CLOCK_PLL_N > 86) +#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 (CLOCK_PLL_N << RCC_PLLCFGR_PLLN_Pos) +#define PLL_N (CONFIG_CLOCK_PLL_N << RCC_PLLCFGR_PLLN_Pos) #if defined(CPU_FAM_STM32WB) -#if (CLOCK_PLL_R < 1 || CLOCK_PLL_R > 8) +#if (CONFIG_CLOCK_PLL_R < 1 || CONFIG_CLOCK_PLL_R > 8) #error "PLL configuration: PLL R value is invalid" #else -#define PLL_R ((CLOCK_PLL_R - 1)<< RCC_PLLCFGR_PLLR_Pos) +#define PLL_R ((CONFIG_CLOCK_PLL_R - 1)<< RCC_PLLCFGR_PLLR_Pos) #endif #else -#if (CLOCK_PLL_R == 2) +#if (CONFIG_CLOCK_PLL_R == 2) #define PLL_R (0) -#elif (CLOCK_PLL_R == 4) +#elif (CONFIG_CLOCK_PLL_R == 4) #define PLL_R (RCC_PLLCFGR_PLLR_0) -#elif (CLOCK_PLL_R == 6) +#elif (CONFIG_CLOCK_PLL_R == 6) #define PLL_R (RCC_PLLCFGR_PLLR_1) -#elif (CLOCK_PLL_R == 8) +#elif (CONFIG_CLOCK_PLL_R == 8) #define PLL_R (RCC_PLLCFGR_PLLR_0 | RCC_PLLCFGR_PLLR_1) #else #error "PLL configuration: PLL R value is invalid" @@ -97,6 +86,88 @@ #endif /** @} */ +#if CONFIG_CLOCK_MSI == KHZ(100) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_0) +#elif CONFIG_CLOCK_MSI == KHZ(200) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_1) +#elif CONFIG_CLOCK_MSI == KHZ(400) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_2) +#elif CONFIG_CLOCK_MSI == KHZ(800) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_3) +#elif CONFIG_CLOCK_MSI == MHZ(1) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_4) +#elif CONFIG_CLOCK_MSI == MHZ(2) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_5) +#elif CONFIG_CLOCK_MSI == MHZ(4) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_6) +#elif CONFIG_CLOCK_MSI == MHZ(8) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_7) +#elif CONFIG_CLOCK_MSI == MHZ(16) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_8) +#elif CONFIG_CLOCK_MSI == MHZ(24) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_9) +#elif CONFIG_CLOCK_MSI == MHZ(32) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_10) +#elif CONFIG_CLOCK_MSI == MHZ(48) +#define CLOCK_MSIRANGE (RCC_CR_MSIRANGE_11) +#else +#error "Invalid MSI clock" +#endif + +#if defined(CPU_FAM_STM32WB) +#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 +#else /* CPU_FAM_STM32L4 */ +#define CLOCK_AHB_DIV (RCC_CFGR_HPRE_DIV1) + +#if CONFIG_CLOCK_APB1_DIV == 1 +#define CLOCK_APB1_DIV (RCC_CFGR_PPRE1_DIV1) +#elif CONFIG_CLOCK_APB1_DIV == 2 +#define CLOCK_APB1_DIV (RCC_CFGR_PPRE1_DIV1) +#elif CONFIG_CLOCK_APB1_DIV == 4 +#define CLOCK_APB1_DIV (RCC_CFGR_PPRE1_DIV4) +#elif CONFIG_CLOCK_APB1_DIV == 8 +#define CLOCK_APB1_DIV (RCC_CFGR_PPRE1_DIV8) +#elif CONFIG_CLOCK_APB1_DIV == 16 +#define CLOCK_APB1_DIV (RCC_CFGR_PPRE1_DIV16) +#endif + +#if CONFIG_CLOCK_APB2_DIV == 1 +#define CLOCK_APB2_DIV (RCC_CFGR_PPRE2_DIV1) +#elif CONFIG_CLOCK_APB2_DIV == 2 +#define CLOCK_APB2_DIV (RCC_CFGR_PPRE2_DIV1) +#elif CONFIG_CLOCK_APB2_DIV == 4 +#define CLOCK_APB2_DIV (RCC_CFGR_PPRE2_DIV4) +#elif CONFIG_CLOCK_APB2_DIV == 8 +#define CLOCK_APB2_DIV (RCC_CFGR_PPRE2_DIV8) +#elif CONFIG_CLOCK_APB2_DIV == 16 +#define CLOCK_APB2_DIV (RCC_CFGR_PPRE2_DIV16) +#endif +#endif /* CPU_FAM_STM32WB */ + /** * @name Deduct the needed flash wait states from the core clock frequency * @{ @@ -124,9 +195,9 @@ void stmclk_init_sysclk(void) stmclk_enable_hsi(); /* use HSI as system clock while we do any further configuration and - * configure the AHB and APB clock dividers as configure by the board */ - RCC->CFGR = (RCC_CFGR_SW_HSI | CLOCK_AHB_DIV | - CLOCK_APB1_DIV | CLOCK_APB2_DIV); + * 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); + #if defined(CPU_FAM_STM32WB) /* Use HSE/2 for radios systems */ RCC->EXTCFGR = (RCC_EXTCFGR_RFCSS | CLOCK_EXTAHB_DIV); @@ -151,50 +222,80 @@ void stmclk_init_sysclk(void) (instead of MSIRANGE in the RCC_CR) */ RCC->CR = (RCC_CR_HSION); -#if (CLOCK_HSE) - /* if configured, we need to enable the HSE clock now */ - RCC->CR |= (RCC_CR_HSEON); - while (!(RCC->CR & RCC_CR_HSERDY)) {} -#endif + if (CONFIG_USE_CLOCK_HSE) { + RCC->CR |= (RCC_CR_HSEON); + while (!(RCC->CR & RCC_CR_HSERDY)) {} -#if ((CLOCK_HSE == 0) || CLOCK_MSI_ENABLE) - /* reset clock to MSI with 48MHz, disables all other clocks */ + /* Select HSE as system clock and configure the different prescalers */ + RCC->CFGR &= ~RCC_CFGR_SW; + RCC->CFGR |= RCC_CFGR_SW_HSE; + } + else if (CONFIG_USE_CLOCK_MSI) { #if defined(CPU_FAM_STM32WB) - RCC->CR |= (RCC_CR_MSIRANGE_11 | RCC_CR_MSION); + RCC->CR |= (CLOCK_MSIRANGE | RCC_CR_MSION); #else - RCC->CR |= (RCC_CR_MSIRANGE_11 | RCC_CR_MSION | RCC_CR_MSIRGSEL); + RCC->CR |= (CLOCK_MSIRANGE | RCC_CR_MSION | RCC_CR_MSIRGSEL); #endif - while (!(RCC->CR & RCC_CR_MSIRDY)) {} - /* select the MSI clock for the 48MHz clock tree (USB, RNG) */ - RCC->CCIPR = (RCC_CCIPR_CLK48SEL_0 | RCC_CCIPR_CLK48SEL_1); -#if (CLOCK_MSI_LSE_PLL && CLOCK_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)) {} -#endif /* (CLOCK_MSI_LSE_PLL && CLOCK_LSE) */ -#endif /* ((CLOCK_HSE == 0) || CLOCK_MSI_ENABLE) */ + while (!(RCC->CR & RCC_CR_MSIRDY)) {} - /* now we can safely configure and start the PLL */ - RCC->PLLCFGR = (PLL_SRC | PLL_M | PLL_N | PLL_R | RCC_PLLCFGR_PLLREN); - RCC->CR |= (RCC_CR_PLLON); - while (!(RCC->CR & RCC_CR_PLLRDY)) {} + if (CONFIG_CLOCK_MSI == MHZ(48)) { + /* select the MSI clock for the 48MHz clock tree (USB, RNG) */ + RCC->CCIPR = (RCC_CCIPR_CLK48SEL_0 | RCC_CCIPR_CLK48SEL_1); + } + /* Select MSI as system clock and configure the different prescalers */ + RCC->CFGR = (RCC_CFGR_SW_MSI | CLOCK_AHB_DIV | CLOCK_APB1_DIV | CLOCK_APB2_DIV); + } + else if (CONFIG_USE_CLOCK_PLL) { + if (CONFIG_BOARD_HAS_HSE && CONFIG_CLOCK_PLL_SRC_HSE) { + /* if configured, we need to enable the HSE clock now */ + RCC->CR |= (RCC_CR_HSEON); + while (!(RCC->CR & RCC_CR_HSERDY)) {} + } - /* now that the PLL is running, we use it as system clock */ - RCC->CFGR |= RCC_CFGR_SW_PLL; - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) {} + if (CONFIG_CLOCK_PLL_SRC_MSI) { + /* reset clock to MSI with 48MHz, disables all other clocks */ +#if defined(CPU_FAM_STM32WB) + RCC->CR |= (CLOCK_MSIRANGE | RCC_CR_MSION); +#else + RCC->CR |= (CLOCK_MSIRANGE | RCC_CR_MSION | RCC_CR_MSIRGSEL); +#endif + while (!(RCC->CR & RCC_CR_MSIRDY)) {} + + if (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)) {} + } + + if (CONFIG_CLOCK_MSI == MHZ(48)) { + /* select the MSI clock for the 48MHz clock tree (USB, RNG) */ + RCC->CCIPR = (RCC_CCIPR_CLK48SEL_0 | RCC_CCIPR_CLK48SEL_1); + } + } + + /* now we can safely configure and start the PLL */ + RCC->PLLCFGR = (PLL_SRC | PLL_M | PLL_N | PLL_R | RCC_PLLCFGR_PLLREN); + RCC->CR |= (RCC_CR_PLLON); + while (!(RCC->CR & RCC_CR_PLLRDY)) {} + + /* now that the PLL is running, we use it as system clock */ + RCC->CFGR |= RCC_CFGR_SW_PLL; + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) {} + } stmclk_disable_hsi(); irq_restore(is); -#ifdef MODULE_PERIPH_RTT - /* Ensure LPTIM1 clock source (LSI or LSE) is correctly reset when initializing - the clock, this is particularly useful after waking up from deep sleep */ -#if CLOCK_LSE - RCC->CCIPR |= RCC_CCIPR_LPTIM1SEL_0 | RCC_CCIPR_LPTIM1SEL_1; -#else - RCC->CCIPR |= RCC_CCIPR_LPTIM1SEL_0; -#endif /* CLOCK_LSE */ -#endif /* MODULE_PERIPH_RTT */ + if (IS_USED(MODULE_PERIPH_RTT)) { + /* Ensure LPTIM1 clock source (LSI or LSE) is correctly reset when initializing + the clock, this is particularly useful after waking up from deep sleep */ + if (CONFIG_BOARD_HAS_LSE) { + RCC->CCIPR |= RCC_CCIPR_LPTIM1SEL_0 | RCC_CCIPR_LPTIM1SEL_1; + } + else { + RCC->CCIPR |= RCC_CCIPR_LPTIM1SEL_0; + } + } }