diff --git a/.zed/settings.json b/.zed/settings.json new file mode 100644 index 0000000..6708fc6 --- /dev/null +++ b/.zed/settings.json @@ -0,0 +1,15 @@ +{ + "lsp": { + "rust-analyzer": { + "initialization_options": { + "cargo": { + "features": ["stm32g474"] + }, + "check": { + "allTargets": false, + "targets": "thumbv7em-none-eabihf" + } + } + } + } +} diff --git a/Cargo.toml b/Cargo.toml index 35454e0..1853f6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,9 @@ stm32-hrtim = { path = "." } [dependencies] stm32f3 = { git = "https://github.com/stm32-rs/stm32-rs-nightlies", optional = true } -stm32h7 = { git = "https://github.com/stm32-rs/stm32-rs-nightlies", features = ["critical-section"], optional = true } +stm32h7 = { git = "https://github.com/stm32-rs/stm32-rs-nightlies", features = [ + "critical-section", +], optional = true } stm32g4 = { version = "0.22.0", package = "stm32g4-staging", optional = true } defmt = { version = "0.3.10", optional = true } @@ -22,7 +24,7 @@ cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } defmt-rtt = "0.4.0" cortex-m-rt = "0.7.2" panic-probe = { version = "0.3.0", features = ["print-defmt"] } -stm32g4xx-hal = { git = "https://github.com/usbalbin/stm32g4xx-hal", branch = "hrtim", features = ["defmt", "hrtim"] } +#stm32g4xx-hal = { git = "https://github.com/usbalbin/stm32g4xx-hal", branch = "hrtim", features = ["defmt", "hrtim"] } [features] default = [] @@ -46,8 +48,8 @@ stm32h753 = ["stm32h7/stm32h753", "hrtim_v1_1"] #stm32h755 = ["stm32h7/stm32h755", "hrtim_v1_1"] #stm32h757 = ["stm32h7/stm32h757", "hrtim_v1_1"] -stm32g474 = ["stm32g4/stm32g474", "stm32g4xx-hal/stm32g474", "hrtim_v2"] -stm32g484 = ["stm32g4/stm32g484", "stm32g4xx-hal/stm32g484", "hrtim_v2"] +stm32g474 = ["stm32g4/stm32g474", "hrtim_v2"] +stm32g484 = ["stm32g4/stm32g484", "hrtim_v2"] defmt = ["dep:defmt", "fugit/defmt"] # G4 @@ -95,4 +97,4 @@ path = "examples/stm32g4/hrtim.rs" [[example]] name = "stm32g4-master" required-features = ["stm32g4"] -path = "examples/stm32g4/master.rs" \ No newline at end of file +path = "examples/stm32g4/master.rs" diff --git a/examples/stm32g4/adc-trigger.rs b/examples/stm32g4/adc-trigger.rs index 05505c7..9c574a3 100644 --- a/examples/stm32g4/adc-trigger.rs +++ b/examples/stm32g4/adc-trigger.rs @@ -14,9 +14,9 @@ use stm32g4xx_hal::{ dma::{self, channel::DMAExt, config::DmaConfig, TransferExt}, gpio::GpioExt, hrtim::{HrControltExt, HrPwmBuilderExt}, + pac::{CorePeripherals, Peripherals}, pwr::PwrExt, rcc::{self, RccExt}, - stm32::{CorePeripherals, Peripherals}, }; #[entry] diff --git a/examples/stm32g4/capture-dma.rs b/examples/stm32g4/capture-dma.rs index bd55126..54031a5 100644 --- a/examples/stm32g4/capture-dma.rs +++ b/examples/stm32g4/capture-dma.rs @@ -16,9 +16,9 @@ use stm32g4xx_hal::{ dma::{channel::DMAExt, config::DmaConfig, TransferExt}, gpio::GpioExt, hrtim::{external_event::EevInputExt, HrControltExt, HrPwmBuilderExt}, + pac::Peripherals, pwr::PwrExt, rcc::{self, RccExt}, - stm32::Peripherals, }; #[entry] diff --git a/examples/stm32g4/capture.rs b/examples/stm32g4/capture.rs index 85c1b26..5e13641 100644 --- a/examples/stm32g4/capture.rs +++ b/examples/stm32g4/capture.rs @@ -15,9 +15,9 @@ use stm32_hrtim::{ use stm32g4xx_hal::{ gpio::GpioExt, hrtim::{external_event::EevInputExt, HrControltExt, HrPwmBuilderExt}, + pac::Peripherals, pwr::PwrExt, rcc::{self, RccExt}, - stm32::Peripherals, }; #[entry] diff --git a/examples/stm32g4/eev-comp.rs b/examples/stm32g4/eev-comp.rs index ab196f9..c3b6aca 100644 --- a/examples/stm32g4/eev-comp.rs +++ b/examples/stm32g4/eev-comp.rs @@ -19,9 +19,9 @@ use stm32g4xx_hal::{ delay::SYSTDelayExt, gpio::{GpioExt, SignalEdge}, hrtim::{external_event::EevInputExt, HrControltExt, HrPwmBuilderExt}, + pac::{CorePeripherals, Peripherals}, pwr::PwrExt, rcc::{self, RccExt}, - stm32::{CorePeripherals, Peripherals}, }; #[entry] diff --git a/examples/stm32g4/eev.rs b/examples/stm32g4/eev.rs index 0cf45e0..07b41f5 100644 --- a/examples/stm32g4/eev.rs +++ b/examples/stm32g4/eev.rs @@ -16,9 +16,9 @@ use stm32_hrtim::{ use stm32g4xx_hal::{ gpio::GpioExt, hrtim::{external_event::EevInputExt, HrControltExt, HrPwmBuilderExt}, + pac::Peripherals, pwr::PwrExt, rcc::{self, RccExt}, - stm32::Peripherals, }; #[entry] diff --git a/examples/stm32g4/flt.rs b/examples/stm32g4/flt.rs index 3deff42..de43713 100644 --- a/examples/stm32g4/flt.rs +++ b/examples/stm32g4/flt.rs @@ -16,9 +16,9 @@ use stm32g4xx_hal::{ delay::{DelayExt, SYSTDelayExt}, gpio::GpioExt, hrtim::{fault::FaultInput, HrControltExt, HrPwmBuilderExt}, + pac::{CorePeripherals, Peripherals}, pwr::PwrExt, rcc::{self, RccExt}, - stm32::{CorePeripherals, Peripherals}, time::ExtU32, }; diff --git a/examples/stm32g4/hrtim.rs b/examples/stm32g4/hrtim.rs index 8187ef3..9b5b526 100644 --- a/examples/stm32g4/hrtim.rs +++ b/examples/stm32g4/hrtim.rs @@ -8,7 +8,13 @@ use stm32_hrtim::{ Pscl4, }; use stm32g4xx_hal::{ - delay::{DelayExt, SYSTDelayExt}, gpio::GpioExt, hrtim::{HrControltExt, HrPwmBuilderExt}, pwr::PwrExt, rcc::{self, RccExt}, stm32::{CorePeripherals, Peripherals}, time::ExtU32 + delay::{DelayExt, SYSTDelayExt}, + gpio::GpioExt, + hrtim::{HrControltExt, HrPwmBuilderExt}, + pac::{CorePeripherals, Peripherals}, + pwr::PwrExt, + rcc::{self, RccExt}, + time::ExtU32, }; #[entry] diff --git a/examples/stm32g4/master.rs b/examples/stm32g4/master.rs index 8166507..3121524 100644 --- a/examples/stm32g4/master.rs +++ b/examples/stm32g4/master.rs @@ -10,7 +10,13 @@ use stm32_hrtim::{ HrParts, HrPwmAdvExt, HrTimerMode, MasterPreloadSource, PreloadSource, Pscl4, }; use stm32g4xx_hal::{ - delay::{DelayExt, SYSTDelayExt}, gpio::GpioExt, hrtim::{HrControltExt, HrPwmBuilderExt}, pwr::PwrExt, rcc::{self, RccExt}, stm32::{CorePeripherals, Peripherals}, time::ExtU32 + delay::{DelayExt, SYSTDelayExt}, + gpio::GpioExt, + hrtim::{HrControltExt, HrPwmBuilderExt}, + pac::{CorePeripherals, Peripherals}, + pwr::PwrExt, + rcc::{self, RccExt}, + time::ExtU32, }; #[entry] diff --git a/src/capture.rs b/src/capture.rs index 1e8e469..352b25e 100644 --- a/src/capture.rs +++ b/src/capture.rs @@ -1,13 +1,7 @@ -use super::timer; - -#[cfg(feature = "hrtim_v2")] -use crate::pac::HRTIM_TIMF; -use crate::pac::{HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME}; +use super::timer::{self, Ch1, Ch2, ChExt, InstanceX}; +use crate::ext::{CptcrW, MasterExt, TimExt}; use core::marker::PhantomData; -pub struct Ch1; -pub struct Ch2; - pub struct Dma; pub struct NoDma; @@ -161,108 +155,84 @@ pub fn dma_value_to_signed(x: u32, #[allow(unused_variables)] period: u16) -> i3 } } -macro_rules! impl_capture { - ($($TIMX:ident),+) => {$( - impl_capture!($TIMX: Ch1, cpt1r, cpt1cr, cpt1, cpt1ie, cpt1de, cpt1c); - impl_capture!($TIMX: Ch2, cpt2r, cpt2cr, cpt2, cpt2ie, cpt2de, cpt2c); - )+}; - - ($TIMX:ident: $CH:ident, $cptXr:ident, $cptXcr:ident, $cptX:ident, $cptXie:ident, $cptXde:ident, $cptXc:ident) => { - impl HrCapt<$TIMX, PSCL, $CH, NoDma> { - /// Add event to capture - /// - /// If multiple events are added, they will be ORed together meaning - /// that a capture will be trigger if any one of the events triggers - pub fn add_event>(&mut self, _event: &E) { - let tim = unsafe { &*$TIMX::ptr() }; - - // SAFETY: We are the only one with access to cptXYcr - unsafe { - tim.$cptXcr().modify(|r, w| w.bits(r.bits() | E::BITS)); - } - } - - /// Remove event to capture - pub fn remove_event>(&mut self, _event: &E) { - let tim = unsafe { &*$TIMX::ptr() }; - - // SAFETY: We are the only one with access to cptXYcr - unsafe { - tim.$cptXcr().modify(|r, w| w.bits(r.bits() & !E::BITS)); - } - } - - /// Force capture trigger now - pub fn trigger_now(&mut self) { - // SAFETY: We are the only one with access to cptXYcr - let tim = unsafe { &*$TIMX::ptr() }; - - tim.$cptXcr().modify(|_, w| w.swcpt().set_bit()); - } - - // TODO: It would be sufficient to instead of hr_control only require exclusive access to the owning timer - // however that would be hard to do since typically the capture device is a field of that same timer. - // Would it make more sense to have this method direcly on HrTim instead? - pub fn enable_interrupt(&mut self, enable: bool, _hr_control: &mut super::HrPwmControl) { - let tim = unsafe { &*$TIMX::ptr() }; - - tim.dier().modify(|_r, w| w.$cptXie().bit(enable)); - } - - pub fn enable_dma(self, _ch: timer::DmaChannel<$TIMX>) -> HrCapt<$TIMX, PSCL, $CH, Dma> { - // SAFETY: We own the only insance of this timers dma channel, no one else can do this - let tim = unsafe { &*$TIMX::ptr() }; - tim.dier().modify(|_r, w| w.$cptXde().set_bit()); - HrCapt { - _x: PhantomData - } - } +impl HrCapt { + /// Add event to capture + /// + /// If multiple events are added, they will be ORed together meaning + /// that a capture will be trigger if any one of the events triggers + pub fn add_event>(&mut self, _event: &E) { + let tim = unsafe { &*TIM::ptr() }; + + // SAFETY: We are the only one with access to cptXYcr + unsafe { + tim.cptcr(CH::CH).modify(|r, w| w.bits(r.bits() | E::BITS)); } + } - impl HrCapture for HrCapt<$TIMX, PSCL, $CH, DMA> { - fn get_last(&self) -> (u16, CountingDirection) { - let tim = unsafe { &*$TIMX::ptr() }; - let data = tim.$cptXr().read(); - - #[cfg(feature = "hrtim_v2")] - let dir = match data.dir().bit() { - true => CountingDirection::Down, - false => CountingDirection::Up, - }; - #[cfg(any(feature = "hrtim_v1", feature = "hrtim_v1_1"))] - let dir = CountingDirection::Up; + /// Remove event to capture + pub fn remove_event>(&mut self, _event: &E) { + let tim = unsafe { &*TIM::ptr() }; - let value = data.cpt().bits(); + // SAFETY: We are the only one with access to cptXYcr + unsafe { + tim.cptcr(CH::CH).modify(|r, w| w.bits(r.bits() & !E::BITS)); + } + } - (value, dir) - } + /// Force capture trigger now + pub fn trigger_now(&mut self) { + // SAFETY: We are the only one with access to cptXYcr + let tim = unsafe { &*TIM::ptr() }; - fn clear_interrupt(&mut self) { - let tim = unsafe { &*$TIMX::ptr() }; + tim.cptcr(CH::CH).modify(|_, w| w.set_swcpt()); + } - // No need for exclusive access since this is a write only register - tim.icr().write(|w| w.$cptXc().clear()); - } + // TODO: It would be sufficient to instead of hr_control only require exclusive access to the owning timer + // however that would be hard to do since typically the capture device is a field of that same timer. + // Would it make more sense to have this method direcly on HrTim instead? + pub fn enable_interrupt(&mut self, enable: bool, _hr_control: &mut super::HrPwmControl) { + let tim = unsafe { &*TIM::ptr() }; - fn is_pending(&self) -> bool { - let tim = unsafe { &*$TIMX::ptr() }; + tim.dier().modify(|_r, w| w.cptie(CH::CH as _).bit(enable)); + } - // No need for exclusive access since this is a read only register - tim.isr().read().$cptX().bit() - } - } - }; + pub fn enable_dma(self, _ch: timer::DmaChannel) -> HrCapt { + // SAFETY: We own the only insance of this timers dma channel, no one else can do this + let tim = unsafe { &*TIM::ptr() }; + tim.dier().modify(|_r, w| w.cptde(CH::CH as _).set_bit()); + HrCapt { _x: PhantomData } + } } -impl_capture! { - HRTIM_TIMA, - HRTIM_TIMB, - HRTIM_TIMC, - HRTIM_TIMD, - HRTIM_TIME -} +impl HrCapture for HrCapt { + fn get_last(&self) -> (u16, CountingDirection) { + let tim = unsafe { &*TIM::ptr() }; + let data = tim.cptr(CH::CH).read(); + + #[cfg(feature = "hrtim_v2")] + let dir = match data.dir().bit() { + true => CountingDirection::Down, + false => CountingDirection::Up, + }; + #[cfg(any(feature = "hrtim_v1", feature = "hrtim_v1_1"))] + let dir = CountingDirection::Up; + + let value = data.cpt().bits(); + + (value, dir) + } -#[cfg(feature = "hrtim_v2")] -impl_capture! { - HRTIM_TIMF + fn clear_interrupt(&mut self) { + let tim = unsafe { &*TIM::ptr() }; + + // No need for exclusive access since this is a write only register + tim.icr().write(|w| w.cptc(CH::CH as _).clear()); + } + + fn is_pending(&self) -> bool { + let tim = unsafe { &*TIM::ptr() }; + + // No need for exclusive access since this is a read only register + tim.isr().read().cpt(CH::CH as _).bit() + } } diff --git a/src/compare_register.rs b/src/compare_register.rs index da938e1..ef4633b 100644 --- a/src/compare_register.rs +++ b/src/compare_register.rs @@ -1,18 +1,43 @@ use core::marker::PhantomData; +use crate::ext::{Cmp, MasterExt}; #[cfg(feature = "hrtim_v2")] use crate::pac::HRTIM_TIMF; use crate::pac::{HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME}; +use crate::timer::{Instance, InstanceX}; pub trait HrCompareRegister { fn get_duty(&self) -> u16; fn set_duty(&mut self, duty: u16); } -pub struct HrCr1(PhantomData<(TIM, PSCL)>); -pub struct HrCr2(PhantomData<(TIM, PSCL)>); -pub struct HrCr3(PhantomData<(TIM, PSCL)>); -pub struct HrCr4(PhantomData<(TIM, PSCL)>); +pub struct Cmp1; +pub struct Cmp2; +pub struct Cmp3; +pub struct Cmp4; + +pub trait CmpExt { + const CMP: Cmp; +} + +impl CmpExt for Cmp1 { + const CMP: Cmp = Cmp::Cmp1; +} +impl CmpExt for Cmp2 { + const CMP: Cmp = Cmp::Cmp2; +} +impl CmpExt for Cmp3 { + const CMP: Cmp = Cmp::Cmp3; +} +impl CmpExt for Cmp4 { + const CMP: Cmp = Cmp::Cmp4; +} + +pub struct HrCr(PhantomData<(TIM, PSCL, CMP)>); +pub type HrCr1 = HrCr; +pub type HrCr2 = HrCr; +pub type HrCr3 = HrCr; +pub type HrCr4 = HrCr; #[cfg(feature = "stm32g4")] use super::adc_trigger::{ @@ -20,43 +45,32 @@ use super::adc_trigger::{ AdcTrigger6810 as Adc6810, }; +impl HrCompareRegister for HrCr { + fn get_duty(&self) -> u16 { + let tim = unsafe { &*TIM::ptr() }; + + tim.cmpr(CMP::CMP).read().cmp().bits() + } + fn set_duty(&mut self, duty: u16) { + let tim = unsafe { &*TIM::ptr() }; + + tim.cmpr(CMP::CMP).write(|w| unsafe { w.cmp().bits(duty) }); + } +} + macro_rules! hrtim_cr_helper { (HRTIM_MASTER: $cr_type:ident: - $cmpXYr:ident, [$(($Trigger:ty: $trigger_bits:expr)),*], [$(($event_dst:ident, $tim_event_index:expr)),*], - $bit_index:literal ) => { // Strip bit_index since master timer has other bits that are common across all destinations - hrtim_cr_helper!(HRTIM_MASTER: $cr_type: $cmpXYr, [$(($Trigger: $trigger_bits)),*], [$(($event_dst, $tim_event_index)),*]); + hrtim_cr_helper!(HRTIM_MASTER: $cr_type: [$(($Trigger: $trigger_bits)),*], [$(($event_dst, $tim_event_index)),*]); }; ($TIMX:ident: $cr_type:ident: - $cmpXYr:ident, [$(($Trigger:ty: $trigger_bits:expr)),*], [$(($event_dst:ident, $tim_event_index:expr)),*] - $(, $bit_index:literal)* ) => { - impl HrCompareRegister for $cr_type<$TIMX, PSCL> { - fn get_duty(&self) -> u16 { - let tim = unsafe { &*$TIMX::ptr() }; - - tim.$cmpXYr().read().cmp().bits() - } - fn set_duty(&mut self, duty: u16) { - let tim = unsafe { &*$TIMX::ptr() }; - - tim.$cmpXYr().write(|w| unsafe { w.cmp().bits(duty) }); - } - } - - $( - /// Compare match event - impl super::event::EventSource<$TIMX, PSCL> for $cr_type<$TIMX, PSCL> { - const BITS: u32 = 1 << $bit_index; - } - )* - $( /// Compare match event for neighbor timer impl super::event::EventSource<$event_dst, PSCL> for $cr_type<$TIMX, PSCL> { @@ -79,10 +93,10 @@ macro_rules! hrtim_cr { [$(($cr3_trigger:ident: $cr3_trigger_bits:expr)),*], [$(($cr3_event_dst:ident, $cr3_tim_event_index:expr)),*], [$(($cr4_trigger:ident: $cr4_trigger_bits:expr)),*], [$(($cr4_event_dst:ident, $cr4_tim_event_index:expr)),*] ]),+) => {$( - hrtim_cr_helper!($TIMX: HrCr1: cmp1r, [$(($cr1_trigger: $cr1_trigger_bits)),*], [$(($cr1_event_dst, $cr1_tim_event_index)),*], 3); - hrtim_cr_helper!($TIMX: HrCr2: cmp2r, [$(($cr2_trigger: $cr2_trigger_bits)),*], [$(($cr2_event_dst, $cr2_tim_event_index)),*], 4); - hrtim_cr_helper!($TIMX: HrCr3: cmp3r, [$(($cr3_trigger: $cr3_trigger_bits)),*], [$(($cr3_event_dst, $cr3_tim_event_index)),*], 5); - hrtim_cr_helper!($TIMX: HrCr4: cmp4r, [$(($cr4_trigger: $cr4_trigger_bits)),*], [$(($cr4_event_dst, $cr4_tim_event_index)),*], 6); + hrtim_cr_helper!($TIMX: HrCr1: [$(($cr1_trigger: $cr1_trigger_bits)),*], [$(($cr1_event_dst, $cr1_tim_event_index)),*]); + hrtim_cr_helper!($TIMX: HrCr2: [$(($cr2_trigger: $cr2_trigger_bits)),*], [$(($cr2_event_dst, $cr2_tim_event_index)),*]); + hrtim_cr_helper!($TIMX: HrCr3: [$(($cr3_trigger: $cr3_trigger_bits)),*], [$(($cr3_event_dst, $cr3_tim_event_index)),*]); + hrtim_cr_helper!($TIMX: HrCr4: [$(($cr4_trigger: $cr4_trigger_bits)),*], [$(($cr4_event_dst, $cr4_tim_event_index)),*]); )+}; } @@ -185,53 +199,34 @@ hrtim_cr! { ] } -macro_rules! hrtim_master_cr { - ($($cr_type:ident: $cr_index:expr),*) => {$( - /// Compare match event for neighbor timer - impl super::event::EventSource for $cr_type { - const BITS: u32 = 1 << ($cr_index + 7); // MSTCMP1 is at bit 8 etc - } - - impl super::event::TimerResetEventSource for $cr_type { - const BITS: u32 = 1 << ($cr_index + 4); // MSTCMP1 is at bit 5 - } - )*}; +/// Compare match event for neighbor timer +impl super::event::EventSource + for HrCr +{ + const BITS: u32 = 1 << (CMP::CMP as u8 + 8); // MSTCMP1 is at bit 8 etc } -hrtim_master_cr! { - HrCr1: 1, - HrCr2: 2, - HrCr3: 3, - HrCr4: 4 +impl super::event::TimerResetEventSource + for HrCr +{ + const BITS: u32 = 1 << (CMP::CMP as u8 + 5); // MSTCMP1 is at bit 5 } -macro_rules! hrtim_timer_rst { - ($($TIMX:ident: $cr_type:ident: $bit_index:literal),*) => {$( - impl super::event::TimerResetEventSource for $cr_type<$TIMX, PSCL> { - const BITS: u32 = 1 << $bit_index; - } - )*}; +/// Compare match event +impl super::event::EventSource + for HrCr +{ + const BITS: u32 = 1 << (CMP::CMP as u8 + 3); } -hrtim_timer_rst! { - HRTIM_TIMA: HrCr2: 2, - HRTIM_TIMA: HrCr4: 3, - - HRTIM_TIMB: HrCr2: 2, - HRTIM_TIMB: HrCr4: 3, - - HRTIM_TIMC: HrCr2: 2, - HRTIM_TIMC: HrCr4: 3, - - HRTIM_TIMD: HrCr2: 2, - HRTIM_TIMD: HrCr4: 3, - - HRTIM_TIME: HrCr2: 2, - HRTIM_TIME: HrCr4: 3 +impl super::event::TimerResetEventSource + for HrCr2 +{ + const BITS: u32 = 1 << 2; } -#[cfg(feature = "hrtim_v2")] -hrtim_timer_rst! { - HRTIM_TIMF: HrCr2: 2, - HRTIM_TIMF: HrCr4: 3 +impl super::event::TimerResetEventSource + for HrCr4 +{ + const BITS: u32 = 1 << 3; } diff --git a/src/ext.rs b/src/ext.rs new file mode 100644 index 0000000..3e4239e --- /dev/null +++ b/src/ext.rs @@ -0,0 +1,572 @@ +#[cfg(feature = "stm32f3")] +pub use stm32f3::*; +#[cfg(feature = "stm32g4")] +pub use stm32g4::*; +#[cfg(feature = "stm32h7")] +pub use stm32h7::*; + +use crate::pac; +use pac::hrtim_master as master; +use pac::hrtim_tima as tima; +use pac::hrtim_timb as timb; +use pac::hrtim_timc as timc; +use pac::hrtim_timd as timd; +use pac::hrtim_time as time; +#[cfg(feature = "hrtim_v2")] +use pac::hrtim_timf as timf; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[repr(u8)] +pub enum Chan { + Ch1 = 0, + Ch2 = 1, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[repr(u8)] +pub enum Cmp { + Cmp1 = 0, + Cmp2 = 1, + Cmp3 = 2, + Cmp4 = 3, +} + +pub trait MasterExt { + type CRrs: reg::MasterCrR + reg::MasterCrW; + fn cr(&self) -> &Reg; + type ISRrs: reg::MasterIsr; + fn isr(&self) -> &Reg; + type ICRrs: reg::MasterIcr; + fn icr(&self) -> &Reg; + type DIERrs: reg::MasterDierR + reg::MasterDierW; + fn dier(&self) -> &Reg; + fn cntr(&self) -> &master::CNTR; + fn perr(&self) -> &master::PERR; + fn repr(&self) -> &master::REPR; + fn cmp1r(&self) -> &master::CMP1R; + fn cmp2r(&self) -> &master::CMP1R; + fn cmp3r(&self) -> &master::CMP1R; + fn cmp4r(&self) -> &master::CMP1R; + fn cmpr(&self, c: Cmp) -> &master::CMP1R { + match c { + Cmp::Cmp1 => self.cmp1r(), + Cmp::Cmp2 => self.cmp2r(), + Cmp::Cmp3 => self.cmp3r(), + Cmp::Cmp4 => self.cmp4r(), + } + } +} + +pub trait TimExt: + MasterExt +{ + fn cmp1cr(&self) -> &tima::CMP1CR; + fn cpt1r(&self) -> &tima::CPT1R; + fn cpt2r(&self) -> &tima::CPT1R; + fn cptr(&self, c: Chan) -> &tima::CPT1R { + match c { + Chan::Ch1 => self.cpt1r(), + Chan::Ch2 => self.cpt2r(), + } + } + fn dtr(&self) -> &tima::DTR; + fn eefr1(&self) -> &tima::EEFR1; + fn eefr2(&self) -> &tima::EEFR2; + type SET1Rrs: RegisterSpec + Readable + Writable + Resettable; + type RST1Rrs: RegisterSpec + Readable + Writable + Resettable; + fn set1r(&self) -> &Reg; + fn rst1r(&self) -> &Reg; + fn set2r(&self) -> &Reg; + fn rst2r(&self) -> &Reg; + fn set_r(&self, c: Chan) -> &Reg { + match c { + Chan::Ch1 => self.set1r(), + Chan::Ch2 => self.set2r(), + } + } + fn rst_r(&self, c: Chan) -> &Reg { + match c { + Chan::Ch1 => self.rst1r(), + Chan::Ch2 => self.rst2r(), + } + } + type RSTRrs: RegisterSpec + Readable + Writable + Resettable; + fn rstr(&self) -> &Reg; + fn chpr(&self) -> &tima::CHPR; + type CPT1CRrs: reg::CptcrW + Readable; + fn cpt1cr(&self) -> &Reg; + fn cpt2cr(&self) -> &Reg; + fn cptcr(&self, c: Chan) -> &Reg { + match c { + Chan::Ch1 => self.cpt1cr(), + Chan::Ch2 => self.cpt2cr(), + } + } + fn outr(&self) -> &tima::OUTR; + fn fltr(&self) -> &tima::FLTR; + #[cfg(feature = "hrtim_v2")] + fn cr2(&self) -> &tima::CR2; + #[cfg(feature = "hrtim_v2")] + fn eefr3(&self) -> &tima::EEFR3; +} + +macro_rules! wrap_r { + (pub trait $TrR:ident { + $(fn $f:ident(&self $(, $n:ident: u8)?) -> $fr:path;)* + }) => { + pub trait $TrR { + $(fn $f(&self $(, $n: u8)?) -> $fr;)* + } + impl $TrR for R { + $( + #[inline(always)] + fn $f(&self $(, $n: u8)?) -> $fr { + REG::$f(self $(, $n)?) + } + )* + } + }; +} + +macro_rules! wrap_w { + (pub trait $TrR:ident { + $(fn $f:ident(&mut self $(, $n:ident: u8)?) -> $fr:path;)* + }) => { + pub trait $TrR { + $(fn $f(&mut self $(, $n: u8)?) -> $fr;)* + } + + impl $TrR for W { + $( + #[inline(always)] + fn $f(&mut self $(, $n: u8)?) -> $fr { + REG::$f(self $(, $n)?) + } + )* + } + }; +} + +wrap_r! { + pub trait MasterCrR { + fn ckpsc(&self) -> master::cr::CKPSC_R; + fn cont(&self) -> master::cr::CONT_R; + fn retrig(&self) -> master::cr::RETRIG_R; + fn half(&self) -> master::cr::HALF_R; + fn syncrst(&self) -> master::cr::SYNCRST_R; + fn syncstrt(&self) -> master::cr::SYNCSTRT_R; + fn dacsync(&self) -> master::cr::DACSYNC_R; + fn preen(&self) -> master::cr::PREEN_R; + } +} + +wrap_w! { + pub trait MasterCrW { + fn ckpsc(&mut self) -> master::cr::CKPSC_W; + fn cont(&mut self) -> master::cr::CONT_W; + fn retrig(&mut self) -> master::cr::RETRIG_W; + fn half(&mut self) -> master::cr::HALF_W; + fn syncrst(&mut self) -> master::cr::SYNCRST_W; + fn syncstrt(&mut self) -> master::cr::SYNCSTRT_W; + fn dacsync(&mut self) -> master::cr::DACSYNC_W; + fn preen(&mut self) -> master::cr::PREEN_W; + } +} + +wrap_r! { +pub trait TimCrR { + fn pshpll(&self) -> tima::cr::PSHPLL_R; + fn delcmp2(&self) -> tima::cr::DELCMP2_R; + fn delcmp4(&self) -> tima::cr::DELCMP4_R; + fn mstu(&self) -> tima::cr::MSTU_R; + fn trepu(&self) -> tima::cr::TREPU_R; + fn trstu(&self) -> tima::cr::TRSTU_R; + fn updgat(&self) -> tima::cr::UPDGAT_R; + } +} +wrap_w! { + pub trait TimCrW { + fn pshpll(&mut self) -> tima::cr::PSHPLL_W; + fn delcmp2(&mut self) -> tima::cr::DELCMP2_W; + fn delcmp4(&mut self) -> tima::cr::DELCMP4_W; + fn mstu(&mut self) -> tima::cr::MSTU_W; + fn trepu(&mut self) -> tima::cr::TREPU_W; + fn trstu(&mut self) -> tima::cr::TRSTU_W; + fn updgat(&mut self) -> tima::cr::UPDGAT_W; + } +} + +pub trait CptcrW { + fn set_swcpt(&mut self) -> &mut Self; +} +impl CptcrW for W { + #[inline(always)] + fn set_swcpt(&mut self) -> &mut Self { + REG::set_swcpt(self) + } +} + +wrap_r! { + pub trait MasterIsr { + fn cmp(&self, n: u8) -> master::isr::CMP_R; + fn cmp1(&self) -> master::isr::CMP_R; + fn cmp2(&self) -> master::isr::CMP_R; + fn cmp3(&self) -> master::isr::CMP_R; + fn cmp4(&self) -> master::isr::CMP_R; + fn rep(&self) -> master::isr::REP_R; + fn upd(&self) -> master::isr::UPD_R; + } +} +wrap_w! { + pub trait MasterIcr { + fn cmpc(&mut self, n: u8) -> master::icr::CMPC_W; + fn cmp1c(&mut self) -> master::icr::CMPC_W; + fn cmp2c(&mut self) -> master::icr::CMPC_W; + fn cmp3c(&mut self) -> master::icr::CMPC_W; + fn cmp4c(&mut self) -> master::icr::CMPC_W; + fn repc(&mut self) -> master::icr::CMPC_W; + fn updc(&mut self) -> master::icr::CMPC_W; + } +} + +wrap_r! { + pub trait MasterDierR { + fn cmpie(&self, n: u8) -> master::dier::CMPIE_R; + fn cmp1ie(&self) -> master::dier::CMPIE_R; + fn cmp2ie(&self) -> master::dier::CMPIE_R; + fn cmp3ie(&self) -> master::dier::CMPIE_R; + fn cmp4ie(&self) -> master::dier::CMPIE_R; + fn repie(&self) -> master::dier::REPIE_R; + fn updie(&self) -> master::dier::UPDIE_R; + } +} + +wrap_w! { + pub trait MasterDierW { + fn cmpie(&mut self, n: u8) -> master::dier::CMPIE_W; + fn cmp1ie(&mut self) -> master::dier::CMPIE_W; + fn cmp2ie(&mut self) -> master::dier::CMPIE_W; + fn cmp3ie(&mut self) -> master::dier::CMPIE_W; + fn cmp4ie(&mut self) -> master::dier::CMPIE_W; + fn repie(&mut self) -> master::dier::REPIE_W; + fn updie(&mut self) -> master::dier::UPDIE_W; + } +} + +mod reg { + use super::*; + pub trait MasterCrR: RegisterSpec + Readable + Sized { + fn ckpsc(r: &R) -> master::cr::CKPSC_R; + fn cont(r: &R) -> master::cr::CONT_R; + fn retrig(r: &R) -> master::cr::RETRIG_R; + fn half(r: &R) -> master::cr::HALF_R; + fn syncrst(r: &R) -> master::cr::SYNCRST_R; + fn syncstrt(r: &R) -> master::cr::SYNCSTRT_R; + fn dacsync(r: &R) -> master::cr::DACSYNC_R; + fn preen(r: &R) -> master::cr::PREEN_R; + } + pub trait MasterCrW: RegisterSpec + Writable + Resettable + Sized { + fn ckpsc(w: &mut W) -> master::cr::CKPSC_W; + fn cont(w: &mut W) -> master::cr::CONT_W; + fn retrig(w: &mut W) -> master::cr::RETRIG_W; + fn half(w: &mut W) -> master::cr::HALF_W; + fn syncrst(w: &mut W) -> master::cr::SYNCRST_W; + fn syncstrt(w: &mut W) -> master::cr::SYNCSTRT_W; + fn dacsync(w: &mut W) -> master::cr::DACSYNC_W; + fn preen(w: &mut W) -> master::cr::PREEN_W; + } + + pub trait TimCrR: MasterCrR { + fn pshpll(r: &R) -> tima::cr::PSHPLL_R; + fn delcmp2(r: &R) -> tima::cr::DELCMP2_R; + fn delcmp4(r: &R) -> tima::cr::DELCMP4_R; + fn mstu(r: &R) -> tima::cr::MSTU_R; + fn trepu(r: &R) -> tima::cr::TREPU_R; + fn trstu(r: &R) -> tima::cr::TRSTU_R; + fn updgat(r: &R) -> tima::cr::UPDGAT_R; + } + pub trait TimCrW: MasterCrW { + fn pshpll(w: &mut W) -> tima::cr::PSHPLL_W; + fn delcmp2(w: &mut W) -> tima::cr::DELCMP2_W; + fn delcmp4(w: &mut W) -> tima::cr::DELCMP4_W; + fn mstu(w: &mut W) -> tima::cr::MSTU_W; + fn trepu(w: &mut W) -> tima::cr::TREPU_W; + fn trstu(w: &mut W) -> tima::cr::TRSTU_W; + fn updgat(w: &mut W) -> tima::cr::UPDGAT_W; + } + + pub trait CptcrW: RegisterSpec + Writable + Resettable + Sized { + // TODO: replace this + fn set_swcpt(w: &mut W) -> &mut W; + } + + pub trait MasterIsr: RegisterSpec + Readable + Sized { + fn cmp(r: &R, n: u8) -> master::isr::CMP_R; + fn cmp1(r: &R) -> master::isr::CMP_R { + Self::cmp(r, 0) + } + fn cmp2(r: &R) -> master::isr::CMP_R { + Self::cmp(r, 1) + } + fn cmp3(r: &R) -> master::isr::CMP_R { + Self::cmp(r, 2) + } + fn cmp4(r: &R) -> master::isr::CMP_R { + Self::cmp(r, 3) + } + fn rep(r: &R) -> master::isr::REP_R; + fn upd(r: &R) -> master::isr::UPD_R; + } + pub trait MasterIcr: RegisterSpec + Writable + Resettable + Sized { + fn cmpc(w: &mut W, n: u8) -> master::icr::CMPC_W; + fn cmp1c(w: &mut W) -> master::icr::CMPC_W { + Self::cmpc(w, 0) + } + fn cmp2c(w: &mut W) -> master::icr::CMPC_W { + Self::cmpc(w, 1) + } + fn cmp3c(w: &mut W) -> master::icr::CMPC_W { + Self::cmpc(w, 2) + } + fn cmp4c(w: &mut W) -> master::icr::CMPC_W { + Self::cmpc(w, 3) + } + fn repc(w: &mut W) -> master::icr::CMPC_W; + fn updc(w: &mut W) -> master::icr::CMPC_W; + } + pub trait MasterDierR: RegisterSpec + Readable + Sized { + fn cmpie(r: &R, n: u8) -> master::dier::CMPIE_R; + fn cmp1ie(r: &R) -> master::dier::CMPIE_R { + Self::cmpie(r, 0) + } + fn cmp2ie(r: &R) -> master::dier::CMPIE_R { + Self::cmpie(r, 1) + } + fn cmp3ie(r: &R) -> master::dier::CMPIE_R { + Self::cmpie(r, 2) + } + fn cmp4ie(r: &R) -> master::dier::CMPIE_R { + Self::cmpie(r, 3) + } + fn repie(r: &R) -> master::dier::REPIE_R; + fn updie(r: &R) -> master::dier::UPDIE_R; + } + + pub trait MasterDierW: RegisterSpec + Writable + Resettable + Sized { + fn cmpie(w: &mut W, n: u8) -> master::dier::CMPIE_W; + fn cmp1ie(w: &mut W) -> master::dier::CMPIE_W { + Self::cmpie(w, 0) + } + fn cmp2ie(w: &mut W) -> master::dier::CMPIE_W { + Self::cmpie(w, 1) + } + fn cmp3ie(w: &mut W) -> master::dier::CMPIE_W { + Self::cmpie(w, 2) + } + fn cmp4ie(w: &mut W) -> master::dier::CMPIE_W { + Self::cmpie(w, 3) + } + fn repie(w: &mut W) -> master::dier::REPIE_W; + fn updie(w: &mut W) -> master::dier::UPDIE_W; + } +} + +macro_rules! impl_reg { + ($($r:ident -> &$rty:path;)*) => { + $( + #[inline(always)] + fn $r(&self) -> &$rty { + self.$r() + } + )* + }; +} + +macro_rules! impl_read { + ($($f:ident $(: $n:ident)? -> $fty:path;)*) => { + $( + #[inline(always)] + fn $f(r: &R $(, $n: u8)?) -> $fty { + r.$f($($n)?) + } + )* + }; +} +macro_rules! impl_write { + ($($f:ident $(: $n:ident)? -> $fty:path;)*) => { + $( + #[inline(always)] + fn $f(w: &mut W $(, $n: u8)?) -> $fty { + w.$f($($n)?) + } + )* + }; +} + +macro_rules! impl_master_ext { + ($tim:ident) => { + impl MasterExt for $tim::RegisterBlock { + type CRrs = $tim::cr::CRrs; + type ISRrs = $tim::isr::ISRrs; + type ICRrs = $tim::icr::ICRrs; + type DIERrs = $tim::dier::DIERrs; + impl_reg! { + isr -> &Reg; + icr -> &Reg; + dier -> &Reg; + cr -> &Reg; + cntr -> &master::CNTR; + perr -> &master::PERR; + repr -> &master::REPR; + cmp1r -> &master::CMP1R; + cmp2r -> &master::CMP1R; + cmp3r -> &master::CMP1R; + cmp4r -> &master::CMP1R; + } + } + + impl reg::MasterCrR for $tim::cr::CRrs { + impl_read! { + ckpsc -> master::cr::CKPSC_R; + cont -> master::cr::CONT_R; + retrig -> master::cr::RETRIG_R; + half -> master::cr::HALF_R; + syncrst -> master::cr::SYNCRST_R; + syncstrt -> master::cr::SYNCSTRT_R; + dacsync -> master::cr::DACSYNC_R; + preen -> master::cr::PREEN_R; + } + } + impl reg::MasterCrW for $tim::cr::CRrs { + impl_write! { + ckpsc -> master::cr::CKPSC_W; + cont -> master::cr::CONT_W; + retrig -> master::cr::RETRIG_W; + half -> master::cr::HALF_W; + syncrst -> master::cr::SYNCRST_W; + syncstrt -> master::cr::SYNCSTRT_W; + dacsync -> master::cr::DACSYNC_W; + preen -> master::cr::PREEN_W; + } + } + }; +} + +impl_master_ext!(master); +impl_master_ext!(tima); +impl_master_ext!(timb); +impl_master_ext!(timc); +impl_master_ext!(timd); +impl_master_ext!(time); +#[cfg(feature = "hrtim_v2")] +impl_master_ext!(timf); + +macro_rules! impl_tim_ext { + ($tim:ident) => { + impl TimExt for $tim::RegisterBlock { + type SET1Rrs = $tim::set1r::SET1Rrs; + type RST1Rrs = $tim::rst1r::RST1Rrs; + type RSTRrs = $tim::rstr::RSTRrs; + type CPT1CRrs = $tim::cpt1cr::CPT1CRrs; + impl_reg! { + cmp1cr -> &tima::CMP1CR; + cpt1r -> &tima::CPT1R; + cpt2r -> &tima::CPT1R; + dtr -> &tima::DTR; + eefr1 -> &tima::EEFR1; + eefr2 -> &tima::EEFR2; + set1r -> &Reg; + rst1r -> &Reg; + set2r -> &Reg; + rst2r -> &Reg; + rstr -> &Reg; + chpr -> &tima::CHPR; + cpt1cr -> &Reg; + cpt2cr -> &Reg; + outr -> &tima::OUTR; + fltr -> &tima::FLTR; + } + #[cfg(feature = "hrtim_v2")] + impl_reg! { + cr2 -> &tima::CR2; + eefr3 -> &tima::EEFR3; + } + } + + impl reg::TimCrR for $tim::cr::CRrs { + impl_read! { + pshpll -> tima::cr::PSHPLL_R; + delcmp2 -> tima::cr::DELCMP2_R; + delcmp4 -> tima::cr::DELCMP4_R; + mstu -> tima::cr::MSTU_R; + trepu -> tima::cr::TREPU_R; + trstu -> tima::cr::TRSTU_R; + updgat -> tima::cr::UPDGAT_R; + } + } + impl reg::TimCrW for $tim::cr::CRrs { + impl_write! { + pshpll -> tima::cr::PSHPLL_W; + delcmp2 -> tima::cr::DELCMP2_W; + delcmp4 -> tima::cr::DELCMP4_W; + mstu -> tima::cr::MSTU_W; + trepu -> tima::cr::TREPU_W; + trstu -> tima::cr::TRSTU_W; + updgat -> tima::cr::UPDGAT_W; + } + } + + impl reg::CptcrW for $tim::cpt1cr::CPT1CRrs { + #[inline(always)] + fn set_swcpt(w: &mut W) -> &mut W { + w.swcpt().set_bit() + } + } + }; +} + +impl_tim_ext!(tima); +impl_tim_ext!(timb); +impl_tim_ext!(timc); +impl_tim_ext!(timd); +impl_tim_ext!(time); +#[cfg(feature = "hrtim_v2")] +impl_tim_ext!(timf); + +macro_rules! impl_irq_ext { + ($tim:ident) => { + impl reg::MasterIsr for $tim::isr::ISRrs { + impl_read! { + cmp: n -> master::isr::CMP_R; + rep -> master::isr::REP_R; + upd -> master::isr::UPD_R; + } + } + + impl reg::MasterIcr for $tim::icr::ICRrs { + impl_write! { + cmpc: n -> master::icr::CMPC_W; + repc -> master::icr::CMPC_W; + updc -> master::icr::CMPC_W; + } + } + + impl reg::MasterDierR for $tim::dier::DIERrs { + impl_read! { + cmpie: n -> master::dier::CMPIE_R; + repie -> master::dier::REPIE_R; + updie -> master::dier::UPDIE_R; + } + } + impl reg::MasterDierW for $tim::dier::DIERrs { + impl_write! { + cmpie: n -> master::dier::CMPIE_W; + repie -> master::dier::REPIE_W; + updie -> master::dier::UPDIE_W; + } + } + }; +} + +impl_irq_ext!(master); +impl_irq_ext!(tima); diff --git a/src/lib.rs b/src/lib.rs index 31d92ac..b2c987d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,6 +36,7 @@ pub mod compare_register; pub mod control; pub mod deadtime; pub mod event; +pub mod ext; pub mod external_event; pub mod fault; pub mod output; @@ -93,6 +94,7 @@ use self::deadtime::DeadtimeConfig; use self::output::ToHrOut; use self::timer_eev_cfg::EevCfgs; +use timer::{Instance, InstanceX}; /// Internal enum that keeps track of the count settings before PWM is finalized enum CountSettings { //Frequency(Hertz), @@ -115,7 +117,7 @@ pub enum HrCountingDirection { /// Counting up * | * | /// * * /// * | * | - /// * * + /// * * /// * | * | /// * * /// -------------------------------------- @@ -142,7 +144,7 @@ pub enum HrCountingDirection { /// * | * * | /// * * * /// * | * * | - /// 0 -->* * + /// 0 -->* * /// --------------------------------------------------------------------------- /// | *---------------* | *---------------* /// | | | | | | @@ -465,244 +467,100 @@ macro_rules! hrtim_finalize_body { } }}; } +impl HrPwmBuilder +where + PSCL: HrtimPrescaler, + PINS: ToHrOut, +{ + /// Set the prescaler; PWM count runs at base_frequency/(prescaler+1) + pub fn prescaler

