diff --git a/embassy-stm32/src/rcc/l0l1.rs b/embassy-stm32/src/rcc/l0l1.rs index 9fb2062d..3af27959 100644 --- a/embassy-stm32/src/rcc/l0l1.rs +++ b/embassy-stm32/src/rcc/l0l1.rs @@ -1,8 +1,8 @@ pub use crate::pac::pwr::vals::Vos as VoltageScale; pub use crate::pac::rcc::vals::{ - Hpre as AHBPrescaler, Msirange as MSIRange, Plldiv as PLLDiv, Pllmul as PLLMul, Ppre as APBPrescaler, + Hpre as AHBPrescaler, Msirange as MSIRange, Plldiv as PLLDiv, Plldiv as PllDiv, Pllmul as PLLMul, Pllmul as PllMul, + Pllsrc as PLLSource, Ppre as APBPrescaler, Sw as ClockSrc, }; -use crate::pac::rcc::vals::{Pllsrc, Sw}; #[cfg(crs)] use crate::pac::{crs, CRS, SYSCFG}; use crate::pac::{FLASH, PWR, RCC}; @@ -12,39 +12,50 @@ 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, PLLMul, PLLDiv), - HSE(Hertz), - HSI, +#[derive(Clone, Copy, Eq, PartialEq)] +pub enum HseMode { + /// crystal/ceramic oscillator (HSEBYP=0) + Oscillator, + /// external analog clock (low swing) (HSEBYP=1) + Bypass, } -/// PLL clock input source -#[derive(Clone, Copy)] -pub enum PLLSource { - HSI, - HSE(Hertz), +#[derive(Clone, Copy, Eq, PartialEq)] +pub struct Hse { + /// HSE frequency. + pub freq: Hertz, + /// HSE mode. + pub mode: HseMode, } -impl From for Pllsrc { - fn from(val: PLLSource) -> Pllsrc { - match val { - PLLSource::HSI => Pllsrc::HSI, - PLLSource::HSE(_) => Pllsrc::HSE, - } - } +#[derive(Clone, Copy)] +pub struct Pll { + /// PLL source + pub source: PLLSource, + + /// PLL multiplication factor. + pub mul: PllMul, + + /// PLL main output division factor. + pub div: PllDiv, } /// Clocks configutation pub struct Config { + // base clock sources + pub msi: Option, + pub hsi: bool, + pub hse: Option, + #[cfg(crs)] + pub hsi48: bool, + + pub pll: Option, + pub mux: ClockSrc, pub ahb_pre: AHBPrescaler, pub apb1_pre: APBPrescaler, pub apb2_pre: APBPrescaler, - #[cfg(crs)] - pub enable_hsi48: bool, + pub ls: super::LsConfig, pub voltage_scale: VoltageScale, } @@ -53,12 +64,18 @@ impl Default for Config { #[inline] fn default() -> Config { Config { - mux: ClockSrc::MSI(MSIRange::RANGE5), + msi: Some(MSIRange::RANGE5), + hse: None, + hsi: false, + #[cfg(crs)] + hsi48: false, + + pll: None, + + mux: ClockSrc::MSI, ahb_pre: AHBPrescaler::DIV1, apb1_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1, - #[cfg(crs)] - enable_hsi48: false, voltage_scale: VoltageScale::RANGE1, ls: Default::default(), } @@ -71,72 +88,68 @@ pub(crate) unsafe fn init(config: Config) { PWR.cr().write(|w| w.set_vos(config.voltage_scale)); while PWR.csr().read().vosf() {} - let (sys_clk, sw) = match config.mux { - ClockSrc::MSI(range) => { - // Set MSI range - RCC.icscr().write(|w| w.set_msirange(range)); - - // Enable MSI - RCC.cr().write(|w| w.set_msion(true)); - while !RCC.cr().read().msirdy() {} - - let freq = 32_768 * (1 << (range as u8 + 1)); - (Hertz(freq), Sw::MSI) - } - ClockSrc::HSI => { - // Enable HSI - RCC.cr().write(|w| w.set_hsion(true)); - while !RCC.cr().read().hsirdy() {} - - (HSI_FREQ, Sw::HSI) - } - ClockSrc::HSE(freq) => { - // Enable HSE - RCC.cr().write(|w| w.set_hseon(true)); - while !RCC.cr().read().hserdy() {} - - (freq, Sw::HSE) - } - ClockSrc::PLL(src, mul, div) => { - let freq = match src { - PLLSource::HSE(freq) => { - // Enable HSE - RCC.cr().write(|w| w.set_hseon(true)); - while !RCC.cr().read().hserdy() {} - freq - } - PLLSource::HSI => { - // Enable HSI - RCC.cr().write(|w| w.set_hsion(true)); - while !RCC.cr().read().hsirdy() {} - HSI_FREQ - } - }; - - // Disable PLL - RCC.cr().modify(|w| w.set_pllon(false)); - while RCC.cr().read().pllrdy() {} - - let freq = freq * mul / div; - - assert!(freq <= Hertz(32_000_000)); - - RCC.cfgr().write(move |w| { - w.set_pllmul(mul); - w.set_plldiv(div); - w.set_pllsrc(src.into()); - }); - - // Enable PLL - RCC.cr().modify(|w| w.set_pllon(true)); - while !RCC.cr().read().pllrdy() {} - - (freq, Sw::PLL1_P) - } - }; - let rtc = config.ls.init(); + let msi = config.msi.map(|range| { + RCC.icscr().modify(|w| w.set_msirange(range)); + + RCC.cr().modify(|w| w.set_msion(true)); + while !RCC.cr().read().msirdy() {} + + Hertz(32_768 * (1 << (range as u8 + 1))) + }); + + let hsi = config.hsi.then(|| { + RCC.cr().modify(|w| w.set_hsion(true)); + while !RCC.cr().read().hsirdy() {} + + HSI_FREQ + }); + + let hse = config.hse.map(|hse| { + RCC.cr().modify(|w| { + w.set_hsebyp(hse.mode == HseMode::Bypass); + w.set_hseon(true); + }); + while !RCC.cr().read().hserdy() {} + + hse.freq + }); + + let pll = config.pll.map(|pll| { + let freq = match pll.source { + PLLSource::HSE => hse.unwrap(), + PLLSource::HSI => hsi.unwrap(), + }; + + // Disable PLL + RCC.cr().modify(|w| w.set_pllon(false)); + while RCC.cr().read().pllrdy() {} + + let freq = freq * pll.mul / pll.div; + + assert!(freq <= Hertz(32_000_000)); + + RCC.cfgr().write(move |w| { + w.set_pllmul(pll.mul); + w.set_plldiv(pll.div); + w.set_pllsrc(pll.source); + }); + + // Enable PLL + RCC.cr().modify(|w| w.set_pllon(true)); + while !RCC.cr().read().pllrdy() {} + + freq + }); + + let sys_clk = match config.mux { + ClockSrc::HSE => hse.unwrap(), + ClockSrc::HSI => hsi.unwrap(), + ClockSrc::MSI => msi.unwrap(), + ClockSrc::PLL1_P => pll.unwrap(), + }; + let wait_states = match (config.voltage_scale, sys_clk.0) { (VoltageScale::RANGE1, ..=16_000_000) => 0, (VoltageScale::RANGE2, ..=8_000_000) => 0, @@ -150,7 +163,7 @@ pub(crate) unsafe fn init(config: Config) { FLASH.acr().modify(|w| w.set_latency(wait_states != 0)); 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); @@ -161,7 +174,7 @@ pub(crate) unsafe fn init(config: Config) { let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre); #[cfg(crs)] - if config.enable_hsi48 { + if config.hsi48 { // Reset CRS peripheral RCC.apb1rstr().modify(|w| w.set_crsrst(true)); RCC.apb1rstr().modify(|w| w.set_crsrst(false)); diff --git a/embassy-stm32/src/rcc/l4l5.rs b/embassy-stm32/src/rcc/l4l5.rs index 0d052713..44748620 100644 --- a/embassy-stm32/src/rcc/l4l5.rs +++ b/embassy-stm32/src/rcc/l4l5.rs @@ -193,9 +193,6 @@ pub(crate) unsafe fn init(config: Config) { }); while !RCC.cr().read().msirdy() {} - // Enable as clock source for USB, RNG if running at 48 MHz - if range == MSIRange::RANGE48M {} - msirange_to_hertz(range) }); diff --git a/examples/stm32l0/src/bin/button_exti.rs b/examples/stm32l0/src/bin/button_exti.rs index af82b995..441b00c6 100644 --- a/examples/stm32l0/src/bin/button_exti.rs +++ b/examples/stm32l0/src/bin/button_exti.rs @@ -12,7 +12,7 @@ use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] async fn main(_spawner: Spawner) { let mut config = Config::default(); - config.rcc.enable_hsi48 = true; + config.rcc.hsi48 = true; let p = embassy_stm32::init(config); let button = Input::new(p.PB2, Pull::Up); diff --git a/examples/stm32l0/src/bin/lora_cad.rs b/examples/stm32l0/src/bin/lora_cad.rs index 5c2b331c..61024ef7 100644 --- a/examples/stm32l0/src/bin/lora_cad.rs +++ b/examples/stm32l0/src/bin/lora_cad.rs @@ -24,7 +24,7 @@ const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriatel async fn main(_spawner: Spawner) { let mut config = embassy_stm32::Config::default(); config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI; - config.rcc.enable_hsi48 = true; + config.rcc.hsi48 = true; let p = embassy_stm32::init(config); let mut spi_config = spi::Config::default(); diff --git a/examples/stm32l0/src/bin/lora_lorawan.rs b/examples/stm32l0/src/bin/lora_lorawan.rs index d44d03d3..9c4f3291 100644 --- a/examples/stm32l0/src/bin/lora_lorawan.rs +++ b/examples/stm32l0/src/bin/lora_lorawan.rs @@ -34,7 +34,7 @@ const LORAWAN_REGION: region::Region = region::Region::EU868; // warning: set th async fn main(_spawner: Spawner) { let mut config = embassy_stm32::Config::default(); config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI; - config.rcc.enable_hsi48 = true; + config.rcc.hsi48 = true; let p = embassy_stm32::init(config); let mut spi_config = spi::Config::default(); diff --git a/examples/stm32l0/src/bin/lora_p2p_receive.rs b/examples/stm32l0/src/bin/lora_p2p_receive.rs index 0478ce1e..4a50182c 100644 --- a/examples/stm32l0/src/bin/lora_p2p_receive.rs +++ b/examples/stm32l0/src/bin/lora_p2p_receive.rs @@ -24,7 +24,7 @@ const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriatel async fn main(_spawner: Spawner) { let mut config = embassy_stm32::Config::default(); config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI; - config.rcc.enable_hsi48 = true; + config.rcc.hsi48 = true; let p = embassy_stm32::init(config); let mut spi_config = spi::Config::default(); diff --git a/examples/stm32l0/src/bin/lora_p2p_send.rs b/examples/stm32l0/src/bin/lora_p2p_send.rs index 88a836d3..f6de6a5c 100644 --- a/examples/stm32l0/src/bin/lora_p2p_send.rs +++ b/examples/stm32l0/src/bin/lora_p2p_send.rs @@ -24,7 +24,7 @@ const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriatel async fn main(_spawner: Spawner) { let mut config = embassy_stm32::Config::default(); config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI; - config.rcc.enable_hsi48 = true; + config.rcc.hsi48 = true; let p = embassy_stm32::init(config); let mut spi_config = spi::Config::default(); diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs index ff808281..54e23e43 100644 --- a/tests/stm32/src/common.rs +++ b/tests/stm32/src/common.rs @@ -460,23 +460,25 @@ pub fn config() -> Config { #[cfg(feature = "stm32l073rz")] { use embassy_stm32::rcc::*; - config.rcc.mux = ClockSrc::PLL( - // 32Mhz clock (16 * 4 / 2) - PLLSource::HSI, - PLLMul::MUL4, - PLLDiv::DIV2, - ); + config.rcc.hsi = true; + config.rcc.pll = Some(Pll { + source: PLLSource::HSI, + mul: PLLMul::MUL4, + div: PLLDiv::DIV2, // 32Mhz clock (16 * 4 / 2) + }); + config.rcc.mux = ClockSrc::PLL1_P; } #[cfg(any(feature = "stm32l152re"))] { use embassy_stm32::rcc::*; - config.rcc.mux = ClockSrc::PLL( - // 32Mhz clock (16 * 4 / 2) - PLLSource::HSI, - PLLMul::MUL4, - PLLDiv::DIV2, - ); + config.rcc.hsi = true; + config.rcc.pll = Some(Pll { + source: PLLSource::HSI, + mul: PLLMul::MUL4, + div: PLLDiv::DIV2, // 32Mhz clock (16 * 4 / 2) + }); + config.rcc.mux = ClockSrc::PLL1_P; } config