From 595cf532efd462fd1df5a90b6f4a3e0084315a15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Mon, 19 Aug 2024 19:04:52 +0200 Subject: [PATCH] Rework hal initialization --- esp-hal/src/clock/mod.rs | 506 ++++++++------------- esp-hal/src/lib.rs | 28 ++ esp-hal/src/prelude.rs | 2 +- esp-hal/src/system.rs | 30 +- hil-test/tests/embassy_timers_executors.rs | 90 ++-- 5 files changed, 244 insertions(+), 412 deletions(-) diff --git a/esp-hal/src/clock/mod.rs b/esp-hal/src/clock/mod.rs index 67b68dfebc9..9e8850d5e8f 100644 --- a/esp-hal/src/clock/mod.rs +++ b/esp-hal/src/clock/mod.rs @@ -70,16 +70,14 @@ //! # } //! ``` +use core::marker::PhantomData; + use fugit::HertzU32; #[cfg(esp32c2)] use portable_atomic::{AtomicU32, Ordering}; #[cfg(any(esp32, esp32c2))] use crate::rtc_cntl::RtcClock; -use crate::{ - peripheral::{Peripheral, PeripheralRef}, - system::SystemClockControl, -}; #[cfg_attr(esp32, path = "clocks_ll/esp32.rs")] #[cfg_attr(esp32c2, path = "clocks_ll/esp32c2.rs")] @@ -111,36 +109,63 @@ pub trait Clock { pub enum CpuClock { /// 80MHz CPU clock #[cfg(not(esp32h2))] - Clock80MHz, + Clock80MHz = 80, + /// 96MHz CPU clock #[cfg(esp32h2)] - Clock96MHz, + Clock96MHz = 96, + /// 120MHz CPU clock #[cfg(esp32c2)] - Clock120MHz, + Clock120MHz = 120, + /// 160MHz CPU clock #[cfg(not(any(esp32c2, esp32h2)))] - Clock160MHz, + Clock160MHz = 160, + /// 240MHz CPU clock #[cfg(xtensa)] - Clock240MHz, + Clock240MHz = 240, +} + +impl Default for CpuClock { + fn default() -> Self { + Self::boot_default() + } +} + +impl CpuClock { + /// Use the default frequency. + pub fn boot_default() -> Self { + cfg_if::cfg_if! { + if #[cfg(esp32h2)] { + Self::Clock96MHz + } else { + // FIXME: I don't think this is correct in general? + Self::Clock80MHz + } + } + } + + /// Use the highest possible frequency for a particular chip. + pub fn max() -> Self { + cfg_if::cfg_if! { + if #[cfg(esp32c2)] { + Self::Clock120MHz + } else if #[cfg(any(esp32c3, esp32c6))] { + Self::Clock160MHz + } else if #[cfg(esp32h2)] { + Self::Clock96MHz + } else { + Self::Clock240MHz + } + } + } } -#[allow(dead_code)] impl Clock for CpuClock { fn frequency(&self) -> HertzU32 { - match self { - #[cfg(not(esp32h2))] - CpuClock::Clock80MHz => HertzU32::MHz(80), - #[cfg(esp32h2)] - CpuClock::Clock96MHz => HertzU32::MHz(96), - #[cfg(esp32c2)] - CpuClock::Clock120MHz => HertzU32::MHz(120), - #[cfg(not(any(esp32c2, esp32h2)))] - CpuClock::Clock160MHz => HertzU32::MHz(160), - #[cfg(xtensa)] - CpuClock::Clock240MHz => HertzU32::MHz(240), - } + HertzU32::MHz(*self as u32) } } @@ -256,81 +281,65 @@ impl Clock for ApbClock { /// Frozen clock frequencies /// /// The instantiation of this type indicates that the clock configuration can no -/// longer be changed -pub struct Clocks<'d> { - _private: PeripheralRef<'d, SystemClockControl>, - /// CPU clock frequency - pub cpu_clock: HertzU32, - /// APB clock frequency - pub apb_clock: HertzU32, - /// XTAL clock frequency - pub xtal_clock: HertzU32, - /// I2C clock frequency - #[cfg(esp32)] - pub i2c_clock: HertzU32, - /// PWM clock frequency - #[cfg(esp32)] - pub pwm_clock: HertzU32, - /// Crypto PWM clock frequency - #[cfg(esp32s3)] - pub crypto_pwm_clock: HertzU32, - /// Crypto clock frequency - #[cfg(any(esp32c6, esp32h2))] - pub crypto_clock: HertzU32, - /// PLL 48M clock frequency (fixed) - #[cfg(esp32h2)] - pub pll_48m_clock: HertzU32, - /// PLL 96M clock frequency (fixed) - #[cfg(esp32h2)] - pub pll_96m_clock: HertzU32, +/// longer be changed. +pub struct Clocks<'a> { + _private: PhantomData<&'a ()>, + rates: RawClocks, } -#[doc(hidden)] -impl<'d> Clocks<'d> { +impl<'a> Clocks<'a> { /// This should not be used in user code. /// The whole point this exists is make it possible to have other crates /// (i.e. esp-wifi) create `Clocks` #[doc(hidden)] - pub fn from_raw_clocks( - system_clock_control: PeripheralRef<'d, SystemClockControl>, - raw_clocks: RawClocks, - ) -> Clocks<'d> { + pub(crate) fn from_raw_clocks(raw_clocks: RawClocks) -> Clocks<'a> { Self { - _private: system_clock_control, - cpu_clock: raw_clocks.cpu_clock, - apb_clock: raw_clocks.apb_clock, - xtal_clock: raw_clocks.xtal_clock, - #[cfg(esp32)] - i2c_clock: raw_clocks.i2c_clock, - #[cfg(esp32)] - pwm_clock: raw_clocks.pwm_clock, - #[cfg(esp32s3)] - crypto_pwm_clock: raw_clocks.crypto_pwm_clock, - #[cfg(any(esp32c6, esp32h2))] - crypto_clock: raw_clocks.crypto_clock, - #[cfg(esp32h2)] - pll_48m_clock: raw_clocks.pll_48m_clock, - #[cfg(esp32h2)] - pll_96m_clock: raw_clocks.pll_96m_clock, + _private: PhantomData, + rates: raw_clocks, } } } -#[doc(hidden)] +impl core::ops::Deref for Clocks<'_> { + type Target = RawClocks; + + fn deref(&self) -> &RawClocks { + &self.rates + } +} + +/// The list of the clock frequencies that are used in the system. pub struct RawClocks { + /// CPU clock frequency pub cpu_clock: HertzU32, + + /// APB clock frequency pub apb_clock: HertzU32, + + /// XTAL clock frequency pub xtal_clock: HertzU32, + + /// I2C clock frequency #[cfg(esp32)] pub i2c_clock: HertzU32, + + /// PWM clock frequency #[cfg(esp32)] pub pwm_clock: HertzU32, + + /// Crypto PWM clock frequency #[cfg(esp32s3)] pub crypto_pwm_clock: HertzU32, + + /// Crypto clock frequency #[cfg(any(esp32c6, esp32h2))] pub crypto_clock: HertzU32, + + /// PLL 48M clock frequency (fixed) #[cfg(esp32h2)] pub pll_48m_clock: HertzU32, + + /// PLL 96M clock frequency (fixed) #[cfg(esp32h2)] pub pll_96m_clock: HertzU32, } @@ -359,72 +368,51 @@ cfg_if::cfg_if! { /// /// After setting all frequencies, call the freeze function to apply the /// configuration. -pub struct ClockControl<'d> { - _private: PeripheralRef<'d, SystemClockControl>, +pub struct ClockControl { desired_rates: RawClocks, } -impl<'d> ClockControl<'d> { +impl ClockControl { + pub(crate) fn new(clock: CpuClock) -> Self { + Self::configure(clock) + } + /// Applies the clock configuration and returns a Clocks struct that /// signifies that the clocks are frozen, and contains the frequencies /// used. After this function is called, the clocks can not change - pub fn freeze(self) -> Clocks<'d> { - Clocks::from_raw_clocks(self._private, self.desired_rates) + pub fn freeze(self) -> Clocks<'static> { + Clocks::from_raw_clocks(self.desired_rates) } } #[cfg(esp32)] -impl<'d> ClockControl<'d> { - /// Use what is considered the default settings after boot. - pub fn boot_defaults( - clock_control: impl Peripheral

