#![macro_use] use core::mem::MaybeUninit; use crate::time::Hertz; mod bd; mod mco; pub use bd::*; pub use mco::*; #[cfg_attr(rcc_f0, path = "f0.rs")] #[cfg_attr(any(rcc_f1, rcc_f100, rcc_f1cl), path = "f1.rs")] #[cfg_attr(rcc_f2, path = "f2.rs")] #[cfg_attr(any(rcc_f3, rcc_f3_v2), path = "f3.rs")] #[cfg_attr(any(rcc_f4, rcc_f410, rcc_f7), path = "f4f7.rs")] #[cfg_attr(rcc_c0, path = "c0.rs")] #[cfg_attr(rcc_g0, path = "g0.rs")] #[cfg_attr(rcc_g4, path = "g4.rs")] #[cfg_attr(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab), path = "h.rs")] #[cfg_attr(any(rcc_l0, rcc_l0_v2, rcc_l1), path = "l0l1.rs")] #[cfg_attr(any(rcc_l4, rcc_l4plus, rcc_l5, rcc_wl5, rcc_wle, rcc_wb), path = "l4l5.rs")] #[cfg_attr(rcc_u5, path = "u5.rs")] #[cfg_attr(rcc_wba, path = "wba.rs")] mod _version; #[cfg(feature = "low-power")] use core::sync::atomic::{AtomicU32, Ordering}; pub use _version::*; // Model Clock Configuration // // pub struct Clocks { // hse: Option, // hsi: bool, // lse: Option, // lsi: bool, // rtc: RtcSource, // } #[derive(Clone, Copy, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Clocks { pub sys: Hertz, // APB pub pclk1: Hertz, pub pclk1_tim: Hertz, #[cfg(not(any(rcc_c0, rcc_g0)))] pub pclk2: Hertz, #[cfg(not(any(rcc_c0, rcc_g0)))] pub pclk2_tim: Hertz, #[cfg(any(rcc_wl5, rcc_wle, rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab, rcc_u5))] pub pclk3: Hertz, #[cfg(any(rcc_h7, rcc_h7rm0433, rcc_h7ab, stm32h5))] pub pclk4: Hertz, #[cfg(any(rcc_wba))] pub pclk7: Hertz, // AHB pub hclk1: Hertz, #[cfg(any( rcc_l4, rcc_l4plus, rcc_l5, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab, rcc_g4, rcc_u5, rcc_wb, rcc_wba, rcc_wl5, rcc_wle ))] pub hclk2: Hertz, #[cfg(any( rcc_l4, rcc_l4plus, rcc_l5, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab, rcc_u5, rcc_wb, rcc_wl5, rcc_wle ))] pub hclk3: Hertz, #[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab, rcc_wba))] pub hclk4: Hertz, #[cfg(all(rcc_f4, not(stm32f410)))] pub plli2s1_q: Option, #[cfg(all(rcc_f4, not(stm32f410)))] pub plli2s1_r: Option, #[cfg(rcc_l4)] pub pllsai1_p: Option, #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] pub pllsai1_q: Option, #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] pub pllsai1_r: Option, #[cfg(rcc_l4)] pub pllsai2_p: Option, #[cfg(any(stm32g4, rcc_l4))] pub pll1_p: Option, #[cfg(any(stm32h5, stm32h7, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_l4))] pub pll1_q: Option, #[cfg(any(stm32h5, stm32h7))] pub pll2_p: Option, #[cfg(any(stm32h5, stm32h7))] pub pll2_q: Option, #[cfg(any(stm32h5, stm32h7))] pub pll2_r: Option, #[cfg(any(stm32h5, stm32h7))] pub pll3_p: Option, #[cfg(any(stm32h5, stm32h7))] pub pll3_q: Option, #[cfg(any(stm32h5, stm32h7))] pub pll3_r: Option, #[cfg(any( rcc_f1, rcc_f100, rcc_f1cl, rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab, rcc_f3, rcc_g4 ))] pub adc: Option, #[cfg(any(rcc_f3, rcc_g4))] pub adc34: Option, #[cfg(stm32f334)] pub hrtim: Option, pub rtc: Option, #[cfg(any(stm32h5, stm32h7, rcc_l4, rcc_c0))] pub hsi: Option, #[cfg(stm32h5)] pub hsi48: Option, #[cfg(stm32h5)] pub lsi: Option, #[cfg(any(stm32h5, stm32h7))] pub csi: Option, #[cfg(any(stm32h5, stm32h7, rcc_l4, rcc_c0))] pub lse: Option, #[cfg(any(stm32h5, stm32h7))] pub hse: Option, #[cfg(stm32h5)] pub audioclk: Option, #[cfg(any(stm32h5, stm32h7))] pub per: Option, #[cfg(stm32h7)] pub rcc_pclk_d3: Option, #[cfg(rcc_l4)] pub sai1_extclk: Option, #[cfg(rcc_l4)] pub sai2_extclk: Option, } #[cfg(feature = "low-power")] static CLOCK_REFCOUNT: AtomicU32 = AtomicU32::new(0); #[cfg(feature = "low-power")] pub fn low_power_ready() -> bool { // trace!("clock refcount: {}", CLOCK_REFCOUNT.load(Ordering::SeqCst)); CLOCK_REFCOUNT.load(Ordering::SeqCst) == 0 } #[cfg(feature = "low-power")] pub(crate) fn clock_refcount_add(_cs: critical_section::CriticalSection) { // We don't check for overflow because constructing more than u32 peripherals is unlikely let n = CLOCK_REFCOUNT.load(Ordering::Relaxed); CLOCK_REFCOUNT.store(n + 1, Ordering::Relaxed); } #[cfg(feature = "low-power")] pub(crate) fn clock_refcount_sub(_cs: critical_section::CriticalSection) { let n = CLOCK_REFCOUNT.load(Ordering::Relaxed); assert!(n != 0); CLOCK_REFCOUNT.store(n - 1, Ordering::Relaxed); } /// Frozen clock frequencies /// /// The existence of this value indicates that the clock configuration can no longer be changed static mut CLOCK_FREQS: MaybeUninit = MaybeUninit::uninit(); /// Sets the clock frequencies /// /// Safety: Sets a mutable global. pub(crate) unsafe fn set_freqs(freqs: Clocks) { debug!("rcc: {:?}", freqs); CLOCK_FREQS = MaybeUninit::new(freqs); } /// Safety: Reads a mutable global. pub(crate) unsafe fn get_freqs() -> &'static Clocks { CLOCK_FREQS.assume_init_ref() } #[cfg(feature = "unstable-pac")] pub mod low_level { pub use super::sealed::*; } pub(crate) mod sealed { use critical_section::CriticalSection; pub trait RccPeripheral { fn frequency() -> crate::time::Hertz; fn enable_and_reset_with_cs(cs: CriticalSection); fn disable_with_cs(cs: CriticalSection); fn enable_and_reset() { critical_section::with(|cs| Self::enable_and_reset_with_cs(cs)) } fn disable() { critical_section::with(|cs| Self::disable_with_cs(cs)) } } } pub trait RccPeripheral: sealed::RccPeripheral + 'static {} #[allow(unused)] mod util { use crate::time::Hertz; pub fn calc_pclk(hclk: Hertz, ppre: D) -> (Hertz, Hertz) where Hertz: core::ops::Div, { let pclk = hclk / ppre; let pclk_tim = if hclk == pclk { pclk } else { pclk * 2u32 }; (pclk, pclk_tim) } pub fn all_equal(mut iter: impl Iterator) -> bool { let Some(x) = iter.next() else { return true }; if !iter.all(|y| y == x) { return false; } true } pub fn get_equal(mut iter: impl Iterator) -> Result, ()> { let Some(x) = iter.next() else { return Ok(None) }; if !iter.all(|y| y == x) { return Err(()); } Ok(Some(x)) } }