(self, _prescaler: P) -> HrPwmBuilder + where + P: HrtimPrescaler, + { + let HrPwmBuilder { + _tim, + _prescaler: _, + pins, + timer_mode, + fault_enable_bits, + fault1_bits, + fault2_bits, + enable_push_pull, + interleaved_mode, + counting_direction, + //base_freq, + count, + preload_source, + repetition_counter, + deadtime, + enable_repetition_interrupt, + eev_cfg, + out1_polarity, + out2_polarity, + } = self; + + let period = match count { + CountSettings::Period(period) => period, + }; -macro_rules! hrtim_common_methods { - ($TIMX:ident, $PS:ident) => { - /// Set the prescaler; PWM count runs at base_frequency/(prescaler+1) - pub fn prescaler

(self, _prescaler: P) -> HrPwmBuilder<$TIMX, P, $PS, PINS> - where - P: HrtimPrescaler, - { - let HrPwmBuilder { - _tim, - _prescaler: _, - pins, - timer_mode, - fault_enable_bits, - fault1_bits, - fault2_bits, - enable_push_pull, - interleaved_mode, - counting_direction, - //base_freq, - count, - preload_source, - repetition_counter, - deadtime, - enable_repetition_interrupt, - eev_cfg, - out1_polarity, - out2_polarity, - } = self; - - let period = match count { - CountSettings::Period(period) => period, - }; - - let count = CountSettings::Period(period); - - HrPwmBuilder { - _tim, - _prescaler: PhantomData, - pins, - timer_mode, - fault_enable_bits, - fault1_bits, - fault2_bits, - enable_push_pull, - interleaved_mode, - counting_direction, - //base_freq, - count, - preload_source, - repetition_counter, - deadtime, - enable_repetition_interrupt, - eev_cfg, - out1_polarity, - out2_polarity, - } - } - - pub fn timer_mode(mut self, timer_mode: HrTimerMode) -> Self { - self.timer_mode = timer_mode; - self - } - - // TODO: Allow setting multiple? - pub fn preload(mut self, preload_source: $PS) -> Self { - self.preload_source = Some(preload_source); - self - } - - /// Set the period; PWM count runs from 0 to period, repeating every (period+1) counts - pub fn period(mut self, period: u16) -> Self { - self.count = CountSettings::Period(period); - self - } - - /// Set repetition counter, useful to reduce interrupts generated - /// from timer by a factor (repetition_counter + 1) - pub fn repetition_counter(mut self, repetition_counter: u8) -> Self { - self.repetition_counter = repetition_counter; - self - } - - pub fn enable_repetition_interrupt(mut self) -> Self { - self.enable_repetition_interrupt = true; - self - } + let count = CountSettings::Period(period); - pub fn eev_cfg(mut self, eev_cfg: EevCfgs<$TIMX>) -> Self { - self.eev_cfg = eev_cfg; - self + HrPwmBuilder { + _tim, + _prescaler: PhantomData, + pins, + timer_mode, + fault_enable_bits, + fault1_bits, + fault2_bits, + enable_push_pull, + interleaved_mode, + counting_direction, + //base_freq, + count, + preload_source, + repetition_counter, + deadtime, + enable_repetition_interrupt, + eev_cfg, + out1_polarity, + out2_polarity, } - }; -} - -// Implement PWM configuration for timer -macro_rules! hrtim_hal { - ($($TIMX:ident: $($out:ident)*,)+) => { - $( - impl HrPwmAdvExt for $TIMX { - type PreloadSource = PreloadSource; - - fn pwm_advanced( - self, - pins: PINS, - ) -> HrPwmBuilder - where - PINS: ToHrOut<$TIMX>, - { - // TODO: That 32x factor... Is that included below, or should we - // do that? Also that will likely risk overflowing u32 since - // 170MHz * 32 = 5.44GHz > u32::MAX.Hz() - //let clk = HertzU64::from(HRTIM_COMMON::get_timer_frequency(&rcc.clocks)) * 32; - - HrPwmBuilder { - _tim: PhantomData, - _prescaler: PhantomData, - pins, - timer_mode: HrTimerMode::Continuous, - fault_enable_bits: 0b000000, - fault1_bits: 0b00, - fault2_bits: 0b00, - counting_direction: HrCountingDirection::Up, - //base_freq: clk, - count: CountSettings::Period(u16::MAX), - preload_source: None, - enable_push_pull: false, - interleaved_mode: InterleavedMode::Disabled, - repetition_counter: 0, - deadtime: None, - enable_repetition_interrupt: false, - eev_cfg: EevCfgs::default(), - out1_polarity: Polarity::ActiveHigh, - out2_polarity: Polarity::ActiveHigh, - } - } - } - - impl - HrPwmBuilder<$TIMX, PSCL, PreloadSource, PINS> - where - PSCL: HrtimPrescaler, - PINS: ToHrOut<$TIMX>, - { - // For HAL writers: - // Make sure to connect gpios after calling this function and then it should be safe to - // conjure an instance of HrParts<$TIMX, PSCL, PINS::Out> - pub fn _init(self, _control: &mut HrPwmControl) -> PINS { - hrtim_finalize_body!(self, PreloadSource, $TIMX, [$($out)*]); - self.pins - } - - hrtim_common_methods!($TIMX, PreloadSource); - - pub fn with_fault_source(mut self, _fault_source: FS) -> Self - where FS: FaultSource - { - self.fault_enable_bits |= FS::ENABLE_BITS; - - self - } - - pub fn fault_action1(mut self, fault_action1: FaultAction) -> Self { - self.fault1_bits = fault_action1 as _; - - self - } - - pub fn fault_action2(mut self, fault_action2: FaultAction) -> Self { - self.fault2_bits = fault_action2 as _; - - self - } - - pub fn out1_polarity(mut self, polarity: Polarity) -> Self { - self.out1_polarity = polarity; - - self - } - - pub fn out2_polarity(mut self, polarity: Polarity) -> Self { - self.out2_polarity = polarity; - - self - } - - /// Enable or disable Push-Pull mode - /// - /// Enabling Push-Pull mode will make output 1 and 2 - /// alternate every period with one being - /// inactive and the other getting to output its wave form - /// as normal - /// - /// ---- . ---- - ///out1 | | . | | - /// | | . | | - /// -------- ---------------------------- -------------------- - /// . ------ . ------ - ///out2 . | | . | | - /// . | | . | | - /// ------------------------ ---------------------------- -- - /// - /// NOTE: setting this will overide any 'Swap Mode' set - pub fn push_pull_mode(mut self, enable: bool) -> Self { - // TODO: add check for incompatible modes - self.enable_push_pull = enable; - - self - } - - /// Set counting direction - /// - /// See [`HrCountingDirection`] - pub fn counting_direction(mut self, counting_direction: HrCountingDirection) -> Self { - self.counting_direction = counting_direction; + } - self - } + pub fn timer_mode(mut self, timer_mode: HrTimerMode) -> Self { + self.timer_mode = timer_mode; + self + } - /// Set interleaved or half modes - /// - /// NOTE: Check [`InterleavedMode`] for more info about special cases - pub fn interleaved_mode(mut self, mode: InterleavedMode) -> Self { - self.interleaved_mode = mode; + // TODO: Allow setting multiple? + pub fn preload(mut self, preload_source: TIM::PreloadSource) -> Self { + self.preload_source = Some(preload_source); + self + } - self - } + /// Set the period; PWM count runs from 0 to period, repeating every (period+1) counts + pub fn period(mut self, period: u16) -> Self { + self.count = CountSettings::Period(period); + self + } - pub fn deadtime(mut self, deadtime: DeadtimeConfig) -> Self { - self.deadtime = Some(deadtime); + /// Set repetition counter, useful to reduce interrupts generated + /// from timer by a factor (repetition_counter + 1) + pub fn repetition_counter(mut self, repetition_counter: u8) -> Self { + self.repetition_counter = repetition_counter; + self + } - self - } + pub fn enable_repetition_interrupt(mut self) -> Self { + self.enable_repetition_interrupt = true; + self + } - //pub fn swap_mode(mut self, enable: bool) -> Self - } - )+ - }; + pub fn eev_cfg(mut self, eev_cfg: EevCfgs) -> Self { + self.eev_cfg = eev_cfg; + self + } } impl HrPwmAdvExt for HRTIM_MASTER { @@ -744,18 +602,154 @@ impl HrPwmAdvExt for HRTIM_MASTER { } } -impl HrPwmBuilder +impl HrPwmAdvExt for TIM { + type PreloadSource = PreloadSource; + + fn pwm_advanced( + self, + pins: PINS, + ) -> HrPwmBuilder + where + PINS: ToHrOut, + { + // TODO: That 32x factor... Is that included below, or should we + // do that? Also that will likely risk overflowing u32 since + // 170MHz * 32 = 5.44GHz > u32::MAX.Hz() + //let clk = HertzU64::from(HRTIM_COMMON::get_timer_frequency(&rcc.clocks)) * 32; + + HrPwmBuilder { + _tim: PhantomData, + _prescaler: PhantomData, + pins, + timer_mode: HrTimerMode::Continuous, + fault_enable_bits: 0b000000, + fault1_bits: 0b00, + fault2_bits: 0b00, + counting_direction: HrCountingDirection::Up, + //base_freq: clk, + count: CountSettings::Period(u16::MAX), + preload_source: None, + enable_push_pull: false, + interleaved_mode: InterleavedMode::Disabled, + repetition_counter: 0, + deadtime: None, + enable_repetition_interrupt: false, + eev_cfg: EevCfgs::default(), + out1_polarity: Polarity::ActiveHigh, + out2_polarity: Polarity::ActiveHigh, + } + } +} + +impl HrPwmBuilder where PSCL: HrtimPrescaler, - PINS: ToHrOut, + PINS: ToHrOut, { - pub fn finalize(self, _control: &mut HrPwmControl) -> HrParts { - hrtim_finalize_body!(self, MasterPreloadSource, HRTIM_MASTER, []); + pub fn with_fault_source(mut self, _fault_source: FS) -> Self + where + FS: FaultSource, + { + self.fault_enable_bits |= FS::ENABLE_BITS; - unsafe { MaybeUninit::uninit().assume_init() } + self + } + + pub fn fault_action1(mut self, fault_action1: FaultAction) -> Self { + self.fault1_bits = fault_action1 as _; + + self + } + + pub fn fault_action2(mut self, fault_action2: FaultAction) -> Self { + self.fault2_bits = fault_action2 as _; + + self + } + + pub fn out1_polarity(mut self, polarity: Polarity) -> Self { + self.out1_polarity = polarity; + + self + } + + pub fn out2_polarity(mut self, polarity: Polarity) -> Self { + self.out2_polarity = polarity; + + self + } + + /// Enable or disable Push-Pull mode + /// + /// Enabling Push-Pull mode will make output 1 and 2 + /// alternate every period with one being + /// inactive and the other getting to output its wave form + /// as normal + /// + /// ---- . ---- + ///out1 | | . | | + /// | | . | | + /// -------- ---------------------------- -------------------- + /// . ------ . ------ + ///out2 . | | . | | + /// . | | . | | + /// ------------------------ ---------------------------- -- + /// + /// NOTE: setting this will overide any 'Swap Mode' set + pub fn push_pull_mode(mut self, enable: bool) -> Self { + // TODO: add check for incompatible modes + self.enable_push_pull = enable; + + self } - hrtim_common_methods!(HRTIM_MASTER, MasterPreloadSource); + /// Set counting direction + /// + /// See [`HrCountingDirection`] + pub fn counting_direction(mut self, counting_direction: HrCountingDirection) -> Self { + self.counting_direction = counting_direction; + + self + } + + /// Set interleaved or half modes + /// + /// NOTE: Check [`InterleavedMode`] for more info about special cases + pub fn interleaved_mode(mut self, mode: InterleavedMode) -> Self { + self.interleaved_mode = mode; + + self + } + + pub fn deadtime(mut self, deadtime: DeadtimeConfig) -> Self { + self.deadtime = Some(deadtime); + + self + } + + //pub fn swap_mode(mut self, enable: bool) -> Self +} + +// Implement PWM configuration for timer +macro_rules! hrtim_hal { + ($($TIMX:ident: $($out:ident)*,)+) => { + $( + impl + HrPwmBuilder<$TIMX, PSCL, PreloadSource, PINS> + where + PSCL: HrtimPrescaler, + PINS: ToHrOut<$TIMX>, + { + // For HAL writers: + // Make sure to connect gpios after calling this function and then it should be safe to + // conjure an instance of HrParts<$TIMX, PSCL, PINS::Out> + pub fn _init(self, _control: &mut HrPwmControl) -> PINS { + hrtim_finalize_body!(self, PreloadSource, $TIMX, [$($out)*]); + self.pins + } + } + )+ + }; } hrtim_hal! { @@ -771,6 +765,18 @@ hrtim_hal! { HRTIM_TIMF: out, } +impl HrPwmBuilder +where + PSCL: HrtimPrescaler, + PINS: ToHrOut, +{ + pub fn finalize(self, _control: &mut HrPwmControl) -> HrParts { + hrtim_finalize_body!(self, MasterPreloadSource, HRTIM_MASTER, []); + + unsafe { MaybeUninit::uninit().assume_init() } + } +} + /// # Safety /// Only implement for valid prescalers with correct values pub unsafe trait HrtimPrescaler: Default { diff --git a/src/output.rs b/src/output.rs index f6f999e..a32fb5d 100644 --- a/src/output.rs +++ b/src/output.rs @@ -1,82 +1,81 @@ -#[cfg(feature = "hrtim_v2")] -use crate::pac::HRTIM_TIMF; -use crate::pac::{HRTIM_COMMON, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME}; +use crate::{ + ext::{Chan, TimExt}, + pac::HRTIM_COMMON, + timer::{Ch1, Ch2, ChExt, InstanceX}, +}; use core::marker::PhantomData; use super::event::EventSource; -macro_rules! hrtim_out { - ($($TIMX:ident: $out_type:ident: $tXYoen:ident, $tXYodis:ident, $tXYods:ident, $setXYr:ident, $rstXYr:ident,)+) => {$( - impl HrOutput<$TIMX, PSCL> for $out_type<$TIMX, PSCL> { - fn enable(&mut self) { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.oenr().write(|w| { w.$tXYoen().set_bit() }); - } +impl HrOutput for HrOut { + fn enable(&mut self) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.oenr().write(|w| match CH::CH { + Chan::Ch1 => w.t1oen(TIM::T_X as _).set_bit(), + Chan::Ch2 => w.t2oen(TIM::T_X as _).set_bit(), + }); + } - fn disable(&mut self) { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.odisr().write(|w| { w.$tXYodis().set_bit() }); - } + fn disable(&mut self) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.odisr().write(|w| match CH::CH { + Chan::Ch1 => w.t1odis(TIM::T_X as _).set_bit(), + Chan::Ch2 => w.t2odis(TIM::T_X as _).set_bit(), + }); + } - fn enable_set_event>(&mut self, _set_event: &ES) { - let tim = unsafe { &*$TIMX::ptr() }; - unsafe { tim.$setXYr().modify(|r, w| w.bits(r.bits() | ES::BITS)); } - } - fn disable_set_event>(&mut self, _set_event: &ES) { - let tim = unsafe { &*$TIMX::ptr() }; - unsafe { tim.$setXYr().modify(|r, w| w.bits(r.bits() & !ES::BITS)); } - } + fn enable_set_event>(&mut self, _set_event: &ES) { + let tim = unsafe { &*TIM::ptr() }; + unsafe { + tim.set_r(CH::CH).modify(|r, w| w.bits(r.bits() | ES::BITS)); + } + } + fn disable_set_event>(&mut self, _set_event: &ES) { + let tim = unsafe { &*TIM::ptr() }; + unsafe { + tim.set_r(CH::CH) + .modify(|r, w| w.bits(r.bits() & !ES::BITS)); + } + } - fn enable_rst_event>(&mut self, _reset_event: &ES) { - let tim = unsafe { &*$TIMX::ptr() }; - unsafe { tim.$rstXYr().modify(|r, w| w.bits(r.bits() | ES::BITS)); } - } - fn disable_rst_event>(&mut self, _reset_event: &ES) { - let tim = unsafe { &*$TIMX::ptr() }; - unsafe { tim.$rstXYr().modify(|r, w| w.bits(r.bits() & !ES::BITS)); } - } + fn enable_rst_event>(&mut self, _reset_event: &ES) { + let tim = unsafe { &*TIM::ptr() }; + unsafe { + tim.rst_r(CH::CH).modify(|r, w| w.bits(r.bits() | ES::BITS)); + } + } + fn disable_rst_event>(&mut self, _reset_event: &ES) { + let tim = unsafe { &*TIM::ptr() }; + unsafe { + tim.rst_r(CH::CH) + .modify(|r, w| w.bits(r.bits() & !ES::BITS)); + } + } - fn get_state(&self) -> State { - let ods; - let oen; + fn get_state(&self) -> State { + let ods; + let oen; - unsafe { - let common = &*HRTIM_COMMON::ptr(); - ods = common.odsr().read().$tXYods().bit_is_set(); - oen = common.oenr().read().$tXYoen().bit_is_set(); + unsafe { + let common = &*HRTIM_COMMON::ptr(); + match CH::CH { + Chan::Ch1 => { + ods = common.odsr().read().t1ods(TIM::T_X as _).bit_is_set(); + oen = common.oenr().read().t1oen(TIM::T_X as _).bit_is_set(); } - - match (oen, ods) { - (true, _) => State::Running, - (false, false) => State::Idle, - (false, true) => State::Fault + Chan::Ch2 => { + ods = common.odsr().read().t2ods(TIM::T_X as _).bit_is_set(); + oen = common.oenr().read().t2oen(TIM::T_X as _).bit_is_set(); } } } - )+}; -} - -hrtim_out! { - HRTIM_TIMA: HrOut1: ta1oen, ta1odis, ta1ods, set1r, rst1r, - HRTIM_TIMA: HrOut2: ta2oen, ta2odis, ta2ods, set2r, rst2r, - - HRTIM_TIMB: HrOut1: tb1oen, tb1odis, tb1ods, set1r, rst1r, - HRTIM_TIMB: HrOut2: tb2oen, tb2odis, tb2ods, set2r, rst2r, - HRTIM_TIMC: HrOut1: tc1oen, tc1odis, tc1ods, set1r, rst1r, - HRTIM_TIMC: HrOut2: tc2oen, tc2odis, tc2ods, set2r, rst2r, - - HRTIM_TIMD: HrOut1: td1oen, td1odis, td1ods, set1r, rst1r, - HRTIM_TIMD: HrOut2: td2oen, td2odis, td2ods, set2r, rst2r, - - HRTIM_TIME: HrOut1: te1oen, te1odis, te1ods, set1r, rst1r, - HRTIM_TIME: HrOut2: te2oen, te2odis, te2ods, set2r, rst2r, -} - -#[cfg(feature = "hrtim_v2")] -hrtim_out! { - HRTIM_TIMF: HrOut1: tf1oen, tf1odis, tf1ods, set1r, rst1r, - HRTIM_TIMF: HrOut2: tf2oen, tf2odis, tf2ods, set2r, rst2r, + match (oen, ods) { + (true, _) => State::Running, + (false, false) => State::Idle, + (false, true) => State::Fault, + } + } } pub trait HrOutput { @@ -146,8 +145,9 @@ where type Out = (PA::Out, PB::Out); } -pub struct HrOut1(PhantomData<(TIM, PSCL)>); -pub struct HrOut2(PhantomData<(TIM, PSCL)>); +pub struct HrOut(PhantomData<(TIM, PSCL, CH)>); +pub type HrOut1 = HrOut; +pub type HrOut2 = HrOut; unsafe impl ToHrOut for () { type Out = (); diff --git a/src/timer.rs b/src/timer.rs index 182b97c..9ed1f99 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -1,11 +1,13 @@ #[cfg(feature = "hrtim_v2")] use crate::pac::HRTIM_TIMF; use crate::pac::{HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME}; -use core::marker::PhantomData; +use core::{marker::PhantomData, ops::Deref}; +pub use super::ext::{Chan, Cmp}; use super::{ capture::{self, HrCapt, HrCapture}, control::HrPwmCtrl, + ext::{MasterDierW, MasterExt, MasterIcr, TimExt}, HrtimPrescaler, }; @@ -16,6 +18,89 @@ pub struct HrTim { capture_ch2: CPT2, } +pub struct Ch1; +pub struct Ch2; + +pub trait ChExt { + const CH: Chan; +} + +impl ChExt for Ch1 { + const CH: Chan = Chan::Ch1; +} + +impl ChExt for Ch2 { + const CH: Chan = Chan::Ch2; +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(u8)] +pub enum Timer { + Master, + Tim(TimX), +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(u8)] +pub enum TimX { + A = 0, + B = 1, + C = 2, + D = 3, + E = 4, + #[cfg(feature = "hrtim_v2")] + F = 5, +} + +pub trait Instance: Deref { + type RB: MasterExt; + const TIMX: Timer; + fn ptr() -> *const Self::RB; +} + +pub trait InstanceX: Instance { + const T_X: TimX; +} + +impl Instance for HRTIM_MASTER { + type RB = crate::pac::hrtim_master::RegisterBlock; + const TIMX: Timer = Timer::Master; + fn ptr() -> *const Self::RB { + Self::ptr() + } +} + +macro_rules! hrtim_timer { + ($( + $TIMX:ident: + $timx:ident, + $T:ident, + )+) => {$( + impl Instance for $TIMX { + type RB = crate::pac::$timx::RegisterBlock; + const TIMX: Timer = Timer::Tim(Self::T_X); + fn ptr() -> *const Self::RB { + Self::ptr() + } + } + impl InstanceX for $TIMX { + const T_X: TimX = TimX::$T; + } + + )+} +} + +hrtim_timer! { + HRTIM_TIMA: hrtim_tima, A, + HRTIM_TIMB: hrtim_timb, B, + HRTIM_TIMC: hrtim_timc, C, + HRTIM_TIMD: hrtim_timd, D, + HRTIM_TIME: hrtim_time, E, +} + +#[cfg(feature = "hrtim_v2")] +hrtim_timer! {HRTIM_TIMF: hrtim_timf, F,} + /// This is the DMA channel of a HRTIM timer /// /// Every HRTIM timer including the master timer has a DMA channel @@ -102,198 +187,233 @@ pub trait HrSlaveTimerCpt: HrSlaveTimer { type CaptureCh1: HrCapture; type CaptureCh2: HrCapture; - fn capture_ch1(&mut self) -> &mut ::CaptureCh1; - fn capture_ch2(&mut self) -> &mut ::CaptureCh2; - fn split_capture( - self, - ) -> TimerSplitCapture; + fn capture_ch1(&mut self) -> &mut Self::CaptureCh1; + fn capture_ch2(&mut self) -> &mut Self::CaptureCh2; + fn split_capture(self) -> TimerSplitCapture; } -macro_rules! hrtim_timer { - ($( - $TIMX:ident: - $tXcen:ident, - $tXudis:ident, - $(($rstXr:ident))*, - )+) => {$( - impl HrTimer for HrTim<$TIMX, PSCL, CPT1, CPT2> { - type Prescaler = PSCL; - type Timer = $TIMX; +impl HrTimer for HrTim { + type Prescaler = PSCL; + type Timer = TIM; - fn get_period(&self) -> u16 { - let tim = unsafe { &*$TIMX::ptr() }; + fn get_period(&self) -> u16 { + let tim = unsafe { &*TIM::ptr() }; - tim.perr().read().per().bits() - } - fn set_period(&mut self, period: u16) { - let tim = unsafe { &*$TIMX::ptr() }; + tim.perr().read().per().bits() + } + fn set_period(&mut self, period: u16) { + let tim = unsafe { &*TIM::ptr() }; - tim.perr().write(|w| unsafe { w.per().bits(period as u16) }); - } + tim.perr().write(|w| unsafe { w.per().bits(period as u16) }); + } - /// Start timer - fn start(&mut self, _hr_control: &mut HrPwmCtrl) { - // Start timer + /// Start timer + fn start(&mut self, _hr_control: &mut HrPwmCtrl) { + // Start timer + + // SAFETY: Since we hold _hr_control there is no risk for a race condition + let master = unsafe { &*HRTIM_MASTER::ptr() }; + master.cr().modify(|_, w| match TIM::TIMX { + Timer::Master => w.mcen().set_bit(), + Timer::Tim(v) => w.tcen(v as _).set_bit(), + }); + } - // SAFETY: Since we hold _hr_control there is no risk for a race condition - let master = unsafe { &*HRTIM_MASTER::ptr() }; - master.cr().modify(|_r, w| { w.$tXcen().set_bit() }); - } + /// Stop timer + fn stop(&mut self, _hr_control: &mut HrPwmCtrl) { + // Stop counter + // SAFETY: Since we hold _hr_control there is no risk for a race condition + let master = unsafe { &*HRTIM_MASTER::ptr() }; + master.cr().modify(|_, w| match TIM::TIMX { + Timer::Master => w.mcen().clear_bit(), + Timer::Tim(v) => w.tcen(v as _).clear_bit(), + }); + } - /// Stop timer - fn stop(&mut self, _hr_control: &mut HrPwmCtrl) { - // Stop counter - // SAFETY: Since we hold _hr_control there is no risk for a race condition - let master = unsafe { &*HRTIM_MASTER::ptr() }; - master.cr().modify(|_r, w| { w.$tXcen().set_bit() }); - } + /// Stop timer and reset counter + fn stop_and_reset(&mut self, _hr_control: &mut HrPwmCtrl) { + self.stop(_hr_control); - /// Stop timer and reset counter - fn stop_and_reset(&mut self, _hr_control: &mut HrPwmCtrl) { - self.stop(_hr_control); + // Reset counter + let tim = unsafe { &*TIM::ptr() }; + unsafe { + tim.cntr().write(|w| w.cnt().bits(0)); + } + } - // Reset counter - let tim = unsafe { &*$TIMX::ptr() }; - unsafe { tim.cntr().write(|w| w.cnt().bits(0)); } - } + /// Make a handle to this timers reset event to use as adc trigger + fn as_reset_adc_trigger(&self) -> super::adc_trigger::TimerReset { + super::adc_trigger::TimerReset(PhantomData) + } - /// Make a handle to this timers reset event to use as adc trigger - fn as_reset_adc_trigger(&self) -> super::adc_trigger::TimerReset { - super::adc_trigger::TimerReset(PhantomData) - } + /// Make a handle to this timers period event to use as adc trigger + fn as_period_adc_trigger(&self) -> super::adc_trigger::TimerPeriod { + super::adc_trigger::TimerPeriod(PhantomData) + } - /// Make a handle to this timers period event to use as adc trigger - fn as_period_adc_trigger(&self) -> super::adc_trigger::TimerPeriod { - super::adc_trigger::TimerPeriod(PhantomData) - } + fn clear_repetition_interrupt(&mut self) { + let tim = unsafe { &*TIM::ptr() }; - fn clear_repetition_interrupt(&mut self) { - let tim = unsafe { &*$TIMX::ptr() }; + tim.icr().write(|w| w.repc().clear()); + } - tim.icr().write(|w| w.repc().clear()); - } + /// Disable register updates + /// + /// Calling this function temporarily disables the transfer from preload to active registers, + /// whatever the selected update event. This allows to modify several registers. + /// The regular update event takes place once [`Self::enable_register_updates`] is called. + fn disable_register_updates(&mut self, _hr_control: &mut HrPwmCtrl) { + use super::HRTIM_COMMON; + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.cr1().modify(|_, w| match TIM::TIMX { + Timer::Master => w.mudis().set_bit(), + Timer::Tim(v) => w.tudis(v as _).set_bit(), + }); + } - /// Disable register updates - /// - /// Calling this function temporarily disables the transfer from preload to active registers, - /// whatever the selected update event. This allows to modify several registers. - /// The regular update event takes place once [`Self::enable_register_updates`] is called. - fn disable_register_updates(&mut self, _hr_control: &mut HrPwmCtrl) { - use super::HRTIM_COMMON; - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.cr1().modify(|_r, w| w.$tXudis().set_bit()); - } + /// Enable register updates + /// + /// See [`Self::disable_register_updates`]. + /// + /// NOTE: Register updates are enabled by default, no need to call this + /// unless [`Self::disable_register_updates`] has been called. + fn enable_register_updates<'a>(&mut self, _hr_control: &mut HrPwmCtrl) { + use super::HRTIM_COMMON; + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.cr1().modify(|_, w| match TIM::TIMX { + Timer::Master => w.mudis().clear_bit(), + Timer::Tim(v) => w.tudis(v as _).clear_bit(), + }); + } +} - /// Enable register updates - /// - /// See [`Self::disable_register_updates`]. - /// - /// NOTE: Register updates are enabled by default, no need to call this - /// unless [`Self::disable_register_updates`] has been called. - fn enable_register_updates<'a>(&mut self, _hr_control: &mut HrPwmCtrl) { - use super::HRTIM_COMMON; - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.cr1().modify(|_r, w| w.$tXudis().clear_bit()); - } +impl HrTim { + pub fn set_repetition_counter(&mut self, repetition_counter: u8) { + let tim = unsafe { &*TIM::ptr() }; + + unsafe { + tim.repr().write(|w| w.rep().bits(repetition_counter)); } + } - impl HrTim<$TIMX, PSCL, CPT1, CPT2> { - pub fn set_repetition_counter(&mut self, repetition_counter: u8) { - let tim = unsafe { &*$TIMX::ptr() }; + pub fn enable_repetition_interrupt(&mut self, enable: bool) { + let tim = unsafe { &*TIM::ptr() }; - unsafe { tim.repr().write(|w| w.rep().bits(repetition_counter)); } - } + tim.dier().modify(|_r, w| w.repie().bit(enable)); + } +} - pub fn enable_repetition_interrupt(&mut self, enable: bool) { - let tim = unsafe { &*$TIMX::ptr() }; +impl HrSlaveTimer + for HrTim +{ + type CptCh1 = HrCapt; + type CptCh2 = HrCapt; - tim.dier().modify(|_r, w| w.repie().bit(enable)); - } + /// Reset this timer every time the specified event occurs + /// + /// Behaviour depends on `timer_mode`: + /// + /// * `HrTimerMode::SingleShotNonRetriggable`: Enabling the timer enables it but does not start it. + /// A first reset event starts the counting and any subsequent reset is ignored until the counter + /// reaches the PER value. The PER event is then generated and the counter is stopped. A reset event + /// restarts the counting from 0x0000. + /// * `HrTimerMode:SingleShotRetriggable`: Enabling the timer enables it but does not start it. + /// A reset event starts the counting if the counter is stopped, otherwise it clears the counter. + /// When the counter reaches the PER value, the PER event is generated and the counter is stopped. + /// A reset event restarts the counting from 0x0000. + /// * `HrTimerMode::Continuous`: Enabling the timer enables and starts it simultaneously. + /// When the counter reaches the PER value, it rolls-over to 0x0000 and resumes counting. + /// The counter can be reset at any time + fn enable_reset_event>( + &mut self, + _event: &E, + ) { + let tim = unsafe { &*TIM::ptr() }; + + unsafe { + tim.rstr().modify(|r, w| w.bits(r.bits() | E::BITS)); } + } - $( - impl HrSlaveTimer for HrTim<$TIMX, PSCL, CPT1, CPT2> { - type CptCh1 = HrCapt; - type CptCh2 = HrCapt; - - /// Reset this timer every time the specified event occurs - /// - /// Behaviour depends on `timer_mode`: - /// - /// * `HrTimerMode::SingleShotNonRetriggable`: Enabling the timer enables it but does not start it. - /// A first reset event starts the counting and any subsequent reset is ignored until the counter - /// reaches the PER value. The PER event is then generated and the counter is stopped. A reset event - /// restarts the counting from 0x0000. - /// * `HrTimerMode:SingleShotRetriggable`: Enabling the timer enables it but does not start it. - /// A reset event starts the counting if the counter is stopped, otherwise it clears the counter. - /// When the counter reaches the PER value, the PER event is generated and the counter is stopped. - /// A reset event restarts the counting from 0x0000. - /// * `HrTimerMode::Continuous`: Enabling the timer enables and starts it simultaneously. - /// When the counter reaches the PER value, it rolls-over to 0x0000 and resumes counting. - /// The counter can be reset at any time - fn enable_reset_event>(&mut self, _event: &E) { - let tim = unsafe { &*$TIMX::ptr() }; - - unsafe { tim.$rstXr().modify(|r, w| w.bits(r.bits() | E::BITS)); } - } - - /// Stop listening to the specified event - fn disable_reset_event>(&mut self, _event: &E) { - let tim = unsafe { &*$TIMX::ptr() }; - - unsafe { tim.$rstXr().modify(|r, w| w.bits(r.bits() & !E::BITS)); } - } - } + /// Stop listening to the specified event + fn disable_reset_event>( + &mut self, + _event: &E, + ) { + let tim = unsafe { &*TIM::ptr() }; - impl HrSlaveTimerCpt for HrTim<$TIMX, PSCL, HrCapt<$TIMX, PSCL, capture::Ch1, capture::NoDma>, HrCapt<$TIMX, PSCL, capture::Ch2, capture::NoDma>> { - type CaptureCh1 = ::CptCh1; - type CaptureCh2 = ::CptCh2; - - /// Access the timers first capture channel - fn capture_ch1(&mut self) -> &mut Self::CaptureCh1 { - &mut self.capture_ch1 - } - - /// Access the timers second capture channel - fn capture_ch2(&mut self) -> &mut Self::CaptureCh2 { - &mut self.capture_ch2 - } - - fn split_capture(self) -> TimerSplitCapture<$TIMX, PSCL, capture::Ch1, capture::Ch2> { - let HrTim{ - _timer, - _prescaler, - capture_ch1, - capture_ch2, - } = self; - - TimerSplitCapture { - timer: HrTim{ - _timer, - _prescaler, - capture_ch1: (), - capture_ch2: (), - }, - ch1: capture_ch1, - ch2: capture_ch2, - } - } - } + unsafe { + tim.rstr().modify(|r, w| w.bits(r.bits() & !E::BITS)); + } + } +} - /// Timer Period event - impl super::event::EventSource for HrTim<$TIMX, PSCL, CPT1, CPT2> { - // $rstXr - const BITS: u32 = 1 << 2; - } +impl HrSlaveTimerCpt + for HrTim< + TIM, + PSCL, + HrCapt, + HrCapt, + > +where + HrCapt: HrCapture, + HrCapt: HrCapture, +{ + type CaptureCh1 = ::CptCh1; + type CaptureCh2 = ::CptCh2; - /// Timer Update event - impl super::capture::CaptureEvent<$TIMX, PSCL> for HrTim<$TIMX, PSCL, CPT1, CPT2> { - const BITS: u32 = 1 << 1; - } - )* - )+} + /// Access the timers first capture channel + fn capture_ch1(&mut self) -> &mut Self::CaptureCh1 { + &mut self.capture_ch1 + } + + /// Access the timers second capture channel + fn capture_ch2(&mut self) -> &mut Self::CaptureCh2 { + &mut self.capture_ch2 + } + + fn split_capture(self) -> TimerSplitCapture { + let HrTim { + _timer, + _prescaler, + capture_ch1, + capture_ch2, + } = self; + + TimerSplitCapture { + timer: HrTim { + _timer, + _prescaler, + capture_ch1: (), + capture_ch2: (), + }, + ch1: capture_ch1, + ch2: capture_ch2, + } + } +} + +/// Timer Period event +impl super::event::EventSource + for HrTim +{ + // $rstXr + const BITS: u32 = 1 << 2; } +/// Timer Update event +impl super::capture::CaptureEvent + for HrTim +{ + const BITS: u32 = 1 << 1; +} + +#[cfg(feature = "stm32g4")] +use super::adc_trigger::{ + AdcTrigger13 as Adc13, AdcTrigger24 as Adc24, AdcTrigger579 as Adc579, + AdcTrigger6810 as Adc6810, +}; + #[cfg(feature = "stm32g4")] macro_rules! hrtim_timer_adc_trigger { ($($TIMX:ident: @@ -314,24 +434,6 @@ macro_rules! hrtim_timer_adc_trigger { } } -#[cfg(feature = "stm32g4")] -use super::adc_trigger::{ - AdcTrigger13 as Adc13, AdcTrigger24 as Adc24, AdcTrigger579 as Adc579, - AdcTrigger6810 as Adc6810, -}; - -hrtim_timer! { - HRTIM_MASTER: mcen, mudis,, - - HRTIM_TIMA: tacen, taudis, (rstr), - HRTIM_TIMB: tbcen, tbudis, (rstr), - HRTIM_TIMC: tccen, tcudis, (rstr), - HRTIM_TIMD: tdcen, tdudis, (rstr), - HRTIM_TIME: tecen, teudis, (rstr), -} -#[cfg(feature = "hrtim_v2")] -hrtim_timer! {HRTIM_TIMF: tfcen, tfudis, (rstr),} - #[cfg(feature = "stm32g4")] hrtim_timer_adc_trigger! { HRTIM_MASTER: [(Adc13: [(PER: 1 << 4),]), (Adc24: [(PER: 1 << 4),]), (Adc579: [(PER: 4),]), (Adc6810: [(PER: 4),])],