+ 'd, - ) -> ClockControl<'d> { - let xtal_freq = if RtcClock::estimate_xtal_frequency() > 33 { - 40 - } else { - 26 - }; - - ClockControl { - _private: clock_control.into_ref(), - desired_rates: RawClocks { - cpu_clock: HertzU32::MHz(80), - apb_clock: HertzU32::MHz(80), - xtal_clock: HertzU32::MHz(xtal_freq), - i2c_clock: HertzU32::MHz(80), - pwm_clock: HertzU32::MHz(160), - }, - } - } - +impl ClockControl { /// Configure the CPU clock speed. - pub fn configure( - clock_control: impl Peripheral

+ 'd, - cpu_clock_speed: CpuClock, - ) -> ClockControl<'d> { + pub(crate) fn configure(cpu_clock_speed: CpuClock) -> ClockControl { let xtal_freq = if RtcClock::estimate_xtal_frequency() > 33 { XtalClock::RtcXtalFreq40M } else { XtalClock::RtcXtalFreq26M }; - let pll_freq = match cpu_clock_speed { - CpuClock::Clock80MHz => PllClock::Pll320MHz, - CpuClock::Clock160MHz => PllClock::Pll320MHz, - CpuClock::Clock240MHz => PllClock::Pll480MHz, - }; - - clocks_ll::esp32_rtc_update_to_xtal(xtal_freq, 1); - clocks_ll::esp32_rtc_bbpll_enable(); - clocks_ll::esp32_rtc_bbpll_configure(xtal_freq, pll_freq); - clocks_ll::set_cpu_freq(cpu_clock_speed); + if cpu_clock_speed != CpuClock::boot_default() { + let pll_freq = match cpu_clock_speed { + CpuClock::Clock80MHz => PllClock::Pll320MHz, + CpuClock::Clock160MHz => PllClock::Pll320MHz, + CpuClock::Clock240MHz => PllClock::Pll480MHz, + }; + + clocks_ll::esp32_rtc_update_to_xtal(xtal_freq, 1); + clocks_ll::esp32_rtc_bbpll_enable(); + clocks_ll::esp32_rtc_bbpll_configure(xtal_freq, pll_freq); + clocks_ll::set_cpu_freq(cpu_clock_speed); + } ClockControl { - _private: clock_control.into_ref(), desired_rates: RawClocks { cpu_clock: cpu_clock_speed.frequency(), apb_clock: HertzU32::MHz(80), - xtal_clock: HertzU32::MHz(40), + xtal_clock: HertzU32::MHz(xtal_freq.mhz()), i2c_clock: HertzU32::MHz(80), // The docs are unclear here. pwm_clock seems to be tied to clocks.apb_clock // while simultaneously being fixed at 160 MHz. @@ -433,43 +421,12 @@ impl<'d> ClockControl<'d> { }, } } - - /// Use the highest possible frequency for a particular chip - pub fn max(clock_control: impl Peripheral

+ 'd) -> ClockControl<'d> { - Self::configure(clock_control, CpuClock::Clock240MHz) - } } #[cfg(esp32c2)] -impl<'d> ClockControl<'d> { - /// Use what is considered the default settings after boot. - pub fn boot_defaults( - clock_control: impl Peripheral

+ 'd, - ) -> ClockControl<'d> { - let xtal_freq = if RtcClock::estimate_xtal_frequency() > 33 { - 40 - } else { - 26 - }; - XTAL_FREQ_MHZ.store(xtal_freq, Ordering::Relaxed); - - ClockControl { - _private: clock_control.into_ref(), - desired_rates: RawClocks { - cpu_clock: HertzU32::MHz(80), - apb_clock: HertzU32::MHz(40), - xtal_clock: HertzU32::MHz(xtal_freq), - }, - } - } - +impl ClockControl { /// Configure the CPU clock speed. - pub fn configure( - clock_control: impl Peripheral

+ 'd, - cpu_clock_speed: CpuClock, - ) -> ClockControl<'d> { - let apb_freq; - + pub(crate) fn configure(cpu_clock_speed: CpuClock) -> ClockControl { let xtal_freq = if RtcClock::estimate_xtal_frequency() > 33 { XtalClock::RtcXtalFreq40M } else { @@ -477,22 +434,26 @@ impl<'d> ClockControl<'d> { }; XTAL_FREQ_MHZ.store(xtal_freq.mhz(), Ordering::Relaxed); - let pll_freq = PllClock::Pll480MHz; - - if cpu_clock_speed.mhz() <= xtal_freq.mhz() { - apb_freq = ApbClock::ApbFreqOther(cpu_clock_speed.mhz()); - clocks_ll::esp32c2_rtc_update_to_xtal(xtal_freq, 1); - clocks_ll::esp32c2_rtc_apb_freq_update(apb_freq); + let apb_freq; + if cpu_clock_speed != CpuClock::boot_default() { + let pll_freq = PllClock::Pll480MHz; + + if cpu_clock_speed.mhz() <= xtal_freq.mhz() { + apb_freq = ApbClock::ApbFreqOther(cpu_clock_speed.mhz()); + clocks_ll::esp32c2_rtc_update_to_xtal(xtal_freq, 1); + clocks_ll::esp32c2_rtc_apb_freq_update(apb_freq); + } else { + apb_freq = ApbClock::ApbFreq40MHz; + clocks_ll::esp32c2_rtc_bbpll_enable(); + clocks_ll::esp32c2_rtc_bbpll_configure(xtal_freq, pll_freq); + clocks_ll::esp32c2_rtc_freq_to_pll_mhz(cpu_clock_speed); + clocks_ll::esp32c2_rtc_apb_freq_update(apb_freq); + } } else { apb_freq = ApbClock::ApbFreq40MHz; - clocks_ll::esp32c2_rtc_bbpll_enable(); - clocks_ll::esp32c2_rtc_bbpll_configure(xtal_freq, pll_freq); - clocks_ll::esp32c2_rtc_freq_to_pll_mhz(cpu_clock_speed); - clocks_ll::esp32c2_rtc_apb_freq_update(apb_freq); } ClockControl { - _private: clock_control.into_ref(), desired_rates: RawClocks { cpu_clock: cpu_clock_speed.frequency(), apb_clock: apb_freq.frequency(), @@ -500,52 +461,33 @@ impl<'d> ClockControl<'d> { }, } } - - /// Use the highest possible frequency for a particular chip - pub fn max(clock_control: impl Peripheral

+ 'd) -> ClockControl<'d> { - Self::configure(clock_control, CpuClock::Clock120MHz) - } } #[cfg(esp32c3)] -impl<'d> ClockControl<'d> { - /// Use what is considered the default settings after boot. - pub fn boot_defaults( - clock_control: impl Peripheral

+ 'd, - ) -> ClockControl<'d> { - ClockControl { - _private: clock_control.into_ref(), - desired_rates: RawClocks { - cpu_clock: HertzU32::MHz(80), - apb_clock: HertzU32::MHz(80), - xtal_clock: HertzU32::MHz(40), - }, - } - } - +impl ClockControl { /// Configure the CPU clock speed. - pub fn configure( - clock_control: impl Peripheral

+ 'd, - cpu_clock_speed: CpuClock, - ) -> ClockControl<'d> { - let apb_freq; + pub(crate) fn configure(cpu_clock_speed: CpuClock) -> ClockControl { let xtal_freq = XtalClock::RtcXtalFreq40M; - let pll_freq = PllClock::Pll480MHz; - if cpu_clock_speed.mhz() <= xtal_freq.mhz() { - apb_freq = ApbClock::ApbFreqOther(cpu_clock_speed.mhz()); - clocks_ll::esp32c3_rtc_update_to_xtal(xtal_freq, 1); - clocks_ll::esp32c3_rtc_apb_freq_update(apb_freq); + let apb_freq; + if cpu_clock_speed != CpuClock::boot_default() { + if cpu_clock_speed.mhz() <= xtal_freq.mhz() { + apb_freq = ApbClock::ApbFreqOther(cpu_clock_speed.mhz()); + clocks_ll::esp32c3_rtc_update_to_xtal(xtal_freq, 1); + clocks_ll::esp32c3_rtc_apb_freq_update(apb_freq); + } else { + let pll_freq = PllClock::Pll480MHz; + apb_freq = ApbClock::ApbFreq80MHz; + clocks_ll::esp32c3_rtc_bbpll_enable(); + clocks_ll::esp32c3_rtc_bbpll_configure(xtal_freq, pll_freq); + clocks_ll::esp32c3_rtc_freq_to_pll_mhz(cpu_clock_speed); + clocks_ll::esp32c3_rtc_apb_freq_update(apb_freq); + } } else { apb_freq = ApbClock::ApbFreq80MHz; - clocks_ll::esp32c3_rtc_bbpll_enable(); - clocks_ll::esp32c3_rtc_bbpll_configure(xtal_freq, pll_freq); - clocks_ll::esp32c3_rtc_freq_to_pll_mhz(cpu_clock_speed); - clocks_ll::esp32c3_rtc_apb_freq_update(apb_freq); } ClockControl { - _private: clock_control.into_ref(), desired_rates: RawClocks { cpu_clock: cpu_clock_speed.frequency(), apb_clock: apb_freq.frequency(), @@ -553,53 +495,33 @@ impl<'d> ClockControl<'d> { }, } } - - /// Use the highest possible frequency for a particular chip - pub fn max(clock_control: impl Peripheral

+ 'd) -> ClockControl<'d> { - Self::configure(clock_control, CpuClock::Clock160MHz) - } } #[cfg(esp32c6)] -impl<'d> ClockControl<'d> { - /// Use what is considered the default settings after boot. - pub fn boot_defaults( - clock_control: impl Peripheral

+ 'd, - ) -> ClockControl<'d> { - ClockControl { - _private: clock_control.into_ref(), - desired_rates: RawClocks { - cpu_clock: HertzU32::MHz(80), - apb_clock: HertzU32::MHz(80), - xtal_clock: HertzU32::MHz(40), - crypto_clock: HertzU32::MHz(160), - }, - } - } - +impl ClockControl { /// Configure the CPU clock speed. - pub fn configure( - clock_control: impl Peripheral

+ 'd, - cpu_clock_speed: CpuClock, - ) -> ClockControl<'d> { - let apb_freq; + pub(crate) fn configure(cpu_clock_speed: CpuClock) -> ClockControl { let xtal_freq = XtalClock::RtcXtalFreq40M; - let pll_freq = PllClock::Pll480MHz; - if cpu_clock_speed.mhz() <= xtal_freq.mhz() { - apb_freq = ApbClock::ApbFreqOther(cpu_clock_speed.mhz()); - clocks_ll::esp32c6_rtc_update_to_xtal(xtal_freq, 1); - clocks_ll::esp32c6_rtc_apb_freq_update(apb_freq); + let apb_freq; + if cpu_clock_speed != CpuClock::boot_default() { + if cpu_clock_speed.mhz() <= xtal_freq.mhz() { + apb_freq = ApbClock::ApbFreqOther(cpu_clock_speed.mhz()); + clocks_ll::esp32c6_rtc_update_to_xtal(xtal_freq, 1); + clocks_ll::esp32c6_rtc_apb_freq_update(apb_freq); + } else { + let pll_freq = PllClock::Pll480MHz; + apb_freq = ApbClock::ApbFreq80MHz; + clocks_ll::esp32c6_rtc_bbpll_enable(); + clocks_ll::esp32c6_rtc_bbpll_configure(xtal_freq, pll_freq); + clocks_ll::esp32c6_rtc_freq_to_pll_mhz(cpu_clock_speed); + clocks_ll::esp32c6_rtc_apb_freq_update(apb_freq); + } } else { apb_freq = ApbClock::ApbFreq80MHz; - clocks_ll::esp32c6_rtc_bbpll_enable(); - clocks_ll::esp32c6_rtc_bbpll_configure(xtal_freq, pll_freq); - clocks_ll::esp32c6_rtc_freq_to_pll_mhz(cpu_clock_speed); - clocks_ll::esp32c6_rtc_apb_freq_update(apb_freq); } ClockControl { - _private: clock_control.into_ref(), desired_rates: RawClocks { cpu_clock: cpu_clock_speed.frequency(), apb_clock: apb_freq.frequency(), @@ -608,55 +530,33 @@ impl<'d> ClockControl<'d> { }, } } - - /// Use the highest possible frequency for a particular chip - pub fn max(clock_control: impl Peripheral

+ 'd) -> ClockControl<'d> { - Self::configure(clock_control, CpuClock::Clock160MHz) - } } #[cfg(esp32h2)] -impl<'d> ClockControl<'d> { - /// Use what is considered the default settings after boot. - pub fn boot_defaults( - clock_control: impl Peripheral

+ 'd, - ) -> ClockControl<'d> { - ClockControl { - _private: clock_control.into_ref(), - desired_rates: RawClocks { - cpu_clock: HertzU32::MHz(96), - apb_clock: HertzU32::MHz(32), - xtal_clock: HertzU32::MHz(32), - pll_48m_clock: HertzU32::MHz(48), - crypto_clock: HertzU32::MHz(96), - pll_96m_clock: HertzU32::MHz(96), - }, - } - } - +impl ClockControl { /// Configure the CPU clock speed. - pub fn configure( - clock_control: impl Peripheral

+ 'd, - cpu_clock_speed: CpuClock, - ) -> ClockControl<'d> { - let apb_freq; + pub(crate) fn configure(cpu_clock_speed: CpuClock) -> ClockControl { let xtal_freq = XtalClock::RtcXtalFreq32M; - let pll_freq = PllClock::Pll96MHz; - if cpu_clock_speed.mhz() <= xtal_freq.mhz() { - apb_freq = ApbClock::ApbFreqOther(cpu_clock_speed.mhz()); - clocks_ll::esp32h2_rtc_update_to_xtal(xtal_freq, 1); - clocks_ll::esp32h2_rtc_apb_freq_update(apb_freq); + let apb_freq; + if cpu_clock_speed != CpuClock::boot_default() { + if cpu_clock_speed.mhz() <= xtal_freq.mhz() { + apb_freq = ApbClock::ApbFreqOther(cpu_clock_speed.mhz()); + clocks_ll::esp32h2_rtc_update_to_xtal(xtal_freq, 1); + clocks_ll::esp32h2_rtc_apb_freq_update(apb_freq); + } else { + let pll_freq = PllClock::Pll96MHz; + apb_freq = ApbClock::ApbFreq32MHz; + clocks_ll::esp32h2_rtc_bbpll_enable(); + clocks_ll::esp32h2_rtc_bbpll_configure(xtal_freq, pll_freq); + clocks_ll::esp32h2_rtc_freq_to_pll_mhz(cpu_clock_speed); + clocks_ll::esp32h2_rtc_apb_freq_update(apb_freq); + } } else { apb_freq = ApbClock::ApbFreq32MHz; - clocks_ll::esp32h2_rtc_bbpll_enable(); - clocks_ll::esp32h2_rtc_bbpll_configure(xtal_freq, pll_freq); - clocks_ll::esp32h2_rtc_freq_to_pll_mhz(cpu_clock_speed); - clocks_ll::esp32h2_rtc_apb_freq_update(apb_freq); } ClockControl { - _private: clock_control.into_ref(), desired_rates: RawClocks { cpu_clock: cpu_clock_speed.frequency(), apb_clock: apb_freq.frequency(), @@ -667,38 +567,17 @@ impl<'d> ClockControl<'d> { }, } } - - /// Use the highest possible frequency for a particular chip - pub fn max(clock_control: impl Peripheral

+ 'd) -> ClockControl<'d> { - Self::configure(clock_control, CpuClock::Clock96MHz) - } } #[cfg(esp32s2)] -impl<'d> ClockControl<'d> { - /// Use what is considered the default settings after boot. - pub fn boot_defaults( - clock_control: impl Peripheral

+ 'd, - ) -> ClockControl<'d> { - ClockControl { - _private: clock_control.into_ref(), - desired_rates: RawClocks { - cpu_clock: HertzU32::MHz(80), - apb_clock: HertzU32::MHz(80), - xtal_clock: HertzU32::MHz(40), - }, - } - } - +impl ClockControl { /// Configure the CPU clock speed. - pub fn configure( - clock_control: impl Peripheral

+ 'd, - cpu_clock_speed: CpuClock, - ) -> ClockControl<'d> { - clocks_ll::set_cpu_clock(cpu_clock_speed); + pub(crate) fn configure(cpu_clock_speed: CpuClock) -> ClockControl { + if cpu_clock_speed != CpuClock::boot_default() { + clocks_ll::set_cpu_clock(cpu_clock_speed); + } ClockControl { - _private: clock_control.into_ref(), desired_rates: RawClocks { cpu_clock: cpu_clock_speed.frequency(), apb_clock: HertzU32::MHz(80), @@ -706,39 +585,17 @@ impl<'d> ClockControl<'d> { }, } } - - /// Use the highest possible frequency for a particular chip - pub fn max(clock_control: impl Peripheral

+ 'd) -> ClockControl<'d> { - Self::configure(clock_control, CpuClock::Clock240MHz) - } } #[cfg(esp32s3)] -impl<'d> ClockControl<'d> { - /// Use what is considered the default settings after boot. - pub fn boot_defaults( - clock_control: impl Peripheral

+ 'd, - ) -> ClockControl<'d> { - ClockControl { - _private: clock_control.into_ref(), - desired_rates: RawClocks { - cpu_clock: HertzU32::MHz(80), - apb_clock: HertzU32::MHz(80), - xtal_clock: HertzU32::MHz(40), - crypto_pwm_clock: HertzU32::MHz(160), - }, - } - } - +impl ClockControl { /// Configure the CPU clock speed. - pub fn configure( - clock_control: impl Peripheral

+ 'd, - cpu_clock_speed: CpuClock, - ) -> ClockControl<'d> { - clocks_ll::set_cpu_clock(cpu_clock_speed); + pub(crate) fn configure(cpu_clock_speed: CpuClock) -> ClockControl { + if cpu_clock_speed != CpuClock::boot_default() { + clocks_ll::set_cpu_clock(cpu_clock_speed); + } ClockControl { - _private: clock_control.into_ref(), desired_rates: RawClocks { cpu_clock: cpu_clock_speed.frequency(), apb_clock: HertzU32::MHz(80), @@ -747,9 +604,4 @@ impl<'d> ClockControl<'d> { }, } } - - /// Use the highest possible frequency for a particular chip - pub fn max(clock_control: impl Peripheral

+ 'd) -> ClockControl<'d> { - Self::configure(clock_control, CpuClock::Clock240MHz) - } } diff --git a/esp-hal/src/lib.rs b/esp-hal/src/lib.rs index 9710e12bea0..dc687108b2c 100644 --- a/esp-hal/src/lib.rs +++ b/esp-hal/src/lib.rs @@ -644,3 +644,31 @@ macro_rules! before_snippet { )) }; } + +use crate::{ + clock::{ClockControl, Clocks, CpuClock}, + peripherals::Peripherals, +}; + +/// System components. +pub struct System { + /// The available peripheral instances. + pub peripherals: Peripherals, + + /// The configured clocks. + pub clocks: Clocks<'static>, + + /// The available software interrupts. + pub software_interrupt_control: crate::system::SoftwareInterruptControl, +} + +/// Initialize the system. +pub fn init(clock_config: CpuClock) -> System { + let peripherals = Peripherals::take(); + + System { + peripherals, + clocks: ClockControl::new(clock_config).freeze(), + software_interrupt_control: crate::system::SoftwareInterruptControl::new(), + } +} diff --git a/esp-hal/src/prelude.rs b/esp-hal/src/prelude.rs index 32c9a1cd8a5..41a19827407 100644 --- a/esp-hal/src/prelude.rs +++ b/esp-hal/src/prelude.rs @@ -38,4 +38,4 @@ pub use crate::timer::timg::{ pub use crate::timer::Timer as _esp_hal_timer_Timer; #[cfg(any(uart0, uart1, uart2))] pub use crate::uart::Instance as _esp_hal_uart_Instance; -pub use crate::{entry, macros::*, InterruptConfigurable}; +pub use crate::{clock::CpuClock, entry, macros::*, InterruptConfigurable, System}; diff --git a/esp-hal/src/system.rs b/esp-hal/src/system.rs index da49a3e2196..6aeff9fdebb 100755 --- a/esp-hal/src/system.rs +++ b/esp-hal/src/system.rs @@ -31,12 +31,7 @@ #![allow(missing_docs)] // TODO: Remove when able -use crate::{ - interrupt::InterruptHandler, - peripheral::PeripheralRef, - peripherals::SYSTEM, - InterruptConfigurable, -}; +use crate::{interrupt::InterruptHandler, peripherals::SYSTEM, InterruptConfigurable}; /// Peripherals which can be enabled via `PeripheralClockControl` pub enum Peripheral { @@ -108,27 +103,6 @@ pub enum Peripheral { LcdCam, } -/// The `DPORT`/`PCR`/`SYSTEM` peripheral split into its different logical -/// components. -pub struct SystemControl<'d> { - _inner: PeripheralRef<'d, SYSTEM>, - pub clock_control: SystemClockControl, - pub software_interrupt_control: SoftwareInterruptControl, -} - -impl<'d> SystemControl<'d> { - /// Construct a new instance of [`SystemControl`]. - pub fn new(system: impl crate::peripheral::Peripheral

+ 'd) -> Self { - crate::into_ref!(system); - - Self { - _inner: system, - clock_control: SystemClockControl::new(), - software_interrupt_control: SoftwareInterruptControl::new(), - } - } -} - /// A software interrupt can be triggered by software. #[non_exhaustive] pub struct SoftwareInterrupt; @@ -261,7 +235,7 @@ pub struct SoftwareInterruptControl { } impl SoftwareInterruptControl { - fn new() -> Self { + pub(crate) fn new() -> Self { SoftwareInterruptControl { software_interrupt0: SoftwareInterrupt {}, software_interrupt1: SoftwareInterrupt {}, diff --git a/hil-test/tests/embassy_timers_executors.rs b/hil-test/tests/embassy_timers_executors.rs index 966a41d6461..921c9a3a5b7 100644 --- a/hil-test/tests/embassy_timers_executors.rs +++ b/hil-test/tests/embassy_timers_executors.rs @@ -7,10 +7,7 @@ use embassy_time::{Duration, Ticker, Timer}; use esp_hal::{ - clock::{ClockControl, Clocks}, - peripherals::Peripherals, prelude::*, - system::SystemControl, timer::{timg::TimerGroup, ErasedTimer, OneShotTimer, PeriodicTimer}, }; #[cfg(not(feature = "esp32"))] @@ -107,25 +104,15 @@ mod test_cases { } } -struct Resources { - clocks: Clocks<'static>, - timg0: esp_hal::peripherals::TIMG0, - #[cfg(not(feature = "esp32"))] - systimer: esp_hal::peripherals::SYSTIMER, - software_interrupt_control: esp_hal::system::SoftwareInterruptControl, +fn set_up_embassy_with_timg0(system: System) { + let timg0 = TimerGroup::new(system.peripherals.TIMG0, &system.clocks); + esp_hal_embassy::init(&system.clocks, timg0.timer0); } -impl Resources { - fn set_up_embassy_with_timg0(self) { - let timg0 = TimerGroup::new(self.timg0, &self.clocks); - esp_hal_embassy::init(&self.clocks, timg0.timer0); - } - - #[cfg(not(feature = "esp32"))] - fn set_up_embassy_with_systimer(self) { - let systimer = SystemTimer::new(self.systimer).split::(); - esp_hal_embassy::init(&self.clocks, systimer.alarm0); - } +#[cfg(not(feature = "esp32"))] +fn set_up_embassy_with_systimer(system: System) { + let systimer = SystemTimer::new(system.peripherals.SYSTIMER).split::(); + esp_hal_embassy::init(&system.clocks, systimer.alarm0); } #[cfg(test)] @@ -135,23 +122,14 @@ mod test { use crate::{test_cases::*, test_helpers::*}; #[init] - fn init() -> Resources { - let peripherals = unsafe { Peripherals::steal() }; - let system = SystemControl::new(peripherals.SYSTEM); - - Resources { - clocks: ClockControl::boot_defaults(system.clock_control).freeze(), - timg0: peripherals.TIMG0, - #[cfg(not(feature = "esp32"))] - systimer: peripherals.SYSTIMER, - software_interrupt_control: system.software_interrupt_control, - } + fn init() -> System { + esp_hal::init(CpuClock::boot_default()) } #[test] #[timeout(3)] - async fn test_one_shot_timg(resources: Resources) { - resources.set_up_embassy_with_timg0(); + async fn test_one_shot_timg(system: System) { + set_up_embassy_with_timg0(system); run_test_one_shot_async().await; } @@ -159,16 +137,16 @@ mod test { #[test] #[timeout(3)] #[cfg(not(feature = "esp32"))] - async fn test_one_shot_systimer(resources: Resources) { - resources.set_up_embassy_with_systimer(); + async fn test_one_shot_systimer(system: System) { + set_up_embassy_with_systimer(system); run_test_one_shot_async().await; } #[test] #[timeout(3)] - fn test_periodic_timg(resources: Resources) { - let timg0 = TimerGroup::new(resources.timg0, &resources.clocks); + fn test_periodic_timg(system: System) { + let timg0 = TimerGroup::new(system.peripherals.TIMG0, &system.clocks); run_test_periodic_timer(timg0.timer0); } @@ -176,32 +154,32 @@ mod test { #[test] #[timeout(3)] #[cfg(not(feature = "esp32"))] - fn test_periodic_systimer(resources: Resources) { - let systimer = SystemTimer::new(resources.systimer).split::(); + fn test_periodic_systimer(system: System) { + let systimer = SystemTimer::new(system.peripherals.SYSTIMER).split::(); run_test_periodic_timer(systimer.alarm0); } #[test] #[timeout(3)] - fn test_periodic_oneshot_timg(mut resources: Resources) { - let mut timg0 = TimerGroup::new(&mut resources.timg0, &resources.clocks); + fn test_periodic_oneshot_timg(mut system: System) { + let mut timg0 = TimerGroup::new(&mut system.peripherals.TIMG0, &system.clocks); run_test_periodic_timer(&mut timg0.timer0); - let mut timg0 = TimerGroup::new(&mut resources.timg0, &resources.clocks); + let mut timg0 = TimerGroup::new(&mut system.peripherals.TIMG0, &system.clocks); run_test_oneshot_timer(&mut timg0.timer0); } #[test] #[timeout(3)] #[cfg(not(feature = "esp32"))] - fn test_periodic_oneshot_systimer(mut resources: Resources) { - let mut systimer = SystemTimer::new(&mut resources.systimer); + fn test_periodic_oneshot_systimer(mut system: System) { + let mut systimer = SystemTimer::new(&mut system.peripherals.SYSTIMER); let unit = FrozenUnit::new(&mut systimer.unit0); let mut alarm: Alarm<'_, Periodic, _, _, _> = Alarm::new(systimer.comparator0, &unit); run_test_periodic_timer(&mut alarm); - let mut systimer = SystemTimer::new(&mut resources.systimer); + let mut systimer = SystemTimer::new(&mut system.peripherals.SYSTIMER); let unit = FrozenUnit::new(&mut systimer.unit0); let mut alarm: Alarm<'_, Target, _, _, _> = Alarm::new(systimer.comparator0, &unit); run_test_oneshot_timer(&mut alarm); @@ -209,8 +187,8 @@ mod test { #[test] #[timeout(3)] - async fn test_join_timg(resources: Resources) { - resources.set_up_embassy_with_timg0(); + async fn test_join_timg(system: System) { + set_up_embassy_with_timg0(system); run_join_test().await; } @@ -218,8 +196,8 @@ mod test { #[test] #[timeout(3)] #[cfg(not(feature = "esp32"))] - async fn test_join_systimer(resources: Resources) { - resources.set_up_embassy_with_systimer(); + async fn test_join_systimer(system: System) { + set_up_embassy_with_systimer(system); run_join_test().await; } @@ -228,21 +206,21 @@ mod test { #[test] #[timeout(3)] #[cfg(not(feature = "esp32"))] - async fn test_interrupt_executor(resources: Resources) { - let timg0 = TimerGroup::new(resources.timg0, &resources.clocks); + async fn test_interrupt_executor(system: System) { + let timg0 = TimerGroup::new(system.peripherals.TIMG0, &system.clocks); let timer0: ErasedTimer = timg0.timer0.into(); let timer0 = OneShotTimer::new(timer0); - let systimer = SystemTimer::new(resources.systimer).split::(); + let systimer = SystemTimer::new(system.peripherals.SYSTIMER).split::(); let alarm0: ErasedTimer = systimer.alarm0.into(); let timer1 = OneShotTimer::new(alarm0); let timers = mk_static!([OneShotTimer; 2], [timer0, timer1]); - esp_hal_embassy::init(&resources.clocks, timers); + esp_hal_embassy::init(&system.clocks, timers); let executor = mk_static!( InterruptExecutor<2>, - InterruptExecutor::new(resources.software_interrupt_control.software_interrupt2) + InterruptExecutor::new(system.software_interrupt_control.software_interrupt2) ); #[embassy_executor::task] @@ -281,8 +259,8 @@ mod test { /// Test that timg0 and systimer don't have vastly different tick rates. #[test] #[timeout(3)] - async fn tick_test_timer_tick_rates(resources: Resources) { - resources.set_up_embassy_with_timg0(); + async fn tick_test_timer_tick_rates(system: System) { + set_up_embassy_with_timg0(system); // We are retrying 5 times because probe-rs polling RTT may introduce some // jitter.