diff --git a/boards/b-l475e-iot01a/include/periph_conf.h b/boards/b-l475e-iot01a/include/periph_conf.h index e975a8af10..46b8d94ba0 100644 --- a/boards/b-l475e-iot01a/include/periph_conf.h +++ b/boards/b-l475e-iot01a/include/periph_conf.h @@ -19,8 +19,13 @@ #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 + #include "periph_cpu.h" -#include "l4/cfg_clock_80_1.h" +#include "l4/cfg_clock_default.h" #include "cfg_rtt_default.h" #ifdef __cplusplus diff --git a/boards/common/stm32/include/l4/cfg_clock_80_1.h b/boards/common/stm32/include/l4/cfg_clock_80_1.h deleted file mode 100644 index 127906d645..0000000000 --- a/boards/common/stm32/include/l4/cfg_clock_80_1.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2017 Freie Universität Berlin - * 2019 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 boards_common_stm32 - * @{ - * - * @file - * @brief Configure STM32L4 clock using 80MHz core clock and LSE (32.768kHz) - * - * @author Hauke Petersen - * @author Alexandre Abadie - */ - -#ifndef L4_CFG_CLOCK_80_1_H -#define L4_CFG_CLOCK_80_1_H - -#include "periph_cpu.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @name Clock system configuration - * @{ - */ -/* 0: no external high speed crystal available - * else: actual crystal frequency [in Hz] */ -#define CLOCK_HSE (0) - -/* 0: no external low speed crystal available, - * 1: external crystal available (always 32.768kHz) - */ -#define CLOCK_LSE (1) - -/* 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) - -/* 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) - -/* 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) -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* L4_CFG_CLOCK_80_1_H */ -/** @} */ diff --git a/boards/common/stm32/include/l4/cfg_clock_default.h b/boards/common/stm32/include/l4/cfg_clock_default.h new file mode 100644 index 0000000000..68d28e9b4b --- /dev/null +++ b/boards/common/stm32/include/l4/cfg_clock_default.h @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2017 Freie Universität Berlin + * 2019 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 boards_common_stm32 + * @{ + * + * @file + * @brief Default STM32L4 clock configuration + * + * @author Hauke Petersen + * @author Alexandre Abadie + */ + +#ifndef L4_CFG_CLOCK_DEFAULT_H +#define L4_CFG_CLOCK_DEFAULT_H + +#include "periph_cpu.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Clock system configuration + * @{ + */ +#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 IS_ACTIVE(CONFIG_USE_CLOCK_PLL) && \ + (IS_ACTIVE(CONFIG_USE_CLOCK_MSI) || IS_ACTIVE(CONFIG_USE_CLOCK_HSE) || \ + IS_ACTIVE(CONFIG_USE_CLOCK_HSI)) +#error "Cannot use PLL as clock source with other clock configurations" +#endif + +#if IS_ACTIVE(CONFIG_USE_CLOCK_MSI) && \ + (IS_ACTIVE(CONFIG_USE_CLOCK_PLL) || IS_ACTIVE(CONFIG_USE_CLOCK_HSI) || \ + IS_ACTIVE(CONFIG_USE_CLOCK_HSE)) +#error "Cannot use MSI as clock source with other clock configurations" +#endif + +#if IS_ACTIVE(CONFIG_USE_CLOCK_HSE) && \ + (IS_ACTIVE(CONFIG_USE_CLOCK_PLL) || IS_ACTIVE(CONFIG_USE_CLOCK_MSI) || \ + IS_ACTIVE(CONFIG_USE_CLOCK_HSI)) +#error "Cannot use HSE as clock source with other clock configurations" +#endif + +#if IS_ACTIVE(CONFIG_USE_CLOCK_HSI) && \ + (IS_ACTIVE(CONFIG_USE_CLOCK_PLL) || IS_ACTIVE(CONFIG_USE_CLOCK_MSI) || \ + IS_ACTIVE(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 IS_ACTIVE(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 IS_ACTIVE(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) || \ + IS_ACTIVE(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 IS_ACTIVE(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 IS_ACTIVE(CONFIG_USE_CLOCK_HSI) +#define CLOCK_CORECLOCK (CLOCK_HSI) + +#elif IS_ACTIVE(CONFIG_USE_CLOCK_HSE) +#if !IS_ACTIVE(CONFIG_BOARD_HAS_HSE) +#error "The board doesn't provide an HSE oscillator" +#endif +#define CLOCK_CORECLOCK (CLOCK_HSE) + +#elif IS_ACTIVE(CONFIG_USE_CLOCK_MSI) +#define CLOCK_CORECLOCK (CONFIG_CLOCK_MSI) + +#elif IS_ACTIVE(CONFIG_USE_CLOCK_PLL) +#if IS_ACTIVE(CONFIG_CLOCK_PLL_SRC_MSI) +#define CLOCK_PLL_SRC (CONFIG_CLOCK_MSI) +#elif IS_ACTIVE(CONFIG_CLOCK_PLL_SRC_HSE) +#define CLOCK_PLL_SRC (CLOCK_HSE) +#else /* CONFIG_CLOCK_PLL_SRC_ */ +#define CLOCK_PLL_SRC (CLOCK_HSI) +#endif +/* PLL configuration: make sure your values are legit! + * + * compute by: CORECLOCK = (((PLL_IN / M) * N) / R) + * with: + * PLL_IN: input clock, HSE or MSI + * M: pre-divider, allowed range: [1:8] + * N: multiplier, allowed range: [8:86] + * R: post-divider, allowed range: [2:8] + * + * Also the following constraints need to be met: + * (PLL_IN / M) -> [4MHz:16MHz] + * (PLL_IN / M) * N -> [64MHz:344MHz] + * CORECLOCK -> 64MHz, 80MHZ or 120MHz MAX! + */ +#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 /* HCLK, max: 64/80/120MHz */ + +#ifndef CONFIG_CLOCK_APB1_DIV +#define CONFIG_CLOCK_APB1_DIV (4) +#endif +#define CLOCK_APB1 (CLOCK_AHB / CONFIG_CLOCK_APB1_DIV) /* PCLK1, max: 64/80/120MHz */ +#ifndef CONFIG_CLOCK_APB2_DIV +#define CONFIG_CLOCK_APB2_DIV (2) +#endif +#define CLOCK_APB2 (CLOCK_AHB / CONFIG_CLOCK_APB2_DIV) /* PCLK1, max: 64/80/120MHz */ + +#ifdef __cplusplus +} +#endif + +#endif /* L4_CFG_CLOCK_DEFAULT_H */ +/** @} */ diff --git a/boards/nucleo-l412kb/include/periph_conf.h b/boards/nucleo-l412kb/include/periph_conf.h index 074d4cdf3c..59f7f4a1af 100644 --- a/boards/nucleo-l412kb/include/periph_conf.h +++ b/boards/nucleo-l412kb/include/periph_conf.h @@ -23,8 +23,13 @@ #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 + #include "periph_cpu.h" -#include "l4/cfg_clock_80_1.h" +#include "l4/cfg_clock_default.h" #include "cfg_i2c1_pb6_pb7.h" #include "cfg_timer_tim2.h" #include "cfg_rtt_default.h" diff --git a/boards/nucleo-l432kc/include/periph_conf.h b/boards/nucleo-l432kc/include/periph_conf.h index 7630af0909..341140dfd4 100644 --- a/boards/nucleo-l432kc/include/periph_conf.h +++ b/boards/nucleo-l432kc/include/periph_conf.h @@ -21,8 +21,13 @@ #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 + #include "periph_cpu.h" -#include "l4/cfg_clock_80_1.h" +#include "l4/cfg_clock_default.h" #include "cfg_i2c1_pb6_pb7.h" #include "cfg_rtt_default.h" #include "cfg_timer_tim2.h" diff --git a/boards/nucleo-l433rc/include/periph_conf.h b/boards/nucleo-l433rc/include/periph_conf.h index 3f1a401a9b..32ae46860a 100644 --- a/boards/nucleo-l433rc/include/periph_conf.h +++ b/boards/nucleo-l433rc/include/periph_conf.h @@ -19,8 +19,13 @@ #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 + #include "periph_cpu.h" -#include "l4/cfg_clock_80_1.h" +#include "l4/cfg_clock_default.h" #include "cfg_rtt_default.h" #include "cfg_timer_tim2.h" diff --git a/boards/nucleo-l452re/include/periph_conf.h b/boards/nucleo-l452re/include/periph_conf.h index 639e788e5b..87e7883f39 100644 --- a/boards/nucleo-l452re/include/periph_conf.h +++ b/boards/nucleo-l452re/include/periph_conf.h @@ -25,8 +25,13 @@ #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 + #include "periph_cpu.h" -#include "l4/cfg_clock_80_1.h" +#include "l4/cfg_clock_default.h" #include "cfg_i2c1_pb8_pb9.h" #include "cfg_rtt_default.h" #include "cfg_timer_tim2.h" diff --git a/boards/nucleo-l476rg/include/periph_conf.h b/boards/nucleo-l476rg/include/periph_conf.h index e781c5593f..5efcf1d4e0 100644 --- a/boards/nucleo-l476rg/include/periph_conf.h +++ b/boards/nucleo-l476rg/include/periph_conf.h @@ -23,8 +23,13 @@ #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 + #include "periph_cpu.h" -#include "l4/cfg_clock_80_1.h" +#include "l4/cfg_clock_default.h" #include "cfg_i2c1_pb8_pb9.h" #include "cfg_rtt_default.h" diff --git a/boards/nucleo-l496zg/include/periph_conf.h b/boards/nucleo-l496zg/include/periph_conf.h index 9f8b8aa717..990e12f5f5 100644 --- a/boards/nucleo-l496zg/include/periph_conf.h +++ b/boards/nucleo-l496zg/include/periph_conf.h @@ -19,8 +19,13 @@ #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 + #include "periph_cpu.h" -#include "l4/cfg_clock_80_1.h" +#include "l4/cfg_clock_default.h" #include "cfg_i2c1_pb8_pb9.h" #include "cfg_rtt_default.h" diff --git a/boards/nucleo-l4r5zi/include/periph_conf.h b/boards/nucleo-l4r5zi/include/periph_conf.h index 05f72776b4..d7f8ac8ed8 100644 --- a/boards/nucleo-l4r5zi/include/periph_conf.h +++ b/boards/nucleo-l4r5zi/include/periph_conf.h @@ -20,6 +20,19 @@ #define PERIPH_CONF_H #include "periph_cpu.h" + +/* Add specific clock configuration (HSE, LSE) for this board here */ +#define CLOCK_CORECLOCK_MAX MHZ(120) + +#ifndef CONFIG_BOARD_HAS_LSE +#define CONFIG_BOARD_HAS_LSE 1 +#endif + +#ifndef CONFIG_CLOCK_PLL_N +#define CONFIG_CLOCK_PLL_N (30) +#endif + +#include "l4/cfg_clock_default.h" #include "cfg_i2c1_pb8_pb9.h" #include "cfg_rtt_default.h" @@ -27,47 +40,6 @@ extern "C" { #endif -/** - * @name Clock system configuration - * @{ - */ -/* 0: no external high speed crystal available - * else: actual crystal frequency [in Hz] */ -#define CLOCK_HSE (0) - -#ifndef CLOCK_LSE -/* 0: no external low speed crystal available, - * 1: external crystal available (always 32.768kHz) */ -#define CLOCK_LSE (1) -#endif - -/* 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 CLOCK_MSI_LSE_PLL -/* 0: disable Hardware auto calibration with LSE - * 1: enable Hardware auto calibration with LSE (PLL-mode) - * Same as with CLOCK_LSE above this defaults to 0 because LSE is - * mandatory for MSI/LSE-trimming to work */ -#define CLOCK_MSI_LSE_PLL (0) -#endif - -/* give the target core clock (HCLK) frequency [in Hz], maximum: 120MHz */ -#define CLOCK_CORECLOCK (120000000U) -/* PLL configuration: make sure your values are legit! */ -#define CLOCK_PLL_M (6) -#define CLOCK_PLL_N (30) -#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) -/** @} */ - /** * @name Timer configuration * @{ diff --git a/boards/p-l496g-cell02/include/periph_conf.h b/boards/p-l496g-cell02/include/periph_conf.h index fc0428c14f..9f5061acfc 100644 --- a/boards/p-l496g-cell02/include/periph_conf.h +++ b/boards/p-l496g-cell02/include/periph_conf.h @@ -19,8 +19,13 @@ #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 + #include "periph_cpu.h" -#include "l4/cfg_clock_80_1.h" +#include "l4/cfg_clock_default.h" #include "cfg_rtt_default.h" #include "cfg_timer_tim2.h" diff --git a/boards/p-nucleo-wb55/include/periph_conf.h b/boards/p-nucleo-wb55/include/periph_conf.h index 471ce7632b..b73c07fed5 100644 --- a/boards/p-nucleo-wb55/include/periph_conf.h +++ b/boards/p-nucleo-wb55/include/periph_conf.h @@ -21,6 +21,30 @@ #define PERIPH_CONF_H #include "periph_cpu.h" + +/* Add specific clock configuration (HSE, LSE) for this board here */ +#define CLOCK_CORECLOCK_MAX MHZ(64) + +#ifndef CONFIG_BOARD_HAS_LSE +#define CONFIG_BOARD_HAS_LSE 1 +#endif + +#ifndef CONFIG_BOARD_HAS_HSE +#define CONFIG_BOARD_HAS_HSE 1 +#endif + +#define CLOCK_HSE MHZ(32) + +#ifndef CONFIG_CLOCK_PLL_M +#define CONFIG_CLOCK_PLL_M (5) +#endif + +/* EXTAHB (HCLK2) max freq 32 Mhz*/ +#define CLOCK_EXTAHB_DIV RCC_EXTCFGR_C2HPRE_3 +#define CLOCK_EXTAHB (CLOCK_CORECLOCK / 2) + +#include "l4/cfg_clock_default.h" + #include "cfg_i2c1_pb8_pb9.h" #include "cfg_rtt_default.h" #include "cfg_timer_tim2.h" @@ -29,64 +53,6 @@ extern "C" { #endif -/** - * @name Clock system configuration - * @{ - */ -/* 0: no external high speed crystal available - * else: actual crystal frequency [in Hz] */ -#define CLOCK_HSE (32000000U) - -#ifndef CLOCK_LSE -/* 0: no external low speed crystal available, - * 1: external crystal available (always 32.768kHz) - */ -#define CLOCK_LSE (1) -#endif - -/* 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 CLOCK_MSI_LSE_PLL -/* 0: disable Hardware auto calibration with LSE - * 1: enable Hardware auto calibration with LSE (PLL-mode) - */ -#define CLOCK_MSI_LSE_PLL (1) -#endif - -/* give the target core clock (HCLK) frequency [in Hz], maximum: 64MHz */ -#define CLOCK_CORECLOCK (64000000U) -/* 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:8] - * - * Also the following constraints need to be met: - * (PLL_IN / M) -> [4MHz:16MHz] - * (PLL_IN / M) * N -> [64MHz:344MHz] - * CORECLOCK -> 64MHz MAX! - */ -#define CLOCK_PLL_M (4) -#define CLOCK_PLL_N (32) -#define CLOCK_PLL_R (4) - -/* EXTAHB (HCLK2) max freq 32 Mhz*/ -#define CLOCK_EXTAHB_DIV RCC_EXTCFGR_C2HPRE_3 -#define CLOCK_EXTAHB (CLOCK_CORECLOCK / 2) -/* peripheral clock setup */ -#define CLOCK_AHB_DIV 0x00000000U -#define CLOCK_AHB (CLOCK_CORECLOCK / 1) -#define CLOCK_APB1_DIV 0x00000000U -#define CLOCK_APB1 (CLOCK_CORECLOCK / 1) -#define CLOCK_APB2_DIV 0x00000000U -#define CLOCK_APB2 (CLOCK_CORECLOCK / 1) -/** @} */ - /** * @name UART configuration * @{ diff --git a/boards/stm32l476g-disco/include/periph_conf.h b/boards/stm32l476g-disco/include/periph_conf.h index a0b1a36b64..54c5dfc100 100644 --- a/boards/stm32l476g-disco/include/periph_conf.h +++ b/boards/stm32l476g-disco/include/periph_conf.h @@ -19,8 +19,13 @@ #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 + #include "periph_cpu.h" -#include "l4/cfg_clock_80_1.h" +#include "l4/cfg_clock_default.h" #include "cfg_rtt_default.h" #ifdef __cplusplus diff --git a/cpu/stm32/stmclk/stmclk_l4wb.c b/cpu/stm32/stmclk/stmclk_l4wb.c index edecda4c96..793847ce89 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 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 #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,86 @@ 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 + /* Enable the HSE clock only when it's provided by the board and required: + - Use HSE as system clock + - Use HSE as PLL input clock + */ + if (IS_ACTIVE(CONFIG_BOARD_HAS_HSE) && + (IS_ACTIVE(CONFIG_USE_CLOCK_HSE) || IS_ACTIVE(CONFIG_CLOCK_PLL_SRC_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 */ + if (IS_ACTIVE(CONFIG_USE_CLOCK_HSE)) { + /* Select HSE as system clock and configure the different prescalers */ + RCC->CFGR &= ~RCC_CFGR_SW; + RCC->CFGR |= RCC_CFGR_SW_HSE; + } + else if (IS_ACTIVE(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)) {} - - /* 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; + 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 (IS_ACTIVE(CONFIG_USE_CLOCK_PLL)) { + if (IS_ACTIVE(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->CCIPR |= RCC_CCIPR_LPTIM1SEL_0; -#endif /* CLOCK_LSE */ -#endif /* MODULE_PERIPH_RTT */ + RCC->CR |= (CLOCK_MSIRANGE | RCC_CR_MSION | RCC_CR_MSIRGSEL); +#endif + while (!(RCC->CR & RCC_CR_MSIRDY)) {} + + if (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)) {} + } + + 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) {} + } + + if (!IS_ACTIVE(CONFIG_USE_CLOCK_HSI) || + (IS_ACTIVE(CONFIG_USE_CLOCK_PLL) && !IS_ACTIVE(CONFIG_CLOCK_PLL_SRC_HSI))) { + /* Disable HSI only if not used */ + stmclk_disable_hsi(); + } + + 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 (IS_ACTIVE(CONFIG_BOARD_HAS_LSE)) { + RCC->CCIPR |= RCC_CCIPR_LPTIM1SEL_0 | RCC_CCIPR_LPTIM1SEL_1; + } + else { + RCC->CCIPR |= RCC_CCIPR_LPTIM1SEL_0; + } + } + + irq_restore(is); }