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