diff --git a/src/rcc.rs b/src/rcc.rs index 53b67fa..09ccb5c 100644 --- a/src/rcc.rs +++ b/src/rcc.rs @@ -1 +1,2 @@ +mod core_clocks; mod reset_reason; diff --git a/src/rcc/core_clocks.rs b/src/rcc/core_clocks.rs new file mode 100644 index 0000000..e65036f --- /dev/null +++ b/src/rcc/core_clocks.rs @@ -0,0 +1,146 @@ +//! Structure to represent frozen core clock frequencies + +use crate::time::Hertz; + +/// Frozen core clock frequencies +/// +/// The existence of this value indicates that the core clock +/// configuration can no longer be changed +#[derive(Clone, Copy)] +pub struct CoreClocks { + pub(super) hclk: Hertz, + pub(super) pclk1: Hertz, + pub(super) pclk2: Hertz, + pub(super) pclk3: Hertz, + pub(super) ppre1: u8, + pub(super) ppre2: u8, + pub(super) ppre3: u8, + pub(super) csi_ck: Option, + pub(super) hsi_ck: Option, + pub(super) hsi48_ck: Option, + pub(super) lsi_ck: Option, + pub(super) per_ck: Option, + pub(super) hse_ck: Option, + pub(super) lse_ck: Option, + pub(super) audio_ck: Option, + pub(super) mco1_ck: Option, + pub(super) mco2_ck: Option, + pub(super) pll1_p_ck: Option, + pub(super) pll1_q_ck: Option, + pub(super) pll1_r_ck: Option, + pub(super) pll2_p_ck: Option, + pub(super) pll2_q_ck: Option, + pub(super) pll2_r_ck: Option, + pub(super) timx_ker_ck: Hertz, + pub(super) timy_ker_ck: Hertz, + pub(super) sys_ck: Hertz, +} + +/// Getters for pclk and ppre +macro_rules! pclk_ppre_getter { + ($(($pclk:ident, $ppre:ident),)+) => { + $( + /// Returns the frequency of the APBn + pub fn $pclk(&self) -> Hertz { + self.$pclk + } + /// Returns the prescaler of the APBn + pub fn $ppre(&self) -> u8 { + self.$ppre + } + )+ + }; +} + +/// Getters for optional clocks +macro_rules! optional_ck_getter { + ($($opt_ck:ident: $doc:expr,)+) => { + $( + /// Returns `Some(frequency)` if + #[doc=$doc] + /// is running, otherwise `None` + pub fn $opt_ck(&self) -> Option { + self.$opt_ck + } + )+ + }; +} + +/// Getters for pll clocks +macro_rules! pll_getter { + ($($pll_ck:ident,)+) => { + $( + /// Returns `Some(frequency)` if the PLLx output is running, + /// otherwise `None` + pub fn $pll_ck(&self) -> Option { + self.$pll_ck + } + )+ + }; +} + +#[allow(dead_code)] +impl CoreClocks { + /// Returns the frequency of AHB1,2,3 busses + pub fn hclk(&self) -> Hertz { + self.hclk + } + + pclk_ppre_getter! { + (pclk1, ppre1), + (pclk2, ppre2), + (pclk3, ppre3), + } + + optional_ck_getter! { + csi_ck: "csi_ck", + hsi_ck: "hsi_ck", + hsi48_ck: "hsi48_ck", + per_ck: "per_ck", + hse_ck: "hse_ck", + lse_ck: "lse_ck", + lsi_ck: "lsi_ck", + audio_ck: "audio_ck", + } + + /// Returns `Some(frequency)` if the MCO1 output is running, otherwise + /// `None` + pub fn mco1_ck(&self) -> Option { + self.mco1_ck + } + + /// Returns `Some(frequency)` if the MCO2 output is running, otherwise + /// `None` + pub fn mco2_ck(&self) -> Option { + self.mco2_ck + } + + pll_getter! { + pll1_p_ck, + pll1_q_ck, + pll1_r_ck, + pll2_p_ck, + pll2_q_ck, + pll2_r_ck, + } + + /// Returns the input frequency to the SCGU + pub fn sys_ck(&self) -> Hertz { + self.sys_ck + } + + /// Returns the input frequency to the SCGU - ALIAS + pub fn sysclk(&self) -> Hertz { + self.sys_ck + } + + /// Returns the CK_INT frequency for timers on APB1 + pub fn timx_ker_ck(&self) -> Hertz { + self.timx_ker_ck + } + + /// Returns the CK_INT frequency for timers on APB2 + pub fn timy_ker_ck(&self) -> Hertz { + self.timy_ker_ck + } +}