From 9de05598fa787bc4b29a602b16d67751573ea997 Mon Sep 17 00:00:00 2001 From: vrepetenko Date: Sat, 22 May 2021 08:17:45 +0000 Subject: [PATCH] STM32WL port: clock management added. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@14418 27425a3e-05d8-49a3-a47f-9c15f0e5edd8 --- .../RT-STM32WL55JC-NUCLEO64/cfg/mcuconf.h | 4 +- os/hal/ports/STM32/STM32WLxx/hal_lld.c | 625 +++++++++++++++++- os/hal/ports/STM32/STM32WLxx/hal_lld.h | 430 +++++++++--- 3 files changed, 925 insertions(+), 134 deletions(-) diff --git a/demos/STM32/RT-STM32WL55JC-NUCLEO64/cfg/mcuconf.h b/demos/STM32/RT-STM32WL55JC-NUCLEO64/cfg/mcuconf.h index 64bc77bd6..0cbd9e78d 100644 --- a/demos/STM32/RT-STM32WL55JC-NUCLEO64/cfg/mcuconf.h +++ b/demos/STM32/RT-STM32WL55JC-NUCLEO64/cfg/mcuconf.h @@ -37,6 +37,7 @@ * HAL driver system settings. */ #define STM32_NO_INIT FALSE +#define STM32_CLOCK_DYNAMIC FALSE #define STM32_VOS STM32_VOS_RANGE1 #define STM32_PVD_ENABLE FALSE #define STM32_PLS STM32_PLS_LEV0 @@ -64,7 +65,7 @@ #define STM32_MCOSEL STM32_MCOSEL_NOCLOCK #define STM32_MCOPRE STM32_MCOPRE_DIV1 #define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK - +#define STM32_PWR_CR2 (PWR_CR2_PLS_LVL0 | PWR_CR2_PVDE) /* * Peripherals clock sources. @@ -82,7 +83,6 @@ #define STM32_RNGSEL STM32_RNGSEL_LSE #define STM32_RTCSEL STM32_RTCSEL_LSE - /* * IRQ system settings. */ diff --git a/os/hal/ports/STM32/STM32WLxx/hal_lld.c b/os/hal/ports/STM32/STM32WLxx/hal_lld.c index b960c3085..2084f0e03 100644 --- a/os/hal/ports/STM32/STM32WLxx/hal_lld.c +++ b/os/hal/ports/STM32/STM32WLxx/hal_lld.c @@ -28,6 +28,26 @@ /* Driver local definitions. */ /*===========================================================================*/ +/** + * @brief Number of thresholds in the wait states array. + */ +#define STM32_WS_THRESHOLDS 3 + +/** + * @brief FLASH_ACR reset value. + */ +#define STM32_FLASH_ACR_RESET 0x00000600U + +/** + * @brief RCC_CR reset value. + */ +#define STM32_RCC_CR_RESET 0x00000061U + +/** + * @brief MSI range array size. + */ +#define STM32_MSIRANGE_ARRAY_SIZE 12 + /*===========================================================================*/ /* Driver exported variables. */ /*===========================================================================*/ @@ -38,14 +58,518 @@ */ 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_EWRFBUSY, + .pwr_cr4 = 0U, + .rcc_cr = RCC_CR_MSIRANGE_6 | RCC_CR_MSION, + .rcc_cfgr = RCC_CFGR_PPRE2F | RCC_CFGR_PPRE1F | RCC_CFGR_HPREF, + .rcc_extcfgr = 0U, + .rcc_pllcfgr = 0U, + .flash_acr = FLASH_ACR_DCEN | FLASH_ACR_ICEN +}; + +/** + * @brief Default clock configuration. + */ +const halclkcfg_t hal_clkcfg_default = { + .pwr_cr1 = STM32_VOS | PWR_CR1_DBP, + .pwr_cr2 = STM32_PWR_CR2, + .pwr_cr3 = STM32_PWR_CR3, + .pwr_cr4 = STM32_PWR_CR4, + .rcc_cr = RCC_CR_MSIRANGE_6 | RCC_CR_MSION +#if STM32_HSI16_ENABLED + | RCC_CR_HSIKERON | RCC_CR_HSION +#endif +#if STM32_HSE32_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_extcfgr = STM32_SHDHPRE, + .rcc_pllcfgr = STM32_PLLR | STM32_PLLREN | + STM32_PLLQ | STM32_PLLQEN | + STM32_PLLP | STM32_PLLPEN | + STM32_PLLN | STM32_PLLM | + STM32_PLLSRC, + .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] = { + STM32_SYSCLK, + STM32_PLL_P_CLKOUT, + STM32_PLL_Q_CLKOUT, + STM32_PLL_R_CLKOUT, + STM32_HCLK, + STM32_PCLK1, + STM32_TIMP1CLK, + STM32_PCLK2, + STM32_TIMP2CLK, + STM32_HCLK3, + STM32_MCOCLK +}; + +/** + * @brief Type of a structure representing system limits. + */ +typedef struct { + halfreq_t sysclk_max; + 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 = STM32_VOS1_SYSCLK_MAX, + .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} +}; + +/** + * @brief System limits for VOS RANGE2. + */ +static const system_limits_t vos_range2 = { + .sysclk_max = STM32_VOS2_SYSCLK_MAX, + .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} +}; +#endif /* defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ + /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ +/** + * @brief Safe setting of flash ACR register. + * + * @param[in] acr value for the ACR register + */ +static void flash_set_acr(uint32_t acr) { + + FLASH->ACR = acr; + while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != (acr & FLASH_ACR_LATENCY_Msk)) { + /* Waiting for flash wait states setup.*/ + } +} + +#if defined(HAL_LLD_USE_CLOCK_MANAGEMENT) || defined(__DOXYGEN__) +/** + * @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 msirange[STM32_MSIRANGE_ARRAY_SIZE] = + {100000U, 200000U, 400000U, + 800000U, 1000000U, 2000000U, + 4000000U, 8000000U, 16000000U, + 24000000U, 32000000U, 48000000U}; + static const uint32_t hprediv[16] = {1U, 3U, 5U, 1U, 1U, 6U, 10U, 32U, + 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 hsi16clk = 0U, hseclk = 0U, msiclk = 0U, pllselclk; + halfreq_t pllpclk = 0U, pllqclk = 0U, pllrclk = 0U; + halfreq_t sysclk, hclk, pclk1, pclk2, pclk1tim, pclk2tim, hclk3, mcoclk; + uint32_t mcodiv; + uint32_t msiidx, 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.*/ + msiidx = (uint8_t)((ccp->rcc_cr & RCC_CR_MSIRANGE) >> RCC_CR_MSIRANGE_Pos); + if (msiidx >= STM32_MSIRANGE_ARRAY_SIZE) { + return true; + } + msiclk = msirange[msiidx]; + + /* HSI16 clock.*/ + if ((ccp->rcc_cr & RCC_CR_HSION) != 0U) { + hsi16clk = STM32_HSI16CLK; + } + + /* HSE32 clock.*/ + if ((ccp->rcc_cr & RCC_CR_HSEON) != 0U) { + hseclk = STM32_HSECLK; + } + + /* PLL MUX clock.*/ + switch (ccp->rcc_pllcfgr & RCC_PLLCFGR_PLLSRC_Msk) { + case STM32_PLLSRC_HSI16: + pllselclk = hsi16clk; + break; + case STM32_PLLSRC_HSE: + pllselclk = hseclk; + break; + case STM32_PLLSRC_MSI: + pllselclk = msiclk; + break; + default: + pllselclk = 0U; + } + + /* PLL outputs.*/ + if ((ccp->rcc_cr & RCC_CR_PLLON) != 0U) { + uint32_t pllmdiv, pllndiv, pllpdiv, pllqdiv, pllrdiv; + halfreq_t pllvcoclk; + + /* PLL M divider.*/ + pllmdiv = ((ccp->rcc_pllcfgr & RCC_PLLCFGR_PLLM_Msk) >> RCC_PLLCFGR_PLLM_Pos) + 1U; + + /* PLL N divider.*/ + pllndiv = (ccp->rcc_pllcfgr & RCC_PLLCFGR_PLLN_Msk) >> RCC_PLLCFGR_PLLN_Pos; + if (pllndiv < STM32_PLLN_VALUE_MIN) { + return true; + } + + /* PLL VCO frequency.*/ + pllvcoclk = (pllselclk / (halfreq_t)pllmdiv) * (halfreq_t)pllndiv; + + if((pllvcoclk < slp->pllvco_min) || (pllvcoclk > slp->pllvco_max)) { + return true; + } + + /* PLL P output frequency.*/ + pllpdiv = ((ccp->rcc_pllcfgr & RCC_PLLCFGR_PLLP_Msk) >> RCC_PLLCFGR_PLLP_Pos) + 1; + + if ((pllpdiv < STM32_PLLP_VALUE_MIN) || (pllpdiv > STM32_PLLP_VALUE_MAX)) { + return true; + } + + if ((ccp->rcc_pllcfgr & RCC_PLLCFGR_PLLPEN) != 0U) { + pllpclk = pllvcoclk / pllpdiv ; + + if((pllpclk < slp->pllp_min) || (pllpclk > slp->pllp_max)) { + return true; + } + } + + /* PLL Q output frequency.*/ + pllqdiv = ((ccp->rcc_pllcfgr & RCC_PLLCFGR_PLLQ_Msk) >> RCC_PLLCFGR_PLLQ_Pos) + 1; + + if (pllqdiv < STM32_PLLQ_VALUE_MIN) { + return true; + } + + if ((ccp->rcc_pllcfgr & RCC_PLLCFGR_PLLQEN) != 0U) { + pllqclk = pllvcoclk / pllqdiv; + + if((pllqclk < slp->pllq_min) || (pllqclk > slp->pllq_max)) { + return true; + } + } + + /* PLL R output frequency.*/ + pllrdiv = ((ccp->rcc_pllcfgr & RCC_PLLCFGR_PLLR_Msk) >> RCC_PLLCFGR_PLLR_Pos) + 1; + + if (pllrdiv < STM32_PLLR_VALUE_MIN) { + return true; + } + + if ((ccp->rcc_pllcfgr & RCC_PLLCFGR_PLLREN) != 0U) { + pllrclk = pllvcoclk / pllrdiv; + + if((pllrclk < slp->pllr_min) || (pllrclk > slp->pllr_max)) { + return true; + } + } + } + + /* SYSCLK frequency.*/ + switch(ccp->rcc_cfgr & RCC_CFGR_SW_Msk) { + case STM32_SW_HSI16: + sysclk = hsi16clk; + break; + case STM32_SW_HSE: + sysclk = hseclk; + break; + case STM32_SW_PLL: + sysclk = pllrclk; + break; + case STM32_SW_MSI: + sysclk = msiclk; + break; + default: + sysclk = 0U; + } + + if ((sysclk > slp->sysclk_max) || sysclk == 0U) { + return true; + } + + /* LPRUN sysclk check.*/ + if (((ccp->pwr_cr1 & PWR_CR1_LPR_Msk) != 0) && (sysclk > STM32_LPRUN_SYSCLK_MAX) ) { + 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_2) { + 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_2) { + pclk2tim = pclk2; + } + else { + pclk2tim = pclk2 * 2U; + } + + /* HCLK3 frequncy.*/ + hclk3 = sysclk / hprediv[(ccp->rcc_extcfgr & RCC_EXTCFGR_SHDHPRE_Msk) >> RCC_EXTCFGR_SHDHPRE_Pos]; + + /* 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_HSI16: + mcoclk = hsi16clk; + break; + case STM32_MCOSEL_HSE32: + mcoclk = STM32_HSE32CLK; + break; + case STM32_MCOSEL_PLL: + mcoclk = pllrclk; + break; + case STM32_MCOSEL_PLLP: + mcoclk = pllpclk; + break; + case STM32_MCOSEL_PLLQ: + mcoclk = pllqclk; + break; + case STM32_MCOSEL_LSI: + mcoclk = STM32_LSICLK; + break; + case STM32_MCOSEL_LSE: + mcoclk = STM32_LSECLK; + break; + case STM32_MCOSEL_MSI: + mcoclk = msiclk; + 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 (hclk3 > 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_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_HCLK3] = hclk3; + 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; + PWR->CR2 = 0U; + PWR->CR3 = PWR_CR3_EWRFBUSY; + PWR->CR4 = 0U; + + /* 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) { + msi_reset(); + + /* Resetting flash ACR settings to the default value.*/ + flash_set_acr(STM32_FLASH_ACR_RESET); + + /* Resetting all other clock sources and PLLs.*/ + RCC->CR = STM32_RCC_CR_RESET; + while ((RCC->CR & (RCC_CR_HSIRDY | RCC_CR_HSERDY)) != 0U) { + /* Waiting for oscillators to shut down.*/ + } + + } + + /* HSE32 setup, if required, before starting the PLL.*/ + if ((ccp->rcc_cr & RCC_CR_HSEON) != 0U) { + hse32_enable(); + } + + /* HSI setup.*/ + if ((ccp->rcc_cr & RCC_CR_HSION) != 0U) { + hsi16_enable(); + } + + /* PLL setup.*/ + RCC->PLLCFGR = ccp->rcc_pllcfgr; + + /* HSI, HSE32, PLL enabled if specified.*/ + RCC->CR = ccp->rcc_cr; + + /* PLL activation polling if required.*/ + if ((ccp->rcc_cr & RCC_CR_PLLON) != 0U) { + pll_wait_lock(); + } + + /* 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_set_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; + + /* 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); + /* Apply RCC EXTCFGR.*/ + RCC->EXTCFGR = ccp->rcc_extcfgr; + + while ((RCC->CFGR & RCC_CFGR_SWS) != ((ccp->rcc_cfgr & RCC_CFGR_SW_Msk) << RCC_CFGR_SWS_Pos)) { + /* Waiting for clock switch.*/ + } + + /* If MSI is not in configuration then it is finally shut down.*/ + if ((ccp->rcc_cr & RCC_CR_MSION) == 0U) { + msi_disable(); + } + + return false; +} +#endif /* defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ + /*===========================================================================*/ /* Driver interrupt handlers. */ /*===========================================================================*/ @@ -70,6 +594,7 @@ void hal_lld_init(void) { irqInit(); } + /** * @brief STM32WLxx clocks and PLL initialization. * @note All the involved constants come from the file @p board.h. @@ -93,26 +618,44 @@ void stm32_clock_init(void) { rccResetAPB1R2(~0); rccResetAPB2(~0); - /* Flash setup for selected MSI speed setting.*/ - FLASH->ACR = FLASH_ACR_DCEN | FLASH_ACR_ICEN | FLASH_ACR_PRFTEN | - STM32_MSI_FLASHBITS; - /* RTC clock enable.*/ #if HAL_USE_RTC rccEnableAPB1R1(RCC_APB1ENR1_RTCAPBEN, false) #endif +#if defined(HAL_LLD_USE_CLOCK_MANAGEMENT) + /* 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(); +#else /* !defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ + /* Flash setup for selected MSI speed setting.*/ + flash_set_acr(FLASH_ACR_DCEN | FLASH_ACR_ICEN | + FLASH_ACR_PRFTEN |STM32_FLASHBITS); + /* Core voltage setup, backup domain access enabled and left open.*/ PWR->CR1 = STM32_VOS | PWR_CR1_DBP; - while ((PWR->SR2 & PWR_SR2_VOSF) != 0) /* Wait until regulator is */ - ; /* stable. */ + 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 */ + /* Additional PWR configurations.*/ + PWR->CR2 = STM32_PWR_CR2; + PWR->CR3 = STM32_PWR_CR3; + PWR->CR4 = STM32_PWR_CR4; /* MSI clock reset.*/ msi_reset(); @@ -149,13 +692,8 @@ void stm32_clock_init(void) { RCC->CCIPR = ccipr; } - /* Set flash WS's for SYSCLK source */ - if (STM32_FLASHBITS > STM32_MSI_FLASHBITS) { - FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY_Msk) | STM32_FLASHBITS; - while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != - (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { - } - } + /* Set flash WS's according HCLK3.*/ + flash_set_acr((FLASH->ACR & ~FLASH_ACR_LATENCY_Msk) | STM32_FLASHBITS); /* Switching to the configured SYSCLK source if it is different from MSI.*/ #if (STM32_SW != STM32_SW_MSI) @@ -164,15 +702,50 @@ void stm32_clock_init(void) { while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) ; #endif +#endif /* defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ - /* Reduce the flash WS's for SYSCLK source if they are less than MSI WSs */ - if (STM32_FLASHBITS < STM32_MSI_FLASHBITS) { - FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY_Msk) | STM32_FLASHBITS; - while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != - (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { - } - } #endif /* STM32_NO_INIT */ } +#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; + } + + 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/STM32WLxx/hal_lld.h b/os/hal/ports/STM32/STM32WLxx/hal_lld.h index 4dac09f51..0b9828e31 100644 --- a/os/hal/ports/STM32/STM32WLxx/hal_lld.h +++ b/os/hal/ports/STM32/STM32WLxx/hal_lld.h @@ -65,6 +65,24 @@ #endif /** @} */ +/** + * @name Clock points names + * @{ + */ +#define CLK_SYSCLK 0U +#define CLK_PLLPCLK 1U +#define CLK_PLLQCLK 2U +#define CLK_PLLRCLK 3U +#define CLK_HCLK 4U +#define CLK_PCLK1 5U +#define CLK_PCLK1TIM 6U +#define CLK_PCLK2 7U +#define CLK_PCLK2TIM 8U +#define CLK_HCLK3 9U +#define CLK_MCO 10U +#define CLK_ARRAY_SIZE 11U +/** @} */ + /** * @name HSE32 clock sources * @{ @@ -83,20 +101,45 @@ #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. */ -/** @} */ +/* Some ST headers do not have this definition.*/ +#if !defined(PWR_CR2_PLS_LVL0) +#define PWR_CR2_PLS_LVL0 (0x0UL << PWR_CR2_PLS_Pos) +#endif + +/* Some ST headers do not have this definition.*/ +#if !defined(PWR_CR2_PLS_LVL1) +#define PWR_CR2_PLS_LVL1 (0x1UL << PWR_CR2_PLS_Pos) +#endif + +/* Some ST headers do not have this definition.*/ +#if !defined(PWR_CR2_PLS_LVL2) +#define PWR_CR2_PLS_LVL2 (0x2UL << PWR_CR2_PLS_Pos) +#endif + +/* Some ST headers do not have this definition.*/ +#if !defined(PWR_CR2_PLS_LVL3) +#define PWR_CR2_PLS_LVL3 (0x3UL << PWR_CR2_PLS_Pos) +#endif + +/* Some ST headers do not have this definition.*/ +#if !defined(PWR_CR2_PLS_LVL4) +#define PWR_CR2_PLS_LVL4 (0x4UL << PWR_CR2_PLS_Pos) +#endif + +/* Some ST headers do not have this definition.*/ +#if !defined(PWR_CR2_PLS_LVL5) +#define PWR_CR2_PLS_LVL5 (0x5UL << PWR_CR2_PLS_Pos) +#endif + +/* Some ST headers do not have this definition.*/ +#if !defined(PWR_CR2_PLS_LVL6) +#define PWR_CR2_PLS_LVL6 (0x6UL << PWR_CR2_PLS_Pos) +#endif + +/* Some ST headers do not have this definition.*/ +#if !defined(PWR_CR2_PLS_LVL7) +#define PWR_CR2_PLS_LVL7 (0x7UL << PWR_CR2_PLS_Pos) +#endif /** * @name PWR_CR4 register bits definitions @@ -153,6 +196,46 @@ #define STM32_MCOPRE_DIV16 (4 << 28) /**< MCO divided by 16. */ /** @} */ +/* Some ST headers do not have this definition.*/ +#if !defined(RCC_CFGR_SW_MSI) +#define RCC_CFGR_SW_MSI (0x00000000UL) +#endif + +/* Some ST headers do not have this definition.*/ +#if !defined(RCC_CFGR_SW_HSI) +#define RCC_CFGR_SW_HSI (0x00000001UL) +#endif + +/* Some ST headers do not have this definition.*/ +#if !defined(RCC_CFGR_SW_HSE) +#define RCC_CFGR_SW_HSE (0x00000002UL) +#endif + +/* Some ST headers do not have this definition.*/ +#if !defined(RCC_CFGR_SW_PLL) +#define RCC_CFGR_SW_PLL (0x00000003UL) +#endif + +/* Some ST headers do not have this definition.*/ +#if !defined(RCC_CFGR_SWS_HSI) +#define RCC_CFGR_SWS_HSI (0x00000000UL) +#endif + +/* Some ST headers do not have this definition.*/ +#if !defined(RCC_CFGR_SWS_HSI) +#define RCC_CFGR_SWS_HSI (0x00000004UL) +#endif + +/* Some ST headers do not have this definition.*/ +#if !defined(RCC_CFGR_SWS_HSE) +#define RCC_CFGR_SWS_HSE (0x00000008UL) +#endif + +/* Some ST headers do not have this definition.*/ +#if !defined(RCC_CFGR_SWS_PLL) +#define RCC_CFGR_SWS_PLL (0x0000000CUL) +#endif + /** * @name RCC_PLLCFGR register bits definitions * @{ @@ -268,6 +351,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 @@ -279,17 +369,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_LVL0) #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_EWRFBUSY) +#endif + +/** + * @brief PWR CR4 register initialization value. + */ +#if !defined(STM32_PWR_CR4) || defined(__DOXYGEN__) +#define STM32_PWR_CR4 (0U) #endif /** @@ -538,6 +635,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. */ @@ -612,7 +714,65 @@ */ #define STM32_PLLP_VALUE_MIN 2 +/** @} */ +/** + * @brief Low Power Run mode sysclk limit. + */ +#define STM32_LPRUN_SYSCLK_MAX 2000000U + +/** + * @brief Range 1 Voltage related limits. + * @{ + */ +#define STM32_VOS1_SYSCLK_MAX 48000000U +#define STM32_VOS1_LSECLK_MAX 32768U +#define STM32_VOS1_LSECLK_BYP_MAX 1000000U +#define STM32_VOS1_LSECLK_MIN 32768U +#define STM32_VOS1_LSECLK_BYP_MIN 32768U +#define STM32_VOS1_PLLIN_MAX 16000000U +#define STM32_VOS1_PLLIN_MIN 2660000U +#define STM32_VOS1_PLLVCO_MAX 344000000U +#define STM32_VOS1_PLLVCO_MIN 96000000U +#define STM32_VOS1_PLLP_MAX 48000000U +#define STM32_VOS1_PLLP_MIN 3000000U +#define STM32_VOS1_PLLQ_MAX 48000000U +#define STM32_VOS1_PLLQ_MIN 12000000U +#define STM32_VOS1_PLLR_MAX 48000000U +#define STM32_VOS1_PLLR_MIN 12000000U +#define STM32_VOS1_PCLK1_MAX 80000000U +#define STM32_VOS1_PCLK2_MAX 80000000U +#define STM32_VOS1_ADCCLK_MAX 48000000U +#define STM32_VOS1_0WS_THRESHOLD 18000000U +#define STM32_VOS1_1WS_THRESHOLD 36000000U +#define STM32_VOS1_2WS_THRESHOLD 48000000U +/** @} */ + +/** + * @brief Range 2 Voltage related limits. + * @{ + */ +#define STM32_VOS2_SYSCLK_MAX 16000000U +#define STM32_VOS2_LSECLK_MAX 32768U +#define STM32_VOS2_LSECLK_BYP_MAX 1000000U +#define STM32_VOS2_LSECLK_MIN 32768U +#define STM32_VOS2_LSECLK_BYP_MIN 32768U +#define STM32_VOS2_PLLIN_MAX 16000000U +#define STM32_VOS2_PLLIN_MIN 2660000U +#define STM32_VOS2_PLLVCO_MAX 128000000U +#define STM32_VOS2_PLLVCO_MIN 96000000U +#define STM32_VOS2_PLLP_MAX 16000000U +#define STM32_VOS2_PLLP_MIN 3000000U +#define STM32_VOS2_PLLQ_MAX 12000000U +#define STM32_VOS2_PLLQ_MIN 16000000U +#define STM32_VOS2_PLLR_MAX 16000000U +#define STM32_VOS2_PLLR_MIN 12000000U +#define STM32_VOS2_PCLK1_MAX 16000000U +#define STM32_VOS2_PCLK2_MAX 16000000U +#define STM32_VOS2_ADCCLK_MAX 16000000U +#define STM32_VOS2_0WS_THRESHOLD 6000000U +#define STM32_VOS2_1WS_THRESHOLD 12000000U +#define STM32_VOS2_2WS_THRESHOLD 16000000U /** @} */ /* Voltage related limits.*/ @@ -624,125 +784,125 @@ /** * @brief Maximum SYSCLK clock frequency at current voltage setting. */ -#define STM32_SYSCLK_MAX 48000000 +#define STM32_SYSCLK_MAX STM32_VOS1_SYSCLK_MAX /** * @brief Maximum LSE clock frequency. */ -#define STM32_LSECLK_MAX 32768 +#define STM32_LSECLK_MAX STM32_VOS1_LSECLK_MAX /** * @brief Maximum LSE clock frequency. */ -#define STM32_LSECLK_BYP_MAX 1000000 +#define STM32_LSECLK_BYP_MAX STM32_VOS1_LSECLK_BYP_MAX /** * @brief Minimum LSE clock frequency. */ -#define STM32_LSECLK_MIN 32768 +#define STM32_LSECLK_MIN STM32_VOS1_LSECLK_MIN /** * @brief Minimum LSE clock frequency. */ -#define STM32_LSECLK_BYP_MIN 32768 +#define STM32_LSECLK_BYP_MIN STM32_VOS1_LSECLK_BYP_MIN /** * @brief Maximum PLLs input clock frequency. */ -#define STM32_PLLIN_MAX 16000000 +#define STM32_PLLIN_MAX STM32_VOS1_PLLIN_MAX /** * @brief Minimum PLLs input clock frequency. */ -#define STM32_PLLIN_MIN 2660000 +#define STM32_PLLIN_MIN STM32_VOS1_PLLIN_MIN /** * @brief Maximum VCO clock frequency at current voltage setting. */ -#define STM32_PLLVCO_MAX 344000000 +#define STM32_PLLVCO_MAX STM32_VOS1_PLLVCO_MAX /** * @brief Minimum VCO clock frequency at current voltage setting. */ -#define STM32_PLLVCO_MIN 96000000 +#define STM32_PLLVCO_MIN STM32_VOS1_PLLVCO_MIN /** * @brief Maximum PLL-P output clock frequency. */ -#define STM32_PLLP_MAX 48000000 +#define STM32_PLLP_MAX STM32_VOS1_PLLP_MAX /** * @brief Minimum PLL-P output clock frequency. */ -#define STM32_PLLP_MIN 3000000 +#define STM32_PLLP_MIN STM32_VOS1_PLLP_MIN /** * @brief Maximum PLL-Q output clock frequency. */ -#define STM32_PLLQ_MAX 48000000 +#define STM32_PLLQ_MAX STM32_VOS1_PLLQ_MAX /** * @brief Minimum PLL-Q output clock frequency. */ -#define STM32_PLLQ_MIN 12000000 +#define STM32_PLLQ_MIN STM32_VOS1_PLLQ_MIN /** * @brief Maximum PLL-R output clock frequency. */ -#define STM32_PLLR_MAX 48000000 +#define STM32_PLLR_MAX STM32_VOS1_PLLR_MAX /** * @brief Minimum PLL-R output clock frequency. */ -#define STM32_PLLR_MIN 12000000 +#define STM32_PLLR_MIN STM32_VOS1_PLLR_MIN /** * @brief Maximum APB1 clock frequency. */ -#define STM32_PCLK1_MAX 80000000 +#define STM32_PCLK1_MAX STM32_VOS1_PCLK1_MAX /** * @brief Maximum APB2 clock frequency. */ -#define STM32_PCLK2_MAX 80000000 +#define STM32_PCLK2_MAX STM32_VOS1_PCLK2_MAX /** * @brief Maximum ADC clock frequency. */ -#define STM32_ADCCLK_MAX 48000000 +#define STM32_ADCCLK_MAX STM32_VOS1_ADCCLK_MAX /** * @name Flash Wait states * @{ */ -#define STM32_0WS_THRESHOLD 18000000 -#define STM32_1WS_THRESHOLD 36000000 -#define STM32_2WS_THRESHOLD 48000000 +#define STM32_0WS_THRESHOLD STM32_VOS1_0WS_THRESHOLD +#define STM32_1WS_THRESHOLD STM32_VOS1_1WS_THRESHOLD +#define STM32_2WS_THRESHOLD STM32_VOS1_2WS_THRESHOLD /** @} */ #elif STM32_VOS == STM32_VOS_RANGE2 -#define STM32_SYSCLK_MAX 16000000 -#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 16000000 -#define STM32_PLLP_MIN 3000000 -#define STM32_PLLQ_MAX 12000000 -#define STM32_PLLQ_MIN 16000000 -#define STM32_PLLR_MAX 16000000 -#define STM32_PLLR_MIN 12000000 -#define STM32_PCLK1_MAX 16000000 -#define STM32_PCLK2_MAX 16000000 -#define STM32_ADCCLK_MAX 16000000 +#define STM32_SYSCLK_MAX STM32_VOS2_SYSCLK_MAX +#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 6000000 -#define STM32_1WS_THRESHOLD 12000000 -#define STM32_2WS_THRESHOLD 16000000 +#define STM32_0WS_THRESHOLD STM32_VOS2_0WS_THRESHOLD +#define STM32_1WS_THRESHOLD STM32_VOS2_1WS_THRESHOLD +#define STM32_2WS_THRESHOLD STM32_VOS2_2WS_THRESHOLD #else #error "invalid STM32_VOS value specified" @@ -1128,9 +1288,9 @@ * @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 #elif STM32_USART1SEL == STM32_USART1SEL_LSE @@ -1143,9 +1303,9 @@ * @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 #elif STM32_USART2SEL == STM32_USART2SEL_LSE @@ -1158,9 +1318,9 @@ * @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 #elif STM32_LPUART1SEL == STM32_LPUART1SEL_LSE @@ -1173,9 +1333,9 @@ * @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 #else @@ -1186,9 +1346,9 @@ * @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 #else @@ -1199,9 +1359,9 @@ * @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 #else @@ -1212,7 +1372,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 #elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16 @@ -1227,7 +1387,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 #elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_HSI16 @@ -1242,7 +1402,7 @@ * @brief LPTIM3 clock frequency. */ #if (STM32_LPTIM3SEL == STM32_LPTIM3SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_LPTIM3CLK STM32_PCLK1 +#define STM32_LPTIM3CLK hal_lld_get_clock_point(CLK_PCLK1) #elif STM32_LPTIM1SEL == STM32_LPTIM3SEL_LSI #define STM32_LPTIM3CLK STM32_LSICLK #elif STM32_LPTIM1SEL == STM32_LPTIM3SEL_HSI16 @@ -1257,7 +1417,7 @@ * @brief RNG clock point. */ #if (STM32_RNGSEL == STM32_RNGSEL_PLLQ) || defined(__DOXYGEN__) -#define STM32_RNGCLK STM32_PLL_Q_CLKOUT +#define STM32_RNGCLK hal_lld_get_clock_point(CLK_PLLQCLK) #elif STM32_RNGSEL == STM32_RNGSEL_LSI #define STM32_RNGCLK STM32_LSICLK #elif STM32_RNGSEL == STM32_RNGSEL_LSE @@ -1274,67 +1434,116 @@ #elif STM32_ADCSEL == STM32_ADCSEL_HSI16 #define STM32_ADCCLK STM32_HSI16CLK #elif STM32_ADCSEL == STM32_ADCSEL_PLLP -#define STM32_ADCCLK STM32_PLL_P_CLKOUT +#define STM32_ADCCLK hal_lld_get_clock_point(CLK__PLLPCLK) #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" #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 Flash settings. */ -#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) -#define STM32_FLASHBITS 0 +#if (STM32_HCLK3 <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) +#define STM32_FLASHBITS (0U) -#elif STM32_HCLK <= STM32_1WS_THRESHOLD +#elif STM32_HCLK3 <= STM32_1WS_THRESHOLD #define STM32_FLASHBITS FLASH_ACR_LATENCY_0 -#elif STM32_HCLK <= STM32_2WS_THRESHOLD +#elif STM32_HCLK3 <= STM32_2WS_THRESHOLD #define STM32_FLASHBITS FLASH_ACR_LATENCY_1 #endif -/** - * @brief Flash settings for MSI. - */ -#if (STM32_MSICLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) -#define STM32_MSI_FLASHBITS 0 - -#elif STM32_MSICLK <= STM32_1WS_THRESHOLD -#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_0 - -#elif STM32_MSICLK <= STM32_2WS_THRESHOLD -#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_1 - -#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 rcc_cr; + uint32_t rcc_cfgr; + uint32_t rcc_extcfgr; + uint32_t rcc_pllcfgr; + 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_PLLPCLK ? STM32_PLL_P_CLKOUT : \ + (clkpt) == CLK_PLLQCLK ? STM32_PLL_Q_CLKOUT : \ + (clkpt) == CLK_PLLRCLK ? STM32_PLL_R_CLKOUT : \ + (clkpt) == CLK_HCLK ? STM32_HCLK : \ + (clkpt) == CLK_PCLK1 ? STM32_PCLK1 : \ + (clkpt) == CLK_PCLK1TIM ? STM32_TIMP1CLK : \ + (clkpt) == CLK_PCLK2 ? STM32_PCLK2 : \ + (clkpt) == CLK_PCLK2TIM ? STM32_TIMP2CLK : \ + (clkpt) == CLK_HCLK3 ? STM32_HCLK3 : \ + (clkpt) == CLK_MCO ? STM32_MCOCLK : \ + 0U) +#endif /* !defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ + /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ @@ -1349,11 +1558,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