Merge pull request #2063 from embassy-rs/rcc-no-spaghetti
stm32/rcc: port L4 to the "flattened" API like h5/h7.
This commit is contained in:
		@@ -1,9 +1,8 @@
 | 
			
		||||
use crate::pac::rcc::regs::Cfgr;
 | 
			
		||||
pub use crate::pac::rcc::vals::{
 | 
			
		||||
    Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv,
 | 
			
		||||
    Pllr as PllRDiv, Ppre as APBPrescaler,
 | 
			
		||||
    Pllr as PllRDiv, Pllsrc as PLLSource, Ppre as APBPrescaler, Sw as ClockSrc,
 | 
			
		||||
};
 | 
			
		||||
use crate::pac::rcc::vals::{Msirange, Pllsrc, Sw};
 | 
			
		||||
use crate::pac::{FLASH, RCC};
 | 
			
		||||
use crate::rcc::{set_freqs, Clocks};
 | 
			
		||||
use crate::time::Hertz;
 | 
			
		||||
@@ -11,42 +10,47 @@ use crate::time::Hertz;
 | 
			
		||||
/// HSI speed
 | 
			
		||||
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
 | 
			
		||||
 | 
			
		||||
/// System clock mux source
 | 
			
		||||
#[derive(Clone, Copy)]
 | 
			
		||||
pub enum ClockSrc {
 | 
			
		||||
    MSI(MSIRange),
 | 
			
		||||
    PLL(PLLSource, PllRDiv, PllPreDiv, PllMul, Option<PllQDiv>),
 | 
			
		||||
    HSE(Hertz),
 | 
			
		||||
    HSI16,
 | 
			
		||||
}
 | 
			
		||||
pub struct Pll {
 | 
			
		||||
    /// PLL pre-divider (DIVM).
 | 
			
		||||
    pub prediv: PllPreDiv,
 | 
			
		||||
 | 
			
		||||
/// PLL clock input source
 | 
			
		||||
#[derive(Clone, Copy)]
 | 
			
		||||
pub enum PLLSource {
 | 
			
		||||
    HSI16,
 | 
			
		||||
    HSE(Hertz),
 | 
			
		||||
    MSI(MSIRange),
 | 
			
		||||
}
 | 
			
		||||
    /// PLL multiplication factor.
 | 
			
		||||
    pub mul: PllMul,
 | 
			
		||||
 | 
			
		||||
impl From<PLLSource> for Pllsrc {
 | 
			
		||||
    fn from(val: PLLSource) -> Pllsrc {
 | 
			
		||||
        match val {
 | 
			
		||||
            PLLSource::HSI16 => Pllsrc::HSI16,
 | 
			
		||||
            PLLSource::HSE(_) => Pllsrc::HSE,
 | 
			
		||||
            PLLSource::MSI(_) => Pllsrc::MSI,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    /// PLL P division factor. If None, PLL P output is disabled.
 | 
			
		||||
    pub divp: Option<PllPDiv>,
 | 
			
		||||
    /// PLL Q division factor. If None, PLL Q output is disabled.
 | 
			
		||||
    pub divq: Option<PllQDiv>,
 | 
			
		||||
    /// PLL R division factor. If None, PLL R output is disabled.
 | 
			
		||||
    pub divr: Option<PllRDiv>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Clocks configutation
 | 
			
		||||
pub struct Config {
 | 
			
		||||
    // base clock sources
 | 
			
		||||
    pub msi: Option<MSIRange>,
 | 
			
		||||
    pub hsi16: bool,
 | 
			
		||||
    pub hse: Option<Hertz>,
 | 
			
		||||
    #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
 | 
			
		||||
    pub hsi48: bool,
 | 
			
		||||
 | 
			
		||||
    // pll
 | 
			
		||||
    pub pll_src: PLLSource,
 | 
			
		||||
    pub pll: Option<Pll>,
 | 
			
		||||
    pub pllsai1: Option<Pll>,
 | 
			
		||||
    #[cfg(any(
 | 
			
		||||
        stm32l47x, stm32l48x, stm32l49x, stm32l4ax, stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx
 | 
			
		||||
    ))]
 | 
			
		||||
    pub pllsai2: Option<Pll>,
 | 
			
		||||
 | 
			
		||||
    // sysclk, buses.
 | 
			
		||||
    pub mux: ClockSrc,
 | 
			
