From c2279a28d3c3d8f962d7411565d38dea03457535 Mon Sep 17 00:00:00 2001 From: Zgarbul Andrey Date: Sun, 31 Mar 2024 15:05:28 +0300 Subject: [PATCH] TIMG clusters (#1364) --- esp-hal/CHANGELOG.md | 5 +- esp-hal/Cargo.toml | 16 +-- esp-hal/src/timer.rs | 281 +++++++++--------------------------------- esp-lp-hal/Cargo.toml | 6 +- 4 files changed, 75 insertions(+), 233 deletions(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index c52f94806..87eac536c 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -43,8 +43,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - DMA channels can/have to be explicitly created for async or blocking drivers, added `set_interrupt_handler` to DMA channels, SPI, I2S, PARL_IO, don't enable interrupts on startup for DMA, I2S, PARL_IO, GPIO (#1300) - UART: Rework `change_baud` so it is possible to set baud rate even after instantiation (#1350) - Runtime ISR binding for SHA,ECC and RSA (#1354) -- Update `pac`s with removed suffixes in `int` field names. Use `W1TC` for `int_clr` -- Update `pac`s with removed suffixes in `int` field names. Use `W1TC` for `int_clr` (#1357) and MCPWM clusters (#1360) +- Update `pac`s with removed suffixes in `int` field names. Use `W1TC` for `int_clr` (#1357) + MCPWM clusters (#1360) + TIMG clusters (#1364) ### Removed diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index 9d59045f4..a151b5f9c 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -52,14 +52,14 @@ xtensa-lx = { version = "0.9.0", optional = true } # IMPORTANT: # Each supported device MUST have its PAC included below along with a # corresponding feature. -esp32 = { git = "https://github.com/esp-rs/esp-pacs", rev = "bc355d6", features = ["critical-section"], optional = true } -esp32c2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "bc355d6", features = ["critical-section"], optional = true } -esp32c3 = { git = "https://github.com/esp-rs/esp-pacs", rev = "bc355d6", features = ["critical-section"], optional = true } -esp32c6 = { git = "https://github.com/esp-rs/esp-pacs", rev = "bc355d6", features = ["critical-section"], optional = true } -esp32h2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "bc355d6", features = ["critical-section"], optional = true } -esp32p4 = { git = "https://github.com/esp-rs/esp-pacs", rev = "bc355d6", features = ["critical-section"], optional = true } -esp32s2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "bc355d6", features = ["critical-section"], optional = true } -esp32s3 = { git = "https://github.com/esp-rs/esp-pacs", rev = "bc355d6", features = ["critical-section"], optional = true } +esp32 = { git = "https://github.com/esp-rs/esp-pacs", rev = "130e7f8", features = ["critical-section"], optional = true } +esp32c2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "130e7f8", features = ["critical-section"], optional = true } +esp32c3 = { git = "https://github.com/esp-rs/esp-pacs", rev = "130e7f8", features = ["critical-section"], optional = true } +esp32c6 = { git = "https://github.com/esp-rs/esp-pacs", rev = "130e7f8", features = ["critical-section"], optional = true } +esp32h2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "130e7f8", features = ["critical-section"], optional = true } +esp32p4 = { git = "https://github.com/esp-rs/esp-pacs", rev = "130e7f8", features = ["critical-section"], optional = true } +esp32s2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "130e7f8", features = ["critical-section"], optional = true } +esp32s3 = { git = "https://github.com/esp-rs/esp-pacs", rev = "130e7f8", features = ["critical-section"], optional = true } [target.'cfg(target_arch = "riscv32")'.dependencies] esp-riscv-rt = { version = "0.7.0", optional = true, path = "../esp-riscv-rt" } diff --git a/esp-hal/src/timer.rs b/esp-hal/src/timer.rs index 2da1b209f..fe018765e 100644 --- a/esp-hal/src/timer.rs +++ b/esp-hal/src/timer.rs @@ -103,7 +103,8 @@ impl TimerGroupInstance for TIMG0 { fn configure_src_clk() { unsafe { (*Self::register_block()) - .t0config() + .t(0) + .config() .modify(|_, w| w.use_xtal().clear_bit()) }; } @@ -156,7 +157,8 @@ impl TimerGroupInstance for TIMG1 { fn configure_src_clk() { unsafe { (*Self::register_block()) - .t1config() + .t(1) + .config() .modify(|_, w| w.use_xtal().clear_bit()) }; } @@ -267,7 +269,7 @@ where } /// Timer peripheral instance -pub trait Instance: crate::private::Sealed { +pub trait Instance: crate::private::Sealed + Enable { fn reset_counter(&mut self); fn set_counter_active(&mut self, state: bool); @@ -297,17 +299,24 @@ pub trait Instance: crate::private::Sealed { fn set_divider(&mut self, divider: u16); fn is_interrupt_set(&self) -> bool; +} +pub trait Enable: crate::private::Sealed { fn enable_peripheral(&self); } -pub struct Timer0 { +pub struct TimerX { phantom: PhantomData, } -impl crate::private::Sealed for Timer0 {} +pub type Timer0 = TimerX; -impl Timer0 +#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] +pub type Timer1 = TimerX; + +impl crate::private::Sealed for TimerX {} + +impl TimerX where TG: TimerGroupInstance, { @@ -317,65 +326,58 @@ where phantom: PhantomData, } } + + unsafe fn t() -> &'static crate::peripherals::timg0::T { + (*TG::register_block()).t(T as usize) + } } /// Timer peripheral instance -impl Instance for Timer0 +impl Instance for TimerX where TG: TimerGroupInstance, + Self: Enable, { fn reset_counter(&mut self) { - let reg_block = unsafe { &*TG::register_block() }; + let t = unsafe { Self::t() }; - reg_block - .t0loadlo() - .write(|w| unsafe { w.load_lo().bits(0) }); + t.loadlo().write(|w| unsafe { w.load_lo().bits(0) }); - reg_block - .t0loadhi() - .write(|w| unsafe { w.load_hi().bits(0) }); + t.loadhi().write(|w| unsafe { w.load_hi().bits(0) }); - reg_block.t0load().write(|w| unsafe { w.load().bits(1) }); + t.load().write(|w| unsafe { w.load().bits(1) }); } fn set_counter_active(&mut self, state: bool) { - let reg_block = unsafe { &*TG::register_block() }; - - reg_block.t0config().modify(|_, w| w.en().bit(state)); + unsafe { Self::t() } + .config() + .modify(|_, w| w.en().bit(state)); } fn is_counter_active(&self) -> bool { - let reg_block = unsafe { &*TG::register_block() }; - - reg_block.t0config().read().en().bit_is_set() + unsafe { Self::t() }.config().read().en().bit_is_set() } fn set_counter_decrementing(&mut self, decrementing: bool) { - let reg_block = unsafe { &*TG::register_block() }; - - reg_block - .t0config() + unsafe { Self::t() } + .config() .modify(|_, w| w.increase().bit(!decrementing)); } fn set_auto_reload(&mut self, auto_reload: bool) { - let reg_block = unsafe { &*TG::register_block() }; - - reg_block - .t0config() + unsafe { Self::t() } + .config() .modify(|_, w| w.autoreload().bit(auto_reload)); } fn set_alarm_active(&mut self, state: bool) { - let reg_block = unsafe { &*TG::register_block() }; - - reg_block.t0config().modify(|_, w| w.alarm_en().bit(state)); + unsafe { Self::t() } + .config() + .modify(|_, w| w.alarm_en().bit(state)); } fn is_alarm_active(&self) -> bool { - let reg_block = unsafe { &*TG::register_block() }; - - reg_block.t0config().read().alarm_en().bit_is_set() + unsafe { Self::t() }.config().read().alarm_en().bit_is_set() } fn load_alarm_value(&mut self, value: u64) { @@ -383,15 +385,11 @@ where let high = (value >> 32) as u32; let low = (value & 0xFFFF_FFFF) as u32; - let reg_block = unsafe { &*TG::register_block() }; + let t = unsafe { Self::t() }; - reg_block - .t0alarmlo() - .write(|w| unsafe { w.alarm_lo().bits(low) }); + t.alarmlo().write(|w| unsafe { w.alarm_lo().bits(low) }); - reg_block - .t0alarmhi() - .write(|w| unsafe { w.alarm_hi().bits(high) }); + t.alarmhi().write(|w| unsafe { w.alarm_hi().bits(high) }); } fn listen(&mut self) { @@ -399,17 +397,17 @@ where // always use level interrupt #[cfg(any(esp32, esp32s2))] - reg_block - .t0config() + unsafe { Self::t() } + .config() .modify(|_, w| w.level_int_en().set_bit()); - reg_block.int_ena_timers().modify(|_, w| w.t0().set_bit()); + reg_block.int_ena_timers().modify(|_, w| w.t(T).set_bit()); } fn unlisten(&mut self) { let reg_block = unsafe { &*TG::register_block() }; - reg_block.int_ena_timers().modify(|_, w| w.t0().clear_bit()); + reg_block.int_ena_timers().modify(|_, w| w.t(T).clear_bit()); } fn clear_interrupt(&mut self) { @@ -417,23 +415,23 @@ where reg_block .int_clr_timers() - .write(|w| w.t0().clear_bit_by_one()); + .write(|w| w.t(T).clear_bit_by_one()); } fn now(&self) -> u64 { - let reg_block = unsafe { &*TG::register_block() }; + let t = unsafe { Self::t() }; - reg_block.t0update().write(|w| w.update().set_bit()); - while reg_block.t0update().read().update().bit_is_set() {} + t.update().write(|w| w.update().set_bit()); + while t.update().read().update().bit_is_set() {} - let value_lo = reg_block.t0lo().read().bits() as u64; - let value_hi = (reg_block.t0hi().read().bits() as u64) << 32; + let value_lo = t.lo().read().bits() as u64; + let value_hi = (t.hi().read().bits() as u64) << 32; value_lo | value_hi } fn divider(&self) -> u32 { - let reg_block = unsafe { &*TG::register_block() }; + let t = unsafe { Self::t() }; // From the ESP32 TRM, "11.2.1 16­-bit Prescaler and Clock Selection": // @@ -441,7 +439,7 @@ where // Specifically, when TIMGn_Tx_DIVIDER is either 1 or 2, the clock divisor is 2; // when TIMGn_Tx_DIVIDER is 0, the clock divisor is 65536. Any other value will // cause the clock to be divided by exactly that value." - match reg_block.t0config().read().divider().bits() { + match t.config().read().divider().bits() { 0 => 65536, 1 | 2 => 2, n => n as u32, @@ -451,187 +449,30 @@ where fn is_interrupt_set(&self) -> bool { let reg_block = unsafe { &*TG::register_block() }; - reg_block.int_raw_timers().read().t0().bit_is_set() + reg_block.int_raw_timers().read().t(T).bit_is_set() } fn set_divider(&mut self, divider: u16) { - let reg_block = unsafe { &*TG::register_block() }; - - reg_block - .t0config() + unsafe { Self::t() } + .config() .modify(|_, w| unsafe { w.divider().bits(divider) }) } +} +impl Enable for Timer0 +where + TG: TimerGroupInstance, +{ fn enable_peripheral(&self) { PeripheralClockControl::enable(crate::system::Peripheral::Timg0); } } #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] -pub struct Timer1 { - phantom: PhantomData, -} - -#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] -impl crate::private::Sealed for Timer1 {} - -#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] -impl Timer1 +impl Enable for Timer1 where TG: TimerGroupInstance, { - #[allow(unused)] - pub(crate) unsafe fn steal() -> Self { - Self { - phantom: PhantomData, - } - } -} - -/// Timer peripheral instance -#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] -impl Instance for Timer1 -where - TG: TimerGroupInstance, -{ - fn reset_counter(&mut self) { - let reg_block = unsafe { &*TG::register_block() }; - - reg_block - .t1loadlo() - .write(|w| unsafe { w.load_lo().bits(0) }); - - reg_block - .t1loadhi() - .write(|w| unsafe { w.load_hi().bits(0) }); - - reg_block.t1load().write(|w| unsafe { w.load().bits(1) }); - } - - fn set_counter_active(&mut self, state: bool) { - let reg_block = unsafe { &*TG::register_block() }; - - reg_block.t1config().modify(|_, w| w.en().bit(state)); - } - - fn is_counter_active(&self) -> bool { - let reg_block = unsafe { &*TG::register_block() }; - - reg_block.t1config().read().en().bit_is_set() - } - - fn set_counter_decrementing(&mut self, decrementing: bool) { - let reg_block = unsafe { &*TG::register_block() }; - - reg_block - .t1config() - .modify(|_, w| w.increase().bit(!decrementing)); - } - - fn set_auto_reload(&mut self, auto_reload: bool) { - let reg_block = unsafe { &*TG::register_block() }; - - reg_block - .t1config() - .modify(|_, w| w.autoreload().bit(auto_reload)); - } - - fn set_alarm_active(&mut self, state: bool) { - let reg_block = unsafe { &*TG::register_block() }; - - reg_block.t1config().modify(|_, w| w.alarm_en().bit(state)); - } - - fn is_alarm_active(&self) -> bool { - let reg_block = unsafe { &*TG::register_block() }; - - reg_block.t1config().read().alarm_en().bit_is_set() - } - - fn load_alarm_value(&mut self, value: u64) { - let value = value & 0x3F_FFFF_FFFF_FFFF; - let high = (value >> 32) as u32; - let low = (value & 0xFFFF_FFFF) as u32; - - let reg_block = unsafe { &*TG::register_block() }; - - reg_block - .t1alarmlo() - .write(|w| unsafe { w.alarm_lo().bits(low) }); - - reg_block - .t1alarmhi() - .write(|w| unsafe { w.alarm_hi().bits(high) }); - } - - fn listen(&mut self) { - let reg_block = unsafe { &*TG::register_block() }; - - // always use level interrupt - #[cfg(any(esp32, esp32s2))] - reg_block - .t1config() - .modify(|_, w| w.level_int_en().set_bit()); - - reg_block.int_ena_timers().modify(|_, w| w.t1().set_bit()); - } - - fn unlisten(&mut self) { - let reg_block = unsafe { &*TG::register_block() }; - - reg_block.int_ena_timers().modify(|_, w| w.t1().clear_bit()); - } - - fn clear_interrupt(&mut self) { - let reg_block = unsafe { &*TG::register_block() }; - - reg_block - .int_clr_timers() - .write(|w| w.t1().clear_bit_by_one()); - } - - fn now(&self) -> u64 { - let reg_block = unsafe { &*TG::register_block() }; - - reg_block.t1update().write(|w| w.update().set_bit()); - while reg_block.t1update().read().update().bit_is_set() {} - - let value_lo = reg_block.t1lo().read().bits() as u64; - let value_hi = (reg_block.t1hi().read().bits() as u64) << 32; - - value_lo | value_hi - } - - fn divider(&self) -> u32 { - let reg_block = unsafe { &*TG::register_block() }; - - // From the ESP32 TRM, "11.2.1 16­-bit Prescaler and Clock Selection": - // - // "The prescaler can divide the APB clock by a factor from 2 to 65536. - // Specifically, when TIMGn_Tx_DIVIDER is either 1 or 2, the clock divisor is 2; - // when TIMGn_Tx_DIVIDER is 0, the clock divisor is 65536. Any other value will - // cause the clock to be divided by exactly that value." - match reg_block.t1config().read().divider().bits() { - 0 => 65536, - 1 | 2 => 2, - n => n as u32, - } - } - - fn is_interrupt_set(&self) -> bool { - let reg_block = unsafe { &*TG::register_block() }; - - reg_block.int_raw_timers().read().t1().bit_is_set() - } - - fn set_divider(&mut self, divider: u16) { - let reg_block = unsafe { &*TG::register_block() }; - - reg_block - .t1config() - .modify(|_, w| unsafe { w.divider().bits(divider) }) - } - fn enable_peripheral(&self) { PeripheralClockControl::enable(crate::system::Peripheral::Timg1); } diff --git a/esp-lp-hal/Cargo.toml b/esp-lp-hal/Cargo.toml index 58a90e1ed..a4c51ca2a 100644 --- a/esp-lp-hal/Cargo.toml +++ b/esp-lp-hal/Cargo.toml @@ -24,9 +24,9 @@ categories = [ cfg-if = "1.0.0" embedded-hal-02 = { version = "0.2.7", package = "embedded-hal", optional = true, features = ["unproven"] } embedded-hal-1 = { version = "1.0.0", package = "embedded-hal", optional = true } -esp32c6-lp = { git = "https://github.com/esp-rs/esp-pacs", rev = "bc355d6", features = ["critical-section"], optional = true } -esp32s2-ulp = { git = "https://github.com/esp-rs/esp-pacs", rev = "bc355d6", features = ["critical-section"], optional = true } -esp32s3-ulp = { git = "https://github.com/esp-rs/esp-pacs", rev = "bc355d6", features = ["critical-section"], optional = true } +esp32c6-lp = { git = "https://github.com/esp-rs/esp-pacs", rev = "130e7f8", features = ["critical-section"], optional = true } +esp32s2-ulp = { git = "https://github.com/esp-rs/esp-pacs", rev = "130e7f8", features = ["critical-section"], optional = true } +esp32s3-ulp = { git = "https://github.com/esp-rs/esp-pacs", rev = "130e7f8", features = ["critical-section"], optional = true } nb = { version = "1.1.0", optional = true } paste = { version = "1.0.14", optional = true } procmacros = { package = "esp-hal-procmacros", path = "../esp-hal-procmacros" }