stm32f3xx_hal/rcc.rs
1//! # Reset and Clock Control
2//!
3//! The most important function this module
4//! delivers is the clock configuration.
5//!
6//! To configure the clock, we first have to obtain the
7//! device peripherals.
8//!
9//! ```
10//! # use cortex_m_rt::entry;
11//! # use stm32f3xx-hal::{prelude::*, time::rate::*};
12//!
13//! # #[entry]
14//! # fn main() -> ! {
15//! // Get our peripherals
16//! let dp = pac::Peripherals::take().unwrap();
17//!
18//! let mut flash = dp.FLASH.constrain();
19//! let mut rcc = dp.RCC.constrain();
20//! # }
21//! ```
22//!
23//! After that we can configure the clock
24//!
25//! ```
26//! # use cortex_m_rt::entry;
27//! # use stm32f3xx-hal::{prelude::*, time::rate::*};
28//! #
29//! # #[entry]
30//! # fn main() -> ! {
31//! # let dp = pac::Peripherals::take().unwrap();
32//!
33//! # let mut flash = dp.FLASH.constrain();
34//! # let mut rcc = dp.RCC.constrain();
35//! let clocks = rcc.cfgr
36//! // Using the external oscillator
37//! // Set the frequency to that of the external oscillator
38//! .use_hse(8.MHz())
39//! // Set the frequency for the AHB bus,
40//! // which the root of every following clock peripheral
41//! .hclk(48.MHz())
42//! // The sysclk is equivalent to the core clock
43//! .sysclk(48.MHz())
44//! // The following are peripheral clocks, which are both
45//! // needed to configure specific peripherals.
46//! // Looking at the peripheral function parameters
47//! // should give more insight, which peripheral clock is needed.
48//! .pclk1(12.MHz())
49//! .pclk2(12.MHz())
50//! // Freeze / apply the configuration and setup all clocks
51//! .freeze(&mut flash.acr);
52//! # }
53//! ```
54//!
55//! All fields can be omitted and will internally be set to a calculated default.
56//! For more details read the documentation of the [`CFGR`] methods to
57//! find out how to setup the clock.
58
59use crate::pac::{
60 rcc::{self, cfgr, cfgr2},
61 RCC,
62};
63
64use crate::flash::ACR;
65use crate::time::{
66 fixed_point::FixedPoint,
67 rate::{Hertz, Megahertz},
68};
69
70impl crate::private::Sealed for RCC {}
71
72/// Extension trait that constrains the []`RCC`] peripheral
73#[allow(clippy::module_name_repetitions)]
74pub trait RccExt: crate::private::Sealed {
75 /// Constrains the [`RCC`] peripheral.
76 ///
77 /// Consumes the [`pac::RCC`] peripheral and converts it to a [`HAL`] internal type
78 /// constraining it's public access surface to fit the design of the `HAL`.
79 ///
80 /// [`pac::RCC`]: `crate::pac::RCC`
81 /// [`HAL`]: `crate`
82 fn constrain(self) -> Rcc;
83}
84
85mod enable;
86
87impl RccExt for RCC {
88 fn constrain(self) -> Rcc {
89 Rcc {
90 ahb: AHB { _0: () },
91 apb1: APB1 { _0: () },
92 apb2: APB2 { _0: () },
93 bdcr: BDCR { _0: () },
94 cfgr: CFGR::default(),
95 }
96 }
97}
98
99/// Constrained RCC peripheral
100///
101/// An instance of this struct is acquired by calling the [`constrain`](RccExt::constrain) function
102/// on the [`RCC`](crate::pac::RCC) struct.
103///
104/// ```
105/// let dp = pac::Peripherals::take().unwrap();
106/// let rcc = dp.RCC.constrain();
107/// ```
108pub struct Rcc {
109 /// AMBA High-performance Bus (AHB) registers
110 pub ahb: AHB,
111 /// Advanced Peripheral Bus 1 (APB1) registers
112 pub apb1: APB1,
113 /// Advanced Peripheral Bus 2 (APB2) registers
114 pub apb2: APB2,
115 /// RCC Backup Domain
116 pub bdcr: BDCR,
117 /// Clock configuration
118 pub cfgr: CFGR,
119}
120
121/// AMBA High-performance Bus (AHB) registers
122///
123/// An instance of this struct is acquired from the [`RCC`](crate::pac::RCC) struct.
124///
125/// ```
126/// let dp = pac::Peripherals::take().unwrap();
127/// let rcc = dp.RCC.constrain();
128/// use_ahb(&mut rcc.ahb)
129/// ```
130pub struct AHB {
131 _0: (),
132}
133
134/// Advanced Peripheral Bus 1 (APB1) registers
135///
136/// An instance of this struct is acquired from the [`RCC`](crate::pac::RCC) struct.
137///
138/// ```
139/// let dp = pac::Peripherals::take().unwrap();
140/// let rcc = dp.RCC.constrain();
141/// use_apb1(&mut rcc.apb1)
142/// ```
143pub struct APB1 {
144 _0: (),
145}
146
147/// Advanced Peripheral Bus 2 (APB2) registers
148///
149/// An instance of this struct is acquired from the [`RCC`](crate::pac::RCC) struct.
150///
151/// ```
152/// let dp = pac::Peripherals::take().unwrap();
153/// let rcc = dp.RCC.constrain();
154/// use_apb2(&mut rcc.apb2)
155/// ```
156pub struct APB2 {
157 _0: (),
158}
159
160macro_rules! bus_struct {
161 ($($busX:ident => ($EN:ident, $en:ident, $RST:ident, $rst:ident),)+) => {
162 $(
163 impl $busX {
164 fn new() -> Self {
165 Self { _0: () }
166 }
167
168 #[allow(unused)]
169 fn enr(&self) -> &rcc::$EN {
170 // FIXME: this should still be shared carefully
171 // SAFETY: this proxy grants exclusive access to this register
172 unsafe { &(*RCC::ptr()).$en }
173 }
174
175 #[allow(unused)]
176 fn rstr(&self) -> &rcc::$RST {
177 // FIXME: this should still be shared carefully
178 // SAFETY: this proxy grants exclusive access to this register
179 unsafe { &(*RCC::ptr()).$rst }
180 }
181 }
182 )+
183 };
184}
185
186bus_struct! {
187 AHB => (AHBENR, ahbenr, AHBRSTR, ahbrstr),
188 APB1 => (APB1ENR, apb1enr, APB1RSTR, apb1rstr),
189 APB2 => (APB2ENR, apb2enr, APB2RSTR, apb2rstr),
190}
191
192/// Bus associated to peripheral
193#[allow(clippy::module_name_repetitions)]
194pub trait RccBus: crate::Sealed {
195 /// The underlying bus peripheral
196 type Bus;
197}
198
199/// Enable/disable peripheral
200pub trait Enable: RccBus {
201 /// Enables peripheral
202 fn enable(bus: &mut Self::Bus);
203
204 /// Disables peripheral
205 fn disable(bus: &mut Self::Bus);
206
207 /// Check if peripheral enabled
208 fn is_enabled() -> bool;
209
210 /// Check if peripheral disabled
211 fn is_disabled() -> bool;
212
213 /// Enables peripheral
214 ///
215 /// # Safety
216 ///
217 /// Takes access to RCC internally, so you have to make sure
218 /// you don't have race condition accessing RCC registers
219 unsafe fn enable_unchecked();
220
221 /// Disables peripheral
222 ///
223 /// # Safety
224 ///
225 /// Takes access to RCC internally, so you have to make sure
226 /// you don't have race condition accessing RCC registers
227 unsafe fn disable_unchecked();
228}
229
230/// Reset peripheral
231pub trait Reset: RccBus {
232 /// Resets peripheral
233 fn reset(bus: &mut Self::Bus);
234
235 /// # Safety
236 ///
237 /// Resets peripheral. Takes access to RCC internally
238 unsafe fn reset_unchecked();
239}
240
241/// Frequency on bus that peripheral is connected in
242pub trait BusClock {
243 /// Calculates frequency depending on `Clock` state
244 fn clock(clocks: &Clocks) -> Hertz;
245}
246
247impl<T> BusClock for T
248where
249 T: RccBus,
250 T::Bus: BusClock,
251{
252 fn clock(clocks: &Clocks) -> Hertz {
253 T::Bus::clock(clocks)
254 }
255}
256
257impl BusClock for AHB {
258 fn clock(clocks: &Clocks) -> Hertz {
259 clocks.hclk
260 }
261}
262impl BusClock for APB1 {
263 fn clock(clocks: &Clocks) -> Hertz {
264 clocks.pclk1
265 }
266}
267impl BusClock for APB2 {
268 fn clock(clocks: &Clocks) -> Hertz {
269 clocks.pclk2
270 }
271}
272
273/// Frequency on bus that timer is connected in
274pub trait BusTimerClock {
275 /// Calculates base frequency of timer depending on `Clock` state
276 fn timer_clock(clocks: &Clocks) -> Hertz;
277}
278
279impl<T> BusTimerClock for T
280where
281 T: RccBus,
282 T::Bus: BusTimerClock,
283{
284 fn timer_clock(clocks: &Clocks) -> Hertz {
285 T::Bus::timer_clock(clocks)
286 }
287}
288
289impl BusTimerClock for APB1 {
290 fn timer_clock(clocks: &Clocks) -> Hertz {
291 let pclk_mul = if clocks.ppre1 > 1 { 2 } else { 1 };
292 Hertz(clocks.pclk1.0 * pclk_mul)
293 }
294}
295impl BusTimerClock for APB2 {
296 fn timer_clock(clocks: &Clocks) -> Hertz {
297 let pclk_mul = if clocks.ppre2 > 1 { 2 } else { 1 };
298 Hertz(clocks.pclk2.0 * pclk_mul)
299 }
300}
301
302/// Frequency of interal hardware RC oscillator (HSI OSC)
303pub const HSI: Hertz = Hertz(8_000_000);
304/// Frequency of external 32.768 kHz oscillator (LSE OSC)
305pub const LSE: Hertz = Hertz(32_768);
306
307// some microcontrollers do not have USB
308#[cfg(any(feature = "stm32f301", feature = "stm32f318", feature = "stm32f334",))]
309mod usb_clocking {
310 use crate::rcc::PllConfig;
311
312 pub(crate) fn is_valid(
313 _sysclk: u32,
314 _hse: Option<u32>,
315 _pclk1: u32,
316 _pll_config: &Option<PllConfig>,
317 ) -> (bool, bool) {
318 (false, false)
319 }
320
321 pub(crate) fn set_usbpre<W>(w: &mut W, _: bool) -> &mut W {
322 w
323 }
324}
325
326#[cfg(not(any(feature = "stm32f301", feature = "stm32f318", feature = "stm32f334",)))]
327mod usb_clocking {
328 use crate::pac::rcc::cfgr;
329 use crate::rcc::PllConfig;
330
331 /// Check for all clock options to be
332 pub(crate) fn is_valid(
333 sysclk: u32,
334 hse: Option<u32>,
335 pclk1: u32,
336 pll_config: &Option<PllConfig>,
337 ) -> (cfgr::USBPRE_A, bool) {
338 // the USB clock is only valid if an external crystal is used, the PLL is enabled, and the
339 // PLL output frequency is a supported one.
340 // usbpre == false: divide clock by 1.5, otherwise no division
341 let usb_ok = hse.is_some() && pll_config.is_some();
342 // The APB1 clock must have a minimum frequency of 10 MHz to avoid data overrun/underrun
343 // problems. [RM0316 32.5.2]
344 if pclk1 >= 10_000_000 {
345 match (usb_ok, sysclk) {
346 (true, 72_000_000) => (cfgr::USBPRE_A::Div15, true),
347 (true, 48_000_000) => (cfgr::USBPRE_A::Div1, true),
348 _ => (cfgr::USBPRE_A::Div1, false),
349 }
350 } else {
351 (cfgr::USBPRE_A::Div1, false)
352 }
353 }
354
355 pub(crate) fn set_usbpre(w: &mut cfgr::W, usb_prescale: cfgr::USBPRE_A) -> &mut cfgr::W {
356 w.usbpre().variant(usb_prescale)
357 }
358}
359
360/// Backup Domain Control register (`RCC_BDCR`)
361pub struct BDCR {
362 _0: (),
363}
364
365impl BDCR {
366 #[allow(unused)]
367 #[allow(clippy::unused_self)]
368 #[must_use]
369 pub(crate) fn bdcr(&mut self) -> &rcc::BDCR {
370 // SAFETY: this proxy grants exclusive access to this register
371 unsafe { &(*RCC::ptr()).bdcr }
372 }
373}
374
375/// Clock configuration
376///
377/// An instance of this struct is acquired from the [`RCC`](crate::pac::RCC) struct.
378///
379/// ```
380/// let dp = pac::Peripherals::take().unwrap();
381/// let rcc = dp.RCC.constrain();
382/// use_cfgr(&mut rcc.cfgr)
383/// ```
384pub struct CFGR {
385 hse: Option<u32>,
386 hse_bypass: bool,
387 pll_bypass: bool,
388 css: bool,
389 hclk: Option<u32>,
390 pclk1: Option<u32>,
391 pclk2: Option<u32>,
392 sysclk: Option<u32>,
393}
394
395impl Default for CFGR {
396 fn default() -> Self {
397 Self {
398 hse: None,
399 hse_bypass: false,
400 pll_bypass: true,
401 css: false,
402 hclk: None,
403 pclk1: None,
404 pclk2: None,
405 sysclk: None,
406 }
407 }
408}
409
410pub(crate) struct PllConfig {
411 src: cfgr::PLLSRC_A,
412 mul: cfgr::PLLMUL_A,
413 div: Option<cfgr2::PREDIV_A>,
414}
415
416/// Determine the [greatest common divisor](https://en.wikipedia.org/wiki/Greatest_common_divisor)
417///
418/// This function is based on the [Euclidean algorithm](https://en.wikipedia.org/wiki/Euclidean_algorithm).
419// TODO(Sh3Rm4n): As num-traits is a indirecty dependecy of this crate through embedded-time,
420// use its implementation instead.
421fn gcd(mut a: u32, mut b: u32) -> u32 {
422 while b != 0 {
423 let r = a % b;
424 a = b;
425 b = r;
426 }
427 a
428}
429
430/// Convert pll multiplier into equivalent register field type
431fn into_pll_mul(mul: u8) -> cfgr::PLLMUL_A {
432 match mul {
433 2 => cfgr::PLLMUL_A::Mul2,
434 3 => cfgr::PLLMUL_A::Mul3,
435 4 => cfgr::PLLMUL_A::Mul4,
436 5 => cfgr::PLLMUL_A::Mul5,
437 6 => cfgr::PLLMUL_A::Mul6,
438 7 => cfgr::PLLMUL_A::Mul7,
439 8 => cfgr::PLLMUL_A::Mul8,
440 9 => cfgr::PLLMUL_A::Mul9,
441 10 => cfgr::PLLMUL_A::Mul10,
442 11 => cfgr::PLLMUL_A::Mul11,
443 12 => cfgr::PLLMUL_A::Mul12,
444 13 => cfgr::PLLMUL_A::Mul13,
445 14 => cfgr::PLLMUL_A::Mul14,
446 15 => cfgr::PLLMUL_A::Mul15,
447 16 => cfgr::PLLMUL_A::Mul16,
448 _ => crate::unreachable!(),
449 }
450}
451
452/// Convert pll divisor into equivalent register field type
453fn into_pre_div(div: u8) -> cfgr2::PREDIV_A {
454 match div {
455 1 => cfgr2::PREDIV_A::Div1,
456 2 => cfgr2::PREDIV_A::Div2,
457 3 => cfgr2::PREDIV_A::Div3,
458 4 => cfgr2::PREDIV_A::Div4,
459 5 => cfgr2::PREDIV_A::Div5,
460 6 => cfgr2::PREDIV_A::Div6,
461 7 => cfgr2::PREDIV_A::Div7,
462 8 => cfgr2::PREDIV_A::Div8,
463 9 => cfgr2::PREDIV_A::Div9,
464 10 => cfgr2::PREDIV_A::Div10,
465 11 => cfgr2::PREDIV_A::Div11,
466 12 => cfgr2::PREDIV_A::Div12,
467 13 => cfgr2::PREDIV_A::Div13,
468 14 => cfgr2::PREDIV_A::Div14,
469 15 => cfgr2::PREDIV_A::Div15,
470 16 => cfgr2::PREDIV_A::Div16,
471 _ => crate::unreachable!(),
472 }
473}
474
475impl CFGR {
476 /// Uses `HSE` (external oscillator) instead of `HSI` (internal RC oscillator) as the clock source.
477 ///
478 /// Will result in a hang if an external oscillator is not connected or it fails to start,
479 /// unless [css](CFGR::enable_css) is enabled.
480 ///
481 /// # Panics
482 ///
483 /// Panics if conversion from `Megahertz` to `Hertz` produces a value greater then `u32::MAX`.
484 #[must_use]
485 pub fn use_hse(mut self, freq: Megahertz) -> Self {
486 let freq: Hertz = crate::expect!(freq.try_into(), "ConversionError");
487 self.hse = Some(freq.integer());
488 self
489 }
490
491 /// Set this to disallow bypass the PLLCLK for the systemclock generation.
492 #[must_use]
493 pub fn use_pll(mut self) -> Self {
494 self.pll_bypass = false;
495 self
496 }
497
498 /// Enable `HSE` bypass.
499 ///
500 /// Uses user provided clock signal instead of an external oscillator.
501 /// `OSC_OUT` pin is free and can be used as GPIO.
502 ///
503 /// No effect if `HSE` is not enabled.
504 #[must_use]
505 pub fn bypass_hse(mut self) -> Self {
506 self.hse_bypass = true;
507 self
508 }
509
510 /// Enable `CSS` (Clock Security System).
511 ///
512 /// System clock is automatically switched to `HSI` and an interrupt (`CSSI`) is generated
513 /// when `HSE` clock failure is detected.
514 ///
515 /// No effect if `HSE` is not enabled.
516 #[must_use]
517 pub fn enable_css(mut self) -> Self {
518 self.css = true;
519 self
520 }
521
522 /// Sets a frequency for the AHB bus.
523 ///
524 /// # Panics
525 ///
526 /// Panics if conversion from `Megahertz` to `Hertz` produces a value greater then `u32::MAX`.
527 #[must_use]
528 pub fn hclk(mut self, freq: Megahertz) -> Self {
529 let freq: Hertz = crate::expect!(freq.try_into(), "ConversionError");
530 self.hclk = Some(freq.integer());
531 self
532 }
533
534 /// Sets a frequency for the `APB1` bus
535 ///
536 /// - Maximal supported frequency: 36 Mhz
537 ///
538 /// If not manually set, it will be set to [`CFGR::sysclk`] frequency
539 /// or [`CFGR::sysclk`] frequency / 2, if [`CFGR::sysclk`] > 36 Mhz
540 ///
541 /// # Panics
542 ///
543 /// Panics if conversion from `Megahertz` to `Hertz` produces a value greater then `u32::MAX`.
544 #[must_use]
545 pub fn pclk1(mut self, freq: Megahertz) -> Self {
546 let freq: Hertz = crate::expect!(freq.try_into(), "ConversionError");
547 self.pclk1 = Some(freq.integer());
548 self
549 }
550
551 /// Sets a frequency for the `APB2` bus
552 ///
553 /// # Resolution and Limits
554 ///
555 /// - Maximal supported frequency with HSE: 72 Mhz
556 /// - Maximal supported frequency without HSE: 64 Mhz
557 ///
558 /// This is true for devices **except** the following devices,
559 /// as these allow finer resolutions
560 /// even when using the internal oscillator:
561 ///
562 /// [stm32f302xd,stm32f302xe,stm32f303xd,stm32f303xe,stm32f398]
563 ///
564 /// # Panics
565 ///
566 /// Panics if conversion from `Megahertz` to `Hertz` produces a value greater then `u32::MAX`.
567 #[must_use]
568 pub fn pclk2(mut self, freq: Megahertz) -> Self {
569 let freq: Hertz = crate::expect!(freq.try_into(), "ConversionError");
570 self.pclk2 = Some(freq.integer());
571 self
572 }
573
574 /// Sets the system (core) frequency
575 ///
576 /// # Resolution and Limits
577 ///
578 /// - Maximal supported frequency with `HSE`: 72 Mhz
579 /// - Maximal supported frequency without `HSE`: 64 Mhz
580 ///
581 /// If [`CFGR::use_hse`] is not set, `HSI / 2` will be used.
582 /// Only multiples of (HSI / 2) (4 Mhz) are allowed.
583 ///
584 /// This is true for devices **except** the following devices,
585 /// as these allow finer resolutions
586 /// even when using the internal oscillator:
587 ///
588 /// [stm32f302xd,stm32f302xe,stm32f303xd,stm32f303xe,stm32f398]
589 ///
590 /// # Panics
591 ///
592 /// Panics if conversion from `Megahertz` to `Hertz` produces a value greater then `u32::MAX`.
593 #[must_use]
594 pub fn sysclk(mut self, freq: Megahertz) -> Self {
595 let freq: Hertz = crate::expect!(freq.try_into(), "ConversionError");
596 self.sysclk = Some(freq.integer());
597 self
598 }
599
600 /// Calculate the values for the pll multiplier (`PLLMUL`) and the pll divisior (`PLLDIV`).
601 ///
602 /// These values are chosen depending on the chosen system clock (SYSCLK) and the frequency of the
603 /// oscillator clock (`HSE` / `HSI`).
604 ///
605 /// For these devices, `PLL_SRC` can selected between the internal oscillator (`HSI`) and
606 /// the external oscillator (`HSE`).
607 ///
608 /// HSI is divided by 2 before its transferred to `PLL_SRC`.
609 /// HSE can be divided between `1..16`, before it is transferred to `PLL_SRC`.
610 /// After this system clock frequency (`SYSCLK`) can be changed via multiplier.
611 /// The value can be multiplied with `2..16`.
612 ///
613 /// To determine the optimal values, if `HSE` is chosen as `PLL_SRC`, the greatest common divisor
614 /// is calculated and the limitations of the possible values are taken into consideration.
615 ///
616 /// `HSI` is simpler to calculate, but the possible system clocks are less than `HSE`, because the
617 /// division is not configurable.
618 #[cfg(not(feature = "gpio-f303e"))]
619 fn calc_pll(&self, sysclk: u32) -> (u32, PllConfig) {
620 let pllsrcclk = self.hse.unwrap_or(HSI.integer() / 2);
621 // Get the optimal value for the pll divisor (PLL_DIV) and multiplier (PLL_MUL)
622 // Only for HSE PLL_DIV can be changed
623 let (pll_mul, pll_div): (u32, Option<u32>) = if self.hse.is_some() {
624 // Get the optimal value for the pll divisor (PLL_DIV) and multiplier (PLL_MUL)
625 // with the greatest common divisor calculation.
626 let common_divisor = gcd(sysclk, pllsrcclk);
627 let mut multiplier = sysclk / common_divisor;
628 let mut divisor = pllsrcclk / common_divisor;
629
630 // Check if the multiplier can be represented by PLL_MUL
631 if multiplier == 1 {
632 // PLL_MUL minimal value is 2
633 multiplier *= 2;
634 divisor *= 2;
635 }
636
637 // PLL_MUL maximal value is 16
638 crate::assert!(multiplier <= 16);
639
640 // PRE_DIV maximal value is 16
641 crate::assert!(divisor <= 16);
642
643 (multiplier, Some(divisor))
644 }
645 // HSI division is always divided by 2 and has no adjustable division
646 else {
647 let pll_mul = sysclk / pllsrcclk;
648 crate::assert!(pll_mul <= 16);
649 (pll_mul, None)
650 };
651
652 let sysclk = (pllsrcclk / pll_div.unwrap_or(1)) * pll_mul;
653 crate::assert!(sysclk <= 72_000_000);
654
655 let pll_src = if self.hse.is_some() {
656 cfgr::PLLSRC_A::HseDivPrediv
657 } else {
658 cfgr::PLLSRC_A::HsiDiv2
659 };
660
661 // Convert into register bit field types
662 #[allow(clippy::cast_possible_truncation)]
663 let pll_mul_bits = into_pll_mul(pll_mul as u8);
664 #[allow(clippy::cast_possible_truncation)]
665 let pll_div_bits = pll_div.map(|pll_div| into_pre_div(pll_div as u8));
666
667 (
668 sysclk,
669 PllConfig {
670 src: pll_src,
671 mul: pll_mul_bits,
672 div: pll_div_bits,
673 },
674 )
675 }
676
677 /// Calculate the values for the pll multiplier (`PLLMUL`) and the pll divisor (`PLLDIV`).
678 ///
679 /// These values are chosen depending on the chosen system clock (`SYSCLK`) and the frequency of the oscillator
680 /// clk (`HSI` / `HSE`).
681 ///
682 /// For these devices, `PLL_SRC` can be set to choose between the internal oscillator (HSI) and
683 /// the external oscillator (`HSE`).
684 /// After this the system clock frequency (`SYSCLK`) can be changed via a division and a
685 /// multiplication block.
686 /// It can be divided from with values `1..16` and multiplied from `2..16`.
687 ///
688 /// To determine the optimal values, the greatest common divisor is calculated and the
689 /// limitations of the possible values are taken into considiration.
690 #[cfg(feature = "gpio-f303e")]
691 fn calc_pll(&self, sysclk: u32) -> (u32, PllConfig) {
692 let pllsrcclk = self.hse.unwrap_or(HSI.integer());
693
694 let (pll_mul, pll_div) = {
695 // Get the optimal value for the pll divisor (PLL_DIV) and multiplcator (PLL_MUL)
696 // with the greatest common divisor calculation.
697 let common_divisor = gcd(sysclk, pllsrcclk);
698 let mut multiplier = sysclk / common_divisor;
699 let mut divisor = pllsrcclk / common_divisor;
700
701 // Check if the multiplier can be represented by PLL_MUL
702 if multiplier == 1 {
703 // PLL_MUL minimal value is 2
704 multiplier *= 2;
705 divisor *= 2;
706 }
707
708 // PLL_MUL maximal value is 16
709 crate::assert!(multiplier <= 16);
710
711 // PRE_DIV maximal value is 16
712 crate::assert!(divisor <= 16);
713
714 (multiplier, divisor)
715 };
716
717 let sysclk = (pllsrcclk / pll_div) * pll_mul;
718 crate::assert!(sysclk <= 72_000_000);
719
720 // Select hardware clock source of the PLL
721 // TODO Check whether HSI_DIV2 could be useful
722 let pll_src = if self.hse.is_some() {
723 cfgr::PLLSRC_A::HseDivPrediv
724 } else {
725 cfgr::PLLSRC_A::HseDivPrediv
726 };
727
728 // Convert into register bit field types
729 #[allow(clippy::cast_possible_truncation)]
730 let pll_mul_bits = into_pll_mul(pll_mul as u8);
731 #[allow(clippy::cast_possible_truncation)]
732 let pll_div_bits = into_pre_div(pll_div as u8);
733
734 (
735 sysclk,
736 PllConfig {
737 src: pll_src,
738 mul: pll_mul_bits,
739 div: Some(pll_div_bits),
740 },
741 )
742 }
743
744 /// Get the system clock, the system clock source and the `pll_options`, if needed.
745 ///
746 /// The system clock source is determined by the chosen system clock and the provided hardware
747 /// clock.
748 /// This function does only chose the PLL if needed, otherwise it will use the oscillator clock as system clock.
749 ///
750 /// Calls [`CFGR::calc_pll`] internally.
751 fn get_sysclk(&self) -> (u32, cfgr::SW_A, Option<PllConfig>) {
752 // If a sysclk is given, check if the PLL has to be used,
753 // else select the system clock source, which is either HSI or HSE.
754 match (self.sysclk, self.hse) {
755 // No need to use the PLL
756 // PLL is needed for USB, but we can make this assumption, to not use PLL here,
757 // because the two valid USB clocks, 72 Mhz and 48 Mhz, can't be generated
758 // directly from neither the internal rc (8 Mhz) nor the external
759 // Oscillator (max 32 Mhz), without using the PLL.
760 (Some(sysclk), Some(hse)) if sysclk == hse && self.pll_bypass => {
761 (hse, cfgr::SW_A::Hse, None)
762 }
763 // No need to use the PLL
764 (Some(sysclk), None) if sysclk == HSI.integer() && self.pll_bypass => {
765 (HSI.integer(), cfgr::SW_A::Hsi, None)
766 }
767 (Some(sysclk), _) => {
768 let (sysclk, pll_config) = self.calc_pll(sysclk);
769 (sysclk, cfgr::SW_A::Pll, Some(pll_config))
770 }
771 // Use HSE as system clock
772 (None, Some(hse)) => (hse, cfgr::SW_A::Hse, None),
773 // Use HSI as system clock
774 (None, None) => (HSI.integer(), cfgr::SW_A::Hsi, None),
775 }
776 }
777
778 /// Freezes the clock configuration, making it effective
779 ///
780 /// This function internally calculates the specific.
781 /// divisors for the different clock peripheries.
782 ///
783 /// # Panics
784 ///
785 /// If any of the set frequencies via [`sysclk`](CFGR::sysclk), [`hclk`](CFGR::hclk), [`pclk1`](CFGR::pclk1) or [`pclk2`](CFGR::pclk2)
786 /// are invalid or can not be reached because of e.g. to low frequencies
787 /// of the former, as [`sysclk`](CFGR::sysclk) depends on the configuration of [`hclk`](CFGR::hclk)
788 /// this function will panic.
789 pub fn freeze(self, acr: &mut ACR) -> Clocks {
790 let (sysclk, sysclk_source, pll_config) = self.get_sysclk();
791
792 let (hpre_bits, hpre) =
793 self.hclk
794 .map_or((cfgr::HPRE_A::Div1, 1), |hclk| match sysclk / hclk {
795 0 => crate::unreachable!(),
796 1 => (cfgr::HPRE_A::Div1, 1),
797 2 => (cfgr::HPRE_A::Div2, 2),
798 3..=5 => (cfgr::HPRE_A::Div4, 4),
799 6..=11 => (cfgr::HPRE_A::Div8, 8),
800 12..=39 => (cfgr::HPRE_A::Div16, 16),
801 40..=95 => (cfgr::HPRE_A::Div64, 64),
802 96..=191 => (cfgr::HPRE_A::Div128, 128),
803 192..=383 => (cfgr::HPRE_A::Div256, 256),
804 _ => (cfgr::HPRE_A::Div512, 512),
805 });
806
807 let hclk: u32 = sysclk / hpre;
808
809 crate::assert!(hclk <= 72_000_000);
810
811 let (mut ppre1_bits, mut ppre1) =
812 self.pclk1
813 .map_or((cfgr::PPRE1_A::Div1, 1), |pclk1| match hclk / pclk1 {
814 0 => crate::unreachable!(),
815 1 => (cfgr::PPRE1_A::Div1, 1),
816 2 => (cfgr::PPRE1_A::Div2, 2),
817 3..=5 => (cfgr::PPRE1_A::Div4, 4),
818 6..=11 => (cfgr::PPRE1_A::Div8, 8),
819 _ => (cfgr::PPRE1_A::Div16, 16),
820 });
821
822 let mut pclk1 = hclk / u32::from(ppre1);
823
824 // This ensures, that no panic happens, when
825 // pclk1 is not manually set.
826 // As hclk highest value is 72.MHz()
827 // dividing by 2 should always be sufficient
828 if self.pclk1.is_none() && pclk1 > 36_000_000 {
829 ppre1_bits = cfgr::PPRE1_A::Div2;
830 ppre1 = 2;
831 pclk1 = hclk / u32::from(ppre1);
832 }
833
834 crate::assert!(pclk1 <= 36_000_000);
835
836 let (ppre2_bits, ppre2) =
837 self.pclk2
838 .map_or((cfgr::PPRE2_A::Div1, 1), |pclk2| match hclk / pclk2 {
839 0 => crate::unreachable!(),
840 1 => (cfgr::PPRE2_A::Div1, 1),
841 2 => (cfgr::PPRE2_A::Div2, 2),
842 3..=5 => (cfgr::PPRE2_A::Div4, 4),
843 6..=11 => (cfgr::PPRE2_A::Div8, 8),
844 _ => (cfgr::PPRE2_A::Div16, 16),
845 });
846
847 let pclk2 = hclk / u32::from(ppre2);
848
849 crate::assert!(pclk2 <= 72_000_000);
850
851 // Adjust flash wait states according to the
852 // HCLK frequency (cpu core clock)
853 acr.acr().modify(|_, w| {
854 if hclk <= 24_000_000 {
855 w.latency().ws0()
856 } else if hclk <= 48_000_000 {
857 w.latency().ws1()
858 } else {
859 w.latency().ws2()
860 }
861 });
862
863 let (usbpre, usbclk_valid) = usb_clocking::is_valid(sysclk, self.hse, pclk1, &pll_config);
864
865 // SAFETY: RCC ptr is guaranteed to be valid. This funciton is the first, which uses the
866 // RCC peripheral: RCC.constrain() -> Rcc -> CFGR
867 let rcc = unsafe { &*RCC::ptr() };
868
869 // enable HSE and wait for it to be ready
870 if self.hse.is_some() {
871 rcc.cr.modify(|_, w| {
872 w.hsebyp().bit(self.hse_bypass);
873 w.csson().bit(self.css);
874 w.hseon().on()
875 });
876
877 while rcc.cr.read().hserdy().is_not_ready() {}
878 }
879
880 // enable PLL and wait for it to be ready
881 if let Some(pll_config) = pll_config {
882 rcc.cfgr.modify(|_, w| {
883 w.pllmul()
884 .variant(pll_config.mul)
885 .pllsrc()
886 .variant(pll_config.src)
887 });
888
889 if let Some(pll_div) = pll_config.div {
890 rcc.cfgr2.modify(|_, w| w.prediv().variant(pll_div));
891 };
892
893 rcc.cr.modify(|_, w| w.pllon().on());
894
895 while rcc.cr.read().pllrdy().is_not_ready() {}
896 };
897
898 // set prescalers and clock source
899 rcc.cfgr.modify(|_, w| {
900 usb_clocking::set_usbpre(w, usbpre);
901
902 w.ppre2()
903 .variant(ppre2_bits)
904 .ppre1()
905 .variant(ppre1_bits)
906 .hpre()
907 .variant(hpre_bits)
908 .sw()
909 .variant(sysclk_source)
910 });
911
912 Clocks {
913 hclk: Hertz(hclk),
914 pclk1: Hertz(pclk1),
915 pclk2: Hertz(pclk2),
916 ppre1,
917 ppre2,
918 sysclk: Hertz(sysclk),
919 usbclk_valid,
920 pll_bypass: self.pll_bypass,
921 }
922 }
923}
924
925/// Frozen clock frequencies
926///
927/// The existence of this value indicates that the clock configuration can no longer be changed.
928/// This struct can be obtained via the [freeze](CFGR::freeze) method of the [CFGR](CFGR) struct.
929#[derive(Debug, Clone, Copy)]
930pub struct Clocks {
931 hclk: Hertz,
932 pclk1: Hertz,
933 pclk2: Hertz,
934 ppre1: u8,
935 ppre2: u8,
936 sysclk: Hertz,
937 usbclk_valid: bool,
938 pll_bypass: bool,
939}
940
941// TODO(Sh3Rm4n) Add defmt support for embedded-time!
942#[cfg(feature = "defmt")]
943impl defmt::Format for Clocks {
944 fn format(&self, f: defmt::Formatter) {
945 // Format as hexadecimal.
946 defmt::write!(
947 f,
948 "Clocks {{ hclk: {} Hz, pclk1: {} Hz, pclk2: {} Hz, ppre1: {:b}, ppre2: {:b}, sysclk: {} Hz, usbclk_valid: {}, pll_bypass: {} }}",
949 self.hclk.integer(),
950 self.pclk1.integer(),
951 self.pclk2.integer(),
952 self.ppre1,
953 self.ppre2,
954 self.sysclk.integer(),
955 self.usbclk_valid,
956 self.pll_bypass,
957 );
958 }
959}
960
961// TODO(Sh3Rm4n): Think of some way to generlize APB1 and APB2 as types to then implement a method,
962// with which the ppre or pclk can be obtained by passing in the type of APB.
963// With that in place, some places of macro magic are not needed anymore.
964impl Clocks {
965 /// Returns the frequency of the AHB
966 #[must_use]
967 pub fn hclk(&self) -> Hertz {
968 self.hclk
969 }
970
971 /// Returns the frequency of the APB1
972 #[must_use]
973 pub fn pclk1(&self) -> Hertz {
974 self.pclk1
975 }
976
977 /// Returns the frequency of the APB2
978 #[must_use]
979 pub fn pclk2(&self) -> Hertz {
980 self.pclk2
981 }
982
983 /// Returns the prescaler of the APB1
984 #[must_use]
985 pub fn ppre1(&self) -> u8 {
986 self.ppre1
987 }
988
989 /// Returns the prescaler of the APB2
990 #[must_use]
991 pub fn ppre2(&self) -> u8 {
992 self.ppre2
993 }
994
995 /// Returns the system (core) frequency
996 #[must_use]
997 pub fn sysclk(&self) -> Hertz {
998 self.sysclk
999 }
1000
1001 /// Returns the PLL clock if configured, else it returns `None`.
1002 ///
1003 /// The PLL clock is a source of the system clock, but it is not necessarily configured to be one.
1004 #[must_use]
1005 pub fn pllclk(&self) -> Option<Hertz> {
1006 if self.pll_bypass {
1007 None
1008 } else {
1009 // The PLLCLK is the same as the sysclk, beccause
1010 // the sysclk is using it as a source.
1011 Some(self.sysclk())
1012 }
1013 }
1014
1015 /// Returns whether the USBCLK clock frequency is valid for the USB peripheral
1016 ///
1017 /// If the microcontroller does support USB, 48 Mhz or 72 Mhz have to be used
1018 /// and the [`CFGR::use_hse`] must be set.
1019 ///
1020 /// The APB1 / [`CFGR::pclk1`] clock must have a minimum frequency of 10 MHz to avoid data
1021 /// overrun/underrun problems. [RM0316 32.5.2][RM0316]
1022 ///
1023 /// [RM0316]: https://www.st.com/resource/en/reference_manual/dm00043574.pdf
1024 #[must_use]
1025 pub fn usbclk_valid(&self) -> bool {
1026 self.usbclk_valid
1027 }
1028}