From edecbf51444799dd66f50fd151c60056233e762e Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Thu, 20 May 2021 07:47:54 +0000 Subject: [PATCH] Dynamic support implemented for STM32L4+, improvements to STM32G4 HAL port. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@14398 27425a3e-05d8-49a3-a47f-9c15f0e5edd8 --- os/hal/ports/STM32/LLD/RCCv1/stm32_hsi48.inc | 17 +- os/hal/ports/STM32/LLD/RCCv1/stm32_msi.inc | 11 +- os/hal/ports/STM32/LLD/RCCv1/stm32_pll.inc | 7 +- .../ports/STM32/LLD/RCCv1/stm32_pllsai1.inc | 12 + .../ports/STM32/LLD/RCCv1/stm32_pllsai2.inc | 19 +- os/hal/ports/STM32/STM32G4xx/hal_lld.c | 67 +- os/hal/ports/STM32/STM32G4xx/hal_lld.h | 307 ++++---- os/hal/ports/STM32/STM32L4xx+/hal_lld.c | 666 +++++++++++++++++- os/hal/ports/STM32/STM32L4xx+/hal_lld.h | 528 ++++++++------ readme.txt | 2 +- 10 files changed, 1192 insertions(+), 444 deletions(-) diff --git a/os/hal/ports/STM32/LLD/RCCv1/stm32_hsi48.inc b/os/hal/ports/STM32/LLD/RCCv1/stm32_hsi48.inc index a1e5fabf3..7296791f2 100644 --- a/os/hal/ports/STM32/LLD/RCCv1/stm32_hsi48.inc +++ b/os/hal/ports/STM32/LLD/RCCv1/stm32_hsi48.inc @@ -61,13 +61,24 @@ /* Driver local functions. */ /*===========================================================================*/ +__STATIC_INLINE void hsi48_enable(void) { + + RCC->CRRCR |= RCC_CRRCR_HSI48ON; + while ((RCC->CRRCR & RCC_CRRCR_HSI48RDY) == 0U) { + /* Waiting for HSI48 activation.*/ + } +} + +__STATIC_INLINE void hsi48_disable(void) { + + RCC->CRRCR &= ~RCC_CRRCR_HSI48ON; +} + __STATIC_INLINE void hsi48_init(void) { #if STM32_HSI48_ENABLED /* HSI activation.*/ - RCC->CRRCR |= RCC_CRRCR_HSI48ON; - while ((RCC->CRRCR & RCC_CRRCR_HSI48RDY) == 0U) { - } + hsi48_enable(); #endif } diff --git a/os/hal/ports/STM32/LLD/RCCv1/stm32_msi.inc b/os/hal/ports/STM32/LLD/RCCv1/stm32_msi.inc index c96f043d4..f4e8d3084 100644 --- a/os/hal/ports/STM32/LLD/RCCv1/stm32_msi.inc +++ b/os/hal/ports/STM32/LLD/RCCv1/stm32_msi.inc @@ -167,13 +167,18 @@ __STATIC_INLINE void msi_reset(void) { - /* Resetting to the MSI clock in case we come here after an initialization, - because a debugger for example.*/ - RCC->CR = RCC_CR_MSION; + /* Making sure MSI is active and ready.*/ + RCC->CR |= RCC_CR_MSION; while ((RCC->CR & RCC_CR_MSIRDY) == 0U) { /* Wait until MSI is stable.*/ } + /* Resetting MSI defaults. + Note from RM0432: MSIRANGE can be modified when MSI is OFF (MSION=0) + or when MSI is ready (MSIRDY=1). MSIRANGE must NOT be modified when + MSI is ON and NOT ready (MSION=1 and MSIRDY=0).*/ + RCC->CR = (RCC->CR & ~RCC_CR_MSIRANGE_Msk) | RCC_CR_MSIRANGE_6; + /* Clocking from MSI, in case MSI was not the default source.*/ RCC->CFGR = 0U; while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_MSI) { diff --git a/os/hal/ports/STM32/LLD/RCCv1/stm32_pll.inc b/os/hal/ports/STM32/LLD/RCCv1/stm32_pll.inc index e2448f45e..f36eb07d8 100644 --- a/os/hal/ports/STM32/LLD/RCCv1/stm32_pll.inc +++ b/os/hal/ports/STM32/LLD/RCCv1/stm32_pll.inc @@ -319,9 +319,14 @@ /* Driver local functions. */ /*===========================================================================*/ +__STATIC_INLINE bool pll_not_locked(void) { + + return (bool)((RCC->CR & RCC_CR_PLLRDY) == 0U); +} + __STATIC_INLINE void pll_wait_lock(void) { - while ((RCC->CR & RCC_CR_PLLRDY) == 0U) { + while (pll_not_locked()) { /* Waiting for PLL lock.*/ } } diff --git a/os/hal/ports/STM32/LLD/RCCv1/stm32_pllsai1.inc b/os/hal/ports/STM32/LLD/RCCv1/stm32_pllsai1.inc index dcc8de480..6ae5c1c09 100644 --- a/os/hal/ports/STM32/LLD/RCCv1/stm32_pllsai1.inc +++ b/os/hal/ports/STM32/LLD/RCCv1/stm32_pllsai1.inc @@ -323,6 +323,18 @@ /* Driver local functions. */ /*===========================================================================*/ +__STATIC_INLINE bool pllsai1_not_locked(void) { + + return (bool)((RCC->CR & RCC_CR_PLLSAI1RDY) == 0U); +} + +__STATIC_INLINE void pllsai1_wait_lock(void) { + + while (pllsai1_not_locked()) { + /* Waiting for PLLSAI1 lock.*/ + } +} + __STATIC_INLINE void pllsai1_init(void) { #if STM32_ACTIVATE_PLLSAI1 diff --git a/os/hal/ports/STM32/LLD/RCCv1/stm32_pllsai2.inc b/os/hal/ports/STM32/LLD/RCCv1/stm32_pllsai2.inc index 5e02e75dc..317280231 100644 --- a/os/hal/ports/STM32/LLD/RCCv1/stm32_pllsai2.inc +++ b/os/hal/ports/STM32/LLD/RCCv1/stm32_pllsai2.inc @@ -323,6 +323,22 @@ /* Driver local functions. */ /*===========================================================================*/ +__STATIC_INLINE bool pllsai2_not_locked(void) { + + if ((RCC->CR & RCC_CR_PLLSAI2ON) == 0U) { + /* Disabled, no need to lock.*/ + return false; + } + return (bool)((RCC->CR & RCC_CR_PLLSAI2RDY) == 0U); +} + +__STATIC_INLINE void pllsai2_wait_lock(void) { + + while (pllsai2_not_locked()) { + /* Waiting for PLLSAI2 lock.*/ + } +} + __STATIC_INLINE void pllsai2_init(void) { #if STM32_ACTIVATE_PLLSAI2 @@ -335,8 +351,7 @@ __STATIC_INLINE void pllsai2_init(void) { RCC->CR |= RCC_CR_PLLSAI2ON; /* Waiting for PLL lock.*/ - while ((RCC->CR & RCC_CR_PLLSAI2RDY) == 0U) - ; + pllsai2_wait_lock(); #endif } diff --git a/os/hal/ports/STM32/STM32G4xx/hal_lld.c b/os/hal/ports/STM32/STM32G4xx/hal_lld.c index 7d3756883..1a4b8513f 100644 --- a/os/hal/ports/STM32/STM32G4xx/hal_lld.c +++ b/os/hal/ports/STM32/STM32G4xx/hal_lld.c @@ -139,42 +139,46 @@ typedef struct { * @brief System limits for VOS RANGE1. */ static const system_limits_t vos_range1 = { - .sysclk_max_boost = 170000000U, - .sysclk_max_noboost = 150000000U, - .pllin_max = 16000000U, - .pllin_min = 2660000U, - .pllvco_max = 344000000U, - .pllvco_min = 96000000U, - .pllp_max = 170000000U, - .pllp_min = 2064500U, - .pllq_max = 170000000U, - .pllq_min = 8000000U, - .pllr_max = 170000000U, - .pllr_min = 8000000U, - .flash_thresholds = { 20000000U, 40000000U, 60000000U, 80000000U, - 100000000U, 120000000U, 140000000U, 160000000U, - 170000000U} + .sysclk_max_boost = STM32_VOS1_SYSCLK_MAX, + .sysclk_max_noboost = STM32_VOS1_SYSCLK_MAX_NOBOOST, + .pllin_max = STM32_VOS1_PLLIN_MAX, + .pllin_min = STM32_VOS1_PLLIN_MIN, + .pllvco_max = STM32_VOS1_PLLVCO_MAX, + .pllvco_min = STM32_VOS1_PLLVCO_MIN, + .pllp_max = STM32_VOS1_PLLP_MAX, + .pllp_min = STM32_VOS1_PLLP_MIN, + .pllq_max = STM32_VOS1_PLLQ_MAX, + .pllq_min = STM32_VOS1_PLLQ_MIN, + .pllr_max = STM32_VOS1_PLLR_MAX, + .pllr_min = STM32_VOS1_PLLR_MIN, + .flash_thresholds = {STM32_VOS1_0WS_THRESHOLD, STM32_VOS1_1WS_THRESHOLD, + STM32_VOS1_2WS_THRESHOLD, STM32_VOS1_3WS_THRESHOLD, + STM32_VOS1_4WS_THRESHOLD, STM32_VOS1_5WS_THRESHOLD, + STM32_VOS1_6WS_THRESHOLD, STM32_VOS1_7WS_THRESHOLD, + STM32_VOS1_8WS_THRESHOLD} }; /** * @brief System limits for VOS RANGE2. */ static const system_limits_t vos_range2 = { - .sysclk_max_boost = 0U, - .sysclk_max_noboost = 26000000U, - .pllin_max = 16000000U, - .pllin_min = 2660000U, - .pllvco_max = 128000000U, - .pllvco_min = 96000000U, - .pllp_max = 26000000U, - .pllp_min = 2064500U, - .pllq_max = 26000000U, - .pllq_min = 8000000U, - .pllr_max = 26000000U, - .pllr_min = 8000000U, - .flash_thresholds = { 8000000U, 16000000U, 26000000U, 0U, - 0U, 0U, 0U, 0U, - 0U} + .sysclk_max_boost = STM32_VOS2_SYSCLK_MAX, + .sysclk_max_noboost = STM32_VOS2_SYSCLK_MAX_NOBOOST, + .pllin_max = STM32_VOS2_PLLIN_MAX, + .pllin_min = STM32_VOS2_PLLIN_MIN, + .pllvco_max = STM32_VOS2_PLLVCO_MAX, + .pllvco_min = STM32_VOS2_PLLVCO_MIN, + .pllp_max = STM32_VOS2_PLLP_MAX, + .pllp_min = STM32_VOS2_PLLP_MIN, + .pllq_max = STM32_VOS2_PLLQ_MAX, + .pllq_min = STM32_VOS2_PLLQ_MIN, + .pllr_max = STM32_VOS2_PLLR_MAX, + .pllr_min = STM32_VOS2_PLLR_MIN, + .flash_thresholds = {STM32_VOS2_0WS_THRESHOLD, STM32_VOS2_1WS_THRESHOLD, + STM32_VOS2_2WS_THRESHOLD, STM32_VOS2_3WS_THRESHOLD, + STM32_VOS2_4WS_THRESHOLD, STM32_VOS2_5WS_THRESHOLD, + STM32_VOS2_6WS_THRESHOLD, STM32_VOS2_7WS_THRESHOLD, + STM32_VOS2_8WS_THRESHOLD} }; #endif /* defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ @@ -387,7 +391,8 @@ static bool hal_lld_clock_check_tree(const halclkcfg_t *ccp) { flashws = ((ccp->flash_acr & FLASH_ACR_LATENCY_Msk) >> FLASH_ACR_LATENCY_Pos); if (flashws >= STM32_WS_THRESHOLDS) { return true; - } if (hclk > slp->flash_thresholds[flashws]) { + } + if (hclk > slp->flash_thresholds[flashws]) { return true; } diff --git a/os/hal/ports/STM32/STM32G4xx/hal_lld.h b/os/hal/ports/STM32/STM32G4xx/hal_lld.h index 8ea9ffd7d..e9234d873 100644 --- a/os/hal/ports/STM32/STM32G4xx/hal_lld.h +++ b/os/hal/ports/STM32/STM32G4xx/hal_lld.h @@ -652,177 +652,154 @@ #endif +/** + * @name System Limits for VOS range 1 + * @{ + */ +#define STM32_VOS1_SYSCLK_MAX 170000000 +#define STM32_VOS1_SYSCLK_MAX_NOBOOST 150000000 +#define STM32_VOS1_HSECLK_MAX 48000000 +#define STM32_VOS1_HSECLK_BYP_MAX 48000000 +#define STM32_VOS1_HSECLK_MIN 8000000 +#define STM32_VOS1_HSECLK_BYP_MIN 8000000 +#define STM32_VOS1_LSECLK_MAX 32768 +#define STM32_VOS1_LSECLK_BYP_MAX 1000000 +#define STM32_VOS1_LSECLK_MIN 32768 +#define STM32_VOS1_LSECLK_BYP_MIN 32768 +#define STM32_VOS1_PLLIN_MAX 16000000 +#define STM32_VOS1_PLLIN_MIN 2660000 +#define STM32_VOS1_PLLVCO_MAX 344000000 +#define STM32_VOS1_PLLVCO_MIN 96000000 +#define STM32_VOS1_PLLP_MAX 170000000 +#define STM32_VOS1_PLLP_MIN 2064500 +#define STM32_VOS1_PLLQ_MAX 170000000 +#define STM32_VOS1_PLLQ_MIN 8000000 +#define STM32_VOS1_PLLR_MAX 170000000 +#define STM32_VOS1_PLLR_MIN 8000000 +#define STM32_VOS1_PCLK1_MAX 170000000 +#define STM32_VOS1_PCLK2_MAX 170000000 +#define STM32_VOS1_ADCCLK_MAX 60000000 + +#define STM32_VOS1_0WS_THRESHOLD 20000000 +#define STM32_VOS1_1WS_THRESHOLD 40000000 +#define STM32_VOS1_2WS_THRESHOLD 60000000 +#define STM32_VOS1_3WS_THRESHOLD 80000000 +#define STM32_VOS1_4WS_THRESHOLD 100000000 +#define STM32_VOS1_5WS_THRESHOLD 120000000 +#define STM32_VOS1_6WS_THRESHOLD 140000000 +#define STM32_VOS1_7WS_THRESHOLD 160000000 +#define STM32_VOS1_8WS_THRESHOLD 170000000 +/** @} */ + +/** + * @name System Limits for VOS range 2 + * @{ + */ +#define STM32_VOS2_SYSCLK_MAX 26000000 +#define STM32_VOS2_SYSCLK_MAX_NOBOOST 26000000 +#define STM32_VOS2_HSECLK_MAX 26000000 +#define STM32_VOS2_HSECLK_BYP_MAX 26000000 +#define STM32_VOS2_HSECLK_MIN 8000000 +#define STM32_VOS2_HSECLK_BYP_MIN 8000000 +#define STM32_VOS2_LSECLK_MAX 32768 +#define STM32_VOS2_LSECLK_BYP_MAX 1000000 +#define STM32_VOS2_LSECLK_MIN 32768 +#define STM32_VOS2_LSECLK_BYP_MIN 32768 +#define STM32_VOS2_PLLIN_MAX 16000000 +#define STM32_VOS2_PLLIN_MIN 2660000 +#define STM32_VOS2_PLLVCO_MAX 128000000 +#define STM32_VOS2_PLLVCO_MIN 96000000 +#define STM32_VOS2_PLLP_MAX 26000000 +#define STM32_VOS2_PLLP_MIN 2064500 +#define STM32_VOS2_PLLQ_MAX 26000000 +#define STM32_VOS2_PLLQ_MIN 8000000 +#define STM32_VOS2_PLLR_MAX 26000000 +#define STM32_VOS2_PLLR_MIN 8000000 +#define STM32_VOS2_PCLK1_MAX 26000000 +#define STM32_VOS2_PCLK2_MAX 26000000 +#define STM32_VOS2_ADCCLK_MAX 26000000 + +#define STM32_VOS2_0WS_THRESHOLD 8000000 +#define STM32_VOS2_1WS_THRESHOLD 16000000 +#define STM32_VOS2_2WS_THRESHOLD 26000000 +#define STM32_VOS2_3WS_THRESHOLD 0 +#define STM32_VOS2_4WS_THRESHOLD 0 +#define STM32_VOS2_5WS_THRESHOLD 0 +#define STM32_VOS2_6WS_THRESHOLD 0 +#define STM32_VOS2_7WS_THRESHOLD 0 +#define STM32_VOS2_8WS_THRESHOLD 0 +/** @} */ + /* Voltage related limits.*/ #if (STM32_VOS == STM32_VOS_RANGE1) || defined(__DOXYGEN__) -/** - * @name System Limits - * @{ - */ -/** - * @brief Maximum SYSCLK clock frequency. - */ -#define STM32_SYSCLK_MAX 170000000 +#define STM32_SYSCLK_MAX STM32_VOS1_SYSCLK_MAX +#define STM32_SYSCLK_MAX_NOBOOST STM32_VOS1_SYSCLK_MAX_NOBOOST +#define STM32_HSECLK_MAX STM32_VOS1_HSECLK_MAX +#define STM32_HSECLK_BYP_MAX STM32_VOS1_HSECLK_BYP_MAX +#define STM32_HSECLK_MIN STM32_VOS1_HSECLK_MIN +#define STM32_HSECLK_BYP_MIN STM32_VOS1_HSECLK_BYP_MIN +#define STM32_LSECLK_MAX STM32_VOS1_LSECLK_MAX +#define STM32_LSECLK_BYP_MAX STM32_VOS1_LSECLK_BYP_MAX +#define STM32_LSECLK_MIN STM32_VOS1_LSECLK_MIN +#define STM32_LSECLK_BYP_MIN STM32_VOS1_LSECLK_BYP_MIN +#define STM32_PLLIN_MAX STM32_VOS1_PLLIN_MAX +#define STM32_PLLIN_MIN STM32_VOS1_PLLIN_MIN +#define STM32_PLLVCO_MAX STM32_VOS1_PLLVCO_MAX +#define STM32_PLLVCO_MIN STM32_VOS1_PLLVCO_MIN +#define STM32_PLLP_MAX STM32_VOS1_PLLP_MAX +#define STM32_PLLP_MIN STM32_VOS1_PLLP_MIN +#define STM32_PLLQ_MAX STM32_VOS1_PLLQ_MAX +#define STM32_PLLQ_MIN STM32_VOS1_PLLQ_MIN +#define STM32_PLLR_MAX STM32_VOS1_PLLR_MAX +#define STM32_PLLR_MIN STM32_VOS1_PLLR_MIN +#define STM32_PCLK1_MAX STM32_VOS1_PCLK1_MAX +#define STM32_PCLK2_MAX STM32_VOS1_PCLK2_MAX +#define STM32_ADCCLK_MAX STM32_VOS1_ADCCLK_MAX -/** - * @brief Maximum SYSCLK clock frequency without voltage boost. - */ -#define STM32_SYSCLK_MAX_NOBOOST 150000000 - -/** - * @brief Maximum HSE clock frequency at current voltage setting. - */ -#define STM32_HSECLK_MAX 48000000 - -/** - * @brief Maximum HSE clock frequency using an external source. - */ -#define STM32_HSECLK_BYP_MAX 48000000 - -/** - * @brief Minimum HSE clock frequency. - */ -#define STM32_HSECLK_MIN 8000000 - -/** - * @brief Minimum HSE clock frequency using an external source. - */ -#define STM32_HSECLK_BYP_MIN 8000000 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSECLK_MAX 32768 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSECLK_BYP_MAX 1000000 - -/** - * @brief Minimum LSE clock frequency. - */ -#define STM32_LSECLK_MIN 32768 - -/** - * @brief Minimum LSE clock frequency. - */ -#define STM32_LSECLK_BYP_MIN 32768 - -/** - * @brief Maximum PLLs input clock frequency. - */ -#define STM32_PLLIN_MAX 16000000 - -/** - * @brief Minimum PLLs input clock frequency. - */ -#define STM32_PLLIN_MIN 2660000 - -/** - * @brief Maximum VCO clock frequency at current voltage setting. - */ -#define STM32_PLLVCO_MAX 344000000 - -/** - * @brief Minimum VCO clock frequency at current voltage setting. - */ -#define STM32_PLLVCO_MIN 96000000 - -/** - * @brief Maximum PLL-P output clock frequency. - */ -#define STM32_PLLP_MAX 170000000 - -/** - * @brief Minimum PLL-P output clock frequency. - */ -#define STM32_PLLP_MIN 2064500 - -/** - * @brief Maximum PLL-Q output clock frequency. - */ -#define STM32_PLLQ_MAX 170000000 - -/** - * @brief Minimum PLL-Q output clock frequency. - */ -#define STM32_PLLQ_MIN 8000000 - -/** - * @brief Maximum PLL-R output clock frequency. - */ -#define STM32_PLLR_MAX 170000000 - -/** - * @brief Minimum PLL-R output clock frequency. - */ -#define STM32_PLLR_MIN 8000000 - -/** - * @brief Maximum APB clock frequency. - */ -#define STM32_PCLK1_MAX 170000000 - -/** - * @brief Maximum APB clock frequency. - */ -#define STM32_PCLK2_MAX 170000000 - -/** - * @brief Maximum ADC clock frequency. - */ -#define STM32_ADCCLK_MAX 60000000 -/** @} */ - -/** - * @name Flash Wait states - * @{ - */ -#define STM32_0WS_THRESHOLD 20000000 -#define STM32_1WS_THRESHOLD 40000000 -#define STM32_2WS_THRESHOLD 60000000 -#define STM32_3WS_THRESHOLD 80000000 -#define STM32_4WS_THRESHOLD 100000000 -#define STM32_5WS_THRESHOLD 120000000 -#define STM32_6WS_THRESHOLD 140000000 -#define STM32_7WS_THRESHOLD 160000000 -#define STM32_8WS_THRESHOLD 170000000 -/** @} */ +#define STM32_0WS_THRESHOLD STM32_VOS1_0WS_THRESHOLD +#define STM32_1WS_THRESHOLD STM32_VOS1_1WS_THRESHOLD +#define STM32_2WS_THRESHOLD STM32_VOS1_2WS_THRESHOLD +#define STM32_3WS_THRESHOLD STM32_VOS1_3WS_THRESHOLD +#define STM32_4WS_THRESHOLD STM32_VOS1_4WS_THRESHOLD +#define STM32_5WS_THRESHOLD STM32_VOS1_5WS_THRESHOLD +#define STM32_6WS_THRESHOLD STM32_VOS1_6WS_THRESHOLD +#define STM32_7WS_THRESHOLD STM32_VOS1_7WS_THRESHOLD +#define STM32_8WS_THRESHOLD STM32_VOS1_8WS_THRESHOLD #elif STM32_VOS == STM32_VOS_RANGE2 -#define STM32_SYSCLK_MAX 26000000 -#define STM32_SYSCLK_MAX_NOBOOST 26000000 -#define STM32_HSECLK_MAX 26000000 -#define STM32_HSECLK_BYP_MAX 26000000 -#define STM32_HSECLK_MIN 8000000 -#define STM32_HSECLK_BYP_MIN 8000000 -#define STM32_LSECLK_MAX 32768 -#define STM32_LSECLK_BYP_MAX 1000000 -#define STM32_LSECLK_MIN 32768 -#define STM32_LSECLK_BYP_MIN 32768 -#define STM32_PLLIN_MAX 16000000 -#define STM32_PLLIN_MIN 2660000 -#define STM32_PLLVCO_MAX 128000000 -#define STM32_PLLVCO_MIN 96000000 -#define STM32_PLLP_MAX 26000000 -#define STM32_PLLP_MIN 2064500 -#define STM32_PLLQ_MAX 26000000 -#define STM32_PLLQ_MIN 8000000 -#define STM32_PLLR_MAX 26000000 -#define STM32_PLLR_MIN 8000000 -#define STM32_PCLK1_MAX 26000000 -#define STM32_PCLK2_MAX 26000000 -#define STM32_ADCCLK_MAX 26000000 +#define STM32_SYSCLK_MAX STM32_VOS2_SYSCLK_MAX +#define STM32_SYSCLK_MAX_NOBOOST STM32_VOS2_SYSCLK_MAX_NOBOOST +#define STM32_HSECLK_MAX STM32_VOS2_HSECLK_MAX +#define STM32_HSECLK_BYP_MAX STM32_VOS2_HSECLK_BYP_MAX +#define STM32_HSECLK_MIN STM32_VOS2_HSECLK_MIN +#define STM32_HSECLK_BYP_MIN STM32_VOS2_HSECLK_BYP_MIN +#define STM32_LSECLK_MAX STM32_VOS2_LSECLK_MAX +#define STM32_LSECLK_BYP_MAX STM32_VOS2_LSECLK_BYP_MAX +#define STM32_LSECLK_MIN STM32_VOS2_LSECLK_MIN +#define STM32_LSECLK_BYP_MIN STM32_VOS2_LSECLK_BYP_MIN +#define STM32_PLLIN_MAX STM32_VOS2_PLLIN_MAX +#define STM32_PLLIN_MIN STM32_VOS2_PLLIN_MIN +#define STM32_PLLVCO_MAX STM32_VOS2_PLLVCO_MAX +#define STM32_PLLVCO_MIN STM32_VOS2_PLLVCO_MIN +#define STM32_PLLP_MAX STM32_VOS2_PLLP_MAX +#define STM32_PLLP_MIN STM32_VOS2_PLLP_MIN +#define STM32_PLLQ_MAX STM32_VOS2_PLLQ_MAX +#define STM32_PLLQ_MIN STM32_VOS2_PLLQ_MIN +#define STM32_PLLR_MAX STM32_VOS2_PLLR_MAX +#define STM32_PLLR_MIN STM32_VOS2_PLLR_MIN +#define STM32_PCLK1_MAX STM32_VOS2_PCLK1_MAX +#define STM32_PCLK2_MAX STM32_VOS2_PCLK2_MAX +#define STM32_ADCCLK_MAX STM32_VOS2_ADCCLK_MAX -#define STM32_0WS_THRESHOLD 8000000 -#define STM32_1WS_THRESHOLD 16000000 -#define STM32_2WS_THRESHOLD 26000000 -#define STM32_3WS_THRESHOLD 0 -#define STM32_4WS_THRESHOLD 0 -#define STM32_5WS_THRESHOLD 0 -#define STM32_6WS_THRESHOLD 0 -#define STM32_7WS_THRESHOLD 0 -#define STM32_8WS_THRESHOLD 0 +#define STM32_0WS_THRESHOLD STM32_VOS2_0WS_THRESHOLD +#define STM32_1WS_THRESHOLD STM32_VOS2_1WS_THRESHOLD +#define STM32_2WS_THRESHOLD STM32_VOS2_2WS_THRESHOLD +#define STM32_3WS_THRESHOLD STM32_VOS2_3WS_THRESHOLD +#define STM32_4WS_THRESHOLD STM32_VOS2_4WS_THRESHOLD +#define STM32_5WS_THRESHOLD STM32_VOS2_5WS_THRESHOLD +#define STM32_6WS_THRESHOLD STM32_VOS2_6WS_THRESHOLD +#define STM32_7WS_THRESHOLD STM32_VOS2_7WS_THRESHOLD +#define STM32_8WS_THRESHOLD STM32_VOS2_8WS_THRESHOLD #else #error "invalid STM32_VOS value specified" diff --git a/os/hal/ports/STM32/STM32L4xx+/hal_lld.c b/os/hal/ports/STM32/STM32L4xx+/hal_lld.c index 54cf3cf93..6291b7f48 100644 --- a/os/hal/ports/STM32/STM32L4xx+/hal_lld.c +++ b/os/hal/ports/STM32/STM32L4xx+/hal_lld.c @@ -28,6 +28,11 @@ /* Driver local definitions. */ /*===========================================================================*/ +/** + * @brief Number of thresholds in the wait states array. + */ +#define STM32_WS_THRESHOLDS 6 + /*===========================================================================*/ /* Driver exported variables. */ /*===========================================================================*/ @@ -38,16 +43,569 @@ */ uint32_t SystemCoreClock = STM32_HCLK; +#if defined(HAL_LLD_USE_CLOCK_MANAGEMENT) || defined(__DOXYGEN__) +/** + * @brief Post-reset clock configuration. + */ +const halclkcfg_t hal_clkcfg_reset = { + .pwr_cr1 = PWR_CR1_VOS_0, + .pwr_cr2 = 0U, + .pwr_cr3 = PWR_CR3_EIWF, + .pwr_cr4 = 0U, + .pwr_cr5 = PWR_CR5_R1MODE, + .rcc_cr = RCC_CR_MSIRANGE_6 | RCC_CR_MSION, + .rcc_cfgr = RCC_CFGR_SW_MSI, + .rcc_pllcfgr = 0U, + .rcc_pllsai1cfgr = 0U, + .rcc_pllsai2cfgr = 0U, + .rcc_crrcr = 0U, + .flash_acr = FLASH_ACR_DCEN | FLASH_ACR_ICEN | + FLASH_ACR_LATENCY_0WS +}; + +/** + * @brief Default clock configuration. + */ +const halclkcfg_t hal_clkcfg_default = { + .pwr_cr1 = STM32_VOS_RANGE1 | PWR_CR1_DBP, + .pwr_cr2 = STM32_PWR_CR2, + .pwr_cr3 = STM32_PWR_CR3, + .pwr_cr4 = STM32_PWR_CR4, + .pwr_cr5 = STM32_CR5BITS, + .rcc_cr = 0U +#if STM32_MSIPLL_ENABLED + | STM32_MSIRANGE | RCC_CR_MSIPLLEN | RCC_CR_MSION +#else + | STM32_MSIRANGE | RCC_CR_MSION +#endif +#if STM32_HSI16_ENABLED + | RCC_CR_HSIKERON | RCC_CR_HSION +#endif +#if STM32_HSE_ENABLED + | RCC_CR_HSEON +#endif +#if STM32_ACTIVATE_PLL + | RCC_CR_PLLON +#endif + , + .rcc_cfgr = STM32_MCOPRE | STM32_MCOSEL | + STM32_PPRE2 | STM32_PPRE1 | + STM32_HPRE | STM32_SW, + .rcc_pllcfgr = STM32_PLLPDIV | STM32_PLLR | + STM32_PLLREN | STM32_PLLQ | + STM32_PLLQEN | STM32_PLLP | + STM32_PLLPEN | STM32_PLLN | + STM32_PLLM | STM32_PLLSRC, + .rcc_pllsai1cfgr = STM32_PLLSAI1PDIV | STM32_PLLSAI1R | + STM32_PLLSAI1REN | STM32_PLLSAI1Q | + STM32_PLLSAI1QEN | STM32_PLLSAI1P | + STM32_PLLSAI1PEN | STM32_PLLSAI1N | + STM32_PLLSAI1M, + .rcc_pllsai2cfgr = STM32_PLLSAI2PDIV | STM32_PLLSAI2R | + STM32_PLLSAI2REN | STM32_PLLSAI2Q | + STM32_PLLSAI2QEN | STM32_PLLSAI2P | + STM32_PLLSAI2PEN | STM32_PLLSAI2N | + STM32_PLLSAI2M, +#if STM32_HSI48_ENABLED + .rcc_crrcr = RCC_CRRCR_HSI48ON, +#else + .rcc_crrcr = 0U, +#endif + .flash_acr = FLASH_ACR_DCEN | FLASH_ACR_ICEN | + FLASH_ACR_PRFTEN | STM32_FLASHBITS +}; +#endif /* defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ + /*===========================================================================*/ /* Driver local variables and types. */ /*===========================================================================*/ +#if defined(HAL_LLD_USE_CLOCK_MANAGEMENT) || defined(__DOXYGEN__) +/** + * @brief Dynamic clock points for this device. + */ +static halfreq_t clock_points[CLK_ARRAY_SIZE] = { + [CLK_SYSCLK] = STM32_SYSCLK, + [CLK_PLLPCLK] = STM32_PLL_P_CLKOUT, + [CLK_PLLQCLK] = STM32_PLL_Q_CLKOUT, + [CLK_PLLRCLK] = STM32_PLL_R_CLKOUT, + [CLK_PLLSAI1PCLK] = STM32_PLLSAI1_P_CLKOUT, + [CLK_PLLSAI1QCLK] = STM32_PLLSAI1_Q_CLKOUT, + [CLK_PLLSAI1RCLK] = STM32_PLLSAI1_R_CLKOUT, + [CLK_PLLSAI2PCLK] = STM32_PLLSAI2_P_CLKOUT, + [CLK_PLLSAI2QCLK] = STM32_PLLSAI2_Q_CLKOUT, + [CLK_PLLSAI2RCLK] = STM32_PLLSAI2_R_CLKOUT, + [CLK_HCLK] = STM32_HCLK, + [CLK_PCLK1] = STM32_PCLK1, + [CLK_PCLK1TIM] = STM32_TIMP1CLK, + [CLK_PCLK2] = STM32_PCLK2, + [CLK_PCLK2TIM] = STM32_TIMP2CLK, + [CLK_MCO] = STM32_MCOCLK, +}; + +/** + * @brief Type of a structure representing system limits. + */ +typedef struct { + halfreq_t sysclk_max_boost; + halfreq_t sysclk_max_noboost; + halfreq_t pllin_max; + halfreq_t pllin_min; + halfreq_t pllvco_max; + halfreq_t pllvco_min; + halfreq_t pllp_max; + halfreq_t pllp_min; + halfreq_t pllq_max; + halfreq_t pllq_min; + halfreq_t pllr_max; + halfreq_t pllr_min; + halfreq_t flash_thresholds[STM32_WS_THRESHOLDS]; +} system_limits_t; + +/** + * @brief System limits for VOS RANGE1. + */ +static const system_limits_t vos_range1 = { + .sysclk_max_boost = STM32_VOS1_SYSCLK_MAX, + .sysclk_max_noboost = STM32_VOS1_SYSCLK_MAX_NOBOOST, + .pllin_max = STM32_VOS1_PLLIN_MAX, + .pllin_min = STM32_VOS1_PLLIN_MIN, + .pllvco_max = STM32_VOS1_PLLVCO_MAX, + .pllvco_min = STM32_VOS1_PLLVCO_MIN, + .pllp_max = STM32_VOS1_PLLP_MAX, + .pllp_min = STM32_VOS1_PLLP_MIN, + .pllq_max = STM32_VOS1_PLLQ_MAX, + .pllq_min = STM32_VOS1_PLLQ_MIN, + .pllr_max = STM32_VOS1_PLLR_MAX, + .pllr_min = STM32_VOS1_PLLR_MIN, + .flash_thresholds = {STM32_VOS1_0WS_THRESHOLD, STM32_VOS1_1WS_THRESHOLD, + STM32_VOS1_2WS_THRESHOLD, STM32_VOS1_3WS_THRESHOLD, + STM32_VOS1_4WS_THRESHOLD, STM32_VOS1_5WS_THRESHOLD} +}; + +/** + * @brief System limits for VOS RANGE2. + */ +static const system_limits_t vos_range2 = { + .sysclk_max_boost = STM32_VOS2_SYSCLK_MAX, + .sysclk_max_noboost = STM32_VOS2_SYSCLK_MAX_NOBOOST, + .pllin_max = STM32_VOS2_PLLIN_MAX, + .pllin_min = STM32_VOS2_PLLIN_MIN, + .pllvco_max = STM32_VOS2_PLLVCO_MAX, + .pllvco_min = STM32_VOS2_PLLVCO_MIN, + .pllp_max = STM32_VOS2_PLLP_MAX, + .pllp_min = STM32_VOS2_PLLP_MIN, + .pllq_max = STM32_VOS2_PLLQ_MAX, + .pllq_min = STM32_VOS2_PLLQ_MIN, + .pllr_max = STM32_VOS2_PLLR_MAX, + .pllr_min = STM32_VOS2_PLLR_MIN, + .flash_thresholds = {STM32_VOS2_0WS_THRESHOLD, STM32_VOS2_1WS_THRESHOLD, + STM32_VOS2_2WS_THRESHOLD, STM32_VOS2_3WS_THRESHOLD, + STM32_VOS2_4WS_THRESHOLD, STM32_VOS2_5WS_THRESHOLD} +}; +#endif /* defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ + /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ #include "stm32_bd.inc" +#if defined(HAL_LLD_USE_CLOCK_MANAGEMENT) || defined(__DOXYGEN__) +static bool hal_lld_check_pll(const system_limits_t *slp, + uint32_t cfgr, + halfreq_t selclk, + halfreq_t *pclkp, + halfreq_t *qclkp, + halfreq_t *rclkp) { + uint32_t mdiv, ndiv, pdiv, qdiv, rdiv; + halfreq_t vcoclk, pclk = 0U, qclk = 0U, rclk = 0U; + + /* PLL M divider.*/ + mdiv = ((cfgr & RCC_PLLCFGR_PLLM_Msk) >> RCC_PLLCFGR_PLLM_Pos) + 1U; + + /* PLL N divider.*/ + ndiv = (cfgr & RCC_PLLCFGR_PLLN_Msk) >> RCC_PLLCFGR_PLLN_Pos; + if (ndiv < 8) { + return true; + } + + /* PLL VCO frequency.*/ + vcoclk = (selclk / (halfreq_t)mdiv) * (halfreq_t)ndiv; + + if((vcoclk < slp->pllvco_min) || (vcoclk > slp->pllvco_max)) { + return true; + } + + /* PLL P output frequency.*/ + pdiv = (cfgr & RCC_PLLCFGR_PLLPDIV_Msk) >> RCC_PLLCFGR_PLLPDIV_Pos; + if (pdiv == 1U) { + return true; + } + if (pdiv == 0U) { + if ((cfgr & RCC_PLLCFGR_PLLP) == 0U) { + pdiv = 7U; + } + else { + pdiv = 17U; + } + } + if ((cfgr & RCC_PLLCFGR_PLLPEN) != 0U) { + pclk = vcoclk / pdiv; + + if((pclk < slp->pllp_min) || (pclk > slp->pllp_max)) { + return true; + } + } + + /* PLL Q output frequency.*/ + qdiv = 2U + (2U * (cfgr & RCC_PLLCFGR_PLLQ_Msk) >> RCC_PLLCFGR_PLLQ_Pos); + if ((cfgr & RCC_PLLCFGR_PLLQEN) != 0U) { + qclk = vcoclk / qdiv; + + if((qclk < slp->pllq_min) || (qclk > slp->pllq_max)) { + return true; + } + } + + /* PLL R output frequency.*/ + rdiv = 2U + (2U * (cfgr & RCC_PLLCFGR_PLLR_Msk) >> RCC_PLLCFGR_PLLR_Pos); + if ((cfgr & RCC_PLLCFGR_PLLREN) != 0U) { + rclk = vcoclk / rdiv; + + if((rclk < slp->pllr_min) || (rclk > slp->pllr_max)) { + return true; + } + } + + *pclkp = pclk; + *qclkp = qclk; + *rclkp = rclk; + + return false; +} +/** + * @brief Recalculates the clock tree frequencies. + * + * @param[in] ccp pointer to clock a @p halclkcfg_t structure + * @return The frequency calculation result. + * @retval false if the clock settings look valid + * @retval true if the clock settings look invalid + * + * @notapi + */ +static bool hal_lld_clock_check_tree(const halclkcfg_t *ccp) { + static const uint32_t hprediv[16] = {1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, + 2U, 4U, 8U, 16U, 64U, 128U, 256U, 512U}; + static const uint32_t pprediv[16] = {1U, 1U, 1U, 1U, 2U, 4U, 8U, 16U}; + const system_limits_t *slp; + halfreq_t msiclk = 0U, hsi16clk = 0U, hseclk = 0U, pllselclk; + halfreq_t pllpclk = 0U, pllqclk = 0U, pllrclk = 0U; + halfreq_t pllsai1pclk = 0U, pllsai1qclk = 0U, pllsai1rclk = 0U; + halfreq_t pllsai2pclk = 0U, pllsai2qclk = 0U, pllsai2rclk = 0U; + halfreq_t sysclk, hclk, pclk1, pclk2, pclk1tim, pclk2tim, mcoclk; + uint32_t mcodiv, flashws; + + /* System limits based on desired VOS settings.*/ + if ((ccp->pwr_cr1 & PWR_CR1_VOS_Msk) == PWR_CR1_VOS_1) { + slp = &vos_range2; + } + else if ((ccp->pwr_cr1 & PWR_CR1_VOS_Msk) == PWR_CR1_VOS_0) { + slp = &vos_range1; + } + else { + return true; + } + + /* MSI clock.*/ + if ((ccp->rcc_cr & RCC_CR_MSION) != 0U) { + msiclk = STM32_MSICLK; + } + + /* HSI16 clock.*/ + if ((ccp->rcc_cr & RCC_CR_HSION) != 0U) { + hsi16clk = STM32_HSI16CLK; + } + + /* HSE clock.*/ + if ((ccp->rcc_cr & RCC_CR_HSEON) != 0U) { + hseclk = STM32_HSECLK; + } + + /* PLL MUX clock.*/ + switch (ccp->rcc_pllcfgr & RCC_PLLCFGR_PLLSRC_Msk) { + case RCC_PLLCFGR_PLLSRC_MSI: + pllselclk = msiclk; + break; + case RCC_PLLCFGR_PLLSRC_HSI: + pllselclk = hsi16clk; + break; + case RCC_PLLCFGR_PLLSRC_HSE: + pllselclk = hseclk; + break; + default: + pllselclk = 0U; + } + + /* PLL outputs.*/ + if ((ccp->rcc_cr & RCC_CR_PLLON) != 0U) { + if (hal_lld_check_pll(slp, ccp->rcc_pllcfgr, pllselclk, + &pllpclk, &pllqclk, &pllrclk)) { + return true; + } + } + + /* PLLSAI1 outputs.*/ + if ((ccp->rcc_cr & RCC_CR_PLLSAI1ON) != 0U) { + if (hal_lld_check_pll(slp, ccp->rcc_pllsai1cfgr, pllselclk, + &pllsai1pclk, &pllsai1qclk, &pllsai1rclk)) { + return true; + } + } + + /* PLLSAI2 outputs.*/ + if ((ccp->rcc_cr & RCC_CR_PLLSAI2ON) != 0U) { + if (hal_lld_check_pll(slp, ccp->rcc_pllsai2cfgr, pllselclk, + &pllsai2pclk, &pllsai2qclk, &pllsai2rclk)) { + return true; + } + } + + /* SYSCLK frequency.*/ + switch(ccp->rcc_cfgr & RCC_CFGR_SW_Msk) { + case RCC_CFGR_SW_MSI: + sysclk = msiclk; + break; + case RCC_CFGR_SW_HSI: + sysclk = hsi16clk; + break; + case RCC_CFGR_SW_HSE: + sysclk = hseclk; + break; + case RCC_CFGR_SW_PLL: + sysclk = pllrclk; + break; + default: + sysclk = 0U; + } + + if ((ccp->pwr_cr5 & PWR_CR5_R1MODE) == 0U) { + if (sysclk > slp->sysclk_max_boost) { + return true; + } + } + else { + if (sysclk > slp->sysclk_max_noboost) { + return true; + } + } + + /* HCLK frequency.*/ + hclk = sysclk / hprediv[(ccp->rcc_cfgr & RCC_CFGR_HPRE_Msk) >> RCC_CFGR_HPRE_Pos]; + + /* PPRE1 frequency.*/ + pclk1 = hclk / pprediv[(ccp->rcc_cfgr & RCC_CFGR_PPRE1_Msk) >> RCC_CFGR_PPRE1_Pos]; + if ((ccp->rcc_cfgr & RCC_CFGR_PPRE1_Msk) < RCC_CFGR_PPRE1_DIV2) { + pclk1tim = pclk1; + } + else { + pclk1tim = pclk1 * 2U; + } + + /* PPRE2 frequency.*/ + pclk2 = hclk / pprediv[(ccp->rcc_cfgr & RCC_CFGR_PPRE2_Msk) >> RCC_CFGR_PPRE2_Pos]; + if ((ccp->rcc_cfgr & RCC_CFGR_PPRE1_Msk) < RCC_CFGR_PPRE2_DIV2) { + pclk2tim = pclk2; + } + else { + pclk2tim = pclk2 * 2U; + } + + /* MCO clock.*/ + switch(ccp->rcc_cfgr & RCC_CFGR_MCOSEL_Msk) { + case STM32_MCOSEL_NOCLOCK: + mcoclk = 0U; + break; + case STM32_MCOSEL_SYSCLK: + mcoclk = sysclk; + break; + case STM32_MCOSEL_MSI: + mcoclk = hsi16clk; + break; + case STM32_MCOSEL_HSI16: + mcoclk = hsi16clk; + break; + case STM32_MCOSEL_HSE: + mcoclk = hseclk; + break; + case STM32_MCOSEL_PLLRCLK: + mcoclk = pllrclk; + break; + case STM32_MCOSEL_LSI: + mcoclk = STM32_LSICLK; + break; + case STM32_MCOSEL_LSE: + mcoclk = STM32_LSECLK; + break; + case STM32_MCOSEL_HSI48: + mcoclk = STM32_HSI48CLK; + break; + default: + mcoclk = 0U; + } + mcodiv = 1U << ((ccp->rcc_cfgr & RCC_CFGR_MCOPRE_Msk) >> RCC_CFGR_MCOPRE_Pos); + if (mcodiv > 16U) { + return true; + } + mcoclk /= mcodiv; + + /* Flash settings.*/ + flashws = ((ccp->flash_acr & FLASH_ACR_LATENCY_Msk) >> FLASH_ACR_LATENCY_Pos); + if (flashws >= STM32_WS_THRESHOLDS) { + return true; + } + if (hclk > slp->flash_thresholds[flashws]) { + return true; + } + + /* Writing out results.*/ + clock_points[CLK_SYSCLK] = sysclk; + clock_points[CLK_PLLPCLK] = pllpclk; + clock_points[CLK_PLLQCLK] = pllqclk; + clock_points[CLK_PLLRCLK] = pllrclk; + clock_points[CLK_PLLSAI1PCLK] = pllsai1pclk; + clock_points[CLK_PLLSAI1QCLK] = pllsai1qclk; + clock_points[CLK_PLLSAI1RCLK] = pllsai1rclk; + clock_points[CLK_PLLSAI2PCLK] = pllsai2pclk; + clock_points[CLK_PLLSAI2QCLK] = pllsai2qclk; + clock_points[CLK_PLLSAI2RCLK] = pllsai2rclk; + clock_points[CLK_HCLK] = hclk; + clock_points[CLK_PCLK1] = pclk1; + clock_points[CLK_PCLK1TIM] = pclk1tim; + clock_points[CLK_PCLK2] = pclk2; + clock_points[CLK_PCLK2TIM] = pclk2tim; + clock_points[CLK_MCO] = mcoclk; + + return false; +} + +/** + * @brief Switches to a different clock configuration. + * + * @param[in] ccp pointer to clock a @p halclkcfg_t structure + * @return The clock switch result. + * @retval false if the clock switch succeeded + * @retval true if the clock switch failed + * + * @notapi + */ +bool hal_lld_clock_raw_switch(const halclkcfg_t *ccp) { + + /* Restoring default PWR settings related clocks and sleep modes.*/ + PWR->CR1 = PWR_CR1_VOS_0; + + /* Waiting for all regulator status bits to be cleared, this means that + power levels are stable.*/ + while ((PWR->SR2 & (PWR_SR2_VOSF | PWR_SR2_REGLPF)) != 0U) { + /* Waiting for the regulator to be ready.*/ + } + + /* If the clock source is not MSI then we switch to MSI and reset some + other relevant registers to their default value.*/ + if ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_MSI) { + /* Making sure MSI is activated and in use.*/ + msi_reset(); + + /* Resetting flash ACR settings to the default value.*/ + FLASH->ACR = 0x00000600U; + + /* Resetting all other clock sources and PLLs.*/ + RCC->CRRCR = 0U; + RCC->CR = 0x00000063U; + while ((RCC->CR & (RCC_CR_HSIRDY | RCC_CR_HSERDY)) != 0U) { + /* Waiting for oscillators to shut down.*/ + } + + /* Disabling boost mode.*/ + PWR->CR5 = PWR_CR5_R1MODE; + } + + /* HSI16 setup, if required, before starting the PLL.*/ + if ((ccp->rcc_cr & RCC_CR_HSION) != 0U) { + hsi16_enable(); + } + + /* HSE setup, if required, before starting the PLL.*/ + if ((ccp->rcc_cr & RCC_CR_HSEON) != 0U) { + hse_enable(); + } + + /* HSI48 setup, if required, before starting the PLL.*/ + if ((ccp->rcc_crrcr & RCC_CRRCR_HSI48ON) != 0U) { + hsi48_enable(); + } + + /* PLLs setup.*/ + RCC->PLLCFGR = ccp->rcc_pllcfgr; + RCC->PLLSAI1CFGR = ccp->rcc_pllsai1cfgr; + RCC->PLLSAI2CFGR = ccp->rcc_pllsai2cfgr; + + /* PLLs enabled if specified.*/ + RCC->CR = ccp->rcc_cr; + + /* PLLs activation polling if required.*/ + while (true) { + if (((ccp->rcc_cr & RCC_CR_PLLON) != 0U) && pll_not_locked()) { + continue; + } + if (((ccp->rcc_cr & RCC_CR_PLLSAI1ON) != 0U) && pllsai1_not_locked()) { + continue; + } + if (((ccp->rcc_cr & RCC_CR_PLLSAI2ON) != 0U) && pllsai2_not_locked()) { + continue; + } + break; + } + + /* MCO and bus dividers first.*/ + RCC->CFGR = (RCC->CFGR & RCC_CFGR_SW_Msk) | (ccp->rcc_cfgr & ~RCC_CFGR_SW_Msk); + + /* Final flash ACR settings.*/ + FLASH->ACR = ccp->flash_acr; + + /* Final PWR modes.*/ + PWR->CR1 = ccp->pwr_cr1; + PWR->CR2 = ccp->pwr_cr2; + PWR->CR3 = ccp->pwr_cr3; + PWR->CR4 = ccp->pwr_cr4; + PWR->CR5 = ccp->pwr_cr5; + + /* Waiting for the correct regulator state.*/ + if ((ccp->pwr_cr1 & PWR_CR1_LPR) == 0U) { + /* Main mode selected.*/ + + while ((PWR->SR2 & PWR_SR2_REGLPF) != 0U) { + /* Waiting for the regulator to be in main mode.*/ + } + } + else { + /* Low power mode selected.*/ + + while ((PWR->SR2 & PWR_SR2_REGLPF) == 0U) { + /* Waiting for the regulator to be in low power mode.*/ + } + } + + /* Switching to the final clock source.*/ + RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW_Msk) | (ccp->rcc_cfgr & RCC_CFGR_SW_Msk); + while ((RCC->CFGR & RCC_CFGR_SWS) != ((ccp->rcc_cfgr & RCC_CFGR_SW_Msk) << RCC_CFGR_SWS_Pos)) { + /* Waiting for clock switch.*/ + } + + return false; +} +#endif /* defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ + /*===========================================================================*/ /* Driver interrupt handlers. */ /*===========================================================================*/ @@ -75,6 +633,48 @@ void hal_lld_init(void) { irqInit(); } +#if defined(HAL_LLD_USE_CLOCK_MANAGEMENT) || defined(__DOXYGEN__) +void stm32_clock_init(void) { + +#if !STM32_NO_INIT + /* Reset of all peripherals. + Note, GPIOs are not reset because initialized before this point in + board files.*/ + rccResetAHB1(~0); + rccResetAHB2(~STM32_GPIO_EN_MASK); + rccResetAHB3(~0); + rccResetAPB1R1(~0); + rccResetAPB1R2(~0); + rccResetAPB2(~0); + + /* SYSCFG clock enabled here because it is a multi-functional unit shared + among multiple drivers.*/ + rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, false); + + /* PWR clock enabled.*/ + rccEnablePWRInterface(false); + + /* Backup domain made accessible.*/ + PWR->CR1 |= PWR_CR1_DBP; + + /* Backup domain reset.*/ + bd_reset(); + + /* Static clocks setup.*/ + lse_init(); + lsi_init(); + + /* Selecting the default clock/power/flash configuration.*/ + if (hal_lld_clock_raw_switch(&hal_clkcfg_default)) { + osalSysHalt("clkswc"); + } + + /* Backup domain initializations.*/ + bd_init(); +#endif /* STM32_NO_INIT */ +} + +#else /* !defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ /** * @brief STM32L4xx clocks and PLL initialization. * @note All the involved constants come from the file @p board.h. @@ -111,22 +711,11 @@ void stm32_clock_init(void) { while ((PWR->SR2 & PWR_SR2_VOSF) != 0) /* Wait until regulator is */ ; /* stable. */ - /* Programmable voltage detector enable.*/ -#if STM32_PVD_ENABLE - PWR->CR2 = PWR_CR2_PVDE | (STM32_PLS & STM32_PLS_MASK); -#else - PWR->CR2 = 0; -#endif /* STM32_PVD_ENABLE */ - - /* Enabling independent VDDUSB.*/ -#if HAL_USE_USB - PWR->CR2 |= PWR_CR2_USV; -#endif /* HAL_USE_USB */ - - /* Enabling independent VDDIO2 required by GPIOG.*/ -#if STM32_HAS_GPIOG - PWR->CR2 |= PWR_CR2_IOSV; -#endif /* STM32_HAS_GPIOG */ + /* Additional PWR configurations.*/ + PWR->CR2 = STM32_PWR_CR2; + PWR->CR3 = STM32_PWR_CR3; + PWR->CR4 = STM32_PWR_CR4; + PWR->CR5 = STM32_CR5BITS; /* MSI clock reset.*/ msi_reset(); @@ -205,5 +794,50 @@ void stm32_clock_init(void) { } #endif /* STM32_NO_INIT */ } +#endif /* !defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ + +#if defined(HAL_LLD_USE_CLOCK_MANAGEMENT) || defined(__DOXYGEN__) +/** + * @brief Switches to a different clock configuration + * + * @param[in] ccp pointer to clock a @p halclkcfg_t structure + * @return The clock switch result. + * @retval false if the clock switch succeeded + * @retval true if the clock switch failed + * + * @notapi + */ +bool hal_lld_clock_switch_mode(const halclkcfg_t *ccp) { + + if (hal_lld_clock_check_tree(ccp)) { + return true; + } + + if (hal_lld_clock_raw_switch(ccp)) { + return true; + } + + /* Updating the CMSIS variable.*/ + SystemCoreClock = hal_lld_get_clock_point(CLK_HCLK); + + return false; +} + +/** + * @brief Returns the frequency of a clock point in Hz. + * + * @param[in] clkpt clock point to be returned + * @return The clock point frequency in Hz or zero if the + * frequency is unknown. + * + * @notapi + */ +halfreq_t hal_lld_get_clock_point(halclkpt_t clkpt) { + + osalDbgAssert(clkpt < CLK_ARRAY_SIZE, "invalid clock point"); + + return clock_points[clkpt]; +} +#endif /* defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ /** @} */ diff --git a/os/hal/ports/STM32/STM32L4xx+/hal_lld.h b/os/hal/ports/STM32/STM32L4xx+/hal_lld.h index 3330080aa..6848e5014 100644 --- a/os/hal/ports/STM32/STM32L4xx+/hal_lld.h +++ b/os/hal/ports/STM32/STM32L4xx+/hal_lld.h @@ -66,6 +66,29 @@ #endif /** @} */ +/** + * @name Clock points names + * @{ + */ +#define CLK_SYSCLK 0U +#define CLK_PLLPCLK 1U +#define CLK_PLLQCLK 2U +#define CLK_PLLRCLK 3U +#define CLK_PLLSAI1PCLK 4U +#define CLK_PLLSAI1QCLK 5U +#define CLK_PLLSAI1RCLK 6U +#define CLK_PLLSAI2PCLK 7U +#define CLK_PLLSAI2QCLK 8U +#define CLK_PLLSAI2RCLK 9U +#define CLK_HCLK 10U +#define CLK_PCLK1 11U +#define CLK_PCLK1TIM 12U +#define CLK_PCLK2 13U +#define CLK_PCLK2TIM 14U +#define CLK_MCO 15U +#define CLK_ARRAY_SIZE 16U +/** @} */ + /** * @name PWR_CR1 register bits definitions * @{ @@ -75,21 +98,6 @@ #define STM32_VOS_RANGE2 (2 << 9) /**< Core voltage 1.0 Volts. */ /** @} */ -/** - * @name PWR_CR2 register bits definitions - * @{ - */ -#define STM32_PLS_MASK (7 << 1) /**< PLS bits mask. */ -#define STM32_PLS_LEV0 (0 << 1) /**< PVD level 0. */ -#define STM32_PLS_LEV1 (1 << 1) /**< PVD level 1. */ -#define STM32_PLS_LEV2 (2 << 1) /**< PVD level 2. */ -#define STM32_PLS_LEV3 (3 << 1) /**< PVD level 3. */ -#define STM32_PLS_LEV4 (4 << 1) /**< PVD level 4. */ -#define STM32_PLS_LEV5 (5 << 1) /**< PVD level 5. */ -#define STM32_PLS_LEV6 (6 << 1) /**< PVD level 6. */ -#define STM32_PLS_EXT (7 << 1) /**< PVD level 7. */ -/** @} */ - /** * @name RCC_CFGR register bits definitions * @{ @@ -110,7 +118,7 @@ #define STM32_MCOSEL_MSI (2 << 24) /**< MSI clock on MCO pin. */ #define STM32_MCOSEL_HSI16 (3 << 24) /**< HSI16 clock on MCO pin. */ #define STM32_MCOSEL_HSE (4 << 24) /**< HSE clock on MCO pin. */ -#define STM32_MCOSEL_PLL (5 << 24) /**< PLL clock on MCO pin. */ +#define STM32_MCOSEL_PLLRCLK (5 << 24) /**< PLLR clock on MCO pin. */ #define STM32_MCOSEL_LSI (6 << 24) /**< LSI clock on MCO pin. */ #define STM32_MCOSEL_LSE (7 << 24) /**< LSE clock on MCO pin. */ #define STM32_MCOSEL_HSI48 (8 << 24) /**< HSI48 clock on MCO pin. */ @@ -300,6 +308,13 @@ #define STM32_NO_INIT FALSE #endif +/** + * @brief Enables the dynamic clock handling. + */ +#if !defined(STM32_CLOCK_DYNAMIC) || defined(__DOXYGEN__) +#define STM32_CLOCK_DYNAMIC FALSE +#endif + /** * @brief Core voltage selection. * @note This setting affects all the performance and clock related @@ -311,17 +326,24 @@ #endif /** - * @brief Enables or disables the programmable voltage detector. + * @brief PWR CR2 register initialization value. */ -#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) -#define STM32_PVD_ENABLE FALSE +#if !defined(STM32_PWR_CR2) || defined(__DOXYGEN__) +#define STM32_PWR_CR2 (PWR_CR2_PLS_LEV0 | PWR_CR2_IOSV) #endif /** - * @brief Sets voltage level for programmable voltage detector. + * @brief PWR CR3 register initialization value. */ -#if !defined(STM32_PLS) || defined(__DOXYGEN__) -#define STM32_PLS STM32_PLS_LEV0 +#if !defined(STM32_PWR_CR3) || defined(__DOXYGEN__) +#define STM32_PWR_CR3 (PWR_CR3_EIWF) +#endif + +/** + * @brief PWR CR4 register initialization value. + */ +#if !defined(STM32_PWR_CR4) || defined(__DOXYGEN__) +#define STM32_PWR_CR4 (0U) #endif /** @@ -773,6 +795,11 @@ /* Derived constants and error checks. */ /*===========================================================================*/ +/* Clock handling mode selection.*/ +#if STM32_CLOCK_DYNAMIC == TRUE +#define HAL_LLD_USE_CLOCK_MANAGEMENT +#endif + /* * Configuration-related checks. */ @@ -800,171 +827,142 @@ #endif +/** + * @name System Limits for VOS range 1 + * @{ + */ +#define STM32_VOS1_SYSCLK_MAX 120000000 +#define STM32_VOS1_SYSCLK_MAX_NOBOOST 80000000 +#define STM32_VOS1_HSECLK_MAX 48000000 +#define STM32_VOS1_HSECLK_BYP_MAX 48000000 +#define STM32_VOS1_HSECLK_MIN 8000000 +#define STM32_VOS1_HSECLK_BYP_MIN 8000000 +#define STM32_VOS1_LSECLK_MAX 32768 +#define STM32_VOS1_LSECLK_BYP_MAX 1000000 +#define STM32_VOS1_LSECLK_MIN 32768 +#define STM32_VOS1_LSECLK_BYP_MIN 32768 +#define STM32_VOS1_PLLIN_MAX 16000000 +#define STM32_VOS1_PLLIN_MIN 2660000 +#define STM32_VOS1_PLLVCO_MAX 344000000 +#define STM32_VOS1_PLLVCO_MIN 64000000 +#define STM32_VOS1_PLLP_MAX 120000000 +#define STM32_VOS1_PLLP_MIN 2064500 +#define STM32_VOS1_PLLQ_MAX 120000000 +#define STM32_VOS1_PLLQ_MIN 8000000 +#define STM32_VOS1_PLLR_MAX 120000000 +#define STM32_VOS1_PLLR_MIN 8000000 +#define STM32_VOS1_PCLK1_MAX 120000000 +#define STM32_VOS1_PCLK2_MAX 120000000 +#define STM32_VOS1_ADCCLK_MAX 80000000 + +#define STM32_VOS1_0WS_THRESHOLD 20000000 +#define STM32_VOS1_1WS_THRESHOLD 40000000 +#define STM32_VOS1_2WS_THRESHOLD 60000000 +#define STM32_VOS1_3WS_THRESHOLD 80000000 +#define STM32_VOS1_4WS_THRESHOLD 100000000 +#define STM32_VOS1_5WS_THRESHOLD 120000000 +/** @} */ + +/** + * @name System Limits for VOS range 2 + * @{ + */ +#define STM32_VOS2_SYSCLK_MAX 0 +#define STM32_VOS2_SYSCLK_MAX_NOBOOST 26000000 +#define STM32_VOS2_HSECLK_MAX 26000000 +#define STM32_VOS2_HSECLK_BYP_MAX 26000000 +#define STM32_VOS2_HSECLK_MIN 8000000 +#define STM32_VOS2_HSECLK_BYP_MIN 8000000 +#define STM32_VOS2_LSECLK_MAX 32768 +#define STM32_VOS2_LSECLK_BYP_MAX 1000000 +#define STM32_VOS2_LSECLK_MIN 32768 +#define STM32_VOS2_LSECLK_BYP_MIN 32768 +#define STM32_VOS2_PLLIN_MAX 16000000 +#define STM32_VOS2_PLLIN_MIN 2660000 +#define STM32_VOS2_PLLVCO_MAX 128000000 +#define STM32_VOS2_PLLVCO_MIN 64000000 +#define STM32_VOS2_PLLP_MAX 26000000 +#define STM32_VOS2_PLLP_MIN 2064500 +#define STM32_VOS2_PLLQ_MAX 26000000 +#define STM32_VOS2_PLLQ_MIN 8000000 +#define STM32_VOS2_PLLR_MAX 26000000 +#define STM32_VOS2_PLLR_MIN 8000000 +#define STM32_VOS2_PCLK1_MAX 26000000 +#define STM32_VOS2_PCLK2_MAX 26000000 +#define STM32_VOS2_ADCCLK_MAX 26000000 + +#define STM32_VOS2_0WS_THRESHOLD 8000000 +#define STM32_VOS2_1WS_THRESHOLD 16000000 +#define STM32_VOS2_2WS_THRESHOLD 26000000 +#define STM32_VOS2_3WS_THRESHOLD 0 +#define STM32_VOS2_4WS_THRESHOLD 0 +#define STM32_VOS2_5WS_THRESHOLD 0 +/** @} */ + /* Voltage related limits.*/ #if (STM32_VOS == STM32_VOS_RANGE1) || defined(__DOXYGEN__) -/** - * @name System Limits - * @{ - */ -/** - * @brief Maximum SYSCLK clock frequency in boost mode. - */ -#define STM32_SYSCLK_MAX 120000000 +#define STM32_SYSCLK_MAX STM32_VOS1_SYSCLK_MAX +#define STM32_SYSCLK_MAX_NOBOOST STM32_VOS1_SYSCLK_MAX_NOBOOST +#define STM32_HSECLK_MAX STM32_VOS1_HSECLK_MAX +#define STM32_HSECLK_BYP_MAX STM32_VOS1_HSECLK_BYP_MAX +#define STM32_HSECLK_MIN STM32_VOS1_HSECLK_MIN +#define STM32_HSECLK_BYP_MIN STM32_VOS1_HSECLK_BYP_MIN +#define STM32_LSECLK_MAX STM32_VOS1_LSECLK_MAX +#define STM32_LSECLK_BYP_MAX STM32_VOS1_LSECLK_BYP_MAX +#define STM32_LSECLK_MIN STM32_VOS1_LSECLK_MIN +#define STM32_LSECLK_BYP_MIN STM32_VOS1_LSECLK_BYP_MIN +#define STM32_PLLIN_MAX STM32_VOS1_PLLIN_MAX +#define STM32_PLLIN_MIN STM32_VOS1_PLLIN_MIN +#define STM32_PLLVCO_MAX STM32_VOS1_PLLVCO_MAX +#define STM32_PLLVCO_MIN STM32_VOS1_PLLVCO_MIN +#define STM32_PLLP_MAX STM32_VOS1_PLLP_MAX +#define STM32_PLLP_MIN STM32_VOS1_PLLP_MIN +#define STM32_PLLQ_MAX STM32_VOS1_PLLQ_MAX +#define STM32_PLLQ_MIN STM32_VOS1_PLLQ_MIN +#define STM32_PLLR_MAX STM32_VOS1_PLLR_MAX +#define STM32_PLLR_MIN STM32_VOS1_PLLR_MIN +#define STM32_PCLK1_MAX STM32_VOS1_PCLK1_MAX +#define STM32_PCLK2_MAX STM32_VOS1_PCLK2_MAX +#define STM32_ADCCLK_MAX STM32_VOS1_ADCCLK_MAX -/** - * @brief Maximum SYSCLK clock frequency in normal mode. - */ -#define STM32_SYSCLK_NOBOOST_MAX 80000000 - -/** - * @brief Maximum HSE clock frequency at current voltage setting. - */ -#define STM32_HSECLK_MAX 48000000 - -/** - * @brief Maximum HSE clock frequency using an external source. - */ -#define STM32_HSECLK_BYP_MAX 48000000 - -/** - * @brief Minimum HSE clock frequency. - */ -#define STM32_HSECLK_MIN 8000000 - -/** - * @brief Minimum HSE clock frequency using an external source. - */ -#define STM32_HSECLK_BYP_MIN 8000000 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSECLK_MAX 32768 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSECLK_BYP_MAX 1000000 - -/** - * @brief Minimum LSE clock frequency. - */ -#define STM32_LSECLK_MIN 32768 - -/** - * @brief Minimum LSE clock frequency. - */ -#define STM32_LSECLK_BYP_MIN 32768 - -/** - * @brief Maximum PLLs input clock frequency. - */ -#define STM32_PLLIN_MAX 16000000 - -/** - * @brief Minimum PLLs input clock frequency. - */ -#define STM32_PLLIN_MIN 2660000 - -/** - * @brief Maximum VCO clock frequency at current voltage setting. - */ -#define STM32_PLLVCO_MAX 344000000 - -/** - * @brief Minimum VCO clock frequency at current voltage setting. - */ -#define STM32_PLLVCO_MIN 64000000 - -/** - * @brief Maximum PLL-P output clock frequency. - */ -#define STM32_PLLP_MAX 120000000 - -/** - * @brief Minimum PLL-P output clock frequency. - */ -#define STM32_PLLP_MIN 2064500 - -/** - * @brief Maximum PLL-Q output clock frequency. - */ -#define STM32_PLLQ_MAX 120000000 - -/** - * @brief Minimum PLL-Q output clock frequency. - */ -#define STM32_PLLQ_MIN 8000000 - -/** - * @brief Maximum PLL-R output clock frequency. - */ -#define STM32_PLLR_MAX 120000000 - -/** - * @brief Minimum PLL-R output clock frequency. - */ -#define STM32_PLLR_MIN 8000000 - -/** - * @brief Maximum APB1 clock frequency. - */ -#define STM32_PCLK1_MAX 120000000 - -/** - * @brief Maximum APB2 clock frequency. - */ -#define STM32_PCLK2_MAX 120000000 - -/** - * @brief Maximum ADC clock frequency. - */ -#define STM32_ADCCLK_MAX 80000000 -/** @} */ - -/** - * @name Flash Wait states - * @{ - */ -#define STM32_0WS_THRESHOLD 20000000 -#define STM32_1WS_THRESHOLD 40000000 -#define STM32_2WS_THRESHOLD 60000000 -#define STM32_3WS_THRESHOLD 80000000 -#define STM32_4WS_THRESHOLD 100000000 -#define STM32_5WS_THRESHOLD 120000000 -/** @} */ +#define STM32_0WS_THRESHOLD STM32_VOS1_0WS_THRESHOLD +#define STM32_1WS_THRESHOLD STM32_VOS1_1WS_THRESHOLD +#define STM32_2WS_THRESHOLD STM32_VOS1_2WS_THRESHOLD +#define STM32_3WS_THRESHOLD STM32_VOS1_3WS_THRESHOLD +#define STM32_4WS_THRESHOLD STM32_VOS1_4WS_THRESHOLD +#define STM32_5WS_THRESHOLD STM32_VOS1_5WS_THRESHOLD #elif STM32_VOS == STM32_VOS_RANGE2 -#define STM32_SYSCLK_MAX 26000000 -#define STM32_SYSCLK_NOBOOST_MAX 26000000 -#define STM32_HSECLK_MAX 26000000 -#define STM32_HSECLK_BYP_MAX 26000000 -#define STM32_HSECLK_MIN 8000000 -#define STM32_HSECLK_BYP_MIN 8000000 -#define STM32_LSECLK_MAX 32768 -#define STM32_LSECLK_BYP_MAX 1000000 -#define STM32_LSECLK_MIN 32768 -#define STM32_LSECLK_BYP_MIN 32768 -#define STM32_PLLIN_MAX 16000000 -#define STM32_PLLIN_MIN 2660000 -#define STM32_PLLVCO_MAX 128000000 -#define STM32_PLLVCO_MIN 64000000 -#define STM32_PLLP_MAX 26000000 -#define STM32_PLLP_MIN 2064500 -#define STM32_PLLQ_MAX 26000000 -#define STM32_PLLQ_MIN 8000000 -#define STM32_PLLR_MAX 26000000 -#define STM32_PLLR_MIN 8000000 -#define STM32_PCLK1_MAX 26000000 -#define STM32_PCLK2_MAX 26000000 -#define STM32_ADCCLK_MAX 26000000 +#define STM32_SYSCLK_MAX STM32_VOS2_SYSCLK_MAX +#define STM32_SYSCLK_MAX_NOBOOST STM32_VOS2_SYSCLK_MAX_NOBOOST +#define STM32_HSECLK_MAX STM32_VOS2_HSECLK_MAX +#define STM32_HSECLK_BYP_MAX STM32_VOS2_HSECLK_BYP_MAX +#define STM32_HSECLK_MIN STM32_VOS2_HSECLK_MIN +#define STM32_HSECLK_BYP_MIN STM32_VOS2_HSECLK_BYP_MIN +#define STM32_LSECLK_MAX STM32_VOS2_LSECLK_MAX +#define STM32_LSECLK_BYP_MAX STM32_VOS2_LSECLK_BYP_MAX +#define STM32_LSECLK_MIN STM32_VOS2_LSECLK_MIN +#define STM32_LSECLK_BYP_MIN STM32_VOS2_LSECLK_BYP_MIN +#define STM32_PLLIN_MAX STM32_VOS2_PLLIN_MAX +#define STM32_PLLIN_MIN STM32_VOS2_PLLIN_MIN +#define STM32_PLLVCO_MAX STM32_VOS2_PLLVCO_MAX +#define STM32_PLLVCO_MIN STM32_VOS2_PLLVCO_MIN +#define STM32_PLLP_MAX STM32_VOS2_PLLP_MAX +#define STM32_PLLP_MIN STM32_VOS2_PLLP_MIN +#define STM32_PLLQ_MAX STM32_VOS2_PLLQ_MAX +#define STM32_PLLQ_MIN STM32_VOS2_PLLQ_MIN +#define STM32_PLLR_MAX STM32_VOS2_PLLR_MAX +#define STM32_PLLR_MIN STM32_VOS2_PLLR_MIN +#define STM32_PCLK1_MAX STM32_VOS2_PCLK1_MAX +#define STM32_PCLK2_MAX STM32_VOS2_PCLK2_MAX +#define STM32_ADCCLK_MAX STM32_VOS2_ADCCLK_MAX -#define STM32_0WS_THRESHOLD 8000000 -#define STM32_1WS_THRESHOLD 16000000 -#define STM32_2WS_THRESHOLD 26000000 -#define STM32_3WS_THRESHOLD 0 -#define STM32_4WS_THRESHOLD 0 -#define STM32_5WS_THRESHOLD 0 +#define STM32_0WS_THRESHOLD STM32_VOS2_0WS_THRESHOLD +#define STM32_1WS_THRESHOLD STM32_VOS2_1WS_THRESHOLD +#define STM32_2WS_THRESHOLD STM32_VOS2_2WS_THRESHOLD +#define STM32_3WS_THRESHOLD STM32_VOS2_3WS_THRESHOLD +#define STM32_4WS_THRESHOLD STM32_VOS2_4WS_THRESHOLD +#define STM32_5WS_THRESHOLD STM32_VOS2_5WS_THRESHOLD #else #error "invalid STM32_VOS value specified" @@ -996,7 +994,7 @@ L4 devices.*/ #if (STM32_MCOSEL == STM32_MCOSEL_HSI16) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLRCLK) && \ (STM32_PLLSRC == STM32_PLLSRC_HSI16)) #error "HSI16 not enabled, required by STM32_MCOSEL" #endif @@ -1085,7 +1083,7 @@ #endif #if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLRCLK) && \ (STM32_PLLSRC == STM32_PLLSRC_HSE)) #error "HSE not enabled, required by STM32_MCOSEL" #endif @@ -1436,10 +1434,10 @@ * @brief USART1 clock frequency. */ #if (STM32_USART1SEL == STM32_USART1SEL_PCLK2) || defined(__DOXYGEN__) -#define STM32_USART1CLK STM32_PCLK2 +#define STM32_USART1CLK hal_lld_get_clock_point(CLK_PCLK2) #elif STM32_USART1SEL == STM32_USART1SEL_SYSCLK -#define STM32_USART1CLK STM32_SYSCLK +#define STM32_USART1CLK hal_lld_get_clock_point(CLK_SYSCLK) #elif STM32_USART1SEL == STM32_USART1SEL_HSI16 #define STM32_USART1CLK STM32_HSI16CLK @@ -1455,10 +1453,10 @@ * @brief USART2 clock frequency. */ #if (STM32_USART2SEL == STM32_USART2SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_USART2CLK STM32_PCLK1 +#define STM32_USART2CLK hal_lld_get_clock_point(CLK_PCLK1) #elif STM32_USART2SEL == STM32_USART2SEL_SYSCLK -#define STM32_USART2CLK STM32_SYSCLK +#define STM32_USART2CLK hal_lld_get_clock_point(CLK_SYSCLK) #elif STM32_USART2SEL == STM32_USART2SEL_HSI16 #define STM32_USART2CLK STM32_HSI16CLK @@ -1474,10 +1472,10 @@ * @brief USART3 clock frequency. */ #if (STM32_USART3SEL == STM32_USART3SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_USART3CLK STM32_PCLK1 +#define STM32_USART3CLK hal_lld_get_clock_point(CLK_PCLK1) #elif STM32_USART3SEL == STM32_USART3SEL_SYSCLK -#define STM32_USART3CLK STM32_SYSCLK +#define STM32_USART3CLK hal_lld_get_clock_point(CLK_SYSCLK) #elif STM32_USART3SEL == STM32_USART3SEL_HSI16 #define STM32_USART3CLK STM32_HSI16CLK @@ -1493,10 +1491,10 @@ * @brief UART4 clock frequency. */ #if (STM32_UART4SEL == STM32_UART4SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_UART4CLK STM32_PCLK1 +#define STM32_UART4CLK hal_lld_get_clock_point(CLK_PCLK1) #elif STM32_UART4SEL == STM32_UART4SEL_SYSCLK -#define STM32_UART4CLK STM32_SYSCLK +#define STM32_UART4CLK hal_lld_get_clock_point(CLK_SYSCLK) #elif STM32_UART4SEL == STM32_UART4SEL_HSI16 #define STM32_UART4CLK STM32_HSI16CLK @@ -1512,10 +1510,10 @@ * @brief UART5 clock frequency. */ #if (STM32_UART5SEL == STM32_UART5SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_UART5CLK STM32_PCLK1 +#define STM32_UART5CLK hal_lld_get_clock_point(CLK_PCLK1) #elif STM32_UART5SEL == STM32_UART5SEL_SYSCLK -#define STM32_UART5CLK STM32_SYSCLK +#define STM32_UART5CLK hal_lld_get_clock_point(CLK_SYSCLK) #elif STM32_UART5SEL == STM32_UART5SEL_HSI16 #define STM32_UART5CLK STM32_HSI16CLK @@ -1531,10 +1529,10 @@ * @brief LPUART1 clock frequency. */ #if (STM32_LPUART1SEL == STM32_LPUART1SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_LPUART1CLK STM32_PCLK1 +#define STM32_LPUART1CLK hal_lld_get_clock_point(CLK_PCLK1) #elif STM32_LPUART1SEL == STM32_LPUART1SEL_SYSCLK -#define STM32_LPUART1CLK STM32_SYSCLK +#define STM32_LPUART1CLK hal_lld_get_clock_point(CLK_SYSCLK) #elif STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16 #define STM32_LPUART1CLK STM32_HSI16CLK @@ -1550,10 +1548,10 @@ * @brief I2C1 clock frequency. */ #if (STM32_I2C1SEL == STM32_I2C1SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_I2C1CLK STM32_PCLK1 +#define STM32_I2C1CLK hal_lld_get_clock_point(CLK_PCLK1) #elif STM32_I2C1SEL == STM32_I2C1SEL_SYSCLK -#define STM32_I2C1CLK STM32_SYSCLK +#define STM32_I2C1CLK hal_lld_get_clock_point(CLK_SYSCLK) #elif STM32_I2C1SEL == STM32_I2C1SEL_HSI16 #define STM32_I2C1CLK STM32_HSI16CLK @@ -1566,10 +1564,10 @@ * @brief I2C2 clock frequency. */ #if (STM32_I2C2SEL == STM32_I2C2SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_I2C2CLK STM32_PCLK1 +#define STM32_I2C2CLK hal_lld_get_clock_point(CLK_PCLK1) #elif STM32_I2C2SEL == STM32_I2C2SEL_SYSCLK -#define STM32_I2C2CLK STM32_SYSCLK +#define STM32_I2C2CLK hal_lld_get_clock_point(CLK_SYSCLK) #elif STM32_I2C2SEL == STM32_I2C2SEL_HSI16 #define STM32_I2C2CLK STM32_HSI16CLK @@ -1582,10 +1580,10 @@ * @brief I2C3 clock frequency. */ #if (STM32_I2C3SEL == STM32_I2C3SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_I2C3CLK STM32_PCLK1 +#define STM32_I2C3CLK hal_lld_get_clock_point(CLK_PCLK1) #elif STM32_I2C3SEL == STM32_I2C3SEL_SYSCLK -#define STM32_I2C3CLK STM32_SYSCLK +#define STM32_I2C3CLK hal_lld_get_clock_point(CLK_SYSCLK) #elif STM32_I2C3SEL == STM32_I2C3SEL_HSI16 #define STM32_I2C3CLK STM32_HSI16CLK @@ -1598,10 +1596,10 @@ * @brief I2C4 clock frequency. */ #if (STM32_I2C4SEL == STM32_I2C4SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_I2C4CLK STM32_PCLK1 +#define STM32_I2C4CLK hal_lld_get_clock_point(CLK_PCLK1) #elif STM32_I2C4SEL == STM32_I2C4SEL_SYSCLK -#define STM32_I2C4CLK STM32_SYSCLK +#define STM32_I2C4CLK hal_lld_get_clock_point(CLK_SYSCLK) #elif STM32_I2C4SEL == STM32_I2C4SEL_HSI16 #define STM32_I2C4CLK STM32_HSI16CLK @@ -1614,7 +1612,7 @@ * @brief LPTIM1 clock frequency. */ #if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_LPTIM1CLK STM32_PCLK1 +#define STM32_LPTIM1CLK hal_lld_get_clock_point(CLK_PCLK1) #elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSI #define STM32_LPTIM1CLK STM32_LSICLK @@ -1633,7 +1631,7 @@ * @brief LPTIM2 clock frequency. */ #if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_LPTIM2CLK STM32_PCLK1 +#define STM32_LPTIM2CLK hal_lld_get_clock_point(CLK_PCLK1) #elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSI #define STM32_LPTIM2CLK STM32_LSICLK @@ -1763,7 +1761,7 @@ #define STM32_ADCCLK STM32_PLLSAI1_R_CLKOUT #elif STM32_ADCSEL == STM32_ADCSEL_SYSCLK -#define STM32_ADCCLK STM32_SYSCLK +#define STM32_ADCCLK hal_lld_get_clock_point(CLK_SYSCLK) #else #error "invalid source selected for ADC clock" @@ -1773,10 +1771,10 @@ * @brief DFSDM clock frequency. */ #if (STM32_DFSDMSEL == STM32_DFSDMSEL_PCLK2) || defined(__DOXYGEN__) -#define STM32_DFSDMCLK STM32_PCLK2 +#define STM32_DFSDMCLK hal_lld_get_clock_point(CLK_PCLK2) #elif STM32_DFSDMSEL == STM32_DFSDMSEL_SYSCLK -#define STM32_DFSDMCLK STM32_SYSCLK +#define STM32_DFSDMCLK hal_lld_get_clock_point(CLK_SYSCLK) #else #error "invalid source selected for DFSDM clock" @@ -1810,7 +1808,7 @@ * @brief OSPI clock frequency. */ #if (STM32_OSPISEL == STM32_OSPISEL_SYSCLK) || defined(__DOXYGEN__) -#define STM32_OSPICLK STM32_SYSCLK +#define STM32_OSPICLK hal_lld_get_clock_point(CLK_SYSCLK) #elif STM32_OSPISEL == STM32_OSPISEL_MSI #define STM32_OSPICLK STM32_MSICLK @@ -1823,30 +1821,40 @@ #endif /** - * @brief Clock of timers connected to APB1 + * @brief TIMP1CLK clock frequency. */ #if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK1 (STM32_PCLK1 * 1) + #define STM32_TIMP1CLK (STM32_PCLK1 * 1) #else -#define STM32_TIMCLK1 (STM32_PCLK1 * 2) + #define STM32_TIMP1CLK (STM32_PCLK1 * 2) #endif +/** + * @brief TIMP2CLK clock frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) + #define STM32_TIMP2CLK (STM32_PCLK2 * 1) +#else + #define STM32_TIMP2CLK (STM32_PCLK2 * 2) +#endif + +/** + * @brief Clock of timers connected to APB1. + */ +#define STM32_TIMCLK1 hal_lld_get_clock_point(CLK_PCLK1TIM) + /** * @brief Clock of timers connected to APB2. */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK2 (STM32_PCLK2 * 1) -#else -#define STM32_TIMCLK2 (STM32_PCLK2 * 2) -#endif +#define STM32_TIMCLK2 hal_lld_get_clock_point(CLK_PCLK2TIM) /** * @brief Voltage boost settings. */ -#if (STM32_SYSCLK <= STM32_SYSCLK_NOBOOST_MAX) || defined(__DOXYGEN__) -#define STM32_R1MODE PWR_CR5_R1MODE +#if (STM32_SYSCLK > STM32_SYSCLK_MAX_NOBOOST) || defined(__DOXYGEN__) +#define STM32_CR5BITS 0 #else -#define STM32_R1MODE 0 +#define STM32_CR5BITS PWR_CR5_R1MODE #endif /** @@ -1864,8 +1872,11 @@ #elif STM32_HCLK <= STM32_3WS_THRESHOLD #define STM32_FLASHBITS FLASH_ACR_LATENCY_3WS -#else +#elif STM32_HCLK <= STM32_4WS_THRESHOLD #define STM32_FLASHBITS FLASH_ACR_LATENCY_4WS + +#else +#define STM32_FLASHBITS FLASH_ACR_LATENCY_5WS #endif /** @@ -1883,18 +1894,82 @@ #elif STM32_MSICLK <= STM32_3WS_THRESHOLD #define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_3WS -#else +#elif STM32_MSICLK <= STM32_4WS_THRESHOLD #define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_4WS + +#else +#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_5WS #endif /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ +/** + * @brief Type of a clock point identifier. + */ +typedef unsigned halclkpt_t; + +#if defined(HAL_LLD_USE_CLOCK_MANAGEMENT) || defined(__DOXYGEN__) +/** + * @brief Type of a clock point frequency in Hz. + */ +typedef uint32_t halfreq_t; + +/** + * @brief Type of a clock configuration structure. + */ +typedef struct { + uint32_t pwr_cr1; + uint32_t pwr_cr2; + uint32_t pwr_cr3; + uint32_t pwr_cr4; + uint32_t pwr_cr5; + uint32_t rcc_cr; + uint32_t rcc_cfgr; + uint32_t rcc_pllcfgr; + uint32_t rcc_pllsai1cfgr; + uint32_t rcc_pllsai2cfgr; + uint32_t rcc_crrcr; + uint32_t flash_acr; +} halclkcfg_t; +#endif /* defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ + /*===========================================================================*/ /* Driver macros. */ /*===========================================================================*/ +#if !defined(HAL_LLD_USE_CLOCK_MANAGEMENT) +/** + * @brief Returns the frequency of a clock point in Hz. + * @note Static implementation. + * + * @param[in] clkpt clock point to be returned + * @return The clock point frequency in Hz or zero if the + * frequency is unknown. + * + * @notapi + */ +#define hal_lld_get_clock_point(clkpt) \ + ((clkpt) == CLK_SYSCLK ? STM32_SYSCLK : \ + (clkpt) == CLK_HCLK ? STM32_HCLK : \ + (clkpt) == CLK_PCLK1 ? STM32_PCLK1 : \ + (clkpt) == CLK_PLLPCLK ? STM32_PLL_P_CLKOUT : \ + (clkpt) == CLK_PLLQCLK ? STM32_PLL_Q_CLKOUT : \ + (clkpt) == CLK_PLLRCLK ? STM32_PLL_R_CLKOUT : \ + (clkpt) == CLK_PLLSAI1PCLK ? STM32_PLLSAI1_P_CLKOUT : \ + (clkpt) == CLK_PLLSAI1QCLK ? STM32_PLLSAI1_Q_CLKOUT : \ + (clkpt) == CLK_PLLSAI1RCLK ? STM32_PLLSAI1_R_CLKOUT : \ + (clkpt) == CLK_PLLSAI2PCLK ? STM32_PLLSAI2_P_CLKOUT : \ + (clkpt) == CLK_PLLSAI2QCLK ? STM32_PLLSAI2_Q_CLKOUT : \ + (clkpt) == CLK_PLLSAI2RCLK ? STM32_PLLSAI2_R_CLKOUT : \ + (clkpt) == CLK_PCLK1TIM ? STM32_TIMP1CLK : \ + (clkpt) == CLK_PCLK2 ? STM32_PCLK2 : \ + (clkpt) == CLK_PCLK2TIM ? STM32_TIMP2CLK : \ + (clkpt) == CLK_MCO ? STM32_MCOCLK : \ + 0U) +#endif /* !defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ + /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ @@ -1909,11 +1984,20 @@ #include "stm32_rcc.h" #include "stm32_tim.h" +#if defined(HAL_LLD_USE_CLOCK_MANAGEMENT) && !defined(__DOXYGEN__) +extern const halclkcfg_t hal_clkcfg_reset; +extern const halclkcfg_t hal_clkcfg_default; +#endif + #ifdef __cplusplus extern "C" { #endif void hal_lld_init(void); void stm32_clock_init(void); +#if defined(HAL_LLD_USE_CLOCK_MANAGEMENT) || defined(__DOXYGEN__) + bool hal_lld_clock_switch_mode(const halclkcfg_t *ccp); + halfreq_t hal_lld_get_clock_point(halclkpt_t clkpt); +#endif /* defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ #ifdef __cplusplus } #endif diff --git a/readme.txt b/readme.txt index 12b191ceb..e5ac59808 100644 --- a/readme.txt +++ b/readme.txt @@ -75,7 +75,7 @@ *** Next *** - NEW: STM32 ADCv3, USARTv2, USARTv3, USBv1 updated for dynamic clocking. -- NEW: Dynamic support implemented for STM32G4xx. +- NEW: Dynamic support implemented for STM32G4, STM32L4+. - NEW: Dynamic clocks support in HAL. - NEW: Reload feature added to RT virtual timers. - NEW: Upgraded the clock initialization for STM32G0, STM32L4 and STM32L4++