From 23117a844e95cece3738cc6f60abbf2ecfe279f6 Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Fri, 28 Aug 2020 18:35:52 +0200 Subject: [PATCH] boards: cpu: stm32l0: rework clock configuration --- .../stm32/include/l0/cfg_clock_default.h | 131 +++++++++-- .../stm32/include/l1/cfg_clock_default.h | 129 +++++++++-- cpu/stm32/stmclk/stmclk_l0l1.c | 219 +++++++++++++----- 3 files changed, 379 insertions(+), 100 deletions(-) diff --git a/boards/common/stm32/include/l0/cfg_clock_default.h b/boards/common/stm32/include/l0/cfg_clock_default.h index 76acb59e89..50eb7a8ea1 100644 --- a/boards/common/stm32/include/l0/cfg_clock_default.h +++ b/boards/common/stm32/include/l0/cfg_clock_default.h @@ -29,27 +29,122 @@ extern "C" { * @name Clock system configuration * @{ */ -#define CLOCK_HSI (16000000U) /* internal oscillator */ -#define CLOCK_CORECLOCK (32000000U) /* desired core clock frequency */ -#ifndef CLOCK_LSE -#define CLOCK_LSE (1) /* enable low speed external oscillator */ +/* Select the desired system clock source between PLL, HSE or HSI */ +#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 */ + +#ifndef CONFIG_USE_CLOCK_MSI +#define CONFIG_USE_CLOCK_MSI (0) +#endif /* CONFIG_USE_CLOCK_MSI */ + +#ifndef CONFIG_USE_CLOCK_HSE +#define CONFIG_USE_CLOCK_HSE (0) +#endif /* CONFIG_USE_CLOCK_HSE */ + +#ifndef CONFIG_USE_CLOCK_HSI +#define CONFIG_USE_CLOCK_HSI (0) +#endif /* CONFIG_USE_CLOCK_HSI */ + +#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 -/* configuration of PLL prescaler and multiply values */ -/* CORECLOCK := HSI / CLOCK_PLL_DIV * CLOCK_PLL_MUL */ -#define CLOCK_PLL_DIV RCC_CFGR_PLLDIV2 -#define CLOCK_PLL_MUL RCC_CFGR_PLLMUL4 -/* configuration of peripheral bus clock prescalers */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 /* AHB clock -> 32MHz */ -#define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV1 /* APB2 clock -> 32MHz */ -#define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV1 /* APB1 clock -> 32MHz */ -/* configuration of flash access cycles */ -#define CLOCK_FLASH_LATENCY FLASH_ACR_LATENCY +#if CONFIG_USE_CLOCK_MSI && \ + (CONFIG_USE_CLOCK_PLL || CONFIG_USE_CLOCK_HSE || CONFIG_USE_CLOCK_HSI) +#error "Cannot use MSI as clock source with other clock configurations" +#endif -/* bus clocks for simplified peripheral initialization, UPDATE MANUALLY! */ -#define CLOCK_AHB (CLOCK_CORECLOCK / 1) -#define CLOCK_APB2 (CLOCK_CORECLOCK / 1) -#define CLOCK_APB1 (CLOCK_CORECLOCK / 1) +#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(24) +#endif +#if CONFIG_BOARD_HAS_HSE && (CLOCK_HSE < MHZ(1) || CLOCK_HSE > MHZ(24)) +#error "HSE clock frequency must be between 1MHz and 24MHz" +#endif + +#ifndef CONFIG_CLOCK_HSI_USE_DIV4 +#define CONFIG_CLOCK_HSI_USE_DIV4 (0) +#endif + +#ifndef CONFIG_BOARD_HAS_LSE +#define CONFIG_BOARD_HAS_LSE (1) +#endif +#if CONFIG_BOARD_HAS_LSE +#define CLOCK_LSE (1) +#else +#define CLOCK_LSE (0) +#endif + +#define CLOCK_HSI MHZ(16) + +#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 +#ifndef CONFIG_CLOCK_MSI +#define CONFIG_CLOCK_MSI KHZ(4194) +#endif +#define CLOCK_CORECLOCK (CONFIG_CLOCK_MSI) + +#elif CONFIG_USE_CLOCK_PLL +/* The following parameters configure a 64MHz system clock with HSI as input clock */ +#ifndef CONFIG_CLOCK_PLL_DIV +#define CONFIG_CLOCK_PLL_DIV (2) +#endif +#ifndef CONFIG_CLOCK_PLL_MUL +#define CONFIG_CLOCK_PLL_MUL (4) +#endif +#if CONFIG_BOARD_HAS_HSE +#if CLOCK_HSE < MHZ(2) +#error "HSE must be greater than 2MHz when used as PLL input clock" +#endif +#define CLOCK_PLL_SRC (CLOCK_HSE) +#else /* CLOCK_HSI */ +#define CLOCK_PLL_SRC (CLOCK_HSI) +#endif +#endif /* CONFIG_BOARD_HAS_HSE */ +#define CLOCK_CORECLOCK ((CLOCK_PLL_SRC / CONFIG_CLOCK_PLL_DIV) * CONFIG_CLOCK_PLL_MUL) +#if CLOCK_CORECLOCK > MHZ(32) +#error "SYSCLK cannot exceed 32MHz" +#endif +#endif /* CONFIG_USE_CLOCK_PLL */ + +#define CLOCK_AHB CLOCK_CORECLOCK /* max: 32MHz */ + +#ifndef CONFIG_CLOCK_APB1_DIV +#define CONFIG_CLOCK_APB1_DIV (1) +#endif +#define CLOCK_APB1 (CLOCK_CORECLOCK / CONFIG_CLOCK_APB1_DIV) /* max: 32MHz */ +#ifndef CONFIG_CLOCK_APB2_DIV +#define CONFIG_CLOCK_APB2_DIV (1) +#endif +#define CLOCK_APB2 (CLOCK_CORECLOCK / CONFIG_CLOCK_APB2_DIV) /* max: 32MHz */ /** @} */ #ifdef __cplusplus diff --git a/boards/common/stm32/include/l1/cfg_clock_default.h b/boards/common/stm32/include/l1/cfg_clock_default.h index 5623deb3ed..9da55a11e1 100644 --- a/boards/common/stm32/include/l1/cfg_clock_default.h +++ b/boards/common/stm32/include/l1/cfg_clock_default.h @@ -29,28 +29,121 @@ extern "C" { * @name Clock system configuration * @{ */ -#define CLOCK_HSI (16000000U) /* internal oscillator */ -#define CLOCK_CORECLOCK (32000000U) /* desired core clock frequency */ +/* Select the desired system clock source between PLL, HSE or HSI */ +#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 */ -#ifndef CLOCK_LSE -#define CLOCK_LSE (0) /* disable low speed external oscillator */ +#ifndef CONFIG_USE_CLOCK_MSI +#define CONFIG_USE_CLOCK_MSI (0) +#endif /* CONFIG_USE_CLOCK_MSI */ + +#ifndef CONFIG_USE_CLOCK_HSE +#define CONFIG_USE_CLOCK_HSE (0) +#endif /* CONFIG_USE_CLOCK_HSE */ + +#ifndef CONFIG_USE_CLOCK_HSI +#define CONFIG_USE_CLOCK_HSI (0) +#endif /* CONFIG_USE_CLOCK_HSI */ + +#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 -/* configuration of PLL prescaler and multiply values */ -/* CORECLOCK := HSI / CLOCK_PLL_DIV * CLOCK_PLL_MUL */ -#define CLOCK_PLL_DIV RCC_CFGR_PLLDIV2 -#define CLOCK_PLL_MUL RCC_CFGR_PLLMUL4 -/* configuration of peripheral bus clock prescalers */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 /* AHB clock -> 32MHz */ -#define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV1 /* APB2 clock -> 32MHz */ -#define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV1 /* APB1 clock -> 32MHz */ -/* configuration of flash access cycles */ -#define CLOCK_FLASH_LATENCY FLASH_ACR_LATENCY +#if CONFIG_USE_CLOCK_MSI && \ + (CONFIG_USE_CLOCK_PLL || CONFIG_USE_CLOCK_HSE || CONFIG_USE_CLOCK_HSI) +#error "Cannot use MSI as clock source with other clock configurations" +#endif -/* bus clocks for simplified peripheral initialization, UPDATE MANUALLY! */ -#define CLOCK_AHB (CLOCK_CORECLOCK / 1) -#define CLOCK_APB2 (CLOCK_CORECLOCK / 1) -#define CLOCK_APB1 (CLOCK_CORECLOCK / 1) +#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(24) +#endif +#if CONFIG_BOARD_HAS_HSE && (CLOCK_HSE < MHZ(1) || CLOCK_HSE > MHZ(24)) +#error "HSE clock frequency must be between 1MHz and 24MHz" +#endif + +#ifndef CONFIG_CLOCK_HSI_USE_DIV4 +#define CONFIG_CLOCK_HSI_USE_DIV4 (0) +#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) + +#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 +#ifndef CONFIG_CLOCK_MSI +#define CONFIG_CLOCK_MSI KHZ(4194) +#endif +#define CLOCK_CORECLOCK (CONFIG_CLOCK_MSI) + +#elif CONFIG_USE_CLOCK_PLL +/* The following parameters configure a 64MHz system clock with HSI as input clock */ +#ifndef CONFIG_CLOCK_PLL_DIV +#define CONFIG_CLOCK_PLL_DIV (2) +#endif +#ifndef CONFIG_CLOCK_PLL_MUL +#define CONFIG_CLOCK_PLL_MUL (4) +#endif +#if CONFIG_BOARD_HAS_HSE +#if CLOCK_HSE < MHZ(2) +#error "HSE must be greater than 2MHz when used as PLL input clock" +#endif +#define CLOCK_PLL_SRC (CLOCK_HSE) +#else /* CLOCK_HSI */ +#define CLOCK_PLL_SRC (CLOCK_HSI) +#endif /* CONFIG_BOARD_HAS_HSE */ +#define CLOCK_CORECLOCK ((CLOCK_PLL_SRC / CONFIG_CLOCK_PLL_DIV) * CONFIG_CLOCK_PLL_MUL) +#if CLOCK_CORECLOCK > MHZ(32) +#error "SYSCLK cannot exceed 32MHz" +#endif +#endif /* CONFIG_USE_CLOCK_PLL */ + +#define CLOCK_AHB CLOCK_CORECLOCK /* max: 32MHz */ + +#ifndef CONFIG_CLOCK_APB1_DIV +#define CONFIG_CLOCK_APB1_DIV (1) +#endif +#define CLOCK_APB1 (CLOCK_CORECLOCK / CONFIG_CLOCK_APB1_DIV) /* max: 32MHz */ +#ifndef CONFIG_CLOCK_APB2_DIV +#define CONFIG_CLOCK_APB2_DIV (1) +#endif +#define CLOCK_APB2 (CLOCK_CORECLOCK / CONFIG_CLOCK_APB2_DIV) /* max: 32MHz */ /** @} */ #ifdef __cplusplus diff --git a/cpu/stm32/stmclk/stmclk_l0l1.c b/cpu/stm32/stmclk/stmclk_l0l1.c index c353237111..876631d128 100644 --- a/cpu/stm32/stmclk/stmclk_l0l1.c +++ b/cpu/stm32/stmclk/stmclk_l0l1.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2014 Freie Universität Berlin - * 2017 Inria + * 2017-2020 Inria * 2018 Kaspar Schleiser * * This file is subject to the terms and conditions of the GNU Lesser @@ -22,67 +22,127 @@ */ #include "cpu.h" -#include "board.h" +#include "stmclk.h" #include "periph_conf.h" -#include "periph/init.h" + +#if defined(CPU_FAM_STM32L1) +#define REG_CIR (RCC->CIR) +#else /* CPU_FAM_STM32L0 */ +#define REG_CIR (RCC->CICR) +#endif + +/* configuration of flash access cycles */ +#define CLOCK_FLASH_LATENCY (FLASH_ACR_LATENCY) + +/* Configure the prescalers */ +#define CLOCK_AHB_DIV (RCC_CFGR_HPRE_DIV1) /* HCLK = SYSCLK */ + +#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_DIV2) +#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_DIV2) +#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 /* Check the source to be used for the PLL */ -#if defined(CLOCK_HSI) && defined(CLOCK_HSE) -#error "Only provide one of two CLOCK_HSI/CLOCK_HSE" -#elif CLOCK_HSI -#define CLOCK_CR_SOURCE RCC_CR_HSION -#define CLOCK_CR_SOURCE_RDY RCC_CR_HSIRDY -#define CLOCK_PLL_SOURCE RCC_CFGR_PLLSRC_HSI -#elif CLOCK_HSE -#define CLOCK_CR_SOURCE RCC_CR_HSEON -#define CLOCK_CR_SOURCE_RDY RCC_CR_HSERDY -#define CLOCK_PLL_SOURCE RCC_CFGR_PLLSRC_HSE +#if CONFIG_BOARD_HAS_HSE +#define CLOCK_PLL_SOURCE (RCC_CFGR_PLLSRC_HSE) +#else /* Use HSI as PLL input */ +#define CLOCK_PLL_SOURCE (RCC_CFGR_PLLSRC_HSI) +#endif + +#if CONFIG_CLOCK_PLL_DIV == 2 +#define CLOCK_PLL_DIV (RCC_CFGR_PLLDIV2) +#elif CONFIG_CLOCK_PLL_DIV == 3 +#define CLOCK_PLL_DIV (RCC_CFGR_PLLDIV3) +#elif CONFIG_CLOCK_PLL_DIV == 4 +#define CLOCK_PLL_DIV (RCC_CFGR_PLLDIV4) #else -#error "Please provide CLOCK_HSI or CLOCK_HSE in boards/NAME/includes/perhip_cpu.h" +#error "Invalid PLL DIV value, only 2, 3, and 4 values are allowed." +#endif + +#if CONFIG_CLOCK_PLL_MUL == 3 +#define CLOCK_PLL_MUL (RCC_CFGR_PLLMUL3) +#elif CONFIG_CLOCK_PLL_MUL == 4 +#define CLOCK_PLL_MUL (RCC_CFGR_PLLMUL4) +#elif CONFIG_CLOCK_PLL_MUL == 6 +#define CLOCK_PLL_MUL (RCC_CFGR_PLLMUL6) +#elif CONFIG_CLOCK_PLL_MUL == 8 +#define CLOCK_PLL_MUL (RCC_CFGR_PLLMUL8) +#elif CONFIG_CLOCK_PLL_MUL == 12 +#define CLOCK_PLL_MUL (RCC_CFGR_PLLMUL12) +#elif CONFIG_CLOCK_PLL_MUL == 16 +#define CLOCK_PLL_MUL (RCC_CFGR_PLLMUL16) +#elif CONFIG_CLOCK_PLL_MUL == 24 +#define CLOCK_PLL_MUL (RCC_CFGR_PLLMUL24) +#elif CONFIG_CLOCK_PLL_MUL == 32 +#define CLOCK_PLL_MUL (RCC_CFGR_PLLMUL32) +#elif CONFIG_CLOCK_PLL_MUL == 48 +#define CLOCK_PLL_MUL (RCC_CFGR_PLLMUL48) +#else +#error "Invalid PLL MUL value, only 3, 4, 6, 8, 12, 16, 24, 32 and 48 values are allowed." +#endif + +#if CONFIG_CLOCK_MSI == 65536UL +#define CLOCK_MSIRANGE (RCC_ICSCR_MSIRANGE_0) +#elif CONFIG_CLOCK_MSI == 131072UL +#define CLOCK_MSIRANGE (RCC_ICSCR_MSIRANGE_1) +#elif CONFIG_CLOCK_MSI == 262144UL +#define CLOCK_MSIRANGE (RCC_ICSCR_MSIRANGE_2) +#elif CONFIG_CLOCK_MSI == 524288UL +#define CLOCK_MSIRANGE (RCC_ICSCR_MSIRANGE_3) +#elif CONFIG_CLOCK_MSI == KHZ(1048) +#define CLOCK_MSIRANGE (RCC_ICSCR_MSIRANGE_4) +#elif CONFIG_CLOCK_MSI == KHZ(2097) +#define CLOCK_MSIRANGE (RCC_ICSCR_MSIRANGE_5) +#elif CONFIG_CLOCK_MSI == KHZ(4194) +#define CLOCK_MSIRANGE (RCC_ICSCR_MSIRANGE_6) +#else +#error "Invalid MSI clock value" #endif /** * @brief Configure the controllers clock system * - * The clock initialization make the following assumptions: - * - the external HSE clock from an external oscillator is used as base clock - * - the internal PLL circuit is used for clock refinement - * - * Use the following formulas to calculate the needed values: - * - * SYSCLK = ((HSE_VALUE / CLOCK_PLL_M) * CLOCK_PLL_N) / CLOCK_PLL_P - * USB, SDIO and RNG Clock = ((HSE_VALUE / CLOCK_PLL_M) * CLOCK_PLL_N) / CLOCK_PLL_Q - * - * The actual used values are specified in the board's `periph_conf.h` file. - * - * NOTE: currently there is not timeout for initialization of PLL and other locks + * NOTE: currently there is no timeout for initialization of PLL and other locks * -> when wrong values are chosen, the initialization could stall */ void stmclk_init_sysclk(void) { - /* Reset the RCC clock configuration to the default reset state(for debug purpose) */ - /* Set MSION bit */ - RCC->CR |= RCC_CR_MSION; - /* Reset SW, HPRE, PPRE1, PPRE2, MCOSEL and MCOPRE bits */ - RCC->CFGR &= ~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLDIV | RCC_CFGR_PLLMUL); - /* Reset HSION, HSEON, CSSON and PLLON bits */ - RCC->CR &= ~(RCC_CR_HSION | RCC_CR_HSEON | RCC_CR_HSEBYP | RCC_CR_CSSON | RCC_CR_PLLON); + /* disable any interrupts. Global interrupts could be enabled if this is + * called from some kind of bootloader... */ + unsigned is = irq_disable(); /* Disable all interrupts */ + REG_CIR = 0x0; -#if defined(CPU_FAM_STM32L0) - RCC->CICR = 0x0; -#elif defined(CPU_FAM_STM32L1) - RCC->CIR = 0x0; -#else -#error unexpected MCU -#endif + /* enable HSI clock for the duration of initialization */ + stmclk_enable_hsi(); + + /* Reset the RCC clock configuration to the default reset state(for debug purpose) */ + /* Reset MSION, HSEON, CSSON and PLLON bits */ + RCC->CR &= ~(RCC_CR_MSION | RCC_CR_HSEON | RCC_CR_HSEBYP | RCC_CR_CSSON | RCC_CR_PLLON); + + /* 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); - /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration */ - /* Enable high speed clock source */ - RCC->CR |= CLOCK_CR_SOURCE; - /* Wait till the high speed clock source is ready - * NOTE: the MCU will stay here forever if you use an external clock source and it's not connected */ - while (!(RCC->CR & CLOCK_CR_SOURCE_RDY)) {} #if defined(CPU_FAM_STM32L1) FLASH->ACR |= FLASH_ACR_ACC64; #endif @@ -94,22 +154,53 @@ void stmclk_init_sysclk(void) PWR->CR = PWR_CR_VOS_0; /* Wait Until the Voltage Regulator is ready */ while((PWR->CSR & PWR_CSR_VOSF) != 0) {} - /* HCLK = SYSCLK */ - RCC->CFGR |= (uint32_t)CLOCK_AHB_DIV; - /* PCLK2 = HCLK */ - RCC->CFGR |= (uint32_t)CLOCK_APB2_DIV; - /* PCLK1 = HCLK */ - RCC->CFGR |= (uint32_t)CLOCK_APB1_DIV; - /* PLL configuration: PLLCLK = CLOCK_SOURCE / PLL_DIV * PLL_MUL */ - RCC->CFGR &= ~((uint32_t)(RCC_CFGR_PLLSRC | RCC_CFGR_PLLDIV | RCC_CFGR_PLLMUL)); - RCC->CFGR |= (uint32_t)(CLOCK_PLL_SOURCE | CLOCK_PLL_DIV | CLOCK_PLL_MUL); - /* Enable PLL */ - RCC->CR |= RCC_CR_PLLON; - /* Wait till PLL is ready */ - while ((RCC->CR & RCC_CR_PLLRDY) == 0) {} - /* Select PLL as system clock source */ - RCC->CFGR &= ~((uint32_t)(RCC_CFGR_SW)); - RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; - /* Wait till PLL is used as system clock source */ - while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) {} + + if (CONFIG_USE_CLOCK_HSE) { + /* Enable the HSE clock now */ + RCC->CR |= (RCC_CR_HSEON); + while (!(RCC->CR & RCC_CR_HSERDY)) {} + + /* 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) { + /* Configure MSI range and enable it */ + RCC->ICSCR |= CLOCK_MSIRANGE; + RCC->CR |= (RCC_CR_MSION); + while (!(RCC->CR & RCC_CR_MSIRDY)) {} + + /* Select MSI as system clock and configure the different prescalers */ + RCC->CFGR &= ~(RCC_CFGR_SW); + RCC->CFGR |= RCC_CFGR_SW_MSI; + } + else if (CONFIG_USE_CLOCK_PLL) { + if (CONFIG_BOARD_HAS_HSE) { + /* if configured, we need to enable the HSE clock now */ + RCC->CR |= (RCC_CR_HSEON); + while (!(RCC->CR & RCC_CR_HSERDY)) {} + } + + /* Configure PLL clock source and configure the different prescalers */ + RCC->CFGR &= ~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLDIV | RCC_CFGR_PLLMUL); + RCC->CFGR |= (CLOCK_PLL_SOURCE | CLOCK_PLL_DIV | CLOCK_PLL_MUL); + /* Enable PLL */ + RCC->CR |= RCC_CR_PLLON; + /* Wait till PLL is ready */ + while (!(RCC->CR & RCC_CR_PLLRDY)) {} + + /* Select PLL as system clock source */ + RCC->CFGR &= ~((uint32_t)(RCC_CFGR_SW)); + RCC->CFGR |= RCC_CFGR_SW_PLL; + /* Wait till PLL is used as system clock source */ + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) {} + } + + if (!IS_ACTIVE(CONFIG_USE_CLOCK_HSI) || + (IS_ACTIVE(CONFIG_USE_CLOCK_PLL) && IS_ACTIVE(CONFIG_BOARD_HAS_HSE))) { + /* Disable HSI only if not used */ + stmclk_disable_hsi(); + } + + irq_restore(is); }