STM32WL port: clock management added.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@14418 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
vrepetenko 2021-05-22 08:17:45 +00:00
parent 19ef385fca
commit 9de05598fa
3 changed files with 925 additions and 134 deletions

View File

@ -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.
*/

View File

@ -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) */
/** @} */

View File

@ -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