		||||
    pub ahb_pre: AHBPrescaler,
 | 
			
		||||
    pub apb1_pre: APBPrescaler,
 | 
			
		||||
    pub apb2_pre: APBPrescaler,
 | 
			
		||||
    pub pllsai1: Option<(PllMul, PllPreDiv, Option<PllRDiv>, Option<PllQDiv>, Option<PllPDiv>)>,
 | 
			
		||||
    #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
 | 
			
		||||
    pub hsi48: bool,
 | 
			
		||||
 | 
			
		||||
    // low speed LSI/LSE/RTC
 | 
			
		||||
    pub ls: super::LsConfig,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -54,11 +58,20 @@ impl Default for Config {
 | 
			
		||||
    #[inline]
 | 
			
		||||
    fn default() -> Config {
 | 
			
		||||
        Config {
 | 
			
		||||
            mux: ClockSrc::MSI(MSIRange::RANGE4M),
 | 
			
		||||
            hse: None,
 | 
			
		||||
            hsi16: false,
 | 
			
		||||
            msi: Some(MSIRange::RANGE4M),
 | 
			
		||||
            mux: ClockSrc::MSI,
 | 
			
		||||
            ahb_pre: AHBPrescaler::DIV1,
 | 
			
		||||
            apb1_pre: APBPrescaler::DIV1,
 | 
			
		||||
            apb2_pre: APBPrescaler::DIV1,
 | 
			
		||||
            pll_src: PLLSource::NONE,
 | 
			
		||||
            pll: None,
 | 
			
		||||
            pllsai1: None,
 | 
			
		||||
            #[cfg(any(
 | 
			
		||||
                stm32l47x, stm32l48x, stm32l49x, stm32l4ax, stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx
 | 
			
		||||
            ))]
 | 
			
		||||
            pllsai2: None,
 | 
			
		||||
            #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
 | 
			
		||||
            hsi48: false,
 | 
			
		||||
            ls: Default::default(),
 | 
			
		||||
@@ -80,154 +93,204 @@ pub(crate) unsafe fn init(config: Config) {
 | 
			
		||||
        // Wait until MSI is running
 | 
			
		||||
        while !RCC.cr().read().msirdy() {}
 | 
			
		||||
    }
 | 
			
