From a1038aa70e6d8aee102b140fe1c4cf53ef5c1fc5 Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Mon, 24 Aug 2020 08:26:02 +0200 Subject: [PATCH] cpu: boards: stm32g4: improve clock configuration --- .../stm32/include/g0/cfg_clock_default.h | 109 +++++++++++++---- .../stm32/include/g4/cfg_clock_default.h | 110 +++++++++++++----- boards/nucleo-g070rb/include/periph_conf.h | 6 + boards/nucleo-g474re/include/periph_conf.h | 13 +++ cpu/stm32/stmclk/stmclk_gx.c | 102 +++++++++++++--- 5 files changed, 271 insertions(+), 69 deletions(-) diff --git a/boards/common/stm32/include/g0/cfg_clock_default.h b/boards/common/stm32/include/g0/cfg_clock_default.h index 76da974a34..97df63dad6 100644 --- a/boards/common/stm32/include/g0/cfg_clock_default.h +++ b/boards/common/stm32/include/g0/cfg_clock_default.h @@ -35,41 +35,100 @@ extern "C" { * @{ */ /* Select the desired system clock source between PLL, HSE or HSI */ -#define CLOCK_USE_HSI (0) -#define CLOCK_USE_HSE (0) -#define CLOCK_USE_PLL (1) +#ifndef CONFIG_USE_CLOCK_PLL +#if IS_ACTIVE(CONFIG_USE_CLOCK_HSE) || IS_ACTIVE(CONFIG_USE_CLOCK_HSI) +#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_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_HSE || CONFIG_USE_CLOCK_HSI) +#error "Cannot use PLL as clock source with other clock configurations" +#endif + +#if CONFIG_USE_CLOCK_HSE && \ + (CONFIG_USE_CLOCK_PLL || 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_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 -#define CLOCK_HSI (16000000U) #ifndef CLOCK_HSE -#define CLOCK_HSE (0) +#define CLOCK_HSE MHZ(24) #endif -#ifndef CLOCK_LSE -#define CLOCK_LSE (1U) +#if CONFIG_BOARD_HAS_HSE && (CLOCK_HSE < MHZ(4) || CLOCK_HSE > MHZ(48)) +#error "HSE clock frequency must be between 4MHz and 48MHz" #endif -#if CLOCK_USE_HSI -#define CLOCK_CORECLOCK (CLOCK_HSI) +#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 -#elif CLOCK_USE_HSE -#define CLOCK_CORECLOCK (CLOCK_HSE) +#define CLOCK_HSI MHZ(16) -#elif CLOCK_USE_PLL +#if CONFIG_USE_CLOCK_HSI +#ifndef CONFIG_CLOCK_HSISYS_DIV +#define CONFIG_CLOCK_HSISYS_DIV (1) +#endif +#define CLOCK_CORECLOCK (CLOCK_HSI / CONFIG_CLOCK_HSISYS_DIV) + +#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_PLL /* The following parameters configure a 64MHz system clock with HSI as input clock */ -#define CLOCK_PLL_M (1) -#define CLOCK_PLL_N (20) -#define CLOCK_PLL_R (5) -#if CLOCK_HSE -#define CLOCK_PLL_SRC (CLOCK_HSE) -#else /* CLOCK_HSI */ -#define CLOCK_PLL_SRC (CLOCK_HSI) +#ifndef CONFIG_CLOCK_PLL_M +#define CONFIG_CLOCK_PLL_M (1) #endif -#define CLOCK_CORECLOCK ((CLOCK_PLL_SRC / CLOCK_PLL_M) * CLOCK_PLL_N) / CLOCK_PLL_R -#endif /* CLOCK_USE_PLL */ +#ifndef CONFIG_CLOCK_PLL_N +#define CONFIG_CLOCK_PLL_N (20) +#endif +#ifndef CONFIG_CLOCK_PLL_R +#define CONFIG_CLOCK_PLL_R (5) +#endif +#if CONFIG_BOARD_HAS_HSE +#define CLOCK_PLL_SRC (CLOCK_HSE) +#else /* CLOCK_HSI */ +#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 +#if CLOCK_CORECLOCK > MHZ(64) +#error "SYSCLK cannot exceed 64MHz" +#endif +#endif /* CONFIG_USE_CLOCK_PLL */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_0 -#define CLOCK_AHB (CLOCK_CORECLOCK / 1) /* max: 64MHz */ -#define CLOCK_APB1_DIV RCC_CFGR_PPRE_0 -#define CLOCK_APB1 (CLOCK_CORECLOCK / 1) /* max: 64MHz */ +#define CLOCK_AHB CLOCK_CORECLOCK /* max: 64MHz */ + +#ifndef CONFIG_CLOCK_APB1_DIV +#define CONFIG_CLOCK_APB1_DIV (1) +#endif +#define CLOCK_APB1 (CLOCK_CORECLOCK / CONFIG_CLOCK_APB1_DIV) /* max: 64MHz */ /** @} */ #ifdef __cplusplus diff --git a/boards/common/stm32/include/g4/cfg_clock_default.h b/boards/common/stm32/include/g4/cfg_clock_default.h index af258a87be..5235afae39 100644 --- a/boards/common/stm32/include/g4/cfg_clock_default.h +++ b/boards/common/stm32/include/g4/cfg_clock_default.h @@ -29,44 +29,100 @@ extern "C" { * @name Clock settings * @{ */ -#define CLOCK_USE_HSI (0) -#define CLOCK_USE_HSE (0) -#define CLOCK_USE_PLL (1) +#ifndef CONFIG_USE_CLOCK_PLL +#if IS_ACTIVE(CONFIG_USE_CLOCK_HSE) || IS_ACTIVE(CONFIG_USE_CLOCK_HSI) +#define CONFIG_USE_CLOCK_PLL (0) +#else +#define CONFIG_USE_CLOCK_PLL (1) /* Use PLL by default */ +#endif +#endif /* CONFIG_USE_CLOCK_PLL */ -#define CLOCK_HSI (16000000U) +#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_HSE || CONFIG_USE_CLOCK_HSI) +#error "Cannot use PLL as clock source with other clock configurations" +#endif + +#if CONFIG_USE_CLOCK_HSE && \ + (CONFIG_USE_CLOCK_PLL || 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_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 (24000000U) +#define CLOCK_HSE MHZ(24) #endif -#ifndef CLOCK_LSE -#define CLOCK_LSE (1U) +#if CONFIG_BOARD_HAS_HSE && (CLOCK_HSE < MHZ(4) || CLOCK_HSE > MHZ(48)) +#error "HSE clock frequency must be between 4MHz and 48MHz" #endif -#if CLOCK_USE_HSI -#define CLOCK_CORECLOCK (CLOCK_HSI) +#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 -#elif CLOCK_USE_HSE -#define CLOCK_CORECLOCK (CLOCK_HSE) +#define CLOCK_HSI MHZ(16) -#elif CLOCK_USE_PLL -/* The following parameters configure a 170MHz system clock with HSE as input clock */ -#define CLOCK_PLL_M (6) -#define CLOCK_PLL_N (85) -#define CLOCK_PLL_R (2) -#if CLOCK_HSE -#define CLOCK_PLL_SRC (CLOCK_HSE) +#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_PLL +/* The following parameters configure a 170MHz system clock with HSI16 as input clock */ +#ifndef CONFIG_CLOCK_PLL_M +#define CONFIG_CLOCK_PLL_M (4) +#endif +#ifndef CONFIG_CLOCK_PLL_N +#define CONFIG_CLOCK_PLL_N (85) +#endif +#ifndef CONFIG_CLOCK_PLL_R +#define CONFIG_CLOCK_PLL_R (2) +#endif +#if CONFIG_BOARD_HAS_HSE +#define CLOCK_PLL_SRC (CLOCK_HSE) #else /* CLOCK_HSI */ -#define CLOCK_PLL_SRC (CLOCK_HSI) +#define CLOCK_PLL_SRC (CLOCK_HSI) #endif -#define CLOCK_CORECLOCK ((CLOCK_PLL_SRC / CLOCK_PLL_M) * CLOCK_PLL_N) / CLOCK_PLL_R +#define CLOCK_CORECLOCK \ + ((CLOCK_PLL_SRC / CONFIG_CLOCK_PLL_M) * CONFIG_CLOCK_PLL_N) / CONFIG_CLOCK_PLL_R +#if CLOCK_CORECLOCK > MHZ(170) +#error "SYSCLK cannot exceed 170MHz" #endif +#endif /* CONFIG_USE_CLOCK_PLL */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 -#define CLOCK_AHB (CLOCK_CORECLOCK / 1) /* max 170MHz */ -#define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV1 -#define CLOCK_APB1 (CLOCK_CORECLOCK / 1) /* max 170MHz */ -#define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV1 -#define CLOCK_APB2 (CLOCK_CORECLOCK / 1) /* max 170MHz */ -/** @} */ +#define CLOCK_AHB CLOCK_CORECLOCK /* max: 170MHz */ + +#ifndef CONFIG_CLOCK_APB1_DIV +#define CONFIG_CLOCK_APB1_DIV (1) +#endif +#define CLOCK_APB1 (CLOCK_CORECLOCK / CONFIG_CLOCK_APB1_DIV) /* max: 170MHz */ +#ifndef CONFIG_CLOCK_APB2_DIV +#define CONFIG_CLOCK_APB2_DIV (1) +#endif +#define CLOCK_APB2 (CLOCK_CORECLOCK / CONFIG_CLOCK_APB2_DIV) /* max: 170MHz */ #ifdef __cplusplus } diff --git a/boards/nucleo-g070rb/include/periph_conf.h b/boards/nucleo-g070rb/include/periph_conf.h index f3f67897a0..064a8eb811 100644 --- a/boards/nucleo-g070rb/include/periph_conf.h +++ b/boards/nucleo-g070rb/include/periph_conf.h @@ -20,6 +20,12 @@ #define PERIPH_CONF_H #include "periph_cpu.h" + +/* Add specific clock configuration (HSE, LSE) for this board here */ +#ifndef CONFIG_BOARD_HAS_LSE +#define CONFIG_BOARD_HAS_LSE (1) +#endif + #include "g0/cfg_clock_default.h" #include "cfg_i2c1_pb8_pb9.h" #include "cfg_rtt_default.h" diff --git a/boards/nucleo-g474re/include/periph_conf.h b/boards/nucleo-g474re/include/periph_conf.h index 80c173dc14..d82bc1ccc1 100644 --- a/boards/nucleo-g474re/include/periph_conf.h +++ b/boards/nucleo-g474re/include/periph_conf.h @@ -19,6 +19,19 @@ #ifndef PERIPH_CONF_H #define PERIPH_CONF_H +/* Add specific clock configuration (HSE, LSE) for this board here */ +#ifndef CONFIG_BOARD_HAS_LSE +#define CONFIG_BOARD_HAS_LSE (1) +#endif +/* This board provides a 24MHz HSE oscillator */ +#ifndef CONFIG_BOARD_HAS_HSE +#define CONFIG_BOARD_HAS_HSE (1) +#endif +/* By default, configure a 80MHz SYSCLK with PLL using HSE as input clock */ +#ifndef CONFIG_CLOCK_PLL_M +#define CONFIG_CLOCK_PLL_M (6) +#endif + #include "periph_cpu.h" #include "g4/cfg_clock_default.h" #include "cfg_i2c1_pb8_pb9.h" diff --git a/cpu/stm32/stmclk/stmclk_gx.c b/cpu/stm32/stmclk/stmclk_gx.c index 396e53615f..ee221043c4 100644 --- a/cpu/stm32/stmclk/stmclk_gx.c +++ b/cpu/stm32/stmclk/stmclk_gx.c @@ -21,10 +21,6 @@ #include "stmclk.h" #include "periph_conf.h" -#if CLOCK_USE_HSE && CLOCK_HSE == 0 -#error "HSE is selected as input clock source but CLOCK_HSE is not set" -#endif - #if defined(CPU_FAM_STM32G0) #define PLL_M_MIN (1) #define PLL_M_MAX (8) @@ -41,28 +37,28 @@ #define PLL_R_MAX (8) #endif -#if CLOCK_USE_PLL -#if (CLOCK_PLL_M < PLL_M_MIN || CLOCK_PLL_M > PLL_M_MAX) +#if CONFIG_USE_CLOCK_PLL +#if (CONFIG_CLOCK_PLL_M < PLL_M_MIN || CONFIG_CLOCK_PLL_M > PLL_M_MAX) #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 < PLL_N_MIN || CLOCK_PLL_N > PLL_N_MAX) +#if (CONFIG_CLOCK_PLL_N < PLL_N_MIN || CONFIG_CLOCK_PLL_N > PLL_N_MAX) #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 (CLOCK_PLL_R < PLL_R_MIN || CLOCK_PLL_R > PLL_R_MAX) +#if (CONFIG_CLOCK_PLL_R < PLL_R_MIN || CONFIG_CLOCK_PLL_R > PLL_R_MAX) #error "PLL configuration: PLL R value is out of range" #endif #if defined(CPU_FAM_STM32G0) -#define PLL_R ((CLOCK_PLL_R - 1) << RCC_PLLCFGR_PLLR_Pos) +#define PLL_R ((CONFIG_CLOCK_PLL_R - 1) << RCC_PLLCFGR_PLLR_Pos) #else /* CPU_FAM_STM32G4 */ -#define PLL_R (((CLOCK_PLL_R >> 1) - 1) << RCC_PLLCFGR_PLLR_Pos) +#define PLL_R (((CONFIG_CLOCK_PLL_R >> 1) - 1) << RCC_PLLCFGR_PLLR_Pos) #endif -#if CLOCK_HSE +#if CONFIG_BOARD_HAS_HSE #define PLL_IN CLOCK_HSE #define PLL_SRC RCC_PLLCFGR_PLLSRC_HSE #else @@ -70,13 +66,75 @@ #define PLL_SRC RCC_PLLCFGR_PLLSRC_HSI #endif -#endif /* CLOCK_USE_PLL */ +#endif /* CONFIG_USE_CLOCK_PLL */ #if defined(CPU_FAM_STM32G0) #define RCC_CFGR_SW_HSI (0) #define RCC_CFGR_SW_HSE (RCC_CFGR_SW_0) #define RCC_CFGR_SW_PLL (RCC_CFGR_SW_1) + +#if CONFIG_USE_CLOCK_HSI +#if CONFIG_CLOCK_HSISYS_DIV == 1 +#define CLOCK_HSI_DIV (0) +#elif CONFIG_CLOCK_HSISYS_DIV == 2 +#define CLOCK_HSI_DIV (RCC_CR_HSIDIV_0) +#elif CONFIG_CLOCK_HSISYS_DIV == 4 +#define CLOCK_HSI_DIV (RCC_CR_HSIDIV_1) +#elif CONFIG_CLOCK_HSISYS_DIV == 8 +#define CLOCK_HSI_DIV (RCC_CR_HSIDIV_1 | RCC_CR_HSIDIV_0) +#elif CONFIG_CLOCK_HSISYS_DIV == 16 +#define CLOCK_HSI_DIV (RCC_CR_HSIDIV_2) +#elif CONFIG_CLOCK_HSISYS_DIV == 32 +#define CLOCK_HSI_DIV (RCC_CR_HSIDIV_2 | RCC_CR_HSIDIV_0) +#elif CONFIG_CLOCK_HSISYS_DIV == 64 +#define CLOCK_HSI_DIV (RCC_CR_HSIDIV_2 | RCC_CR_HSIDIV_1) +#elif CONFIG_CLOCK_HSISYS_DIV == 128 +#define CLOCK_HSI_DIV (RCC_CR_HSIDIV_2 | RCC_CR_HSIDIV_1 | RCC_CR_HSIDIV_0) #endif +#endif /* CONFIG_USE_CLOCK_HSI */ + +#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_PPRE_2) +#elif CONFIG_CLOCK_APB1_DIV == 4 +#define CLOCK_APB1_DIV (RCC_CFGR_PPRE_2 | RCC_CFGR_PPRE_0) +#elif CONFIG_CLOCK_APB1_DIV == 8 +#define CLOCK_APB1_DIV (RCC_CFGR_PPRE_2 | RCC_CFGR_PPRE_1) +#elif CONFIG_CLOCK_APB1_DIV == 16 +#define CLOCK_APB1_DIV (RCC_CFGR_PPRE_2 | RCC_CFGR_PPRE_1 | RCC_CFGR_PPRE_0) +#endif +#endif /* CPU_FAM_STM32G0 */ + +#if defined(CPU_FAM_STM32G4) +#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_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 +#endif /* CPU_FAM_STM32G4 */ /** Determine the required flash wait states from the core clock frequency */ #if defined(CPU_FAM_STM32G0) @@ -137,15 +195,25 @@ void stmclk_init_sysclk(void) stmclk_enable_lfclk(); #endif -#if CLOCK_USE_HSE +#if CONFIG_USE_CLOCK_HSI && defined(CPU_FAM_STM32G0) + /* configure HSISYS divider, only available on G0 */ + RCC->CR |= CLOCK_HSI_DIV; + while (!(RCC->CR & RCC_CR_HSIRDY)) {} + +#elif CONFIG_USE_CLOCK_HSE /* if configured, we need to enable the HSE clock now */ RCC->CR |= RCC_CR_HSEON; while (!(RCC->CR & RCC_CR_HSERDY)) {} +#if defined(CPU_FAM_STM32G0) + RCC->CFGR = (RCC_CFGR_SW_HSE | CLOCK_AHB_DIV | CLOCK_APB1_DIV); +#elif defined(CPU_FAM_STM32G4) RCC->CFGR = (RCC_CFGR_SW_HSE | CLOCK_AHB_DIV | CLOCK_APB1_DIV | CLOCK_APB2_DIV); +#endif while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSE) {} -#elif CLOCK_USE_PLL -#if CLOCK_HSE + +#elif 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)) {}