From 9b048f4c997d71daee8a5f34b5470424313ad4b7 Mon Sep 17 00:00:00 2001 From: Zgarbul Andrey Date: Sat, 30 Mar 2024 19:19:43 +0300 Subject: [PATCH] MCPWM clusters (#1360) --- esp-hal/CHANGELOG.md | 1 + esp-hal/Cargo.toml | 16 +- esp-hal/src/mcpwm/operator.rs | 352 +++++++--------------------------- esp-hal/src/mcpwm/timer.rs | 128 +++---------- esp-lp-hal/Cargo.toml | 6 +- 5 files changed, 109 insertions(+), 394 deletions(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index c24e56de1..62f669a40 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -44,6 +44,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 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) ### Removed diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index 724cc3bec..9d59045f4 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 = "1a96602", features = ["critical-section"], optional = true } -esp32c2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "1a96602", features = ["critical-section"], optional = true } -esp32c3 = { git = "https://github.com/esp-rs/esp-pacs", rev = "1a96602", features = ["critical-section"], optional = true } -esp32c6 = { git = "https://github.com/esp-rs/esp-pacs", rev = "1a96602", features = ["critical-section"], optional = true } -esp32h2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "1a96602", features = ["critical-section"], optional = true } -esp32p4 = { git = "https://github.com/esp-rs/esp-pacs", rev = "1a96602", features = ["critical-section"], optional = true } -esp32s2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "1a96602", features = ["critical-section"], optional = true } -esp32s3 = { git = "https://github.com/esp-rs/esp-pacs", rev = "1a96602", features = ["critical-section"], optional = true } +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 } [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/mcpwm/operator.rs b/esp-hal/src/mcpwm/operator.rs index b87084a2b..98886178a 100644 --- a/esp-hal/src/mcpwm/operator.rs +++ b/esp-hal/src/mcpwm/operator.rs @@ -142,71 +142,6 @@ impl DeadTimeCfg { } } -#[cfg(feature = "esp32s3")] -fn dt_cfg() -> &'static crate::peripherals::mcpwm0::DB0_CFG { - let block = unsafe { &*PWM::block() }; - match OP { - 0 => block.db0_cfg(), - 1 => unsafe { &*(&block.db1_cfg() as *const _ as *const _) }, - 2 => unsafe { &*(&block.db2_cfg() as *const _ as *const _) }, - _ => unreachable!(), - } -} -#[cfg(feature = "esp32s3")] -fn dt_fed() -> &'static crate::peripherals::mcpwm0::DB0_FED_CFG { - let block = unsafe { &*PWM::block() }; - match OP { - 0 => block.db0_fed_cfg(), - 1 => unsafe { &*(&block.db1_fed_cfg() as *const _ as *const _) }, - 2 => unsafe { &*(&block.db2_fed_cfg() as *const _ as *const _) }, - _ => unreachable!(), - } -} -#[cfg(feature = "esp32s3")] -fn dt_red() -> &'static crate::peripherals::mcpwm0::DB0_RED_CFG { - let block = unsafe { &*PWM::block() }; - match OP { - 0 => block.db0_red_cfg(), - 1 => unsafe { &*(&block.db1_red_cfg() as *const _ as *const _) }, - 2 => unsafe { &*(&block.db2_red_cfg() as *const _ as *const _) }, - _ => unreachable!(), - } -} - -// TODO: dt_cfg, dt_fed, dt_red (and similar functions in mcpwm can be made safe -// by patching PACS) -#[cfg(not(feature = "esp32s3"))] -fn dt_cfg() -> &'static crate::peripherals::mcpwm0::DT0_CFG { - let block = unsafe { &*PWM::block() }; - match OP { - 0 => block.dt0_cfg(), - 1 => unsafe { &*(&block.dt1_cfg() as *const _ as *const _) }, - 2 => unsafe { &*(&block.dt2_cfg() as *const _ as *const _) }, - _ => unreachable!(), - } -} - -#[cfg(not(feature = "esp32s3"))] -fn dt_fed() -> &'static crate::peripherals::mcpwm0::DT0_FED_CFG { - let block = unsafe { &*PWM::block() }; - match OP { - 0 => block.dt0_fed_cfg(), - 1 => unsafe { &*(&block.dt1_fed_cfg() as *const _ as *const _) }, - 2 => unsafe { &*(&block.dt2_fed_cfg() as *const _ as *const _) }, - _ => unreachable!(), - } -} -#[cfg(not(feature = "esp32s3"))] -fn dt_red() -> &'static crate::peripherals::mcpwm0::DT0_RED_CFG { - let block = unsafe { &*PWM::block() }; - match OP { - 0 => block.dt0_red_cfg(), - 1 => unsafe { &*(&block.dt1_red_cfg() as *const _ as *const _) }, - 2 => unsafe { &*(&block.dt2_red_cfg() as *const _ as *const _) }, - _ => unreachable!(), - } -} - /// A MCPWM operator /// /// The PWM Operator submodule has the following functions: @@ -255,9 +190,23 @@ impl Operator { /// Configures deadtime for this operator pub fn set_deadtime(&mut self, cfg: &DeadTimeCfg) { - dt_fed::().write(|w| unsafe { w.bits(cfg.falling_edge_delay as u32) }); - dt_red::().write(|w| unsafe { w.bits(cfg.rising_edge_delay as u32) }); - dt_cfg::().write(|w| unsafe { w.bits(cfg.cfg_reg) }); + let ch = unsafe { &*PWM::block() }.ch(OP as usize); + #[cfg(esp32s3)] + { + ch.db_fed_cfg() + .write(|w| unsafe { w.bits(cfg.falling_edge_delay as u32) }); + ch.db_red_cfg() + .write(|w| unsafe { w.bits(cfg.rising_edge_delay as u32) }); + ch.db_cfg().write(|w| unsafe { w.bits(cfg.cfg_reg) }); + } + #[cfg(not(esp32s3))] + { + ch.dt_fed_cfg() + .write(|w| unsafe { w.bits(cfg.falling_edge_delay as u32) }); + ch.dt_red_cfg() + .write(|w| unsafe { w.bits(cfg.rising_edge_delay as u32) }); + ch.dt_cfg().write(|w| unsafe { w.bits(cfg.cfg_reg) }); + } } /// Use the A output with the given pin and configuration @@ -350,7 +299,11 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> /// another pin #[inline] pub fn update_fed(&self, cycles: u16) { - dt_fed::().write(|w| unsafe { w.bits(cycles as u32) }); + #[cfg(esp32s3)] + let dt_fed = unsafe { Self::ch() }.db_fed_cfg(); + #[cfg(not(esp32s3))] + let dt_fed = unsafe { Self::ch() }.dt_fed_cfg(); + dt_fed.write(|w| unsafe { w.bits(cycles as u32) }); } /// Updates dead-time RED register @@ -359,251 +312,89 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> /// another pin #[inline] pub fn update_red(&self, cycles: u16) { - dt_red::().write(|w| unsafe { w.bits(cycles as u32) }); + #[cfg(esp32s3)] + let dt_red = unsafe { Self::ch() }.db_red_cfg(); + #[cfg(not(esp32s3))] + let dt_red = unsafe { Self::ch() }.dt_red_cfg(); + dt_red.write(|w| unsafe { w.bits(cycles as u32) }); } /// Configure what actions should be taken on timing events pub fn set_actions(&mut self, value: PwmActions) { // SAFETY: // We only write to our GENx_x register - let block = unsafe { &*PWM::block() }; - + let ch = unsafe { Self::ch() }; let bits = value.0; // SAFETY: // `bits` is a valid bit pattern - unsafe { - match (OP, IS_A) { - (0, true) => block.gen0_a().write(|w| w.bits(bits)), - (1, true) => block.gen1_a().write(|w| w.bits(bits)), - (2, true) => block.gen2_a().write(|w| w.bits(bits)), - (0, false) => block.gen0_b().write(|w| w.bits(bits)), - (1, false) => block.gen1_b().write(|w| w.bits(bits)), - (2, false) => block.gen2_b().write(|w| w.bits(bits)), - _ => unreachable!(), - } - } + ch.gen((!IS_A) as usize).write(|w| unsafe { w.bits(bits) }) } /// Set how a new timestamp syncs with the timer - #[cfg(esp32)] pub fn set_update_method(&mut self, update_method: PwmUpdateMethod) { // SAFETY: // We only write to our GENx_x_UPMETHOD register - let block = unsafe { &*PWM::block() }; + let ch = unsafe { Self::ch() }; let bits = update_method.0; - match (OP, IS_A) { - (0, true) => block - .gen0_stmp_cfg() - .modify(|_, w| w.gen0_a_upmethod().variant(bits)), - (1, true) => block - .gen1_stmp_cfg() - .modify(|_, w| w.gen1_a_upmethod().variant(bits)), - (2, true) => block - .gen2_stmp_cfg() - .modify(|_, w| w.gen2_a_upmethod().variant(bits)), - (0, false) => block - .gen0_stmp_cfg() - .modify(|_, w| w.gen0_b_upmethod().variant(bits)), - (1, false) => block - .gen1_stmp_cfg() - .modify(|_, w| w.gen1_b_upmethod().variant(bits)), - (2, false) => block - .gen2_stmp_cfg() - .modify(|_, w| w.gen2_b_upmethod().variant(bits)), - _ => { - unreachable!() - } - } - } - /// Set how a new timestamp syncs with the timer - #[cfg(esp32s3)] - pub fn set_update_method(&mut self, update_method: PwmUpdateMethod) { - // SAFETY: - // We only write to our GENx_x_UPMETHOD register - let block = unsafe { &*PWM::block() }; - let bits = update_method.0; - match (OP, IS_A) { - (0, true) => block - .cmpr0_cfg() - .modify(|_, w| w.cmpr0_a_upmethod().variant(bits)), - (1, true) => block - .cmpr1_cfg() - .modify(|_, w| w.cmpr1_a_upmethod().variant(bits)), - (2, true) => block - .cmpr2_cfg() - .modify(|_, w| w.cmpr2_a_upmethod().variant(bits)), - (0, false) => block - .cmpr0_cfg() - .modify(|_, w| w.cmpr0_b_upmethod().variant(bits)), - (1, false) => block - .cmpr1_cfg() - .modify(|_, w| w.cmpr1_b_upmethod().variant(bits)), - (2, false) => block - .cmpr2_cfg() - .modify(|_, w| w.cmpr2_b_upmethod().variant(bits)), - _ => { - unreachable!() - } - } - } + #[cfg(esp32s3)] + let cfg = ch.cmpr_cfg(); + #[cfg(any(esp32, esp32c6, esp32h2))] + let cfg = ch.gen_stmp_cfg(); - /// Set how a new timestamp syncs with the timer - #[cfg(any(esp32c6, esp32h2))] - pub fn set_update_method(&mut self, update_method: PwmUpdateMethod) { - // SAFETY: - // We only write to our GENx_x_UPMETHOD register - let block = unsafe { &*PWM::block() }; - let bits = update_method.0; - match (OP, IS_A) { - (0, true) => block - .gen0_stmp_cfg() - .modify(|_, w| w.cmpr0_a_upmethod().variant(bits)), - (1, true) => block - .gen1_stmp_cfg() - .modify(|_, w| w.cmpr1_a_upmethod().variant(bits)), - (2, true) => block - .gen2_stmp_cfg() - .modify(|_, w| w.cmpr2_a_upmethod().variant(bits)), - (0, false) => block - .gen0_stmp_cfg() - .modify(|_, w| w.cmpr0_b_upmethod().variant(bits)), - (1, false) => block - .gen1_stmp_cfg() - .modify(|_, w| w.cmpr1_b_upmethod().variant(bits)), - (2, false) => block - .gen2_stmp_cfg() - .modify(|_, w| w.cmpr2_b_upmethod().variant(bits)), - _ => { - unreachable!() + cfg.modify(|_, w| unsafe { + if IS_A { + w.a_upmethod().bits(bits) + } else { + w.b_upmethod().bits(bits) } - } + }) } /// Write a new timestamp. /// The written value will take effect according to the set /// [`PwmUpdateMethod`]. - #[cfg(esp32)] pub fn set_timestamp(&mut self, value: u16) { // SAFETY: // We only write to our GENx_TSTMP_x register - let block = unsafe { &*PWM::block() }; - match (OP, IS_A) { - (0, true) => block.gen0_tstmp_a().write(|w| w.gen0_a().variant(value)), - (1, true) => block.gen1_tstmp_a().write(|w| w.gen1_a().variant(value)), - (2, true) => block.gen2_tstmp_a().write(|w| w.gen2_a().variant(value)), - (0, false) => block.gen0_tstmp_b().write(|w| w.gen0_b().variant(value)), - (1, false) => block.gen1_tstmp_b().write(|w| w.gen1_b().variant(value)), - (2, false) => block.gen2_tstmp_b().write(|w| w.gen2_b().variant(value)), - _ => { - unreachable!() - } + let ch = unsafe { Self::ch() }; + + #[cfg(esp32s3)] + if IS_A { + ch.cmpr_value0().write(|w| unsafe { w.a().bits(value) }) + } else { + ch.cmpr_value1().write(|w| unsafe { w.b().bits(value) }) + } + + #[cfg(any(esp32, esp32c6, esp32h2))] + if IS_A { + ch.gen_tstmp_a().write(|w| unsafe { w.a().bits(value) }) + } else { + ch.gen_tstmp_b().write(|w| unsafe { w.b().bits(value) }) } } /// Get the old timestamp. /// The value of the timestamp will take effect according to the set /// [`PwmUpdateMethod`]. - #[cfg(esp32)] pub fn get_timestamp(&self) -> u16 { // SAFETY: // We only read to our GENx_TSTMP_x register - let block = unsafe { &*PWM::block() }; - match (OP, IS_A) { - (0, true) => block.gen0_tstmp_a().read().gen0_a().bits(), - (1, true) => block.gen1_tstmp_a().read().gen1_a().bits(), - (2, true) => block.gen2_tstmp_a().read().gen2_a().bits(), - (0, false) => block.gen0_tstmp_b().read().gen0_b().bits(), - (1, false) => block.gen1_tstmp_b().read().gen1_b().bits(), - (2, false) => block.gen2_tstmp_b().read().gen2_b().bits(), - _ => { - unreachable!() - } - } - } + let ch = unsafe { Self::ch() }; - /// Write a new timestamp. - /// The written value will take effect according to the set - /// [`PwmUpdateMethod`]. - #[cfg(esp32s3)] - pub fn set_timestamp(&mut self, value: u16) { - // SAFETY: - // We only write to our CMPRx_VALUEx register - let block = unsafe { &*PWM::block() }; - match (OP, IS_A) { - (0, true) => block.cmpr0_value0().write(|w| w.cmpr0_a().variant(value)), - (1, true) => block.cmpr1_value0().write(|w| w.cmpr1_a().variant(value)), - (2, true) => block.cmpr2_value0().write(|w| w.cmpr2_a().variant(value)), - (0, false) => block.cmpr0_value1().write(|w| w.cmpr0_b().variant(value)), - (1, false) => block.cmpr1_value1().write(|w| w.cmpr1_b().variant(value)), - (2, false) => block.cmpr2_value1().write(|w| w.cmpr2_b().variant(value)), - _ => { - unreachable!() - } + #[cfg(esp32s3)] + if IS_A { + ch.cmpr_value0().read().a().bits() + } else { + ch.cmpr_value1().read().b().bits() } - } - /// Get the old timestamp. - /// The value of the timestamp will take effect according to the set - /// [`PwmUpdateMethod`]. - #[cfg(esp32s3)] - pub fn get_timestamp(&self) -> u16 { - // SAFETY: - // We only read to our GENx_TSTMP_x register - let block = unsafe { &*PWM::block() }; - match (OP, IS_A) { - (0, true) => block.cmpr0_value0().read().cmpr0_a().bits(), - (1, true) => block.cmpr1_value0().read().cmpr1_a().bits(), - (2, true) => block.cmpr2_value0().read().cmpr2_a().bits(), - (0, false) => block.cmpr0_value1().read().cmpr0_b().bits(), - (1, false) => block.cmpr1_value1().read().cmpr1_b().bits(), - (2, false) => block.cmpr2_value1().read().cmpr2_b().bits(), - _ => { - unreachable!() - } - } - } - - /// Write a new timestamp. - /// The written value will take effect according to the set - /// [`PwmUpdateMethod`]. - #[cfg(any(esp32c6, esp32h2))] - pub fn set_timestamp(&mut self, value: u16) { - // SAFETY: - // We only write to our GENx_TSTMP_x register - let block = unsafe { &*PWM::block() }; - match (OP, IS_A) { - (0, true) => block.gen0_tstmp_a().write(|w| w.cmpr0_a().variant(value)), - (1, true) => block.gen1_tstmp_a().write(|w| w.cmpr1_a().variant(value)), - (2, true) => block.gen2_tstmp_a().write(|w| w.cmpr2_a().variant(value)), - (0, false) => block.gen0_tstmp_b().write(|w| w.cmpr0_b().variant(value)), - (1, false) => block.gen1_tstmp_b().write(|w| w.cmpr1_b().variant(value)), - (2, false) => block.gen2_tstmp_b().write(|w| w.cmpr2_b().variant(value)), - _ => { - unreachable!() - } - } - } - - /// Get the old timestamp. - /// The value of the timestamp will take effect according to the set - /// [`PwmUpdateMethod`]. - #[cfg(any(esp32c6, esp32h2))] - pub fn get_timestamp(&self) -> u16 { - // SAFETY: - // We only read to our GENx_TSTMP_x register - let block = unsafe { &*PWM::block() }; - match (OP, IS_A) { - (0, true) => block.gen0_tstmp_a().read().cmpr0_a().bits(), - (1, true) => block.gen1_tstmp_a().read().cmpr1_a().bits(), - (2, true) => block.gen2_tstmp_a().read().cmpr2_a().bits(), - (0, false) => block.gen0_tstmp_b().read().cmpr0_b().bits(), - (1, false) => block.gen1_tstmp_b().read().cmpr1_b().bits(), - (2, false) => block.gen2_tstmp_b().read().cmpr2_b().bits(), - _ => { - unreachable!() - } + #[cfg(any(esp32, esp32c6, esp32h2))] + if IS_A { + ch.gen_tstmp_a().read().a().bits() + } else { + ch.gen_tstmp_b().read().b().bits() } } @@ -626,15 +417,12 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> // SAFETY: // The CFG0 registers are identical for all timers so we can pretend they're // TIMER0_CFG0 - let timer0_cfg = &block.timer0_cfg0(); - let timer0_cfg = match tim { - 0 => timer0_cfg, - 1 => unsafe { &*(&block.timer1_cfg0() as *const _ as *const _) }, - 2 => unsafe { &*(&block.timer2_cfg0() as *const _ as *const _) }, - _ => unreachable!(), - }; + block.timer(tim as usize).cfg0().read().period().bits() + } - timer0_cfg.read().timer0_period().bits() + unsafe fn ch() -> &'static crate::peripherals::mcpwm0::CH { + let block = unsafe { &*PWM::block() }; + block.ch(OP as usize) } } diff --git a/esp-hal/src/mcpwm/timer.rs b/esp-hal/src/mcpwm/timer.rs index 5b92c5798..0ed211052 100644 --- a/esp-hal/src/mcpwm/timer.rs +++ b/esp-hal/src/mcpwm/timer.rs @@ -13,7 +13,6 @@ use fugit::HertzU32; use crate::{ clock::Clocks, mcpwm::{FrequencyError, PeripheralClockConfig, PwmPeripheral}, - peripherals::mcpwm0::{TIMER0_CFG0, TIMER0_CFG1}, }; /// A MCPWM timer @@ -46,136 +45,63 @@ impl Timer { /// events but this HAL does not expose these for now. pub fn start(&mut self, timer_config: TimerClockConfig) { // write prescaler and period with immediate update method - self.cfg0().write(|w| { - w.timer0_prescale() - .variant(timer_config.prescaler) - .timer0_period() - .variant(timer_config.period) - .timer0_period_upmethod() - .variant(0) + self.cfg0().write(|w| unsafe { + w.prescale().bits(timer_config.prescaler); + w.period().bits(timer_config.period); + w.period_upmethod().bits(0) }); // set timer to continuously run and set the timer working mode - self.cfg1().write(|w| { - w.timer0_start() - .variant(2) - .timer0_mod() - .variant(timer_config.mode as u8) + self.cfg1().write(|w| unsafe { + w.start().bits(2); + w.mod_().bits(timer_config.mode as u8) }); } /// Stop the timer in its current state pub fn stop(&mut self) { // freeze the timer - self.cfg1().write(|w| w.timer0_mod().variant(0)); + self.cfg1().write(|w| unsafe { w.mod_().bits(0) }); } /// Set the timer counter to the provided value pub fn set_counter(&mut self, phase: u16, direction: CounterDirection) { // SAFETY: // We only write to our TIMERx_SYNC register - let block = unsafe { &*PWM::block() }; - - match TIM { - 0 => { - let sw = block.timer0_sync().read().sw().bit_is_set(); - block.timer0_sync().write(|w| { - w.timer0_phase_direction() - .variant(direction as u8 != 0) - .timer0_phase() - .variant(phase) - .sw() - .variant(!sw) - }); + let tmr = unsafe { Self::tmr() }; + let sw = tmr.sync().read().sw().bit_is_set(); + tmr.sync().write(|w| { + w.phase_direction().bit(direction as u8 != 0); + unsafe { + w.phase().bits(phase); } - 1 => { - let sw = block.timer1_sync().read().sw().bit_is_set(); - block.timer1_sync().write(|w| { - w.timer1_phase_direction() - .variant(direction as u8 != 0) - .timer1_phase() - .variant(phase) - .sw() - .variant(!sw) - }); - } - 2 => { - let sw = block.timer2_sync().read().sw().bit_is_set(); - block.timer2_sync().write(|w| { - w.timer2_phase_direction() - .variant(direction as u8 != 0) - .timer2_phase() - .variant(phase) - .sw() - .variant(!sw) - }); - } - _ => unreachable!(), - } + w.sw().bit(!sw) + }); } /// Read the counter value and counter direction of the timer pub fn status(&self) -> (u16, CounterDirection) { // SAFETY: // We only read from our TIMERx_STATUS register - let block = unsafe { &*PWM::block() }; - - match TIM { - 0 => { - let reg = block.timer0_status().read(); - ( - reg.timer0_value().bits(), - reg.timer0_direction().bit_is_set().into(), - ) - } - 1 => { - let reg = block.timer1_status().read(); - ( - reg.timer1_value().bits(), - reg.timer1_direction().bit_is_set().into(), - ) - } - 2 => { - let reg = block.timer2_status().read(); - ( - reg.timer2_value().bits(), - reg.timer2_direction().bit_is_set().into(), - ) - } - _ => unreachable!(), - } + let reg = unsafe { Self::tmr() }.status().read(); + (reg.value().bits(), reg.direction().bit_is_set().into()) } - fn cfg0(&mut self) -> &TIMER0_CFG0 { + fn cfg0(&mut self) -> &crate::peripherals::mcpwm0::timer::CFG0 { // SAFETY: // We only grant access to our CFG0 register with the lifetime of &mut self - let block = unsafe { &*PWM::block() }; - - // SAFETY: - // The CFG0 registers are identical for all timers so we can pretend they're - // TIMER0_CFG0 - match TIM { - 0 => block.timer0_cfg0(), - 1 => unsafe { &*(&block.timer1_cfg0() as *const _ as *const _) }, - 2 => unsafe { &*(&block.timer2_cfg0() as *const _ as *const _) }, - _ => unreachable!(), - } + unsafe { Self::tmr() }.cfg0() } - fn cfg1(&mut self) -> &TIMER0_CFG1 { + fn cfg1(&mut self) -> &crate::peripherals::mcpwm0::timer::CFG1 { // SAFETY: - // We only grant access to our CFG1 register with the lifetime of &mut self - let block = unsafe { &*PWM::block() }; + // We only grant access to our CFG0 register with the lifetime of &mut self + unsafe { Self::tmr() }.cfg1() + } - // SAFETY: - // The CFG1 registers are identical for all timers so we can pretend they're - // TIMER0_CFG1 - match TIM { - 0 => block.timer0_cfg1(), - 1 => unsafe { &*(&block.timer1_cfg1() as *const _ as *const _) }, - 2 => unsafe { &*(&block.timer2_cfg1() as *const _ as *const _) }, - _ => unreachable!(), - } + unsafe fn tmr() -> &'static crate::peripherals::mcpwm0::TIMER { + let block = unsafe { &*PWM::block() }; + block.timer(TIM as usize) } } diff --git a/esp-lp-hal/Cargo.toml b/esp-lp-hal/Cargo.toml index b85fb3737..58a90e1ed 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 = "1a96602", features = ["critical-section"], optional = true } -esp32s2-ulp = { git = "https://github.com/esp-rs/esp-pacs", rev = "1a96602", features = ["critical-section"], optional = true } -esp32s3-ulp = { git = "https://github.com/esp-rs/esp-pacs", rev = "1a96602", features = ["critical-section"], 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 } nb = { version = "1.1.0", optional = true } paste = { version = "1.0.14", optional = true } procmacros = { package = "esp-hal-procmacros", path = "../esp-hal-procmacros" }