embassy/embassy-stm32/src/rcc/mod.rs

171 lines
4.6 KiB
Rust
Raw Normal View History

#![macro_use]
2021-05-27 09:50:11 +02:00
use core::mem::MaybeUninit;
2021-06-14 10:48:14 +02:00
2023-08-27 16:25:14 +02:00
pub use crate::rcc::bd::RtcClockSource;
2022-06-12 22:15:44 +02:00
use crate::time::Hertz;
2023-09-19 04:22:57 +02:00
pub(crate) mod bd;
mod bus;
#[cfg(any(stm32h5, stm32h7))]
mod mco;
#[cfg(any(stm32h5, stm32h7))]
pub use mco::*;
2022-02-14 02:12:06 +01:00
#[cfg_attr(rcc_f0, path = "f0.rs")]
2022-06-26 23:52:38 +02:00
#[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), path = "f4.rs")]
#[cfg_attr(rcc_f7, path = "f7.rs")]
2023-01-17 18:54:23 +01:00
#[cfg_attr(rcc_c0, path = "c0.rs")]
#[cfg_attr(rcc_g0, path = "g0.rs")]
#[cfg_attr(rcc_g4, path = "g4.rs")]
2023-09-19 04:22:57 +02:00
#[cfg_attr(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab), path = "h.rs")]
#[cfg_attr(rcc_l0, path = "l0.rs")]
#[cfg_attr(rcc_l1, path = "l1.rs")]
#[cfg_attr(rcc_l4, path = "l4.rs")]
2022-04-08 02:57:48 +02:00
#[cfg_attr(rcc_l5, path = "l5.rs")]
#[cfg_attr(rcc_u5, path = "u5.rs")]
#[cfg_attr(rcc_wb, path = "wb.rs")]
2023-09-16 03:44:01 +02:00
#[cfg_attr(rcc_wba, path = "wba.rs")]
2022-04-08 03:40:51 +02:00
#[cfg_attr(any(rcc_wl5, rcc_wle), path = "wl.rs")]
mod _version;
pub use _version::*;
2023-08-24 03:18:34 +02:00
#[cfg(feature = "low-power")]
use atomic_polyfill::{AtomicU32, Ordering};
2023-09-18 01:41:45 +02:00
// Model Clock Configuration
//
// pub struct Clocks {
// hse: Option<Hertz>,
// hsi: bool,
// lse: Option<Hertz>,
// lsi: bool,
// rtc: RtcSource,
// }
2023-01-20 16:31:04 +01:00
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2021-06-14 10:48:14 +02:00
pub struct Clocks {
pub sys: Hertz,
2021-07-30 22:48:13 +02:00
2022-02-14 02:12:06 +01:00
// APB
2021-06-14 10:48:14 +02:00
pub apb1: Hertz,
2021-07-30 22:48:13 +02:00
pub apb1_tim: Hertz,
2023-01-17 18:54:23 +01:00
#[cfg(not(any(rcc_c0, rcc_g0)))]
2021-06-14 10:48:14 +02:00
pub apb2: Hertz,
2023-01-17 18:54:23 +01:00
#[cfg(not(any(rcc_c0, rcc_g0)))]
2021-07-30 22:48:13 +02:00
pub apb2_tim: Hertz,
2023-09-19 04:22:57 +02:00
#[cfg(any(rcc_wl5, rcc_wle, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_u5))]
pub apb3: Hertz,
2022-02-24 05:59:42 +01:00
#[cfg(any(rcc_h7, rcc_h7ab))]
2022-02-14 02:12:06 +01:00
pub apb4: Hertz,
2023-09-16 03:44:01 +02:00
#[cfg(any(rcc_wba))]
pub apb7: Hertz,
2021-06-23 01:07:48 +02:00
2022-02-14 02:12:06 +01:00
// AHB
2021-06-14 10:48:14 +02:00
pub ahb1: Hertz,
2022-01-24 00:50:35 +01:00
#[cfg(any(
2023-04-06 18:53:51 +02:00
rcc_l4, rcc_l5, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_g4, rcc_u5, rcc_wb,
2023-09-16 03:44:01 +02:00
rcc_wba, rcc_wl5, rcc_wle
2022-01-24 00:50:35 +01:00
))]
2021-06-14 10:48:14 +02:00
pub ahb2: Hertz,
2022-02-24 05:59:42 +01:00
#[cfg(any(
2023-04-06 18:53:51 +02:00
rcc_l4, rcc_l5, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_u5, rcc_wb, rcc_wl5,
rcc_wle
2022-02-24 05:59:42 +01:00
))]
2021-06-14 11:41:02 +02:00
pub ahb3: Hertz,
2023-09-16 03:44:01 +02:00
#[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_wba))]
2021-07-09 15:33:17 +02:00
pub ahb4: Hertz,
2022-04-26 19:33:57 +02:00
#[cfg(any(rcc_f2, rcc_f4, rcc_f410, rcc_f7))]
2021-07-28 04:09:48 +02:00
pub pll48: Option<Hertz>,
2023-04-15 04:28:27 +02:00
#[cfg(all(rcc_f4, not(stm32f410)))]
pub plli2s: Option<Hertz>,
2023-04-15 04:28:27 +02:00
#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
pub pllsai: Option<Hertz>,
#[cfg(any(rcc_f1, rcc_f100, rcc_f1cl, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_f3, rcc_g4))]
2022-03-19 11:05:00 +01:00
pub adc: Option<Hertz>,
2023-08-06 18:11:53 +02:00
#[cfg(any(rcc_f3, rcc_g4))]
2023-09-05 23:46:57 +02:00
pub adc34: Option<Hertz>,
2023-08-21 04:31:47 +02:00
#[cfg(stm32f334)]
pub hrtim: Option<Hertz>,
2023-08-22 01:10:10 +02:00
#[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
2023-08-30 02:41:03 +02:00
/// Set only if the lsi or lse is configured, indicates stop is supported
2023-08-06 18:11:53 +02:00
pub rtc: Option<Hertz>,
2023-08-30 02:41:03 +02:00
2023-08-30 02:51:21 +02:00
#[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
2023-08-30 02:41:03 +02:00
/// Set if the hse is configured, indicates stop is not supported
pub rtc_hse: Option<Hertz>,
2021-06-14 10:48:14 +02:00
}
2021-05-27 09:50:11 +02:00
2023-08-24 03:18:34 +02:00
#[cfg(feature = "low-power")]
static CLOCK_REFCOUNT: AtomicU32 = AtomicU32::new(0);
#[cfg(feature = "low-power")]
pub fn low_power_ready() -> bool {
2023-08-25 02:29:11 +02:00
trace!("clock refcount: {}", CLOCK_REFCOUNT.load(Ordering::SeqCst));
2023-08-24 03:18:34 +02:00
CLOCK_REFCOUNT.load(Ordering::SeqCst) == 0
}
#[cfg(feature = "low-power")]
pub(crate) fn clock_refcount_add() {
// We don't check for overflow because constructing more than u32 peripherals is unlikely
CLOCK_REFCOUNT.fetch_add(1, Ordering::Relaxed);
}
#[cfg(feature = "low-power")]
pub(crate) fn clock_refcount_sub() {
assert!(CLOCK_REFCOUNT.fetch_sub(1, Ordering::Relaxed) != 0);
}
2021-05-27 09:50:11 +02:00
/// Frozen clock frequencies
///
/// The existence of this value indicates that the clock configuration can no longer be changed
static mut CLOCK_FREQS: MaybeUninit<Clocks> = MaybeUninit::uninit();
2023-07-24 00:01:34 +02:00
#[cfg(stm32wb)]
/// RCC initialization function
pub(crate) unsafe fn init(config: Config) {
set_freqs(compute_clocks(&config));
configure_clocks(&config);
}
2021-05-27 09:50:11 +02:00
/// Sets the clock frequencies
///
/// Safety: Sets a mutable global.
pub(crate) unsafe fn set_freqs(freqs: Clocks) {
2023-01-20 16:31:04 +01:00
debug!("rcc: {:?}", freqs);
2023-07-04 23:29:46 +02:00
CLOCK_FREQS = MaybeUninit::new(freqs);
2021-05-27 09:50:11 +02:00
}
/// Safety: Reads a mutable global.
pub(crate) unsafe fn get_freqs() -> &'static Clocks {
2023-07-04 23:29:46 +02:00
CLOCK_FREQS.assume_init_ref()
2021-05-27 09:50:11 +02:00
}
#[cfg(feature = "unstable-pac")]
pub mod low_level {
pub use super::sealed::*;
}
pub(crate) mod sealed {
pub trait RccPeripheral {
fn frequency() -> crate::time::Hertz;
fn reset();
fn enable();
fn disable();
}
}
pub trait RccPeripheral: sealed::RccPeripheral + 'static {}