Merge pull request #2026 from embassy-rs/stm32-pac-pll-enums
stm32/rcc: use PLL enums from PAC.
This commit is contained in:
		
						commit
						c3ef98a73d
					
				@ -59,12 +59,11 @@ sdio-host = "0.5.0"
 | 
				
			|||||||
embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
 | 
					embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
 | 
				
			||||||
critical-section = "1.1"
 | 
					critical-section = "1.1"
 | 
				
			||||||
atomic-polyfill = "1.0.1"
 | 
					atomic-polyfill = "1.0.1"
 | 
				
			||||||
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-eecd80c34d4a3035be31404857e6c6e115376f41" }
 | 
					stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-e89b8cfc30e480036aaf502f34c874ee42d68026" }
 | 
				
			||||||
vcell = "0.1.3"
 | 
					vcell = "0.1.3"
 | 
				
			||||||
bxcan = "0.7.0"
 | 
					bxcan = "0.7.0"
 | 
				
			||||||
nb = "1.0.0"
 | 
					nb = "1.0.0"
 | 
				
			||||||
stm32-fmc = "0.3.0"
 | 
					stm32-fmc = "0.3.0"
 | 
				
			||||||
seq-macro = "0.3.0"
 | 
					 | 
				
			||||||
cfg-if = "1.0.0"
 | 
					cfg-if = "1.0.0"
 | 
				
			||||||
embedded-io = { version = "0.6.0" }
 | 
					embedded-io = { version = "0.6.0" }
 | 
				
			||||||
embedded-io-async = { version = "0.6.0", optional = true }
 | 
					embedded-io-async = { version = "0.6.0", optional = true }
 | 
				
			||||||
@ -78,7 +77,7 @@ critical-section = { version = "1.1", features = ["std"] }
 | 
				
			|||||||
[build-dependencies]
 | 
					[build-dependencies]
 | 
				
			||||||
proc-macro2 = "1.0.36"
 | 
					proc-macro2 = "1.0.36"
 | 
				
			||||||
quote = "1.0.15"
 | 
					quote = "1.0.15"
 | 
				
			||||||
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-eecd80c34d4a3035be31404857e6c6e115376f41", default-features = false, features = ["metadata"]}
 | 
					stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-e89b8cfc30e480036aaf502f34c874ee42d68026", default-features = false, features = ["metadata"]}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[features]
 | 
					[features]
 | 
				
			||||||
 | 
				
			|||||||
