stm32f1_hal/rcc/
mod.rs

1//! # Reset & Control Clock
2
3use core::ops::{Deref, DerefMut};
4
5use crate::pac::{
6    BKP, PWR, RCC,
7    rcc::{self, RegisterBlock as RccRB},
8};
9
10use crate::flash::ACR;
11#[cfg(any(feature = "stm32f103", feature = "connectivity"))]
12use crate::time::MHz;
13use fugit::{HertzU32 as Hertz, RateExtU32};
14
15use crate::backup_domain::BackupDomain;
16
17mod enable;
18
19/// Extension trait that constrains the `RCC` peripheral
20pub trait RccExt {
21    /// Constrains the `RCC` peripheral so it plays nicely with the other abstractions
22    fn constrain(self) -> Rcc;
23}
24
25impl RccExt for RCC {
26    fn constrain(self) -> Rcc {
27        Rcc {
28            rb: self,
29            clocks: Clocks::default(),
30        }
31    }
32}
33
34/// Constrained RCC peripheral
35///
36/// Aquired by calling the [constrain](../trait.RccExt.html#tymethod.constrain) method
37/// on the Rcc struct from the `PAC`
38///
39/// ```rust
40/// let dp = pac::Peripherals::take().unwrap();
41/// let mut rcc = dp.RCC.constrain();
42/// ```
43pub struct Rcc {
44    pub clocks: Clocks,
45    pub(crate) rb: RCC,
46}
47
48impl Rcc {
49    /// Applies the clock configuration and returns a `Clocks` struct that signifies that the
50    /// clocks are frozen, and contains the frequencies used. After this function is called,
51    /// the clocks can not change
52    ///
53    /// Usage:
54    ///
55    /// ```rust
56    /// let dp = pac::Peripherals::take().unwrap();
57    /// let mut flash = dp.FLASH.constrain();
58    /// let cfg = rcc::Config::hse(8.MHz()).sysclk(72.MHz());
59    /// let mut rcc = dp.RCC.constrain().freeze(cfg, &mut flash.acr);
60    /// ```
61    #[allow(unused_variables)]
62    #[inline(always)]
63    pub fn freeze(self, cfg: impl Into<RawConfig>, acr: &mut ACR) -> Self {
64        let cfg = cfg.into();
65        let clocks = cfg.get_clocks();
66        // adjust flash wait states
67        #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
68        unsafe {
69            acr.acr().write(|w| {
70                w.latency().bits(if clocks.sysclk <= MHz(24) {
71                    0b000
72                } else if clocks.sysclk <= MHz(48) {
73                    0b001
74                } else {
75                    0b010
76                })
77            });
78        }
79
80        let rcc = unsafe { &*RCC::ptr() };
81
82        if cfg.hse.is_some() {
83            // enable HSE and wait for it to be ready
84
85            rcc.cr().modify(|_, w| {
86                if cfg.hse_bypass {
87                    w.hsebyp().bypassed();
88                }
89                w.hseon().set_bit()
90            });
91
92            while rcc.cr().read().hserdy().bit_is_clear() {}
93        }
94
95        if let Some(pllmul_bits) = cfg.pllmul {
96            // enable PLL and wait for it to be ready
97
98            #[allow(unused_unsafe)]
99            rcc.cfgr().modify(|_, w| unsafe {
100                w.pllmul().bits(pllmul_bits).pllsrc().bit(cfg.hse.is_some())
101            });
102
103            rcc.cr().modify(|_, w| w.pllon().set_bit());
104
105            while rcc.cr().read().pllrdy().bit_is_clear() {}
106        }
107
108        // set prescalers and clock source
109        #[cfg(feature = "connectivity")]
110        rcc.cfgr().modify(|_, w| unsafe {
111            w.adcpre().variant(cfg.adcpre);
112            w.ppre2().bits(cfg.ppre2 as u8);
113            w.ppre1().bits(cfg.ppre1 as u8);
114            w.hpre().bits(cfg.hpre as u8);
115            w.otgfspre().variant(cfg.usbpre);
116            w.sw().bits(if cfg.pllmul.is_some() {
117                // PLL
118                0b10
119            } else if cfg.hse.is_some() {
120                // HSE
121                0b1
122            } else {
123                // HSI
124                0b0
125            })
126        });
127
128        #[cfg(feature = "stm32f103")]
129        rcc.cfgr().modify(|_, w| unsafe {
130            w.adcpre().variant(cfg.adcpre);
131            w.ppre2().bits(cfg.ppre2 as u8);
132            w.ppre1().bits(cfg.ppre1 as u8);
133            w.hpre().bits(cfg.hpre as u8);
134            w.usbpre().variant(cfg.usbpre);
135            w.sw().bits(if cfg.pllmul.is_some() {
136                // PLL
137                0b10
138            } else {
139                // HSE or HSI
140                u8::from(cfg.hse.is_some())
141            })
142        });
143
144        #[cfg(any(feature = "stm32f100", feature = "stm32f101"))]
145        rcc.cfgr().modify(|_, w| unsafe {
146            w.adcpre().variant(cfg.adcpre);
147            w.ppre2().bits(cfg.ppre2 as u8);
148            w.ppre1().bits(cfg.ppre1 as u8);
149            w.hpre().bits(cfg.hpre as u8);
150            w.sw().bits(if cfg.pllmul.is_some() {
151                // PLL
152                0b10
153            } else if cfg.hse.is_some() {
154                // HSE
155                0b1
156            } else {
157                // HSI
158                0b0
159            })
160        });
161
162        Self {
163            rb: self.rb,
164            clocks,
165        }
166    }
167
168    pub fn enable<T: Enable>(&mut self, _periph: &T) {
169        T::enable(self);
170    }
171
172    pub fn reset<T: Reset>(&mut self, _periph: &T) {
173        T::reset(self);
174    }
175
176    pub fn get_clock<T: BusClock>(&self, _periph: &T) -> Hertz {
177        T::clock(&self.clocks)
178    }
179
180    pub fn get_timer_clock<T: BusTimerClock>(&self, _periph: &T) -> Hertz {
181        T::timer_clock(&self.clocks)
182    }
183}
184
185impl Deref for Rcc {
186    type Target = RCC;
187    fn deref(&self) -> &Self::Target {
188        &self.rb
189    }
190}
191
192impl DerefMut for Rcc {
193    fn deref_mut(&mut self) -> &mut Self::Target {
194        &mut self.rb
195    }
196}
197
198macro_rules! bus_struct {
199    ($($busX:ident => ($EN:ident, $en:ident, $($RST:ident, $rst:ident,)? $doc:literal),)+) => {
200        $(
201            #[doc = $doc]
202            #[non_exhaustive]
203            pub struct $busX;
204
205            impl $busX {
206                pub(crate) fn enr(rcc: &RccRB) -> &rcc::$EN {
207                    rcc.$en()
208                }
209                $(
210                    pub(crate) fn rstr(rcc: &RccRB) -> &rcc::$RST {
211                        rcc.$rst()
212                    }
213                )?
214            }
215        )+
216    };
217}
218use bus_struct;
219
220bus_struct! {
221    APB1 => (APB1ENR, apb1enr, APB1RSTR, apb1rstr, "Advanced Peripheral Bus 1 (APB1) registers"),
222    APB2 => (APB2ENR, apb2enr, APB2RSTR, apb2rstr, "Advanced Peripheral Bus 2 (APB2) registers"),
223    AHB => (AHBENR, ahbenr, "Advanced High-performance Bus (AHB) registers"),
224}
225
226const HSI: u32 = 8_000_000; // Hz
227
228/// Clock configuration
229///
230/// Used to configure the frequencies of the clocks present in the processor.
231///
232/// After setting all frequencies, call the [freeze](#method.freeze) function to
233/// apply the configuration.
234///
235/// **NOTE**: Currently, it is not guaranteed that the exact frequencies selected will be
236/// used, only frequencies close to it.
237#[derive(Debug, Default, PartialEq, Eq)]
238pub struct Config {
239    hse: Option<u32>,
240    hse_bypass: bool,
241    hclk: Option<u32>,
242    pclk1: Option<u32>,
243    pclk2: Option<u32>,
244    sysclk: Option<u32>,
245    adcclk: Option<u32>,
246}
247
248impl Config {
249    pub const DEFAULT: Self = Self {
250        hse: None,
251        hse_bypass: false,
252        hclk: None,
253        pclk1: None,
254        pclk2: None,
255        sysclk: None,
256        adcclk: None,
257    };
258
259    pub fn hsi() -> Self {
260        Self::DEFAULT
261    }
262
263    pub fn hse(freq: Hertz) -> Self {
264        Self::DEFAULT.use_hse(freq)
265    }
266
267    /// Uses HSE (external oscillator) instead of HSI (internal RC oscillator) as the clock source.
268    /// Will result in a hang if an external oscillator is not connected or it fails to start.
269    /// The frequency specified must be the frequency of the external oscillator
270    #[inline(always)]
271    pub fn use_hse(mut self, freq: Hertz) -> Self {
272        self.hse = Some(freq.raw());
273        self
274    }
275
276    /// Bypasses the high-speed external oscillator and uses an external clock input on the OSC_IN
277    /// pin.
278    ///
279    /// For this configuration, the OSC_IN pin should be connected to a clock source with a
280    /// frequency specified in the call to use_hse(), and the OSC_OUT pin should not be connected.
281    ///
282    /// This function has no effect unless use_hse() is also called.
283    pub fn bypass_hse_oscillator(self) -> Self {
284        Self {
285            hse_bypass: true,
286            ..self
287        }
288    }
289
290    /// Sets the desired frequency for the HCLK clock
291    #[inline(always)]
292    pub fn hclk(mut self, freq: Hertz) -> Self {
293        self.hclk = Some(freq.raw());
294        self
295    }
296
297    /// Sets the desired frequency for the PCKL1 clock
298    #[inline(always)]
299    pub fn pclk1(mut self, freq: Hertz) -> Self {
300        self.pclk1 = Some(freq.raw());
301        self
302    }
303
304    /// Sets the desired frequency for the PCLK2 clock
305    #[inline(always)]
306    pub fn pclk2(mut self, freq: Hertz) -> Self {
307        self.pclk2 = Some(freq.raw());
308        self
309    }
310
311    /// Sets the desired frequency for the SYSCLK clock
312    #[inline(always)]
313    pub fn sysclk(mut self, freq: Hertz) -> Self {
314        self.sysclk = Some(freq.raw());
315        self
316    }
317
318    /// Sets the desired frequency for the ADCCLK clock
319    #[inline(always)]
320    pub fn adcclk(mut self, freq: Hertz) -> Self {
321        self.adcclk = Some(freq.raw());
322        self
323    }
324}
325
326pub trait BkpExt {
327    /// Enables write access to the registers in the backup domain
328    fn constrain(self, pwr: &mut PWR, rcc: &mut RCC) -> BackupDomain;
329}
330
331impl BkpExt for BKP {
332    fn constrain(self, pwr: &mut PWR, rcc: &mut RCC) -> BackupDomain {
333        // Enable the backup interface by setting PWREN and BKPEN
334        BKP::enable(rcc);
335        PWR::enable(rcc);
336
337        // Enable access to the backup registers
338        pwr.cr().modify(|_r, w| w.dbp().set_bit());
339
340        BackupDomain { _regs: self }
341    }
342}
343
344/// Frozen clock frequencies
345///
346/// The existence of this value indicates that the clock configuration can no longer be changed
347///
348/// To acquire it, use the freeze function on the `rcc.cfgr` register. If desired, you can adjust
349/// the frequencies using the methods on [cfgr](struct.CFGR.html) before calling freeze.
350///
351/// ```rust
352/// let dp = pac::Peripherals::take().unwrap();
353/// let mut rcc = dp.RCC.constrain();
354/// let mut flash = dp.FLASH.constrain();
355///
356/// let clocks = rcc.cfgr.freeze(&mut flash.acr);
357/// ```
358#[derive(Clone, Copy, Debug, PartialEq, Eq)]
359pub struct Clocks {
360    hclk: Hertz,
361    pclk1: Hertz,
362    pclk2: Hertz,
363    ppre1: u8,
364    ppre2: u8,
365    sysclk: Hertz,
366    adcclk: Hertz,
367    #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
368    usbclk_valid: bool,
369}
370
371impl Default for Clocks {
372    fn default() -> Clocks {
373        let freq = HSI.Hz();
374        Clocks {
375            hclk: freq,
376            pclk1: freq,
377            pclk2: freq,
378            ppre1: 1,
379            ppre2: 1,
380            sysclk: freq,
381            adcclk: freq / 2,
382            #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
383            usbclk_valid: false,
384        }
385    }
386}
387
388impl Clocks {
389    /// Returns the frequency of the AHB
390    pub const fn hclk(&self) -> Hertz {
391        self.hclk
392    }
393
394    /// Returns the frequency of the APB1
395    pub const fn pclk1(&self) -> Hertz {
396        self.pclk1
397    }
398
399    /// Returns the frequency of the APB2
400    pub const fn pclk2(&self) -> Hertz {
401        self.pclk2
402    }
403
404    /// Returns the frequency of the APB1 Timers
405    pub const fn pclk1_tim(&self) -> Hertz {
406        Hertz::from_raw(self.pclk1.raw() * if self.ppre1() == 1 { 1 } else { 2 })
407    }
408
409    /// Returns the frequency of the APB2 Timers
410    pub const fn pclk2_tim(&self) -> Hertz {
411        Hertz::from_raw(self.pclk2.raw() * if self.ppre2() == 1 { 1 } else { 2 })
412    }
413
414    pub(crate) const fn ppre1(&self) -> u8 {
415        self.ppre1
416    }
417
418    // TODO remove `allow`
419    #[allow(dead_code)]
420    pub(crate) const fn ppre2(&self) -> u8 {
421        self.ppre2
422    }
423
424    /// Returns the system (core) frequency
425    pub const fn sysclk(&self) -> Hertz {
426        self.sysclk
427    }
428
429    /// Returns the adc clock frequency
430    pub const fn adcclk(&self) -> Hertz {
431        self.adcclk
432    }
433
434    /// Returns whether the USBCLK clock frequency is valid for the USB peripheral
435    #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
436    pub const fn usbclk_valid(&self) -> bool {
437        self.usbclk_valid
438    }
439}
440
441/// Frequency on bus that peripheral is connected in
442pub trait BusClock {
443    /// Calculates frequency depending on `Clock` state
444    fn clock(clocks: &Clocks) -> Hertz;
445}
446
447/// Frequency on bus that timer is connected in
448pub trait BusTimerClock {
449    /// Calculates base frequency of timer depending on `Clock` state
450    fn timer_clock(clocks: &Clocks) -> Hertz;
451}
452
453impl<T> BusClock for T
454where
455    T: RccBus,
456    T::Bus: BusClock,
457{
458    fn clock(clocks: &Clocks) -> Hertz {
459        T::Bus::clock(clocks)
460    }
461}
462
463impl<T> BusTimerClock for T
464where
465    T: RccBus,
466    T::Bus: BusTimerClock,
467{
468    fn timer_clock(clocks: &Clocks) -> Hertz {
469        T::Bus::timer_clock(clocks)
470    }
471}
472
473impl BusClock for AHB {
474    fn clock(clocks: &Clocks) -> Hertz {
475        clocks.hclk
476    }
477}
478
479impl BusClock for APB1 {
480    fn clock(clocks: &Clocks) -> Hertz {
481        clocks.pclk1
482    }
483}
484
485impl BusClock for APB2 {
486    fn clock(clocks: &Clocks) -> Hertz {
487        clocks.pclk2
488    }
489}
490
491impl BusTimerClock for APB1 {
492    fn timer_clock(clocks: &Clocks) -> Hertz {
493        clocks.pclk1_tim()
494    }
495}
496
497impl BusTimerClock for APB2 {
498    fn timer_clock(clocks: &Clocks) -> Hertz {
499        clocks.pclk2_tim()
500    }
501}
502
503/// Bus associated to peripheral
504pub trait RccBus {
505    /// Bus type;
506    type Bus;
507}
508
509/// Enable/disable peripheral
510pub trait Enable: RccBus {
511    /// Enables peripheral
512    fn enable(rcc: &mut RCC);
513
514    /// Disables peripheral
515    fn disable(rcc: &mut RCC);
516
517    /// Check if peripheral enabled
518    fn is_enabled() -> bool;
519
520    /// Check if peripheral disabled
521    #[inline]
522    fn is_disabled() -> bool {
523        !Self::is_enabled()
524    }
525
526    /// # Safety
527    ///
528    /// Enables peripheral. Takes access to RCC internally
529    unsafe fn enable_unchecked() {
530        let mut rcc = unsafe { RCC::steal() };
531        Self::enable(&mut rcc);
532    }
533
534    /// # Safety
535    ///
536    /// Disables peripheral. Takes access to RCC internally
537    unsafe fn disable_unchecked() {
538        let mut rcc = unsafe { RCC::steal() };
539        Self::disable(&mut rcc);
540    }
541}
542
543/// Reset peripheral
544pub trait Reset: RccBus {
545    /// Resets peripheral
546    fn reset(rcc: &mut RCC);
547
548    /// # Safety
549    ///
550    /// Resets peripheral. Takes access to RCC internally
551    unsafe fn reset_unchecked() {
552        let mut rcc = unsafe { RCC::steal() };
553        Self::reset(&mut rcc);
554    }
555}
556
557#[derive(Clone, Copy, Debug, PartialEq)]
558pub struct RawConfig {
559    pub hse: Option<u32>,
560    pub hse_bypass: bool,
561    pub pllmul: Option<u8>,
562    pub hpre: HPre,
563    pub ppre1: PPre,
564    pub ppre2: PPre,
565    #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
566    pub usbpre: UsbPre,
567    pub adcpre: AdcPre,
568    pub allow_overclock: bool,
569}
570
571impl Default for RawConfig {
572    fn default() -> Self {
573        Self {
574            hse: None,
575            hse_bypass: false,
576            pllmul: None,
577            hpre: HPre::Div1,
578            ppre1: PPre::Div1,
579            ppre2: PPre::Div1,
580            #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
581            usbpre: UsbPre::Div1_5,
582            adcpre: AdcPre::Div2,
583            allow_overclock: false,
584        }
585    }
586}
587
588#[repr(u8)]
589#[derive(Clone, Copy, Debug, PartialEq, Eq)]
590pub enum HPre {
591    /// SYSCLK not divided
592    Div1 = 7,
593    /// SYSCLK divided by 2
594    Div2 = 8,
595    /// SYSCLK divided by 4
596    Div4 = 9,
597    /// SYSCLK divided by 8
598    Div8 = 10,
599    /// SYSCLK divided by 16
600    Div16 = 11,
601    /// SYSCLK divided by 64
602    Div64 = 12,
603    /// SYSCLK divided by 128
604    Div128 = 13,
605    /// SYSCLK divided by 256
606    Div256 = 14,
607    /// SYSCLK divided by 512
608    Div512 = 15,
609}
610
611#[derive(Clone, Copy, Debug, PartialEq, Eq)]
612#[repr(u8)]
613pub enum PPre {
614    /// HCLK not divided
615    Div1 = 3,
616    /// HCLK divided by 2
617    Div2 = 4,
618    /// HCLK divided by 4
619    Div4 = 5,
620    /// HCLK divided by 8
621    Div8 = 6,
622    /// HCLK divided by 16
623    Div16 = 7,
624}
625
626#[cfg(feature = "stm32f103")]
627pub type UsbPre = rcc::cfgr::USBPRE;
628#[cfg(feature = "connectivity")]
629pub type UsbPre = rcc::cfgr::OTGFSPRE;
630pub type AdcPre = rcc::cfgr::ADCPRE;
631
632impl From<Config> for RawConfig {
633    #[inline(always)]
634    fn from(cfgr: Config) -> Self {
635        Self::from_cfgr(cfgr)
636    }
637}
638
639impl RawConfig {
640    pub const fn from_cfgr(cfgr: Config) -> Self {
641        let hse = cfgr.hse;
642        let hse_bypass = cfgr.hse_bypass;
643        let pllsrcclk = if let Some(hse) = hse { hse } else { HSI / 2 };
644
645        let pllmul = if let Some(sysclk) = cfgr.sysclk {
646            sysclk / pllsrcclk
647        } else {
648            1
649        };
650
651        let (pllmul_bits, sysclk) = if pllmul == 1 {
652            (None, if let Some(hse) = hse { hse } else { HSI })
653        } else {
654            #[cfg(not(feature = "connectivity"))]
655            let pllmul = match pllmul {
656                1..=16 => pllmul,
657                0 => 1,
658                _ => 16,
659            };
660
661            #[cfg(feature = "connectivity")]
662            let pllmul = match pllmul {
663                4..=9 => pllmul,
664                0..=3 => 4,
665                _ => 9,
666            };
667
668            (Some(pllmul as u8 - 2), pllsrcclk * pllmul)
669        };
670
671        let hpre_bits = if let Some(hclk) = cfgr.hclk {
672            match sysclk / hclk {
673                0..=1 => HPre::Div1,
674                2 => HPre::Div2,
675                3..=5 => HPre::Div4,
676                6..=11 => HPre::Div8,
677                12..=39 => HPre::Div16,
678                40..=95 => HPre::Div64,
679                96..=191 => HPre::Div128,
680                192..=383 => HPre::Div256,
681                _ => HPre::Div512,
682            }
683        } else {
684            HPre::Div1
685        };
686
687        let hclk = if hpre_bits as u8 >= 0b1100 {
688            sysclk / (1 << (hpre_bits as u8 - 0b0110))
689        } else {
690            sysclk / (1 << (hpre_bits as u8 - 0b0111))
691        };
692
693        let pclk1 = if let Some(pclk1) = cfgr.pclk1 {
694            pclk1
695        } else if hclk < 36_000_000 {
696            hclk
697        } else {
698            36_000_000
699        };
700        let ppre1_bits = match hclk.div_ceil(pclk1) {
701            0 | 1 => PPre::Div1,
702            2 => PPre::Div2,
703            3..=5 => PPre::Div4,
704            6..=11 => PPre::Div8,
705            _ => PPre::Div16,
706        };
707
708        let ppre2_bits = if let Some(pclk2) = cfgr.pclk2 {
709            match hclk / pclk2 {
710                0..=1 => PPre::Div1,
711                2 => PPre::Div2,
712                3..=5 => PPre::Div4,
713                6..=11 => PPre::Div8,
714                _ => PPre::Div16,
715            }
716        } else {
717            PPre::Div1
718        };
719
720        let ppre2 = 1 << (ppre2_bits as u8 - 0b011);
721        let pclk2 = hclk / (ppre2 as u32);
722
723        // usbpre == false: divide clock by 1.5, otherwise no division
724        #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
725        let usbpre = match (hse, pllmul_bits, sysclk) {
726            (Some(_), Some(_), 72_000_000) => UsbPre::Div1_5,
727            _ => UsbPre::Div1,
728        };
729
730        let apre_bits = if let Some(adcclk) = cfgr.adcclk {
731            match pclk2 / adcclk {
732                0..=2 => AdcPre::Div2,
733                3..=4 => AdcPre::Div4,
734                5..=7 => AdcPre::Div6,
735                _ => AdcPre::Div8,
736            }
737        } else {
738            AdcPre::Div8
739        };
740
741        Self {
742            hse,
743            hse_bypass,
744            pllmul: pllmul_bits,
745            hpre: hpre_bits,
746            ppre1: ppre1_bits,
747            ppre2: ppre2_bits,
748            #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
749            usbpre,
750            adcpre: apre_bits,
751            allow_overclock: false,
752        }
753    }
754
755    // NOTE: to maintain the invariant that the existence of a Clocks
756    // value implies frozen clocks, this function must not be pub.
757    fn get_clocks(&self) -> Clocks {
758        let sysclk = if let Some(pllmul_bits) = self.pllmul {
759            let pllsrcclk = if let Some(hse) = self.hse {
760                hse
761            } else {
762                HSI / 2
763            };
764            pllsrcclk * (pllmul_bits as u32 + 2)
765        } else if let Some(hse) = self.hse {
766            hse
767        } else {
768            HSI
769        };
770
771        let hclk = if self.hpre as u8 >= 0b1100 {
772            sysclk / (1 << (self.hpre as u8 - 0b0110))
773        } else {
774            sysclk / (1 << (self.hpre as u8 - 0b0111))
775        };
776
777        let ppre1 = 1 << (self.ppre1 as u8 - 0b011);
778        let pclk1 = hclk / (ppre1 as u32);
779
780        let ppre2 = 1 << (self.ppre2 as u8 - 0b011);
781        let pclk2 = hclk / (ppre2 as u32);
782
783        let apre = (self.adcpre as u8 + 1) << 1;
784        let adcclk = pclk2 / (apre as u32);
785
786        // the USB clock is only valid if an external crystal is used, the PLL is enabled, and the
787        // PLL output frequency is a supported one.
788        #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
789        let usbclk_valid = matches!(
790            (self.hse, self.pllmul, sysclk),
791            (Some(_), Some(_), 72_000_000) | (Some(_), Some(_), 48_000_000)
792        );
793
794        assert!(
795            self.allow_overclock
796                || (sysclk <= 72_000_000
797                    && hclk <= 72_000_000
798                    && pclk1 <= 36_000_000
799                    && pclk2 <= 72_000_000
800                    && adcclk <= 14_000_000)
801        );
802
803        Clocks {
804            hclk: hclk.Hz(),
805            pclk1: pclk1.Hz(),
806            pclk2: pclk2.Hz(),
807            ppre1,
808            ppre2,
809            sysclk: sysclk.Hz(),
810            adcclk: adcclk.Hz(),
811            #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
812            usbclk_valid,
813        }
814    }
815}
816
817#[test]
818fn rcc_config_usb() {
819    let cfgr = Config::default()
820        .use_hse(8.MHz())
821        .sysclk(48.MHz())
822        .pclk1(24.MHz());
823
824    let config = RawConfig::from_cfgr(cfgr);
825    let config_expected = RawConfig {
826        hse: Some(8_000_000),
827        hse_bypass: false,
828        pllmul: Some(4),
829        hpre: HPre::Div1,
830        ppre1: PPre::Div2,
831        ppre2: PPre::Div1,
832        #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
833        usbpre: UsbPre::Div1,
834        adcpre: AdcPre::Div8,
835        allow_overclock: false,
836    };
837    assert_eq!(config, config_expected);
838
839    let clocks = config.get_clocks();
840    let clocks_expected = Clocks {
841        hclk: 48.MHz(),
842        pclk1: 24.MHz(),
843        pclk2: 48.MHz(),
844        ppre1: 2,
845        ppre2: 1,
846        sysclk: 48.MHz(),
847        adcclk: 6.MHz(),
848        #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
849        usbclk_valid: true,
850    };
851    assert_eq!(clocks, clocks_expected);
852}