stm32f1_hal/rcc/
mod.rs

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