embassy_stm32/rcc/
h.rs

1use core::ops::RangeInclusive;
2
3use crate::pac;
4pub use crate::pac::rcc::vals::{
5    Hsidiv as HSIPrescaler, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, Pllsrc as PllSource, Sw as Sysclk,
6};
7use crate::pac::rcc::vals::{Pllrge, Pllvcosel, Timpre};
8use crate::pac::{FLASH, PWR, RCC};
9use crate::time::Hertz;
10
11/// HSI speed
12pub const HSI_FREQ: Hertz = Hertz(64_000_000);
13
14/// CSI speed
15pub const CSI_FREQ: Hertz = Hertz(4_000_000);
16
17const VCO_RANGE: RangeInclusive<Hertz> = Hertz(150_000_000)..=Hertz(420_000_000);
18#[cfg(any(stm32h5, pwr_h7rm0455))]
19const VCO_WIDE_RANGE: RangeInclusive<Hertz> = Hertz(128_000_000)..=Hertz(560_000_000);
20#[cfg(pwr_h7rm0468)]
21const VCO_WIDE_RANGE: RangeInclusive<Hertz> = Hertz(192_000_000)..=Hertz(836_000_000);
22#[cfg(any(pwr_h7rm0399, pwr_h7rm0433))]
23const VCO_WIDE_RANGE: RangeInclusive<Hertz> = Hertz(192_000_000)..=Hertz(960_000_000);
24#[cfg(any(stm32h7rs))]
25const VCO_WIDE_RANGE: RangeInclusive<Hertz> = Hertz(384_000_000)..=Hertz(1672_000_000);
26
27pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler};
28
29#[cfg(any(stm32h5, stm32h7))]
30#[derive(Clone, Copy, Eq, PartialEq)]
31pub enum VoltageScale {
32    Scale0,
33    Scale1,
34    Scale2,
35    Scale3,
36}
37#[cfg(stm32h7rs)]
38pub use crate::pac::pwr::vals::Vos as VoltageScale;
39#[cfg(all(stm32h7rs, peri_usb_otg_hs))]
40pub use crate::pac::rcc::vals::{Usbphycsel, Usbrefcksel};
41
42#[derive(Clone, Copy, Eq, PartialEq)]
43pub enum HseMode {
44    /// crystal/ceramic oscillator (HSEBYP=0)
45    Oscillator,
46    /// external analog clock (low swing) (HSEBYP=1, HSEEXT=0)
47    Bypass,
48    /// external digital clock (full swing) (HSEBYP=1, HSEEXT=1)
49    #[cfg(any(rcc_h5, rcc_h50, rcc_h7rs))]
50    BypassDigital,
51}
52
53#[derive(Clone, Copy, Eq, PartialEq)]
54pub struct Hse {
55    /// HSE frequency.
56    pub freq: Hertz,
57    /// HSE mode.
58    pub mode: HseMode,
59}
60
61#[derive(Clone, Copy)]
62pub struct Pll {
63    /// Source clock selection.
64    pub source: PllSource,
65
66    /// PLL pre-divider (DIVM).
67    pub prediv: PllPreDiv,
68
69    /// PLL multiplication factor.
70    pub mul: PllMul,
71
72    /// PLL P division factor. If None, PLL P output is disabled.
73    /// On PLL1, it must be even for most series (in particular,
74    /// it cannot be 1 in series other than stm32h7, stm32h7rs23/733,
75    /// stm32h7, stm32h7rs25/735 and stm32h7, stm32h7rs30.)
76    pub divp: Option<PllDiv>,
77    /// PLL Q division factor. If None, PLL Q output is disabled.
78    pub divq: Option<PllDiv>,
79    /// PLL R division factor. If None, PLL R output is disabled.
80    pub divr: Option<PllDiv>,
81}
82
83fn apb_div_tim(apb: &APBPrescaler, clk: Hertz, tim: TimerPrescaler) -> Hertz {
84    match (tim, apb) {
85        (TimerPrescaler::DefaultX2, APBPrescaler::DIV1) => clk,
86        (TimerPrescaler::DefaultX2, APBPrescaler::DIV2) => clk,
87        (TimerPrescaler::DefaultX2, APBPrescaler::DIV4) => clk / 2u32,
88        (TimerPrescaler::DefaultX2, APBPrescaler::DIV8) => clk / 4u32,
89        (TimerPrescaler::DefaultX2, APBPrescaler::DIV16) => clk / 8u32,
90
91        (TimerPrescaler::DefaultX4, APBPrescaler::DIV1) => clk,
92        (TimerPrescaler::DefaultX4, APBPrescaler::DIV2) => clk,
93        (TimerPrescaler::DefaultX4, APBPrescaler::DIV4) => clk,
94        (TimerPrescaler::DefaultX4, APBPrescaler::DIV8) => clk / 2u32,
95        (TimerPrescaler::DefaultX4, APBPrescaler::DIV16) => clk / 4u32,
96
97        _ => unreachable!(),
98    }
99}
100
101/// Timer prescaler
102#[derive(Clone, Copy, Eq, PartialEq)]
103pub enum TimerPrescaler {
104    /// The timers kernel clock is equal to hclk if PPREx corresponds to a
105    /// division by 1 or 2, else it is equal to 2*pclk
106    DefaultX2,
107
108    /// The timers kernel clock is equal to hclk if PPREx corresponds to a
109    /// division by 1, 2 or 4, else it is equal to 4*pclk
110    DefaultX4,
111}
112
113impl From<TimerPrescaler> for Timpre {
114    fn from(value: TimerPrescaler) -> Self {
115        match value {
116            TimerPrescaler::DefaultX2 => Timpre::DEFAULT_X2,
117            TimerPrescaler::DefaultX4 => Timpre::DEFAULT_X4,
118        }
119    }
120}
121
122/// Power supply configuration
123/// See RM0433 Rev 4 7.4
124#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468, pwr_h7rs))]
125#[derive(Clone, Copy, PartialEq)]
126pub enum SupplyConfig {
127    /// Default power supply configuration.
128    /// V CORE Power Domains are supplied from the LDO according to VOS.
129    /// SMPS step-down converter enabled at 1.2V, may be used to supply the LDO.
130    Default,
131
132    /// Power supply configuration using the LDO.
133    /// V CORE Power Domains are supplied from the LDO according to VOS.
134    /// LDO power mode (Main, LP, Off) will follow system low-power modes.
135    /// SMPS step-down converter disabled.
136    LDO,
137
138    /// Power supply configuration directly from the SMPS step-down converter.
139    /// V CORE Power Domains are supplied from SMPS step-down converter according to VOS.
140    /// LDO bypassed.
141    /// SMPS step-down converter power mode (MR, LP, Off) will follow system low-power modes.
142    DirectSMPS,
143
144    /// Power supply configuration from the SMPS step-down converter, that supplies the LDO.
145    /// V CORE Power Domains are supplied from the LDO according to VOS
146    /// LDO power mode (Main, LP, Off) will follow system low-power modes.
147    /// SMPS step-down converter enabled according to SDLEVEL, and supplies the LDO.
148    /// SMPS step-down converter power mode (MR, LP, Off) will follow system low-power modes.
149    SMPSLDO(SMPSSupplyVoltage),
150
151    /// Power supply configuration from SMPS supplying external circuits and potentially the LDO.
152    /// V CORE Power Domains are supplied from voltage regulator according to VOS
153    /// LDO power mode (Main, LP, Off) will follow system low-power modes.
154    /// SMPS step-down converter enabled according to SDLEVEL used to supply external circuits and may supply the LDO.
155    /// SMPS step-down converter forced ON in MR mode.
156    SMPSExternalLDO(SMPSSupplyVoltage),
157
158    /// Power supply configuration from SMPS supplying external circuits and bypassing the LDO.
159    /// V CORE supplied from external source
160    /// SMPS step-down converter enabled according to SDLEVEL used to supply external circuits and may supply the external source for V CORE .
161    /// SMPS step-down converter forced ON in MR mode.
162    SMPSExternalLDOBypass(SMPSSupplyVoltage),
163
164    /// Power supply configuration from an external source, SMPS disabled and the LDO bypassed.
165    /// V CORE supplied from external source
166    /// SMPS step-down converter disabled and LDO bypassed, voltage monitoring still active.
167    SMPSDisabledLDOBypass,
168}
169
170/// SMPS step-down converter voltage output level.
171/// This is only used in certain power supply configurations:
172/// SMPSLDO, SMPSExternalLDO, SMPSExternalLDOBypass.
173#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468, pwr_h7rs))]
174#[derive(Clone, Copy, Eq, PartialEq, Debug)]
175pub enum SMPSSupplyVoltage {
176    /// 1.8v
177    V1_8,
178    /// 2.5v
179    #[cfg(not(pwr_h7rs))]
180    V2_5,
181}
182
183/// Configuration of the core clocks
184#[non_exhaustive]
185#[derive(Clone, Copy)]
186pub struct Config {
187    pub hsi: Option<HSIPrescaler>,
188    pub hse: Option<Hse>,
189    pub csi: bool,
190    pub hsi48: Option<super::Hsi48Config>,
191    pub sys: Sysclk,
192
193    pub pll1: Option<Pll>,
194    pub pll2: Option<Pll>,
195    #[cfg(any(rcc_h5, stm32h7, stm32h7rs))]
196    pub pll3: Option<Pll>,
197
198    #[cfg(any(stm32h7, stm32h7rs))]
199    pub d1c_pre: AHBPrescaler,
200    pub ahb_pre: AHBPrescaler,
201    pub apb1_pre: APBPrescaler,
202    pub apb2_pre: APBPrescaler,
203    #[cfg(not(stm32h7rs))]
204    pub apb3_pre: APBPrescaler,
205    #[cfg(any(stm32h7, stm32h7rs))]
206    pub apb4_pre: APBPrescaler,
207    #[cfg(stm32h7rs)]
208    pub apb5_pre: APBPrescaler,
209
210    pub timer_prescaler: TimerPrescaler,
211    pub voltage_scale: VoltageScale,
212    pub ls: super::LsConfig,
213
214    #[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468, pwr_h7rs))]
215    pub supply_config: SupplyConfig,
216
217    /// Per-peripheral kernel clock selection muxes
218    pub mux: super::mux::ClockMux,
219}
220
221impl Default for Config {
222    fn default() -> Self {
223        Self {
224            hsi: Some(HSIPrescaler::DIV1),
225            hse: None,
226            csi: false,
227            hsi48: Some(Default::default()),
228            sys: Sysclk::HSI,
229            pll1: None,
230            pll2: None,
231            #[cfg(any(rcc_h5, stm32h7, stm32h7rs))]
232            pll3: None,
233
234            #[cfg(any(stm32h7, stm32h7rs))]
235            d1c_pre: AHBPrescaler::DIV1,
236            ahb_pre: AHBPrescaler::DIV1,
237            apb1_pre: APBPrescaler::DIV1,
238            apb2_pre: APBPrescaler::DIV1,
239            #[cfg(not(stm32h7rs))]
240            apb3_pre: APBPrescaler::DIV1,
241            #[cfg(any(stm32h7, stm32h7rs))]
242            apb4_pre: APBPrescaler::DIV1,
243            #[cfg(stm32h7rs)]
244            apb5_pre: APBPrescaler::DIV1,
245
246            timer_prescaler: TimerPrescaler::DefaultX2,
247            #[cfg(not(rcc_h7rs))]
248            voltage_scale: VoltageScale::Scale0,
249            #[cfg(rcc_h7rs)]
250            voltage_scale: VoltageScale::HIGH,
251            ls: Default::default(),
252
253            #[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468, pwr_h7rs))]
254            supply_config: SupplyConfig::LDO,
255
256            mux: Default::default(),
257        }
258    }
259}
260
261pub(crate) unsafe fn init(config: Config) {
262    #[cfg(any(stm32h7))]
263    let pwr_reg = PWR.cr3();
264    #[cfg(any(stm32h7rs))]
265    let pwr_reg = PWR.csr2();
266
267    // NB. The lower bytes of CR3 can only be written once after
268    // POR, and must be written with a valid combination. Refer to
269    // RM0433 Rev 7 6.8.4. This is partially enforced by dropping
270    // `self` at the end of this method, but of course we cannot
271    // know what happened between the previous POR and here.
272    #[cfg(pwr_h7rm0433)]
273    pwr_reg.modify(|w| {
274        w.set_scuen(true);
275        w.set_ldoen(true);
276        w.set_bypass(false);
277    });
278
279    #[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468, pwr_h7rs))]
280    {
281        use pac::pwr::vals::Sdlevel;
282        match config.supply_config {
283            SupplyConfig::Default => {
284                pwr_reg.modify(|w| {
285                    w.set_sdlevel(Sdlevel::RESET);
286                    w.set_sdexthp(false);
287                    w.set_sden(true);
288                    w.set_ldoen(true);
289                    w.set_bypass(false);
290                });
291            }
292            SupplyConfig::LDO => {
293                pwr_reg.modify(|w| {
294                    w.set_sden(false);
295                    w.set_ldoen(true);
296                    w.set_bypass(false);
297                });
298            }
299            SupplyConfig::DirectSMPS => {
300                pwr_reg.modify(|w| {
301                    w.set_sdexthp(false);
302                    w.set_sden(true);
303                    w.set_ldoen(false);
304                    w.set_bypass(false);
305                });
306            }
307            SupplyConfig::SMPSLDO(sdlevel)
308            | SupplyConfig::SMPSExternalLDO(sdlevel)
309            | SupplyConfig::SMPSExternalLDOBypass(sdlevel) => {
310                let sdlevel = match sdlevel {
311                    SMPSSupplyVoltage::V1_8 => Sdlevel::V1_8,
312                    #[cfg(not(pwr_h7rs))]
313                    SMPSSupplyVoltage::V2_5 => Sdlevel::V2_5,
314                };
315                pwr_reg.modify(|w| {
316                    w.set_sdlevel(sdlevel);
317                    w.set_sdexthp(matches!(
318                        config.supply_config,
319                        SupplyConfig::SMPSExternalLDO(_) | SupplyConfig::SMPSExternalLDOBypass(_)
320                    ));
321                    w.set_sden(true);
322                    w.set_ldoen(matches!(
323                        config.supply_config,
324                        SupplyConfig::SMPSLDO(_) | SupplyConfig::SMPSExternalLDO(_)
325                    ));
326                    w.set_bypass(matches!(config.supply_config, SupplyConfig::SMPSExternalLDOBypass(_)));
327                });
328            }
329            SupplyConfig::SMPSDisabledLDOBypass => {
330                pwr_reg.modify(|w| {
331                    w.set_sden(false);
332                    w.set_ldoen(false);
333                    w.set_bypass(true);
334                });
335            }
336        }
337    }
338
339    // Validate the supply configuration. If you are stuck here, it is
340    // because the voltages on your board do not match those specified
341    // in the D3CR.VOS and CR3.SDLEVEL fields. By default after reset
342    // VOS = Scale 3, so check that the voltage on the VCAP pins =
343    // 1.0V.
344    #[cfg(any(stm32h7))]
345    while !PWR.csr1().read().actvosrdy() {}
346    #[cfg(any(stm32h7rs))]
347    while !PWR.sr1().read().actvosrdy() {}
348
349    // Configure voltage scale.
350    #[cfg(any(pwr_h5, pwr_h50))]
351    {
352        PWR.voscr().modify(|w| {
353            w.set_vos(match config.voltage_scale {
354                VoltageScale::Scale0 => crate::pac::pwr::vals::Vos::SCALE0,
355                VoltageScale::Scale1 => crate::pac::pwr::vals::Vos::SCALE1,
356                VoltageScale::Scale2 => crate::pac::pwr::vals::Vos::SCALE2,
357                VoltageScale::Scale3 => crate::pac::pwr::vals::Vos::SCALE3,
358            })
359        });
360        while !PWR.vossr().read().vosrdy() {}
361    }
362    #[cfg(syscfg_h7)]
363    {
364        // in chips without the overdrive bit, we can go from any scale to any scale directly.
365        PWR.d3cr().modify(|w| {
366            w.set_vos(match config.voltage_scale {
367                VoltageScale::Scale0 => crate::pac::pwr::vals::Vos::SCALE0,
368                VoltageScale::Scale1 => crate::pac::pwr::vals::Vos::SCALE1,
369                VoltageScale::Scale2 => crate::pac::pwr::vals::Vos::SCALE2,
370                VoltageScale::Scale3 => crate::pac::pwr::vals::Vos::SCALE3,
371            })
372        });
373        while !PWR.d3cr().read().vosrdy() {}
374    }
375    #[cfg(pwr_h7rs)]
376    {
377        PWR.csr4().modify(|w| w.set_vos(config.voltage_scale));
378        while !PWR.csr4().read().vosrdy() {}
379    }
380
381    #[cfg(syscfg_h7od)]
382    {
383        match config.voltage_scale {
384            VoltageScale::Scale0 => {
385                // to go to scale0, we must go to Scale1 first...
386                PWR.d3cr().modify(|w| w.set_vos(crate::pac::pwr::vals::Vos::SCALE1));
387                while !PWR.d3cr().read().vosrdy() {}
388
389                // Then enable overdrive.
390                critical_section::with(|_| pac::SYSCFG.pwrcr().modify(|w| w.set_oden(1)));
391                while !PWR.d3cr().read().vosrdy() {}
392            }
393            _ => {
394                // for all other scales, we can go directly.
395                PWR.d3cr().modify(|w| {
396                    w.set_vos(match config.voltage_scale {
397                        VoltageScale::Scale0 => unreachable!(),
398                        VoltageScale::Scale1 => crate::pac::pwr::vals::Vos::SCALE1,
399                        VoltageScale::Scale2 => crate::pac::pwr::vals::Vos::SCALE2,
400                        VoltageScale::Scale3 => crate::pac::pwr::vals::Vos::SCALE3,
401                    })
402                });
403                while !PWR.d3cr().read().vosrdy() {}
404            }
405        }
406    }
407
408    // Turn on the HSI
409    match config.hsi {
410        None => RCC.cr().modify(|w| w.set_hsion(true)),
411        Some(hsidiv) => RCC.cr().modify(|w| {
412            w.set_hsidiv(hsidiv);
413            w.set_hsion(true);
414        }),
415    }
416    while !RCC.cr().read().hsirdy() {}
417
418    // Use the HSI clock as system clock during the actual clock setup
419    RCC.cfgr().modify(|w| w.set_sw(Sysclk::HSI));
420    while RCC.cfgr().read().sws() != Sysclk::HSI {}
421
422    // Configure HSI
423    let hsi = match config.hsi {
424        None => None,
425        Some(hsidiv) => Some(HSI_FREQ / hsidiv),
426    };
427
428    // Configure HSE
429    let hse = match config.hse {
430        None => {
431            RCC.cr().modify(|w| w.set_hseon(false));
432            None
433        }
434        Some(hse) => {
435            RCC.cr().modify(|w| {
436                w.set_hsebyp(hse.mode != HseMode::Oscillator);
437                #[cfg(any(rcc_h5, rcc_h50, rcc_h7rs))]
438                w.set_hseext(match hse.mode {
439                    HseMode::Oscillator | HseMode::Bypass => pac::rcc::vals::Hseext::ANALOG,
440                    HseMode::BypassDigital => pac::rcc::vals::Hseext::DIGITAL,
441                });
442            });
443            RCC.cr().modify(|w| w.set_hseon(true));
444            while !RCC.cr().read().hserdy() {}
445            Some(hse.freq)
446        }
447    };
448
449    // Configure HSI48.
450    let hsi48 = config.hsi48.map(super::init_hsi48);
451
452    // Configure CSI.
453    RCC.cr().modify(|w| w.set_csion(config.csi));
454    let csi = match config.csi {
455        false => None,
456        true => {
457            while !RCC.cr().read().csirdy() {}
458            Some(CSI_FREQ)
459        }
460    };
461
462    // H7 has shared PLLSRC, check it's equal in all PLLs.
463    #[cfg(any(stm32h7, stm32h7rs))]
464    {
465        let plls = [&config.pll1, &config.pll2, &config.pll3];
466        if !super::util::all_equal(plls.into_iter().flatten().map(|p| p.source)) {
467            panic!("Source must be equal across all enabled PLLs.")
468        };
469    }
470
471    // Configure PLLs.
472    let pll_input = PllInput { csi, hse, hsi };
473    let pll1 = init_pll(0, config.pll1, &pll_input);
474    let pll2 = init_pll(1, config.pll2, &pll_input);
475    #[cfg(any(rcc_h5, stm32h7, stm32h7rs))]
476    let pll3 = init_pll(2, config.pll3, &pll_input);
477
478    // Configure sysclk
479    let sys = match config.sys {
480        Sysclk::HSI => unwrap!(hsi),
481        Sysclk::HSE => unwrap!(hse),
482        Sysclk::CSI => unwrap!(csi),
483        Sysclk::PLL1_P => unwrap!(pll1.p),
484        _ => unreachable!(),
485    };
486
487    // Check limits.
488    #[cfg(stm32h5)]
489    let (hclk_max, pclk_max) = match config.voltage_scale {
490        VoltageScale::Scale0 => (Hertz(250_000_000), Hertz(250_000_000)),
491        VoltageScale::Scale1 => (Hertz(200_000_000), Hertz(200_000_000)),
492        VoltageScale::Scale2 => (Hertz(150_000_000), Hertz(150_000_000)),
493        VoltageScale::Scale3 => (Hertz(100_000_000), Hertz(100_000_000)),
494    };
495    #[cfg(pwr_h7rm0455)]
496    let (d1cpre_clk_max, hclk_max, pclk_max) = match config.voltage_scale {
497        VoltageScale::Scale0 => (Hertz(280_000_000), Hertz(280_000_000), Hertz(140_000_000)),
498        VoltageScale::Scale1 => (Hertz(225_000_000), Hertz(225_000_000), Hertz(112_500_000)),
499        VoltageScale::Scale2 => (Hertz(160_000_000), Hertz(160_000_000), Hertz(80_000_000)),
500        VoltageScale::Scale3 => (Hertz(88_000_000), Hertz(88_000_000), Hertz(44_000_000)),
501    };
502    #[cfg(pwr_h7rm0468)]
503    let (d1cpre_clk_max, hclk_max, pclk_max) = match config.voltage_scale {
504        VoltageScale::Scale0 => {
505            let d1cpre_clk_max = if pac::SYSCFG.ur18().read().cpu_freq_boost() {
506                550_000_000
507            } else {
508                520_000_000
509            };
510            (Hertz(d1cpre_clk_max), Hertz(275_000_000), Hertz(137_500_000))
511        }
512        VoltageScale::Scale1 => (Hertz(400_000_000), Hertz(200_000_000), Hertz(100_000_000)),
513        VoltageScale::Scale2 => (Hertz(300_000_000), Hertz(150_000_000), Hertz(75_000_000)),
514        VoltageScale::Scale3 => (Hertz(170_000_000), Hertz(85_000_000), Hertz(42_500_000)),
515    };
516    #[cfg(all(stm32h7, not(any(pwr_h7rm0455, pwr_h7rm0468))))]
517    let (d1cpre_clk_max, hclk_max, pclk_max) = match config.voltage_scale {
518        VoltageScale::Scale0 => (Hertz(480_000_000), Hertz(240_000_000), Hertz(120_000_000)),
519        VoltageScale::Scale1 => (Hertz(400_000_000), Hertz(200_000_000), Hertz(100_000_000)),
520        VoltageScale::Scale2 => (Hertz(300_000_000), Hertz(150_000_000), Hertz(75_000_000)),
521        VoltageScale::Scale3 => (Hertz(200_000_000), Hertz(100_000_000), Hertz(50_000_000)),
522    };
523    #[cfg(stm32h7rs)]
524    let (d1cpre_clk_max, hclk_max, pclk_max) = match config.voltage_scale {
525        VoltageScale::HIGH => (Hertz(600_000_000), Hertz(300_000_000), Hertz(150_000_000)),
526        VoltageScale::LOW => (Hertz(400_000_000), Hertz(200_000_000), Hertz(100_000_000)),
527    };
528
529    #[cfg(any(stm32h7, stm32h7rs))]
530    let hclk = {
531        let d1cpre_clk = sys / config.d1c_pre;
532        assert!(d1cpre_clk <= d1cpre_clk_max);
533        sys / config.ahb_pre
534    };
535    #[cfg(stm32h5)]
536    let hclk = sys / config.ahb_pre;
537    assert!(hclk <= hclk_max);
538
539    let apb1 = hclk / config.apb1_pre;
540    let apb1_tim = apb_div_tim(&config.apb1_pre, hclk, config.timer_prescaler);
541    assert!(apb1 <= pclk_max);
542    let apb2 = hclk / config.apb2_pre;
543    let apb2_tim = apb_div_tim(&config.apb2_pre, hclk, config.timer_prescaler);
544    assert!(apb2 <= pclk_max);
545    #[cfg(not(stm32h7rs))]
546    let apb3 = hclk / config.apb3_pre;
547    #[cfg(not(stm32h7rs))]
548    assert!(apb3 <= pclk_max);
549    #[cfg(any(stm32h7, stm32h7rs))]
550    let apb4 = hclk / config.apb4_pre;
551    #[cfg(any(stm32h7, stm32h7rs))]
552    assert!(apb4 <= pclk_max);
553    #[cfg(stm32h7rs)]
554    let apb5 = hclk / config.apb5_pre;
555    #[cfg(stm32h7rs)]
556    assert!(apb5 <= pclk_max);
557
558    flash_setup(hclk, config.voltage_scale);
559
560    let rtc = config.ls.init();
561
562    #[cfg(all(stm32h7rs, peri_usb_otg_hs))]
563    let usb_refck = match config.mux.usbphycsel {
564        Usbphycsel::HSE => hse,
565        Usbphycsel::HSE_DIV_2 => hse.map(|hse_val| hse_val / 2u8),
566        Usbphycsel::PLL3_Q => pll3.q,
567        _ => None,
568    };
569    #[cfg(all(stm32h7rs, peri_usb_otg_hs))]
570    let usb_refck_sel = match usb_refck {
571        Some(clk_val) => match clk_val {
572            Hertz(16_000_000) => Usbrefcksel::MHZ16,
573            Hertz(19_200_000) => Usbrefcksel::MHZ19_2,
574            Hertz(20_000_000) => Usbrefcksel::MHZ20,
575            Hertz(24_000_000) => Usbrefcksel::MHZ24,
576            Hertz(26_000_000) => Usbrefcksel::MHZ26,
577            Hertz(32_000_000) => Usbrefcksel::MHZ32,
578            _ => panic!("cannot select USBPHYC reference clock with source frequency of {} Hz, must be one of 16, 19.2, 20, 24, 26, 32 MHz", clk_val),
579        },
580        None => Usbrefcksel::MHZ24,
581    };
582
583    #[cfg(stm32h7)]
584    {
585        RCC.d1cfgr().modify(|w| {
586            w.set_d1cpre(config.d1c_pre);
587            w.set_d1ppre(config.apb3_pre);
588            w.set_hpre(config.ahb_pre);
589        });
590        // Ensure core prescaler value is valid before future lower core voltage
591        while RCC.d1cfgr().read().d1cpre() != config.d1c_pre {}
592
593        RCC.d2cfgr().modify(|w| {
594            w.set_d2ppre1(config.apb1_pre);
595            w.set_d2ppre2(config.apb2_pre);
596        });
597        RCC.d3cfgr().modify(|w| {
598            w.set_d3ppre(config.apb4_pre);
599        });
600    }
601    #[cfg(stm32h7rs)]
602    {
603        RCC.cdcfgr().write(|w| {
604            w.set_cpre(config.d1c_pre);
605        });
606        while RCC.cdcfgr().read().cpre() != config.d1c_pre {}
607
608        RCC.bmcfgr().write(|w| {
609            w.set_bmpre(config.ahb_pre);
610        });
611        while RCC.bmcfgr().read().bmpre() != config.ahb_pre {}
612
613        RCC.apbcfgr().modify(|w| {
614            w.set_ppre1(config.apb1_pre);
615            w.set_ppre2(config.apb2_pre);
616            w.set_ppre4(config.apb4_pre);
617            w.set_ppre5(config.apb5_pre);
618        });
619
620        #[cfg(peri_usb_otg_hs)]
621        RCC.ahbperckselr().modify(|w| {
622            w.set_usbrefcksel(usb_refck_sel);
623        });
624    }
625    #[cfg(stm32h5)]
626    {
627        // Set hpre
628        RCC.cfgr2().modify(|w| w.set_hpre(config.ahb_pre));
629        while RCC.cfgr2().read().hpre() != config.ahb_pre {}
630
631        // set ppre
632        RCC.cfgr2().modify(|w| {
633            w.set_ppre1(config.apb1_pre);
634            w.set_ppre2(config.apb2_pre);
635            w.set_ppre3(config.apb3_pre);
636        });
637    }
638
639    RCC.cfgr().modify(|w| w.set_timpre(config.timer_prescaler.into()));
640
641    RCC.cfgr().modify(|w| w.set_sw(config.sys));
642    while RCC.cfgr().read().sws() != config.sys {}
643
644    // Disable HSI if not used
645    if config.hsi.is_none() {
646        RCC.cr().modify(|w| w.set_hsion(false));
647    }
648
649    // IO compensation cell - Requires CSI clock and SYSCFG
650    #[cfg(any(stm32h7))] // TODO h5, h7rs
651    if csi.is_some() {
652        // Enable the compensation cell, using back-bias voltage code
653        // provide by the cell.
654        critical_section::with(|_| {
655            pac::SYSCFG.cccsr().modify(|w| {
656                w.set_en(true);
657                w.set_cs(false);
658                w.set_hslv(false);
659            })
660        });
661        while !pac::SYSCFG.cccsr().read().rdy() {}
662    }
663
664    config.mux.init();
665
666    set_clocks!(
667        sys: Some(sys),
668        hclk1: Some(hclk),
669        hclk2: Some(hclk),
670        hclk3: Some(hclk),
671        hclk4: Some(hclk),
672        #[cfg(stm32h7rs)]
673        hclk5: Some(hclk),
674        pclk1: Some(apb1),
675        pclk2: Some(apb2),
676        #[cfg(not(stm32h7rs))]
677        pclk3: Some(apb3),
678        #[cfg(any(stm32h7, stm32h7rs))]
679        pclk4: Some(apb4),
680        #[cfg(stm32h7rs)]
681        pclk5: Some(apb5),
682
683        pclk1_tim: Some(apb1_tim),
684        pclk2_tim: Some(apb2_tim),
685        rtc: rtc,
686
687        hsi: hsi,
688        hsi48: hsi48,
689        csi: csi,
690        csi_div_122: csi.map(|c| c / 122u32),
691        hse: hse,
692
693        lse: None,
694        lsi: None,
695
696        pll1_q: pll1.q,
697        pll2_p: pll2.p,
698        pll2_q: pll2.q,
699        pll2_r: pll2.r,
700        #[cfg(stm32h7rs)]
701        pll2_s: None, // TODO
702        #[cfg(stm32h7rs)]
703        pll2_t: None, // TODO
704        #[cfg(any(rcc_h5, stm32h7, stm32h7rs))]
705        pll3_p: pll3.p,
706        #[cfg(any(rcc_h5, stm32h7, stm32h7rs))]
707        pll3_q: pll3.q,
708        #[cfg(any(rcc_h5, stm32h7, stm32h7rs))]
709        pll3_r: pll3.r,
710
711        #[cfg(rcc_h50)]
712        pll3_p: None,
713        #[cfg(rcc_h50)]
714        pll3_q: None,
715        #[cfg(rcc_h50)]
716        pll3_r: None,
717
718        #[cfg(dsihost)]
719        dsi_phy: None, // DSI PLL clock not supported, don't call `RccPeripheral::frequency()` in the drivers
720
721        #[cfg(stm32h5)]
722        audioclk: None,
723        i2s_ckin: None,
724        #[cfg(stm32h7rs)]
725        spdifrx_symb: None, // TODO
726        #[cfg(stm32h7rs)]
727        clk48mohci: None, // TODO
728        #[cfg(stm32h7rs)]
729        hse_div_2: hse.map(|clk| clk / 2u32),
730        #[cfg(stm32h7rs)]
731        usb: Some(Hertz(48_000_000)),
732    );
733}
734
735struct PllInput {
736    hsi: Option<Hertz>,
737    hse: Option<Hertz>,
738    csi: Option<Hertz>,
739}
740
741struct PllOutput {
742    p: Option<Hertz>,
743    #[allow(dead_code)]
744    q: Option<Hertz>,
745    #[allow(dead_code)]
746    r: Option<Hertz>,
747}
748
749fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
750    let Some(config) = config else {
751        // Stop PLL
752        RCC.cr().modify(|w| w.set_pllon(num, false));
753        while RCC.cr().read().pllrdy(num) {}
754
755        // "To save power when PLL1 is not used, the value of PLL1M must be set to 0.""
756        #[cfg(any(stm32h7, stm32h7rs))]
757        RCC.pllckselr().write(|w| w.set_divm(num, PllPreDiv::from_bits(0)));
758        #[cfg(stm32h5)]
759        RCC.pllcfgr(num).write(|w| w.set_divm(PllPreDiv::from_bits(0)));
760
761        return PllOutput {
762            p: None,
763            q: None,
764            r: None,
765        };
766    };
767
768    let in_clk = match config.source {
769        PllSource::DISABLE => panic!("must not set PllSource::Disable"),
770        PllSource::HSI => unwrap!(input.hsi),
771        PllSource::HSE => unwrap!(input.hse),
772        PllSource::CSI => unwrap!(input.csi),
773    };
774
775    let ref_clk = in_clk / config.prediv as u32;
776
777    let ref_range = match ref_clk.0 {
778        ..=1_999_999 => Pllrge::RANGE1,
779        ..=3_999_999 => Pllrge::RANGE2,
780        ..=7_999_999 => Pllrge::RANGE4,
781        ..=16_000_000 => Pllrge::RANGE8,
782        x => panic!("pll ref_clk out of range: {} hz", x),
783    };
784
785    // The smaller range (150 to 420 MHz) must
786    // be chosen when the reference clock frequency is lower than 2 MHz.
787    let wide_allowed = ref_range != Pllrge::RANGE1;
788
789    let vco_clk = ref_clk * config.mul;
790    let vco_range = if VCO_RANGE.contains(&vco_clk) {
791        Pllvcosel::MEDIUM_VCO
792    } else if wide_allowed && VCO_WIDE_RANGE.contains(&vco_clk) {
793        Pllvcosel::WIDE_VCO
794    } else {
795        panic!("pll vco_clk out of range: {} hz", vco_clk.0)
796    };
797
798    let p = config.divp.map(|div| {
799        if num == 0 {
800            // on PLL1, DIVP must be even for most series.
801            // The enum value is 1 less than the divider, so check it's odd.
802            #[cfg(not(any(pwr_h7rm0468, stm32h7rs)))]
803            assert!(div.to_bits() % 2 == 1);
804            #[cfg(pwr_h7rm0468)]
805            assert!(div.to_bits() % 2 == 1 || div.to_bits() == 0);
806        }
807
808        vco_clk / div
809    });
810    let q = config.divq.map(|div| vco_clk / div);
811    let r = config.divr.map(|div| vco_clk / div);
812
813    #[cfg(stm32h5)]
814    RCC.pllcfgr(num).write(|w| {
815        w.set_pllsrc(config.source);
816        w.set_divm(config.prediv);
817        w.set_pllvcosel(vco_range);
818        w.set_pllrge(ref_range);
819        w.set_pllfracen(false);
820        w.set_pllpen(p.is_some());
821        w.set_pllqen(q.is_some());
822        w.set_pllren(r.is_some());
823    });
824
825    #[cfg(any(stm32h7, stm32h7rs))]
826    {
827        RCC.pllckselr().modify(|w| {
828            w.set_divm(num, config.prediv);
829            w.set_pllsrc(config.source);
830        });
831        RCC.pllcfgr().modify(|w| {
832            w.set_pllvcosel(num, vco_range);
833            w.set_pllrge(num, ref_range);
834            w.set_pllfracen(num, false);
835            w.set_divpen(num, p.is_some());
836            w.set_divqen(num, q.is_some());
837            w.set_divren(num, r.is_some());
838        });
839    }
840
841    RCC.plldivr(num).write(|w| {
842        w.set_plln(config.mul);
843        w.set_pllp(config.divp.unwrap_or(PllDiv::DIV2));
844        w.set_pllq(config.divq.unwrap_or(PllDiv::DIV2));
845        w.set_pllr(config.divr.unwrap_or(PllDiv::DIV2));
846    });
847
848    RCC.cr().modify(|w| w.set_pllon(num, true));
849    while !RCC.cr().read().pllrdy(num) {}
850
851    PllOutput { p, q, r }
852}
853
854fn flash_setup(clk: Hertz, vos: VoltageScale) {
855    // RM0481 Rev 1, table 37
856    // LATENCY  WRHIGHFREQ  VOS3           VOS2            VOS1            VOS0
857    //      0           0   0 to 20 MHz    0 to 30 MHz     0 to 34 MHz     0 to 42 MHz
858    //      1           0   20 to 40 MHz   30 to 60 MHz    34 to 68 MHz    42 to 84 MHz
859    //      2           1   40 to 60 MHz   60 to 90 MHz    68 to 102 MHz   84 to 126 MHz
860    //      3           1   60 to 80 MHz   90 to 120 MHz   102 to 136 MHz  126 to 168 MHz
861    //      4           2   80 to 100 MHz  120 to 150 MHz  136 to 170 MHz  168 to 210 MHz
862    //      5           2                                  170 to 200 MHz  210 to 250 MHz
863    #[cfg(stm32h5)]
864    let (latency, wrhighfreq) = match (vos, clk.0) {
865        (VoltageScale::Scale0, ..=42_000_000) => (0, 0),
866        (VoltageScale::Scale0, ..=84_000_000) => (1, 0),
867        (VoltageScale::Scale0, ..=126_000_000) => (2, 1),
868        (VoltageScale::Scale0, ..=168_000_000) => (3, 1),
869        (VoltageScale::Scale0, ..=210_000_000) => (4, 2),
870        (VoltageScale::Scale0, ..=250_000_000) => (5, 2),
871
872        (VoltageScale::Scale1, ..=34_000_000) => (0, 0),
873        (VoltageScale::Scale1, ..=68_000_000) => (1, 0),
874        (VoltageScale::Scale1, ..=102_000_000) => (2, 1),
875        (VoltageScale::Scale1, ..=136_000_000) => (3, 1),
876        (VoltageScale::Scale1, ..=170_000_000) => (4, 2),
877        (VoltageScale::Scale1, ..=200_000_000) => (5, 2),
878
879        (VoltageScale::Scale2, ..=30_000_000) => (0, 0),
880        (VoltageScale::Scale2, ..=60_000_000) => (1, 0),
881        (VoltageScale::Scale2, ..=90_000_000) => (2, 1),
882        (VoltageScale::Scale2, ..=120_000_000) => (3, 1),
883        (VoltageScale::Scale2, ..=150_000_000) => (4, 2),
884
885        (VoltageScale::Scale3, ..=20_000_000) => (0, 0),
886        (VoltageScale::Scale3, ..=40_000_000) => (1, 0),
887        (VoltageScale::Scale3, ..=60_000_000) => (2, 1),
888        (VoltageScale::Scale3, ..=80_000_000) => (3, 1),
889        (VoltageScale::Scale3, ..=100_000_000) => (4, 2),
890
891        _ => unreachable!(),
892    };
893
894    #[cfg(all(flash_h7, not(pwr_h7rm0468)))]
895    let (latency, wrhighfreq) = match (vos, clk.0) {
896        // VOS 0 range VCORE 1.26V - 1.40V
897        (VoltageScale::Scale0, ..=70_000_000) => (0, 0),
898        (VoltageScale::Scale0, ..=140_000_000) => (1, 1),
899        (VoltageScale::Scale0, ..=185_000_000) => (2, 1),
900        (VoltageScale::Scale0, ..=210_000_000) => (2, 2),
901        (VoltageScale::Scale0, ..=225_000_000) => (3, 2),
902        (VoltageScale::Scale0, ..=240_000_000) => (4, 2),
903        // VOS 1 range VCORE 1.15V - 1.26V
904        (VoltageScale::Scale1, ..=70_000_000) => (0, 0),
905        (VoltageScale::Scale1, ..=140_000_000) => (1, 1),
906        (VoltageScale::Scale1, ..=185_000_000) => (2, 1),
907        (VoltageScale::Scale1, ..=210_000_000) => (2, 2),
908        (VoltageScale::Scale1, ..=225_000_000) => (3, 2),
909        // VOS 2 range VCORE 1.05V - 1.15V
910        (VoltageScale::Scale2, ..=55_000_000) => (0, 0),
911        (VoltageScale::Scale2, ..=110_000_000) => (1, 1),
912        (VoltageScale::Scale2, ..=165_000_000) => (2, 1),
913        (VoltageScale::Scale2, ..=224_000_000) => (3, 2),
914        // VOS 3 range VCORE 0.95V - 1.05V
915        (VoltageScale::Scale3, ..=45_000_000) => (0, 0),
916        (VoltageScale::Scale3, ..=90_000_000) => (1, 1),
917        (VoltageScale::Scale3, ..=135_000_000) => (2, 1),
918        (VoltageScale::Scale3, ..=180_000_000) => (3, 2),
919        (VoltageScale::Scale3, ..=224_000_000) => (4, 2),
920        _ => unreachable!(),
921    };
922
923    // See RM0468 Rev 3 Table 16. FLASH recommended number of wait
924    // states and programming delay
925    #[cfg(all(flash_h7, pwr_h7rm0468))]
926    let (latency, wrhighfreq) = match (vos, clk.0) {
927        // VOS 0 range VCORE 1.26V - 1.40V
928        (VoltageScale::Scale0, ..=70_000_000) => (0, 0),
929        (VoltageScale::Scale0, ..=140_000_000) => (1, 1),
930        (VoltageScale::Scale0, ..=210_000_000) => (2, 2),
931        (VoltageScale::Scale0, ..=275_000_000) => (3, 3),
932        // VOS 1 range VCORE 1.15V - 1.26V
933        (VoltageScale::Scale1, ..=67_000_000) => (0, 0),
934        (VoltageScale::Scale1, ..=133_000_000) => (1, 1),
935        (VoltageScale::Scale1, ..=200_000_000) => (2, 2),
936        // VOS 2 range VCORE 1.05V - 1.15V
937        (VoltageScale::Scale2, ..=50_000_000) => (0, 0),
938        (VoltageScale::Scale2, ..=100_000_000) => (1, 1),
939        (VoltageScale::Scale2, ..=150_000_000) => (2, 2),
940        // VOS 3 range VCORE 0.95V - 1.05V
941        (VoltageScale::Scale3, ..=35_000_000) => (0, 0),
942        (VoltageScale::Scale3, ..=70_000_000) => (1, 1),
943        (VoltageScale::Scale3, ..=85_000_000) => (2, 2),
944        _ => unreachable!(),
945    };
946
947    // See RM0455 Rev 10 Table 16. FLASH recommended number of wait
948    // states and programming delay
949    #[cfg(flash_h7ab)]
950    let (latency, wrhighfreq) = match (vos, clk.0) {
951        // VOS 0 range VCORE 1.25V - 1.35V
952        (VoltageScale::Scale0, ..=42_000_000) => (0, 0),
953        (VoltageScale::Scale0, ..=84_000_000) => (1, 0),
954        (VoltageScale::Scale0, ..=126_000_000) => (2, 1),
955        (VoltageScale::Scale0, ..=168_000_000) => (3, 1),
956        (VoltageScale::Scale0, ..=210_000_000) => (4, 2),
957        (VoltageScale::Scale0, ..=252_000_000) => (5, 2),
958        (VoltageScale::Scale0, ..=280_000_000) => (6, 3),
959        // VOS 1 range VCORE 1.15V - 1.25V
960        (VoltageScale::Scale1, ..=38_000_000) => (0, 0),
961        (VoltageScale::Scale1, ..=76_000_000) => (1, 0),
962        (VoltageScale::Scale1, ..=114_000_000) => (2, 1),
963        (VoltageScale::Scale1, ..=152_000_000) => (3, 1),
964        (VoltageScale::Scale1, ..=190_000_000) => (4, 2),
965        (VoltageScale::Scale1, ..=225_000_000) => (5, 2),
966        // VOS 2 range VCORE 1.05V - 1.15V
967        (VoltageScale::Scale2, ..=34) => (0, 0),
968        (VoltageScale::Scale2, ..=68) => (1, 0),
969        (VoltageScale::Scale2, ..=102) => (2, 1),
970        (VoltageScale::Scale2, ..=136) => (3, 1),
971        (VoltageScale::Scale2, ..=160) => (4, 2),
972        // VOS 3 range VCORE 0.95V - 1.05V
973        (VoltageScale::Scale3, ..=22) => (0, 0),
974        (VoltageScale::Scale3, ..=44) => (1, 0),
975        (VoltageScale::Scale3, ..=66) => (2, 1),
976        (VoltageScale::Scale3, ..=88) => (3, 1),
977        _ => unreachable!(),
978    };
979    #[cfg(flash_h7rs)]
980    let (latency, wrhighfreq) = match (vos, clk.0) {
981        // VOS high range VCORE 1.30V - 1.40V
982        (VoltageScale::HIGH, ..=40_000_000) => (0, 0),
983        (VoltageScale::HIGH, ..=80_000_000) => (1, 0),
984        (VoltageScale::HIGH, ..=120_000_000) => (2, 1),
985        (VoltageScale::HIGH, ..=160_000_000) => (3, 1),
986        (VoltageScale::HIGH, ..=200_000_000) => (4, 2),
987        (VoltageScale::HIGH, ..=240_000_000) => (5, 2),
988        (VoltageScale::HIGH, ..=280_000_000) => (6, 3),
989        (VoltageScale::HIGH, ..=320_000_000) => (7, 3),
990        // VOS low range VCORE 1.15V - 1.26V
991        (VoltageScale::LOW, ..=36_000_000) => (0, 0),
992        (VoltageScale::LOW, ..=72_000_000) => (1, 0),
993        (VoltageScale::LOW, ..=108_000_000) => (2, 1),
994        (VoltageScale::LOW, ..=144_000_000) => (3, 1),
995        (VoltageScale::LOW, ..=180_000_000) => (4, 2),
996        (VoltageScale::LOW, ..=216_000_000) => (5, 2),
997        _ => unreachable!(),
998    };
999
1000    debug!("flash: latency={} wrhighfreq={}", latency, wrhighfreq);
1001
1002    FLASH.acr().write(|w| {
1003        w.set_wrhighfreq(wrhighfreq);
1004        w.set_latency(latency);
1005    });
1006    while FLASH.acr().read().latency() != latency {}
1007}