diff --git a/os/hal/include/hal.h b/os/hal/include/hal.h index f91516b61..3c1feefed 100644 --- a/os/hal/include/hal.h +++ b/os/hal/include/hal.h @@ -289,7 +289,7 @@ extern "C" { */ static inline bool halClockSwitchMode(const halclkcfg_t *ccp) { - return hal_clock_switch_mode(ccp); + return hal_lld_clock_switch_mode(ccp); } /** @@ -301,7 +301,7 @@ static inline bool halClockSwitchMode(const halclkcfg_t *ccp) { * * @xclass */ -static inline halfreq_t halClockGetPointX(halclkpoint_t clkpt) { +static inline halfreq_t halClockGetPointX(unsigned clkpt) { return hal_lld_get_clock_point(clkpt); } diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c b/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c index 70d721afe..3bd82a38e 100644 --- a/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c +++ b/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c @@ -407,6 +407,7 @@ #error "STM32_ST_USE_TIMER specifies an unsupported timer" #endif +#if 0 /* TODO remove */ #if ST_CLOCK_SRC % OSAL_ST_FREQUENCY != 0 #error "the selected ST frequency is not obtainable because integer rounding" #endif @@ -414,6 +415,7 @@ #if (ST_CLOCK_SRC / OSAL_ST_FREQUENCY) - 1 > 0xFFFF #error "the selected ST frequency is not obtainable because TIM timer prescaler limits" #endif +#endif #endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ @@ -486,6 +488,10 @@ void st_lld_init(void) { #if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING /* Free running counter mode.*/ + osalDbgAssert((ST_CLOCK_SRC % OSAL_ST_FREQUENCY) == 0U, + "clock rounding error"); + osalDbgAssert(((ST_CLOCK_SRC / OSAL_ST_FREQUENCY) - 1U) < 0x10000, + "clock prescaler overflow"); /* Enabling timer clock.*/ ST_ENABLE_CLOCK(); diff --git a/os/hal/ports/STM32/STM32G4xx/hal_lld.c b/os/hal/ports/STM32/STM32G4xx/hal_lld.c index eb03db1ed..8f5351246 100644 --- a/os/hal/ports/STM32/STM32G4xx/hal_lld.c +++ b/os/hal/ports/STM32/STM32G4xx/hal_lld.c @@ -38,10 +38,130 @@ */ 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_HSIKERON | RCC_CR_HSION, + .rcc_cfgr = RCC_CFGR_SW_HSI, + .rcc_pllcfgr = 0U, + .flash_acr = FLASH_ACR_DBG_SWEN | FLASH_ACR_DCEN | + FLASH_ACR_ICEN | FLASH_ACR_LATENCY_1WS +}; + +/** + * @brief Default clock configuration. + */ +const halclkcfg_t hal_clkcfg_default = { + .pwr_cr1 = STM32_VOS_RANGE1, + .pwr_cr2 = STM32_PWR_CR2, + .pwr_cr3 = STM32_PWR_CR3, + .pwr_cr4 = STM32_PWR_CR4, + .pwr_cr5 = STM32_CR5BITS, + .rcc_cr = 0U +#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, + .flash_acr = FLASH_ACR_DBG_SWEN | 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]; + +/** + * @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[9]; +} system_limits_t; + +/** + * @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} +}; + +/** + * @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} +}; +#endif /* defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ + /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ @@ -85,6 +205,301 @@ __STATIC_INLINE void bd_init(void) { RCC->BDCR = bdcr; } +#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 + */ +bool hal_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 hsi16clk = 0U, hseclk = 0U, pllselclk; + halfreq_t pllpclk = 0U, pllqclk = 0U, pllrclk = 0U; + halfreq_t sysclk, hclk, pclk1, pclk2, pclk1tim, pclk2tim, mcoclk; + uint32_t mcodiv; + + /* 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; + } + + /* 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_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) { + 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 < 8) { + 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_PLLPDIV_Msk) >> RCC_PLLCFGR_PLLPDIV_Pos; + if (pllpdiv == 1U) { + return true; + } + if (pllpdiv == 0U) { + if ((ccp->rcc_pllcfgr & RCC_PLLCFGR_PLLP) == 0U) { + pllpdiv = 7U; + } + else { + pllpdiv = 17U; + } + } + 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 = 2U + (2U * (ccp->rcc_pllcfgr & RCC_PLLCFGR_PLLQ_Msk) >> RCC_PLLCFGR_PLLQ_Pos); + 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 = 2U + (2U * (ccp->rcc_pllcfgr & RCC_PLLCFGR_PLLR_Msk) >> RCC_PLLCFGR_PLLR_Pos); + 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 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_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; + + /* 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_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_EIWF; + PWR->CR4 = 0U; + + /* Making sure HSI is activated.*/ + RCC->CR |= RCC_CR_HSION; + while ((RCC->CR & RCC_CR_HSIRDY) == 0U) { + } + + /* Disabling boost mode.*/ + PWR->CR5 = PWR_CR5_R1MODE; + + /* Switching to the HSI oscillator.*/ + RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW_Msk) | RCC_CFGR_SW_HSI; + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) { + /* Waiting for clock switch.*/ + } + + /* Resetting flash ACR settings to the default value.*/ + FLASH->ACR = 0x00040601U; + + /* HSE setup.*/ + if ((ccp->rcc_cr & RCC_CR_HSEON) == 0U) { + RCC->CR &= ~RCC_CR_HSEON; + } + else { + RCC->CR |= RCC_CR_HSEON; + while ((RCC->CR & RCC_CR_HSERDY) == 0U) { + /* Waiting for HSE activation.*/ + } + } + + /* PLL setup.*/ + RCC->PLLCFGR = ccp->rcc_pllcfgr; + + /* HSI, HSE, PLL enabled if specified.*/ + RCC->CR = ccp->rcc_cr; + + /* PLL activation polling if required.*/ + if ((ccp->rcc_cr & RCC_CR_PLLON) != 0U) { + while ((RCC->CR & RCC_CR_PLLRDY) == 0U) { + /* Waiting for PLL 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->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; + + /* 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. */ /*===========================================================================*/ @@ -100,6 +515,12 @@ __STATIC_INLINE void bd_init(void) { */ void hal_lld_init(void) { +#if defined(HAL_LLD_USE_CLOCK_MANAGEMENT) + if (hal_clock_check_tree(&hal_clkcfg_default)) { + osalSysHalt("clkcfg"); + } +#endif + /* DMA subsystems initialization.*/ #if defined(STM32_DMA_REQUIRED) dmaInit(); @@ -112,6 +533,7 @@ void hal_lld_init(void) { irqInit(); } +#if defined(HAL_LLD_USE_CLOCK_MANAGEMENT) || defined(__DOXYGEN__) /** * @brief STM32L4xx clocks and PLL initialization. * @note All the involved constants come from the file @p board.h. @@ -121,6 +543,51 @@ void hal_lld_init(void) { */ 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 enable.*/ +#if (HAL_USE_RTC == TRUE) && defined(RCC_APBENR1_RTCAPBEN) + rccEnableAPB1R1(RCC_APB1ENR1_PWREN | RCC_APB1ENR1_RTCAPBEN, false) +#else + rccEnableAPB1R1(RCC_APB1ENR1_PWREN, false) +#endif + + /* 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) */ +void stm32_clock_init(void) { + #if !STM32_NO_INIT /* Reset of all peripherals. @@ -201,5 +668,47 @@ 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_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(unsigned 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/STM32G4xx/hal_lld.h b/os/hal/ports/STM32/STM32G4xx/hal_lld.h index 0271e080c..f717e092b 100644 --- a/os/hal/ports/STM32/STM32G4xx/hal_lld.h +++ b/os/hal/ports/STM32/STM32G4xx/hal_lld.h @@ -80,6 +80,23 @@ #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_MCO 9U +#define CLK_ARRAY_SIZE 10U +/** @} */ + /** * @name VOS field definitions * @{ @@ -266,6 +283,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 @@ -590,6 +614,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. */ @@ -762,7 +791,7 @@ #elif STM32_VOS == STM32_VOS_RANGE2 #define STM32_SYSCLK_MAX 26000000 -#define STM32_SYSCLK_MAX_NOBOOST 150000000 +#define STM32_SYSCLK_MAX_NOBOOST 26000000 #define STM32_HSECLK_MAX 26000000 #define STM32_HSECLK_BYP_MAX 26000000 #define STM32_HSECLK_MIN 8000000 @@ -1069,7 +1098,7 @@ #define STM32_MCODIVCLK 0 #elif STM32_MCOSEL == STM32_MCOSEL_SYSCLK - #define STM32_MCODIVCLK STM32_SYSCLK + #define STM32_MCODIVCLK hal_lld_get_clock_point(CLK_SYSCLK) #elif STM32_MCOSEL == STM32_MCOSEL_HSI16 #define STM32_MCODIVCLK STM32_HSI16CLK @@ -1078,7 +1107,7 @@ #define STM32_MCODIVCLK STM32_HSECLK #elif STM32_MCOSEL == STM32_MCOSEL_PLLRCLK - #define STM32_MCODIVCLK STM32_PLL_R_CLKOUT + #define STM32_MCODIVCLK hal_lld_get_clock_point(CLK_PLLRCLK) #elif STM32_MCOSEL == STM32_MCOSEL_LSI #define STM32_MCODIVCLK STM32_LSICLK @@ -1138,10 +1167,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 @@ -1157,10 +1186,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 @@ -1176,10 +1205,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 @@ -1195,10 +1224,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 @@ -1214,10 +1243,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 @@ -1233,10 +1262,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 @@ -1252,10 +1281,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 @@ -1268,10 +1297,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 @@ -1284,10 +1313,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 @@ -1300,10 +1329,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 @@ -1316,7 +1345,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 @@ -1335,10 +1364,10 @@ * @brief SAI1 clock frequency. */ #if (STM32_SAI1SEL == STM32_SAI1SEL_SYSCLK) || defined(__DOXYGEN__) - #define STM32_SAI1CLK STM32_SYSCLK + #define STM32_SAI1CLK hal_lld_get_clock_point(CLK_SYSCLK) #elif STM32_SAI1SEL == STM32_SAI1SEL_PLLQCLK - #define STM32_SAI1CLK STM32_PLL_Q_CLKOUT + #define STM32_SAI1CLK hal_lld_get_clock_point(CLK_PLLQCLK) #elif STM32_SAI1SEL == STM32_SAI1SEL_HSI16 #define STM32_SAI1CLK STM32_HSI16CLK @@ -1354,10 +1383,10 @@ * @brief I2S23 clock frequency. */ #if (STM32_I2S23SEL == STM32_I2S23SEL_SYSCLK) || defined(__DOXYGEN__) - #define STM32_I2S23CLK STM32_SYSCLK + #define STM32_I2S23CLK hal_lld_get_clock_point(CLK_SYSCLK) #elif STM32_I2S23SEL == STM32_I2S23SEL_PLLPCLK - #define STM32_I2S23CLK STM32_PLL_P_CLKOUT + #define STM32_I2S23CLK hal_lld_get_clock_point(CLK_PLLPCLK) #elif STM32_I2S23SEL == STM32_I2S23SEL_HSI16 #define STM32_I2S23CLK STM32_HSI16CLK @@ -1376,10 +1405,10 @@ #define STM32_FDCANCLK STM32_HSECLK #elif STM32_FDCANSEL == STM32_FDCANSEL_PLLQCLK - #define STM32_FDCANCLK STM32_PLL_Q_CLKOUT + #define STM32_FDCANCLK hal_lld_get_clock_point(CLK_PLLQCLK) #elif STM32_FDCANSEL == STM32_FDCANSEL_PCLK1 - #define STM32_FDCANCLK STM32_PCLK1 + #define STM32_FDCANCLK hal_lld_get_clock_point(CLK_PCLK1) #else #error "invalid source selected for FDCAN clock" @@ -1392,7 +1421,7 @@ #define STM32_48CLK STM32_HSI48CLK #elif STM32_CLK48SEL == STM32_CLK48SEL_PLLQCLK - #define STM32_48CLK STM32_PLL_Q_CLKOUT + #define STM32_48CLK hal_lld_get_clock_point(CLK_PLLQCLK) #else #error "invalid source selected for 48MHz clock" @@ -1405,10 +1434,10 @@ #define STM32_ADC12CLK 0 #elif STM32_ADC12SEL == STM32_ADC12SEL_PLLPCLK - #define STM32_ADC12CLK STM32_PLL_P_CLKOUT + #define STM32_ADC12CLK hal_lld_get_clock_point(CLK_PLLPCLK) #elif STM32_ADC12SEL == STM32_ADC12SEL_SYSCLK - #define STM32_ADC12CLK STM32_SYSCLK + #define STM32_ADC12CLK hal_lld_get_clock_point(CLK_SYSCLK) #else #error "invalid source selected for ADC clock" @@ -1421,10 +1450,10 @@ #define STM32_ADC345CLK 0 #elif STM32_ADC345SEL == STM32_ADC345SEL_PLLPCLK - #define STM32_ADC345CLK STM32_PLL_P_CLKOUT + #define STM32_ADC345CLK hal_lld_get_clock_point(CLK_PLLPCLK) #elif STM32_ADC345SEL == STM32_ADC345SEL_SYSCLK - #define STM32_ADC345CLK STM32_SYSCLK + #define STM32_ADC345CLK hal_lld_get_clock_point(CLK_SYSCLK) #else #error "invalid source selected for ADC clock" @@ -1451,12 +1480,12 @@ /** * @brief Clock of timers connected to APB1. */ -#define STM32_TIMCLK1 STM32_TIMP1CLK +#define STM32_TIMCLK1 hal_lld_get_clock_point(CLK_PCLK1TIM) /** * @brief Clock of timers connected to APB2. */ -#define STM32_TIMCLK2 STM32_TIMP2CLK +#define STM32_TIMCLK2 hal_lld_get_clock_point(CLK_PCLK2TIM) /** * @brief RNG clock point. @@ -1513,10 +1542,57 @@ /* Driver data structures and types. */ /*===========================================================================*/ +#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 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_MCO ? STM32_MCOCLK : \ + 0U) +#endif /* !defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ + /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ @@ -1531,11 +1607,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(unsigned clkpt); +#endif /* defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ #ifdef __cplusplus } #endif diff --git a/os/hal/templates/hal_lld.c b/os/hal/templates/hal_lld.c index 2cef02481..e0a141880 100644 --- a/os/hal/templates/hal_lld.c +++ b/os/hal/templates/hal_lld.c @@ -84,7 +84,7 @@ void hal_lld_init(void) { * * @notapi */ -bool hal_clock_switch_mode(const halclkcfg_t *ccp) { +bool hal_lld_clock_switch_mode(const halclkcfg_t *ccp) { (void)ccp; @@ -100,7 +100,7 @@ bool hal_clock_switch_mode(const halclkcfg_t *ccp) { * * @notapi */ -halfreq_t hal_lld_get_clock_point(halclkpoint_t clkpt) { +halfreq_t hal_lld_get_clock_point(unsigned clkpt) { (void)clkpt; diff --git a/os/hal/templates/hal_lld.h b/os/hal/templates/hal_lld.h index 3bb909c64..9abb44042 100644 --- a/os/hal/templates/hal_lld.h +++ b/os/hal/templates/hal_lld.h @@ -106,8 +106,8 @@ extern "C" { #endif void hal_lld_init(void); #if defined(HAL_LLD_USE_CLOCK_MANAGEMENT) || defined(__DOXYGEN__) - bool hal_clock_switch_mode(const halclkcfg_t *ccp); - halfreq_t hal_lld_get_clock_point(halclkpoint_t clkpt); + bool hal_lld_clock_switch_mode(const halclkcfg_t *ccp); + halfreq_t hal_lld_get_clock_point(unsigned clkpt); #endif /* defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ #ifdef __cplusplus }