This is an automated email from the ASF dual-hosted git repository. jerzy pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit fa2b4b928714b2922f1c8d53e33eccbd161c946c Author: Jerzy Kasenberg <[email protected]> AuthorDate: Thu Oct 30 21:43:14 2025 +0100 mcu/stm32f1: Optimize clock configuration Function SystemClock_Config was using STM32 HAL functions for initial clock configuration. Now code is switched to use STM32 LL functions to reduce footprint. Additional clock configuration syscfg vals are introduced. PLL was force all the time. Now it is possible to specify if PLL should be configured and what is the source for system clock. Signed-off-by: Jerzy Kasenberg <[email protected]> --- hw/mcu/stm/stm32f1xx/src/clock_stm32f1xx.c | 200 ++++++++--------------------- hw/mcu/stm/stm32f1xx/syscfg.yml | 13 ++ 2 files changed, 65 insertions(+), 148 deletions(-) diff --git a/hw/mcu/stm/stm32f1xx/src/clock_stm32f1xx.c b/hw/mcu/stm/stm32f1xx/src/clock_stm32f1xx.c index eaa6b103d..384fcedc9 100644 --- a/hw/mcu/stm/stm32f1xx/src/clock_stm32f1xx.c +++ b/hw/mcu/stm/stm32f1xx/src/clock_stm32f1xx.c @@ -26,6 +26,7 @@ #include "stm32f1xx_hal_rcc.h" #include "stm32f1xx_hal.h" +#include "stm32f1xx_ll_rcc.h" #include <assert.h> /* @@ -42,161 +43,64 @@ #error "At least one of HSE or HSI clock source must be enabled" #endif +#define BUSY_LOOP(cond) \ + while (cond) { \ + } + +_Static_assert(IS_RCC_PLL_MUL(MYNEWT_VAL(STM32_CLOCK_PLL_MUL)), "Invalid PLL MUL"); +_Static_assert(MYNEWT_VAL_STM32_CLOCK_SYSCLK_SOURCE != LL_RCC_SYS_CLKSOURCE_PLL || + MYNEWT_VAL_STM32_CLOCK_PLL, + "PLL not enable and selected as system clock"); + void SystemClock_Config(void) { - RCC_OscInitTypeDef osc_init = {0}; - RCC_ClkInitTypeDef clk_init = {0}; - HAL_StatusTypeDef status; - - /* - * Enable Power Control clock - */ - __HAL_RCC_PWR_CLK_ENABLE(); - - osc_init.OscillatorType = RCC_OSCILLATORTYPE_NONE; - - /* - * LSI is used to clock the independent watchdog and optionally the RTC. - * It can be disabled per user request, but is automatically enabled again - * when the IWDG is started. - * - * XXX currently the watchdog is not optional, so there's no point in - * disabling LSI through syscfg. - */ - osc_init.OscillatorType |= RCC_OSCILLATORTYPE_LSI; -#if MYNEWT_VAL(STM32_CLOCK_LSI) - osc_init.LSIState = RCC_LSI_ON; -#else - osc_init.LSIState = RCC_LSI_OFF; -#endif - - /* - * LSE is only used to clock the RTC. - */ - osc_init.OscillatorType |= RCC_OSCILLATORTYPE_LSE; -#if (MYNEWT_VAL(STM32_CLOCK_LSE) == 0) - osc_init.LSEState = RCC_LSE_OFF; -#elif MYNEWT_VAL(STM32_CLOCK_LSE_BYPASS) - osc_init.LSEState = RCC_LSE_BYPASS; -#else - osc_init.LSEState = RCC_LSE_ON; -#endif - - /* - * HSE Oscillator (can be used as PLL, SYSCLK and RTC clock source) - */ -#if MYNEWT_VAL(STM32_CLOCK_HSE) - osc_init.OscillatorType |= RCC_OSCILLATORTYPE_HSE; -#if MYNEWT_VAL(STM32_CLOCK_HSE_BYPASS) - osc_init.HSEState = RCC_HSE_BYPASS; -#else - osc_init.HSEState = RCC_HSE_ON; -#endif -#endif - - /* - * HSI Oscillator (can be used as PLL and SYSCLK clock source). It is - * already turned on by default but a new calibration setting might be - * used. If the user chooses to turn it off, it must be turned off after - * SYSCLK was updated to use HSE/PLL. - */ -#if MYNEWT_VAL(STM32_CLOCK_HSI) - osc_init.OscillatorType |= RCC_OSCILLATORTYPE_HSI; - osc_init.HSIState = RCC_HSI_ON; - /* HSI calibration is not optional when HSI is enabled */ - osc_init.HSICalibrationValue = MYNEWT_VAL(STM32_CLOCK_HSI_CALIBRATION); - -#if MYNEWT_VAL(STM32_CLOCK_HSI) && \ - !IS_RCC_CALIBRATION_VALUE(MYNEWT_VAL(STM32_CLOCK_HSI_CALIBRATION)) -#error "Invalid HSI calibration value" -#endif -#endif - - /* - * Default to HSE as source, when both HSE and HSI are enabled. - */ - osc_init.PLL.PLLState = RCC_PLL_ON; -#if MYNEWT_VAL(STM32_CLOCK_HSE) - osc_init.PLL.PLLSource = RCC_PLLSOURCE_HSE; -#else - osc_init.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2; -#endif - -#if !IS_RCC_PLL_MUL(MYNEWT_VAL(STM32_CLOCK_PLL_MUL)) -#error "PLL MUL value is invalid" -#endif - - osc_init.PLL.PLLMUL = MYNEWT_VAL(STM32_CLOCK_PLL_MUL); - -#if !IS_RCC_HSE_PREDIV(MYNEWT_VAL(STM32_CLOCK_PREDIV)) -#error "HSE PREDIV value is invalid" -#endif - osc_init.HSEPredivValue = MYNEWT_VAL(STM32_CLOCK_PREDIV); + __HAL_FLASH_SET_LATENCY(MYNEWT_VAL(STM32_FLASH_LATENCY)); - status = HAL_RCC_OscConfig(&osc_init); - if (status != HAL_OK) { - assert(0); + if (MYNEWT_VAL(STM32_CLOCK_LSI)) { + LL_RCC_LSI_Enable(); } - - /* - * Select PLL as system clock source and configure the HCLK, PCLK1 and - * PCLK2 clocks dividers. HSI and HSE are also valid system clock sources, - * although there is no much point in supporting them now. - */ - clk_init.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | - RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; - clk_init.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; - -#if !IS_RCC_HCLK(MYNEWT_VAL(STM32_CLOCK_AHB_DIVIDER)) -#error "AHB clock divider is invalid" -#endif - -#if !IS_RCC_PCLK(MYNEWT_VAL(STM32_CLOCK_APB1_DIVIDER)) -#error "APB1 clock divider is invalid" -#endif - -#if !IS_RCC_PCLK(MYNEWT_VAL(STM32_CLOCK_APB2_DIVIDER)) -#error "APB2 clock divider is invalid" -#endif - - clk_init.AHBCLKDivider = MYNEWT_VAL(STM32_CLOCK_AHB_DIVIDER); - clk_init.APB1CLKDivider = MYNEWT_VAL(STM32_CLOCK_APB1_DIVIDER); - clk_init.APB2CLKDivider = MYNEWT_VAL(STM32_CLOCK_APB2_DIVIDER); - -#if !IS_FLASH_LATENCY(MYNEWT_VAL(STM32_FLASH_LATENCY)) -#error "Flash latency value is invalid" -#endif - - status = HAL_RCC_ClockConfig(&clk_init, MYNEWT_VAL(STM32_FLASH_LATENCY)); - if (status != HAL_OK) { - assert(0); + if (MYNEWT_VAL(STM32_CLOCK_LSE_BYPASS)) { + LL_RCC_LSE_EnableBypass(); } - -#if ((MYNEWT_VAL(STM32_CLOCK_HSI) == 0) || (MYNEWT_VAL(STM32_CLOCK_HSE) == 0)) - /* - * Turn off HSE/HSI oscillator; this must be done at the end because - * SYSCLK source has to be updated first. - */ - osc_init.OscillatorType = RCC_OSCILLATORTYPE_NONE; -#if (MYNEWT_VAL(STM32_CLOCK_HSE) == 0) - osc_init.OscillatorType |= RCC_OSCILLATORTYPE_HSE; - osc_init.HSEState = RCC_HSE_OFF; -#endif -#if (MYNEWT_VAL(STM32_CLOCK_HSI) == 0) - osc_init.OscillatorType |= RCC_OSCILLATORTYPE_HSI; - osc_init.HSIState = RCC_HSI_OFF; -#endif - osc_init.PLL.PLLState = RCC_PLL_NONE; - - status = HAL_RCC_OscConfig(&osc_init); - if (status != HAL_OK) { - assert(0); + if (MYNEWT_VAL(STM32_CLOCK_LSE)) { + LL_RCC_LSE_Enable(); + } + if (MYNEWT_VAL(STM32_CLOCK_HSE_BYPASS)) { + LL_RCC_HSE_EnableBypass(); + } + if (MYNEWT_VAL(STM32_CLOCK_HSE)) { + LL_RCC_HSE_Enable(); } -#endif -#if PREFETCH_ENABLE - __HAL_FLASH_PREFETCH_BUFFER_ENABLE(); -#endif + LL_RCC_SetAHBPrescaler(MYNEWT_VAL(STM32_CLOCK_AHB_DIVIDER)); + LL_RCC_SetAPB1Prescaler(MYNEWT_VAL(STM32_CLOCK_APB1_DIVIDER)); + LL_RCC_SetAPB2Prescaler(MYNEWT_VAL(STM32_CLOCK_APB2_DIVIDER)); + + BUSY_LOOP(MYNEWT_VAL_STM32_CLOCK_PLL_SOURCE == LL_RCC_PLLSOURCE_HSE && + !LL_RCC_HSE_IsReady()); + BUSY_LOOP(MYNEWT_VAL_STM32_CLOCK_PLL_SOURCE == LL_RCC_PLLSOURCE_HSI_DIV_2 && + !LL_RCC_HSI_IsReady()); + if (MYNEWT_VAL_STM32_CLOCK_PLL) { + LL_RCC_PLL_ConfigDomain_SYS(MYNEWT_VAL_STM32_CLOCK_PLL_SOURCE | + MYNEWT_VAL_STM32_CLOCK_PREDIV, + MYNEWT_VAL_STM32_CLOCK_PLL_MUL); + LL_RCC_PLL_Enable(); + } + BUSY_LOOP(MYNEWT_VAL_STM32_CLOCK_SYSCLK_SOURCE == LL_RCC_PLLSOURCE_HSI_DIV_2 && + !LL_RCC_HSI_IsReady()); + BUSY_LOOP(MYNEWT_VAL_STM32_CLOCK_SYSCLK_SOURCE == LL_RCC_SYS_CLKSOURCE_HSE && + !LL_RCC_HSE_IsReady()); + BUSY_LOOP(MYNEWT_VAL_STM32_CLOCK_SYSCLK_SOURCE == LL_RCC_SYS_CLKSOURCE_PLL && + !LL_RCC_PLL_IsReady()); + LL_RCC_SetSysClkSource(MYNEWT_VAL_STM32_CLOCK_SYSCLK_SOURCE); + + if (MYNEWT_VAL_STM32_CLOCK_PLL_SOURCE == LL_RCC_PLLSOURCE_HSI_DIV_2) { + LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_PLL); + } + if (MYNEWT_VAL_STM32_CLOCK_PLL_SOURCE == LL_RCC_PLLSOURCE_HSE) { + LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_PLL_DIV_1_5); + } } + #endif diff --git a/hw/mcu/stm/stm32f1xx/syscfg.yml b/hw/mcu/stm/stm32f1xx/syscfg.yml index 675e736e1..03d046588 100644 --- a/hw/mcu/stm/stm32f1xx/syscfg.yml +++ b/hw/mcu/stm/stm32f1xx/syscfg.yml @@ -59,14 +59,27 @@ syscfg.defs: description: HSI calibration value value: 'RCC_HSICALIBRATION_DEFAULT' + STM32_CLOCK_PLL: + description: Enable PLL + value: 1 + STM32_CLOCK_PLL_MUL: description: PLL clock multiplication value: 0 + STM32_CLOCK_PLL_SOURCE: + description: Enable PLL + value: LL_RCC_PLLSOURCE_HSI_DIV_2 + STM32_CLOCK_PREDIV: description: HSE clock divider (pre PLL) value: 'RCC_HSE_PREDIV_DIV1' + STM32_CLOCK_SYSCLK_SOURCE: + description: > + System clock selection + value: LL_RCC_SYS_CLKSOURCE_HSI + STM32_CLOCK_AHB_DIVIDER: description: AHB prescaler value: 0
