MCPWM clusters (#1360)

This commit is contained in:
Zgarbul Andrey 2024-03-30 19:19:43 +03:00 committed by GitHub
parent bd1e1fab1a
commit 9b048f4c99
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 109 additions and 394 deletions

View File

@ -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) - 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) - 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`
- Update `pac`s with removed suffixes in `int` field names. Use `W1TC` for `int_clr` (#1357) and MCPWM clusters (#1360)
### Removed ### Removed

View File

@ -52,14 +52,14 @@ xtensa-lx = { version = "0.9.0", optional = true }
# IMPORTANT: # IMPORTANT:
# Each supported device MUST have its PAC included below along with a # Each supported device MUST have its PAC included below along with a
# corresponding feature. # corresponding feature.
esp32 = { 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 = "1a96602", 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 = "1a96602", 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 = "1a96602", 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 = "1a96602", 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 = "1a96602", 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 = "1a96602", 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 = "1a96602", 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] [target.'cfg(target_arch = "riscv32")'.dependencies]
esp-riscv-rt = { version = "0.7.0", optional = true, path = "../esp-riscv-rt" } esp-riscv-rt = { version = "0.7.0", optional = true, path = "../esp-riscv-rt" }

View File

@ -142,71 +142,6 @@ impl DeadTimeCfg {
} }
} }
#[cfg(feature = "esp32s3")]
fn dt_cfg<const OP: u8, PWM: PwmPeripheral>() -> &'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<const OP: u8, PWM: PwmPeripheral>() -> &'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<const OP: u8, PWM: PwmPeripheral>() -> &'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<const OP: u8, PWM: PwmPeripheral>() -> &'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<const OP: u8, PWM: PwmPeripheral>() -> &'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<const OP: u8, PWM: PwmPeripheral>() -> &'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 /// A MCPWM operator
/// ///
/// The PWM Operator submodule has the following functions: /// The PWM Operator submodule has the following functions:
@ -255,9 +190,23 @@ impl<const OP: u8, PWM: PwmPeripheral> Operator<OP, PWM> {
/// Configures deadtime for this operator /// Configures deadtime for this operator
pub fn set_deadtime(&mut self, cfg: &DeadTimeCfg) { pub fn set_deadtime(&mut self, cfg: &DeadTimeCfg) {
dt_fed::<OP, PWM>().write(|w| unsafe { w.bits(cfg.falling_edge_delay as u32) }); let ch = unsafe { &*PWM::block() }.ch(OP as usize);
dt_red::<OP, PWM>().write(|w| unsafe { w.bits(cfg.rising_edge_delay as u32) }); #[cfg(esp32s3)]
dt_cfg::<OP, PWM>().write(|w| unsafe { w.bits(cfg.cfg_reg) }); {
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 /// 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 /// another pin
#[inline] #[inline]
pub fn update_fed(&self, cycles: u16) { pub fn update_fed(&self, cycles: u16) {
dt_fed::<OP, PWM>().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 /// Updates dead-time RED register
@ -359,251 +312,89 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
/// another pin /// another pin
#[inline] #[inline]
pub fn update_red(&self, cycles: u16) { pub fn update_red(&self, cycles: u16) {
dt_red::<OP, PWM>().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 /// Configure what actions should be taken on timing events
pub fn set_actions(&mut self, value: PwmActions<IS_A>) { pub fn set_actions(&mut self, value: PwmActions<IS_A>) {
// SAFETY: // SAFETY:
// We only write to our GENx_x register // We only write to our GENx_x register
let block = unsafe { &*PWM::block() }; let ch = unsafe { Self::ch() };
let bits = value.0; let bits = value.0;
// SAFETY: // SAFETY:
// `bits` is a valid bit pattern // `bits` is a valid bit pattern
unsafe { ch.gen((!IS_A) as usize).write(|w| unsafe { w.bits(bits) })
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!(),
}
}
} }
/// Set how a new timestamp syncs with the timer /// Set how a new timestamp syncs with the timer
#[cfg(esp32)]
pub fn set_update_method(&mut self, update_method: PwmUpdateMethod) { pub fn set_update_method(&mut self, update_method: PwmUpdateMethod) {
// SAFETY: // SAFETY:
// We only write to our GENx_x_UPMETHOD register // We only write to our GENx_x_UPMETHOD register
let block = unsafe { &*PWM::block() }; let ch = unsafe { Self::ch() };
let bits = update_method.0; 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)]
#[cfg(esp32s3)] let cfg = ch.cmpr_cfg();
pub fn set_update_method(&mut self, update_method: PwmUpdateMethod) { #[cfg(any(esp32, esp32c6, esp32h2))]
// SAFETY: let cfg = ch.gen_stmp_cfg();
// 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!()
}
}
}
/// Set how a new timestamp syncs with the timer cfg.modify(|_, w| unsafe {
#[cfg(any(esp32c6, esp32h2))] if IS_A {
pub fn set_update_method(&mut self, update_method: PwmUpdateMethod) { w.a_upmethod().bits(bits)
// SAFETY: } else {
// We only write to our GENx_x_UPMETHOD register w.b_upmethod().bits(bits)
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!()
} }
} })
} }
/// Write a new timestamp. /// Write a new timestamp.
/// The written value will take effect according to the set /// The written value will take effect according to the set
/// [`PwmUpdateMethod`]. /// [`PwmUpdateMethod`].
#[cfg(esp32)]
pub fn set_timestamp(&mut self, value: u16) { pub fn set_timestamp(&mut self, value: u16) {
// SAFETY: // SAFETY:
// We only write to our GENx_TSTMP_x register // We only write to our GENx_TSTMP_x register
let block = unsafe { &*PWM::block() }; let ch = unsafe { Self::ch() };
match (OP, IS_A) {
(0, true) => block.gen0_tstmp_a().write(|w| w.gen0_a().variant(value)), #[cfg(esp32s3)]
(1, true) => block.gen1_tstmp_a().write(|w| w.gen1_a().variant(value)), if IS_A {
(2, true) => block.gen2_tstmp_a().write(|w| w.gen2_a().variant(value)), ch.cmpr_value0().write(|w| unsafe { w.a().bits(value) })
(0, false) => block.gen0_tstmp_b().write(|w| w.gen0_b().variant(value)), } else {
(1, false) => block.gen1_tstmp_b().write(|w| w.gen1_b().variant(value)), ch.cmpr_value1().write(|w| unsafe { w.b().bits(value) })
(2, false) => block.gen2_tstmp_b().write(|w| w.gen2_b().variant(value)), }
_ => {
unreachable!() #[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. /// Get the old timestamp.
/// The value of the timestamp will take effect according to the set /// The value of the timestamp will take effect according to the set
/// [`PwmUpdateMethod`]. /// [`PwmUpdateMethod`].
#[cfg(esp32)]
pub fn get_timestamp(&self) -> u16 { pub fn get_timestamp(&self) -> u16 {
// SAFETY: // SAFETY:
// We only read to our GENx_TSTMP_x register // We only read to our GENx_TSTMP_x register
let block = unsafe { &*PWM::block() }; let ch = unsafe { Self::ch() };
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!()
}
}
}
/// Write a new timestamp. #[cfg(esp32s3)]
/// The written value will take effect according to the set if IS_A {
/// [`PwmUpdateMethod`]. ch.cmpr_value0().read().a().bits()
#[cfg(esp32s3)] } else {
pub fn set_timestamp(&mut self, value: u16) { ch.cmpr_value1().read().b().bits()
// 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!()
}
} }
}
/// Get the old timestamp. #[cfg(any(esp32, esp32c6, esp32h2))]
/// The value of the timestamp will take effect according to the set if IS_A {
/// [`PwmUpdateMethod`]. ch.gen_tstmp_a().read().a().bits()
#[cfg(esp32s3)] } else {
pub fn get_timestamp(&self) -> u16 { ch.gen_tstmp_b().read().b().bits()
// 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!()
}
} }
} }
@ -626,15 +417,12 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
// SAFETY: // SAFETY:
// The CFG0 registers are identical for all timers so we can pretend they're // The CFG0 registers are identical for all timers so we can pretend they're
// TIMER0_CFG0 // TIMER0_CFG0
let timer0_cfg = &block.timer0_cfg0(); block.timer(tim as usize).cfg0().read().period().bits()
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!(),
};
timer0_cfg.read().timer0_period().bits() unsafe fn ch() -> &'static crate::peripherals::mcpwm0::CH {
let block = unsafe { &*PWM::block() };
block.ch(OP as usize)
} }
} }

View File

@ -13,7 +13,6 @@ use fugit::HertzU32;
use crate::{ use crate::{
clock::Clocks, clock::Clocks,
mcpwm::{FrequencyError, PeripheralClockConfig, PwmPeripheral}, mcpwm::{FrequencyError, PeripheralClockConfig, PwmPeripheral},
peripherals::mcpwm0::{TIMER0_CFG0, TIMER0_CFG1},
}; };
/// A MCPWM timer /// A MCPWM timer
@ -46,136 +45,63 @@ impl<const TIM: u8, PWM: PwmPeripheral> Timer<TIM, PWM> {
/// events but this HAL does not expose these for now. /// events but this HAL does not expose these for now.
pub fn start(&mut self, timer_config: TimerClockConfig) { pub fn start(&mut self, timer_config: TimerClockConfig) {
// write prescaler and period with immediate update method // write prescaler and period with immediate update method
self.cfg0().write(|w| { self.cfg0().write(|w| unsafe {
w.timer0_prescale() w.prescale().bits(timer_config.prescaler);
.variant(timer_config.prescaler) w.period().bits(timer_config.period);
.timer0_period() w.period_upmethod().bits(0)
.variant(timer_config.period)
.timer0_period_upmethod()
.variant(0)
}); });
// set timer to continuously run and set the timer working mode // set timer to continuously run and set the timer working mode
self.cfg1().write(|w| { self.cfg1().write(|w| unsafe {
w.timer0_start() w.start().bits(2);
.variant(2) w.mod_().bits(timer_config.mode as u8)
.timer0_mod()
.variant(timer_config.mode as u8)
}); });
} }
/// Stop the timer in its current state /// Stop the timer in its current state
pub fn stop(&mut self) { pub fn stop(&mut self) {
// freeze the timer // 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 /// Set the timer counter to the provided value
pub fn set_counter(&mut self, phase: u16, direction: CounterDirection) { pub fn set_counter(&mut self, phase: u16, direction: CounterDirection) {
// SAFETY: // SAFETY:
// We only write to our TIMERx_SYNC register // We only write to our TIMERx_SYNC register
let block = unsafe { &*PWM::block() }; let tmr = unsafe { Self::tmr() };
let sw = tmr.sync().read().sw().bit_is_set();
match TIM { tmr.sync().write(|w| {
0 => { w.phase_direction().bit(direction as u8 != 0);
let sw = block.timer0_sync().read().sw().bit_is_set(); unsafe {
block.timer0_sync().write(|w| { w.phase().bits(phase);
w.timer0_phase_direction()
.variant(direction as u8 != 0)
.timer0_phase()
.variant(phase)
.sw()
.variant(!sw)
});
} }
1 => { w.sw().bit(!sw)
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!(),
}
} }
/// Read the counter value and counter direction of the timer /// Read the counter value and counter direction of the timer
pub fn status(&self) -> (u16, CounterDirection) { pub fn status(&self) -> (u16, CounterDirection) {
// SAFETY: // SAFETY:
// We only read from our TIMERx_STATUS register // We only read from our TIMERx_STATUS register
let block = unsafe { &*PWM::block() }; let reg = unsafe { Self::tmr() }.status().read();
(reg.value().bits(), reg.direction().bit_is_set().into())
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!(),
}
} }
fn cfg0(&mut self) -> &TIMER0_CFG0 { fn cfg0(&mut self) -> &crate::peripherals::mcpwm0::timer::CFG0 {
// SAFETY: // SAFETY:
// We only grant access to our CFG0 register with the lifetime of &mut self // We only grant access to our CFG0 register with the lifetime of &mut self
let block = unsafe { &*PWM::block() }; unsafe { Self::tmr() }.cfg0()
// 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!(),
}
} }
fn cfg1(&mut self) -> &TIMER0_CFG1 { fn cfg1(&mut self) -> &crate::peripherals::mcpwm0::timer::CFG1 {
// SAFETY: // SAFETY:
// We only grant access to our CFG1 register with the lifetime of &mut self // We only grant access to our CFG0 register with the lifetime of &mut self
let block = unsafe { &*PWM::block() }; unsafe { Self::tmr() }.cfg1()
}
// SAFETY: unsafe fn tmr() -> &'static crate::peripherals::mcpwm0::TIMER {
// The CFG1 registers are identical for all timers so we can pretend they're let block = unsafe { &*PWM::block() };
// TIMER0_CFG1 block.timer(TIM as usize)
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!(),
}
} }
} }

View File

@ -24,9 +24,9 @@ categories = [
cfg-if = "1.0.0" cfg-if = "1.0.0"
embedded-hal-02 = { version = "0.2.7", package = "embedded-hal", optional = true, features = ["unproven"] } 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 } 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 } 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 = "1a96602", 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 = "1a96602", 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 } nb = { version = "1.1.0", optional = true }
paste = { version = "1.0.14", optional = true } paste = { version = "1.0.14", optional = true }
procmacros = { package = "esp-hal-procmacros", path = "../esp-hal-procmacros" } procmacros = { package = "esp-hal-procmacros", path = "../esp-hal-procmacros" }