stm32f7xx_hal/
rcc.rs

1//! Reset and clock control.
2
3use core::cmp::min;
4
5mod enable;
6
7#[cfg_attr(test, allow(unused_imports))]
8use micromath::F32Ext;
9
10use crate::pac::{rcc, FLASH, PWR, RCC};
11use fugit::{HertzU32 as Hertz, RateExtU32};
12
13/// Typical output frequency of the HSI oscillator.
14const HSI_FREQUENCY: Hertz = Hertz::from_raw(16_000_000);
15
16/// Extension trait that constrains the `RCC` peripheral
17pub trait RccExt {
18    /// Constrains the `RCC` peripheral so it plays nicely with the other abstractions
19    fn constrain(self) -> Rcc;
20}
21
22impl RccExt for RCC {
23    fn constrain(self) -> Rcc {
24        Rcc {
25            ahb1: AHB1::new(),
26            ahb2: AHB2::new(),
27            ahb3: AHB3::new(),
28            apb1: APB1::new(),
29            apb2: APB2::new(),
30            bdcr: BDCR::new(),
31            cfgr: CFGR {
32                hse: None,
33                hclk: None,
34                sysclk: None,
35                pclk1: None,
36                pclk2: None,
37                lse: None,
38                lsi: None,
39                use_pll: false,
40                pll48clk: None,
41                pllm: 2,
42                plln: 50,
43                pllp: PLLP::Div2,
44                pllq: 2,
45                use_pllsai: false,
46                pllsain: 192,
47                pllsaip: PLLSAIP::Div2,
48                pllsaiq: 2,
49                use_plli2s: false,
50                plli2sr: 2,
51                plli2sq: 2,
52                plli2sn: 192,
53                mco1: MCO1::Hsi,
54                mco1pre: MCOPRE::Div1_no_div,
55                mco2: MCO2::Sysclk,
56                mco2pre: MCOPRE::Div1_no_div,
57            },
58        }
59    }
60}
61
62/// Constrained RCC peripheral
63pub struct Rcc {
64    /// Advanced High-Performance Bus 1 (AHB1) registers
65    pub ahb1: AHB1,
66    /// Advanced High-Performance Bus 2 (AHB2) registers
67    pub ahb2: AHB2,
68    /// Advanced High-Performance Bus 3 (AHB3) registers
69    pub ahb3: AHB3,
70
71    /// Advanced Peripheral Bus 1 (APB1) registers
72    pub apb1: APB1,
73    /// Advanced Peripheral Bus 2 (APB2) registers
74    pub apb2: APB2,
75    /// RCC Backup Domain
76    pub bdcr: BDCR,
77    pub cfgr: CFGR,
78}
79
80macro_rules! bus_struct {
81    ($($busX:ident => ($EN:ident, $en:ident, $LPEN:ident, $lpen:ident, $RST:ident, $rst:ident, $doc:literal),)+) => {
82        $(
83            #[doc = $doc]
84            pub struct $busX {
85                _0: (),
86            }
87
88            impl $busX {
89                pub(crate) fn new() -> Self {
90                    Self { _0: () }
91                }
92
93                pub(crate) fn enr(&self) -> &rcc::$EN {
94                    // NOTE(unsafe) this proxy grants exclusive access to this register
95                    unsafe { &(*RCC::ptr()).$en }
96                }
97
98                pub(crate) fn lpenr(&self) -> &rcc::$LPEN {
99                    // NOTE(unsafe) this proxy grants exclusive access to this register
100                    unsafe { &(*RCC::ptr()).$lpen }
101                }
102
103                pub(crate) fn rstr(&self) -> &rcc::$RST {
104                    // NOTE(unsafe) this proxy grants exclusive access to this register
105                    unsafe { &(*RCC::ptr()).$rst }
106                }
107            }
108        )+
109    };
110}
111
112bus_struct! {
113    APB1 => (APB1ENR, apb1enr, APB1LPENR, apb1lpenr, APB1RSTR, apb1rstr, "Advanced Peripheral Bus 1 (APB1) registers"),
114    APB2 => (APB2ENR, apb2enr, APB2LPENR, apb2lpenr, APB2RSTR, apb2rstr, "Advanced Peripheral Bus 2 (APB2) registers"),
115    AHB1 => (AHB1ENR, ahb1enr, AHB1LPENR, ahb1lpenr, AHB1RSTR, ahb1rstr, "Advanced High-performance Bus 1 (AHB1) registers"),
116    AHB2 => (AHB2ENR, ahb2enr, AHB2LPENR, ahb2lpenr, AHB2RSTR, ahb2rstr, "Advanced High-performance Bus 2 (AHB2) registers"),
117    AHB3 => (AHB3ENR, ahb3enr, AHB3LPENR, ahb3lpenr, AHB3RSTR, ahb3rstr, "Advanced High-performance Bus 3 (AHB3) registers"),
118}
119
120/// Backup Domain Control register (RCC_BDCR)
121pub struct BDCR {
122    _0: (),
123}
124
125impl BDCR {
126    pub(crate) fn new() -> Self {
127        Self { _0: () }
128    }
129}
130
131/// HSE clock mode.
132#[derive(Clone, Copy, Debug, PartialEq, Eq)]
133pub enum HSEClockMode {
134    /// Enable HSE oscillator to use external crystal or ceramic resonator.
135    Oscillator,
136    /// Bypass HSE oscillator to use external clock source.
137    Bypass,
138}
139
140/// HSE Clock.
141#[derive(Clone, Copy, Debug, PartialEq, Eq)]
142pub struct HSEClock {
143    /// Input frequency.
144    pub(crate) freq: Hertz,
145    /// Mode.
146    mode: HSEClockMode,
147}
148
149impl HSEClock {
150    /// Provide HSE frequency.
151    ///
152    /// # Panics
153    ///
154    /// Panics if the frequency is outside the valid range. The frequency must be between
155    /// 4 MHz and 26 MHz in oscillator mode and between 1 MHz and 50 MHz in bypass mode.
156    pub fn new(freq: Hertz, mode: HSEClockMode) -> Self {
157        let valid_range = match mode {
158            // Source: Datasheet DS12536 Rev 2, Table 38
159            HSEClockMode::Oscillator => Hertz::MHz(4)..=Hertz::MHz(26),
160            // Source: Datasheet DS12536 Rev 2, Table 40
161            HSEClockMode::Bypass => Hertz::MHz(1)..=Hertz::MHz(50),
162        };
163        assert!(valid_range.contains(&freq));
164
165        HSEClock { freq, mode }
166    }
167}
168
169/// LSE clock mode.
170#[derive(Clone, Copy, Debug, PartialEq, Eq)]
171pub enum LSEClockMode {
172    /// Enable LSE oscillator to use external crystal or ceramic resonator.
173    Oscillator,
174    /// Bypass LSE oscillator to use external clock source.
175    /// Use this if an external oscillator is used which is not connected to `OSC32_IN` such as a MEMS resonator.
176    Bypass,
177}
178
179/// LSE Clock.
180#[derive(Clone, Copy, Debug, PartialEq, Eq)]
181pub struct LSEClock {
182    /// Input frequency.
183    freq: Hertz,
184    /// Mode.
185    mode: LSEClockMode,
186}
187
188impl LSEClock {
189    /// Provide LSE frequency.
190    pub fn new(mode: LSEClockMode) -> Self {
191        // Sets the LSE clock source to 32.768 kHz.
192        LSEClock {
193            freq: 32_768.Hz(),
194            mode,
195        }
196    }
197}
198
199/// PLL P division factors.
200#[derive(Clone, Copy, Debug, PartialEq, Eq)]
201pub enum PLLP {
202    Div2 = 0b00,
203    Div4 = 0b01,
204    Div6 = 0b10,
205    Div8 = 0b11,
206}
207
208/// MCO prescaler
209///
210/// Value on reset: No division
211#[derive(Clone, Copy, Debug, PartialEq, Eq)]
212pub enum MCOPRE {
213    /// No division
214    Div1_no_div,
215    /// Division by 2
216    Div2,
217    /// Division by 3
218    Div3,
219    /// Division by 4
220    Div4,
221    /// Division by 5
222    Div5,
223}
224
225/// PLL48CLK clock source selection
226#[derive(Clone, Copy, Debug, PartialEq, Eq)]
227pub enum PLL48CLK {
228    /// 48 MHz clock from PLLQ is selected
229    Pllq,
230    /// 48 MHz clock from PLLSAI is selected
231    Pllsai,
232}
233
234/// PLLSAIP division factors.
235#[derive(Clone, Copy, Debug, PartialEq, Eq)]
236pub enum PLLSAIP {
237    Div2 = 0b00,
238    Div4 = 0b01,
239    Div6 = 0b10,
240    Div8 = 0b11,
241}
242
243/// Microcontroller clock output 1
244///
245/// Value on reset: HSI
246#[derive(Clone, Copy, Debug, PartialEq, Eq)]
247pub enum MCO1 {
248    /// HSI clock selected
249    Hsi,
250    /// LSE oscillator selected
251    Lse,
252    /// HSE oscillator clock selected
253    Hse,
254    /// PLL clock selected
255    Pll,
256}
257
258/// Microcontroller clock output 2
259///
260/// Value on reset: SYSCLK
261#[derive(Clone, Copy, Debug, PartialEq, Eq)]
262pub enum MCO2 {
263    /// System clock (SYSCLK) selected
264    Sysclk,
265    /// PLLI2S clock selected
266    Plli2s,
267    /// HSE oscillator clock selected
268    Hse,
269    /// PLL clock selected
270    Pll,
271}
272
273#[derive(Clone, Copy, Debug, PartialEq, Eq)]
274enum VOSscale {
275    PwrScale1,
276    PwrScale2,
277    PwrScale3,
278}
279
280impl Default for VOSscale {
281    fn default() -> Self {
282        VOSscale::PwrScale3
283    }
284}
285
286#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
287struct InternalRCCConfig {
288    hpre: u8,
289    ppre1: u8,
290    ppre2: u8,
291    flash_waitstates: u8,
292    overdrive: bool,
293    vos_scale: VOSscale,
294}
295
296#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
297struct FreqRequest {
298    p: Option<(u32, u32)>,
299    q: Option<(u32, u32)>,
300}
301
302/// Clock configuration register.
303#[derive(Debug, PartialEq, Eq)]
304pub struct CFGR {
305    hse: Option<HSEClock>,
306    hclk: Option<u32>,
307    sysclk: Option<u32>,
308    pclk1: Option<u32>,
309    pclk2: Option<u32>,
310    lse: Option<LSEClock>,
311    lsi: Option<Hertz>,
312    use_pll: bool,
313    pll48clk: Option<PLL48CLK>,
314    pllm: u8,
315    plln: u16,
316    pllp: PLLP,
317    pllq: u8,
318    use_pllsai: bool,
319    pllsain: u16,
320    pllsaip: PLLSAIP,
321    pllsaiq: u8,
322    use_plli2s: bool,
323    plli2sr: u8,
324    plli2sq: u8,
325    plli2sn: u16,
326    mco1: MCO1,
327    mco1pre: MCOPRE,
328    mco2: MCO2,
329    mco2pre: MCOPRE,
330}
331
332impl CFGR {
333    /// Configures the HSE oscillator.
334    pub fn hse(mut self, hse: HSEClock) -> Self {
335        self.hse = Some(hse);
336        self
337    }
338
339    /// Sets HCLK frequency.
340    ///
341    /// The HCLK is used for the AHB bus, core, memory and DMA.
342    ///
343    /// # Panics
344    ///
345    /// Panics if the frequency is larger than 216 MHz.
346    pub fn hclk(mut self, freq: Hertz) -> Self {
347        assert!(freq.raw() <= 216_000_000);
348
349        self.hclk = Some(freq.raw());
350        self
351    }
352
353    /// Sets the SYSCLK frequency.
354    ///
355    /// This sets the SYSCLK frequency and sets up the USB clock if defined.
356    /// The provided frequency must be between 12.5 Mhz and 216 Mhz.
357    /// 12.5 Mhz is the VCO minimum frequency and SYSCLK PLLP divider limitation.
358    /// If the ethernet peripheral is on, the user should set a frequency higher than 25 Mhz.
359    ///
360    /// # Panics
361    ///
362    /// Panics if the frequency is not between 12.5 MHz and 216 MHz.
363    pub fn sysclk(mut self, sysclk: Hertz) -> Self {
364        assert!((12_500_000..=216_000_000).contains(&sysclk.raw()));
365
366        self.sysclk = Some(sysclk.raw());
367        self
368    }
369
370    /// Sets the PCLK1 clock (APB1 clock).
371    ///
372    /// If this method isn't called the maximum allowed frequency is used for PCLK1.
373    ///
374    /// # Panics
375    ///
376    /// Panics if the frequency is not between 12.5 MHz and 54 MHz.
377    pub fn pclk1(mut self, freq: Hertz) -> Self {
378        assert!((12_500_000..=54_000_000).contains(&freq.raw()));
379
380        self.pclk1 = Some(freq.raw());
381        self
382    }
383
384    /// Sets PCLK2 clock (APB2 clock).
385    ///
386    /// If this method isn't called the maximum allowed frequency is used for PCLK2.
387    ///
388    /// # Panics
389    ///
390    /// Panics if the frequency is not between 12.5 MHz and 108 MHz.
391    pub fn pclk2(mut self, freq: Hertz) -> Self {
392        assert!((12_500_000..=108_000_000).contains(&freq.raw()));
393
394        self.pclk2 = Some(freq.raw());
395        self
396    }
397
398    /// Sets the LSE clock source to 32.768 kHz.
399    pub fn lse(mut self, lse: LSEClock) -> Self {
400        self.lse = Some(lse);
401        self
402    }
403
404    /// Sets the LSI clock source to 32 kHz.
405    ///
406    /// Be aware that the tolerance is up to ±47% (Min 17 kHz, Typ 32 kHz, Max 47 kHz).
407    pub fn lsi(mut self) -> Self {
408        self.lsi = Some(32.kHz());
409        self
410    }
411
412    /// Sets the SYSCLK clock source to the main PLL.
413    ///
414    /// Note: `sysclk` must be specified or `use_pll48clk` must be set to true, otherwise `use_pll` is reset to false.
415    pub fn use_pll(mut self) -> Self {
416        self.use_pll = true;
417        self
418    }
419
420    /// Sets the 48 MHz clock source.
421    pub fn use_pll48clk(mut self, pll48clk: PLL48CLK) -> Self {
422        self.pll48clk = Some(pll48clk);
423        self
424    }
425
426    /// Sets the common PLL division factor.
427    ///
428    /// # Panics
429    ///
430    /// Panics if the division factor isn't between 2 and 63.
431    pub fn pllm(mut self, pllm: u8) -> Self {
432        assert!((2..=63).contains(&pllm));
433        self.pllm = pllm;
434        self
435    }
436
437    /// Sets the PLL multiplication factor for the main PLL.
438    ///
439    /// # Panics
440    ///
441    /// Panics if the multiplication factor isn't between 50 and 432 (inclusive).
442    pub fn plln(mut self, plln: u16) -> Self {
443        assert!((50..=432).contains(&plln));
444        self.plln = plln;
445        self
446    }
447
448    /// Sets the PLL division factor for the main PLL.
449    pub fn pllp(mut self, pllp: PLLP) -> Self {
450        self.pllp = pllp;
451        self
452    }
453
454    /// Sets the PLL division factor for the 48 MHz clock.
455    /// # Panics
456    ///
457    /// Panics if the division factor isn't between 2 and 15 (inclusive).
458    pub fn pllq(mut self, pllq: u8) -> Self {
459        assert!((2..=15).contains(&pllq));
460        self.pllq = pllq;
461        self
462    }
463
464    /// Enables the PLLSAI clock source.
465    pub fn use_pllsai(mut self) -> Self {
466        self.use_pllsai = true;
467        self
468    }
469
470    /// Sets the PLLSAIN multiplication factor for PLLSAI.
471    ///
472    /// # Panics
473    ///
474    /// Panics if the multiplication factor isn't between 50 and 432.
475    pub fn pllsain(mut self, pllsain: u16) -> Self {
476        assert!((50..=432).contains(&pllsain));
477        self.pllsain = pllsain;
478        self
479    }
480
481    /// Sets the PLLSAIP division factor for PLLSAI.
482    pub fn pllsaip(mut self, pllsaip: PLLSAIP) -> Self {
483        self.pllsaip = pllsaip;
484        self
485    }
486
487    /// Sets the PLLSAIQ division factor for PLLSAIS.
488    ///
489    /// # Panics
490    ///
491    /// Panics if the division factor isn't between 2 and 15.
492    pub fn pllsaiq(mut self, pllsaiq: u8) -> Self {
493        assert!((2..=15).contains(&pllsaiq));
494        self.pllsaiq = pllsaiq;
495        self
496    }
497
498    /// Enables the PLLI2S clock source.
499    pub fn use_plli2s(mut self) -> Self {
500        self.use_plli2s = true;
501        self
502    }
503
504    /// Sets the PLLI2SN multiplication factor for PLLI2S.
505    ///
506    /// # Panics
507    ///
508    /// Panics if the multiplication factor isn't between 50 and 432.
509    pub fn plli2sn(mut self, plli2sn: u16) -> Self {
510        assert!((50..=432).contains(&plli2sn));
511        self.plli2sn = plli2sn;
512        self
513    }
514
515    /// Sets the PLLI2SQ division factor for PLLI2S.
516    ///
517    /// # Panics
518    ///
519    /// Panics if the division factor isn't between 2 and 15.
520    pub fn plli2sq(mut self, plli2sq: u8) -> Self {
521        assert!((2..=15).contains(&plli2sq));
522        self.plli2sq = plli2sq;
523        self
524    }
525
526    /// Sets the PLLI2SR division factor for PLLI2S.
527    ///
528    /// # Panics
529    ///
530    /// Panics if the division factor isn't between 2 and 7.
531    pub fn plli2sr(mut self, plli2sr: u8) -> Self {
532        assert!((2..=7).contains(&plli2sr));
533        self.plli2sr = plli2sr;
534        self
535    }
536
537    /// Sets the MCO1 source
538    pub fn mco1(mut self, mco1: MCO1) -> Self {
539        self.mco1 = mco1;
540        self
541    }
542
543    /// Sets the MCO1 division factors
544    pub fn mco1pre(mut self, mco1pre: MCOPRE) -> Self {
545        self.mco1pre = mco1pre;
546        self
547    }
548
549    /// Sets the MCO2 source
550    pub fn mco2(mut self, mco2: MCO2) -> Self {
551        self.mco2 = mco2;
552        self
553    }
554
555    /// Sets the MCO2 division factors
556    pub fn mco2pre(mut self, mco2pre: MCOPRE) -> Self {
557        self.mco2pre = mco2pre;
558        self
559    }
560
561    // We want to avoid dividing u64 values, because the Cortex-M7 CPU doesn't
562    // have hardware instructions for that, and the software divide that LLVM
563    // gives us is a relatively large amount of code.
564    //
565    // To do this, we operate in a fixed-point domain, and do a multiply by 1/x
566    // instead of dividing by x.  We can calculate those 1/x values in a u32, if
567    // the fixed-point decimal place is chosen to be close enough to the LSB.
568    //
569    // But we also need to be able to represent the largest numerator, so we
570    // need enough bits to the left of the virtual decimal point.
571    //
572    // All of the chunks of code that do this are structured like:
573    //
574    // base_clk * n / m / p
575    //
576    // and they all have the same base_clk and n ranges (n up to 432, base_clk
577    // up to 50MHz).  So base*plln can be as high as 216_000_000_000, and to
578    // represent that we need 38 bits.
579    //
580    // (We could use just 37 bits in one of these cases, if we take into account
581    // that high values of base_clk preclude using high values of n.  But the
582    // other case is checking the output, so we can't assume anything about the
583    // inputs there.)
584    //
585    // So use 26 bits on the right of the decimal place.
586    //
587    // Also note, we need to round the 1/x values, not truncate them.  So we
588    // shift left by one more bit, add one, and shift right by one.
589    const FIXED_POINT_LSHIFT: u32 = 31;
590    const FIXED_POINT_RSHIFT: u32 = 30;
591
592    // We also drop 4 bits from the base_clk so that it and the fractional part
593    // (above) can fit into 64 bits.  The max base_clk*n value needs 38 bits;
594    // shifting this out means it can fit into 34, with 30 (above) for the
595    // fractions.
596    const BASE_CLK_SHIFT: u32 = 4;
597
598    /// Output clock calculation
599    fn calculate_clocks(&self) -> (Clocks, InternalRCCConfig) {
600        let mut config = InternalRCCConfig::default();
601
602        let base_clk = u64::from(
603            match self.hse.as_ref() {
604                Some(hse) => hse.freq,
605                None => HSI_FREQUENCY,
606            }
607            .raw(),
608        ) >> Self::BASE_CLK_SHIFT;
609
610        let mut sysclk = base_clk << Self::BASE_CLK_SHIFT;
611
612        let mut pll48clk_valid = false;
613
614        if self.use_pll {
615            // These initial divisions have to operate on u32 values to avoid
616            // the software division.  Fortunately our 26 bit choice for the
617            // decimal place, and the fact that these are 1/N, means we can
618            // fit them into 26 bits, so a u32 is fine.
619            let one_over_m = ((1 << Self::FIXED_POINT_LSHIFT) / (self.pllm as u32) + 1) >> 1;
620            let one_over_p = ((1 << Self::FIXED_POINT_LSHIFT)
621                / match self.pllp {
622                    PLLP::Div2 => 2u32,
623                    PLLP::Div4 => 4u32,
624                    PLLP::Div6 => 6u32,
625                    PLLP::Div8 => 8u32,
626                }
627                + 1)
628                >> 1;
629            sysclk = (((base_clk as u64 * self.plln as u64 * one_over_m as u64)
630                >> Self::FIXED_POINT_RSHIFT)
631                * one_over_p as u64)
632                >> Self::FIXED_POINT_RSHIFT
633                << Self::BASE_CLK_SHIFT;
634        }
635
636        // Check if pll48clk is valid
637        if let Some(pll48clk) = self.pll48clk {
638            match pll48clk {
639                PLL48CLK::Pllq => {
640                    pll48clk_valid = {
641                        let one_over_m =
642                            ((1 << Self::FIXED_POINT_LSHIFT) / (self.pllm as u32) + 1) >> 1;
643                        let one_over_q =
644                            ((1 << Self::FIXED_POINT_LSHIFT) / (self.pllq as u32) + 1) >> 1;
645                        let pll48clk = (((base_clk as u64 * self.plln as u64 * one_over_m as u64)
646                            >> Self::FIXED_POINT_RSHIFT)
647                            * one_over_q as u64)
648                            >> Self::FIXED_POINT_RSHIFT
649                            << Self::BASE_CLK_SHIFT;
650                        (48_000_000 - 120_000..=48_000_000 + 120_000).contains(&pll48clk)
651                    }
652                }
653                PLL48CLK::Pllsai => {
654                    pll48clk_valid = {
655                        if self.use_pllsai {
656                            // base_clk * pllsain has the same range as above
657                            let one_over_m =
658                                ((1 << Self::FIXED_POINT_LSHIFT) / (self.pllm as u32) + 1) >> 1;
659                            let one_over_p = ((1 << Self::FIXED_POINT_LSHIFT)
660                                / match self.pllsaip {
661                                    PLLSAIP::Div2 => 2u32,
662                                    PLLSAIP::Div4 => 4u32,
663                                    PLLSAIP::Div6 => 6u32,
664                                    PLLSAIP::Div8 => 8u32,
665                                }
666                                + 1)
667                                >> 1;
668                            let pll48clk =
669                                (((base_clk as u64 * self.pllsain as u64 * one_over_m as u64)
670                                    >> Self::FIXED_POINT_RSHIFT)
671                                    * one_over_p as u64)
672                                    >> Self::FIXED_POINT_RSHIFT
673                                    << Self::BASE_CLK_SHIFT;
674                            (48_000_000 - 120_000..=48_000_000 + 120_000).contains(&pll48clk)
675                        } else {
676                            false
677                        }
678                    }
679                }
680            }
681        }
682
683        // SYSCLK, must be <= 216 Mhz. By default, HSI/HSE frequency is chosen
684        assert!(sysclk <= 216_000_000);
685        let sysclk = sysclk as u32;
686
687        // HCLK. By default, SYSCLK frequency is chosen. Because of the method
688        // of clock multiplication and division, even if `sysclk` is set to be
689        // the same as `hclk`, it can be slightly inferior to `sysclk` after
690        // pllm, pllp... calculations
691        let mut hclk: u32 = min(sysclk, self.hclk.unwrap_or(sysclk));
692
693        // Configure HPRE.
694        let hpre_val: f32 = (sysclk as f32 / hclk as f32).ceil();
695
696        // The real value of hpre is computed to be as near as possible to the
697        // desired value, this leads to a quantization error
698        let (hpre_val, hpre): (f32, u8) = match hpre_val as u32 {
699            0 => unreachable!(),
700            1 => (1.0, 0b000),
701            2 => (2.0, 0b1000),
702            3..=5 => (4.0, 0b1001),
703            6..=11 => (8.0, 0b1010),
704            12..=39 => (16.0, 0b1011),
705            40..=95 => (64.0, 0b1100),
706            96..=191 => (128.0, 0b1101),
707            192..=383 => (256.0, 0b1110),
708            _ => (512.0, 0b1111),
709        };
710        config.hpre = hpre;
711        // update hclk with the real value
712        hclk = (sysclk as f32 / hpre_val).floor() as u32;
713
714        // PCLK1 (APB1). Must be <= 54 Mhz. By default, min(hclk, 54Mhz) is
715        // chosen
716        // Add limits dependens on OD follows by DS Table 16.
717        let max_pclk1 = if sysclk <= 180_000_000 {
718            45_000_000
719        } else {
720            54_000_000
721        };
722        let mut pclk1: u32 = min(max_pclk1, self.pclk1.unwrap_or(hclk));
723        // PCLK2 (APB2). Must be <= 108 Mhz. By default, min(hclk, 108Mhz) is
724        // chosen
725        // Add limits dependens on OD follows by DS Table 16.
726        let max_pclk2 = if sysclk <= 180_000_000 {
727            90_000_000
728        } else {
729            108_000_000
730        };
731        let mut pclk2: u32 = min(max_pclk2, self.pclk2.unwrap_or(hclk));
732
733        // Configure PPRE1
734        let mut ppre1_val: u32 = (hclk as f32 / pclk1 as f32).ceil() as u32;
735        config.ppre1 = match ppre1_val {
736            0 => unreachable!(),
737            1 => {
738                ppre1_val = 1;
739                0b000
740            }
741            2 => {
742                ppre1_val = 2;
743                0b100
744            }
745            3..=6 => {
746                ppre1_val = 4;
747                0b101
748            }
749            7..=12 => {
750                ppre1_val = 8;
751                0b110
752            }
753            _ => {
754                ppre1_val = 16;
755                0b111
756            }
757        };
758        // update pclk1 with the real value
759        pclk1 = hclk / ppre1_val;
760
761        // Configure PPRE2
762        let mut ppre2_val: u32 = (hclk as f32 / pclk2 as f32).ceil() as u32;
763        config.ppre2 = match ppre2_val {
764            0 => unreachable!(),
765            1 => {
766                ppre2_val = 1;
767                0b000
768            }
769            2 => {
770                ppre2_val = 2;
771                0b100
772            }
773            3..=6 => {
774                ppre2_val = 4;
775                0b101
776            }
777            7..=12 => {
778                ppre2_val = 8;
779                0b110
780            }
781            _ => {
782                ppre2_val = 16;
783                0b111
784            }
785        };
786        // update pclk2 with the real value
787        pclk2 = hclk / ppre2_val;
788
789        // Assumes TIMPRE bit of RCC_DCKCFGR1 is reset (0)
790        let timclk1 = if ppre1_val == 1 { pclk1 } else { 2 * pclk1 };
791        let timclk2 = if ppre2_val == 1 { pclk2 } else { 2 * pclk2 };
792
793        // Adjust flash wait states
794        config.flash_waitstates = if sysclk <= 30_000_000 {
795            0b0000
796        } else if sysclk <= 60_000_000 {
797            0b0001
798        } else if sysclk <= 90_000_000 {
799            0b0010
800        } else if sysclk <= 120_000_000 {
801            0b0011
802        } else if sysclk <= 150_000_000 {
803            0b0100
804        } else if sysclk <= 180_000_000 {
805            0b0101
806        } else if sysclk <= 210_000_000 {
807            0b0110
808        } else {
809            0b0111
810        };
811        // Adjust power state and overdrive mode
812        // Configure follows by RM 4.1.4
813        // Values getted from DS Table 16. General operating conditions
814        config.vos_scale = if sysclk <= 144_000_000 {
815            VOSscale::PwrScale3
816        } else if sysclk <= 168_000_000 {
817            VOSscale::PwrScale2
818        } else {
819            VOSscale::PwrScale1
820        };
821        // For every frequency higher than 180 need to enable overdrive
822        // Follows by DS Table 16.
823        config.overdrive = sysclk > 180_000_000;
824
825        let clocks = Clocks {
826            hclk: hclk.Hz(),
827            pclk1: pclk1.Hz(),
828            pclk2: pclk2.Hz(),
829            sysclk: sysclk.Hz(),
830            timclk1: timclk1.Hz(),
831            timclk2: timclk2.Hz(),
832            pll48clk_valid,
833            hse: self.hse.map(|hse| hse.freq),
834            lse: self.lse.map(|lse| lse.freq),
835            lsi: self.lsi,
836        };
837
838        (clocks, config)
839    }
840
841    /// Calculate the PLL M, N, P and Q values from the provided clock and requested options.
842    fn calculate_mnpq(
843        f_pll_clock_input: u32,
844        freq_req: FreqRequest,
845    ) -> Option<(u32, u32, Option<u32>, Option<u32>)> {
846        let mut m = 2;
847        let mut n = 432;
848        let mut p = None;
849        let mut q = None;
850
851        if freq_req.p.is_none() && freq_req.q.is_none() {
852            return None;
853        }
854
855        loop {
856            if m > 63 {
857                return None;
858            }
859            let f_vco_input = f_pll_clock_input / m;
860            if f_vco_input < 1_000_000 {
861                return None;
862            }
863            if f_vco_input > 2_000_000 || n < 50 {
864                m += 1;
865                n = 432;
866                continue;
867            }
868            // See the comments around Self::FIXED_POINT_LSHIFT to see how this works.
869            let one_over_m = ((1 << Self::FIXED_POINT_LSHIFT) / (m as u32) + 1) >> 1;
870            let f_vco_clock = (((f_pll_clock_input as u64 >> Self::BASE_CLK_SHIFT)
871                * n as u64
872                * one_over_m as u64)
873                >> Self::FIXED_POINT_RSHIFT
874                << Self::BASE_CLK_SHIFT) as u32;
875            if f_vco_clock < 50_000_000 {
876                m += 1;
877                n = 432;
878                continue;
879            }
880            if f_vco_clock > 432_000_000 {
881                n -= 1;
882                continue;
883            }
884
885            if let Some((p_freq_min, p_freq_max)) = freq_req.p {
886                let mut div = None;
887                for div_p in &[2, 4, 6, 8] {
888                    let f_pll_clock_output = f_vco_clock / div_p;
889                    if f_pll_clock_output >= p_freq_min && f_pll_clock_output <= p_freq_max {
890                        div = Some(*div_p)
891                    }
892                }
893                if div.is_some() {
894                    p = div;
895                    if freq_req.q.is_none() {
896                        break;
897                    }
898                } else {
899                    n -= 1;
900                    continue;
901                }
902            }
903
904            if let Some((q_freq_min, q_freq_max)) = freq_req.q {
905                let mut div = None;
906                for div_q in 2..=15 {
907                    let f_usb_clock_output = f_vco_clock / div_q;
908                    if f_usb_clock_output >= q_freq_min && f_usb_clock_output <= q_freq_max {
909                        div = Some(div_q)
910                    }
911                }
912                if div.is_some() {
913                    q = div;
914                    break;
915                } else {
916                    n -= 1;
917                    continue;
918                }
919            }
920        }
921
922        Some((m, n, p, q))
923    }
924
925    fn pll_configure(&mut self) {
926        let base_clk = match self.hse.as_ref() {
927            Some(hse) => hse.freq,
928            None => HSI_FREQUENCY,
929        }
930        .raw()
931            >> Self::BASE_CLK_SHIFT;
932
933        let sysclk = if let Some(clk) = self.sysclk {
934            clk
935        } else {
936            base_clk << Self::BASE_CLK_SHIFT
937        };
938
939        let p = if base_clk << Self::BASE_CLK_SHIFT == sysclk {
940            None
941        } else {
942            Some((sysclk - 1, sysclk + 1))
943        };
944
945        let q = if let Some(PLL48CLK::Pllq) = self.pll48clk {
946            Some((48_000_000 - 120_000, 48_000_000 + 120_000))
947        } else {
948            None
949        };
950
951        if p.is_none() && q.is_none() {
952            // We don't need PLL
953            self.use_pll = false;
954            return;
955        }
956
957        // We check if (pllm, plln, pllp) allow to obtain the requested Sysclk,
958        // so that we don't have to calculate them
959        let one_over_m = ((1 << Self::FIXED_POINT_LSHIFT) / (self.pllm as u32) + 1) >> 1;
960        let one_over_p = ((1 << Self::FIXED_POINT_LSHIFT)
961            / match self.pllp {
962                PLLP::Div2 => 2u32,
963                PLLP::Div4 => 4u32,
964                PLLP::Div6 => 6u32,
965                PLLP::Div8 => 8u32,
966            }
967            + 1)
968            >> 1;
969        let p_ok = (sysclk as u64)
970            == (((base_clk as u64 * self.plln as u64 * one_over_m as u64)
971                >> Self::FIXED_POINT_RSHIFT)
972                * one_over_p as u64)
973                >> Self::FIXED_POINT_RSHIFT
974                << Self::BASE_CLK_SHIFT;
975        if p_ok && q.is_none() {
976            return;
977        }
978
979        if let Some((m, n, p, q)) =
980            CFGR::calculate_mnpq(base_clk << Self::BASE_CLK_SHIFT, FreqRequest { p, q })
981        {
982            self.pllm = m as u8;
983            self.plln = n as u16;
984            if let Some(p) = p {
985                self.use_pll = true;
986                self.pllp = match p {
987                    2 => PLLP::Div2,
988                    4 => PLLP::Div4,
989                    6 => PLLP::Div6,
990                    8 => PLLP::Div8,
991                    _ => unreachable!(),
992                };
993            }
994            if let Some(q) = q {
995                self.pllq = q as u8;
996            }
997        } else {
998            panic!("couldn't calculate {} from {}", sysclk, base_clk);
999        }
1000    }
1001
1002    /// Configures the default clock settings.
1003    ///
1004    /// Set SYSCLK as 216 Mhz and setup USB clock if defined.
1005    pub fn set_defaults(self) -> Self {
1006        self.sysclk(216.MHz())
1007    }
1008
1009    /// Configure the "mandatory" clocks (`sysclk`, `hclk`, `pclk1` and `pclk2')
1010    /// and return them via the `Clocks` struct.
1011    ///
1012    /// The user shouldn't call freeze more than once as the clocks parameters
1013    /// cannot be changed after the clocks have started.
1014    ///
1015    /// The implementation makes the following choice: HSI is always chosen over
1016    /// HSE except when HSE is provided. When HSE is provided, HSE is used
1017    /// wherever it is possible.
1018    pub fn freeze(mut self) -> Clocks {
1019        let flash = unsafe { &(*FLASH::ptr()) };
1020        let rcc = unsafe { &(*RCC::ptr()) };
1021        let pwr = unsafe { &(*PWR::ptr()) };
1022
1023        self.pll_configure();
1024
1025        let (clocks, config) = self.calculate_clocks();
1026
1027        // Switch to fail-safe clock settings.
1028        // This is useful when booting from a bootloader that alters clock tree configuration.
1029        // Turn on HSI
1030        rcc.cr.modify(|_, w| w.hsion().set_bit());
1031        while rcc.cr.read().hsirdy().bit_is_clear() {}
1032        // Switch to HSI
1033        rcc.cfgr.modify(|_, w| w.sw().hsi());
1034
1035        // Configure HSE if provided
1036        if self.hse.is_some() {
1037            // Configure the HSE mode
1038            match self.hse.as_ref().unwrap().mode {
1039                HSEClockMode::Bypass => rcc.cr.modify(|_, w| w.hsebyp().bypassed()),
1040                HSEClockMode::Oscillator => rcc.cr.modify(|_, w| w.hsebyp().not_bypassed()),
1041            }
1042            // Start HSE
1043            rcc.cr.modify(|_, w| w.hseon().on());
1044            while rcc.cr.read().hserdy().is_not_ready() {}
1045        }
1046
1047        // Enable sequence follows by RM 4.1.4 Entering Overdrive mode.
1048        if self.use_pll || self.pll48clk.is_some() {
1049            // Disable PLL
1050            // Since the main-PLL configuration parameters cannot be changed once PLL is enabled, it is
1051            // recommended to configure PLL before enabling it (selection of the HSI or HSE oscillator as
1052            // PLL clock source, and configuration of division factors M, N, P, and Q).
1053            rcc.cr.modify(|_, w| w.pllon().off());
1054
1055            rcc.pllcfgr.modify(|_, w| unsafe {
1056                w.pllm().bits(self.pllm);
1057                w.plln().bits(self.plln);
1058                w.pllp().bits(self.pllp as u8);
1059                w.pllq().bits(self.pllq);
1060                w.pllsrc().bit(self.hse.is_some())
1061            });
1062
1063            // Enable PWR domain and setup VOSscale and Overdrive options
1064            rcc.apb1enr.modify(|_, w| w.pwren().set_bit());
1065
1066            pwr.cr1.modify(|_, w| match config.vos_scale {
1067                VOSscale::PwrScale3 => w.vos().scale3(),
1068                VOSscale::PwrScale2 => w.vos().scale2(),
1069                VOSscale::PwrScale1 => w.vos().scale1(),
1070            });
1071
1072            // Enable PLL
1073            rcc.cr.modify(|_, w| w.pllon().on());
1074
1075            // Wait for PLL to stabilise
1076            while rcc.cr.read().pllrdy().is_not_ready() {}
1077
1078            //Over-drive
1079            if config.overdrive {
1080                // Entering Over-drive mode
1081                //enable the Over-drive mode
1082                pwr.cr1.modify(|_, w| w.oden().set_bit());
1083
1084                //wait for the ODRDY flag to be set
1085                while !pwr.csr1.read().odrdy().bit_is_set() {}
1086
1087                //switch the voltage regulator from Normal mode to Over-drive mode
1088                pwr.cr1.modify(|_, w| w.odswen().set_bit());
1089
1090                //Wait for the ODSWRDY flag in the PWR_CSR1 to be set.
1091                while !pwr.csr1.read().odswrdy().bit_is_set() {}
1092            }
1093        }
1094
1095        // Configure LSE if provided
1096        if self.lse.is_some() {
1097            // Configure the LSE mode
1098            match self.lse.as_ref().unwrap().mode {
1099                LSEClockMode::Bypass => rcc.bdcr.modify(|_, w| w.lsebyp().bypassed()),
1100                LSEClockMode::Oscillator => rcc.bdcr.modify(|_, w| w.lsebyp().not_bypassed()),
1101            }
1102            // Enable the LSE.
1103            rcc.bdcr.modify(|_, w| w.lseon().on());
1104            while rcc.bdcr.read().lserdy().is_not_ready() {}
1105        }
1106
1107        if self.lsi.is_some() {
1108            rcc.csr.modify(|_, w| w.lsion().on());
1109            while rcc.csr.read().lsirdy().is_not_ready() {}
1110        }
1111
1112        if self.use_pllsai {
1113            let pllsain_freq = match self.hse.as_ref() {
1114                Some(hse) => hse.freq.raw() as u64 / self.pllm as u64 * self.pllsain as u64,
1115                None => 16_000_000 / self.pllm as u64 * self.pllsain as u64,
1116            };
1117            let pllsaip_freq = pllsain_freq
1118                / match self.pllsaip {
1119                    PLLSAIP::Div2 => 2,
1120                    PLLSAIP::Div4 => 4,
1121                    PLLSAIP::Div6 => 6,
1122                    PLLSAIP::Div8 => 8,
1123                };
1124            // let pllsaiq_freq = pllsain_freq / self.pllsaiq as u64;
1125
1126            // The reference manual (RM0410 Rev 4, Page 212), says the following
1127            // "Caution: The software has to set these bits correctly to ensure that the VCO output frequency is between 100 and 432 MHz.",
1128            // but STM32CubeMX states 192 MHz as the minimum. SSo the stricter requirement was chosen.
1129            assert!((192_000_000..=432_000_000).contains(&pllsain_freq));
1130            assert!(pllsaip_freq <= 48_000_000);
1131
1132            rcc.pllsaicfgr.modify(|_, w| unsafe {
1133                w.pllsain().bits(self.pllsain);
1134                w.pllsaip().bits(self.pllsaip as u8);
1135                w.pllsaiq().bits(self.pllsaiq)
1136            });
1137            rcc.cr.modify(|_, w| w.pllsaion().on());
1138        }
1139
1140        if let Some(pll48clk) = self.pll48clk {
1141            match pll48clk {
1142                PLL48CLK::Pllq => rcc.dckcfgr2.modify(|_, w| w.ck48msel().bit(false)),
1143                PLL48CLK::Pllsai => rcc.dckcfgr2.modify(|_, w| w.ck48msel().bit(true)),
1144            }
1145        }
1146
1147        if self.use_plli2s {
1148            let plli2sn_freq = match self.hse.as_ref() {
1149                Some(hse) => hse.freq.raw() as u64 / self.pllm as u64 * self.plli2sn as u64,
1150                None => 16_000_000 / self.pllm as u64 * self.plli2sn as u64,
1151            };
1152            let plli2sr_freq = plli2sn_freq / self.plli2sr as u64;
1153            let plli2sq_freq = plli2sn_freq / self.plli2sq as u64;
1154
1155            assert!((192_000_000..=432_000_000).contains(&plli2sn_freq));
1156            assert!(plli2sr_freq <= 216_000_000);
1157            assert!(plli2sq_freq <= 216_000_000);
1158
1159            rcc.plli2scfgr.modify(|_, w| unsafe {
1160                w.plli2sn().bits(self.plli2sn);
1161                w.plli2sr().bits(self.plli2sr);
1162                w.plli2sq().bits(self.plli2sq)
1163            });
1164            rcc.cr.modify(|_, w| w.plli2son().on());
1165        }
1166
1167        rcc.cfgr.modify(|_, w| {
1168            w.mco1()
1169                .variant(self.mco1.into())
1170                .mco1pre()
1171                .variant(self.mco1pre.into());
1172            w.mco2()
1173                .variant(self.mco2.into())
1174                .mco2pre()
1175                .variant(self.mco2pre.into())
1176        });
1177
1178        flash
1179            .acr
1180            .write(|w| w.latency().bits(config.flash_waitstates));
1181
1182        // Configure HCLK, PCLK1, PCLK2
1183        rcc.cfgr.modify(|_, w| unsafe {
1184            w.ppre1()
1185                .bits(config.ppre1)
1186                .ppre2()
1187                .bits(config.ppre2)
1188                .hpre()
1189                .bits(config.hpre)
1190        });
1191
1192        // Select SYSCLK source
1193        if self.use_pll {
1194            rcc.cfgr.modify(|_, w| w.sw().pll());
1195            while !rcc.cfgr.read().sws().is_pll() {}
1196        } else if self.hse.is_some() {
1197            rcc.cfgr.modify(|_, w| w.sw().hse());
1198            while !rcc.cfgr.read().sws().is_hse() {}
1199        } else {
1200            rcc.cfgr.modify(|_, w| w.sw().hsi());
1201            while !rcc.cfgr.read().sws().is_hsi() {}
1202        }
1203
1204        // As requested by user manual we need to wait 16 ticks before the right
1205        // predivision is applied
1206        cortex_m::asm::delay(16);
1207
1208        clocks
1209    }
1210}
1211
1212/// Frozen clock frequencies
1213///
1214/// The existence of this value indicates that the clock configuration can no longer be changed
1215#[derive(Clone, Copy, Debug)]
1216pub struct Clocks {
1217    hclk: Hertz,
1218    pclk1: Hertz,
1219    pclk2: Hertz,
1220    sysclk: Hertz,
1221    timclk1: Hertz,
1222    timclk2: Hertz,
1223    pll48clk_valid: bool,
1224    hse: Option<Hertz>,
1225    lse: Option<Hertz>,
1226    lsi: Option<Hertz>,
1227}
1228
1229impl Clocks {
1230    /// Returns the frequency of the AHB1
1231    pub fn hclk(&self) -> Hertz {
1232        self.hclk
1233    }
1234
1235    /// Returns the frequency of the APB1
1236    pub fn pclk1(&self) -> Hertz {
1237        self.pclk1
1238    }
1239
1240    /// Returns the frequency of the APB2
1241    pub fn pclk2(&self) -> Hertz {
1242        self.pclk2
1243    }
1244
1245    /// Returns the system (core) frequency
1246    pub fn sysclk(&self) -> Hertz {
1247        self.sysclk
1248    }
1249
1250    /// Returns the frequency for timers on APB1
1251    pub fn timclk1(&self) -> Hertz {
1252        self.timclk1
1253    }
1254
1255    /// Returns the frequency for timers on APB1
1256    pub fn timclk2(&self) -> Hertz {
1257        self.timclk2
1258    }
1259
1260    /// Returns true if the PLL48 clock is within USB
1261    /// specifications. It is required to use the USB functionality.
1262    pub fn is_pll48clk_valid(&self) -> bool {
1263        // USB specification allow +-0.25%
1264        self.pll48clk_valid
1265    }
1266
1267    /// Returns the frequency of the `HSE` if `Some`, else `None`.
1268    pub fn hse(&self) -> Option<Hertz> {
1269        self.hse
1270    }
1271
1272    /// Returns the frequency of the `LSE` if `Some`, else `None`.
1273    pub fn lse(&self) -> Option<Hertz> {
1274        self.lse
1275    }
1276
1277    /// Returns the frequency of the `LSI` if `Some`, else `None`.
1278    pub fn lsi(&self) -> Option<Hertz> {
1279        self.lsi
1280    }
1281}
1282
1283/// Frequency on bus that peripheral is connected in
1284pub trait BusClock {
1285    /// Calculates frequency depending on `Clock` state
1286    fn clock(clocks: &Clocks) -> Hertz;
1287}
1288
1289/// Frequency on bus that timer is connected in
1290pub trait BusTimerClock {
1291    /// Calculates base frequency of timer depending on `Clock` state
1292    fn timer_clock(clocks: &Clocks) -> Hertz;
1293}
1294
1295impl<T> BusClock for T
1296where
1297    T: RccBus,
1298    T::Bus: BusClock,
1299{
1300    fn clock(clocks: &Clocks) -> Hertz {
1301        T::Bus::clock(clocks)
1302    }
1303}
1304
1305impl<T> BusTimerClock for T
1306where
1307    T: RccBus,
1308    T::Bus: BusTimerClock,
1309{
1310    fn timer_clock(clocks: &Clocks) -> Hertz {
1311        T::Bus::timer_clock(clocks)
1312    }
1313}
1314
1315impl BusClock for AHB1 {
1316    fn clock(clocks: &Clocks) -> Hertz {
1317        clocks.hclk
1318    }
1319}
1320
1321impl BusClock for AHB2 {
1322    fn clock(clocks: &Clocks) -> Hertz {
1323        clocks.hclk
1324    }
1325}
1326
1327impl BusClock for AHB3 {
1328    fn clock(clocks: &Clocks) -> Hertz {
1329        clocks.hclk
1330    }
1331}
1332
1333impl BusClock for APB1 {
1334    fn clock(clocks: &Clocks) -> Hertz {
1335        clocks.pclk1
1336    }
1337}
1338
1339impl BusClock for APB2 {
1340    fn clock(clocks: &Clocks) -> Hertz {
1341        clocks.pclk2
1342    }
1343}
1344
1345impl BusTimerClock for APB1 {
1346    fn timer_clock(clocks: &Clocks) -> Hertz {
1347        clocks.timclk1
1348    }
1349}
1350
1351impl BusTimerClock for APB2 {
1352    fn timer_clock(clocks: &Clocks) -> Hertz {
1353        clocks.timclk2
1354    }
1355}
1356
1357impl From<MCO1> for crate::pac::rcc::cfgr::MCO1_A {
1358    fn from(input: MCO1) -> Self {
1359        match input {
1360            MCO1::Hsi => Self::Hsi,
1361            MCO1::Lse => Self::Lse,
1362            MCO1::Hse => Self::Hse,
1363            MCO1::Pll => Self::Pll,
1364        }
1365    }
1366}
1367
1368impl From<MCO2> for crate::pac::rcc::cfgr::MCO2_A {
1369    fn from(input: MCO2) -> Self {
1370        match input {
1371            MCO2::Sysclk => Self::Sysclk,
1372            MCO2::Plli2s => Self::Plli2s,
1373            MCO2::Hse => Self::Hse,
1374            MCO2::Pll => Self::Pll,
1375        }
1376    }
1377}
1378
1379impl From<MCOPRE> for crate::pac::rcc::cfgr::MCO2PRE_A {
1380    fn from(input: MCOPRE) -> Self {
1381        match input {
1382            MCOPRE::Div1_no_div => Self::Div1,
1383            MCOPRE::Div2 => Self::Div2,
1384            MCOPRE::Div3 => Self::Div3,
1385            MCOPRE::Div4 => Self::Div4,
1386            MCOPRE::Div5 => Self::Div5,
1387        }
1388    }
1389}
1390
1391/// Bus associated to peripheral
1392pub trait RccBus: crate::Sealed {
1393    /// Bus type;
1394    type Bus;
1395}
1396
1397/// Enable/disable peripheral
1398pub trait Enable: RccBus {
1399    /// Enables peripheral
1400    fn enable(bus: &mut Self::Bus);
1401
1402    /// Disables peripheral
1403    fn disable(bus: &mut Self::Bus);
1404
1405    /// Check if peripheral enabled
1406    fn is_enabled() -> bool;
1407
1408    /// Check if peripheral disabled
1409    fn is_disabled() -> bool;
1410
1411    /// # Safety
1412    ///
1413    /// Enables peripheral. Takes access to RCC internally
1414    unsafe fn enable_unchecked();
1415
1416    /// # Safety
1417    ///
1418    /// Disables peripheral. Takes access to RCC internally
1419    unsafe fn disable_unchecked();
1420}
1421
1422/// Enable/disable peripheral in low power mode
1423pub trait LPEnable: RccBus {
1424    /// Enables peripheral
1425    fn low_power_enable(bus: &mut Self::Bus);
1426
1427    /// Disables peripheral
1428    fn low_power_disable(bus: &mut Self::Bus);
1429
1430    /// Check if peripheral enabled
1431    fn is_low_power_enabled() -> bool;
1432
1433    /// Check if peripheral disabled
1434    fn is_low_power_disabled() -> bool;
1435
1436    /// # Safety
1437    ///
1438    /// Enables peripheral. Takes access to RCC internally
1439    unsafe fn low_power_enable_unchecked();
1440
1441    /// # Safety
1442    ///
1443    /// Disables peripheral. Takes access to RCC internally
1444    unsafe fn low_power_disable_unchecked();
1445}
1446
1447/// Reset peripheral
1448pub trait Reset: RccBus {
1449    /// Resets peripheral
1450    fn reset(bus: &mut Self::Bus);
1451
1452    /// # Safety
1453    ///
1454    /// Resets peripheral. Takes access to RCC internally
1455    unsafe fn reset_unchecked();
1456}
1457
1458#[cfg(test)]
1459mod tests {
1460    use fugit::{HertzU32 as Hertz, RateExtU32};
1461
1462    use super::{FreqRequest, CFGR};
1463
1464    fn build_request(sysclk: u32, use_pll48clk: bool) -> FreqRequest {
1465        let p = Some((sysclk - 1, sysclk + 1));
1466        let q = if use_pll48clk {
1467            Some((48_000_000 - 120_000, 48_000_000 + 120_000))
1468        } else {
1469            None
1470        };
1471        FreqRequest { p, q }
1472    }
1473
1474    fn check(hse: u32, sysclk: u32, use_pll48clk: bool) {
1475        let request = build_request(sysclk, use_pll48clk);
1476        let (m, n, p, q) =
1477            CFGR::calculate_mnpq(hse, request).expect("Can't calculate PLL parameters");
1478
1479        let pll_in = hse;
1480
1481        if m < 2 || m > 63 {
1482            panic!("Invalid PLL M value: {}", m);
1483        }
1484
1485        let vco_in = pll_in / m;
1486        if vco_in < 1_000_000 || vco_in > 2_000_000 {
1487            panic!("Invalid VCO input frequency: {}", vco_in);
1488        }
1489
1490        if n < 50 || n > 432 {
1491            panic!("Invalid PLL N value: {}", n);
1492        }
1493
1494        let vco = ((pll_in as u64) * (n as u64) / (m as u64)) as u32;
1495        if vco < 100_000_000 || vco > 432_000_000 {
1496            panic!("Invalid VCO frequency: {}", vco);
1497        }
1498
1499        let p = p.expect("PLL P value should be defined!");
1500        if [2, 4, 6, 8].iter().find(|v| **v == p).is_none() {
1501            panic!("Invalid PLL P value: {}", p);
1502        }
1503
1504        let p_freq = vco / p;
1505        if p_freq > 216_000_000 {
1506            panic!("Invalid PLL P frequency: {}", p_freq);
1507        }
1508        if p_freq < (sysclk - 1) || p_freq > (sysclk + 1) {
1509            panic!(
1510                "Invalid PLL P frequency: {} (requested sysclk {})",
1511                p_freq, sysclk
1512            );
1513        }
1514
1515        if use_pll48clk && q.is_none() {
1516            panic!("PLL Q value should be defined!");
1517        }
1518        if let Some(q) = q {
1519            if q < 2 || q > 15 {
1520                panic!("Invalid PLL Q value: {}", q);
1521            }
1522            if use_pll48clk {
1523                let q_freq = vco / q;
1524                if q_freq < (48_000_000 - 120_000) || q_freq > (48_000_000 + 120_000) {
1525                    panic!("Invalid PLL Q frequency: {}", q_freq);
1526                }
1527            }
1528        }
1529    }
1530
1531    #[test]
1532    fn test_pll_calc1() {
1533        check(25_000_000, 48_000_000, false);
1534    }
1535
1536    #[test]
1537    fn test_pll_calc1_usb() {
1538        check(25_000_000, 48_000_000, true);
1539    }
1540
1541    #[test]
1542    fn test_pll_calc2() {
1543        check(12_000_000, 48_000_000, false);
1544    }
1545
1546    #[test]
1547    fn test_pll_calc2_usb() {
1548        check(12_000_000, 48_000_000, true);
1549    }
1550
1551    #[test]
1552    fn test_pll_calc3() {
1553        check(12_000_000, 216_000_000, false);
1554    }
1555
1556    #[test]
1557    fn test_pll_calc3_usb() {
1558        check(12_000_000, 216_000_000, true);
1559    }
1560
1561    #[test]
1562    fn test_rcc_calc1() {
1563        use super::{HSEClock, HSEClockMode, MCO1, MCO2, MCOPRE, PLL48CLK, PLLP, PLLSAIP};
1564
1565        let cfgr = CFGR {
1566            hse: None,
1567            hclk: None,
1568            sysclk: None,
1569            pclk1: None,
1570            pclk2: None,
1571            lse: None,
1572            lsi: None,
1573            use_pll: false,
1574            pll48clk: None,
1575            pllm: 2,
1576            plln: 50,
1577            pllp: PLLP::Div2,
1578            pllq: 2,
1579            use_pllsai: false,
1580            pllsain: 192,
1581            pllsaip: PLLSAIP::Div2,
1582            pllsaiq: 2,
1583            use_plli2s: false,
1584            plli2sr: 2,
1585            plli2sq: 2,
1586            plli2sn: 192,
1587            mco1: MCO1::Hsi,
1588            mco1pre: MCOPRE::Div1_no_div,
1589            mco2: MCO2::Sysclk,
1590            mco2pre: MCOPRE::Div1_no_div,
1591        };
1592
1593        let mut cfgr = cfgr
1594            .hse(HSEClock::new(25.MHz(), HSEClockMode::Bypass))
1595            .use_pll()
1596            .use_pll48clk(PLL48CLK::Pllq)
1597            .sysclk(216.MHz());
1598        cfgr.pll_configure();
1599
1600        assert_eq!(cfgr.hse.unwrap().freq, Hertz::MHz(25));
1601
1602        let (clocks, _config) = cfgr.calculate_clocks();
1603        assert_eq!(clocks.sysclk().raw(), 216_000_000);
1604        assert!(clocks.is_pll48clk_valid());
1605    }
1606
1607    #[test]
1608    fn test_rcc_calc2() {
1609        use super::{HSEClock, HSEClockMode, MCO1, MCO2, MCOPRE, PLL48CLK, PLLP, PLLSAIP};
1610
1611        let cfgr = CFGR {
1612            hse: None,
1613            hclk: None,
1614            sysclk: None,
1615            pclk1: None,
1616            pclk2: None,
1617            lse: None,
1618            lsi: None,
1619            use_pll: false,
1620            pll48clk: None,
1621            pllm: 2,
1622            plln: 50,
1623            pllp: PLLP::Div2,
1624            pllq: 2,
1625            use_pllsai: false,
1626            pllsain: 192,
1627            pllsaip: PLLSAIP::Div2,
1628            pllsaiq: 2,
1629            use_plli2s: false,
1630            plli2sr: 2,
1631            plli2sq: 2,
1632            plli2sn: 192,
1633            mco1: MCO1::Hsi,
1634            mco1pre: MCOPRE::Div1_no_div,
1635            mco2: MCO2::Sysclk,
1636            mco2pre: MCOPRE::Div1_no_div,
1637        };
1638
1639        let mut cfgr = cfgr
1640            .hse(HSEClock::new(25.MHz(), HSEClockMode::Bypass))
1641            .use_pll48clk(PLL48CLK::Pllq)
1642            .sysclk(216.MHz());
1643        cfgr.pll_configure();
1644
1645        assert_eq!(cfgr.hse.unwrap().freq, Hertz::MHz(25));
1646
1647        let (clocks, _config) = cfgr.calculate_clocks();
1648        assert_eq!(clocks.sysclk().raw(), 216_000_000);
1649        assert!(clocks.is_pll48clk_valid());
1650    }
1651
1652    #[test]
1653    fn test_rcc_calc3() {
1654        use super::{HSEClock, HSEClockMode, MCO1, MCO2, MCOPRE, PLL48CLK, PLLP, PLLSAIP};
1655
1656        let cfgr = CFGR {
1657            hse: None,
1658            hclk: None,
1659            sysclk: None,
1660            pclk1: None,
1661            pclk2: None,
1662            lse: None,
1663            lsi: None,
1664            use_pll: false,
1665            pll48clk: None,
1666            pllm: 2,
1667            plln: 50,
1668            pllp: PLLP::Div2,
1669            pllq: 2,
1670            use_pllsai: false,
1671            pllsain: 192,
1672            pllsaip: PLLSAIP::Div2,
1673            pllsaiq: 2,
1674            use_plli2s: false,
1675            plli2sr: 2,
1676            plli2sq: 2,
1677            plli2sn: 192,
1678            mco1: MCO1::Hsi,
1679            mco1pre: MCOPRE::Div1_no_div,
1680            mco2: MCO2::Sysclk,
1681            mco2pre: MCOPRE::Div1_no_div,
1682        };
1683
1684        let mut cfgr = cfgr
1685            .hse(HSEClock::new(25.MHz(), HSEClockMode::Bypass))
1686            .use_pll48clk(PLL48CLK::Pllq)
1687            .set_defaults();
1688        cfgr.pll_configure();
1689
1690        assert_eq!(cfgr.hse.unwrap().freq, Hertz::MHz(25));
1691
1692        let (clocks, _config) = cfgr.calculate_clocks();
1693        assert_eq!(clocks.sysclk().raw(), 216_000_000);
1694        assert!(clocks.is_pll48clk_valid());
1695    }
1696
1697    #[test]
1698    fn test_rcc_default() {
1699        use super::{MCO1, MCO2, MCOPRE, PLLP, PLLSAIP};
1700
1701        let mut cfgr = CFGR {
1702            hse: None,
1703            hclk: None,
1704            sysclk: None,
1705            pclk1: None,
1706            pclk2: None,
1707            lse: None,
1708            lsi: None,
1709            use_pll: false,
1710            pll48clk: None,
1711            pllm: 2,
1712            plln: 50,
1713            pllp: PLLP::Div2,
1714            pllq: 2,
1715            use_pllsai: false,
1716            pllsain: 192,
1717            pllsaip: PLLSAIP::Div2,
1718            pllsaiq: 2,
1719            use_plli2s: false,
1720            plli2sr: 2,
1721            plli2sq: 2,
1722            plli2sn: 192,
1723            mco1: MCO1::Hsi,
1724            mco1pre: MCOPRE::Div1_no_div,
1725            mco2: MCO2::Sysclk,
1726            mco2pre: MCOPRE::Div1_no_div,
1727        };
1728
1729        cfgr.pll_configure();
1730        assert!(!cfgr.use_pll);
1731        let (clocks, _config) = cfgr.calculate_clocks();
1732        assert_eq!(clocks.sysclk().raw(), 16_000_000);
1733    }
1734}