diff options
| author | James Munns <[email protected]> | 2025-11-12 18:54:27 +0100 |
|---|---|---|
| committer | James Munns <[email protected]> | 2025-11-12 18:54:27 +0100 |
| commit | 2f08491f1a09df79bf1d41e26217d21b0bd7bdae (patch) | |
| tree | c68cbb51f49aac5f8001eca81f38750ec10d9d14 /src/clocks/mod.rs | |
| parent | a2e63ff090d240f8dea0d448477990a89db114be (diff) | |
Start adding peripheral helpers
Diffstat (limited to 'src/clocks/mod.rs')
| -rw-r--r-- | src/clocks/mod.rs | 69 |
1 files changed, 62 insertions, 7 deletions
diff --git a/src/clocks/mod.rs b/src/clocks/mod.rs index c86ed1cd5..ad48a9cf2 100644 --- a/src/clocks/mod.rs +++ b/src/clocks/mod.rs | |||
| @@ -6,10 +6,7 @@ use mcxa_pac::scg0::{ | |||
| 6 | }; | 6 | }; |
| 7 | 7 | ||
| 8 | use crate::pac; | 8 | use crate::pac; |
| 9 | 9 | pub mod periph_helpers; | |
| 10 | pub trait SPConfHelper { | ||
| 11 | fn post_enable_config(&self, clocks: &Clocks) -> Result<u32, ClockError>; | ||
| 12 | } | ||
| 13 | 10 | ||
| 14 | // /// Trait describing an AHB clock gate that can be toggled through MRCC. | 11 | // /// Trait describing an AHB clock gate that can be toggled through MRCC. |
| 15 | // pub trait Gate { | 12 | // pub trait Gate { |
| @@ -198,10 +195,22 @@ pub struct Clock { | |||
| 198 | 195 | ||
| 199 | #[derive(Debug, Clone, Copy)] | 196 | #[derive(Debug, Clone, Copy)] |
| 200 | pub enum PoweredClock { | 197 | pub enum PoweredClock { |
| 201 | HighPowerOnly, | 198 | NormalEnabledDeepSleepDisabled, |
| 202 | AlwaysEnabled, | 199 | AlwaysEnabled, |
| 203 | } | 200 | } |
| 204 | 201 | ||
| 202 | impl PoweredClock { | ||
| 203 | /// Does THIS clock meet the power requirements of the OTHER clock? | ||
| 204 | pub fn meets_requirement_of(&self, other: &Self) -> bool { | ||
| 205 | match (self, other) { | ||
| 206 | (PoweredClock::NormalEnabledDeepSleepDisabled, PoweredClock::AlwaysEnabled) => false, | ||
| 207 | (PoweredClock::NormalEnabledDeepSleepDisabled, PoweredClock::NormalEnabledDeepSleepDisabled) => true, | ||
| 208 | (PoweredClock::AlwaysEnabled, PoweredClock::NormalEnabledDeepSleepDisabled) => true, | ||
| 209 | (PoweredClock::AlwaysEnabled, PoweredClock::AlwaysEnabled) => true, | ||
| 210 | } | ||
| 211 | } | ||
| 212 | } | ||
| 213 | |||
| 205 | /// ```text | 214 | /// ```text |
| 206 | /// ┌─────────────────────────────────────────────────────────┐ | 215 | /// ┌─────────────────────────────────────────────────────────┐ |
| 207 | /// │ │ | 216 | /// │ │ |
| @@ -341,6 +350,7 @@ static CLOCKS: critical_section::Mutex<Option<Clocks>> = critical_section::Mutex | |||
| 341 | pub enum ClockError { | 350 | pub enum ClockError { |
| 342 | AlreadyInitialized, | 351 | AlreadyInitialized, |
| 343 | BadConfig { clock: &'static str, reason: &'static str }, | 352 | BadConfig { clock: &'static str, reason: &'static str }, |
| 353 | NotImplemented { clock: &'static str }, | ||
| 344 | } | 354 | } |
| 345 | 355 | ||
| 346 | struct ClockOperator<'a> { | 356 | struct ClockOperator<'a> { |
| @@ -417,7 +427,7 @@ impl ClockOperator<'_> { | |||
| 417 | 427 | ||
| 418 | // When is the FRO enabled? | 428 | // When is the FRO enabled? |
| 419 | let pow_set = match power { | 429 | let pow_set = match power { |
| 420 | PoweredClock::HighPowerOnly => Fircsten::DisabledInStopModes, | 430 | PoweredClock::NormalEnabledDeepSleepDisabled => Fircsten::DisabledInStopModes, |
| 421 | PoweredClock::AlwaysEnabled => Fircsten::EnabledInStopModes, | 431 | PoweredClock::AlwaysEnabled => Fircsten::EnabledInStopModes, |
| 422 | }; | 432 | }; |
| 423 | 433 | ||
| @@ -505,7 +515,7 @@ impl ClockOperator<'_> { | |||
| 505 | }); | 515 | }); |
| 506 | 516 | ||
| 507 | let deep = match power { | 517 | let deep = match power { |
| 508 | PoweredClock::HighPowerOnly => Sircsten::Disabled, | 518 | PoweredClock::NormalEnabledDeepSleepDisabled => Sircsten::Disabled, |
| 509 | PoweredClock::AlwaysEnabled => Sircsten::Enabled, | 519 | PoweredClock::AlwaysEnabled => Sircsten::Enabled, |
| 510 | }; | 520 | }; |
| 511 | let pclk = if *fro_12m_enabled { | 521 | let pclk = if *fro_12m_enabled { |
| @@ -615,3 +625,48 @@ pub fn with_clocks<R: 'static, F: FnOnce(&Clocks) -> R>(f: F) -> Option<R> { | |||
| 615 | Some(f(c)) | 625 | Some(f(c)) |
| 616 | }) | 626 | }) |
| 617 | } | 627 | } |
| 628 | |||
| 629 | impl Clocks { | ||
| 630 | pub fn ensure_fro_lf_div_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> { | ||
| 631 | let Some(clk) = self.fro_lf_div.as_ref() else { | ||
| 632 | return Err(ClockError::BadConfig { clock: "fro_lf_div", reason: "required but not active" }); | ||
| 633 | }; | ||
| 634 | if !clk.power.meets_requirement_of(at_level) { | ||
| 635 | return Err(ClockError::BadConfig { clock: "fro_lf_div", reason: "not low power active" }); | ||
| 636 | } | ||
| 637 | Ok(clk.frequency) | ||
| 638 | } | ||
| 639 | |||
| 640 | pub fn ensure_fro_hf_div_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> { | ||
| 641 | let Some(clk) = self.fro_hf_div.as_ref() else { | ||
| 642 | return Err(ClockError::BadConfig { clock: "fro_hf_div", reason: "required but not active" }); | ||
| 643 | }; | ||
| 644 | if !clk.power.meets_requirement_of(at_level) { | ||
| 645 | return Err(ClockError::BadConfig { clock: "fro_hf_div", reason: "not low power active" }); | ||
| 646 | } | ||
| 647 | Ok(clk.frequency) | ||
| 648 | } | ||
| 649 | |||
| 650 | pub fn ensure_clk_in_active(&self, _at_level: &PoweredClock) -> Result<u32, ClockError> { | ||
| 651 | Err(ClockError::NotImplemented { clock: "clk_in" }) | ||
| 652 | } | ||
| 653 | |||
| 654 | pub fn ensure_clk_16k_active(&self, _at_level: &PoweredClock) -> Result<u32, ClockError> { | ||
| 655 | Err(ClockError::NotImplemented { clock: "clk_16k" }) | ||
| 656 | } | ||
| 657 | |||
| 658 | pub fn ensure_clk_1m_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> { | ||
| 659 | let Some(clk) = self.clk_1m.as_ref() else { | ||
| 660 | return Err(ClockError::BadConfig { clock: "clk_1m", reason: "required but not active" }); | ||
| 661 | }; | ||
| 662 | if !clk.power.meets_requirement_of(at_level) { | ||
| 663 | return Err(ClockError::BadConfig { clock: "clk_1m", reason: "not low power active" }); | ||
| 664 | } | ||
| 665 | Ok(clk.frequency) | ||
| 666 | } | ||
| 667 | |||
| 668 | pub fn ensure_pll1_clk_div_active(&self, _at_level: &PoweredClock) -> Result<u32, ClockError> { | ||
| 669 | Err(ClockError::NotImplemented { clock: "pll1_clk_div" }) | ||
| 670 | } | ||
| 671 | |||
| 672 | } | ||
