libopencm3
A free/libre/open-source firmware library for various ARM Cortex-M3 microcontrollers.
rcc.c
Go to the documentation of this file.
1/** @defgroup rcc_file RCC peripheral API
2 *
3 * @ingroup peripheral_apis
4 * This library supports the Reset and Clock Control System in the STM32 series
5 * of ARM Cortex Microcontrollers by ST Microelectronics.
6 *
7 * LGPL License Terms @ref lgpl_license
8 */
9#include <stddef.h>
14
15#define HZ_PER_MHZ 1000000UL
16#define HZ_PER_KHZ 1000UL
17
18/* Local private copy of the clock configuration for providing user with clock tree data. */
19static struct {
20 uint16_t sysclk_mhz;
21 uint16_t cpu_mhz;
22 uint16_t hclk_mhz;
23 struct {
24 uint16_t pclk1_mhz; /* APB1 clock. */
25 uint16_t pclk2_mhz; /* APB2 clock. */
26 uint16_t pclk3_mhz; /* APB3 clock. */
27 uint16_t pclk4_mhz; /* APB4 clock. */
28 } per;
29 struct pll_clocks { /* Each PLL output set of data. */
30 uint16_t p_mhz;
31 uint16_t q_mhz;
32 uint16_t r_mhz;
34 uint16_t hse_khz; /* This can't exceed 50MHz */
36 .sysclk_mhz = RCC_HSI_BASE_FREQUENCY / HZ_PER_MHZ,
39 .per.pclk1_mhz = RCC_HSI_BASE_FREQUENCY / HZ_PER_MHZ,
40 .per.pclk2_mhz = RCC_HSI_BASE_FREQUENCY / HZ_PER_MHZ,
41 .per.pclk3_mhz = RCC_HSI_BASE_FREQUENCY / HZ_PER_MHZ,
42 .per.pclk4_mhz = RCC_HSI_BASE_FREQUENCY / HZ_PER_MHZ
43};
44
45static void rcc_configure_pll(uint32_t clkin, const struct pll_config *config, int pll_num) {
46 /* Only concern ourselves with the PLL if the input clock is enabled. */
47 if (config->divm == 0 || pll_num < 1 || pll_num > 3) {
48 return;
49 }
50
51 struct pll_clocks *pll_tree_ptr;
52 if (pll_num == 1) {
53 pll_tree_ptr = &rcc_clock_tree.pll1;
54 } else if (pll_num == 2) {
55 pll_tree_ptr = &rcc_clock_tree.pll2;
56 } else {
57 pll_tree_ptr = &rcc_clock_tree.pll3;
58 }
59
60 /* Let's write all of the dividers as specified. */
61 RCC_PLLDIVR(pll_num) = 0;
62 RCC_PLLDIVR(pll_num) |= RCC_PLLNDIVR_DIVN(config->divn);
63
64 /* Setup the PLL config values for this PLL. */
65 uint8_t vco_addshift = 4 * (pll_num - 1); /* Values spaced by 4 for PLL 1/2/3 */
66
67 /* Set the PLL input frequency range. */
68 uint32_t pll_clk_mhz = (clkin / config->divm) / HZ_PER_MHZ;
69 if (pll_clk_mhz > 2 && pll_clk_mhz <= 4) {
71 } else if (pll_clk_mhz > 4 && pll_clk_mhz <= 8) {
73 } else if (pll_clk_mhz > 8) {
75 }
76
77 /* Set the VCO output frequency range. */
78 uint32_t pll_vco_clk_mhz = (pll_clk_mhz * config->divn);
79 if (pll_vco_clk_mhz <= 420) {
80 RCC_PLLCFGR |= (RCC_PLLCFGR_PLL1VCO_MED << vco_addshift);
81 }
82
83 /* Setup the enable bits for the PLL outputs. */
84 uint8_t diven_addshift = 3 * (pll_num - 1); /* Values spaced by 3 for PLL1/2/3 */
85 if (config->divp > 0) {
86 RCC_PLLDIVR(pll_num) |= RCC_PLLNDIVR_DIVP(config->divp);
87 RCC_PLLCFGR |= (RCC_PLLCFGR_DIVP1EN << diven_addshift);
88 pll_tree_ptr->p_mhz = pll_vco_clk_mhz / config->divp;
89 }
90 if (config->divq > 0) {
91 RCC_PLLDIVR(pll_num) |= RCC_PLLNDIVR_DIVQ(config->divq);
92 RCC_PLLCFGR |= (RCC_PLLCFGR_DIVQ1EN << diven_addshift);
93 pll_tree_ptr->q_mhz = pll_vco_clk_mhz / config->divq;
94 }
95 if (config->divr > 0) {
96 RCC_PLLDIVR(pll_num) |= RCC_PLLNDIVR_DIVR(config->divr);
97 RCC_PLLCFGR |= (RCC_PLLCFGR_DIVR1EN << diven_addshift);
98 pll_tree_ptr->r_mhz = pll_vco_clk_mhz / config->divr;
99 }
100
101 /* Attempt to enable and lock PLL. */
102 uint8_t cr_addshift = 2 * (pll_num - 1);
103 RCC_CR |= RCC_CR_PLL1ON << cr_addshift;
104 while (!(RCC_CR & (RCC_CR_PLL1RDY << cr_addshift)));
105}
106
107static void rcc_set_and_enable_plls(const struct rcc_pll_config *config) {
108 /* It is assumed that this function is entered with PLLs disabled and not
109 * running. Setup PLL1/2/3 with configurations specified in the config. */
111 RCC_PLLCKSELR_DIVM2(config->pll2.divm) |
112 RCC_PLLCKSELR_DIVM3(config->pll3.divm) |
113 config->pll_source;
114
115 uint32_t clkin = (config->pll_source == RCC_PLLCKSELR_PLLSRC_HSI)
117
118 RCC_PLLCFGR = 0;
119 rcc_configure_pll(clkin, &config->pll1, 1);
120 rcc_configure_pll(clkin, &config->pll2, 2);
121 rcc_configure_pll(clkin, &config->pll3, 3);
122}
123
124/* This is a helper to calculate dividers that go 2/4/8/16/64/128/256/512.
125 * These dividers also use the top bit as an "enable". */
126static uint16_t rcc_prediv_log_skip32_div(uint16_t clk_mhz, uint32_t div_val) {
127 if (div_val < 0x8) {
128 return clk_mhz;
129 } else if (div_val <= RCC_D1CFGR_D1CPRE_DIV16) {
130 return clk_mhz >> (div_val - 7);
131 } else {
132 return clk_mhz >> (div_val - 6);
133 }
134}
135
136/* This is a helper to help calculate simple 3-bit log dividers with top bit
137 * used as enable bit. */
138static uint16_t rcc_prediv_3bit_log_div(uint16_t clk_mhz, uint32_t div_val) {
139 if (div_val < 0x4) {
140 return clk_mhz;
141 } else {
142 return clk_mhz >> (div_val - 3);
143 }
144}
145
146static void rcc_clock_setup_domain1(const struct rcc_pll_config *config) {
147 RCC_D1CFGR = 0;
149 RCC_D1CFGR_D1HPRE(config->hpre) | RCC_D1CFGR_D1PPRE(config->ppre3);
150
151 /* Update our clock values in our tree based on the config values. */
152 rcc_clock_tree.cpu_mhz =
154 rcc_clock_tree.hclk_mhz =
156 rcc_clock_tree.per.pclk3_mhz =
158}
159
160static void rcc_clock_setup_domain2(const struct rcc_pll_config *config) {
161 RCC_D2CFGR = 0;
163 RCC_D2CFGR_D2PPRE2(config->ppre2);
164
165 /* Update our clock values in our tree based on the config values. */
166 rcc_clock_tree.per.pclk2_mhz =
168 rcc_clock_tree.per.pclk1_mhz =
170}
171
172static void rcc_clock_setup_domain3(const struct rcc_pll_config *config) {
173 RCC_D3CFGR &= 0;
175
176 /* Update our clock values in our tree based on the config values. */
177 rcc_clock_tree.per.pclk4_mhz =
179}
180
181void rcc_clock_setup_pll(const struct rcc_pll_config *config) {
182 /* First, set system clock to utilize HSI, then disable all but HSI. */
187
188 /* Now that we're safely running on HSI, let's setup the power system for scaling. */
189 pwr_set_mode(config->power_mode, config->smps_level);
191
192 /* Set flash waitstates. Enable flash prefetch if we have at least 1WS */
196 } else {
198 }
199
200 /* User has specified an external oscillator, make sure we turn it on. */
201 if (config->hse_frequency > 0) {
203 while (!(RCC_CR & RCC_CR_HSERDY));
204 rcc_clock_tree.hse_khz = config->hse_frequency / HZ_PER_KHZ;
205 }
206
207 /* Set, enable and lock all of the pll from the config. */
209
210 /* Populate our base sysclk settings for use with domain clocks. */
211 if (config->sysclock_source == RCC_PLL) {
212 rcc_clock_tree.sysclk_mhz = rcc_clock_tree.pll1.p_mhz;
213 } else if (config->sysclock_source == RCC_HSE) {
214 rcc_clock_tree.sysclk_mhz = config->hse_frequency / HZ_PER_MHZ;
215 } else {
217 }
218
219 /* PLL's are set, now we need to get everything switched over the correct domains. */
223
224 /* TODO: Configure custom kernel mappings. */
225
226 /* Domains dividers are all configured, now we can switchover to PLL. */
228 uint32_t cfgr_sws = ((RCC_CFGR >> RCC_CFGR_SWS_SHIFT) & RCC_CFGR_SWS_MASK);
229 while(cfgr_sws != RCC_CFGR_SWS_PLL1) {
231 }
232}
233
235 uint32_t clksel;
236 switch (source) {
237 case RCC_SYSCLK:
238 return rcc_clock_tree.sysclk_mhz * HZ_PER_MHZ;
239 case RCC_CPUCLK:
240 case RCC_SYSTICKCLK:
241 return rcc_clock_tree.cpu_mhz * HZ_PER_MHZ;
242 case RCC_AHBCLK:
243 case RCC_HCLK3:
244 return rcc_clock_tree.hclk_mhz * HZ_PER_MHZ;
245 case RCC_APB1CLK:
246 return rcc_clock_tree.per.pclk1_mhz * HZ_PER_MHZ;
247 case RCC_APB2CLK:
248 return rcc_clock_tree.per.pclk2_mhz * HZ_PER_MHZ;
249 case RCC_APB3CLK:
250 return rcc_clock_tree.per.pclk3_mhz * HZ_PER_MHZ;
251 case RCC_APB4CLK:
252 return rcc_clock_tree.per.pclk4_mhz * HZ_PER_MHZ;
253 case RCC_PERCLK:
255 if (clksel == RCC_D1CCIPR_CKPERSEL_HSI) {
257 } else if (clksel == RCC_D1CCIPR_CKPERSEL_HSE) {
258 return rcc_clock_tree.hse_khz * HZ_PER_KHZ;
259 } else {
260 return 0U;
261 }
262 default:
264 return 0U;
265 }
266}
267
268uint32_t rcc_get_usart_clk_freq(uint32_t usart)
269{
270 uint32_t clksel, pclk;
271 if (usart == USART1_BASE || usart == USART6_BASE) {
272 pclk = rcc_clock_tree.per.pclk2_mhz * HZ_PER_MHZ;;
274 } else {
275 pclk = rcc_clock_tree.per.pclk1_mhz * HZ_PER_MHZ;
277 }
278
279 /* Based on extracted clksel value, return the clock. */
280 switch(clksel) {
282 return pclk;
284 return rcc_clock_tree.pll2.q_mhz * HZ_PER_MHZ;
286 return rcc_clock_tree.pll3.q_mhz * HZ_PER_MHZ;
290 return 4000000;
292 return 32768;
293 }
295}
296
297uint32_t rcc_get_timer_clk_freq(uint32_t timer __attribute__((unused)))
298{
299 if (timer >= LPTIM2_BASE && timer <= LPTIM5_BASE) {
300 /* TODO: Read LPTIMxSEL values from D3CCIPR to determine clock source. */
301 return rcc_clock_tree.per.pclk4_mhz * HZ_PER_MHZ;
302 } else if (timer >= TIM1_BASE && timer <= HRTIM_BASE) {
303 return rcc_clock_tree.per.pclk2_mhz * HZ_PER_MHZ;
304 } else {
305 return rcc_clock_tree.per.pclk1_mhz * HZ_PER_MHZ;
306 }
307}
308
309uint32_t rcc_get_i2c_clk_freq(uint32_t i2c)
310{
311 if (i2c == I2C4_BASE) {
312 /* TODO: Read I2C4SEL from D3CCIPR to determine clock source. */
313 return rcc_clock_tree.per.pclk3_mhz * HZ_PER_MHZ;
314 } else {
315 /* TODO: Read I2C123SEL from D2CCIP2R to determine clock source. */
316 return rcc_clock_tree.per.pclk1_mhz * HZ_PER_MHZ;
317 }
318}
319
320uint32_t rcc_get_spi_clk_freq(uint32_t spi)
321{
322 if (spi == SPI4_BASE || spi == SPI5_BASE) {
323 uint32_t clksel =
325 if (clksel == RCC_D2CCIP1R_SPI45SEL_APB4){
326 return rcc_clock_tree.per.pclk2_mhz * HZ_PER_MHZ;
327 } else if (clksel == RCC_D2CCIP1R_SPI45SEL_PLL2Q){
328 return rcc_clock_tree.pll2.q_mhz * HZ_PER_MHZ;
329 } else if (clksel == RCC_D2CCIP1R_SPI45SEL_PLL3Q){
330 return rcc_clock_tree.pll3.q_mhz * HZ_PER_MHZ;
331 } else if (clksel == RCC_D2CCIP1R_SPI45SEL_HSI){
333 } else if (clksel == RCC_D2CCIP1R_SPI45SEL_HSE) {
334 return rcc_clock_tree.hse_khz * HZ_PER_KHZ;
335 } else {
336 return 0U;
337 }
338 } else {
339 uint32_t clksel =
341 if (clksel == RCC_D2CCIP1R_SPI123SEL_PLL1Q) {
342 return rcc_clock_tree.pll1.q_mhz * HZ_PER_MHZ;
343 } else if (clksel == RCC_D2CCIP1R_SPI123SEL_PLL2P) {
344 return rcc_clock_tree.pll2.p_mhz * HZ_PER_MHZ;
345 } else if (clksel == RCC_D2CCIP1R_SPI123SEL_PLL3P) {
346 return rcc_clock_tree.pll3.p_mhz * HZ_PER_MHZ;
347 } else if (clksel == RCC_D2CCIP1R_SPI123SEL_PERCK) {
349 } else {
350 return 0U;
351 }
352 }
353}
354
355uint32_t rcc_get_fdcan_clk_freq(uint32_t fdcan __attribute__((unused)))
356{
357 uint32_t clksel =
359 if (clksel == RCC_D2CCIP1R_FDCANSEL_HSE) {
360 return rcc_clock_tree.hse_khz * HZ_PER_KHZ;
361 } else if (clksel == RCC_D2CCIP1R_FDCANSEL_PLL1Q) {
362 return rcc_clock_tree.pll1.q_mhz * HZ_PER_MHZ;
363 } else if (clksel == RCC_D2CCIP1R_FDCANSEL_PLL2Q) {
364 return rcc_clock_tree.pll2.q_mhz * HZ_PER_MHZ;
365 } else {
366 return 0U;
367 }
368}
369
370void rcc_set_peripheral_clk_sel(uint32_t periph, uint32_t sel) {
371 volatile uint32_t *reg;
372 uint32_t mask;
373 uint32_t val;
374
375 switch (periph) {
376 case FDCAN1_BASE:
377 case FDCAN2_BASE:
378 reg = &RCC_D2CCIP1R;
380 val = sel << RCC_D2CCIP1R_FDCANSEL_SHIFT;
381 break;
382 case RNG_BASE:
383 reg = &RCC_D2CCIP2R;
385 val = sel << RCC_D2CCIP2R_RNGSEL_SHIFT;
386 break;
387 case SPI1_BASE:
388 case SPI2_BASE:
389 case SPI3_BASE:
390 reg = &RCC_D2CCIP2R;
392 val = sel << RCC_D2CCIP1R_SPI123SEL_SHIFT;
393 break;
394 case SPI4_BASE:
395 case SPI5_BASE:
396 reg = &RCC_D2CCIP1R;
398 val = sel << RCC_D2CCIP1R_SPI45SEL_SHIFT;
399 break;
400 case USART1_BASE:
401 case USART6_BASE:
402 reg = &RCC_D2CCIP2R;
405 break;
406 case USART2_BASE:
407 case USART3_BASE:
408 case UART4_BASE:
409 case UART5_BASE:
410 case UART7_BASE:
411 case UART8_BASE:
412 reg = &RCC_D2CCIP2R;
415 break;
416
417 default:
419 return;
420 }
421
422 // Update the register value by masking and oring in new values.
423 uint32_t regval = (*reg & mask) | val;
424 *reg = regval;
425}
426
427void rcc_set_fdcan_clksel(uint8_t clksel) {
430}
431
432void rcc_set_rng_clksel(uint8_t clksel) {
435}
436
437void rcc_set_spi123_clksel(uint8_t clksel) {
440}
441
442void rcc_set_spi45_clksel(uint8_t clksel) {
445}
#define cm3_assert_not_reached()
Check if unreachable code is reached.
Definition: assert.h:102
void flash_prefetch_enable(void)
This buffer is used for instruction fetches and may or may not be enabled by default,...
void flash_prefetch_disable(void)
Note carefully the clock restrictions under which the prefetch buffer may be set to disabled.
void flash_set_ws(uint32_t ws)
Set the Number of Wait States.
#define FLASH_ACR_LATENCY_0WS
void pwr_set_vos_scale(enum pwr_vos_scale scale)
Set the voltage scaling/strength for the internal SMPS/LDO while running.
Definition: pwr.c:117
void pwr_set_mode(enum pwr_sys_mode mode, uint8_t smps_level)
Set power system based on "System Supply Configurations" table in reference manual.
Definition: pwr.c:83
#define RCC_CFGR_SW_PLL1
Definition: h7/rcc.h:179
#define RCC_CFGR_SWS_MASK
Definition: h7/rcc.h:167
#define RCC_CFGR_SWS_HSI
Definition: h7/rcc.h:168
#define RCC_CFGR_SWS_PLL1
Definition: h7/rcc.h:171
#define RCC_CFGR_SW_MASK
Definition: h7/rcc.h:175
#define RCC_CFGR_SWS_SHIFT
Definition: h7/rcc.h:166
#define RCC_CFGR_SW_SHIFT
Definition: h7/rcc.h:174
#define RCC_CR_PLL1RDY
Definition: h7/rcc.h:103
#define RCC_CR_PLL1ON
Definition: h7/rcc.h:104
#define RCC_CR_HSERDY
Definition: h7/rcc.h:107
#define RCC_CR_HSEON
Definition: h7/rcc.h:108
#define RCC_CR_HSION
Definition: h7/rcc.h:122
#define RCC_D1CCIPR_CKPERSEL_HSE
Definition: h7/rcc.h:343
#define RCC_D1CCIPR_CKPERSEL_HSI
Definition: h7/rcc.h:341
#define RCC_D1CFGR_D1PPRE(ppre)
Definition: h7/rcc.h:212
#define RCC_D1CFGR_D1CPRE_DIV16
Definition: h7/rcc.h:189
#define RCC_D1CFGR_D1HPRE(hpre)
Definition: h7/rcc.h:213
#define RCC_D1CFGR_D1CPRE(cpre)
Definition: h7/rcc.h:211
#define RCC_D2CCIP1R_SPI123SEL_PLL3P
Definition: h7/rcc.h:383
#define RCC_D2CCIP1R_SPI123SEL_PLL1Q
Definition: h7/rcc.h:381
#define RCC_D2CCIP1R_FDCANSEL_PLL1Q
Definition: h7/rcc.h:367
#define RCC_D2CCIP1R_SPI45SEL_PLL2Q
Definition: h7/rcc.h:376
#define RCC_D2CCIP1R_SPI45SEL_PLL3Q
Definition: h7/rcc.h:377
#define RCC_D2CCIP1R_SPI45SEL_HSE
Definition: h7/rcc.h:380
#define RCC_D2CCIP1R_FDCANSEL_HSE
Definition: h7/rcc.h:366
#define RCC_D2CCIP1R_FDCANSEL_PLL2Q
Definition: h7/rcc.h:368
#define RCC_D2CCIP1R_SPI123SEL_PERCK
Definition: h7/rcc.h:385
#define RCC_D2CCIP1R_SPI45SEL_APB4
Definition: h7/rcc.h:375
#define RCC_D2CCIP1R_SPI45SEL_HSI
Definition: h7/rcc.h:378
#define RCC_D2CCIP1R_SPI123SEL_PLL2P
Definition: h7/rcc.h:382
#define RCC_D2CCIP2R_USARTSEL_PLL3Q
Definition: h7/rcc.h:414
#define RCC_D2CCIP2R_USARTSEL_PLL2Q
Definition: h7/rcc.h:413
#define RCC_D2CCIP2R_USARTSEL_LSE
Definition: h7/rcc.h:417
#define RCC_D2CCIP2R_USARTSEL_HSI
Definition: h7/rcc.h:415
#define RCC_D2CCIP2R_USARTSEL_PCLK
Definition: h7/rcc.h:412
#define RCC_D2CCIP2R_USARTSEL_CSI
Definition: h7/rcc.h:416
#define RCC_D2CFGR_D2PPRE1(ppre)
Definition: h7/rcc.h:228
#define RCC_D2CFGR_D2PPRE2(ppre)
Definition: h7/rcc.h:227
#define RCC_D3CFGR_D3PPRE(ppre)
Definition: h7/rcc.h:240
#define RCC_D2CCIP2R_USARTSEL_MASK
Definition: h7/rcc.h:401
#define RCC_D2CCIP1R_SPI123SEL_MASK
Definition: h7/rcc.h:357
#define RCC_D2CCIP1R_FDCANSEL_MASK
Definition: h7/rcc.h:351
#define RCC_D1CCIPR_CKPERSEL_SHIFT
Definition: h7/rcc.h:346
#define RCC_HSI_BASE_FREQUENCY
Definition: h7/rcc.h:421
#define RCC_D1CCIPR_CKPERSEL_MASK
Definition: h7/rcc.h:347
#define RCC_D2CCIP2R_USART234578SEL_SHIFT
Definition: h7/rcc.h:400
#define RCC_D2CCIP2R_RNGSEL_SHIFT
Definition: h7/rcc.h:398
#define RCC_D2CCIP1R_SPI123SEL_SHIFT
Definition: h7/rcc.h:356
#define RCC_D2CCIP2R_USART16SEL_SHIFT
Definition: h7/rcc.h:399
#define RCC_D2CCIP2R_RNGSEL_MASK
Definition: h7/rcc.h:397
rcc_clock_source
Enumerations for core system/bus clocks for user/driver/system access to base bus clocks not directly...
Definition: h7/rcc.h:425
#define RCC_D2CCIP1R_SPI45SEL_MASK
Definition: h7/rcc.h:355
#define RCC_D2CCIP1R_FDCANSEL_SHIFT
Definition: h7/rcc.h:350
#define RCC_D2CCIP1R_SPI45SEL_SHIFT
Definition: h7/rcc.h:354
@ RCC_PLL
Definition: h7/rcc.h:439
@ RCC_HSE
Definition: h7/rcc.h:440
@ RCC_APB1CLK
Definition: h7/rcc.h:432
@ RCC_SYSCLK
Definition: h7/rcc.h:427
@ RCC_APB4CLK
Definition: h7/rcc.h:435
@ RCC_APB3CLK
Definition: h7/rcc.h:434
@ RCC_SYSTICKCLK
Definition: h7/rcc.h:429
@ RCC_PERCLK
Definition: h7/rcc.h:428
@ RCC_APB2CLK
Definition: h7/rcc.h:433
@ RCC_HCLK3
Definition: h7/rcc.h:430
@ RCC_CPUCLK
Definition: h7/rcc.h:426
@ RCC_AHBCLK
Definition: h7/rcc.h:431
uint32_t rcc_get_fdcan_clk_freq(uint32_t fdcan)
Get the peripheral clock speed for the FDCAN device at base specified.
Definition: rcc.c:355
void rcc_clock_setup_pll(const struct rcc_pll_config *config)
Setup the base PLLs and clock domains for the STM32H7.
Definition: rcc.c:181
uint32_t rcc_get_bus_clk_freq(enum rcc_clock_source source)
Get the clock rate (in Hz) of the specified clock source.
Definition: rcc.c:234
uint32_t rcc_get_spi_clk_freq(uint32_t spi)
Get the peripheral clock speed for the SPI device at base specified.
Definition: rcc.c:320
uint32_t rcc_get_timer_clk_freq(uint32_t timer)
Get the peripheral clock speed for the Timer at base specified.
Definition: rcc.c:297
void rcc_set_rng_clksel(uint8_t clksel)
Set the clock select for the RNG device.
Definition: rcc.c:432
uint32_t rcc_get_usart_clk_freq(uint32_t usart)
Get the peripheral clock speed for the USART at base specified.
Definition: rcc.c:268
void rcc_set_fdcan_clksel(uint8_t clksel)
Set the clock select for the FDCAN devices.
Definition: rcc.c:427
void rcc_set_spi123_clksel(uint8_t clksel)
Set the clock select for the SPI 1/2/3 devices.
Definition: rcc.c:437
uint32_t rcc_get_i2c_clk_freq(uint32_t i2c)
Get the peripheral clock speed for the I2C device at base specified.
Definition: rcc.c:309
void rcc_set_peripheral_clk_sel(uint32_t periph, uint32_t sel)
Set the clksel value for the specified peripheral.
Definition: rcc.c:370
void rcc_set_spi45_clksel(uint8_t clksel)
Set the clock select for the SPI 4/5 devices.
Definition: rcc.c:442
#define RCC_PLLCFGR_PLLRGE_4_8MHZ
Definition: h7/rcc.h:268
#define RCC_PLLCFGR_DIVR1EN
Definition: h7/rcc.h:277
#define RCC_PLLCFGR_PLL1VCO_MED
Definition: h7/rcc.h:290
#define RCC_PLLCFGR_DIVQ1EN
Definition: h7/rcc.h:278
#define RCC_PLLCFGR_PLLRGE_2_4MHZ
Definition: h7/rcc.h:267
#define RCC_PLLCFGR_PLLRGE_8_16MHZ
Definition: h7/rcc.h:269
#define RCC_PLLCFGR_DIVP1EN
Definition: h7/rcc.h:279
#define RCC_PLLCFGR_PLL1RGE_SHIFT
Definition: h7/rcc.h:288
#define RCC_PLLCKSELR_PLLSRC_HSI
Definition: h7/rcc.h:246
#define RCC_PLLCKSELR_DIVM3(n)
Definition: h7/rcc.h:258
#define RCC_PLLCKSELR_DIVM1(n)
Definition: h7/rcc.h:260
#define RCC_PLLCKSELR_DIVM2(n)
Definition: h7/rcc.h:259
#define RCC_PLLNDIVR_DIVN(n)
Definition: h7/rcc.h:306
#define RCC_PLLNDIVR_DIVR(n)
Definition: h7/rcc.h:303
#define RCC_PLLNDIVR_DIVQ(n)
Definition: h7/rcc.h:304
#define RCC_PLLNDIVR_DIVP(n)
Definition: h7/rcc.h:305
#define RCC_PLLCKSELR
Definition: h7/rcc.h:46
#define RCC_CR
Definition: h7/rcc.h:37
#define RCC_D1CCIPR
Definition: h7/rcc.h:57
#define RCC_D3CFGR
Definition: h7/rcc.h:45
#define RCC_D2CCIP1R
Definition: h7/rcc.h:58
#define RCC_D2CFGR
Definition: h7/rcc.h:44
#define RCC_PLLCFGR
Definition: h7/rcc.h:47
#define RCC_CFGR
Definition: h7/rcc.h:42
#define RCC_D2CCIP2R
Definition: h7/rcc.h:59
#define RCC_PLLDIVR(n)
Definition: h7/rcc.h:49
#define RCC_D1CFGR
Definition: h7/rcc.h:43
#define HZ_PER_KHZ
Definition: rcc.c:16
uint16_t sysclk_mhz
Definition: rcc.c:20
static uint16_t rcc_prediv_3bit_log_div(uint16_t clk_mhz, uint32_t div_val)
Definition: rcc.c:138
struct @0::pll_clocks pll1
static struct @0 rcc_clock_tree
uint16_t cpu_mhz
Definition: rcc.c:21
uint16_t pclk4_mhz
Definition: rcc.c:27
struct @0::pll_clocks pll2
static uint16_t rcc_prediv_log_skip32_div(uint16_t clk_mhz, uint32_t div_val)
Definition: rcc.c:126
uint16_t hclk_mhz
Definition: rcc.c:22
static void rcc_clock_setup_domain2(const struct rcc_pll_config *config)
Definition: rcc.c:160
uint16_t pclk1_mhz
Definition: rcc.c:24
struct @0::pll_clocks pll3
#define HZ_PER_MHZ
Definition: rcc.c:15
uint16_t p_mhz
Definition: rcc.c:30
uint16_t q_mhz
Definition: rcc.c:31
static void rcc_clock_setup_domain3(const struct rcc_pll_config *config)
Definition: rcc.c:172
uint16_t r_mhz
Definition: rcc.c:32
uint16_t pclk2_mhz
Definition: rcc.c:25
uint16_t pclk3_mhz
Definition: rcc.c:26
static void rcc_clock_setup_domain1(const struct rcc_pll_config *config)
Definition: rcc.c:146
struct @0::@1 per
static void rcc_set_and_enable_plls(const struct rcc_pll_config *config)
Definition: rcc.c:107
uint16_t hse_khz
Definition: rcc.c:34
static void rcc_configure_pll(uint32_t clkin, const struct pll_config *config, int pll_num)
Definition: rcc.c:45
#define UART7_BASE
#define LPTIM5_BASE
#define SPI1_BASE
#define FDCAN2_BASE
#define FDCAN1_BASE
#define LPTIM2_BASE
#define I2C4_BASE
#define USART1_BASE
#define UART4_BASE
#define UART5_BASE
#define HRTIM_BASE
#define RNG_BASE
#define USART3_BASE
#define SPI5_BASE
#define SPI2_BASE
#define SPI4_BASE
#define UART8_BASE
#define USART6_BASE
#define USART2_BASE
#define SPI3_BASE
#define TIM1_BASE
uint8_t divm
Pre-divider value for each PLL.
Definition: h7/rcc.h:452
PLL Configuration structure.
Definition: h7/rcc.h:447
uint8_t ppre3
APB3 Peripheral prescaler note: domain 1.
Definition: h7/rcc.h:462
uint8_t core_pre
Core prescaler note: domain 1.
Definition: h7/rcc.h:458
struct rcc_pll_config::pll_config pll1
uint8_t ppre1
APB1 Peripheral prescaler note: domain 2.
Definition: h7/rcc.h:460
struct rcc_pll_config::pll_config pll2
uint8_t smps_level
If using SMPS, voltage level to set.
Definition: h7/rcc.h:467
uint8_t ppre2
APB2 Peripheral prescaler note: domain 2.
Definition: h7/rcc.h:461
uint8_t hpre
HCLK3 prescaler note: domain 1.
Definition: h7/rcc.h:459
uint8_t ppre4
APB4 Peripheral prescaler note: domain 3.
Definition: h7/rcc.h:463
enum rcc_osc sysclock_source
SYSCLK source input selection.
Definition: h7/rcc.h:448
uint8_t flash_waitstates
Latency Value to set for flahs.
Definition: h7/rcc.h:464
enum pwr_vos_scale voltage_scale
LDO/SMPS Voltage scale used for this frequency.
Definition: h7/rcc.h:465
uint32_t hse_frequency
User specified HSE frequency, 0 if none.
Definition: h7/rcc.h:450
struct rcc_pll_config::pll_config pll3
PLL1-PLL3 configurations.
uint8_t pll_source
RCC_PLLCKSELR_PLLSRC_xxx value.
Definition: h7/rcc.h:449
enum pwr_sys_mode power_mode
LDO/SMPS configuration for device.
Definition: h7/rcc.h:466