@ -893,6 +893,105 @@ fn main() {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ========
 | 
				
			||||||
 | 
					    // Generate Div/Mul impls for RCC prescalers/dividers/multipliers.
 | 
				
			||||||
 | 
					    let rcc_registers = METADATA
 | 
				
			||||||
 | 
					        .peripherals
 | 
				
			||||||
 | 
					        .iter()
 | 
				
			||||||
 | 
					        .filter_map(|p| p.registers.as_ref())
 | 
				
			||||||
 | 
					        .find(|r| r.kind == "rcc")
 | 
				
			||||||
 | 
					        .unwrap()
 | 
				
			||||||
 | 
					        .ir;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for e in rcc_registers.enums {
 | 
				
			||||||
 | 
					        fn is_rcc_name(e: &str) -> bool {
 | 
				
			||||||
 | 
					            match e {
 | 
				
			||||||
 | 
					                "Pllp" | "Pllq" | "Pllr" | "Pllm" | "Plln" => true,
 | 
				
			||||||
 | 
					                "Timpre" | "Pllrclkpre" => false,
 | 
				
			||||||
 | 
					                e if e.ends_with("pre") || e.ends_with("div") || e.ends_with("mul") => true,
 | 
				
			||||||
 | 
					                _ => false,
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #[derive(Copy, Clone, Debug)]
 | 
				
			||||||
 | 
					        struct Frac {
 | 
				
			||||||
 | 
					            num: u32,
 | 
				
			||||||
 | 
					            denom: u32,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        impl Frac {
 | 
				
			||||||
 | 
					            fn simplify(self) -> Self {
 | 
				
			||||||
 | 
					                let d = gcd(self.num, self.denom);
 | 
				
			||||||
 | 
					                Self {
 | 
				
			||||||
 | 
					                    num: self.num / d,
 | 
				
			||||||
 | 
					                    denom: self.denom / d,
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fn gcd(a: u32, b: u32) -> u32 {
 | 
				
			||||||
 | 
					            if b == 0 {
 | 
				
			||||||
 | 
					                return a;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            gcd(b, a % b)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fn parse_num(n: &str) -> Result<Frac, ()> {
 | 
				
			||||||
 | 
					            for prefix in ["DIV", "MUL"] {
 | 
				
			||||||
 | 
					                if let Some(n) = n.strip_prefix(prefix) {
 | 
				
			||||||
 | 
					                    let exponent = n.find('_').map(|e| n.len() - 1 - e).unwrap_or(0) as u32;
 | 
				
			||||||
 | 
					                    let mantissa = n.replace('_', "").parse().map_err(|_| ())?;
 | 
				
			||||||
 | 
					                    let f = Frac {
 | 
				
			||||||
 | 
					                        num: mantissa,
 | 
				
			||||||
 | 
					                        denom: 10u32.pow(exponent),
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					                    return Ok(f.simplify());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Err(())
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if is_rcc_name(e.name) {
 | 
				
			||||||
 | 
					            let enum_name = format_ident!("{}", e.name);
 | 
				
			||||||
 | 
					            let mut muls = Vec::new();
 | 
				
			||||||
 | 
					            let mut divs = Vec::new();
 | 
				
			||||||
 | 
					            for v in e.variants {
 | 
				
			||||||
 | 
					                let Ok(val) = parse_num(v.name) else {
 | 
				
			||||||
 | 
					                    panic!("could not parse mul/div. enum={} variant={}", e.name, v.name)
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					                let variant_name = format_ident!("{}", v.name);
 | 
				
			||||||
 | 
					                let variant = quote!(crate::pac::rcc::vals::#enum_name::#variant_name);
 | 
				
			||||||
 | 
					                let num = val.num;
 | 
				
			||||||
 | 
					                let denom = val.denom;
 | 
				
			||||||
 | 
					                muls.push(quote!(#variant => self * #num / #denom,));
 | 
				
			||||||
 | 
					                divs.push(quote!(#variant => self * #denom / #num,));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            g.extend(quote! {
 | 
				
			||||||
 | 
					                impl core::ops::Div<crate::pac::rcc::vals::#enum_name> for crate::time::Hertz {
 | 
				
			||||||
 | 
					                    type Output = crate::time::Hertz;
 | 
				
			||||||
 | 
					                    fn div(self, rhs: crate::pac::rcc::vals::#enum_name) -> Self::Output {
 | 
				
			||||||
 | 
					                        match rhs {
 | 
				
			||||||
 | 
					                            #(#divs)*
 | 
				
			||||||
 | 
					                            #[allow(unreachable_patterns)]
 | 
				
			||||||
 | 
					                            _ => unreachable!(),
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                impl core::ops::Mul<crate::pac::rcc::vals::#enum_name> for crate::time::Hertz {
 | 
				
			||||||
 | 
					                    type Output = crate::time::Hertz;
 | 
				
			||||||
 | 
					                    fn mul(self, rhs: crate::pac::rcc::vals::#enum_name) -> Self::Output {
 | 
				
			||||||
 | 
					                        match rhs {
 | 
				
			||||||
 | 
					                            #(#muls)*
 | 
				
			||||||
 | 
					                            #[allow(unreachable_patterns)]
 | 
				
			||||||
 | 
					                            _ => unreachable!(),
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // ========
 | 
					    // ========
 | 
				
			||||||
    // Write foreach_foo! macrotables
 | 
					    // Write foreach_foo! macrotables
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,56 +0,0 @@
 | 
				
			|||||||
use core::ops::Div;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[allow(unused_imports)]
 | 
					 | 
				
			||||||
use crate::pac::rcc;
 | 
					 | 
				
			||||||
pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler};
 | 
					 | 
				
			||||||
use crate::time::Hertz;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Div<AHBPrescaler> for Hertz {
 | 
					 | 
				
			||||||
    type Output = Hertz;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn div(self, rhs: AHBPrescaler) -> Self::Output {
 | 
					 | 
				
			||||||
        let divisor = match rhs {
 | 
					 | 
				
			||||||
            AHBPrescaler::DIV1 => 1,
 | 
					 | 
				
			||||||
            AHBPrescaler::DIV2 => 2,
 | 
					 | 
				
			||||||
            #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
 | 
					 | 
				
			||||||
            AHBPrescaler::DIV3 => 3,
 | 
					 | 
				
			||||||
            AHBPrescaler::DIV4 => 4,
 | 
					 | 
				
			||||||
            #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
 | 
					 | 
				
			||||||
            AHBPrescaler::DIV5 => 5,
 | 
					 | 
				
			||||||
            #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
 | 
					 | 
				
			||||||
            AHBPrescaler::DIV6 => 6,
 | 
					 | 
				
			||||||
            AHBPrescaler::DIV8 => 8,
 | 
					 | 
				
			||||||
            #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
 | 
					 | 
				
			||||||
            AHBPrescaler::DIV10 => 10,
 | 
					 | 
				
			||||||
            AHBPrescaler::DIV16 => 16,
 | 
					 | 
				
			||||||
            #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
 | 
					 | 
				
			||||||
            AHBPrescaler::DIV32 => 32,
 | 
					 | 
				
			||||||
            #[cfg(not(rcc_wba))]
 | 
					 | 
				
			||||||
            AHBPrescaler::DIV64 => 64,
 | 
					 | 
				
			||||||
            #[cfg(not(rcc_wba))]
 | 
					 | 
				
			||||||
            AHBPrescaler::DIV128 => 128,
 | 
					 | 
				
			||||||
            #[cfg(not(rcc_wba))]
 | 
					 | 
				
			||||||
            AHBPrescaler::DIV256 => 256,
 | 
					 | 
				
			||||||
            #[cfg(not(rcc_wba))]
 | 
					 | 
				
			||||||
            AHBPrescaler::DIV512 => 512,
 | 
					 | 
				
			||||||
            _ => unreachable!(),
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        Hertz(self.0 / divisor)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Div<APBPrescaler> for Hertz {
 | 
					 | 
				
			||||||
    type Output = Hertz;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn div(self, rhs: APBPrescaler) -> Self::Output {
 | 
					 | 
				
			||||||
        let divisor = match rhs {
 | 
					 | 
				
			||||||
            APBPrescaler::DIV1 => 1,
 | 
					 | 
				
			||||||
            APBPrescaler::DIV2 => 2,
 | 
					 | 
				
			||||||
            APBPrescaler::DIV4 => 4,
 | 
					 | 
				
			||||||
            APBPrescaler::DIV8 => 8,
 | 
					 | 
				
			||||||
            APBPrescaler::DIV16 => 16,
 | 
					 | 
				
			||||||
            _ => unreachable!(),
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        Hertz(self.0 / divisor)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
pub use super::bus::{AHBPrescaler, APBPrescaler};
 | 
					 | 
				
			||||||
use crate::pac::flash::vals::Latency;
 | 
					use crate::pac::flash::vals::Latency;
 | 
				
			||||||
 | 
					pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler};
 | 
				
			||||||
use crate::pac::rcc::vals::{Hsidiv, Ppre, Sw};
 | 
					use crate::pac::rcc::vals::{Hsidiv, Ppre, Sw};
 | 
				
			||||||
use crate::pac::{FLASH, RCC};
 | 
					use crate::pac::{FLASH, RCC};
 | 
				
			||||||
use crate::rcc::{set_freqs, Clocks};
 | 
					use crate::rcc::{set_freqs, Clocks};
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,9 @@
 | 
				
			|||||||
use core::convert::TryFrom;
 | 
					 | 
				
			||||||
use core::ops::{Div, Mul};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub use super::bus::{AHBPrescaler, APBPrescaler};
 | 
					 | 
				
			||||||
use crate::pac::flash::vals::Latency;
 | 
					use crate::pac::flash::vals::Latency;
 | 
				
			||||||
use crate::pac::rcc::vals::{Pllp, Pllsrc, Sw};
 | 
					use crate::pac::rcc::vals::Sw;
 | 
				
			||||||
 | 
					pub use crate::pac::rcc::vals::{
 | 
				
			||||||
 | 
					    Hpre as AHBPrescaler, Pllm as PLLPreDiv, Plln as PLLMul, Pllp as PLLPDiv, Pllq as PLLQDiv, Pllsrc as PLLSrc,
 | 
				
			||||||
 | 
					    Ppre as APBPrescaler,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
use crate::pac::{FLASH, RCC};
 | 
					use crate::pac::{FLASH, RCC};
 | 
				
			||||||
use crate::rcc::bd::BackupDomain;
 | 
					use crate::rcc::bd::BackupDomain;
 | 
				
			||||||
use crate::rcc::{set_freqs, Clocks};
 | 
					use crate::rcc::{set_freqs, Clocks};
 | 
				
			||||||
@ -43,17 +43,17 @@ pub enum HSESrc {
 | 
				
			|||||||
pub struct PLLConfig {
 | 
					pub struct PLLConfig {
 | 
				
			||||||
    pub pre_div: PLLPreDiv,
 | 
					    pub pre_div: PLLPreDiv,
 | 
				
			||||||
    pub mul: PLLMul,
 | 
					    pub mul: PLLMul,
 | 
				
			||||||
    pub main_div: PLLMainDiv,
 | 
					    pub p_div: PLLPDiv,
 | 
				
			||||||
    pub pll48_div: PLL48Div,
 | 
					    pub q_div: PLLQDiv,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Default for PLLConfig {
 | 
					impl Default for PLLConfig {
 | 
				
			||||||
    fn default() -> Self {
 | 
					    fn default() -> Self {
 | 
				
			||||||
        PLLConfig {
 | 
					        PLLConfig {
 | 
				
			||||||
            pre_div: PLLPreDiv(16),
 | 
					            pre_div: PLLPreDiv::DIV16,
 | 
				
			||||||
            mul: PLLMul(192),
 | 
					            mul: PLLMul::MUL192,
 | 
				
			||||||
            main_div: PLLMainDiv::Div2,
 | 
					            p_div: PLLPDiv::DIV2,
 | 
				
			||||||
            pll48_div: PLL48Div(4),
 | 
					            q_div: PLLQDiv::DIV4,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -61,9 +61,9 @@ impl Default for PLLConfig {
 | 
				
			|||||||
impl PLLConfig {
 | 
					impl PLLConfig {
 | 
				
			||||||
    pub fn clocks(&self, src_freq: Hertz) -> PLLClocks {
 | 
					    pub fn clocks(&self, src_freq: Hertz) -> PLLClocks {
 | 
				
			||||||
        let in_freq = src_freq / self.pre_div;
 | 
					        let in_freq = src_freq / self.pre_div;
 | 
				
			||||||
        let vco_freq = Hertz((src_freq.0 as u64 * self.mul.0 as u64 / self.pre_div.0 as u64) as u32);
 | 
					        let vco_freq = src_freq / self.pre_div * self.mul;
 | 
				
			||||||
        let main_freq = vco_freq / self.main_div;
 | 
					        let main_freq = vco_freq / self.p_div;
 | 
				
			||||||
        let pll48_freq = vco_freq / self.pll48_div;
 | 
					        let pll48_freq = vco_freq / self.q_div;
 | 
				
			||||||
        PLLClocks {
 | 
					        PLLClocks {
 | 
				
			||||||
            in_freq,
 | 
					            in_freq,
 | 
				
			||||||
            vco_freq,
 | 
					            vco_freq,
 | 
				
			||||||
@ -72,129 +72,6 @@ impl PLLConfig {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Clock source for both main PLL and PLLI2S
 | 
					 | 
				
			||||||
#[derive(Clone, Copy, PartialEq)]
 | 
					 | 
				
			||||||
pub enum PLLSrc {
 | 
					 | 
				
			||||||
    HSE,
 | 
					 | 
				
			||||||
    HSI,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Into<Pllsrc> for PLLSrc {
 | 
					 | 
				
			||||||
    fn into(self) -> Pllsrc {
 | 
					 | 
				
			||||||
        match self {
 | 
					 | 
				
			||||||
            PLLSrc::HSE => Pllsrc::HSE,
 | 
					 | 
				
			||||||
            PLLSrc::HSI => Pllsrc::HSI,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Division factor for both main PLL and PLLI2S
 | 
					 | 
				
			||||||
#[derive(Clone, Copy, PartialEq)]
 | 
					 | 
				
			||||||
#[repr(transparent)]
 | 
					 | 
				
			||||||
pub struct PLLPreDiv(u8);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl TryFrom<u8> for PLLPreDiv {
 | 
					 | 
				
			||||||
    type Error = &'static str;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn try_from(value: u8) -> Result<Self, Self::Error> {
 | 
					 | 
				
			||||||
        match value {
 | 
					 | 
				
			||||||
            2..=63 => Ok(PLLPreDiv(value)),
 | 
					 | 
				
			||||||
            _ => Err("PLLPreDiv must be within range 2..=63"),
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Div<PLLPreDiv> for Hertz {
 | 
					 | 
				
			||||||
    type Output = Hertz;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn div(self, rhs: PLLPreDiv) -> Self::Output {
 | 
					 | 
				
			||||||
        Hertz(self.0 / u32::from(rhs.0))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Multiplication factor for main PLL
 | 
					 | 
				
			||||||
#[derive(Clone, Copy, PartialEq)]
 | 
					 | 
				
			||||||
#[repr(transparent)]
 | 
					 | 
				
			||||||
pub struct PLLMul(u16);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Mul<PLLMul> for Hertz {
 | 
					 | 
				
			||||||
    type Output = Hertz;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn mul(self, rhs: PLLMul) -> Self::Output {
 | 
					 | 
				
			||||||
        Hertz(self.0 * u32::from(rhs.0))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl TryFrom<u16> for PLLMul {
 | 
					 | 
				
			||||||
    type Error = &'static str;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn try_from(value: u16) -> Result<Self, Self::Error> {
 | 
					 | 
				
			||||||
        match value {
 | 
					 | 
				
			||||||
            192..=432 => Ok(PLLMul(value)),
 | 
					 | 
				
			||||||
            _ => Err("PLLMul must be within range 192..=432"),
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// PLL division factor for the main system clock
 | 
					 | 
				
			||||||
#[derive(Clone, Copy, PartialEq)]
 | 
					 | 
				
			||||||
pub enum PLLMainDiv {
 | 
					 | 
				
			||||||
    Div2,
 | 
					 | 
				
			||||||
    Div4,
 | 
					 | 
				
			||||||
    Div6,
 | 
					 | 
				
			||||||
    Div8,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Into<Pllp> for PLLMainDiv {
 | 
					 | 
				
			||||||
    fn into(self) -> Pllp {
 | 
					 | 
				
			||||||
        match self {
 | 
					 | 
				
			||||||
            PLLMainDiv::Div2 => Pllp::DIV2,
 | 
					 | 
				
			||||||
            PLLMainDiv::Div4 => Pllp::DIV4,
 | 
					 | 
				
			||||||
            PLLMainDiv::Div6 => Pllp::DIV6,
 | 
					 | 
				
			||||||
            PLLMainDiv::Div8 => Pllp::DIV8,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Div<PLLMainDiv> for Hertz {
 | 
					 | 
				
			||||||
    type Output = Hertz;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn div(self, rhs: PLLMainDiv) -> Self::Output {
 | 
					 | 
				
			||||||
        let divisor = match rhs {
 | 
					 | 
				
			||||||
            PLLMainDiv::Div2 => 2,
 | 
					 | 
				
			||||||
            PLLMainDiv::Div4 => 4,
 | 
					 | 
				
			||||||
            PLLMainDiv::Div6 => 6,
 | 
					 | 
				
			||||||
            PLLMainDiv::Div8 => 8,
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        Hertz(self.0 / divisor)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// PLL division factor for USB OTG FS / SDIO / RNG
 | 
					 | 
				
			||||||
#[derive(Clone, Copy, PartialEq)]
 | 
					 | 
				
			||||||
#[repr(transparent)]
 | 
					 | 
				
			||||||
pub struct PLL48Div(u8);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Div<PLL48Div> for Hertz {
 | 
					 | 
				
			||||||
    type Output = Hertz;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn div(self, rhs: PLL48Div) -> Self::Output {
 | 
					 | 
				
			||||||
        Hertz(self.0 / u32::from(rhs.0))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl TryFrom<u8> for PLL48Div {
 | 
					 | 
				
			||||||
    type Error = &'static str;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn try_from(value: u8) -> Result<Self, Self::Error> {
 | 
					 | 
				
			||||||
        match value {
 | 
					 | 
				
			||||||
            2..=15 => Ok(PLL48Div(value)),
 | 
					 | 
				
			||||||
            _ => Err("PLL48Div must be within range 2..=15"),
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Clone, Copy, PartialEq)]
 | 
					#[derive(Clone, Copy, PartialEq)]
 | 
				
			||||||
pub struct PLLClocks {
 | 
					pub struct PLLClocks {
 | 
				
			||||||
    pub in_freq: Hertz,
 | 
					    pub in_freq: Hertz,
 | 
				
			||||||
@ -367,11 +244,11 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
    assert!(pll_clocks.pll48_freq <= Hertz(48_000_000));
 | 
					    assert!(pll_clocks.pll48_freq <= Hertz(48_000_000));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    RCC.pllcfgr().write(|w| {
 | 
					    RCC.pllcfgr().write(|w| {
 | 
				
			||||||
        w.set_pllsrc(config.pll_mux.into());
 | 
					        w.set_pllsrc(config.pll_mux);
 | 
				
			||||||
        w.set_pllm(config.pll.pre_div.0);
 | 
					        w.set_pllm(config.pll.pre_div);
 | 
				
			||||||
        w.set_plln(config.pll.mul.0);
 | 
					        w.set_plln(config.pll.mul);
 | 
				
			||||||
        w.set_pllp(config.pll.main_div.into());
 | 
					        w.set_pllp(config.pll.p_div);
 | 
				
			||||||
        w.set_pllq(config.pll.pll48_div.0);
 | 
					        w.set_pllq(config.pll.q_div);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let (sys_clk, sw) = match config.mux {
 | 
					    let (sys_clk, sw) = match config.mux {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					use stm32_metapac::rcc::vals::{Pllm, Plln, Pllq, Pllr};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::pac::rcc::vals::{Hpre, Ppre, Sw};
 | 
					use crate::pac::rcc::vals::{Hpre, Ppre, Sw};
 | 
				
			||||||
use crate::pac::{FLASH, PWR, RCC};
 | 
					use crate::pac::{FLASH, PWR, RCC};
 | 
				
			||||||
use crate::rcc::bd::{BackupDomain, RtcClockSource};
 | 
					use crate::rcc::bd::{BackupDomain, RtcClockSource};
 | 
				
			||||||
@ -170,12 +172,12 @@ fn setup_pll(
 | 
				
			|||||||
    let real_pll48clk = vco_in * plln / pllq;
 | 
					    let real_pll48clk = vco_in * plln / pllq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    RCC.pllcfgr().modify(|w| {
 | 
					    RCC.pllcfgr().modify(|w| {
 | 
				
			||||||
        w.set_pllm(pllm as u8);
 | 
					        w.set_pllm(Pllm::from_bits(pllm as u8));
 | 
				
			||||||
        w.set_plln(plln as u16);
 | 
					        w.set_plln(Plln::from_bits(plln as u16));
 | 
				
			||||||
        w.set_pllp(Pllp::from_bits(pllp as u8));
 | 
					        w.set_pllp(Pllp::from_bits(pllp as u8));
 | 
				
			||||||
        w.set_pllq(pllq as u8);
 | 
					        w.set_pllq(Pllq::from_bits(pllq as u8));
 | 
				
			||||||
        w.set_pllsrc(Pllsrc::from_bits(use_hse as u8));
 | 
					        w.set_pllsrc(Pllsrc::from_bits(use_hse as u8));
 | 
				
			||||||
        w.set_pllr(0);
 | 
					        w.set_pllr(Pllr::from_bits(0));
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let real_pllsysclk = vco_in * plln / sysclk_div;
 | 
					    let real_pllsysclk = vco_in * plln / sysclk_div;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
use crate::pac::pwr::vals::Vos;
 | 
					use crate::pac::pwr::vals::Vos;
 | 
				
			||||||
use crate::pac::rcc::vals::{Hpre, Ppre, Sw};
 | 
					use crate::pac::rcc::vals::{Hpre, Pllm, Plln, Pllp, Pllq, Pllsrc, Ppre, Sw};
 | 
				
			||||||
use crate::pac::{FLASH, PWR, RCC};
 | 
					use crate::pac::{FLASH, PWR, RCC};
 | 
				
			||||||
use crate::rcc::bd::{BackupDomain, RtcClockSource};
 | 
					use crate::rcc::bd::{BackupDomain, RtcClockSource};
 | 
				
			||||||
use crate::rcc::{set_freqs, Clocks};
 | 
					use crate::rcc::{set_freqs, Clocks};
 | 
				
			||||||
@ -29,8 +29,6 @@ pub struct Config {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, pll48clk: bool) -> PllResults {
 | 
					fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, pll48clk: bool) -> PllResults {
 | 
				
			||||||
    use crate::pac::rcc::vals::{Pllp, Pllsrc};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let sysclk = pllsysclk.unwrap_or(pllsrcclk);
 | 
					    let sysclk = pllsysclk.unwrap_or(pllsrcclk);
 | 
				
			||||||
    if pllsysclk.is_none() && !pll48clk {
 | 
					    if pllsysclk.is_none() && !pll48clk {
 | 
				
			||||||
        RCC.pllcfgr().modify(|w| w.set_pllsrc(Pllsrc::from_bits(use_hse as u8)));
 | 
					        RCC.pllcfgr().modify(|w| w.set_pllsrc(Pllsrc::from_bits(use_hse as u8)));
 | 
				
			||||||
@ -84,10 +82,10 @@ fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, pll48clk: bo
 | 
				
			|||||||
    let real_pll48clk = vco_in * plln / pllq;
 | 
					    let real_pll48clk = vco_in * plln / pllq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    RCC.pllcfgr().modify(|w| {
 | 
					    RCC.pllcfgr().modify(|w| {
 | 
				
			||||||
        w.set_pllm(pllm as u8);
 | 
					        w.set_pllm(Pllm::from_bits(pllm as u8));
 | 
				
			||||||
        w.set_plln(plln as u16);
 | 
					        w.set_plln(Plln::from_bits(plln as u16));
 | 
				
			||||||
        w.set_pllp(Pllp::from_bits(pllp as u8));
 | 
					        w.set_pllp(Pllp::from_bits(pllp as u8));
 | 
				
			||||||
        w.set_pllq(pllq as u8);
 | 
					        w.set_pllq(Pllq::from_bits(pllq as u8));
 | 
				
			||||||
        w.set_pllsrc(Pllsrc::from_bits(use_hse as u8));
 | 
					        w.set_pllsrc(Pllsrc::from_bits(use_hse as u8));
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
pub use super::bus::{AHBPrescaler, APBPrescaler};
 | 
					 | 
				
			||||||
use crate::pac::flash::vals::Latency;
 | 
					use crate::pac::flash::vals::Latency;
 | 
				
			||||||
use crate::pac::rcc::vals::{self, Hsidiv, Ppre, Sw};
 | 
					use crate::pac::rcc::vals::{self, Hsidiv, Sw};
 | 
				
			||||||
 | 
					pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Pllm, Plln, Pllp, Pllq, Pllr, Ppre as APBPrescaler};
 | 
				
			||||||
use crate::pac::{FLASH, PWR, RCC};
 | 
					use crate::pac::{FLASH, PWR, RCC};
 | 
				
			||||||
use crate::rcc::{set_freqs, Clocks};
 | 
					use crate::rcc::{set_freqs, Clocks};
 | 
				
			||||||
use crate::time::Hertz;
 | 
					use crate::time::Hertz;
 | 
				
			||||||
@ -60,15 +60,15 @@ pub struct PllConfig {
 | 
				
			|||||||
    /// The initial divisor of that clock signal
 | 
					    /// The initial divisor of that clock signal
 | 
				
			||||||
    pub m: Pllm,
 | 
					    pub m: Pllm,
 | 
				
			||||||
    /// The PLL VCO multiplier, which must be in the range `8..=86`.
 | 
					    /// The PLL VCO multiplier, which must be in the range `8..=86`.
 | 
				
			||||||
    pub n: u8,
 | 
					    pub n: Plln,
 | 
				
			||||||
    /// The final divisor for `PLLRCLK` output which drives the system clock
 | 
					    /// The final divisor for `PLLRCLK` output which drives the system clock
 | 
				
			||||||
    pub r: Pllr,
 | 
					    pub r: Pllr,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// The divisor for the `PLLQCLK` output, if desired
 | 
					    /// The divisor for the `PLLQCLK` output, if desired
 | 
				
			||||||
    pub q: Option<Pllr>,
 | 
					    pub q: Option<Pllq>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// The divisor for the `PLLPCLK` output, if desired
 | 
					    /// The divisor for the `PLLPCLK` output, if desired
 | 
				
			||||||
    pub p: Option<Pllr>,
 | 
					    pub p: Option<Pllp>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Default for PllConfig {
 | 
					impl Default for PllConfig {
 | 
				
			||||||
@ -77,9 +77,9 @@ impl Default for PllConfig {
 | 
				
			|||||||
        // HSI16 / 1 * 8 / 2 = 64 MHz
 | 
					        // HSI16 / 1 * 8 / 2 = 64 MHz
 | 
				
			||||||
        PllConfig {
 | 
					        PllConfig {
 | 
				
			||||||
            source: PllSrc::HSI16,
 | 
					            source: PllSrc::HSI16,
 | 
				
			||||||
            m: Pllm::Div1,
 | 
					            m: Pllm::DIV1,
 | 
				
			||||||
            n: 8,
 | 
					            n: Plln::MUL8,
 | 
				
			||||||
            r: Pllr::Div2,
 | 
					            r: Pllr::DIV2,
 | 
				
			||||||
            q: None,
 | 
					            q: None,
 | 
				
			||||||
            p: None,
 | 
					            p: None,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -92,87 +92,6 @@ pub enum PllSrc {
 | 
				
			|||||||
    HSE(Hertz),
 | 
					    HSE(Hertz),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Clone, Copy)]
 | 
					 | 
				
			||||||
pub enum Pllm {
 | 
					 | 
				
			||||||
    Div1,
 | 
					 | 
				
			||||||
    Div2,
 | 
					 | 
				
			||||||
    Div3,
 | 
					 | 
				
			||||||
    Div4,
 | 
					 | 
				
			||||||
    Div5,
 | 
					 | 
				
			||||||
    Div6,
 | 
					 | 
				
			||||||
    Div7,
 | 
					 | 
				
			||||||
    Div8,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl From<Pllm> for u8 {
 | 
					 | 
				
			||||||
    fn from(v: Pllm) -> Self {
 | 
					 | 
				
			||||||
        match v {
 | 
					 | 
				
			||||||
            Pllm::Div1 => 0b000,
 | 
					 | 
				
			||||||
            Pllm::Div2 => 0b001,
 | 
					 | 
				
			||||||
            Pllm::Div3 => 0b010,
 | 
					 | 
				
			||||||
            Pllm::Div4 => 0b011,
 | 
					 | 
				
			||||||
            Pllm::Div5 => 0b100,
 | 
					 | 
				
			||||||
            Pllm::Div6 => 0b101,
 | 
					 | 
				
			||||||
            Pllm::Div7 => 0b110,
 | 
					 | 
				
			||||||
            Pllm::Div8 => 0b111,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl From<Pllm> for u32 {
 | 
					 | 
				
			||||||
    fn from(v: Pllm) -> Self {
 | 
					 | 
				
			||||||
        match v {
 | 
					 | 
				
			||||||
            Pllm::Div1 => 1,
 | 
					 | 
				
			||||||
            Pllm::Div2 => 2,
 | 
					 | 
				
			||||||
            Pllm::Div3 => 3,
 | 
					 | 
				
			||||||
            Pllm::Div4 => 4,
 | 
					 | 
				
			||||||
            Pllm::Div5 => 5,
 | 
					 | 
				
			||||||
            Pllm::Div6 => 6,
 | 
					 | 
				
			||||||
            Pllm::Div7 => 7,
 | 
					 | 
				
			||||||
            Pllm::Div8 => 8,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Clone, Copy)]
 | 
					 | 
				
			||||||
pub enum Pllr {
 | 
					 | 
				
			||||||
    Div2,
 | 
					 | 
				
			||||||
    Div3,
 | 
					 | 
				
			||||||
    Div4,
 | 
					 | 
				
			||||||
    Div5,
 | 
					 | 
				
			||||||
    Div6,
 | 
					 | 
				
			||||||
    Div7,
 | 
					 | 
				
			||||||
    Div8,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl From<Pllr> for u8 {
 | 
					 | 
				
			||||||
    fn from(v: Pllr) -> Self {
 | 
					 | 
				
			||||||
        match v {
 | 
					 | 
				
			||||||
            Pllr::Div2 => 0b000,
 | 
					 | 
				
			||||||
            Pllr::Div3 => 0b001,
 | 
					 | 
				
			||||||
            Pllr::Div4 => 0b010,
 | 
					 | 
				
			||||||
            Pllr::Div5 => 0b011,
 | 
					 | 
				
			||||||
            Pllr::Div6 => 0b101,
 | 
					 | 
				
			||||||
            Pllr::Div7 => 0b110,
 | 
					 | 
				
			||||||
            Pllr::Div8 => 0b111,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl From<Pllr> for u32 {
 | 
					 | 
				
			||||||
    fn from(v: Pllr) -> Self {
 | 
					 | 
				
			||||||
        match v {
 | 
					 | 
				
			||||||
            Pllr::Div2 => 2,
 | 
					 | 
				
			||||||
            Pllr::Div3 => 3,
 | 
					 | 
				
			||||||
            Pllr::Div4 => 4,
 | 
					 | 
				
			||||||
            Pllr::Div5 => 5,
 | 
					 | 
				
			||||||
            Pllr::Div6 => 6,
 | 
					 | 
				
			||||||
            Pllr::Div7 => 7,
 | 
					 | 
				
			||||||
            Pllr::Div8 => 8,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Clocks configutation
 | 
					/// Clocks configutation
 | 
				
			||||||
pub struct Config {
 | 
					pub struct Config {
 | 
				
			||||||
    pub mux: ClockSrc,
 | 
					    pub mux: ClockSrc,
 | 
				
			||||||
@ -194,29 +113,28 @@ impl Default for Config {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl PllConfig {
 | 
					impl PllConfig {
 | 
				
			||||||
    pub(crate) fn init(self) -> u32 {
 | 
					    pub(crate) fn init(self) -> Hertz {
 | 
				
			||||||
        assert!(self.n >= 8 && self.n <= 86);
 | 
					 | 
				
			||||||
        let (src, input_freq) = match self.source {
 | 
					        let (src, input_freq) = match self.source {
 | 
				
			||||||
            PllSrc::HSI16 => (vals::Pllsrc::HSI16, HSI_FREQ.0),
 | 
					            PllSrc::HSI16 => (vals::Pllsrc::HSI16, HSI_FREQ),
 | 
				
			||||||
            PllSrc::HSE(freq) => (vals::Pllsrc::HSE, freq.0),
 | 
					            PllSrc::HSE(freq) => (vals::Pllsrc::HSE, freq),
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let m_freq = input_freq / u32::from(self.m);
 | 
					        let m_freq = input_freq / self.m;
 | 
				
			||||||
        // RM0454 § 5.4.4:
 | 
					        // RM0454 § 5.4.4:
 | 
				
			||||||
        // > Caution: The software must set these bits so that the PLL input frequency after the
 | 
					        // > Caution: The software must set these bits so that the PLL input frequency after the
 | 
				
			||||||
        // > /M divider is between 2.66 and 16 MHz.
 | 
					        // > /M divider is between 2.66 and 16 MHz.
 | 
				
			||||||
        debug_assert!(m_freq >= 2_660_000 && m_freq <= 16_000_000);
 | 
					        debug_assert!(m_freq.0 >= 2_660_000 && m_freq.0 <= 16_000_000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let n_freq = m_freq * self.n as u32;
 | 
					        let n_freq = m_freq * self.n as u32;
 | 
				
			||||||
        // RM0454 § 5.4.4:
 | 
					        // RM0454 § 5.4.4:
 | 
				
			||||||
        // > Caution: The software must set these bits so that the VCO output frequency is between
 | 
					        // > Caution: The software must set these bits so that the VCO output frequency is between
 | 
				
			||||||
        // > 64 and 344 MHz.
 | 
					        // > 64 and 344 MHz.
 | 
				
			||||||
        debug_assert!(n_freq >= 64_000_000 && n_freq <= 344_000_000);
 | 
					        debug_assert!(n_freq.0 >= 64_000_000 && n_freq.0 <= 344_000_000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let r_freq = n_freq / u32::from(self.r);
 | 
					        let r_freq = n_freq / self.r;
 | 
				
			||||||
        // RM0454 § 5.4.4:
 | 
					        // RM0454 § 5.4.4:
 | 
				
			||||||
        // > Caution: The software must set this bitfield so as not to exceed 64 MHz on this clock.
 | 
					        // > Caution: The software must set this bitfield so as not to exceed 64 MHz on this clock.
 | 
				
			||||||
        debug_assert!(r_freq <= 64_000_000);
 | 
					        debug_assert!(r_freq.0 <= 64_000_000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // RM0454 § 5.2.3:
 | 
					        // RM0454 § 5.2.3:
 | 
				
			||||||
        // > To modify the PLL configuration, proceed as follows:
 | 
					        // > To modify the PLL configuration, proceed as follows:
 | 
				
			||||||
@ -239,25 +157,16 @@ impl PllConfig {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Configure PLLSYSCFGR
 | 
					        // Configure PLLCFGR
 | 
				
			||||||
        RCC.pllsyscfgr().modify(|w| {
 | 
					        RCC.pllcfgr().modify(|w| {
 | 
				
			||||||
            w.set_pllr(u8::from(self.r));
 | 
					            w.set_pllr(self.r);
 | 
				
			||||||
            w.set_pllren(false);
 | 
					            w.set_pllren(false);
 | 
				
			||||||
 | 
					            w.set_pllq(self.q.unwrap_or(Pllq::DIV2));
 | 
				
			||||||
            if let Some(q) = self.q {
 | 
					 | 
				
			||||||
                w.set_pllq(u8::from(q));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            w.set_pllqen(false);
 | 
					            w.set_pllqen(false);
 | 
				
			||||||
 | 
					            w.set_pllp(self.p.unwrap_or(Pllp::DIV2));
 | 
				
			||||||
            if let Some(p) = self.p {
 | 
					 | 
				
			||||||
                w.set_pllp(u8::from(p));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            w.set_pllpen(false);
 | 
					            w.set_pllpen(false);
 | 
				
			||||||
 | 
					 | 
				
			||||||
            w.set_plln(self.n);
 | 
					            w.set_plln(self.n);
 | 
				
			||||||
 | 
					            w.set_pllm(self.m);
 | 
				
			||||||
            w.set_pllm(self.m as u8);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            w.set_pllsrc(src)
 | 
					            w.set_pllsrc(src)
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -269,7 +178,7 @@ impl PllConfig {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // > 5. Enable the desired PLL outputs by configuring PLLPEN, PLLQEN, and PLLREN in PLL
 | 
					        // > 5. Enable the desired PLL outputs by configuring PLLPEN, PLLQEN, and PLLREN in PLL
 | 
				
			||||||
        // > configuration register (RCC_PLLCFGR).
 | 
					        // > configuration register (RCC_PLLCFGR).
 | 
				
			||||||
        RCC.pllsyscfgr().modify(|w| {
 | 
					        RCC.pllcfgr().modify(|w| {
 | 
				
			||||||
            // We'll use R for system clock, so enable that unconditionally
 | 
					            // We'll use R for system clock, so enable that unconditionally
 | 
				
			||||||
            w.set_pllren(true);
 | 
					            w.set_pllren(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -293,14 +202,14 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
            });
 | 
					            });
 | 
				
			||||||
            while !RCC.cr().read().hsirdy() {}
 | 
					            while !RCC.cr().read().hsirdy() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            (HSI_FREQ.0 >> div.to_bits(), Sw::HSI)
 | 
					            (HSI_FREQ / div, Sw::HSI)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        ClockSrc::HSE(freq) => {
 | 
					        ClockSrc::HSE(freq) => {
 | 
				
			||||||
            // Enable HSE
 | 
					            // Enable HSE
 | 
				
			||||||
            RCC.cr().write(|w| w.set_hseon(true));
 | 
					            RCC.cr().write(|w| w.set_hseon(true));
 | 
				
			||||||
            while !RCC.cr().read().hserdy() {}
 | 
					            while !RCC.cr().read().hserdy() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            (freq.0, Sw::HSE)
 | 
					            (freq, Sw::HSE)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        ClockSrc::PLL(pll) => {
 | 
					        ClockSrc::PLL(pll) => {
 | 
				
			||||||
            let freq = pll.init();
 | 
					            let freq = pll.init();
 | 
				
			||||||
@ -310,15 +219,15 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
            // Enable LSI
 | 
					            // Enable LSI
 | 
				
			||||||
            RCC.csr().write(|w| w.set_lsion(true));
 | 
					            RCC.csr().write(|w| w.set_lsion(true));
 | 
				
			||||||
            while !RCC.csr().read().lsirdy() {}
 | 
					            while !RCC.csr().read().lsirdy() {}
 | 
				
			||||||
            (LSI_FREQ.0, Sw::LSI)
 | 
					            (LSI_FREQ, Sw::LSI)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Determine the flash latency implied by the target clock speed
 | 
					    // Determine the flash latency implied by the target clock speed
 | 
				
			||||||
    // RM0454 § 3.3.4:
 | 
					    // RM0454 § 3.3.4:
 | 
				
			||||||
    let target_flash_latency = if sys_clk <= 24_000_000 {
 | 
					    let target_flash_latency = if sys_clk.0 <= 24_000_000 {
 | 
				
			||||||
        Latency::WS0
 | 
					        Latency::WS0
 | 
				
			||||||
    } else if sys_clk <= 48_000_000 {
 | 
					    } else if sys_clk.0 <= 48_000_000 {
 | 
				
			||||||
        Latency::WS1
 | 
					        Latency::WS1
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        Latency::WS2
 | 
					        Latency::WS2
 | 
				
			||||||
@ -374,27 +283,25 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
        FLASH.acr().modify(|w| w.set_latency(target_flash_latency));
 | 
					        FLASH.acr().modify(|w| w.set_latency(target_flash_latency));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let ahb_freq = Hertz(sys_clk) / config.ahb_pre;
 | 
					    let ahb_freq = sys_clk / config.ahb_pre;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let (apb_freq, apb_tim_freq) = match config.apb_pre {
 | 
					    let (apb_freq, apb_tim_freq) = match config.apb_pre {
 | 
				
			||||||
        APBPrescaler::DIV1 => (ahb_freq.0, ahb_freq.0),
 | 
					        APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
 | 
				
			||||||
        pre => {
 | 
					        pre => {
 | 
				
			||||||
            let pre: Ppre = pre.into();
 | 
					            let freq = ahb_freq / pre;
 | 
				
			||||||
            let pre: u8 = 1 << (pre.to_bits() - 3);
 | 
					            (freq, freq * 2u32)
 | 
				
			||||||
            let freq = ahb_freq.0 / pre as u32;
 | 
					 | 
				
			||||||
            (freq, freq * 2)
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if config.low_power_run {
 | 
					    if config.low_power_run {
 | 
				
			||||||
        assert!(sys_clk <= 2_000_000);
 | 
					        assert!(sys_clk.0 <= 2_000_000);
 | 
				
			||||||
        PWR.cr1().modify(|w| w.set_lpr(true));
 | 
					        PWR.cr1().modify(|w| w.set_lpr(true));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    set_freqs(Clocks {
 | 
					    set_freqs(Clocks {
 | 
				
			||||||
        sys: Hertz(sys_clk),
 | 
					        sys: sys_clk,
 | 
				
			||||||
        ahb1: ahb_freq,
 | 
					        ahb1: ahb_freq,
 | 
				
			||||||
        apb1: Hertz(apb_freq),
 | 
					        apb1: apb_freq,
 | 
				
			||||||
        apb1_tim: Hertz(apb_tim_freq),
 | 
					        apb1_tim: apb_tim_freq,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,9 @@ use stm32_metapac::flash::vals::Latency;
 | 
				
			|||||||
use stm32_metapac::rcc::vals::{Adcsel, Pllsrc, Sw};
 | 
					use stm32_metapac::rcc::vals::{Adcsel, Pllsrc, Sw};
 | 
				
			||||||
use stm32_metapac::FLASH;
 | 
					use stm32_metapac::FLASH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub use super::bus::{AHBPrescaler, APBPrescaler};
 | 
					pub use crate::pac::rcc::vals::{
 | 
				
			||||||
 | 
					    Hpre as AHBPrescaler, Pllm as PllM, Plln as PllN, Pllp as PllP, Pllq as PllQ, Pllr as PllR, Ppre as APBPrescaler,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
use crate::pac::{PWR, RCC};
 | 
					use crate::pac::{PWR, RCC};
 | 
				
			||||||
use crate::rcc::sealed::RccPeripheral;
 | 
					use crate::rcc::sealed::RccPeripheral;
 | 
				
			||||||
use crate::rcc::{set_freqs, Clocks};
 | 
					use crate::rcc::{set_freqs, Clocks};
 | 
				
			||||||
@ -61,181 +63,6 @@ impl Into<Pllsrc> for PllSrc {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
seq_macro::seq!(P in 2..=31 {
 | 
					 | 
				
			||||||
    /// Output divider for the PLL P output.
 | 
					 | 
				
			||||||
    #[derive(Clone, Copy)]
 | 
					 | 
				
			||||||
    pub enum PllP {
 | 
					 | 
				
			||||||
        // Note: If PLL P is set to 0 the PLLP bit controls the output division. There does not seem to
 | 
					 | 
				
			||||||
        // a good reason to do this so the API does not support it.
 | 
					 | 
				
			||||||
        // Div1 is invalid
 | 
					 | 
				
			||||||
        #(
 | 
					 | 
				
			||||||
            Div~P,
 | 
					 | 
				
			||||||
        )*
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    impl From<PllP> for u8 {
 | 
					 | 
				
			||||||
        /// Returns the register value for the P output divider.
 | 
					 | 
				
			||||||
        fn from(val: PllP) -> u8 {
 | 
					 | 
				
			||||||
            match val {
 | 
					 | 
				
			||||||
                #(
 | 
					 | 
				
			||||||
                    PllP::Div~P => P,
 | 
					 | 
				
			||||||
                )*
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl PllP {
 | 
					 | 
				
			||||||
    /// Returns the numeric value of the P output divider.
 | 
					 | 
				
			||||||
    pub fn to_div(self) -> u32 {
 | 
					 | 
				
			||||||
        let val: u8 = self.into();
 | 
					 | 
				
			||||||
        val as u32
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Output divider for the PLL Q output.
 | 
					 | 
				
			||||||
#[derive(Clone, Copy)]
 | 
					 | 
				
			||||||
pub enum PllQ {
 | 
					 | 
				
			||||||
    Div2,
 | 
					 | 
				
			||||||
    Div4,
 | 
					 | 
				
			||||||
    Div6,
 | 
					 | 
				
			||||||
    Div8,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl PllQ {
 | 
					 | 
				
			||||||
    /// Returns the numeric value of the Q output divider.
 | 
					 | 
				
			||||||
    pub fn to_div(self) -> u32 {
 | 
					 | 
				
			||||||
        let val: u8 = self.into();
 | 
					 | 
				
			||||||
        (val as u32 + 1) * 2
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl From<PllQ> for u8 {
 | 
					 | 
				
			||||||
    /// Returns the register value for the Q output divider.
 | 
					 | 
				
			||||||
    fn from(val: PllQ) -> u8 {
 | 
					 | 
				
			||||||
        match val {
 | 
					 | 
				
			||||||
            PllQ::Div2 => 0b00,
 | 
					 | 
				
			||||||
            PllQ::Div4 => 0b01,
 | 
					 | 
				
			||||||
            PllQ::Div6 => 0b10,
 | 
					 | 
				
			||||||
            PllQ::Div8 => 0b11,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Output divider for the PLL R output.
 | 
					 | 
				
			||||||
#[derive(Clone, Copy)]
 | 
					 | 
				
			||||||
pub enum PllR {
 | 
					 | 
				
			||||||
    Div2,
 | 
					 | 
				
			||||||
    Div4,
 | 
					 | 
				
			||||||
    Div6,
 | 
					 | 
				
			||||||
    Div8,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl PllR {
 | 
					 | 
				
			||||||
    /// Returns the numeric value of the R output divider.
 | 
					 | 
				
			||||||
    pub fn to_div(self) -> u32 {
 | 
					 | 
				
			||||||
        let val: u8 = self.into();
 | 
					 | 
				
			||||||
        (val as u32 + 1) * 2
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl From<PllR> for u8 {
 | 
					 | 
				
			||||||
    /// Returns the register value for the R output divider.
 | 
					 | 
				
			||||||
    fn from(val: PllR) -> u8 {
 | 
					 | 
				
			||||||
        match val {
 | 
					 | 
				
			||||||
            PllR::Div2 => 0b00,
 | 
					 | 
				
			||||||
            PllR::Div4 => 0b01,
 | 
					 | 
				
			||||||
            PllR::Div6 => 0b10,
 | 
					 | 
				
			||||||
            PllR::Div8 => 0b11,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
seq_macro::seq!(N in 8..=127 {
 | 
					 | 
				
			||||||
    /// Multiplication factor for the PLL VCO input clock.
 | 
					 | 
				
			||||||
    #[derive(Clone, Copy)]
 | 
					 | 
				
			||||||
    pub enum PllN {
 | 
					 | 
				
			||||||
        #(
 | 
					 | 
				
			||||||
            Mul~N,
 | 
					 | 
				
			||||||
        )*
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    impl From<PllN> for u8 {
 | 
					 | 
				
			||||||
        /// Returns the register value for the N multiplication factor.
 | 
					 | 
				
			||||||
        fn from(val: PllN) -> u8 {
 | 
					 | 
				
			||||||
            match val {
 | 
					 | 
				
			||||||
                #(
 | 
					 | 
				
			||||||
                    PllN::Mul~N => N,
 | 
					 | 
				
			||||||
                )*
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    impl PllN {
 | 
					 | 
				
			||||||
        /// Returns the numeric value of the N multiplication factor.
 | 
					 | 
				
			||||||
        pub fn to_mul(self) -> u32 {
 | 
					 | 
				
			||||||
            match self {
 | 
					 | 
				
			||||||
                #(
 | 
					 | 
				
			||||||
                    PllN::Mul~N => N,
 | 
					 | 
				
			||||||
                )*
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// PLL Pre-division. This must be set such that the PLL input is between 2.66 MHz and 16 MHz.
 | 
					 | 
				
			||||||
#[derive(Copy, Clone)]
 | 
					 | 
				
			||||||
pub enum PllM {
 | 
					 | 
				
			||||||
    Div1,
 | 
					 | 
				
			||||||
    Div2,
 | 
					 | 
				
			||||||
    Div3,
 | 
					 | 
				
			||||||
    Div4,
 | 
					 | 
				
			||||||
    Div5,
 | 
					 | 
				
			||||||
    Div6,
 | 
					 | 
				
			||||||
    Div7,
 | 
					 | 
				
			||||||
    Div8,
 | 
					 | 
				
			||||||
    Div9,
 | 
					 | 
				
			||||||
    Div10,
 | 
					 | 
				
			||||||
    Div11,
 | 
					 | 
				
			||||||
    Div12,
 | 
					 | 
				
			||||||
    Div13,
 | 
					 | 
				
			||||||
    Div14,
 | 
					 | 
				
			||||||
    Div15,
 | 
					 | 
				
			||||||
    Div16,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl PllM {
 | 
					 | 
				
			||||||
    /// Returns the numeric value of the M pre-division.
 | 
					 | 
				
			||||||
    pub fn to_div(self) -> u32 {
 | 
					 | 
				
			||||||
        let val: u8 = self.into();
 | 
					 | 
				
			||||||
        val as u32 + 1
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl From<PllM> for u8 {
 | 
					 | 
				
			||||||
    /// Returns the register value for the M pre-division.
 | 
					 | 
				
			||||||
    fn from(val: PllM) -> u8 {
 | 
					 | 
				
			||||||
        match val {
 | 
					 | 
				
			||||||
            PllM::Div1 => 0b0000,
 | 
					 | 
				
			||||||
            PllM::Div2 => 0b0001,
 | 
					 | 
				
			||||||
            PllM::Div3 => 0b0010,
 | 
					 | 
				
			||||||
            PllM::Div4 => 0b0011,
 | 
					 | 
				
			||||||
            PllM::Div5 => 0b0100,
 | 
					 | 
				
			||||||
            PllM::Div6 => 0b0101,
 | 
					 | 
				
			||||||
            PllM::Div7 => 0b0110,
 | 
					 | 
				
			||||||
            PllM::Div8 => 0b0111,
 | 
					 | 
				
			||||||
            PllM::Div9 => 0b1000,
 | 
					 | 
				
			||||||
            PllM::Div10 => 0b1001,
 | 
					 | 
				
			||||||
            PllM::Div11 => 0b1010,
 | 
					 | 
				
			||||||
            PllM::Div12 => 0b1011,
 | 
					 | 
				
			||||||
            PllM::Div13 => 0b1100,
 | 
					 | 
				
			||||||
            PllM::Div14 => 0b1101,
 | 
					 | 
				
			||||||
            PllM::Div15 => 0b1110,
 | 
					 | 
				
			||||||
            PllM::Div16 => 0b1111,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// PLL Configuration
 | 
					/// PLL Configuration
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// Use this struct to configure the PLL source, input frequency, multiplication factor, and output
 | 
					/// Use this struct to configure the PLL source, input frequency, multiplication factor, and output
 | 
				
			||||||
@ -360,12 +187,12 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
                RCC.cr().write(|w| w.set_hsion(true));
 | 
					                RCC.cr().write(|w| w.set_hsion(true));
 | 
				
			||||||
                while !RCC.cr().read().hsirdy() {}
 | 
					                while !RCC.cr().read().hsirdy() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                HSI_FREQ.0
 | 
					                HSI_FREQ
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            PllSrc::HSE(freq) => {
 | 
					            PllSrc::HSE(freq) => {
 | 
				
			||||||
                RCC.cr().write(|w| w.set_hseon(true));
 | 
					                RCC.cr().write(|w| w.set_hseon(true));
 | 
				
			||||||
                while !RCC.cr().read().hserdy() {}
 | 
					                while !RCC.cr().read().hserdy() {}
 | 
				
			||||||
                freq.0
 | 
					                freq
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -373,7 +200,7 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
        RCC.cr().modify(|w| w.set_pllon(false));
 | 
					        RCC.cr().modify(|w| w.set_pllon(false));
 | 
				
			||||||
        while RCC.cr().read().pllrdy() {}
 | 
					        while RCC.cr().read().pllrdy() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let internal_freq = src_freq / pll_config.prediv_m.to_div() * pll_config.mul_n.to_mul();
 | 
					        let internal_freq = src_freq / pll_config.prediv_m * pll_config.mul_n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        RCC.pllcfgr().write(|w| {
 | 
					        RCC.pllcfgr().write(|w| {
 | 
				
			||||||
            w.set_plln(pll_config.mul_n.into());
 | 
					            w.set_plln(pll_config.mul_n.into());
 | 
				
			||||||
@ -383,26 +210,26 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        let pll_p_freq = pll_config.div_p.map(|div_p| {
 | 
					        let pll_p_freq = pll_config.div_p.map(|div_p| {
 | 
				
			||||||
            RCC.pllcfgr().modify(|w| {
 | 
					            RCC.pllcfgr().modify(|w| {
 | 
				
			||||||
                w.set_pllpdiv(div_p.into());
 | 
					                w.set_pllp(div_p);
 | 
				
			||||||
                w.set_pllpen(true);
 | 
					                w.set_pllpen(true);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            Hertz(internal_freq / div_p.to_div())
 | 
					            internal_freq / div_p
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let pll_q_freq = pll_config.div_q.map(|div_q| {
 | 
					        let pll_q_freq = pll_config.div_q.map(|div_q| {
 | 
				
			||||||
            RCC.pllcfgr().modify(|w| {
 | 
					            RCC.pllcfgr().modify(|w| {
 | 
				
			||||||
                w.set_pllq(div_q.into());
 | 
					                w.set_pllq(div_q);
 | 
				
			||||||
                w.set_pllqen(true);
 | 
					                w.set_pllqen(true);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            Hertz(internal_freq / div_q.to_div())
 | 
					            internal_freq / div_q
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let pll_r_freq = pll_config.div_r.map(|div_r| {
 | 
					        let pll_r_freq = pll_config.div_r.map(|div_r| {
 | 
				
			||||||
            RCC.pllcfgr().modify(|w| {
 | 
					            RCC.pllcfgr().modify(|w| {
 | 
				
			||||||
                w.set_pllr(div_r.into());
 | 
					                w.set_pllr(div_r);
 | 
				
			||||||
                w.set_pllren(true);
 | 
					                w.set_pllren(true);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            Hertz(internal_freq / div_r.to_div())
 | 
					            internal_freq / div_r
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Enable the PLL
 | 
					        // Enable the PLL
 | 
				
			||||||
 | 
				
			|||||||
@ -6,8 +6,8 @@ use crate::pac::pwr::vals::Vos;
 | 
				
			|||||||
pub use crate::pac::rcc::vals::Adcdacsel as AdcClockSource;
 | 
					pub use crate::pac::rcc::vals::Adcdacsel as AdcClockSource;
 | 
				
			||||||
#[cfg(stm32h7)]
 | 
					#[cfg(stm32h7)]
 | 
				
			||||||
pub use crate::pac::rcc::vals::Adcsel as AdcClockSource;
 | 
					pub use crate::pac::rcc::vals::Adcsel as AdcClockSource;
 | 
				
			||||||
pub use crate::pac::rcc::vals::Ckpersel as PerClockSource;
 | 
					 | 
				
			||||||
use crate::pac::rcc::vals::{Ckpersel, Hsidiv, Pllrge, Pllsrc, Pllvcosel, Sw, Timpre};
 | 
					use crate::pac::rcc::vals::{Ckpersel, Hsidiv, Pllrge, Pllsrc, Pllvcosel, Sw, Timpre};
 | 
				
			||||||
 | 
					pub use crate::pac::rcc::vals::{Ckpersel as PerClockSource, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul};
 | 
				
			||||||
use crate::pac::{FLASH, PWR, RCC};
 | 
					use crate::pac::{FLASH, PWR, RCC};
 | 
				
			||||||
#[cfg(stm32h7)]
 | 
					#[cfg(stm32h7)]
 | 
				
			||||||
use crate::rcc::bd::{BackupDomain, LseCfg, RtcClockSource};
 | 
					use crate::rcc::bd::{BackupDomain, LseCfg, RtcClockSource};
 | 
				
			||||||
@ -34,7 +34,7 @@ const VCO_WIDE_RANGE: RangeInclusive<u32> = 192_000_000..=836_000_000;
 | 
				
			|||||||
#[cfg(any(pwr_h7rm0399, pwr_h7rm0433))]
 | 
					#[cfg(any(pwr_h7rm0399, pwr_h7rm0433))]
 | 
				
			||||||
const VCO_WIDE_RANGE: RangeInclusive<u32> = 192_000_000..=960_000_000;
 | 
					const VCO_WIDE_RANGE: RangeInclusive<u32> = 192_000_000..=960_000_000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub use super::bus::{AHBPrescaler, APBPrescaler};
 | 
					pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Clone, Copy, Eq, PartialEq)]
 | 
					#[derive(Clone, Copy, Eq, PartialEq)]
 | 
				
			||||||
pub enum VoltageScale {
 | 
					pub enum VoltageScale {
 | 
				
			||||||
@ -109,19 +109,19 @@ pub struct Pll {
 | 
				
			|||||||
    #[cfg(stm32h5)]
 | 
					    #[cfg(stm32h5)]
 | 
				
			||||||
    pub source: PllSource,
 | 
					    pub source: PllSource,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// PLL pre-divider (DIVM). Must be between 1 and 63.
 | 
					    /// PLL pre-divider (DIVM).
 | 
				
			||||||
    pub prediv: u8,
 | 
					    pub prediv: PllPreDiv,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// PLL multiplication factor. Must be between 4 and 512.
 | 
					    /// PLL multiplication factor.
 | 
				
			||||||
    pub mul: u16,
 | 
					    pub mul: PllMul,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// PLL P division factor. If None, PLL P output is disabled. Must be between 1 and 128.
 | 
					    /// PLL P division factor. If None, PLL P output is disabled.
 | 
				
			||||||
    /// On PLL1, it must be even (in particular, it cannot be 1.)
 | 
					    /// On PLL1, it must be even (in particular, it cannot be 1.)
 | 
				
			||||||
    pub divp: Option<u16>,
 | 
					    pub divp: Option<PllDiv>,
 | 
				
			||||||
    /// PLL Q division factor. If None, PLL Q output is disabled. Must be between 1 and 128.
 | 
					    /// PLL Q division factor. If None, PLL Q output is disabled.
 | 
				
			||||||
    pub divq: Option<u16>,
 | 
					    pub divq: Option<PllDiv>,
 | 
				
			||||||
    /// PLL R division factor. If None, PLL R output is disabled. Must be between 1 and 128.
 | 
					    /// PLL R division factor. If None, PLL R output is disabled.
 | 
				
			||||||
    pub divr: Option<u16>,
 | 
					    pub divr: Option<PllDiv>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn apb_div_tim(apb: &APBPrescaler, clk: Hertz, tim: TimerPrescaler) -> Hertz {
 | 
					fn apb_div_tim(apb: &APBPrescaler, clk: Hertz, tim: TimerPrescaler) -> Hertz {
 | 
				
			||||||
@ -604,9 +604,9 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // "To save power when PLL1 is not used, the value of PLL1M must be set to 0.""
 | 
					        // "To save power when PLL1 is not used, the value of PLL1M must be set to 0.""
 | 
				
			||||||
        #[cfg(stm32h7)]
 | 
					        #[cfg(stm32h7)]
 | 
				
			||||||
        RCC.pllckselr().write(|w| w.set_divm(num, 0));
 | 
					        RCC.pllckselr().write(|w| w.set_divm(num, PllPreDiv::from_bits(0)));
 | 
				
			||||||
        #[cfg(stm32h5)]
 | 
					        #[cfg(stm32h5)]
 | 
				
			||||||
        RCC.pllcfgr(num).write(|w| w.set_divm(0));
 | 
					        RCC.pllcfgr(num).write(|w| w.set_divm(PllPreDiv::from_bits(0)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return PllOutput {
 | 
					        return PllOutput {
 | 
				
			||||||
            p: None,
 | 
					            p: None,
 | 
				
			||||||
@ -615,9 +615,6 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert!(1 <= config.prediv && config.prediv <= 63);
 | 
					 | 
				
			||||||
    assert!(4 <= config.mul && config.mul <= 512);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[cfg(stm32h5)]
 | 
					    #[cfg(stm32h5)]
 | 
				
			||||||
    let source = config.source;
 | 
					    let source = config.source;
 | 
				
			||||||
    #[cfg(stm32h7)]
 | 
					    #[cfg(stm32h7)]
 | 
				
			||||||
@ -653,22 +650,16 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let p = config.divp.map(|div| {
 | 
					    let p = config.divp.map(|div| {
 | 
				
			||||||
        assert!(1 <= div && div <= 128);
 | 
					 | 
				
			||||||
        if num == 0 {
 | 
					        if num == 0 {
 | 
				
			||||||
            // on PLL1, DIVP must be even.
 | 
					            // on PLL1, DIVP must be even.
 | 
				
			||||||
            assert!(div % 2 == 0);
 | 
					            // The enum value is 1 less than the divider, so check it's odd.
 | 
				
			||||||
 | 
					            assert!(div.to_bits() % 2 == 1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        vco_clk / div
 | 
					        vco_clk / div
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    let q = config.divq.map(|div| {
 | 
					    let q = config.divq.map(|div| vco_clk / div);
 | 
				
			||||||
        assert!(1 <= div && div <= 128);
 | 
					    let r = config.divr.map(|div| vco_clk / div);
 | 
				
			||||||
        vco_clk / div
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    let r = config.divr.map(|div| {
 | 
					 | 
				
			||||||
        assert!(1 <= div && div <= 128);
 | 
					 | 
				
			||||||
        vco_clk / div
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[cfg(stm32h5)]
 | 
					    #[cfg(stm32h5)]
 | 
				
			||||||
    RCC.pllcfgr(num).write(|w| {
 | 
					    RCC.pllcfgr(num).write(|w| {
 | 
				
			||||||
@ -699,10 +690,10 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    RCC.plldivr(num).write(|w| {
 | 
					    RCC.plldivr(num).write(|w| {
 | 
				
			||||||
        w.set_plln(config.mul - 1);
 | 
					        w.set_plln(config.mul);
 | 
				
			||||||
        w.set_pllp((config.divp.unwrap_or(1) - 1) as u8);
 | 
					        w.set_pllp(config.divp.unwrap_or(PllDiv::DIV2));
 | 
				
			||||||
        w.set_pllq((config.divq.unwrap_or(1) - 1) as u8);
 | 
					        w.set_pllq(config.divq.unwrap_or(PllDiv::DIV2));
 | 
				
			||||||
        w.set_pllr((config.divr.unwrap_or(1) - 1) as u8);
 | 
					        w.set_pllr(config.divr.unwrap_or(PllDiv::DIV2));
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    RCC.cr().modify(|w| w.set_pllon(num, true));
 | 
					    RCC.cr().modify(|w| w.set_pllon(num, true));
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,8 @@
 | 
				
			|||||||
use super::bd::BackupDomain;
 | 
					use super::bd::BackupDomain;
 | 
				
			||||||
pub use super::bus::{AHBPrescaler, APBPrescaler};
 | 
					 | 
				
			||||||
use super::RtcClockSource;
 | 
					use super::RtcClockSource;
 | 
				
			||||||
pub use crate::pac::pwr::vals::Vos as VoltageScale;
 | 
					pub use crate::pac::pwr::vals::Vos as VoltageScale;
 | 
				
			||||||
use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw};
 | 
					use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw};
 | 
				
			||||||
 | 
					pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler};
 | 
				
			||||||
#[cfg(crs)]
 | 
					#[cfg(crs)]
 | 
				
			||||||
use crate::pac::{crs, CRS, SYSCFG};
 | 
					use crate::pac::{crs, CRS, SYSCFG};
 | 
				
			||||||
use crate::pac::{FLASH, PWR, RCC};
 | 
					use crate::pac::{FLASH, PWR, RCC};
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
pub use super::bus::{AHBPrescaler, APBPrescaler};
 | 
					 | 
				
			||||||
use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw};
 | 
					use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw};
 | 
				
			||||||
 | 
					pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler};
 | 
				
			||||||
use crate::pac::{FLASH, RCC};
 | 
					use crate::pac::{FLASH, RCC};
 | 
				
			||||||
use crate::rcc::{set_freqs, Clocks};
 | 
					use crate::rcc::{set_freqs, Clocks};
 | 
				
			||||||
use crate::time::Hertz;
 | 
					use crate::time::Hertz;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,9 @@
 | 
				
			|||||||
use stm32_metapac::rcc::regs::Cfgr;
 | 
					use crate::pac::rcc::regs::Cfgr;
 | 
				
			||||||
 | 
					pub use crate::pac::rcc::vals::{
 | 
				
			||||||
pub use super::bus::{AHBPrescaler, APBPrescaler};
 | 
					    Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv,
 | 
				
			||||||
use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw};
 | 
					    Pllr as PllRDiv, Ppre as APBPrescaler,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					use crate::pac::rcc::vals::{Msirange, Pllsrc, Sw};
 | 
				
			||||||
use crate::pac::{FLASH, RCC};
 | 
					use crate::pac::{FLASH, RCC};
 | 
				
			||||||
use crate::rcc::bd::{BackupDomain, RtcClockSource};
 | 
					use crate::rcc::bd::{BackupDomain, RtcClockSource};
 | 
				
			||||||
use crate::rcc::{set_freqs, Clocks};
 | 
					use crate::rcc::{set_freqs, Clocks};
 | 
				
			||||||
@ -17,62 +19,11 @@ pub const LSI_FREQ: Hertz = Hertz(32_000);
 | 
				
			|||||||
#[derive(Clone, Copy)]
 | 
					#[derive(Clone, Copy)]
 | 
				
			||||||
pub enum ClockSrc {
 | 
					pub enum ClockSrc {
 | 
				
			||||||
    MSI(MSIRange),
 | 
					    MSI(MSIRange),
 | 
				
			||||||
    PLL(PLLSource, PLLClkDiv, PLLSrcDiv, PLLMul, Option<PLL48Div>),
 | 
					    PLL(PLLSource, PllRDiv, PllPreDiv, PllMul, Option<PllQDiv>),
 | 
				
			||||||
    HSE(Hertz),
 | 
					    HSE(Hertz),
 | 
				
			||||||
    HSI16,
 | 
					    HSI16,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// MSI Clock Range
 | 
					 | 
				
			||||||
///
 | 
					 | 
				
			||||||
/// These ranges control the frequency of the MSI. Internally, these ranges map
 | 
					 | 
				
			||||||
/// to the `MSIRANGE` bits in the `RCC_ICSCR` register.
 | 
					 | 
				
			||||||
#[derive(Clone, Copy)]
 | 
					 | 
				
			||||||
pub enum MSIRange {
 | 
					 | 
				
			||||||
    /// Around 100 kHz
 | 
					 | 
				
			||||||
    Range0,
 | 
					 | 
				
			||||||
    /// Around 200 kHz
 | 
					 | 
				
			||||||
    Range1,
 | 
					 | 
				
			||||||
    /// Around 400 kHz
 | 
					 | 
				
			||||||
    Range2,
 | 
					 | 
				
			||||||
    /// Around 800 kHz
 | 
					 | 
				
			||||||
    Range3,
 | 
					 | 
				
			||||||
    /// Around 1 MHz
 | 
					 | 
				
			||||||
    Range4,
 | 
					 | 
				
			||||||
    /// Around 2 MHz
 | 
					 | 
				
			||||||
    Range5,
 | 
					 | 
				
			||||||
    /// Around 4 MHz (reset value)
 | 
					 | 
				
			||||||
    Range6,
 | 
					 | 
				
			||||||
    /// Around 8 MHz
 | 
					 | 
				
			||||||
    Range7,
 | 
					 | 
				
			||||||
    /// Around 16 MHz
 | 
					 | 
				
			||||||
    Range8,
 | 
					 | 
				
			||||||
    /// Around 24 MHz
 | 
					 | 
				
			||||||
    Range9,
 | 
					 | 
				
			||||||
    /// Around 32 MHz
 | 
					 | 
				
			||||||
    Range10,
 | 
					 | 
				
			||||||
    /// Around 48 MHz
 | 
					 | 
				
			||||||
    Range11,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Default for MSIRange {
 | 
					 | 
				
			||||||
    fn default() -> MSIRange {
 | 
					 | 
				
			||||||
        MSIRange::Range6
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub type PLL48Div = PLLClkDiv;
 | 
					 | 
				
			||||||
pub type PLLSAI1RDiv = PLLClkDiv;
 | 
					 | 
				
			||||||
pub type PLLSAI1QDiv = PLLClkDiv;
 | 
					 | 
				
			||||||
pub type PLLSAI1PDiv = PLLClkDiv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// PLL divider
 | 
					 | 
				
			||||||
#[derive(Clone, Copy)]
 | 
					 | 
				
			||||||
pub enum PLLDiv {
 | 
					 | 
				
			||||||
    Div2,
 | 
					 | 
				
			||||||
    Div3,
 | 
					 | 
				
			||||||
    Div4,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// PLL clock input source
 | 
					/// PLL clock input source
 | 
				
			||||||
#[derive(Clone, Copy)]
 | 
					#[derive(Clone, Copy)]
 | 
				
			||||||
pub enum PLLSource {
 | 
					pub enum PLLSource {
 | 
				
			||||||
@ -81,95 +32,6 @@ pub enum PLLSource {
 | 
				
			|||||||
    MSI(MSIRange),
 | 
					    MSI(MSIRange),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
seq_macro::seq!(N in 8..=86 {
 | 
					 | 
				
			||||||
    #[derive(Clone, Copy)]
 | 
					 | 
				
			||||||
    pub enum PLLMul {
 | 
					 | 
				
			||||||
        #(
 | 
					 | 
				
			||||||
            Mul~N,
 | 
					 | 
				
			||||||
        )*
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    impl From<PLLMul> for u8 {
 | 
					 | 
				
			||||||
        fn from(val: PLLMul) -> u8 {
 | 
					 | 
				
			||||||
            match val {
 | 
					 | 
				
			||||||
                #(
 | 
					 | 
				
			||||||
                    PLLMul::Mul~N => N,
 | 
					 | 
				
			||||||
                )*
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    impl PLLMul {
 | 
					 | 
				
			||||||
        pub fn to_mul(self) -> u32 {
 | 
					 | 
				
			||||||
            match self {
 | 
					 | 
				
			||||||
                #(
 | 
					 | 
				
			||||||
                    PLLMul::Mul~N => N,
 | 
					 | 
				
			||||||
                )*
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Clone, Copy)]
 | 
					 | 
				
			||||||
pub enum PLLClkDiv {
 | 
					 | 
				
			||||||
    Div2,
 | 
					 | 
				
			||||||
    Div4,
 | 
					 | 
				
			||||||
    Div6,
 | 
					 | 
				
			||||||
    Div8,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl PLLClkDiv {
 | 
					 | 
				
			||||||
    pub fn to_div(self) -> u32 {
 | 
					 | 
				
			||||||
        let val: u8 = self.into();
 | 
					 | 
				
			||||||
        (val as u32 + 1) * 2
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl From<PLLClkDiv> for u8 {
 | 
					 | 
				
			||||||
    fn from(val: PLLClkDiv) -> u8 {
 | 
					 | 
				
			||||||
        match val {
 | 
					 | 
				
			||||||
            PLLClkDiv::Div2 => 0b00,
 | 
					 | 
				
			||||||
            PLLClkDiv::Div4 => 0b01,
 | 
					 | 
				
			||||||
            PLLClkDiv::Div6 => 0b10,
 | 
					 | 
				
			||||||
            PLLClkDiv::Div8 => 0b11,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Clone, Copy)]
 | 
					 | 
				
			||||||
pub enum PLLSrcDiv {
 | 
					 | 
				
			||||||
    Div1,
 | 
					 | 
				
			||||||
    Div2,
 | 
					 | 
				
			||||||
    Div3,
 | 
					 | 
				
			||||||
    Div4,
 | 
					 | 
				
			||||||
    Div5,
 | 
					 | 
				
			||||||
    Div6,
 | 
					 | 
				
			||||||
    Div7,
 | 
					 | 
				
			||||||
    Div8,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl PLLSrcDiv {
 | 
					 | 
				
			||||||
    pub fn to_div(self) -> u32 {
 | 
					 | 
				
			||||||
        let val: u8 = self.into();
 | 
					 | 
				
			||||||
        val as u32 + 1
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl From<PLLSrcDiv> for u8 {
 | 
					 | 
				
			||||||
    fn from(val: PLLSrcDiv) -> u8 {
 | 
					 | 
				
			||||||
        match val {
 | 
					 | 
				
			||||||
            PLLSrcDiv::Div1 => 0b000,
 | 
					 | 
				
			||||||
            PLLSrcDiv::Div2 => 0b001,
 | 
					 | 
				
			||||||
            PLLSrcDiv::Div3 => 0b010,
 | 
					 | 
				
			||||||
            PLLSrcDiv::Div4 => 0b011,
 | 
					 | 
				
			||||||
            PLLSrcDiv::Div5 => 0b100,
 | 
					 | 
				
			||||||
            PLLSrcDiv::Div6 => 0b101,
 | 
					 | 
				
			||||||
            PLLSrcDiv::Div7 => 0b110,
 | 
					 | 
				
			||||||
            PLLSrcDiv::Div8 => 0b111,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl From<PLLSource> for Pllsrc {
 | 
					impl From<PLLSource> for Pllsrc {
 | 
				
			||||||
    fn from(val: PLLSource) -> Pllsrc {
 | 
					    fn from(val: PLLSource) -> Pllsrc {
 | 
				
			||||||
        match val {
 | 
					        match val {
 | 
				
			||||||
@ -180,57 +42,13 @@ impl From<PLLSource> for Pllsrc {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<MSIRange> for Msirange {
 | 
					 | 
				
			||||||
    fn from(val: MSIRange) -> Msirange {
 | 
					 | 
				
			||||||
        match val {
 | 
					 | 
				
			||||||
            MSIRange::Range0 => Msirange::RANGE100K,
 | 
					 | 
				
			||||||
            MSIRange::Range1 => Msirange::RANGE200K,
 | 
					 | 
				
			||||||
            MSIRange::Range2 => Msirange::RANGE400K,
 | 
					 | 
				
			||||||
            MSIRange::Range3 => Msirange::RANGE800K,
 | 
					 | 
				
			||||||
            MSIRange::Range4 => Msirange::RANGE1M,
 | 
					 | 
				
			||||||
            MSIRange::Range5 => Msirange::RANGE2M,
 | 
					 | 
				
			||||||
            MSIRange::Range6 => Msirange::RANGE4M,
 | 
					 | 
				
			||||||
            MSIRange::Range7 => Msirange::RANGE8M,
 | 
					 | 
				
			||||||
            MSIRange::Range8 => Msirange::RANGE16M,
 | 
					 | 
				
			||||||
            MSIRange::Range9 => Msirange::RANGE24M,
 | 
					 | 
				
			||||||
            MSIRange::Range10 => Msirange::RANGE32M,
 | 
					 | 
				
			||||||
            MSIRange::Range11 => Msirange::RANGE48M,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl From<MSIRange> for u32 {
 | 
					 | 
				
			||||||
    fn from(val: MSIRange) -> u32 {
 | 
					 | 
				
			||||||
        match val {
 | 
					 | 
				
			||||||
            MSIRange::Range0 => 100_000,
 | 
					 | 
				
			||||||
            MSIRange::Range1 => 200_000,
 | 
					 | 
				
			||||||
            MSIRange::Range2 => 400_000,
 | 
					 | 
				
			||||||
            MSIRange::Range3 => 800_000,
 | 
					 | 
				
			||||||
            MSIRange::Range4 => 1_000_000,
 | 
					 | 
				
			||||||
            MSIRange::Range5 => 2_000_000,
 | 
					 | 
				
			||||||
            MSIRange::Range6 => 4_000_000,
 | 
					 | 
				
			||||||
            MSIRange::Range7 => 8_000_000,
 | 
					 | 
				
			||||||
            MSIRange::Range8 => 16_000_000,
 | 
					 | 
				
			||||||
            MSIRange::Range9 => 24_000_000,
 | 
					 | 
				
			||||||
            MSIRange::Range10 => 32_000_000,
 | 
					 | 
				
			||||||
            MSIRange::Range11 => 48_000_000,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Clocks configutation
 | 
					/// Clocks configutation
 | 
				
			||||||
pub struct Config {
 | 
					pub struct Config {
 | 
				
			||||||
    pub mux: ClockSrc,
 | 
					    pub mux: ClockSrc,
 | 
				
			||||||
    pub ahb_pre: AHBPrescaler,
 | 
					    pub ahb_pre: AHBPrescaler,
 | 
				
			||||||
    pub apb1_pre: APBPrescaler,
 | 
					    pub apb1_pre: APBPrescaler,
 | 
				
			||||||
    pub apb2_pre: APBPrescaler,
 | 
					    pub apb2_pre: APBPrescaler,
 | 
				
			||||||
    pub pllsai1: Option<(
 | 
					    pub pllsai1: Option<(PllMul, PllPreDiv, Option<PllRDiv>, Option<PllQDiv>, Option<PllPDiv>)>,
 | 
				
			||||||
        PLLMul,
 | 
					 | 
				
			||||||
        PLLSrcDiv,
 | 
					 | 
				
			||||||
        Option<PLLSAI1RDiv>,
 | 
					 | 
				
			||||||
        Option<PLLSAI1QDiv>,
 | 
					 | 
				
			||||||
        Option<PLLSAI1PDiv>,
 | 
					 | 
				
			||||||
    )>,
 | 
					 | 
				
			||||||
    #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
 | 
					    #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
 | 
				
			||||||
    pub hsi48: bool,
 | 
					    pub hsi48: bool,
 | 
				
			||||||
    pub rtc_mux: RtcClockSource,
 | 
					    pub rtc_mux: RtcClockSource,
 | 
				
			||||||
@ -242,7 +60,7 @@ impl Default for Config {
 | 
				
			|||||||
    #[inline]
 | 
					    #[inline]
 | 
				
			||||||
    fn default() -> Config {
 | 
					    fn default() -> Config {
 | 
				
			||||||
        Config {
 | 
					        Config {
 | 
				
			||||||
            mux: ClockSrc::MSI(MSIRange::Range6),
 | 
					            mux: ClockSrc::MSI(MSIRange::RANGE4M),
 | 
				
			||||||
            ahb_pre: AHBPrescaler::DIV1,
 | 
					            ahb_pre: AHBPrescaler::DIV1,
 | 
				
			||||||
            apb1_pre: APBPrescaler::DIV1,
 | 
					            apb1_pre: APBPrescaler::DIV1,
 | 
				
			||||||
            apb2_pre: APBPrescaler::DIV1,
 | 
					            apb2_pre: APBPrescaler::DIV1,
 | 
				
			||||||
@ -262,7 +80,7 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
        // Turn on MSI and configure it to 4MHz.
 | 
					        // Turn on MSI and configure it to 4MHz.
 | 
				
			||||||
        RCC.cr().modify(|w| {
 | 
					        RCC.cr().modify(|w| {
 | 
				
			||||||
            w.set_msirgsel(true); // MSI Range is provided by MSIRANGE[3:0].
 | 
					            w.set_msirgsel(true); // MSI Range is provided by MSIRANGE[3:0].
 | 
				
			||||||
            w.set_msirange(MSIRange::default().into());
 | 
					            w.set_msirange(MSIRange::RANGE4M);
 | 
				
			||||||
            w.set_msipllen(false);
 | 
					            w.set_msipllen(false);
 | 
				
			||||||
            w.set_msion(true)
 | 
					            w.set_msion(true)
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
@ -298,40 +116,40 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
            while !RCC.cr().read().msirdy() {}
 | 
					            while !RCC.cr().read().msirdy() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Enable as clock source for USB, RNG if running at 48 MHz
 | 
					            // Enable as clock source for USB, RNG if running at 48 MHz
 | 
				
			||||||
            if let MSIRange::Range11 = range {
 | 
					            if range == MSIRange::RANGE48M {
 | 
				
			||||||
                RCC.ccipr().modify(|w| {
 | 
					                RCC.ccipr().modify(|w| {
 | 
				
			||||||
                    w.set_clk48sel(0b11);
 | 
					                    w.set_clk48sel(0b11);
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            (range.into(), Sw::MSI)
 | 
					            (msirange_to_hertz(range), Sw::MSI)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        ClockSrc::HSI16 => {
 | 
					        ClockSrc::HSI16 => {
 | 
				
			||||||
            // Enable HSI16
 | 
					            // Enable HSI16
 | 
				
			||||||
            RCC.cr().write(|w| w.set_hsion(true));
 | 
					            RCC.cr().write(|w| w.set_hsion(true));
 | 
				
			||||||
            while !RCC.cr().read().hsirdy() {}
 | 
					            while !RCC.cr().read().hsirdy() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            (HSI_FREQ.0, Sw::HSI16)
 | 
					            (HSI_FREQ, Sw::HSI16)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        ClockSrc::HSE(freq) => {
 | 
					        ClockSrc::HSE(freq) => {
 | 
				
			||||||
            // Enable HSE
 | 
					            // Enable HSE
 | 
				
			||||||
            RCC.cr().write(|w| w.set_hseon(true));
 | 
					            RCC.cr().write(|w| w.set_hseon(true));
 | 
				
			||||||
            while !RCC.cr().read().hserdy() {}
 | 
					            while !RCC.cr().read().hserdy() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            (freq.0, Sw::HSE)
 | 
					            (freq, Sw::HSE)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        ClockSrc::PLL(src, div, prediv, mul, pll48div) => {
 | 
					        ClockSrc::PLL(src, divr, prediv, mul, divq) => {
 | 
				
			||||||
            let src_freq = match src {
 | 
					            let src_freq = match src {
 | 
				
			||||||
                PLLSource::HSE(freq) => {
 | 
					                PLLSource::HSE(freq) => {
 | 
				
			||||||
                    // Enable HSE
 | 
					                    // Enable HSE
 | 
				
			||||||
                    RCC.cr().write(|w| w.set_hseon(true));
 | 
					                    RCC.cr().write(|w| w.set_hseon(true));
 | 
				
			||||||
                    while !RCC.cr().read().hserdy() {}
 | 
					                    while !RCC.cr().read().hserdy() {}
 | 
				
			||||||
                    freq.0
 | 
					                    freq
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                PLLSource::HSI16 => {
 | 
					                PLLSource::HSI16 => {
 | 
				
			||||||
                    // Enable HSI
 | 
					                    // Enable HSI
 | 
				
			||||||
                    RCC.cr().write(|w| w.set_hsion(true));
 | 
					                    RCC.cr().write(|w| w.set_hsion(true));
 | 
				
			||||||
                    while !RCC.cr().read().hsirdy() {}
 | 
					                    while !RCC.cr().read().hsirdy() {}
 | 
				
			||||||
                    HSI_FREQ.0
 | 
					                    HSI_FREQ
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                PLLSource::MSI(range) => {
 | 
					                PLLSource::MSI(range) => {
 | 
				
			||||||
                    // Enable MSI
 | 
					                    // Enable MSI
 | 
				
			||||||
@ -343,7 +161,8 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
                        w.set_msion(true);
 | 
					                        w.set_msion(true);
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    while !RCC.cr().read().msirdy() {}
 | 
					                    while !RCC.cr().read().msirdy() {}
 | 
				
			||||||
                    range.into()
 | 
					
 | 
				
			||||||
 | 
					                    msirange_to_hertz(range)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -351,28 +170,28 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
            RCC.cr().modify(|w| w.set_pllon(false));
 | 
					            RCC.cr().modify(|w| w.set_pllon(false));
 | 
				
			||||||
            while RCC.cr().read().pllrdy() {}
 | 
					            while RCC.cr().read().pllrdy() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let freq = (src_freq / prediv.to_div() * mul.to_mul()) / div.to_div();
 | 
					            let freq = src_freq / prediv * mul / divr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            #[cfg(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx))]
 | 
					            #[cfg(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx))]
 | 
				
			||||||
            assert!(freq <= 120_000_000);
 | 
					            assert!(freq.0 <= 120_000_000);
 | 
				
			||||||
            #[cfg(not(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx)))]
 | 
					            #[cfg(not(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx)))]
 | 
				
			||||||
            assert!(freq <= 80_000_000);
 | 
					            assert!(freq.0 <= 80_000_000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            RCC.pllcfgr().write(move |w| {
 | 
					            RCC.pllcfgr().write(move |w| {
 | 
				
			||||||
                w.set_plln(mul.into());
 | 
					                w.set_plln(mul);
 | 
				
			||||||
                w.set_pllm(prediv.into());
 | 
					                w.set_pllm(prediv);
 | 
				
			||||||
                w.set_pllr(div.into());
 | 
					                w.set_pllr(divr);
 | 
				
			||||||
                if let Some(pll48div) = pll48div {
 | 
					                if let Some(divq) = divq {
 | 
				
			||||||
                    w.set_pllq(pll48div.into());
 | 
					                    w.set_pllq(divq);
 | 
				
			||||||
                    w.set_pllqen(true);
 | 
					                    w.set_pllqen(true);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                w.set_pllsrc(src.into());
 | 
					                w.set_pllsrc(src.into());
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Enable as clock source for USB, RNG if PLL48 divisor is provided
 | 
					            // Enable as clock source for USB, RNG if PLL48 divisor is provided
 | 
				
			||||||
            if let Some(pll48div) = pll48div {
 | 
					            if let Some(divq) = divq {
 | 
				
			||||||
                let freq = (src_freq / prediv.to_div() * mul.to_mul()) / pll48div.to_div();
 | 
					                let freq = src_freq / prediv * mul / divq;
 | 
				
			||||||
                assert!(freq == 48_000_000);
 | 
					                assert!(freq.0 == 48_000_000);
 | 
				
			||||||
                RCC.ccipr().modify(|w| {
 | 
					                RCC.ccipr().modify(|w| {
 | 
				
			||||||
                    w.set_clk48sel(0b10);
 | 
					                    w.set_clk48sel(0b10);
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
@ -380,25 +199,25 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if let Some((mul, prediv, r_div, q_div, p_div)) = config.pllsai1 {
 | 
					            if let Some((mul, prediv, r_div, q_div, p_div)) = config.pllsai1 {
 | 
				
			||||||
                RCC.pllsai1cfgr().write(move |w| {
 | 
					                RCC.pllsai1cfgr().write(move |w| {
 | 
				
			||||||
                    w.set_pllsai1n(mul.into());
 | 
					                    w.set_plln(mul);
 | 
				
			||||||
                    w.set_pllsai1m(prediv.into());
 | 
					                    w.set_pllm(prediv);
 | 
				
			||||||
                    if let Some(r_div) = r_div {
 | 
					                    if let Some(r_div) = r_div {
 | 
				
			||||||
                        w.set_pllsai1r(r_div.into());
 | 
					                        w.set_pllr(r_div);
 | 
				
			||||||
                        w.set_pllsai1ren(true);
 | 
					                        w.set_pllren(true);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    if let Some(q_div) = q_div {
 | 
					                    if let Some(q_div) = q_div {
 | 
				
			||||||
                        w.set_pllsai1q(q_div.into());
 | 
					                        w.set_pllq(q_div);
 | 
				
			||||||
                        w.set_pllsai1qen(true);
 | 
					                        w.set_pllqen(true);
 | 
				
			||||||
                        let freq = (src_freq / prediv.to_div() * mul.to_mul()) / q_div.to_div();
 | 
					                        let freq = src_freq / prediv * mul / q_div;
 | 
				
			||||||
                        if freq == 48_000_000 {
 | 
					                        if freq.0 == 48_000_000 {
 | 
				
			||||||
                            RCC.ccipr().modify(|w| {
 | 
					                            RCC.ccipr().modify(|w| {
 | 
				
			||||||
                                w.set_clk48sel(0b1);
 | 
					                                w.set_clk48sel(0b1);
 | 
				
			||||||
                            });
 | 
					                            });
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    if let Some(p_div) = p_div {
 | 
					                    if let Some(p_div) = p_div {
 | 
				
			||||||
                        w.set_pllsai1pdiv(p_div.into());
 | 
					                        w.set_pllp(p_div);
 | 
				
			||||||
                        w.set_pllsai1pen(true);
 | 
					                        w.set_pllpen(true);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -425,17 +244,13 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Set flash wait states
 | 
					    // Set flash wait states
 | 
				
			||||||
    FLASH.acr().modify(|w| {
 | 
					    FLASH.acr().modify(|w| {
 | 
				
			||||||
        w.set_latency(if sys_clk <= 16_000_000 {
 | 
					        w.set_latency(match sys_clk.0 {
 | 
				
			||||||
            0b000
 | 
					            0..=16_000_000 => 0,
 | 
				
			||||||
        } else if sys_clk <= 32_000_000 {
 | 
					            0..=32_000_000 => 1,
 | 
				
			||||||
            0b001
 | 
					            0..=48_000_000 => 2,
 | 
				
			||||||
        } else if sys_clk <= 48_000_000 {
 | 
					            0..=64_000_000 => 3,
 | 
				
			||||||
            0b010
 | 
					            _ => 4,
 | 
				
			||||||
        } else if sys_clk <= 64_000_000 {
 | 
					        })
 | 
				
			||||||
            0b011
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            0b100
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    RCC.cfgr().modify(|w| {
 | 
					    RCC.cfgr().modify(|w| {
 | 
				
			||||||
@ -445,43 +260,50 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
        w.set_ppre2(config.apb2_pre.into());
 | 
					        w.set_ppre2(config.apb2_pre.into());
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let ahb_freq: u32 = match config.ahb_pre {
 | 
					    let ahb_freq = sys_clk / config.ahb_pre;
 | 
				
			||||||
        AHBPrescaler::DIV1 => sys_clk,
 | 
					 | 
				
			||||||
        pre => {
 | 
					 | 
				
			||||||
            let pre: Hpre = pre.into();
 | 
					 | 
				
			||||||
            let pre = 1 << (pre.to_bits() as u32 - 7);
 | 
					 | 
				
			||||||
            sys_clk / pre
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
 | 
					    let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
 | 
				
			||||||
        APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
 | 
					        APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
 | 
				
			||||||
        pre => {
 | 
					        pre => {
 | 
				
			||||||
            let pre: Ppre = pre.into();
 | 
					            let freq = ahb_freq / pre;
 | 
				
			||||||
            let pre: u8 = 1 << (pre.to_bits() - 3);
 | 
					            (freq, freq * 2u32)
 | 
				
			||||||
            let freq = ahb_freq / pre as u32;
 | 
					 | 
				
			||||||
            (freq, freq * 2)
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
 | 
					    let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
 | 
				
			||||||
        APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
 | 
					        APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
 | 
				
			||||||
        pre => {
 | 
					        pre => {
 | 
				
			||||||
            let pre: Ppre = pre.into();
 | 
					            let freq = ahb_freq / pre;
 | 
				
			||||||
            let pre: u8 = 1 << (pre.to_bits() - 3);
 | 
					            (freq, freq * 2u32)
 | 
				
			||||||
            let freq = ahb_freq / pre as u32;
 | 
					 | 
				
			||||||
            (freq, freq * 2)
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    set_freqs(Clocks {
 | 
					    set_freqs(Clocks {
 | 
				
			||||||
        sys: Hertz(sys_clk),
 | 
					        sys: sys_clk,
 | 
				
			||||||
        ahb1: Hertz(ahb_freq),
 | 
					        ahb1: ahb_freq,
 | 
				
			||||||
        ahb2: Hertz(ahb_freq),
 | 
					        ahb2: ahb_freq,
 | 
				
			||||||
        ahb3: Hertz(ahb_freq),
 | 
					        ahb3: ahb_freq,
 | 
				
			||||||
        apb1: Hertz(apb1_freq),
 | 
					        apb1: apb1_freq,
 | 
				
			||||||
        apb2: Hertz(apb2_freq),
 | 
					        apb2: apb2_freq,
 | 
				
			||||||
        apb1_tim: Hertz(apb1_tim_freq),
 | 
					        apb1_tim: apb1_tim_freq,
 | 
				
			||||||
        apb2_tim: Hertz(apb2_tim_freq),
 | 
					        apb2_tim: apb2_tim_freq,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn msirange_to_hertz(range: Msirange) -> Hertz {
 | 
				
			||||||
 | 
					    match range {
 | 
				
			||||||
 | 
					        MSIRange::RANGE100K => Hertz(100_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE200K => Hertz(200_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE400K => Hertz(400_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE800K => Hertz(800_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE1M => Hertz(1_000_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE2M => Hertz(2_000_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE4M => Hertz(4_000_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE8M => Hertz(8_000_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE16M => Hertz(16_000_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE24M => Hertz(24_000_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE32M => Hertz(32_000_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE48M => Hertz(48_000_000),
 | 
				
			||||||
 | 
					        _ => unreachable!(),
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,11 @@
 | 
				
			|||||||
use stm32_metapac::PWR;
 | 
					use crate::pac::rcc::regs::Cfgr;
 | 
				
			||||||
 | 
					pub use crate::pac::rcc::vals::{
 | 
				
			||||||
pub use super::bus::{AHBPrescaler, APBPrescaler};
 | 
					    Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv,
 | 
				
			||||||
use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw};
 | 
					    Pllr as PllRDiv, Ppre as APBPrescaler,
 | 
				
			||||||
use crate::pac::{FLASH, RCC};
 | 
					};
 | 
				
			||||||
 | 
					use crate::pac::rcc::vals::{Msirange, Pllsrc, Sw};
 | 
				
			||||||
 | 
					use crate::pac::{FLASH, PWR, RCC};
 | 
				
			||||||
 | 
					use crate::rcc::bd::RtcClockSource;
 | 
				
			||||||
use crate::rcc::{set_freqs, Clocks};
 | 
					use crate::rcc::{set_freqs, Clocks};
 | 
				
			||||||
use crate::time::Hertz;
 | 
					use crate::time::Hertz;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -16,62 +19,11 @@ pub const LSI_FREQ: Hertz = Hertz(32_000);
 | 
				
			|||||||
#[derive(Clone, Copy)]
 | 
					#[derive(Clone, Copy)]
 | 
				
			||||||
pub enum ClockSrc {
 | 
					pub enum ClockSrc {
 | 
				
			||||||
    MSI(MSIRange),
 | 
					    MSI(MSIRange),
 | 
				
			||||||
    PLL(PLLSource, PLLClkDiv, PLLSrcDiv, PLLMul, Option<PLL48Div>),
 | 
					    PLL(PLLSource, PllRDiv, PllPreDiv, PllMul, Option<PllQDiv>),
 | 
				
			||||||
    HSE(Hertz),
 | 
					    HSE(Hertz),
 | 
				
			||||||
    HSI16,
 | 
					    HSI16,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// MSI Clock Range
 | 
					 | 
				
			||||||
///
 | 
					 | 
				
			||||||
/// These ranges control the frequency of the MSI. Internally, these ranges map
 | 
					 | 
				
			||||||
/// to the `MSIRANGE` bits in the `RCC_ICSCR` register.
 | 
					 | 
				
			||||||
#[derive(Clone, Copy)]
 | 
					 | 
				
			||||||
pub enum MSIRange {
 | 
					 | 
				
			||||||
    /// Around 100 kHz
 | 
					 | 
				
			||||||
    Range0,
 | 
					 | 
				
			||||||
    /// Around 200 kHz
 | 
					 | 
				
			||||||
    Range1,
 | 
					 | 
				
			||||||
    /// Around 400 kHz
 | 
					 | 
				
			||||||
    Range2,
 | 
					 | 
				
			||||||
    /// Around 800 kHz
 | 
					 | 
				
			||||||
    Range3,
 | 
					 | 
				
			||||||
    /// Around 1 MHz
 | 
					 | 
				
			||||||
    Range4,
 | 
					 | 
				
			||||||
    /// Around 2 MHz
 | 
					 | 
				
			||||||
    Range5,
 | 
					 | 
				
			||||||
    /// Around 4 MHz (reset value)
 | 
					 | 
				
			||||||
    Range6,
 | 
					 | 
				
			||||||
    /// Around 8 MHz
 | 
					 | 
				
			||||||
    Range7,
 | 
					 | 
				
			||||||
    /// Around 16 MHz
 | 
					 | 
				
			||||||
    Range8,
 | 
					 | 
				
			||||||
    /// Around 24 MHz
 | 
					 | 
				
			||||||
    Range9,
 | 
					 | 
				
			||||||
    /// Around 32 MHz
 | 
					 | 
				
			||||||
    Range10,
 | 
					 | 
				
			||||||
    /// Around 48 MHz
 | 
					 | 
				
			||||||
    Range11,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Default for MSIRange {
 | 
					 | 
				
			||||||
    fn default() -> MSIRange {
 | 
					 | 
				
			||||||
        MSIRange::Range6
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub type PLL48Div = PLLClkDiv;
 | 
					 | 
				
			||||||
pub type PLLSAI1RDiv = PLLClkDiv;
 | 
					 | 
				
			||||||
pub type PLLSAI1QDiv = PLLClkDiv;
 | 
					 | 
				
			||||||
pub type PLLSAI1PDiv = PLLClkDiv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// PLL divider
 | 
					 | 
				
			||||||
#[derive(Clone, Copy)]
 | 
					 | 
				
			||||||
pub enum PLLDiv {
 | 
					 | 
				
			||||||
    Div2,
 | 
					 | 
				
			||||||
    Div3,
 | 
					 | 
				
			||||||
    Div4,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// PLL clock input source
 | 
					/// PLL clock input source
 | 
				
			||||||
#[derive(Clone, Copy)]
 | 
					#[derive(Clone, Copy)]
 | 
				
			||||||
pub enum PLLSource {
 | 
					pub enum PLLSource {
 | 
				
			||||||
@ -80,95 +32,6 @@ pub enum PLLSource {
 | 
				
			|||||||
    MSI(MSIRange),
 | 
					    MSI(MSIRange),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
seq_macro::seq!(N in 8..=86 {
 | 
					 | 
				
			||||||
    #[derive(Clone, Copy)]
 | 
					 | 
				
			||||||
    pub enum PLLMul {
 | 
					 | 
				
			||||||
        #(
 | 
					 | 
				
			||||||
            Mul~N,
 | 
					 | 
				
			||||||
        )*
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    impl From<PLLMul> for u8 {
 | 
					 | 
				
			||||||
        fn from(val: PLLMul) -> u8 {
 | 
					 | 
				
			||||||
            match val {
 | 
					 | 
				
			||||||
                #(
 | 
					 | 
				
			||||||
                    PLLMul::Mul~N => N,
 | 
					 | 
				
			||||||
                )*
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    impl PLLMul {
 | 
					 | 
				
			||||||
        pub fn to_mul(self) -> u32 {
 | 
					 | 
				
			||||||
            match self {
 | 
					 | 
				
			||||||
                #(
 | 
					 | 
				
			||||||
                    PLLMul::Mul~N => N,
 | 
					 | 
				
			||||||
                )*
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Clone, Copy)]
 | 
					 | 
				
			||||||
pub enum PLLClkDiv {
 | 
					 | 
				
			||||||
    Div2,
 | 
					 | 
				
			||||||
    Div4,
 | 
					 | 
				
			||||||
    Div6,
 | 
					 | 
				
			||||||
    Div8,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl PLLClkDiv {
 | 
					 | 
				
			||||||
    pub fn to_div(self) -> u32 {
 | 
					 | 
				
			||||||
        let val: u8 = self.into();
 | 
					 | 
				
			||||||
        (val as u32 + 1) * 2
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl From<PLLClkDiv> for u8 {
 | 
					 | 
				
			||||||
    fn from(val: PLLClkDiv) -> u8 {
 | 
					 | 
				
			||||||
        match val {
 | 
					 | 
				
			||||||
            PLLClkDiv::Div2 => 0b00,
 | 
					 | 
				
			||||||
            PLLClkDiv::Div4 => 0b01,
 | 
					 | 
				
			||||||
            PLLClkDiv::Div6 => 0b10,
 | 
					 | 
				
			||||||
            PLLClkDiv::Div8 => 0b11,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Clone, Copy)]
 | 
					 | 
				
			||||||
pub enum PLLSrcDiv {
 | 
					 | 
				
			||||||
    Div1,
 | 
					 | 
				
			||||||
    Div2,
 | 
					 | 
				
			||||||
    Div3,
 | 
					 | 
				
			||||||
    Div4,
 | 
					 | 
				
			||||||
    Div5,
 | 
					 | 
				
			||||||
    Div6,
 | 
					 | 
				
			||||||
    Div7,
 | 
					 | 
				
			||||||
    Div8,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl PLLSrcDiv {
 | 
					 | 
				
			||||||
    pub fn to_div(self) -> u32 {
 | 
					 | 
				
			||||||
        let val: u8 = self.into();
 | 
					 | 
				
			||||||
        val as u32 + 1
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl From<PLLSrcDiv> for u8 {
 | 
					 | 
				
			||||||
    fn from(val: PLLSrcDiv) -> u8 {
 | 
					 | 
				
			||||||
        match val {
 | 
					 | 
				
			||||||
            PLLSrcDiv::Div1 => 0b000,
 | 
					 | 
				
			||||||
            PLLSrcDiv::Div2 => 0b001,
 | 
					 | 
				
			||||||
            PLLSrcDiv::Div3 => 0b010,
 | 
					 | 
				
			||||||
            PLLSrcDiv::Div4 => 0b011,
 | 
					 | 
				
			||||||
            PLLSrcDiv::Div5 => 0b100,
 | 
					 | 
				
			||||||
            PLLSrcDiv::Div6 => 0b101,
 | 
					 | 
				
			||||||
            PLLSrcDiv::Div7 => 0b110,
 | 
					 | 
				
			||||||
            PLLSrcDiv::Div8 => 0b111,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl From<PLLSource> for Pllsrc {
 | 
					impl From<PLLSource> for Pllsrc {
 | 
				
			||||||
    fn from(val: PLLSource) -> Pllsrc {
 | 
					    fn from(val: PLLSource) -> Pllsrc {
 | 
				
			||||||
        match val {
 | 
					        match val {
 | 
				
			||||||
@ -179,75 +42,59 @@ impl From<PLLSource> for Pllsrc {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<MSIRange> for Msirange {
 | 
					 | 
				
			||||||
    fn from(val: MSIRange) -> Msirange {
 | 
					 | 
				
			||||||
        match val {
 | 
					 | 
				
			||||||
            MSIRange::Range0 => Msirange::RANGE100K,
 | 
					 | 
				
			||||||
            MSIRange::Range1 => Msirange::RANGE200K,
 | 
					 | 
				
			||||||
            MSIRange::Range2 => Msirange::RANGE400K,
 | 
					 | 
				
			||||||
            MSIRange::Range3 => Msirange::RANGE800K,
 | 
					 | 
				
			||||||
            MSIRange::Range4 => Msirange::RANGE1M,
 | 
					 | 
				
			||||||
            MSIRange::Range5 => Msirange::RANGE2M,
 | 
					 | 
				
			||||||
            MSIRange::Range6 => Msirange::RANGE4M,
 | 
					 | 
				
			||||||
            MSIRange::Range7 => Msirange::RANGE8M,
 | 
					 | 
				
			||||||
            MSIRange::Range8 => Msirange::RANGE16M,
 | 
					 | 
				
			||||||
            MSIRange::Range9 => Msirange::RANGE24M,
 | 
					 | 
				
			||||||
            MSIRange::Range10 => Msirange::RANGE32M,
 | 
					 | 
				
			||||||
            MSIRange::Range11 => Msirange::RANGE48M,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl From<MSIRange> for u32 {
 | 
					 | 
				
			||||||
    fn from(val: MSIRange) -> u32 {
 | 
					 | 
				
			||||||
        match val {
 | 
					 | 
				
			||||||
            MSIRange::Range0 => 100_000,
 | 
					 | 
				
			||||||
            MSIRange::Range1 => 200_000,
 | 
					 | 
				
			||||||
            MSIRange::Range2 => 400_000,
 | 
					 | 
				
			||||||
            MSIRange::Range3 => 800_000,
 | 
					 | 
				
			||||||
            MSIRange::Range4 => 1_000_000,
 | 
					 | 
				
			||||||
            MSIRange::Range5 => 2_000_000,
 | 
					 | 
				
			||||||
            MSIRange::Range6 => 4_000_000,
 | 
					 | 
				
			||||||
            MSIRange::Range7 => 8_000_000,
 | 
					 | 
				
			||||||
            MSIRange::Range8 => 16_000_000,
 | 
					 | 
				
			||||||
            MSIRange::Range9 => 24_000_000,
 | 
					 | 
				
			||||||
            MSIRange::Range10 => 32_000_000,
 | 
					 | 
				
			||||||
            MSIRange::Range11 => 48_000_000,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Clocks configutation
 | 
					/// Clocks configutation
 | 
				
			||||||
pub struct Config {
 | 
					pub struct Config {
 | 
				
			||||||
    pub mux: ClockSrc,
 | 
					    pub mux: ClockSrc,
 | 
				
			||||||
    pub ahb_pre: AHBPrescaler,
 | 
					    pub ahb_pre: AHBPrescaler,
 | 
				
			||||||
    pub apb1_pre: APBPrescaler,
 | 
					    pub apb1_pre: APBPrescaler,
 | 
				
			||||||
    pub apb2_pre: APBPrescaler,
 | 
					    pub apb2_pre: APBPrescaler,
 | 
				
			||||||
    pub pllsai1: Option<(
 | 
					    pub pllsai1: Option<(PllMul, PllPreDiv, Option<PllRDiv>, Option<PllQDiv>, Option<PllPDiv>)>,
 | 
				
			||||||
        PLLMul,
 | 
					 | 
				
			||||||
        PLLSrcDiv,
 | 
					 | 
				
			||||||
        Option<PLLSAI1RDiv>,
 | 
					 | 
				
			||||||
        Option<PLLSAI1QDiv>,
 | 
					 | 
				
			||||||
        Option<PLLSAI1PDiv>,
 | 
					 | 
				
			||||||
    )>,
 | 
					 | 
				
			||||||
    pub hsi48: bool,
 | 
					    pub hsi48: bool,
 | 
				
			||||||
 | 
					    pub rtc_mux: RtcClockSource,
 | 
				
			||||||
 | 
					    pub lse: Option<Hertz>,
 | 
				
			||||||
 | 
					    pub lsi: bool,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Default for Config {
 | 
					impl Default for Config {
 | 
				
			||||||
    #[inline]
 | 
					    #[inline]
 | 
				
			||||||
    fn default() -> Config {
 | 
					    fn default() -> Config {
 | 
				
			||||||
        Config {
 | 
					        Config {
 | 
				
			||||||
            mux: ClockSrc::MSI(MSIRange::Range6),
 | 
					            mux: ClockSrc::MSI(MSIRange::RANGE4M),
 | 
				
			||||||
            ahb_pre: AHBPrescaler::DIV1,
 | 
					            ahb_pre: AHBPrescaler::DIV1,
 | 
				
			||||||
            apb1_pre: APBPrescaler::DIV1,
 | 
					            apb1_pre: APBPrescaler::DIV1,
 | 
				
			||||||
            apb2_pre: APBPrescaler::DIV1,
 | 
					            apb2_pre: APBPrescaler::DIV1,
 | 
				
			||||||
            pllsai1: None,
 | 
					            pllsai1: None,
 | 
				
			||||||
            hsi48: false,
 | 
					            hsi48: false,
 | 
				
			||||||
 | 
					            rtc_mux: RtcClockSource::LSI,
 | 
				
			||||||
 | 
					            lsi: true,
 | 
				
			||||||
 | 
					            lse: None,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub(crate) unsafe fn init(config: Config) {
 | 
					pub(crate) unsafe fn init(config: Config) {
 | 
				
			||||||
 | 
					    // Switch to MSI to prevent problems with PLL configuration.
 | 
				
			||||||
 | 
					    if !RCC.cr().read().msion() {
 | 
				
			||||||
 | 
					        // Turn on MSI and configure it to 4MHz.
 | 
				
			||||||
 | 
					        RCC.cr().modify(|w| {
 | 
				
			||||||
 | 
					            w.set_msirgsel(true); // MSI Range is provided by MSIRANGE[3:0].
 | 
				
			||||||
 | 
					            w.set_msirange(MSIRange::RANGE4M);
 | 
				
			||||||
 | 
					            w.set_msipllen(false);
 | 
				
			||||||
 | 
					            w.set_msion(true)
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Wait until MSI is running
 | 
				
			||||||
 | 
					        while !RCC.cr().read().msirdy() {}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if RCC.cfgr().read().sws() != Sw::MSI {
 | 
				
			||||||
 | 
					        // Set MSI as a clock source, reset prescalers.
 | 
				
			||||||
 | 
					        RCC.cfgr().write_value(Cfgr::default());
 | 
				
			||||||
 | 
					        // Wait for clock switch status bits to change.
 | 
				
			||||||
 | 
					        while RCC.cfgr().read().sws() != Sw::MSI {}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //BackupDomain::configure_ls(config.rtc_mux, config.lsi, config.lse.map(|_| Default::default()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    PWR.cr1().modify(|w| w.set_vos(stm32_metapac::pwr::vals::Vos::RANGE0));
 | 
					    PWR.cr1().modify(|w| w.set_vos(stm32_metapac::pwr::vals::Vos::RANGE0));
 | 
				
			||||||
    let (sys_clk, sw) = match config.mux {
 | 
					    let (sys_clk, sw) = match config.mux {
 | 
				
			||||||
        ClockSrc::MSI(range) => {
 | 
					        ClockSrc::MSI(range) => {
 | 
				
			||||||
@ -255,47 +102,53 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
            RCC.cr().write(|w| {
 | 
					            RCC.cr().write(|w| {
 | 
				
			||||||
                let bits: Msirange = range.into();
 | 
					                let bits: Msirange = range.into();
 | 
				
			||||||
                w.set_msirange(bits);
 | 
					                w.set_msirange(bits);
 | 
				
			||||||
                w.set_msipllen(false);
 | 
					 | 
				
			||||||
                w.set_msirgsel(true);
 | 
					                w.set_msirgsel(true);
 | 
				
			||||||
                w.set_msion(true);
 | 
					                w.set_msion(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if config.rtc_mux == RtcClockSource::LSE {
 | 
				
			||||||
 | 
					                    // If LSE is enabled, enable calibration of MSI
 | 
				
			||||||
 | 
					                    w.set_msipllen(true);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    w.set_msipllen(false);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            while !RCC.cr().read().msirdy() {}
 | 
					            while !RCC.cr().read().msirdy() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Enable as clock source for USB, RNG if running at 48 MHz
 | 
					            // Enable as clock source for USB, RNG if running at 48 MHz
 | 
				
			||||||
            if let MSIRange::Range11 = range {
 | 
					            if range == MSIRange::RANGE48M {
 | 
				
			||||||
                RCC.ccipr1().modify(|w| {
 | 
					                RCC.ccipr1().modify(|w| {
 | 
				
			||||||
                    w.set_clk48msel(0b11);
 | 
					                    w.set_clk48msel(0b11);
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            (range.into(), Sw::MSI)
 | 
					            (msirange_to_hertz(range), Sw::MSI)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        ClockSrc::HSI16 => {
 | 
					        ClockSrc::HSI16 => {
 | 
				
			||||||
            // Enable HSI16
 | 
					            // Enable HSI16
 | 
				
			||||||
            RCC.cr().write(|w| w.set_hsion(true));
 | 
					            RCC.cr().write(|w| w.set_hsion(true));
 | 
				
			||||||
            while !RCC.cr().read().hsirdy() {}
 | 
					            while !RCC.cr().read().hsirdy() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            (HSI_FREQ.0, Sw::HSI16)
 | 
					            (HSI_FREQ, Sw::HSI16)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        ClockSrc::HSE(freq) => {
 | 
					        ClockSrc::HSE(freq) => {
 | 
				
			||||||
            // Enable HSE
 | 
					            // Enable HSE
 | 
				
			||||||
            RCC.cr().write(|w| w.set_hseon(true));
 | 
					            RCC.cr().write(|w| w.set_hseon(true));
 | 
				
			||||||
            while !RCC.cr().read().hserdy() {}
 | 
					            while !RCC.cr().read().hserdy() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            (freq.0, Sw::HSE)
 | 
					            (freq, Sw::HSE)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        ClockSrc::PLL(src, div, prediv, mul, pll48div) => {
 | 
					        ClockSrc::PLL(src, divr, prediv, mul, divq) => {
 | 
				
			||||||
            let src_freq = match src {
 | 
					            let src_freq = match src {
 | 
				
			||||||
                PLLSource::HSE(freq) => {
 | 
					                PLLSource::HSE(freq) => {
 | 
				
			||||||
                    // Enable HSE
 | 
					                    // Enable HSE
 | 
				
			||||||
                    RCC.cr().write(|w| w.set_hseon(true));
 | 
					                    RCC.cr().write(|w| w.set_hseon(true));
 | 
				
			||||||
                    while !RCC.cr().read().hserdy() {}
 | 
					                    while !RCC.cr().read().hserdy() {}
 | 
				
			||||||
                    freq.0
 | 
					                    freq
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                PLLSource::HSI16 => {
 | 
					                PLLSource::HSI16 => {
 | 
				
			||||||
                    // Enable HSI
 | 
					                    // Enable HSI
 | 
				
			||||||
                    RCC.cr().write(|w| w.set_hsion(true));
 | 
					                    RCC.cr().write(|w| w.set_hsion(true));
 | 
				
			||||||
                    while !RCC.cr().read().hsirdy() {}
 | 
					                    while !RCC.cr().read().hsirdy() {}
 | 
				
			||||||
                    HSI_FREQ.0
 | 
					                    HSI_FREQ
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                PLLSource::MSI(range) => {
 | 
					                PLLSource::MSI(range) => {
 | 
				
			||||||
                    // Enable MSI
 | 
					                    // Enable MSI
 | 
				
			||||||
@ -307,7 +160,8 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
                        w.set_msion(true);
 | 
					                        w.set_msion(true);
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    while !RCC.cr().read().msirdy() {}
 | 
					                    while !RCC.cr().read().msirdy() {}
 | 
				
			||||||
                    range.into()
 | 
					
 | 
				
			||||||
 | 
					                    msirange_to_hertz(range)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -315,23 +169,23 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
            RCC.cr().modify(|w| w.set_pllon(false));
 | 
					            RCC.cr().modify(|w| w.set_pllon(false));
 | 
				
			||||||
            while RCC.cr().read().pllrdy() {}
 | 
					            while RCC.cr().read().pllrdy() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let freq = (src_freq / prediv.to_div() * mul.to_mul()) / div.to_div();
 | 
					            let freq = src_freq / prediv * mul / divr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            RCC.pllcfgr().write(move |w| {
 | 
					            RCC.pllcfgr().write(move |w| {
 | 
				
			||||||
                w.set_plln(mul.into());
 | 
					                w.set_plln(mul);
 | 
				
			||||||
                w.set_pllm(prediv.into());
 | 
					                w.set_pllm(prediv);
 | 
				
			||||||
                w.set_pllr(div.into());
 | 
					                w.set_pllr(divr);
 | 
				
			||||||
                if let Some(pll48div) = pll48div {
 | 
					                if let Some(divq) = divq {
 | 
				
			||||||
                    w.set_pllq(pll48div.into());
 | 
					                    w.set_pllq(divq);
 | 
				
			||||||
                    w.set_pllqen(true);
 | 
					                    w.set_pllqen(true);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                w.set_pllsrc(src.into());
 | 
					                w.set_pllsrc(src.into());
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Enable as clock source for USB, RNG if PLL48 divisor is provided
 | 
					            // Enable as clock source for USB, RNG if PLL48 divisor is provided
 | 
				
			||||||
            if let Some(pll48div) = pll48div {
 | 
					            if let Some(divq) = divq {
 | 
				
			||||||
                let freq = (src_freq / prediv.to_div() * mul.to_mul()) / pll48div.to_div();
 | 
					                let freq = src_freq / prediv * mul / divq;
 | 
				
			||||||
                assert!(freq == 48_000_000);
 | 
					                assert!(freq.0 == 48_000_000);
 | 
				
			||||||
                RCC.ccipr1().modify(|w| {
 | 
					                RCC.ccipr1().modify(|w| {
 | 
				
			||||||
                    w.set_clk48msel(0b10);
 | 
					                    w.set_clk48msel(0b10);
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
@ -339,25 +193,25 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if let Some((mul, prediv, r_div, q_div, p_div)) = config.pllsai1 {
 | 
					            if let Some((mul, prediv, r_div, q_div, p_div)) = config.pllsai1 {
 | 
				
			||||||
                RCC.pllsai1cfgr().write(move |w| {
 | 
					                RCC.pllsai1cfgr().write(move |w| {
 | 
				
			||||||
                    w.set_pllsai1n(mul.into());
 | 
					                    w.set_plln(mul);
 | 
				
			||||||
                    w.set_pllsai1m(prediv.into());
 | 
					                    w.set_pllm(prediv);
 | 
				
			||||||
                    if let Some(r_div) = r_div {
 | 
					                    if let Some(r_div) = r_div {
 | 
				
			||||||
                        w.set_pllsai1r(r_div.into());
 | 
					                        w.set_pllr(r_div);
 | 
				
			||||||
                        w.set_pllsai1ren(true);
 | 
					                        w.set_pllren(true);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    if let Some(q_div) = q_div {
 | 
					                    if let Some(q_div) = q_div {
 | 
				
			||||||
                        w.set_pllsai1q(q_div.into());
 | 
					                        w.set_pllq(q_div);
 | 
				
			||||||
                        w.set_pllsai1qen(true);
 | 
					                        w.set_pllqen(true);
 | 
				
			||||||
                        let freq = (src_freq / prediv.to_div() * mul.to_mul()) / q_div.to_div();
 | 
					                        let freq = src_freq / prediv * mul / q_div;
 | 
				
			||||||
                        if freq == 48_000_000 {
 | 
					                        if freq.0 == 48_000_000 {
 | 
				
			||||||
                            RCC.ccipr1().modify(|w| {
 | 
					                            RCC.ccipr1().modify(|w| {
 | 
				
			||||||
                                w.set_clk48msel(0b1);
 | 
					                                w.set_clk48msel(0b1);
 | 
				
			||||||
                            });
 | 
					                            });
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    if let Some(p_div) = p_div {
 | 
					                    if let Some(p_div) = p_div {
 | 
				
			||||||
                        w.set_pllsai1pdiv(p_div.into());
 | 
					                        w.set_pllp(p_div);
 | 
				
			||||||
                        w.set_pllsai1pen(true);
 | 
					                        w.set_pllpen(true);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -384,7 +238,7 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
    // Set flash wait states
 | 
					    // Set flash wait states
 | 
				
			||||||
    // VCORE Range 0 (performance), others TODO
 | 
					    // VCORE Range 0 (performance), others TODO
 | 
				
			||||||
    FLASH.acr().modify(|w| {
 | 
					    FLASH.acr().modify(|w| {
 | 
				
			||||||
        w.set_latency(match sys_clk {
 | 
					        w.set_latency(match sys_clk.0 {
 | 
				
			||||||
            0..=20_000_000 => 0,
 | 
					            0..=20_000_000 => 0,
 | 
				
			||||||
            0..=40_000_000 => 1,
 | 
					            0..=40_000_000 => 1,
 | 
				
			||||||
            0..=60_000_000 => 2,
 | 
					            0..=60_000_000 => 2,
 | 
				
			||||||
@ -401,43 +255,50 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
        w.set_ppre2(config.apb2_pre.into());
 | 
					        w.set_ppre2(config.apb2_pre.into());
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let ahb_freq: u32 = match config.ahb_pre {
 | 
					    let ahb_freq = sys_clk / config.ahb_pre;
 | 
				
			||||||
        AHBPrescaler::DIV1 => sys_clk,
 | 
					 | 
				
			||||||
        pre => {
 | 
					 | 
				
			||||||
            let pre: Hpre = pre.into();
 | 
					 | 
				
			||||||
            let pre = 1 << (pre.to_bits() as u32 - 7);
 | 
					 | 
				
			||||||
            sys_clk / pre
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
 | 
					    let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
 | 
				
			||||||
        APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
 | 
					        APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
 | 
				
			||||||
        pre => {
 | 
					        pre => {
 | 
				
			||||||
            let pre: Ppre = pre.into();
 | 
					            let freq = ahb_freq / pre;
 | 
				
			||||||
            let pre: u8 = 1 << (pre.to_bits() - 3);
 | 
					            (freq, freq * 2u32)
 | 
				
			||||||
            let freq = ahb_freq / pre as u32;
 | 
					 | 
				
			||||||
            (freq, freq * 2)
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
 | 
					    let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
 | 
				
			||||||
        APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
 | 
					        APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
 | 
				
			||||||
        pre => {
 | 
					        pre => {
 | 
				
			||||||
            let pre: Ppre = pre.into();
 | 
					            let freq = ahb_freq / pre;
 | 
				
			||||||
            let pre: u8 = 1 << (pre.to_bits() - 3);
 | 
					            (freq, freq * 2u32)
 | 
				
			||||||
            let freq = ahb_freq / pre as u32;
 | 
					 | 
				
			||||||
            (freq, freq * 2)
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    set_freqs(Clocks {
 | 
					    set_freqs(Clocks {
 | 
				
			||||||
        sys: Hertz(sys_clk),
 | 
					        sys: sys_clk,
 | 
				
			||||||
        ahb1: Hertz(ahb_freq),
 | 
					        ahb1: ahb_freq,
 | 
				
			||||||
        ahb2: Hertz(ahb_freq),
 | 
					        ahb2: ahb_freq,
 | 
				
			||||||
        ahb3: Hertz(ahb_freq),
 | 
					        ahb3: ahb_freq,
 | 
				
			||||||
        apb1: Hertz(apb1_freq),
 | 
					        apb1: apb1_freq,
 | 
				
			||||||
        apb2: Hertz(apb2_freq),
 | 
					        apb2: apb2_freq,
 | 
				
			||||||
        apb1_tim: Hertz(apb1_tim_freq),
 | 
					        apb1_tim: apb1_tim_freq,
 | 
				
			||||||
        apb2_tim: Hertz(apb2_tim_freq),
 | 
					        apb2_tim: apb2_tim_freq,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn msirange_to_hertz(range: Msirange) -> Hertz {
 | 
				
			||||||
 | 
					    match range {
 | 
				
			||||||
 | 
					        MSIRange::RANGE100K => Hertz(100_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE200K => Hertz(200_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE400K => Hertz(400_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE800K => Hertz(800_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE1M => Hertz(1_000_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE2M => Hertz(2_000_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE4M => Hertz(4_000_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE8M => Hertz(8_000_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE16M => Hertz(16_000_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE24M => Hertz(24_000_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE32M => Hertz(32_000_000),
 | 
				
			||||||
 | 
					        MSIRange::RANGE48M => Hertz(48_000_000),
 | 
				
			||||||
 | 
					        _ => unreachable!(),
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,6 @@ pub use crate::rcc::bd::RtcClockSource;
 | 
				
			|||||||
use crate::time::Hertz;
 | 
					use crate::time::Hertz;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub(crate) mod bd;
 | 
					pub(crate) mod bd;
 | 
				
			||||||
mod bus;
 | 
					 | 
				
			||||||
mod mco;
 | 
					mod mco;
 | 
				
			||||||
pub use mco::*;
 | 
					pub use mco::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,5 @@
 | 
				
			|||||||
use stm32_metapac::rcc::vals::{Msirange, Msirgsel, Pllm, Pllmboost, Pllrge, Pllsrc, Sw};
 | 
					pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Msirange, Plldiv, Pllm, Plln, Ppre as APBPrescaler};
 | 
				
			||||||
 | 
					use crate::pac::rcc::vals::{Msirgsel, Pllmboost, Pllrge, Pllsrc, Sw};
 | 
				
			||||||
pub use super::bus::{AHBPrescaler, APBPrescaler};
 | 
					 | 
				
			||||||
use crate::pac::{FLASH, PWR, RCC};
 | 
					use crate::pac::{FLASH, PWR, RCC};
 | 
				
			||||||
use crate::rcc::{set_freqs, Clocks};
 | 
					use crate::rcc::{set_freqs, Clocks};
 | 
				
			||||||
use crate::time::Hertz;
 | 
					use crate::time::Hertz;
 | 
				
			||||||
@ -16,7 +15,7 @@ pub use crate::pac::pwr::vals::Vos as VoltageScale;
 | 
				
			|||||||
#[derive(Copy, Clone)]
 | 
					#[derive(Copy, Clone)]
 | 
				
			||||||
pub enum ClockSrc {
 | 
					pub enum ClockSrc {
 | 
				
			||||||
    /// Use an internal medium speed oscillator (MSIS) as the system clock.
 | 
					    /// Use an internal medium speed oscillator (MSIS) as the system clock.
 | 
				
			||||||
    MSI(MSIRange),
 | 
					    MSI(Msirange),
 | 
				
			||||||
    /// Use the external high speed clock as the system clock.
 | 
					    /// Use the external high speed clock as the system clock.
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// HSE clocks faster than 25 MHz require at least `VoltageScale::RANGE3`, and HSE clocks must
 | 
					    /// HSE clocks faster than 25 MHz require at least `VoltageScale::RANGE3`, and HSE clocks must
 | 
				
			||||||
@ -31,29 +30,29 @@ pub enum ClockSrc {
 | 
				
			|||||||
impl Default for ClockSrc {
 | 
					impl Default for ClockSrc {
 | 
				
			||||||
    fn default() -> Self {
 | 
					    fn default() -> Self {
 | 
				
			||||||
        // The default system clock source is MSIS @ 4 MHz, per RM0456 § 11.4.9
 | 
					        // The default system clock source is MSIS @ 4 MHz, per RM0456 § 11.4.9
 | 
				
			||||||
        ClockSrc::MSI(MSIRange::Range4mhz)
 | 
					        ClockSrc::MSI(Msirange::RANGE_4MHZ)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Clone, Copy, Debug)]
 | 
					#[derive(Clone, Copy)]
 | 
				
			||||||
pub struct PllConfig {
 | 
					pub struct PllConfig {
 | 
				
			||||||
    /// The clock source for the PLL.
 | 
					    /// The clock source for the PLL.
 | 
				
			||||||
    pub source: PllSrc,
 | 
					    pub source: PllSrc,
 | 
				
			||||||
    /// The PLL prescaler.
 | 
					    /// The PLL prescaler.
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// The clock speed of the `source` divided by `m` must be between 4 and 16 MHz.
 | 
					    /// The clock speed of the `source` divided by `m` must be between 4 and 16 MHz.
 | 
				
			||||||
    pub m: PllM,
 | 
					    pub m: Pllm,
 | 
				
			||||||
    /// The PLL multiplier.
 | 
					    /// The PLL multiplier.
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// The multiplied clock – `source` divided by `m` times `n` – must be between 128 and 544
 | 
					    /// The multiplied clock – `source` divided by `m` times `n` – must be between 128 and 544
 | 
				
			||||||
    /// MHz. The upper limit may be lower depending on the `Config { voltage_range }`.
 | 
					    /// MHz. The upper limit may be lower depending on the `Config { voltage_range }`.
 | 
				
			||||||
    pub n: PllN,
 | 
					    pub n: Plln,
 | 
				
			||||||
    /// The divider for the R output.
 | 
					    /// The divider for the R output.
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// When used to drive the system clock, `source` divided by `m` times `n` divided by `r`
 | 
					    /// When used to drive the system clock, `source` divided by `m` times `n` divided by `r`
 | 
				
			||||||
    /// must not exceed 160 MHz. System clocks above 55 MHz require a non-default
 | 
					    /// must not exceed 160 MHz. System clocks above 55 MHz require a non-default
 | 
				
			||||||
    /// `Config { voltage_range }`.
 | 
					    /// `Config { voltage_range }`.
 | 
				
			||||||
    pub r: PllClkDiv,
 | 
					    pub r: Plldiv,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl PllConfig {
 | 
					impl PllConfig {
 | 
				
			||||||
@ -61,27 +60,27 @@ impl PllConfig {
 | 
				
			|||||||
    pub const fn hsi16_160mhz() -> Self {
 | 
					    pub const fn hsi16_160mhz() -> Self {
 | 
				
			||||||
        PllConfig {
 | 
					        PllConfig {
 | 
				
			||||||
            source: PllSrc::HSI16,
 | 
					            source: PllSrc::HSI16,
 | 
				
			||||||
            m: PllM::NotDivided,
 | 
					            m: Pllm::DIV1,
 | 
				
			||||||
            n: PllN::Mul10,
 | 
					            n: Plln::MUL10,
 | 
				
			||||||
            r: PllClkDiv::NotDivided,
 | 
					            r: Plldiv::DIV1,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// A configuration for MSIS @ 48 MHz / 3 * 10 / 1 = 160 MHz
 | 
					    /// A configuration for MSIS @ 48 MHz / 3 * 10 / 1 = 160 MHz
 | 
				
			||||||
    pub const fn msis_160mhz() -> Self {
 | 
					    pub const fn msis_160mhz() -> Self {
 | 
				
			||||||
        PllConfig {
 | 
					        PllConfig {
 | 
				
			||||||
            source: PllSrc::MSIS(MSIRange::Range48mhz),
 | 
					            source: PllSrc::MSIS(Msirange::RANGE_48MHZ),
 | 
				
			||||||
            m: PllM::Div3,
 | 
					            m: Pllm::DIV3,
 | 
				
			||||||
            n: PllN::Mul10,
 | 
					            n: Plln::MUL10,
 | 
				
			||||||
            r: PllClkDiv::NotDivided,
 | 
					            r: Plldiv::DIV1,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Clone, Copy, Debug)]
 | 
					#[derive(Clone, Copy)]
 | 
				
			||||||
pub enum PllSrc {
 | 
					pub enum PllSrc {
 | 
				
			||||||
    /// Use an internal medium speed oscillator as the PLL source.
 | 
					    /// Use an internal medium speed oscillator as the PLL source.
 | 
				
			||||||
    MSIS(MSIRange),
 | 
					    MSIS(Msirange),
 | 
				
			||||||
    /// Use the external high speed clock as the system PLL source.
 | 
					    /// Use the external high speed clock as the system PLL source.
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// HSE clocks faster than 25 MHz require at least `VoltageScale::RANGE3`, and HSE clocks must
 | 
					    /// HSE clocks faster than 25 MHz require at least `VoltageScale::RANGE3`, and HSE clocks must
 | 
				
			||||||
@ -101,75 +100,6 @@ impl Into<Pllsrc> for PllSrc {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
seq_macro::seq!(N in 2..=128 {
 | 
					 | 
				
			||||||
    #[derive(Copy, Clone, Debug)]
 | 
					 | 
				
			||||||
    pub enum PllClkDiv {
 | 
					 | 
				
			||||||
        NotDivided = 1,
 | 
					 | 
				
			||||||
        #(
 | 
					 | 
				
			||||||
            Div~N = N,
 | 
					 | 
				
			||||||
        )*
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    impl PllClkDiv {
 | 
					 | 
				
			||||||
        fn to_div(&self) -> u8 {
 | 
					 | 
				
			||||||
            match self {
 | 
					 | 
				
			||||||
                PllClkDiv::NotDivided => 0,
 | 
					 | 
				
			||||||
                #(
 | 
					 | 
				
			||||||
                    PllClkDiv::Div~N => N - 1,
 | 
					 | 
				
			||||||
                )*
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
seq_macro::seq!(N in 4..=512 {
 | 
					 | 
				
			||||||
    #[derive(Copy, Clone, Debug)]
 | 
					 | 
				
			||||||
    pub enum PllN {
 | 
					 | 
				
			||||||
        NotMultiplied = 1,
 | 
					 | 
				
			||||||
        #(
 | 
					 | 
				
			||||||
            Mul~N = N,
 | 
					 | 
				
			||||||
        )*
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    impl PllN {
 | 
					 | 
				
			||||||
        fn to_mul(&self) -> u16 {
 | 
					 | 
				
			||||||
            match self {
 | 
					 | 
				
			||||||
                PllN::NotMultiplied => 0,
 | 
					 | 
				
			||||||
                #(
 | 
					 | 
				
			||||||
                    PllN::Mul~N => N - 1,
 | 
					 | 
				
			||||||
                )*
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Pre-division
 | 
					 | 
				
			||||||
#[derive(Copy, Clone, Debug)]
 | 
					 | 
				
			||||||
pub enum PllM {
 | 
					 | 
				
			||||||
    NotDivided = 0b0000,
 | 
					 | 
				
			||||||
    Div2 = 0b0001,
 | 
					 | 
				
			||||||
    Div3 = 0b0010,
 | 
					 | 
				
			||||||
    Div4 = 0b0011,
 | 
					 | 
				
			||||||
    Div5 = 0b0100,
 | 
					 | 
				
			||||||
    Div6 = 0b0101,
 | 
					 | 
				
			||||||
    Div7 = 0b0110,
 | 
					 | 
				
			||||||
    Div8 = 0b0111,
 | 
					 | 
				
			||||||
    Div9 = 0b1000,
 | 
					 | 
				
			||||||
    Div10 = 0b1001,
 | 
					 | 
				
			||||||
    Div11 = 0b1010,
 | 
					 | 
				
			||||||
    Div12 = 0b1011,
 | 
					 | 
				
			||||||
    Div13 = 0b1100,
 | 
					 | 
				
			||||||
    Div14 = 0b1101,
 | 
					 | 
				
			||||||
    Div15 = 0b1110,
 | 
					 | 
				
			||||||
    Div16 = 0b1111,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Into<Pllm> for PllM {
 | 
					 | 
				
			||||||
    fn into(self) -> Pllm {
 | 
					 | 
				
			||||||
        Pllm::from_bits(self as u8)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Into<Sw> for ClockSrc {
 | 
					impl Into<Sw> for ClockSrc {
 | 
				
			||||||
    fn into(self) -> Sw {
 | 
					    fn into(self) -> Sw {
 | 
				
			||||||
        match self {
 | 
					        match self {
 | 
				
			||||||
@ -181,56 +111,6 @@ impl Into<Sw> for ClockSrc {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Copy, Clone)]
 | 
					 | 
				
			||||||
pub enum MSIRange {
 | 
					 | 
				
			||||||
    /// The 48 MHz MSI speed is unavailable in `VoltageScale::RANGE4`.
 | 
					 | 
				
			||||||
    Range48mhz = 48_000_000,
 | 
					 | 
				
			||||||
    Range24mhz = 24_000_000,
 | 
					 | 
				
			||||||
    Range16mhz = 16_000_000,
 | 
					 | 
				
			||||||
    Range12mhz = 12_000_000,
 | 
					 | 
				
			||||||
    Range4mhz = 4_000_000,
 | 
					 | 
				
			||||||
    Range2mhz = 2_000_000,
 | 
					 | 
				
			||||||
    Range1_33mhz = 1_330_000,
 | 
					 | 
				
			||||||
    Range1mhz = 1_000_000,
 | 
					 | 
				
			||||||
    Range3_072mhz = 3_072_000,
 | 
					 | 
				
			||||||
    Range1_536mhz = 1_536_000,
 | 
					 | 
				
			||||||
    Range1_024mhz = 1_024_000,
 | 
					 | 
				
			||||||
    Range768khz = 768_000,
 | 
					 | 
				
			||||||
    Range400khz = 400_000,
 | 
					 | 
				
			||||||
    Range200khz = 200_000,
 | 
					 | 
				
			||||||
    Range133khz = 133_000,
 | 
					 | 
				
			||||||
    Range100khz = 100_000,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Into<u32> for MSIRange {
 | 
					 | 
				
			||||||
    fn into(self) -> u32 {
 | 
					 | 
				
			||||||
        self as u32
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Into<Msirange> for MSIRange {
 | 
					 | 
				
			||||||
    fn into(self) -> Msirange {
 | 
					 | 
				
			||||||
        match self {
 | 
					 | 
				
			||||||
            MSIRange::Range48mhz => Msirange::RANGE_48MHZ,
 | 
					 | 
				
			||||||
            MSIRange::Range24mhz => Msirange::RANGE_24MHZ,
 | 
					 | 
				
			||||||
            MSIRange::Range16mhz => Msirange::RANGE_16MHZ,
 | 
					 | 
				
			||||||
            MSIRange::Range12mhz => Msirange::RANGE_12MHZ,
 | 
					 | 
				
			||||||
            MSIRange::Range4mhz => Msirange::RANGE_4MHZ,
 | 
					 | 
				
			||||||
            MSIRange::Range2mhz => Msirange::RANGE_2MHZ,
 | 
					 | 
				
			||||||
            MSIRange::Range1_33mhz => Msirange::RANGE_1_33MHZ,
 | 
					 | 
				
			||||||
            MSIRange::Range1mhz => Msirange::RANGE_1MHZ,
 | 
					 | 
				
			||||||
            MSIRange::Range3_072mhz => Msirange::RANGE_3_072MHZ,
 | 
					 | 
				
			||||||
            MSIRange::Range1_536mhz => Msirange::RANGE_1_536MHZ,
 | 
					 | 
				
			||||||
            MSIRange::Range1_024mhz => Msirange::RANGE_1_024MHZ,
 | 
					 | 
				
			||||||
            MSIRange::Range768khz => Msirange::RANGE_768KHZ,
 | 
					 | 
				
			||||||
            MSIRange::Range400khz => Msirange::RANGE_400KHZ,
 | 
					 | 
				
			||||||
            MSIRange::Range200khz => Msirange::RANGE_200KHZ,
 | 
					 | 
				
			||||||
            MSIRange::Range133khz => Msirange::RANGE_133KHZ,
 | 
					 | 
				
			||||||
            MSIRange::Range100khz => Msirange::RANGE_100KHZ,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Copy, Clone)]
 | 
					#[derive(Copy, Clone)]
 | 
				
			||||||
pub struct Config {
 | 
					pub struct Config {
 | 
				
			||||||
    pub mux: ClockSrc,
 | 
					    pub mux: ClockSrc,
 | 
				
			||||||
@ -273,11 +153,11 @@ impl Config {
 | 
				
			|||||||
        frequency
 | 
					        frequency
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    unsafe fn init_msis(&self, range: MSIRange) -> Hertz {
 | 
					    unsafe fn init_msis(&self, range: Msirange) -> Hertz {
 | 
				
			||||||
        // Check MSI output per RM0456 § 11.4.10
 | 
					        // Check MSI output per RM0456 § 11.4.10
 | 
				
			||||||
        match self.voltage_range {
 | 
					        match self.voltage_range {
 | 
				
			||||||
            VoltageScale::RANGE4 => {
 | 
					            VoltageScale::RANGE4 => {
 | 
				
			||||||
                assert!(range as u32 <= 24_000_000);
 | 
					                assert!(msirange_to_hertz(range).0 <= 24_000_000);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            _ => {}
 | 
					            _ => {}
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -291,8 +171,7 @@ impl Config {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        RCC.icscr1().modify(|w| {
 | 
					        RCC.icscr1().modify(|w| {
 | 
				
			||||||
            let bits: Msirange = range.into();
 | 
					            w.set_msisrange(range);
 | 
				
			||||||
            w.set_msisrange(bits);
 | 
					 | 
				
			||||||
            w.set_msirgsel(Msirgsel::RCC_ICSCR1);
 | 
					            w.set_msirgsel(Msirgsel::RCC_ICSCR1);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        RCC.cr().write(|w| {
 | 
					        RCC.cr().write(|w| {
 | 
				
			||||||
@ -300,7 +179,7 @@ impl Config {
 | 
				
			|||||||
            w.set_msison(true);
 | 
					            w.set_msison(true);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        while !RCC.cr().read().msisrdy() {}
 | 
					        while !RCC.cr().read().msisrdy() {}
 | 
				
			||||||
        Hertz(range as u32)
 | 
					        msirange_to_hertz(range)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -344,14 +223,14 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Calculate the reference clock, which is the source divided by m
 | 
					            // Calculate the reference clock, which is the source divided by m
 | 
				
			||||||
            let reference_clk = source_clk / (pll.m as u8 as u32 + 1);
 | 
					            let reference_clk = source_clk / pll.m;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Check limits per RM0456 § 11.4.6
 | 
					            // Check limits per RM0456 § 11.4.6
 | 
				
			||||||
            assert!(Hertz::mhz(4) <= reference_clk && reference_clk <= Hertz::mhz(16));
 | 
					            assert!(Hertz::mhz(4) <= reference_clk && reference_clk <= Hertz::mhz(16));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Calculate the PLL1 VCO clock and PLL1 R output clock
 | 
					            // Calculate the PLL1 VCO clock and PLL1 R output clock
 | 
				
			||||||
            let pll1_clk = reference_clk * (pll.n as u8 as u32);
 | 
					            let pll1_clk = reference_clk * pll.n;
 | 
				
			||||||
            let pll1r_clk = pll1_clk / (pll.r as u8 as u32);
 | 
					            let pll1r_clk = pll1_clk / pll.r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Check system clock per RM0456 § 11.4.9
 | 
					            // Check system clock per RM0456 § 11.4.9
 | 
				
			||||||
            assert!(pll1r_clk <= Hertz::mhz(160));
 | 
					            assert!(pll1r_clk <= Hertz::mhz(160));
 | 
				
			||||||
@ -387,11 +266,11 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
                    Pllmboost::DIV2
 | 
					                    Pllmboost::DIV2
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    // Bypass, giving EPOD 4-16 MHz
 | 
					                    // Bypass, giving EPOD 4-16 MHz
 | 
				
			||||||
                    Pllmboost::BYPASS
 | 
					                    Pllmboost::DIV1
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                // Nothing to do
 | 
					                // Nothing to do
 | 
				
			||||||
                Pllmboost::BYPASS
 | 
					                Pllmboost::DIV1
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Disable the PLL, and wait for it to disable
 | 
					            // Disable the PLL, and wait for it to disable
 | 
				
			||||||
@ -402,7 +281,7 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
            RCC.pll1cfgr().write(|w| {
 | 
					            RCC.pll1cfgr().write(|w| {
 | 
				
			||||||
                // Configure PLL1 source and prescaler
 | 
					                // Configure PLL1 source and prescaler
 | 
				
			||||||
                w.set_pllsrc(pll.source.into());
 | 
					                w.set_pllsrc(pll.source.into());
 | 
				
			||||||
                w.set_pllm(pll.m.into());
 | 
					                w.set_pllm(pll.m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Configure PLL1 input frequncy range
 | 
					                // Configure PLL1 input frequncy range
 | 
				
			||||||
                let input_range = if reference_clk <= Hertz::mhz(8) {
 | 
					                let input_range = if reference_clk <= Hertz::mhz(8) {
 | 
				
			||||||
@ -422,9 +301,9 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
            // Configure the PLL divisors
 | 
					            // Configure the PLL divisors
 | 
				
			||||||
            RCC.pll1divr().modify(|w| {
 | 
					            RCC.pll1divr().modify(|w| {
 | 
				
			||||||
                // Set the VCO multiplier
 | 
					                // Set the VCO multiplier
 | 
				
			||||||
                w.set_plln(pll.n.to_mul());
 | 
					                w.set_plln(pll.n);
 | 
				
			||||||
                // Set the R output divisor
 | 
					                // Set the R output divisor
 | 
				
			||||||
                w.set_pllr(pll.r.to_div());
 | 
					                w.set_pllr(pll.r);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Do we need the EPOD booster to reach the target clock speed per § 10.5.4?
 | 
					            // Do we need the EPOD booster to reach the target clock speed per § 10.5.4?
 | 
				
			||||||
@ -442,8 +321,7 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            pll1r_clk
 | 
					            pll1r_clk
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
    .0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if config.hsi48 {
 | 
					    if config.hsi48 {
 | 
				
			||||||
        RCC.cr().modify(|w| w.set_hsi48on(true));
 | 
					        RCC.cr().modify(|w| w.set_hsi48on(true));
 | 
				
			||||||
@ -455,13 +333,13 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
    let wait_states = match config.voltage_range {
 | 
					    let wait_states = match config.voltage_range {
 | 
				
			||||||
        // VOS 1 range VCORE 1.26V - 1.40V
 | 
					        // VOS 1 range VCORE 1.26V - 1.40V
 | 
				
			||||||
        VoltageScale::RANGE1 => {
 | 
					        VoltageScale::RANGE1 => {
 | 
				
			||||||
            if sys_clk < 32_000_000 {
 | 
					            if sys_clk.0 < 32_000_000 {
 | 
				
			||||||
                0
 | 
					                0
 | 
				
			||||||
            } else if sys_clk < 64_000_000 {
 | 
					            } else if sys_clk.0 < 64_000_000 {
 | 
				
			||||||
                1
 | 
					                1
 | 
				
			||||||
            } else if sys_clk < 96_000_000 {
 | 
					            } else if sys_clk.0 < 96_000_000 {
 | 
				
			||||||
                2
 | 
					                2
 | 
				
			||||||
            } else if sys_clk < 128_000_000 {
 | 
					            } else if sys_clk.0 < 128_000_000 {
 | 
				
			||||||
                3
 | 
					                3
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                4
 | 
					                4
 | 
				
			||||||
@ -469,11 +347,11 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        // VOS 2 range VCORE 1.15V - 1.26V
 | 
					        // VOS 2 range VCORE 1.15V - 1.26V
 | 
				
			||||||
        VoltageScale::RANGE2 => {
 | 
					        VoltageScale::RANGE2 => {
 | 
				
			||||||
            if sys_clk < 30_000_000 {
 | 
					            if sys_clk.0 < 30_000_000 {
 | 
				
			||||||
                0
 | 
					                0
 | 
				
			||||||
            } else if sys_clk < 60_000_000 {
 | 
					            } else if sys_clk.0 < 60_000_000 {
 | 
				
			||||||
                1
 | 
					                1
 | 
				
			||||||
            } else if sys_clk < 90_000_000 {
 | 
					            } else if sys_clk.0 < 90_000_000 {
 | 
				
			||||||
                2
 | 
					                2
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                3
 | 
					                3
 | 
				
			||||||
@ -481,9 +359,9 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        // VOS 3 range VCORE 1.05V - 1.15V
 | 
					        // VOS 3 range VCORE 1.05V - 1.15V
 | 
				
			||||||
        VoltageScale::RANGE3 => {
 | 
					        VoltageScale::RANGE3 => {
 | 
				
			||||||
            if sys_clk < 24_000_000 {
 | 
					            if sys_clk.0 < 24_000_000 {
 | 
				
			||||||
                0
 | 
					                0
 | 
				
			||||||
            } else if sys_clk < 48_000_000 {
 | 
					            } else if sys_clk.0 < 48_000_000 {
 | 
				
			||||||
                1
 | 
					                1
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                2
 | 
					                2
 | 
				
			||||||
@ -491,7 +369,7 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        // VOS 4 range VCORE 0.95V - 1.05V
 | 
					        // VOS 4 range VCORE 0.95V - 1.05V
 | 
				
			||||||
        VoltageScale::RANGE4 => {
 | 
					        VoltageScale::RANGE4 => {
 | 
				
			||||||
            if sys_clk < 12_000_000 {
 | 
					            if sys_clk.0 < 12_000_000 {
 | 
				
			||||||
                0
 | 
					                0
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                1
 | 
					                1
 | 
				
			||||||
@ -522,62 +400,70 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Configure the bus prescalers
 | 
					    // Configure the bus prescalers
 | 
				
			||||||
    RCC.cfgr2().modify(|w| {
 | 
					    RCC.cfgr2().modify(|w| {
 | 
				
			||||||
        w.set_hpre(config.ahb_pre.into());
 | 
					        w.set_hpre(config.ahb_pre);
 | 
				
			||||||
        w.set_ppre1(config.apb1_pre.into());
 | 
					        w.set_ppre1(config.apb1_pre);
 | 
				
			||||||
        w.set_ppre2(config.apb2_pre.into());
 | 
					        w.set_ppre2(config.apb2_pre);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    RCC.cfgr3().modify(|w| {
 | 
					    RCC.cfgr3().modify(|w| {
 | 
				
			||||||
        w.set_ppre3(config.apb3_pre.into());
 | 
					        w.set_ppre3(config.apb3_pre);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let ahb_freq: u32 = match config.ahb_pre {
 | 
					    let ahb_freq = sys_clk / config.ahb_pre;
 | 
				
			||||||
        AHBPrescaler::DIV1 => sys_clk,
 | 
					 | 
				
			||||||
        pre => {
 | 
					 | 
				
			||||||
            let pre: u8 = pre.into();
 | 
					 | 
				
			||||||
            let pre = 1 << (pre as u32 - 7);
 | 
					 | 
				
			||||||
            sys_clk / pre
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
 | 
					    let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
 | 
				
			||||||
        APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
 | 
					        APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
 | 
				
			||||||
        pre => {
 | 
					        pre => {
 | 
				
			||||||
            let pre: u8 = pre.into();
 | 
					            let freq = ahb_freq / pre;
 | 
				
			||||||
            let pre: u8 = 1 << (pre - 3);
 | 
					            (freq, freq * 2u32)
 | 
				
			||||||
            let freq = ahb_freq / pre as u32;
 | 
					 | 
				
			||||||
            (freq, freq * 2)
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
 | 
					    let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
 | 
				
			||||||
        APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
 | 
					        APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
 | 
				
			||||||
        pre => {
 | 
					        pre => {
 | 
				
			||||||
            let pre: u8 = pre.into();
 | 
					            let freq = ahb_freq / pre;
 | 
				
			||||||
            let pre: u8 = 1 << (pre - 3);
 | 
					            (freq, freq * 2u32)
 | 
				
			||||||
            let freq = ahb_freq / pre as u32;
 | 
					 | 
				
			||||||
            (freq, freq * 2)
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let (apb3_freq, _apb3_tim_freq) = match config.apb3_pre {
 | 
					    let (apb3_freq, _apb3_tim_freq) = match config.apb3_pre {
 | 
				
			||||||
        APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
 | 
					        APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
 | 
				
			||||||
        pre => {
 | 
					        pre => {
 | 
				
			||||||
            let pre: u8 = pre.into();
 | 
					            let freq = ahb_freq / pre;
 | 
				
			||||||
            let pre: u8 = 1 << (pre - 3);
 | 
					            (freq, freq * 2u32)
 | 
				
			||||||
            let freq = ahb_freq / pre as u32;
 | 
					 | 
				
			||||||
            (freq, freq * 2)
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    set_freqs(Clocks {
 | 
					    set_freqs(Clocks {
 | 
				
			||||||
        sys: Hertz(sys_clk),
 | 
					        sys: sys_clk,
 | 
				
			||||||
        ahb1: Hertz(ahb_freq),
 | 
					        ahb1: ahb_freq,
 | 
				
			||||||
        ahb2: Hertz(ahb_freq),
 | 
					        ahb2: ahb_freq,
 | 
				
			||||||
        ahb3: Hertz(ahb_freq),
 | 
					        ahb3: ahb_freq,
 | 
				
			||||||
        apb1: Hertz(apb1_freq),
 | 
					        apb1: apb1_freq,
 | 
				
			||||||
        apb2: Hertz(apb2_freq),
 | 
					        apb2: apb2_freq,
 | 
				
			||||||
        apb3: Hertz(apb3_freq),
 | 
					        apb3: apb3_freq,
 | 
				
			||||||
        apb1_tim: Hertz(apb1_tim_freq),
 | 
					        apb1_tim: apb1_tim_freq,
 | 
				
			||||||
        apb2_tim: Hertz(apb2_tim_freq),
 | 
					        apb2_tim: apb2_tim_freq,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn msirange_to_hertz(range: Msirange) -> Hertz {
 | 
				
			||||||
 | 
					    match range {
 | 
				
			||||||
 | 
					        Msirange::RANGE_48MHZ => Hertz(48_000_000),
 | 
				
			||||||
 | 
					        Msirange::RANGE_24MHZ => Hertz(24_000_000),
 | 
				
			||||||
 | 
					        Msirange::RANGE_16MHZ => Hertz(16_000_000),
 | 
				
			||||||
 | 
					        Msirange::RANGE_12MHZ => Hertz(12_000_000),
 | 
				
			||||||
 | 
					        Msirange::RANGE_4MHZ => Hertz(4_000_000),
 | 
				
			||||||
 | 
					        Msirange::RANGE_2MHZ => Hertz(2_000_000),
 | 
				
			||||||
 | 
					        Msirange::RANGE_1_33MHZ => Hertz(1_330_000),
 | 
				
			||||||
 | 
					        Msirange::RANGE_1MHZ => Hertz(1_000_000),
 | 
				
			||||||
 | 
					        Msirange::RANGE_3_072MHZ => Hertz(3_072_000),
 | 
				
			||||||
 | 
					        Msirange::RANGE_1_536MHZ => Hertz(1_536_000),
 | 
				
			||||||
 | 
					        Msirange::RANGE_1_024MHZ => Hertz(1_024_000),
 | 
				
			||||||
 | 
					        Msirange::RANGE_768KHZ => Hertz(768_000),
 | 
				
			||||||
 | 
					        Msirange::RANGE_400KHZ => Hertz(400_000),
 | 
				
			||||||
 | 
					        Msirange::RANGE_200KHZ => Hertz(200_000),
 | 
				
			||||||
 | 
					        Msirange::RANGE_133KHZ => Hertz(133_000),
 | 
				
			||||||
 | 
					        Msirange::RANGE_100KHZ => Hertz(100_000),
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
pub use super::bus::{AHBPrescaler, APBPrescaler};
 | 
					pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler};
 | 
				
			||||||
use crate::rcc::bd::{BackupDomain, RtcClockSource};
 | 
					use crate::rcc::bd::{BackupDomain, RtcClockSource};
 | 
				
			||||||
use crate::rcc::Clocks;
 | 
					use crate::rcc::Clocks;
 | 
				
			||||||
use crate::time::{khz, mhz, Hertz};
 | 
					use crate::time::{khz, mhz, Hertz};
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
pub use super::bus::{AHBPrescaler, APBPrescaler};
 | 
					 | 
				
			||||||
pub use crate::pac::pwr::vals::Vos as VoltageScale;
 | 
					pub use crate::pac::pwr::vals::Vos as VoltageScale;
 | 
				
			||||||
use crate::pac::rcc::vals::Adcsel;
 | 
					use crate::pac::rcc::vals::Adcsel;
 | 
				
			||||||
 | 
					pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler};
 | 
				
			||||||
use crate::pac::{FLASH, RCC};
 | 
					use crate::pac::{FLASH, RCC};
 | 
				
			||||||
use crate::rcc::bd::{BackupDomain, RtcClockSource};
 | 
					use crate::rcc::bd::{BackupDomain, RtcClockSource};
 | 
				
			||||||
use crate::rcc::{set_freqs, Clocks};
 | 
					use crate::rcc::{set_freqs, Clocks};
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,7 @@ use core::convert::TryFrom;
 | 
				
			|||||||
use defmt::*;
 | 
					use defmt::*;
 | 
				
			||||||
use embassy_executor::Spawner;
 | 
					use embassy_executor::Spawner;
 | 
				
			||||||
use embassy_stm32::rcc::{
 | 
					use embassy_stm32::rcc::{
 | 
				
			||||||
    APBPrescaler, ClockSrc, HSEConfig, HSESrc, PLL48Div, PLLConfig, PLLMainDiv, PLLMul, PLLPreDiv, PLLSrc,
 | 
					    APBPrescaler, ClockSrc, HSEConfig, HSESrc, PLLConfig, PLLMul, PLLPDiv, PLLPreDiv, PLLQDiv, PLLSrc,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use embassy_stm32::time::Hertz;
 | 
					use embassy_stm32::time::Hertz;
 | 
				
			||||||
use embassy_stm32::Config;
 | 
					use embassy_stm32::Config;
 | 
				
			||||||
@ -32,9 +32,9 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        // 1 MHz PLL input * 240 = 240 MHz PLL VCO
 | 
					        // 1 MHz PLL input * 240 = 240 MHz PLL VCO
 | 
				
			||||||
        mul: unwrap!(PLLMul::try_from(240)),
 | 
					        mul: unwrap!(PLLMul::try_from(240)),
 | 
				
			||||||
        // 240 MHz PLL VCO / 2 = 120 MHz main PLL output
 | 
					        // 240 MHz PLL VCO / 2 = 120 MHz main PLL output
 | 
				
			||||||
        main_div: PLLMainDiv::Div2,
 | 
					        p_div: PLLPDiv::DIV2,
 | 
				
			||||||
        // 240 MHz PLL VCO / 5 = 48 MHz PLL48 output
 | 
					        // 240 MHz PLL VCO / 5 = 48 MHz PLL48 output
 | 
				
			||||||
        pll48_div: unwrap!(PLL48Div::try_from(5)),
 | 
					        q_div: PLLQDiv::DIV5,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    // System clock comes from PLL (= the 120 MHz main PLL output)
 | 
					    // System clock comes from PLL (= the 120 MHz main PLL output)
 | 
				
			||||||
    config.rcc.mux = ClockSrc::PLL;
 | 
					    config.rcc.mux = ClockSrc::PLL;
 | 
				
			||||||
 | 
				
			|||||||
@ -16,12 +16,12 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    config.rcc.pll = Some(Pll {
 | 
					    config.rcc.pll = Some(Pll {
 | 
				
			||||||
        source: PllSrc::HSI16,
 | 
					        source: PllSrc::HSI16,
 | 
				
			||||||
        prediv_m: PllM::Div4,
 | 
					        prediv_m: PllM::DIV4,
 | 
				
			||||||
        mul_n: PllN::Mul85,
 | 
					        mul_n: PllN::MUL85,
 | 
				
			||||||
        div_p: None,
 | 
					        div_p: None,
 | 
				
			||||||
        div_q: None,
 | 
					        div_q: None,
 | 
				
			||||||
        // Main system clock at 170 MHz
 | 
					        // Main system clock at 170 MHz
 | 
				
			||||||
        div_r: Some(PllR::Div2),
 | 
					        div_r: Some(PllR::DIV2),
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    config.rcc.adc12_clock_source = AdcClockSource::SysClk;
 | 
					    config.rcc.adc12_clock_source = AdcClockSource::SysClk;
 | 
				
			||||||
 | 
				
			|||||||
@ -15,12 +15,12 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    config.rcc.pll = Some(Pll {
 | 
					    config.rcc.pll = Some(Pll {
 | 
				
			||||||
        source: PllSrc::HSI16,
 | 
					        source: PllSrc::HSI16,
 | 
				
			||||||
        prediv_m: PllM::Div4,
 | 
					        prediv_m: PllM::DIV4,
 | 
				
			||||||
        mul_n: PllN::Mul85,
 | 
					        mul_n: PllN::MUL85,
 | 
				
			||||||
        div_p: None,
 | 
					        div_p: None,
 | 
				
			||||||
        div_q: None,
 | 
					        div_q: None,
 | 
				
			||||||
        // Main system clock at 170 MHz
 | 
					        // Main system clock at 170 MHz
 | 
				
			||||||
        div_r: Some(PllR::Div2),
 | 
					        div_r: Some(PllR::DIV2),
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    config.rcc.mux = ClockSrc::PLL;
 | 
					    config.rcc.mux = ClockSrc::PLL;
 | 
				
			||||||
 | 
				
			|||||||
@ -25,16 +25,16 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
    // Change this to `false` to use the HSE clock source for the USB. This example assumes an 8MHz HSE.
 | 
					    // Change this to `false` to use the HSE clock source for the USB. This example assumes an 8MHz HSE.
 | 
				
			||||||
    const USE_HSI48: bool = true;
 | 
					    const USE_HSI48: bool = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let pllq_div = if USE_HSI48 { None } else { Some(PllQ::Div6) };
 | 
					    let pllq_div = if USE_HSI48 { None } else { Some(PllQ::DIV6) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    config.rcc.pll = Some(Pll {
 | 
					    config.rcc.pll = Some(Pll {
 | 
				
			||||||
        source: PllSrc::HSE(Hertz(8_000_000)),
 | 
					        source: PllSrc::HSE(Hertz(8_000_000)),
 | 
				
			||||||
        prediv_m: PllM::Div2,
 | 
					        prediv_m: PllM::DIV2,
 | 
				
			||||||
        mul_n: PllN::Mul72,
 | 
					        mul_n: PllN::MUL72,
 | 
				
			||||||
        div_p: None,
 | 
					        div_p: None,
 | 
				
			||||||
        div_q: pllq_div,
 | 
					        div_q: pllq_div,
 | 
				
			||||||
        // Main system clock at 144 MHz
 | 
					        // Main system clock at 144 MHz
 | 
				
			||||||
        div_r: Some(PllR::Div2),
 | 
					        div_r: Some(PllR::DIV2),
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    config.rcc.mux = ClockSrc::PLL;
 | 
					    config.rcc.mux = ClockSrc::PLL;
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,9 @@ use embassy_net::{Ipv4Address, Stack, StackResources};
 | 
				
			|||||||
use embassy_stm32::eth::generic_smi::GenericSMI;
 | 
					use embassy_stm32::eth::generic_smi::GenericSMI;
 | 
				
			||||||
use embassy_stm32::eth::{Ethernet, PacketQueue};
 | 
					use embassy_stm32::eth::{Ethernet, PacketQueue};
 | 
				
			||||||
use embassy_stm32::peripherals::ETH;
 | 
					use embassy_stm32::peripherals::ETH;
 | 
				
			||||||
use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale};
 | 
					use embassy_stm32::rcc::{
 | 
				
			||||||
 | 
					    AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
use embassy_stm32::rng::Rng;
 | 
					use embassy_stm32::rng::Rng;
 | 
				
			||||||
use embassy_stm32::time::Hertz;
 | 
					use embassy_stm32::time::Hertz;
 | 
				
			||||||
use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
 | 
					use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
 | 
				
			||||||
@ -42,10 +44,10 @@ async fn main(spawner: Spawner) -> ! {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
    config.rcc.pll1 = Some(Pll {
 | 
					    config.rcc.pll1 = Some(Pll {
 | 
				
			||||||
        source: PllSource::Hse,
 | 
					        source: PllSource::Hse,
 | 
				
			||||||
        prediv: 2,
 | 
					        prediv: PllPreDiv::DIV2,
 | 
				
			||||||
        mul: 125,
 | 
					        mul: PllMul::MUL125,
 | 
				
			||||||
        divp: Some(2),
 | 
					        divp: Some(PllDiv::DIV2),
 | 
				
			||||||
        divq: Some(2),
 | 
					        divq: Some(PllDiv::DIV2),
 | 
				
			||||||
        divr: None,
 | 
					        divr: None,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    config.rcc.ahb_pre = AHBPrescaler::DIV1;
 | 
					    config.rcc.ahb_pre = AHBPrescaler::DIV1;
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use defmt::{panic, *};
 | 
					use defmt::{panic, *};
 | 
				
			||||||
use embassy_executor::Spawner;
 | 
					use embassy_executor::Spawner;
 | 
				
			||||||
use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale};
 | 
					use embassy_stm32::rcc::{
 | 
				
			||||||
 | 
					    AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
use embassy_stm32::time::Hertz;
 | 
					use embassy_stm32::time::Hertz;
 | 
				
			||||||
use embassy_stm32::usb::{Driver, Instance};
 | 
					use embassy_stm32::usb::{Driver, Instance};
 | 
				
			||||||
use embassy_stm32::{bind_interrupts, pac, peripherals, usb, Config};
 | 
					use embassy_stm32::{bind_interrupts, pac, peripherals, usb, Config};
 | 
				
			||||||
@ -29,9 +31,9 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
    config.rcc.pll1 = Some(Pll {
 | 
					    config.rcc.pll1 = Some(Pll {
 | 
				
			||||||
        source: PllSource::Hse,
 | 
					        source: PllSource::Hse,
 | 
				
			||||||
        prediv: 2,
 | 
					        prediv: PllPreDiv::DIV2,
 | 
				
			||||||
        mul: 125,
 | 
					        mul: PllMul::MUL125,
 | 
				
			||||||
        divp: Some(2), // 250mhz
 | 
					        divp: Some(PllDiv::DIV2), // 250mhz
 | 
				
			||||||
        divq: None,
 | 
					        divq: None,
 | 
				
			||||||
        divr: None,
 | 
					        divr: None,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
				
			|||||||
@ -18,16 +18,16 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        config.rcc.csi = true;
 | 
					        config.rcc.csi = true;
 | 
				
			||||||
        config.rcc.pll_src = PllSource::Hsi;
 | 
					        config.rcc.pll_src = PllSource::Hsi;
 | 
				
			||||||
        config.rcc.pll1 = Some(Pll {
 | 
					        config.rcc.pll1 = Some(Pll {
 | 
				
			||||||
            prediv: 4,
 | 
					            prediv: PllPreDiv::DIV4,
 | 
				
			||||||
            mul: 50,
 | 
					            mul: PllMul::MUL50,
 | 
				
			||||||
            divp: Some(2),
 | 
					            divp: Some(PllDiv::DIV2),
 | 
				
			||||||
            divq: Some(8), // SPI1 cksel defaults to pll1_q
 | 
					            divq: Some(PllDiv::DIV8), // SPI1 cksel defaults to pll1_q
 | 
				
			||||||
            divr: None,
 | 
					            divr: None,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        config.rcc.pll2 = Some(Pll {
 | 
					        config.rcc.pll2 = Some(Pll {
 | 
				
			||||||
            prediv: 4,
 | 
					            prediv: PllPreDiv::DIV4,
 | 
				
			||||||
            mul: 50,
 | 
					            mul: PllMul::MUL50,
 | 
				
			||||||
            divp: Some(8), // 100mhz
 | 
					            divp: Some(PllDiv::DIV8), // 100mhz
 | 
				
			||||||
            divq: None,
 | 
					            divq: None,
 | 
				
			||||||
            divr: None,
 | 
					            divr: None,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
				
			|||||||
@ -32,10 +32,10 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        config.rcc.csi = true;
 | 
					        config.rcc.csi = true;
 | 
				
			||||||
        config.rcc.pll_src = PllSource::Hsi;
 | 
					        config.rcc.pll_src = PllSource::Hsi;
 | 
				
			||||||
        config.rcc.pll1 = Some(Pll {
 | 
					        config.rcc.pll1 = Some(Pll {
 | 
				
			||||||
            prediv: 4,
 | 
					            prediv: PllPreDiv::DIV4,
 | 
				
			||||||
            mul: 50,
 | 
					            mul: PllMul::MUL50,
 | 
				
			||||||
            divp: Some(2),
 | 
					            divp: Some(PllDiv::DIV2),
 | 
				
			||||||
            divq: Some(8), // 100mhz
 | 
					            divq: Some(PllDiv::DIV8), // 100mhz
 | 
				
			||||||
            divr: None,
 | 
					            divr: None,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
 | 
					        config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
 | 
				
			||||||
 | 
				
			|||||||
@ -20,16 +20,16 @@ fn main() -> ! {
 | 
				
			|||||||
        config.rcc.csi = true;
 | 
					        config.rcc.csi = true;
 | 
				
			||||||
        config.rcc.pll_src = PllSource::Hsi;
 | 
					        config.rcc.pll_src = PllSource::Hsi;
 | 
				
			||||||
        config.rcc.pll1 = Some(Pll {
 | 
					        config.rcc.pll1 = Some(Pll {
 | 
				
			||||||
            prediv: 4,
 | 
					            prediv: PllPreDiv::DIV4,
 | 
				
			||||||
            mul: 50,
 | 
					            mul: PllMul::MUL50,
 | 
				
			||||||
            divp: Some(2),
 | 
					            divp: Some(PllDiv::DIV2),
 | 
				
			||||||
            divq: Some(8), // SPI1 cksel defaults to pll1_q
 | 
					            divq: Some(PllDiv::DIV8), // 100mhz
 | 
				
			||||||
            divr: None,
 | 
					            divr: None,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        config.rcc.pll2 = Some(Pll {
 | 
					        config.rcc.pll2 = Some(Pll {
 | 
				
			||||||
            prediv: 4,
 | 
					            prediv: PllPreDiv::DIV4,
 | 
				
			||||||
            mul: 50,
 | 
					            mul: PllMul::MUL50,
 | 
				
			||||||
            divp: Some(8), // 100mhz
 | 
					            divp: Some(PllDiv::DIV8), // 100mhz
 | 
				
			||||||
            divq: None,
 | 
					            divq: None,
 | 
				
			||||||
            divr: None,
 | 
					            divr: None,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
				
			|||||||
@ -28,16 +28,16 @@ async fn main(spawner: Spawner) {
 | 
				
			|||||||
        config.rcc.csi = true;
 | 
					        config.rcc.csi = true;
 | 
				
			||||||
        config.rcc.pll_src = PllSource::Hsi;
 | 
					        config.rcc.pll_src = PllSource::Hsi;
 | 
				
			||||||
        config.rcc.pll1 = Some(Pll {
 | 
					        config.rcc.pll1 = Some(Pll {
 | 
				
			||||||
            prediv: 4,
 | 
					            prediv: PllPreDiv::DIV4,
 | 
				
			||||||
            mul: 50,
 | 
					            mul: PllMul::MUL50,
 | 
				
			||||||
            divp: Some(2),
 | 
					            divp: Some(PllDiv::DIV2),
 | 
				
			||||||
            divq: Some(8), // SPI1 cksel defaults to pll1_q
 | 
					            divq: Some(PllDiv::DIV8), // 100mhz
 | 
				
			||||||
            divr: None,
 | 
					            divr: None,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        config.rcc.pll2 = Some(Pll {
 | 
					        config.rcc.pll2 = Some(Pll {
 | 
				
			||||||
            prediv: 4,
 | 
					            prediv: PllPreDiv::DIV4,
 | 
				
			||||||
            mul: 50,
 | 
					            mul: PllMul::MUL50,
 | 
				
			||||||
            divp: Some(8), // 100mhz
 | 
					            divp: Some(PllDiv::DIV8), // 100mhz
 | 
				
			||||||
            divq: None,
 | 
					            divq: None,
 | 
				
			||||||
            divr: None,
 | 
					            divr: None,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
				
			|||||||
@ -39,9 +39,9 @@ async fn main(spawner: Spawner) -> ! {
 | 
				
			|||||||
        config.rcc.hsi48 = true; // needed for RNG
 | 
					        config.rcc.hsi48 = true; // needed for RNG
 | 
				
			||||||
        config.rcc.pll_src = PllSource::Hsi;
 | 
					        config.rcc.pll_src = PllSource::Hsi;
 | 
				
			||||||
        config.rcc.pll1 = Some(Pll {
 | 
					        config.rcc.pll1 = Some(Pll {
 | 
				
			||||||
            prediv: 4,
 | 
					            prediv: PllPreDiv::DIV4,
 | 
				
			||||||
            mul: 50,
 | 
					            mul: PllMul::MUL50,
 | 
				
			||||||
            divp: Some(2),
 | 
					            divp: Some(PllDiv::DIV2),
 | 
				
			||||||
            divq: None,
 | 
					            divq: None,
 | 
				
			||||||
            divr: None,
 | 
					            divr: None,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
				
			|||||||
@ -40,9 +40,9 @@ async fn main(spawner: Spawner) -> ! {
 | 
				
			|||||||
        config.rcc.hsi48 = true; // needed for RNG
 | 
					        config.rcc.hsi48 = true; // needed for RNG
 | 
				
			||||||
        config.rcc.pll_src = PllSource::Hsi;
 | 
					        config.rcc.pll_src = PllSource::Hsi;
 | 
				
			||||||
        config.rcc.pll1 = Some(Pll {
 | 
					        config.rcc.pll1 = Some(Pll {
 | 
				
			||||||
            prediv: 4,
 | 
					            prediv: PllPreDiv::DIV4,
 | 
				
			||||||
            mul: 50,
 | 
					            mul: PllMul::MUL50,
 | 
				
			||||||
            divp: Some(2),
 | 
					            divp: Some(PllDiv::DIV2),
 | 
				
			||||||
            divq: None,
 | 
					            divq: None,
 | 
				
			||||||
            divr: None,
 | 
					            divr: None,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
				
			|||||||
@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        config.rcc.csi = true;
 | 
					        config.rcc.csi = true;
 | 
				
			||||||
        config.rcc.pll_src = PllSource::Hsi;
 | 
					        config.rcc.pll_src = PllSource::Hsi;
 | 
				
			||||||
        config.rcc.pll1 = Some(Pll {
 | 
					        config.rcc.pll1 = Some(Pll {
 | 
				
			||||||
            prediv: 4,
 | 
					            prediv: PllPreDiv::DIV4,
 | 
				
			||||||
            mul: 50,
 | 
					            mul: PllMul::MUL50,
 | 
				
			||||||
            divp: Some(2),
 | 
					            divp: Some(PllDiv::DIV2),
 | 
				
			||||||
            divq: Some(8), // 100mhz
 | 
					            divq: Some(PllDiv::DIV8), // 100mhz
 | 
				
			||||||
            divr: None,
 | 
					            divr: None,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
 | 
					        config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
 | 
				
			||||||
 | 
				
			|||||||
@ -22,10 +22,10 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        config.rcc.hsi48 = true; // needed for RNG
 | 
					        config.rcc.hsi48 = true; // needed for RNG
 | 
				
			||||||
        config.rcc.pll_src = PllSource::Hsi;
 | 
					        config.rcc.pll_src = PllSource::Hsi;
 | 
				
			||||||
        config.rcc.pll1 = Some(Pll {
 | 
					        config.rcc.pll1 = Some(Pll {
 | 
				
			||||||
            prediv: 4,
 | 
					            prediv: PllPreDiv::DIV4,
 | 
				
			||||||
            mul: 50,
 | 
					            mul: PllMul::MUL50,
 | 
				
			||||||
            divp: Some(2),
 | 
					            divp: Some(PllDiv::DIV2),
 | 
				
			||||||
            divq: Some(8), // 100 Mhz
 | 
					            divq: Some(PllDiv::DIV8), // 100mhz
 | 
				
			||||||
            divr: None,
 | 
					            divr: None,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
 | 
					        config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
 | 
				
			||||||
 | 
				
			|||||||
@ -21,9 +21,9 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        config.rcc.csi = true;
 | 
					        config.rcc.csi = true;
 | 
				
			||||||
        config.rcc.pll_src = PllSource::Hsi;
 | 
					        config.rcc.pll_src = PllSource::Hsi;
 | 
				
			||||||
        config.rcc.pll1 = Some(Pll {
 | 
					        config.rcc.pll1 = Some(Pll {
 | 
				
			||||||
            prediv: 4,
 | 
					            prediv: PllPreDiv::DIV4,
 | 
				
			||||||
            mul: 50,
 | 
					            mul: PllMul::MUL50,
 | 
				
			||||||
            divp: Some(2),
 | 
					            divp: Some(PllDiv::DIV2),
 | 
				
			||||||
            divq: None,
 | 
					            divq: None,
 | 
				
			||||||
            divr: None,
 | 
					            divr: None,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
				
			|||||||
@ -22,10 +22,10 @@ async fn main(_spawner: Spawner) -> ! {
 | 
				
			|||||||
        config.rcc.csi = true;
 | 
					        config.rcc.csi = true;
 | 
				
			||||||
        config.rcc.pll_src = PllSource::Hsi;
 | 
					        config.rcc.pll_src = PllSource::Hsi;
 | 
				
			||||||
        config.rcc.pll1 = Some(Pll {
 | 
					        config.rcc.pll1 = Some(Pll {
 | 
				
			||||||
            prediv: 4,
 | 
					            prediv: PllPreDiv::DIV4,
 | 
				
			||||||
            mul: 50,
 | 
					            mul: PllMul::MUL50,
 | 
				
			||||||
            divp: Some(2),
 | 
					            divp: Some(PllDiv::DIV2),
 | 
				
			||||||
            divq: Some(4), // default clock chosen by SDMMCSEL. 200 Mhz
 | 
					            divq: Some(PllDiv::DIV4), // default clock chosen by SDMMCSEL. 200 Mhz
 | 
				
			||||||
            divr: None,
 | 
					            divr: None,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
 | 
					        config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
 | 
				
			||||||
 | 
				
			|||||||
@ -44,10 +44,10 @@ fn main() -> ! {
 | 
				
			|||||||
        config.rcc.csi = true;
 | 
					        config.rcc.csi = true;
 | 
				
			||||||
        config.rcc.pll_src = PllSource::Hsi;
 | 
					        config.rcc.pll_src = PllSource::Hsi;
 | 
				
			||||||
        config.rcc.pll1 = Some(Pll {
 | 
					        config.rcc.pll1 = Some(Pll {
 | 
				
			||||||
            prediv: 4,
 | 
					            prediv: PllPreDiv::DIV4,
 | 
				
			||||||
            mul: 50,
 | 
					            mul: PllMul::MUL50,
 | 
				
			||||||
            divp: Some(2),
 | 
					            divp: Some(PllDiv::DIV2),
 | 
				
			||||||
            divq: Some(4), // used by SPI3. 100Mhz.
 | 
					            divq: Some(PllDiv::DIV8), // used by SPI3. 100Mhz.
 | 
				
			||||||
            divr: None,
 | 
					            divr: None,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
 | 
					        config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
 | 
				
			||||||
 | 
				
			|||||||
@ -40,10 +40,10 @@ fn main() -> ! {
 | 
				
			|||||||
        config.rcc.csi = true;
 | 
					        config.rcc.csi = true;
 | 
				
			||||||
        config.rcc.pll_src = PllSource::Hsi;
 | 
					        config.rcc.pll_src = PllSource::Hsi;
 | 
				
			||||||
        config.rcc.pll1 = Some(Pll {
 | 
					        config.rcc.pll1 = Some(Pll {
 | 
				
			||||||
            prediv: 4,
 | 
					            prediv: PllPreDiv::DIV4,
 | 
				
			||||||
            mul: 50,
 | 
					            mul: PllMul::MUL50,
 | 
				
			||||||
            divp: Some(2),
 | 
					            divp: Some(PllDiv::DIV2),
 | 
				
			||||||
            divq: Some(4), // used by SPI3. 100Mhz.
 | 
					            divq: Some(PllDiv::DIV8), // used by SPI3. 100Mhz.
 | 
				
			||||||
            divr: None,
 | 
					            divr: None,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
 | 
					        config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
 | 
				
			||||||
 | 
				
			|||||||
@ -28,9 +28,9 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        config.rcc.hsi48 = true; // needed for USB
 | 
					        config.rcc.hsi48 = true; // needed for USB
 | 
				
			||||||
        config.rcc.pll_src = PllSource::Hsi;
 | 
					        config.rcc.pll_src = PllSource::Hsi;
 | 
				
			||||||
        config.rcc.pll1 = Some(Pll {
 | 
					        config.rcc.pll1 = Some(Pll {
 | 
				
			||||||
            prediv: 4,
 | 
					            prediv: PllPreDiv::DIV4,
 | 
				
			||||||
            mul: 50,
 | 
					            mul: PllMul::MUL50,
 | 
				
			||||||
            divp: Some(2),
 | 
					            divp: Some(PllDiv::DIV2),
 | 
				
			||||||
            divq: None,
 | 
					            divq: None,
 | 
				
			||||||
            divr: None,
 | 
					            divr: None,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use defmt::*;
 | 
					use defmt::*;
 | 
				
			||||||
use embassy_executor::Spawner;
 | 
					use embassy_executor::Spawner;
 | 
				
			||||||
use embassy_stm32::rcc::{ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv};
 | 
					use embassy_stm32::rcc::{ClockSrc, PLLSource, PllMul, PllPreDiv, PllQDiv, PllRDiv};
 | 
				
			||||||
use embassy_stm32::rng::Rng;
 | 
					use embassy_stm32::rng::Rng;
 | 
				
			||||||
use embassy_stm32::{bind_interrupts, peripherals, rng, Config};
 | 
					use embassy_stm32::{bind_interrupts, peripherals, rng, Config};
 | 
				
			||||||
use {defmt_rtt as _, panic_probe as _};
 | 
					use {defmt_rtt as _, panic_probe as _};
 | 
				
			||||||
@ -19,10 +19,10 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
    // 72Mhz clock (16 / 1 * 18 / 4)
 | 
					    // 72Mhz clock (16 / 1 * 18 / 4)
 | 
				
			||||||
    config.rcc.mux = ClockSrc::PLL(
 | 
					    config.rcc.mux = ClockSrc::PLL(
 | 
				
			||||||
        PLLSource::HSI16,
 | 
					        PLLSource::HSI16,
 | 
				
			||||||
        PLLClkDiv::Div4,
 | 
					        PllRDiv::DIV4,
 | 
				
			||||||
        PLLSrcDiv::Div1,
 | 
					        PllPreDiv::DIV1,
 | 
				
			||||||
        PLLMul::Mul18,
 | 
					        PllMul::MUL18,
 | 
				
			||||||
        Some(PLLClkDiv::Div6), // 48Mhz (16 / 1 * 18 / 6)
 | 
					        Some(PllQDiv::DIV6), // 48Mhz (16 / 1 * 18 / 6)
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    let p = embassy_stm32::init(config);
 | 
					    let p = embassy_stm32::init(config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@
 | 
				
			|||||||
use chrono::{NaiveDate, NaiveDateTime};
 | 
					use chrono::{NaiveDate, NaiveDateTime};
 | 
				
			||||||
use defmt::*;
 | 
					use defmt::*;
 | 
				
			||||||
use embassy_executor::Spawner;
 | 
					use embassy_executor::Spawner;
 | 
				
			||||||
use embassy_stm32::rcc::{self, ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv};
 | 
					use embassy_stm32::rcc::{self, ClockSrc, PLLSource, PllMul, PllPreDiv, PllRDiv};
 | 
				
			||||||
use embassy_stm32::rtc::{Rtc, RtcConfig};
 | 
					use embassy_stm32::rtc::{Rtc, RtcConfig};
 | 
				
			||||||
use embassy_stm32::time::Hertz;
 | 
					use embassy_stm32::time::Hertz;
 | 
				
			||||||
use embassy_stm32::Config;
 | 
					use embassy_stm32::Config;
 | 
				
			||||||
@ -18,9 +18,9 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        let mut config = Config::default();
 | 
					        let mut config = Config::default();
 | 
				
			||||||
        config.rcc.mux = ClockSrc::PLL(
 | 
					        config.rcc.mux = ClockSrc::PLL(
 | 
				
			||||||
            PLLSource::HSE(Hertz::mhz(8)),
 | 
					            PLLSource::HSE(Hertz::mhz(8)),
 | 
				
			||||||
            PLLClkDiv::Div2,
 | 
					            PllRDiv::DIV2,
 | 
				
			||||||
            PLLSrcDiv::Div1,
 | 
					            PllPreDiv::DIV1,
 | 
				
			||||||
            PLLMul::Mul20,
 | 
					            PllMul::MUL20,
 | 
				
			||||||
            None,
 | 
					            None,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        config.rcc.lse = Some(Hertz(32_768));
 | 
					        config.rcc.lse = Some(Hertz(32_768));
 | 
				
			||||||
 | 
				
			|||||||
@ -49,7 +49,7 @@ use embassy_net_adin1110::{self, Device, Runner, ADIN1110};
 | 
				
			|||||||
use embedded_hal_bus::spi::ExclusiveDevice;
 | 
					use embedded_hal_bus::spi::ExclusiveDevice;
 | 
				
			||||||
use hal::gpio::Pull;
 | 
					use hal::gpio::Pull;
 | 
				
			||||||
use hal::i2c::Config as I2C_Config;
 | 
					use hal::i2c::Config as I2C_Config;
 | 
				
			||||||
use hal::rcc::{ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv};
 | 
					use hal::rcc::{ClockSrc, PLLSource, PllMul, PllPreDiv, PllRDiv};
 | 
				
			||||||
use hal::spi::{Config as SPI_Config, Spi};
 | 
					use hal::spi::{Config as SPI_Config, Spi};
 | 
				
			||||||
use hal::time::Hertz;
 | 
					use hal::time::Hertz;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -80,9 +80,9 @@ async fn main(spawner: Spawner) {
 | 
				
			|||||||
    // 80MHz highest frequency for flash 0 wait.
 | 
					    // 80MHz highest frequency for flash 0 wait.
 | 
				
			||||||
    config.rcc.mux = ClockSrc::PLL(
 | 
					    config.rcc.mux = ClockSrc::PLL(
 | 
				
			||||||
        PLLSource::HSE(Hertz(8_000_000)),
 | 
					        PLLSource::HSE(Hertz(8_000_000)),
 | 
				
			||||||
        PLLClkDiv::Div2,
 | 
					        PllRDiv::DIV2,
 | 
				
			||||||
        PLLSrcDiv::Div1,
 | 
					        PllPreDiv::DIV1,
 | 
				
			||||||
        PLLMul::Mul20,
 | 
					        PllMul::MUL20,
 | 
				
			||||||
        None,
 | 
					        None,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    config.rcc.hsi48 = true; // needed for rng
 | 
					    config.rcc.hsi48 = true; // needed for rng
 | 
				
			||||||
 | 
				
			|||||||
@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
    info!("Hello World!");
 | 
					    info!("Hello World!");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut config = Config::default();
 | 
					    let mut config = Config::default();
 | 
				
			||||||
    config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PLLClkDiv::Div2, PLLSrcDiv::Div1, PLLMul::Mul10, None);
 | 
					    config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PllRDiv::DIV2, PllPreDiv::DIV1, PllMul::MUL10, None);
 | 
				
			||||||
    config.rcc.hsi48 = true;
 | 
					    config.rcc.hsi48 = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let p = embassy_stm32::init(config);
 | 
					    let p = embassy_stm32::init(config);
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use defmt::*;
 | 
					use defmt::*;
 | 
				
			||||||
use embassy_executor::Spawner;
 | 
					use embassy_executor::Spawner;
 | 
				
			||||||
use embassy_stm32::rcc::{ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv};
 | 
					use embassy_stm32::rcc::{ClockSrc, PLLSource, PllMul, PllPreDiv, PllQDiv, PllRDiv};
 | 
				
			||||||
use embassy_stm32::rng::Rng;
 | 
					use embassy_stm32::rng::Rng;
 | 
				
			||||||
use embassy_stm32::{bind_interrupts, peripherals, rng, Config};
 | 
					use embassy_stm32::{bind_interrupts, peripherals, rng, Config};
 | 
				
			||||||
use {defmt_rtt as _, panic_probe as _};
 | 
					use {defmt_rtt as _, panic_probe as _};
 | 
				
			||||||
@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
    let mut config = Config::default();
 | 
					    let mut config = Config::default();
 | 
				
			||||||
    config.rcc.mux = ClockSrc::PLL(
 | 
					    config.rcc.mux = ClockSrc::PLL(
 | 
				
			||||||
        PLLSource::HSI16,
 | 
					        PLLSource::HSI16,
 | 
				
			||||||
        PLLClkDiv::Div2,
 | 
					        PllRDiv::DIV2,
 | 
				
			||||||
        PLLSrcDiv::Div1,
 | 
					        PllPreDiv::DIV1,
 | 
				
			||||||
        PLLMul::Mul8,
 | 
					        PllMul::MUL8,
 | 
				
			||||||
        Some(PLLClkDiv::Div2),
 | 
					        Some(PllQDiv::DIV2),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    let p = embassy_stm32::init(config);
 | 
					    let p = embassy_stm32::init(config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -45,7 +45,7 @@ async fn net_task(stack: &'static Stack<Device<'static, MTU>>) -> ! {
 | 
				
			|||||||
#[embassy_executor::main]
 | 
					#[embassy_executor::main]
 | 
				
			||||||
async fn main(spawner: Spawner) {
 | 
					async fn main(spawner: Spawner) {
 | 
				
			||||||
    let mut config = Config::default();
 | 
					    let mut config = Config::default();
 | 
				
			||||||
    config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PLLClkDiv::Div2, PLLSrcDiv::Div1, PLLMul::Mul10, None);
 | 
					    config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PllRDiv::DIV2, PllPreDiv::DIV1, PllMul::MUL10, None);
 | 
				
			||||||
    config.rcc.hsi48 = true;
 | 
					    config.rcc.hsi48 = true;
 | 
				
			||||||
    let p = embassy_stm32::init(config);
 | 
					    let p = embassy_stm32::init(config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -22,7 +22,7 @@ bind_interrupts!(struct Irqs {
 | 
				
			|||||||
#[embassy_executor::main]
 | 
					#[embassy_executor::main]
 | 
				
			||||||
async fn main(_spawner: Spawner) {
 | 
					async fn main(_spawner: Spawner) {
 | 
				
			||||||
    let mut config = Config::default();
 | 
					    let mut config = Config::default();
 | 
				
			||||||
    config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PLLClkDiv::Div2, PLLSrcDiv::Div1, PLLMul::Mul10, None);
 | 
					    config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PllRDiv::DIV2, PllPreDiv::DIV1, PllMul::MUL10, None);
 | 
				
			||||||
    config.rcc.hsi48 = true;
 | 
					    config.rcc.hsi48 = true;
 | 
				
			||||||
    let p = embassy_stm32::init(config);
 | 
					    let p = embassy_stm32::init(config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -20,7 +20,7 @@ bind_interrupts!(struct Irqs {
 | 
				
			|||||||
#[embassy_executor::main]
 | 
					#[embassy_executor::main]
 | 
				
			||||||
async fn main(_spawner: Spawner) {
 | 
					async fn main(_spawner: Spawner) {
 | 
				
			||||||
    let mut config = Config::default();
 | 
					    let mut config = Config::default();
 | 
				
			||||||
    config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PLLClkDiv::Div2, PLLSrcDiv::Div1, PLLMul::Mul10, None);
 | 
					    config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PllRDiv::DIV2, PllPreDiv::DIV1, PllMul::MUL10, None);
 | 
				
			||||||
    config.rcc.hsi48 = true;
 | 
					    config.rcc.hsi48 = true;
 | 
				
			||||||
    let p = embassy_stm32::init(config);
 | 
					    let p = embassy_stm32::init(config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -25,9 +25,9 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
    let mut config = Config::default();
 | 
					    let mut config = Config::default();
 | 
				
			||||||
    config.rcc.mux = ClockSrc::PLL1R(PllConfig {
 | 
					    config.rcc.mux = ClockSrc::PLL1R(PllConfig {
 | 
				
			||||||
        source: PllSrc::HSI16,
 | 
					        source: PllSrc::HSI16,
 | 
				
			||||||
        m: PllM::Div2,
 | 
					        m: Pllm::DIV2,
 | 
				
			||||||
        n: PllN::Mul10,
 | 
					        n: Plln::MUL10,
 | 
				
			||||||
        r: PllClkDiv::NotDivided,
 | 
					        r: Plldiv::DIV1,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    //config.rcc.mux = ClockSrc::MSI(MSIRange::Range48mhz);
 | 
					    //config.rcc.mux = ClockSrc::MSI(MSIRange::Range48mhz);
 | 
				
			||||||
    config.rcc.hsi48 = true;
 | 
					    config.rcc.hsi48 = true;
 | 
				
			||||||
 | 
				
			|||||||
@ -202,9 +202,9 @@ pub fn config() -> Config {
 | 
				
			|||||||
            // 1 MHz PLL input * 240 = 240 MHz PLL VCO
 | 
					            // 1 MHz PLL input * 240 = 240 MHz PLL VCO
 | 
				
			||||||
            mul: unwrap!(PLLMul::try_from(240)),
 | 
					            mul: unwrap!(PLLMul::try_from(240)),
 | 
				
			||||||
            // 240 MHz PLL VCO / 2 = 120 MHz main PLL output
 | 
					            // 240 MHz PLL VCO / 2 = 120 MHz main PLL output
 | 
				
			||||||
            main_div: PLLMainDiv::Div2,
 | 
					            p_div: PLLPDiv::DIV2,
 | 
				
			||||||
            // 240 MHz PLL VCO / 5 = 48 MHz PLL48 output
 | 
					            // 240 MHz PLL VCO / 5 = 48 MHz PLL48 output
 | 
				
			||||||
            pll48_div: unwrap!(PLL48Div::try_from(5)),
 | 
					            q_div: PLLQDiv::DIV5,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        // System clock comes from PLL (= the 120 MHz main PLL output)
 | 
					        // System clock comes from PLL (= the 120 MHz main PLL output)
 | 
				
			||||||
        config.rcc.mux = ClockSrc::PLL;
 | 
					        config.rcc.mux = ClockSrc::PLL;
 | 
				
			||||||
@ -239,10 +239,10 @@ pub fn config() -> Config {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
        config.rcc.pll1 = Some(Pll {
 | 
					        config.rcc.pll1 = Some(Pll {
 | 
				
			||||||
            source: PllSource::Hse,
 | 
					            source: PllSource::Hse,
 | 
				
			||||||
            prediv: 2,
 | 
					            prediv: PllPreDiv::DIV2,
 | 
				
			||||||
            mul: 125,
 | 
					            mul: PllMul::MUL125,
 | 
				
			||||||
            divp: Some(2),
 | 
					            divp: Some(PllDiv::DIV2),
 | 
				
			||||||
            divq: Some(2),
 | 
					            divq: Some(PllDiv::DIV2),
 | 
				
			||||||
            divr: None,
 | 
					            divr: None,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        config.rcc.ahb_pre = AHBPrescaler::DIV1;
 | 
					        config.rcc.ahb_pre = AHBPrescaler::DIV1;
 | 
				
			||||||
@ -261,16 +261,16 @@ pub fn config() -> Config {
 | 
				
			|||||||
        config.rcc.hsi48 = true; // needed for RNG
 | 
					        config.rcc.hsi48 = true; // needed for RNG
 | 
				
			||||||
        config.rcc.pll_src = PllSource::Hsi;
 | 
					        config.rcc.pll_src = PllSource::Hsi;
 | 
				
			||||||
        config.rcc.pll1 = Some(Pll {
 | 
					        config.rcc.pll1 = Some(Pll {
 | 
				
			||||||
            prediv: 4,
 | 
					            prediv: PllPreDiv::DIV4,
 | 
				
			||||||
            mul: 50,
 | 
					            mul: PllMul::MUL50,
 | 
				
			||||||
            divp: Some(2),
 | 
					            divp: Some(PllDiv::DIV2),
 | 
				
			||||||
            divq: Some(8), // SPI1 cksel defaults to pll1_q
 | 
					            divq: Some(PllDiv::DIV8), // SPI1 cksel defaults to pll1_q
 | 
				
			||||||
            divr: None,
 | 
					            divr: None,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        config.rcc.pll2 = Some(Pll {
 | 
					        config.rcc.pll2 = Some(Pll {
 | 
				
			||||||
            prediv: 4,
 | 
					            prediv: PllPreDiv::DIV4,
 | 
				
			||||||
            mul: 50,
 | 
					            mul: PllMul::MUL50,
 | 
				
			||||||
            divp: Some(8), // 100mhz
 | 
					            divp: Some(PllDiv::DIV8), // 100mhz
 | 
				
			||||||
            divq: None,
 | 
					            divq: None,
 | 
				
			||||||
            divr: None,
 | 
					            divr: None,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
@ -290,10 +290,10 @@ pub fn config() -> Config {
 | 
				
			|||||||
        config.rcc.mux = ClockSrc::PLL(
 | 
					        config.rcc.mux = ClockSrc::PLL(
 | 
				
			||||||
            // 72Mhz clock (16 / 1 * 18 / 4)
 | 
					            // 72Mhz clock (16 / 1 * 18 / 4)
 | 
				
			||||||
            PLLSource::HSI16,
 | 
					            PLLSource::HSI16,
 | 
				
			||||||
            PLLClkDiv::Div4,
 | 
					            PllRDiv::DIV4,
 | 
				
			||||||
            PLLSrcDiv::Div1,
 | 
					            PllPreDiv::DIV1,
 | 
				
			||||||
            PLLMul::Mul18,
 | 
					            PllMul::MUL18,
 | 
				
			||||||
            Some(PLLClkDiv::Div6), // 48Mhz (16 / 1 * 18 / 6)
 | 
					            Some(PllQDiv::DIV6), // 48Mhz (16 / 1 * 18 / 6)
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -303,9 +303,9 @@ pub fn config() -> Config {
 | 
				
			|||||||
        config.rcc.mux = ClockSrc::PLL(
 | 
					        config.rcc.mux = ClockSrc::PLL(
 | 
				
			||||||
            // 110Mhz clock (16 / 4 * 55 / 2)
 | 
					            // 110Mhz clock (16 / 4 * 55 / 2)
 | 
				
			||||||
            PLLSource::HSI16,
 | 
					            PLLSource::HSI16,
 | 
				
			||||||
            PLLClkDiv::Div2,
 | 
					            PllRDiv::DIV2,
 | 
				
			||||||
            PLLSrcDiv::Div4,
 | 
					            PllPreDiv::DIV4,
 | 
				
			||||||
            PLLMul::Mul55,
 | 
					            PllMul::MUL55,
 | 
				
			||||||
            None,
 | 
					            None,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -313,7 +313,7 @@ pub fn config() -> Config {
 | 
				
			|||||||
    #[cfg(feature = "stm32u585ai")]
 | 
					    #[cfg(feature = "stm32u585ai")]
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        use embassy_stm32::rcc::*;
 | 
					        use embassy_stm32::rcc::*;
 | 
				
			||||||
        config.rcc.mux = ClockSrc::MSI(MSIRange::Range48mhz);
 | 
					        config.rcc.mux = ClockSrc::MSI(Msirange::RANGE_48MHZ);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[cfg(feature = "stm32l073rz")]
 | 
					    #[cfg(feature = "stm32l073rz")]
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user