		||||
    if RCC.cfgr().read().sws() != Sw::MSI {
 | 
			
		||||
    if RCC.cfgr().read().sws() != ClockSrc::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 {}
 | 
			
		||||
        while RCC.cfgr().read().sws() != ClockSrc::MSI {}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let rtc = config.ls.init();
 | 
			
		||||
 | 
			
		||||
    let (sys_clk, sw) = match config.mux {
 | 
			
		||||
        ClockSrc::MSI(range) => {
 | 
			
		||||
            // Enable MSI
 | 
			
		||||
            RCC.cr().write(|w| {
 | 
			
		||||
                w.set_msirange(range);
 | 
			
		||||
                w.set_msirgsel(true);
 | 
			
		||||
                w.set_msion(true);
 | 
			
		||||
    let msi = config.msi.map(|range| {
 | 
			
		||||
        // Enable MSI
 | 
			
		||||
        RCC.cr().write(|w| {
 | 
			
		||||
            w.set_msirange(range);
 | 
			
		||||
            w.set_msirgsel(true);
 | 
			
		||||
            w.set_msion(true);
 | 
			
		||||
 | 
			
		||||
                // If LSE is enabled, enable calibration of MSI
 | 
			
		||||
                w.set_msipllen(config.ls.lse.is_some());
 | 
			
		||||
            });
 | 
			
		||||
            while !RCC.cr().read().msirdy() {}
 | 
			
		||||
            // If LSE is enabled, enable calibration of MSI
 | 
			
		||||
            w.set_msipllen(config.ls.lse.is_some());
 | 
			
		||||
        });
 | 
			
		||||
        while !RCC.cr().read().msirdy() {}
 | 
			
		||||
 | 
			
		||||
            // Enable as clock source for USB, RNG if running at 48 MHz
 | 
			
		||||
            if range == MSIRange::RANGE48M {
 | 
			
		||||
                RCC.ccipr().modify(|w| {
 | 
			
		||||
                    w.set_clk48sel(0b11);
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
            (msirange_to_hertz(range), Sw::MSI)
 | 
			
		||||
        // Enable as clock source for USB, RNG if running at 48 MHz
 | 
			
		||||
        if range == MSIRange::RANGE48M {
 | 
			
		||||
            RCC.ccipr().modify(|w| w.set_clk48sel(0b11));
 | 
			
		||||
        }
 | 
			
		||||
        ClockSrc::HSI16 => {
 | 
			
		||||
            // Enable HSI16
 | 
			
		||||
            RCC.cr().write(|w| w.set_hsion(true));
 | 
			
		||||
            while !RCC.cr().read().hsirdy() {}
 | 
			
		||||
 | 
			
		||||
            (HSI_FREQ, Sw::HSI16)
 | 
			
		||||
        }
 | 
			
		||||
        ClockSrc::HSE(freq) => {
 | 
			
		||||
            // Enable HSE
 | 
			
		||||
            RCC.cr().write(|w| w.set_hseon(true));
 | 
			
		||||
            while !RCC.cr().read().hserdy() {}
 | 
			
		||||
        msirange_to_hertz(range)
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
            (freq, Sw::HSE)
 | 
			
		||||
        }
 | 
			
		||||
        ClockSrc::PLL(src, divr, prediv, mul, divq) => {
 | 
			
		||||
            let src_freq = match src {
 | 
			
		||||
                PLLSource::HSE(freq) => {
 | 
			
		||||
                    // Enable HSE
 | 
			
		||||
                    RCC.cr().write(|w| w.set_hseon(true));
 | 
			
		||||
                    while !RCC.cr().read().hserdy() {}
 | 
			
		||||
                    freq
 | 
			
		||||
                }
 | 
			
		||||
                PLLSource::HSI16 => {
 | 
			
		||||
                    // Enable HSI
 | 
			
		||||
                    RCC.cr().write(|w| w.set_hsion(true));
 | 
			
		||||
                    while !RCC.cr().read().hsirdy() {}
 | 
			
		||||
                    HSI_FREQ
 | 
			
		||||
                }
 | 
			
		||||
                PLLSource::MSI(range) => {
 | 
			
		||||
                    // Enable MSI
 | 
			
		||||
                    RCC.cr().write(|w| {
 | 
			
		||||
                        w.set_msirange(range);
 | 
			
		||||
                        w.set_msipllen(false); // should be turned on if LSE is started
 | 
			
		||||
                        w.set_msirgsel(true);
 | 
			
		||||
                        w.set_msion(true);
 | 
			
		||||
                    });
 | 
			
		||||
                    while !RCC.cr().read().msirdy() {}
 | 
			
		||||
    let hsi16 = config.hsi16.then(|| {
 | 
			
		||||
        RCC.cr().write(|w| w.set_hsion(true));
 | 
			
		||||
        while !RCC.cr().read().hsirdy() {}
 | 
			
		||||
 | 
			
		||||
                    msirange_to_hertz(range)
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
        HSI_FREQ
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
            // Disable PLL
 | 
			
		||||
            RCC.cr().modify(|w| w.set_pllon(false));
 | 
			
		||||
            while RCC.cr().read().pllrdy() {}
 | 
			
		||||
    let hse = config.hse.map(|freq| {
 | 
			
		||||
        RCC.cr().write(|w| w.set_hseon(true));
 | 
			
		||||
        while !RCC.cr().read().hserdy() {}
 | 
			
		||||
 | 
			
		||||
            let freq = src_freq / prediv * mul / divr;
 | 
			
		||||
 | 
			
		||||
            #[cfg(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx))]
 | 
			
		||||
            assert!(freq.0 <= 120_000_000);
 | 
			
		||||
            #[cfg(not(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx)))]
 | 
			
		||||
            assert!(freq.0 <= 80_000_000);
 | 
			
		||||
 | 
			
		||||
            RCC.pllcfgr().write(move |w| {
 | 
			
		||||
                w.set_plln(mul);
 | 
			
		||||
                w.set_pllm(prediv);
 | 
			
		||||
                w.set_pllr(divr);
 | 
			
		||||
                if let Some(divq) = divq {
 | 
			
		||||
                    w.set_pllq(divq);
 | 
			
		||||
                    w.set_pllqen(true);
 | 
			
		||||
                }
 | 
			
		||||
                w.set_pllsrc(src.into());
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            // Enable as clock source for USB, RNG if PLL48 divisor is provided
 | 
			
		||||
            if let Some(divq) = divq {
 | 
			
		||||
                let freq = src_freq / prediv * mul / divq;
 | 
			
		||||
                assert!(freq.0 == 48_000_000);
 | 
			
		||||
                RCC.ccipr().modify(|w| {
 | 
			
		||||
                    w.set_clk48sel(0b10);
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if let Some((mul, prediv, r_div, q_div, p_div)) = config.pllsai1 {
 | 
			
		||||
                RCC.pllsai1cfgr().write(move |w| {
 | 
			
		||||
                    w.set_plln(mul);
 | 
			
		||||
                    w.set_pllm(prediv);
 | 
			
		||||
                    if let Some(r_div) = r_div {
 | 
			
		||||
                        w.set_pllr(r_div);
 | 
			
		||||
                        w.set_pllren(true);
 | 
			
		||||
                    }
 | 
			
		||||
                    if let Some(q_div) = q_div {
 | 
			
		||||
                        w.set_pllq(q_div);
 | 
			
		||||
                        w.set_pllqen(true);
 | 
			
		||||
                        let freq = src_freq / prediv * mul / q_div;
 | 
			
		||||
                        if freq.0 == 48_000_000 {
 | 
			
		||||
                            RCC.ccipr().modify(|w| {
 | 
			
		||||
                                w.set_clk48sel(0b1);
 | 
			
		||||
                            });
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    if let Some(p_div) = p_div {
 | 
			
		||||
                        w.set_pllp(p_div);
 | 
			
		||||
                        w.set_pllpen(true);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                RCC.cr().modify(|w| w.set_pllsai1on(true));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Enable PLL
 | 
			
		||||
            RCC.cr().modify(|w| w.set_pllon(true));
 | 
			
		||||
            while !RCC.cr().read().pllrdy() {}
 | 
			
		||||
            RCC.pllcfgr().modify(|w| w.set_pllren(true));
 | 
			
		||||
 | 
			
		||||
            (freq, Sw::PLL)
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
        freq
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
 | 
			
		||||
    if config.hsi48 {
 | 
			
		||||
    let _hsi48 = config.hsi48.then(|| {
 | 
			
		||||
        RCC.crrcr().modify(|w| w.set_hsi48on(true));
 | 
			
		||||
        while !RCC.crrcr().read().hsi48rdy() {}
 | 
			
		||||
 | 
			
		||||
        // Enable as clock source for USB, RNG and SDMMC
 | 
			
		||||
        RCC.ccipr().modify(|w| w.set_clk48sel(0));
 | 
			
		||||
 | 
			
		||||
        Hertz(48_000_000)
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    let pll_src = match config.pll_src {
 | 
			
		||||
        PLLSource::NONE => None,
 | 
			
		||||
        PLLSource::HSE => hse,
 | 
			
		||||
        PLLSource::HSI16 => hsi16,
 | 
			
		||||
        PLLSource::MSI => msi,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let mut _pllp = None;
 | 
			
		||||
    let mut _pllq = None;
 | 
			
		||||
    let mut _pllr = None;
 | 
			
		||||
    if let Some(pll) = config.pll {
 | 
			
		||||
        let pll_src = pll_src.unwrap();
 | 
			
		||||
 | 
			
		||||
        // Disable PLL
 | 
			
		||||
        RCC.cr().modify(|w| w.set_pllon(false));
 | 
			
		||||
        while RCC.cr().read().pllrdy() {}
 | 
			
		||||
 | 
			
		||||
        let vco_freq = pll_src / pll.prediv * pll.mul;
 | 
			
		||||
 | 
			
		||||
        _pllp = pll.divp.map(|div| vco_freq / div);
 | 
			
		||||
        _pllq = pll.divq.map(|div| vco_freq / div);
 | 
			
		||||
        _pllr = pll.divr.map(|div| vco_freq / div);
 | 
			
		||||
 | 
			
		||||
        RCC.pllcfgr().write(move |w| {
 | 
			
		||||
            w.set_plln(pll.mul);
 | 
			
		||||
            w.set_pllm(pll.prediv);
 | 
			
		||||
            w.set_pllsrc(config.pll_src);
 | 
			
		||||
            if let Some(divp) = pll.divp {
 | 
			
		||||
                w.set_pllp(divp);
 | 
			
		||||
                w.set_pllpen(true);
 | 
			
		||||
            }
 | 
			
		||||
            if let Some(divq) = pll.divq {
 | 
			
		||||
                w.set_pllq(divq);
 | 
			
		||||
                w.set_pllqen(true);
 | 
			
		||||
            }
 | 
			
		||||
            if let Some(divr) = pll.divr {
 | 
			
		||||
                w.set_pllr(divr);
 | 
			
		||||
                w.set_pllren(true);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        if _pllq == Some(Hertz(48_000_000)) {
 | 
			
		||||
            RCC.ccipr().modify(|w| w.set_clk48sel(0b10));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Enable PLL
 | 
			
		||||
        RCC.cr().modify(|w| w.set_pllon(true));
 | 
			
		||||
        while !RCC.cr().read().pllrdy() {}
 | 
			
		||||
    } else {
 | 
			
		||||
        // even if we're not using the main pll, set the source for pllsai
 | 
			
		||||
        RCC.pllcfgr().write(move |w| {
 | 
			
		||||
            w.set_pllsrc(config.pll_src);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if let Some(pll) = config.pllsai1 {
 | 
			
		||||
        let pll_src = pll_src.unwrap();
 | 
			
		||||
 | 
			
		||||
        // Disable PLL
 | 
			
		||||
        RCC.cr().modify(|w| w.set_pllsai1on(false));
 | 
			
		||||
        while RCC.cr().read().pllsai1rdy() {}
 | 
			
		||||
 | 
			
		||||
        let vco_freq = pll_src / pll.prediv * pll.mul;
 | 
			
		||||
 | 
			
		||||
        let _pllp = pll.divp.map(|div| vco_freq / div);
 | 
			
		||||
        let _pllq = pll.divq.map(|div| vco_freq / div);
 | 
			
		||||
        let _pllr = pll.divr.map(|div| vco_freq / div);
 | 
			
		||||
 | 
			
		||||
        RCC.pllsai1cfgr().write(move |w| {
 | 
			
		||||
            w.set_plln(pll.mul);
 | 
			
		||||
            w.set_pllm(pll.prediv);
 | 
			
		||||
            if let Some(divp) = pll.divp {
 | 
			
		||||
                w.set_pllp(divp);
 | 
			
		||||
                w.set_pllpen(true);
 | 
			
		||||
            }
 | 
			
		||||
            if let Some(divq) = pll.divq {
 | 
			
		||||
                w.set_pllq(divq);
 | 
			
		||||
                w.set_pllqen(true);
 | 
			
		||||
            }
 | 
			
		||||
            if let Some(divr) = pll.divr {
 | 
			
		||||
                w.set_pllr(divr);
 | 
			
		||||
                w.set_pllren(true);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        if _pllq == Some(Hertz(48_000_000)) {
 | 
			
		||||
            RCC.ccipr().modify(|w| w.set_clk48sel(0b01));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Enable PLL
 | 
			
		||||
        RCC.cr().modify(|w| w.set_pllsai1on(true));
 | 
			
		||||
        while !RCC.cr().read().pllsai1rdy() {}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(any(
 | 
			
		||||
        stm32l47x, stm32l48x, stm32l49x, stm32l4ax, stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx
 | 
			
		||||
    ))]
 | 
			
		||||
    if let Some(pll) = config.pllsai2 {
 | 
			
		||||
        let pll_src = pll_src.unwrap();
 | 
			
		||||
 | 
			
		||||
        // Disable PLL
 | 
			
		||||
        RCC.cr().modify(|w| w.set_pllsai2on(false));
 | 
			
		||||
        while RCC.cr().read().pllsai2rdy() {}
 | 
			
		||||
 | 
			
		||||
        let vco_freq = pll_src / pll.prediv * pll.mul;
 | 
			
		||||
 | 
			
		||||
        let _pllp = pll.divp.map(|div| vco_freq / div);
 | 
			
		||||
        let _pllq = pll.divq.map(|div| vco_freq / div);
 | 
			
		||||
        let _pllr = pll.divr.map(|div| vco_freq / div);
 | 
			
		||||
 | 
			
		||||
        RCC.pllsai2cfgr().write(move |w| {
 | 
			
		||||
            w.set_plln(pll.mul);
 | 
			
		||||
            w.set_pllm(pll.prediv);
 | 
			
		||||
            if let Some(divp) = pll.divp {
 | 
			
		||||
                w.set_pllp(divp);
 | 
			
		||||
                w.set_pllpen(true);
 | 
			
		||||
            }
 | 
			
		||||
            if let Some(divq) = pll.divq {
 | 
			
		||||
                w.set_pllq(divq);
 | 
			
		||||
                w.set_pllqen(true);
 | 
			
		||||
            }
 | 
			
		||||
            if let Some(divr) = pll.divr {
 | 
			
		||||
                w.set_pllr(divr);
 | 
			
		||||
                w.set_pllren(true);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // Enable PLL
 | 
			
		||||
        RCC.cr().modify(|w| w.set_pllsai2on(true));
 | 
			
		||||
        while !RCC.cr().read().pllsai2rdy() {}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let sys_clk = match config.mux {
 | 
			
		||||
        ClockSrc::HSE => hse.unwrap(),
 | 
			
		||||
        ClockSrc::HSI16 => hsi16.unwrap(),
 | 
			
		||||
        ClockSrc::MSI => msi.unwrap(),
 | 
			
		||||
        ClockSrc::PLL => _pllr.unwrap(),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    #[cfg(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx))]
 | 
			
		||||
    assert!(sys_clk.0 <= 120_000_000);
 | 
			
		||||
    #[cfg(not(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx)))]
 | 
			
		||||
    assert!(sys_clk.0 <= 80_000_000);
 | 
			
		||||
 | 
			
		||||
    // Set flash wait states
 | 
			
		||||
    FLASH.acr().modify(|w| {
 | 
			
		||||
        w.set_latency(match sys_clk.0 {
 | 
			
		||||
@@ -240,7 +303,7 @@ pub(crate) unsafe fn init(config: Config) {
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    RCC.cfgr().modify(|w| {
 | 
			
		||||
        w.set_sw(sw);
 | 
			
		||||
        w.set_sw(config.mux);
 | 
			
		||||
        w.set_hpre(config.ahb_pre);
 | 
			
		||||
        w.set_ppre1(config.apb1_pre);
 | 
			
		||||
        w.set_ppre2(config.apb2_pre);
 | 
			
		||||
@@ -277,7 +340,7 @@ pub(crate) unsafe fn init(config: Config) {
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn msirange_to_hertz(range: Msirange) -> Hertz {
 | 
			
		||||
fn msirange_to_hertz(range: MSIRange) -> Hertz {
 | 
			
		||||
    match range {
 | 
			
		||||
        MSIRange::RANGE100K => Hertz(100_000),
 | 
			
		||||
        MSIRange::RANGE200K => Hertz(200_000),
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
 | 
			
		||||
use defmt::*;
 | 
			
		||||
use embassy_executor::Spawner;
 | 
			
		||||
use embassy_stm32::rcc::{ClockSrc, PLLSource, PllMul, PllPreDiv, PllQDiv, PllRDiv};
 | 
			
		||||
use embassy_stm32::rcc::{ClockSrc, PLLSource, Pll, PllMul, PllPreDiv, PllQDiv, PllRDiv};
 | 
			
		||||
use embassy_stm32::rng::Rng;
 | 
			
		||||
use embassy_stm32::{bind_interrupts, peripherals, rng, Config};
 | 
			
		||||
use {defmt_rtt as _, panic_probe as _};
 | 
			
		||||
@@ -16,14 +16,16 @@ bind_interrupts!(struct Irqs {
 | 
			
		||||
#[embassy_executor::main]
 | 
			
		||||
async fn main(_spawner: Spawner) {
 | 
			
		||||
    let mut config = Config::default();
 | 
			
		||||
    // 72Mhz clock (16 / 1 * 18 / 4)
 | 
			
		||||
    config.rcc.mux = ClockSrc::PLL(
 | 
			
		||||
        PLLSource::HSI16,
 | 
			
		||||
        PllRDiv::DIV4,
 | 
			
		||||
        PllPreDiv::DIV1,
 | 
			
		||||
        PllMul::MUL18,
 | 
			
		||||
        Some(PllQDiv::DIV6), // 48Mhz (16 / 1 * 18 / 6)
 | 
			
		||||
    );
 | 
			
		||||
    config.rcc.mux = ClockSrc::PLL;
 | 
			
		||||
    config.rcc.hsi16 = true;
 | 
			
		||||
    config.rcc.pll_src = PLLSource::HSI16;
 | 
			
		||||
    config.rcc.pll = Some(Pll {
 | 
			
		||||
        prediv: PllPreDiv::DIV1,
 | 
			
		||||
        mul: PllMul::MUL18,
 | 
			
		||||
        divp: None,
 | 
			
		||||
        divq: Some(PllQDiv::DIV6), // 48Mhz (16 / 1 * 18 / 6)
 | 
			
		||||
        divr: Some(PllRDiv::DIV4), // sysclk 72Mhz clock (16 / 1 * 18 / 4)
 | 
			
		||||
    });
 | 
			
		||||
    let p = embassy_stm32::init(config);
 | 
			
		||||
 | 
			
		||||
    info!("Hello World!");
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
use chrono::{NaiveDate, NaiveDateTime};
 | 
			
		||||
use defmt::*;
 | 
			
		||||
use embassy_executor::Spawner;
 | 
			
		||||
use embassy_stm32::rcc::{ClockSrc, LsConfig, PLLSource, PllMul, PllPreDiv, PllRDiv};
 | 
			
		||||
use embassy_stm32::rcc::{ClockSrc, LsConfig, PLLSource, Pll, PllMul, PllPreDiv, PllRDiv};
 | 
			
		||||
use embassy_stm32::rtc::{Rtc, RtcConfig};
 | 
			
		||||
use embassy_stm32::time::Hertz;
 | 
			
		||||
use embassy_stm32::Config;
 | 
			
		||||
@@ -14,18 +14,20 @@ use {defmt_rtt as _, panic_probe as _};
 | 
			
		||||
 | 
			
		||||
#[embassy_executor::main]
 | 
			
		||||
async fn main(_spawner: Spawner) {
 | 
			
		||||
    let p = {
 | 
			
		||||
        let mut config = Config::default();
 | 
			
		||||
        config.rcc.mux = ClockSrc::PLL(
 | 
			
		||||
            PLLSource::HSE(Hertz::mhz(8)),
 | 
			
		||||
            PllRDiv::DIV2,
 | 
			
		||||
            PllPreDiv::DIV1,
 | 
			
		||||
            PllMul::MUL20,
 | 
			
		||||
            None,
 | 
			
		||||
        );
 | 
			
		||||
        config.rcc.ls = LsConfig::default_lse();
 | 
			
		||||
        embassy_stm32::init(config)
 | 
			
		||||
    };
 | 
			
		||||
    let mut config = Config::default();
 | 
			
		||||
    config.rcc.mux = ClockSrc::PLL;
 | 
			
		||||
    config.rcc.hse = Some(Hertz::mhz(8));
 | 
			
		||||
    config.rcc.pll_src = PLLSource::HSE;
 | 
			
		||||
    config.rcc.pll = Some(Pll {
 | 
			
		||||
        prediv: PllPreDiv::DIV1,
 | 
			
		||||
        mul: PllMul::MUL20,
 | 
			
		||||
        divp: None,
 | 
			
		||||
        divq: None,
 | 
			
		||||
        divr: Some(PllRDiv::DIV2), // sysclk 80Mhz clock (8 / 1 * 20 / 2)
 | 
			
		||||
    });
 | 
			
		||||
    config.rcc.ls = LsConfig::default_lse();
 | 
			
		||||
    let p = embassy_stm32::init(config);
 | 
			
		||||
 | 
			
		||||
    info!("Hello World!");
 | 
			
		||||
 | 
			
		||||
    let now = NaiveDate::from_ymd_opt(2020, 5, 15)
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,7 @@ use embassy_net_adin1110::{self, Device, Runner, ADIN1110};
 | 
			
		||||
use embedded_hal_bus::spi::ExclusiveDevice;
 | 
			
		||||
use hal::gpio::Pull;
 | 
			
		||||
use hal::i2c::Config as I2C_Config;
 | 
			
		||||
use hal::rcc::{ClockSrc, PLLSource, PllMul, PllPreDiv, PllRDiv};
 | 
			
		||||
use hal::rcc::{ClockSrc, PLLSource, Pll, PllMul, PllPreDiv, PllRDiv};
 | 
			
		||||
use hal::spi::{Config as SPI_Config, Spi};
 | 
			
		||||
use hal::time::Hertz;
 | 
			
		||||
 | 
			
		||||
@@ -77,13 +77,16 @@ async fn main(spawner: Spawner) {
 | 
			
		||||
 | 
			
		||||
    // 80Mhz clock (Source: 8 / SrcDiv: 1 * PLLMul 20 / ClkDiv 2)
 | 
			
		||||
    // 80MHz highest frequency for flash 0 wait.
 | 
			
		||||
    config.rcc.mux = ClockSrc::PLL(
 | 
			
		||||
        PLLSource::HSE(Hertz(8_000_000)),
 | 
			
		||||
        PllRDiv::DIV2,
 | 
			
		||||
        PllPreDiv::DIV1,
 | 
			
		||||
        PllMul::MUL20,
 | 
			
		||||
        None,
 | 
			
		||||
    );
 | 
			
		||||
    config.rcc.mux = ClockSrc::PLL;
 | 
			
		||||
    config.rcc.hse = Some(Hertz::mhz(8));
 | 
			
		||||
    config.rcc.pll_src = PLLSource::HSE;
 | 
			
		||||
    config.rcc.pll = Some(Pll {
 | 
			
		||||
        prediv: PllPreDiv::DIV1,
 | 
			
		||||
        mul: PllMul::MUL20,
 | 
			
		||||
        divp: None,
 | 
			
		||||
        divq: None,
 | 
			
		||||
        divr: Some(PllRDiv::DIV2), // sysclk 80Mhz clock (8 / 1 * 20 / 2)
 | 
			
		||||
    });
 | 
			
		||||
    config.rcc.hsi48 = true; // needed for rng
 | 
			
		||||
 | 
			
		||||
    let dp = embassy_stm32::init(config);
 | 
			
		||||
 
 | 
			
		||||
@@ -23,8 +23,17 @@ async fn main(_spawner: Spawner) {
 | 
			
		||||
    info!("Hello World!");
 | 
			
		||||
 | 
			
		||||
    let mut config = Config::default();
 | 
			
		||||
    config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PllRDiv::DIV2, PllPreDiv::DIV1, PllMul::MUL10, None);
 | 
			
		||||
    config.rcc.hsi48 = true;
 | 
			
		||||
    config.rcc.mux = ClockSrc::PLL;
 | 
			
		||||
    config.rcc.hsi16 = true;
 | 
			
		||||
    config.rcc.pll_src = PLLSource::HSI16;
 | 
			
		||||
    config.rcc.pll = Some(Pll {
 | 
			
		||||
        prediv: PllPreDiv::DIV1,
 | 
			
		||||
        mul: PllMul::MUL10,
 | 
			
		||||
        divp: None,
 | 
			
		||||
        divq: None,
 | 
			
		||||
        divr: Some(PllRDiv::DIV2), // sysclk 80Mhz (16 / 1 * 10 / 2)
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    let p = embassy_stm32::init(config);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -284,17 +284,19 @@ pub fn config() -> Config {
 | 
			
		||||
        config.rcc.adc_clock_source = AdcClockSource::PLL2_P;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(any(feature = "stm32l4a6zg", feature = "stm32l4r5zi"))]
 | 
			
		||||
    #[cfg(any(feature = "stm32l496zg", feature = "stm32l4a6zg", feature = "stm32l4r5zi"))]
 | 
			
		||||
    {
 | 
			
		||||
        use embassy_stm32::rcc::*;
 | 
			
		||||
        config.rcc.mux = ClockSrc::PLL(
 | 
			
		||||
            // 72Mhz clock (16 / 1 * 18 / 4)
 | 
			
		||||
            PLLSource::HSI16,
 | 
			
		||||
            PllRDiv::DIV4,
 | 
			
		||||
            PllPreDiv::DIV1,
 | 
			
		||||
            PllMul::MUL18,
 | 
			
		||||
            Some(PllQDiv::DIV6), // 48Mhz (16 / 1 * 18 / 6)
 | 
			
		||||
        );
 | 
			
		||||
        config.rcc.mux = ClockSrc::PLL;
 | 
			
		||||
        config.rcc.hsi16 = true;
 | 
			
		||||
        config.rcc.pll_src = PLLSource::HSI16;
 | 
			
		||||
        config.rcc.pll = Some(Pll {
 | 
			
		||||
            prediv: PllPreDiv::DIV1,
 | 
			
		||||
            mul: PllMul::MUL18,
 | 
			
		||||
            divp: None,
 | 
			
		||||
            divq: Some(PllQDiv::DIV6), // 48Mhz (16 / 1 * 18 / 6)
 | 
			
		||||
            divr: Some(PllRDiv::DIV4), // sysclk 72Mhz clock (16 / 1 * 18 / 4)
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(any(feature = "stm32l552ze"))]
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user