diff --git a/include/libopencm3/stm32/f4/rcc.h b/include/libopencm3/stm32/f4/rcc.h index 4e195f00..ff6b1c48 100644 --- a/include/libopencm3/stm32/f4/rcc.h +++ b/include/libopencm3/stm32/f4/rcc.h @@ -185,6 +185,10 @@ #define RCC_CFGR_MCOPRE_DIV_4 0x6 #define RCC_CFGR_MCOPRE_DIV_5 0x7 +/* PLLSRC: PLL entry clock source */ +#define RCC_CFGR_PLLSRC_HSI_CLK 0x0 +#define RCC_CFGR_PLLSRC_HSE_CLK 0x1 + /* I2SSRC: I2S clock selection */ #define RCC_CFGR_I2SSRC (1 << 23) @@ -780,6 +784,7 @@ struct rcc_clock_scale { uint8_t pllp; uint8_t pllq; uint8_t pllr; + uint8_t pll_source; uint32_t flash_config; uint8_t hpre; uint8_t ppre1; @@ -1095,6 +1100,7 @@ void rcc_set_main_pll_hsi(uint32_t pllm, uint32_t plln, uint32_t pllp, void rcc_set_main_pll_hse(uint32_t pllm, uint32_t plln, uint32_t pllp, uint32_t pllq, uint32_t pllr); uint32_t rcc_system_clock_source(void); +void rcc_clock_setup_pll(const struct rcc_clock_scale *clock); void rcc_clock_setup_hse_3v3(const struct rcc_clock_scale *clock); END_DECLS diff --git a/lib/stm32/f4/rcc.c b/lib/stm32/f4/rcc.c index 8a92ec40..aecbea69 100644 --- a/lib/stm32/f4/rcc.c +++ b/lib/stm32/f4/rcc.c @@ -56,6 +56,7 @@ const struct rcc_clock_scale rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_END] = { .pllp = 2, .pllq = 2, .pllr = 0, + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_DIV_NONE, .ppre1 = RCC_CFGR_PPRE_DIV_4, .ppre2 = RCC_CFGR_PPRE_DIV_2, @@ -72,6 +73,7 @@ const struct rcc_clock_scale rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_END] = { .pllp = 4, .pllq = 7, .pllr = 0, + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_DIV_NONE, .ppre1 = RCC_CFGR_PPRE_DIV_2, .ppre2 = RCC_CFGR_PPRE_DIV_NONE, @@ -88,6 +90,7 @@ const struct rcc_clock_scale rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_END] = { .pllp = 2, .pllq = 5, .pllr = 0, + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_DIV_NONE, .ppre1 = RCC_CFGR_PPRE_DIV_4, .ppre2 = RCC_CFGR_PPRE_DIV_2, @@ -104,6 +107,7 @@ const struct rcc_clock_scale rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_END] = { .pllp = 2, .pllq = 7, .pllr = 0, + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_DIV_NONE, .ppre1 = RCC_CFGR_PPRE_DIV_4, .ppre2 = RCC_CFGR_PPRE_DIV_2, @@ -120,6 +124,7 @@ const struct rcc_clock_scale rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_END] = { .pllp = 2, .pllq = 8, .pllr = 0, + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_DIV_NONE, .ppre1 = RCC_CFGR_PPRE_DIV_4, .ppre2 = RCC_CFGR_PPRE_DIV_2, @@ -139,6 +144,7 @@ const struct rcc_clock_scale rcc_hse_12mhz_3v3[RCC_CLOCK_3V3_END] = { .pllp = 2, .pllq = 2, .pllr = 0, + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_DIV_NONE, .ppre1 = RCC_CFGR_PPRE_DIV_4, .ppre2 = RCC_CFGR_PPRE_DIV_2, @@ -155,6 +161,7 @@ const struct rcc_clock_scale rcc_hse_12mhz_3v3[RCC_CLOCK_3V3_END] = { .pllp = 4, .pllq = 7, .pllr = 0, + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_DIV_NONE, .ppre1 = RCC_CFGR_PPRE_DIV_2, .ppre2 = RCC_CFGR_PPRE_DIV_NONE, @@ -171,6 +178,7 @@ const struct rcc_clock_scale rcc_hse_12mhz_3v3[RCC_CLOCK_3V3_END] = { .pllp = 2, .pllq = 5, .pllr = 0, + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_DIV_NONE, .ppre1 = RCC_CFGR_PPRE_DIV_4, .ppre2 = RCC_CFGR_PPRE_DIV_2, @@ -187,6 +195,7 @@ const struct rcc_clock_scale rcc_hse_12mhz_3v3[RCC_CLOCK_3V3_END] = { .pllp = 2, .pllq = 7, .pllr = 0, + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_DIV_NONE, .ppre1 = RCC_CFGR_PPRE_DIV_4, .ppre2 = RCC_CFGR_PPRE_DIV_2, @@ -203,6 +212,7 @@ const struct rcc_clock_scale rcc_hse_12mhz_3v3[RCC_CLOCK_3V3_END] = { .pllp = 2, .pllq = 8, .pllr = 0, + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_DIV_NONE, .ppre1 = RCC_CFGR_PPRE_DIV_4, .ppre2 = RCC_CFGR_PPRE_DIV_2, @@ -222,6 +232,7 @@ const struct rcc_clock_scale rcc_hse_16mhz_3v3[RCC_CLOCK_3V3_END] = { .pllp = 2, .pllq = 2, .pllr = 0, + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_DIV_NONE, .ppre1 = RCC_CFGR_PPRE_DIV_4, .ppre2 = RCC_CFGR_PPRE_DIV_2, @@ -238,6 +249,7 @@ const struct rcc_clock_scale rcc_hse_16mhz_3v3[RCC_CLOCK_3V3_END] = { .pllp = 4, .pllq = 7, .pllr = 0, + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_DIV_NONE, .ppre1 = RCC_CFGR_PPRE_DIV_2, .ppre2 = RCC_CFGR_PPRE_DIV_NONE, @@ -254,6 +266,7 @@ const struct rcc_clock_scale rcc_hse_16mhz_3v3[RCC_CLOCK_3V3_END] = { .pllp = 2, .pllq = 5, .pllr = 0, + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_DIV_NONE, .ppre1 = RCC_CFGR_PPRE_DIV_4, .ppre2 = RCC_CFGR_PPRE_DIV_2, @@ -270,6 +283,7 @@ const struct rcc_clock_scale rcc_hse_16mhz_3v3[RCC_CLOCK_3V3_END] = { .pllp = 2, .pllq = 7, .pllr = 0, + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_DIV_NONE, .ppre1 = RCC_CFGR_PPRE_DIV_4, .ppre2 = RCC_CFGR_PPRE_DIV_2, @@ -286,6 +300,7 @@ const struct rcc_clock_scale rcc_hse_16mhz_3v3[RCC_CLOCK_3V3_END] = { .pllp = 2, .pllq = 8, .pllr = 0, + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_DIV_NONE, .ppre1 = RCC_CFGR_PPRE_DIV_4, .ppre2 = RCC_CFGR_PPRE_DIV_2, @@ -305,6 +320,7 @@ const struct rcc_clock_scale rcc_hse_25mhz_3v3[RCC_CLOCK_3V3_END] = { .pllp = 2, .pllq = 2, .pllr = 0, + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_DIV_NONE, .ppre1 = RCC_CFGR_PPRE_DIV_4, .ppre2 = RCC_CFGR_PPRE_DIV_2, @@ -321,6 +337,7 @@ const struct rcc_clock_scale rcc_hse_25mhz_3v3[RCC_CLOCK_3V3_END] = { .pllp = 4, .pllq = 7, .pllr = 0, + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_DIV_NONE, .ppre1 = RCC_CFGR_PPRE_DIV_2, .ppre2 = RCC_CFGR_PPRE_DIV_NONE, @@ -337,6 +354,7 @@ const struct rcc_clock_scale rcc_hse_25mhz_3v3[RCC_CLOCK_3V3_END] = { .pllp = 2, .pllq = 5, .pllr = 0, + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_DIV_NONE, .ppre1 = RCC_CFGR_PPRE_DIV_4, .ppre2 = RCC_CFGR_PPRE_DIV_2, @@ -353,6 +371,7 @@ const struct rcc_clock_scale rcc_hse_25mhz_3v3[RCC_CLOCK_3V3_END] = { .pllp = 2, .pllq = 7, .pllr = 0, + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_DIV_NONE, .ppre1 = RCC_CFGR_PPRE_DIV_4, .ppre2 = RCC_CFGR_PPRE_DIV_2, @@ -369,6 +388,7 @@ const struct rcc_clock_scale rcc_hse_25mhz_3v3[RCC_CLOCK_3V3_END] = { .pllp = 2, .pllq = 8, .pllr = 0, + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_DIV_NONE, .ppre1 = RCC_CFGR_PPRE_DIV_4, .ppre2 = RCC_CFGR_PPRE_DIV_2, @@ -748,7 +768,15 @@ uint32_t rcc_system_clock_source(void) return (RCC_CFGR & 0x000c) >> 2; } -void rcc_clock_setup_hse_3v3(const struct rcc_clock_scale *clock) +/** + * Setup clocks to run from PLL. + * + * The arguments provide the pll source, multipliers, dividers, all that's + * needed to establish a system clock. + * + * @param clock clock information structure. + */ +void rcc_clock_setup_pll(const struct rcc_clock_scale *clock) { /* Enable internal high-speed oscillator (HSI). */ rcc_osc_on(RCC_HSI); @@ -758,8 +786,10 @@ void rcc_clock_setup_hse_3v3(const struct rcc_clock_scale *clock) rcc_set_sysclk_source(RCC_CFGR_SW_HSI); /* Enable external high-speed oscillator (HSE). */ - rcc_osc_on(RCC_HSE); - rcc_wait_for_osc_ready(RCC_HSE); + if (clock->pll_source == RCC_CFGR_PLLSRC_HSE_CLK) { + rcc_osc_on(RCC_HSE); + rcc_wait_for_osc_ready(RCC_HSE); + } /* Set the VOS scale mode */ rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_PWR); @@ -777,8 +807,13 @@ void rcc_clock_setup_hse_3v3(const struct rcc_clock_scale *clock) rcc_osc_off(RCC_PLL); /* Configure the PLL oscillator. */ - rcc_set_main_pll_hse(clock->pllm, clock->plln, - clock->pllp, clock->pllq, clock->pllr); + if (clock->pll_source == RCC_CFGR_PLLSRC_HSE_CLK) { + rcc_set_main_pll_hse(clock->pllm, clock->plln, + clock->pllp, clock->pllq, clock->pllr); + } else { + rcc_set_main_pll_hsi(clock->pllm, clock->plln, + clock->pllp, clock->pllq, clock->pllr); + } /* Enable PLL oscillator and wait for it to stabilize. */ rcc_osc_on(RCC_PLL); @@ -809,7 +844,19 @@ void rcc_clock_setup_hse_3v3(const struct rcc_clock_scale *clock) rcc_apb2_frequency = clock->apb2_frequency; /* Disable internal high-speed oscillator. */ - rcc_osc_off(RCC_HSI); + if (clock->pll_source == RCC_CFGR_PLLSRC_HSE_CLK) { + rcc_osc_off(RCC_HSI); + } +} + +/** + * Setup clocks with the HSE. + * + * @deprecated Use `rcc_clock_setup_pll` instead. + */ +void __attribute__((deprecated)) rcc_clock_setup_hse_3v3(const struct rcc_clock_scale *clock) +{ + rcc_clock_setup_pll(clock); } /**@}*/