From c3d47ecab7381caadc259cd72cc3256ec8d36965 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 16 Dec 2023 22:37:40 +0100 Subject: [PATCH 01/88] Use latest pac --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b78d4e2b..5e683b15 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ version = "0.0.2" [dependencies] nb = "0.1.1" -stm32g4 = "0.15.1" +stm32g4 = { git = "https://github.com/stm32-rs/stm32-rs-nightlies" } #"0.15.1" paste = "1.0" bitflags = "1.2" vcell = "0.1" From 71202405f57f7cb80884a453b7d24e041b697ff0 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 16 Dec 2023 22:54:56 +0100 Subject: [PATCH 02/88] Update DMA for new pac --- src/dma/stream.rs | 96 +++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/src/dma/stream.rs b/src/dma/stream.rs index 18dc4085..a6a41661 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -182,7 +182,7 @@ impl StreamsTuple { // the stream macro_rules! dma_stream { ($(($name:ident, $number:expr, - regs => $ccr:ident, $cparX:ident, $cmarX:ident, $cndtrX:ident, + regs => $chX:ident, fields => $tcif:ident, $htif:ident, $teif:ident, $gif:ident, $tcisr:ident, $htisr:ident, $teisr:ident, $gisr:ident, dmamux => $dma1_cXcr:ident, $dma2_cXcr:ident, ) ),+$(,)*) => { @@ -266,28 +266,28 @@ macro_rules! dma_stream { #[inline(always)] unsafe fn enable(&mut self) { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma = &*I::ptr(); - dma.$ccr.modify(|_, w| w.en().set_bit()); + let dma_ch = &unsafe { &*I::ptr() }.$chX(); + dma_ch.cr.modify(|_, w| w.en().set_bit()); } #[inline(always)] fn is_enabled() -> bool { //NOTE(unsafe) Atomic read with no side effects - let dma = unsafe { &*I::ptr() }; - dma.$ccr.read().en().bit_is_set() + let dma_ch = &unsafe { &*I::ptr() }.$chX(); + dma_ch.cr.read().en().bit_is_set() } fn disable(&mut self) { if Self::is_enabled() { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; + let dma_ch = &unsafe { &*I::ptr() }.$chX(); // Aborting an on-going transfer might cause interrupts to fire, disable // them let interrupts = Self::get_interrupts_enable(); self.disable_interrupts(); - dma.$ccr.modify(|_, w| w.en().clear_bit()); + dma_ch.cr.modify(|_, w| w.en().clear_bit()); while Self::is_enabled() {} self.clear_interrupts(); @@ -313,14 +313,14 @@ macro_rules! dma_stream { #[inline(always)] fn set_priority(&mut self, priority: config::Priority) { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; - dma.$ccr.modify(|_, w| unsafe { w.pl().bits(priority.bits()) }); + let dma_ch = &unsafe { &*I::ptr() }.$chX(); + dma_ch.cr.modify(|_, w| unsafe { w.pl().bits(priority.bits()) }); } #[inline(always)] fn disable_interrupts(&mut self) { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dmacr = &unsafe { &*I::ptr() }.$ccr; + let dmacr = &unsafe { &*I::ptr() }.$chX().cr; dmacr.modify(|_, w| w .tcie().clear_bit() .teie().clear_bit() @@ -332,8 +332,8 @@ macro_rules! dma_stream { #[inline(always)] fn enable_interrupts(&mut self, interrupt: Self::Interrupts) { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; - dma.$ccr.modify(|_, w| w + let dma_ch = &unsafe { &*I::ptr() }.$chX(); + dma_ch.cr.modify(|_, w| w .tcie().bit(interrupt.transfer_complete) .teie().bit(interrupt.transfer_error) .htie().bit(interrupt.half_transfer) @@ -343,8 +343,8 @@ macro_rules! dma_stream { #[inline(always)] fn get_interrupts_enable() -> Self::Interrupts { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; - let cr = dma.$ccr.read(); + let dma_ch = unsafe { &*I::ptr() }.$chX(); + let cr = dma_ch.cr.read(); DmaInterrupts { transfer_complete: cr.tcie().bit_is_set(), @@ -357,7 +357,7 @@ macro_rules! dma_stream { #[inline(always)] fn set_transfer_complete_interrupt_enable(&mut self, transfer_complete_interrupt: bool) { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dmacr = &unsafe { &*I::ptr() }.$ccr; + let dmacr = &unsafe { &*I::ptr() }.$chX().cr; dmacr.modify(|_, w| w.tcie().bit(transfer_complete_interrupt)); let _ = dmacr.read(); let _ = dmacr.read(); // Delay 2 peripheral clocks @@ -366,7 +366,7 @@ macro_rules! dma_stream { #[inline(always)] fn set_transfer_error_interrupt_enable(&mut self, transfer_error_interrupt: bool) { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dmacr = &unsafe { &*I::ptr() }.$ccr; + let dmacr = &unsafe { &*I::ptr() }.$chX().cr; dmacr.modify(|_, w| w.teie().bit(transfer_error_interrupt)); let _ = dmacr.read(); let _ = dmacr.read(); // Delay 2 peripheral clocks @@ -375,7 +375,7 @@ macro_rules! dma_stream { #[inline(always)] fn set_half_transfer_interrupt_enable(&mut self, half_transfer_interrupt: bool) { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dmacr = &unsafe { &*I::ptr() }.$ccr; + let dmacr = &unsafe { &*I::ptr() }.$chX().cr; dmacr.modify(|_, w| w.htie().bit(half_transfer_interrupt)); let _ = dmacr.read(); let _ = dmacr.read(); // Delay 2 peripheral clocks @@ -401,70 +401,70 @@ macro_rules! dma_stream { #[inline(always)] unsafe fn set_peripheral_address(&mut self, value: u32) { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma = &*I::ptr(); - dma.$cparX.write(|w| w.pa().bits(value)); + let dma_ch = unsafe { &*I::ptr() }.$chX(); + dma_ch.par.write(|w| w.pa().bits(value)); } #[inline(always)] unsafe fn set_memory_address(&mut self, value: u32) { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma = &*I::ptr(); - dma.$cmarX.write(|w| w.ma().bits(value) ); + let dma_ch = unsafe { &*I::ptr() }.$chX(); + dma_ch.mar.write(|w| w.ma().bits(value) ); } #[inline(always)] fn get_memory_address(&self) -> u32 { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; - dma.$cmarX.read().ma().bits() + let dma_ch = unsafe { &*I::ptr() }.$chX(); + dma_ch.mar.read().ma().bits() } #[inline(always)] fn set_number_of_transfers(&mut self, value: u16) { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; - dma.$cndtrX.write(|w| unsafe {w.ndt().bits(value) }); + let dma_ch = unsafe { &*I::ptr() }.$chX(); + dma_ch.ndtr.write(|w| unsafe {w.ndt().bits(value) }); } #[inline(always)] fn get_number_of_transfers() -> u16 { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; - dma.$cndtrX.read().ndt().bits() + let dma_ch = unsafe { &*I::ptr() }.$chX(); + dma_ch.ndtr.read().ndt().bits() } #[inline(always)] unsafe fn set_memory_size(&mut self, size: u8) { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma = &*I::ptr(); - dma.$ccr.modify(|_, w| w.msize().bits(size)); + let dma_ch = unsafe { &*I::ptr() }.$chX(); + dma_ch.cr.modify(|_, w| w.msize().bits(size)); } #[inline(always)] unsafe fn set_peripheral_size(&mut self, size: u8) { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma = &*I::ptr(); - dma.$ccr.modify(|_, w| w.psize().bits(size)); + let dma_ch = unsafe { &*I::ptr() }.$chX(); + dma_ch.cr.modify(|_, w| w.psize().bits(size)); } #[inline(always)] fn set_memory_increment(&mut self, increment: bool) { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; - dma.$ccr.modify(|_, w| w.minc().bit(increment)); + let dma_ch = unsafe { &*I::ptr() }.$chX(); + dma_ch.cr.modify(|_, w| w.minc().bit(increment)); } #[inline(always)] fn set_peripheral_increment(&mut self, increment: bool) { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; - dma.$ccr.modify(|_, w| w.pinc().bit(increment)); + let dma_ch = unsafe { &*I::ptr() }.$chX(); + dma_ch.cr.modify(|_, w| w.pinc().bit(increment)); } #[inline(always)] fn set_direction(&mut self, direction: DmaDirection) { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; - dma.$ccr.modify(|_, w| { + let dma_ch = unsafe { &*I::ptr() }.$chX(); + dma_ch.cr.modify(|_, w| { match direction { DmaDirection::PeripheralToMemory => w.dir().clear_bit().mem2mem().clear_bit(), @@ -479,8 +479,8 @@ macro_rules! dma_stream { #[inline(always)] fn set_circular_buffer(&mut self, circular_buffer: bool) { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; - dma.$ccr.modify(|_, w| w.circ().bit(circular_buffer)); + let dma_ch = unsafe { &*I::ptr() }.$chX(); + dma_ch.cr.modify(|_, w| w.circ().bit(circular_buffer)); } } @@ -505,7 +505,7 @@ macro_rules! dma_stream { #[inline(always)] pub fn set_half_transfer_interrupt_enable(&mut self, half_transfer_interrupt: bool) { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dmacr = &unsafe { &*I::ptr() }.$ccr; + let dmacr = &unsafe { &*I::ptr() }.$chX().cr; dmacr.modify(|_, w| w.htie().bit(half_transfer_interrupt)); let _ = dmacr.read(); let _ = dmacr.read(); // Delay 2 peripheral clocks @@ -530,49 +530,49 @@ dma_stream!( // zero. May need updating if it gets fixed upstream. ( Stream0, 0, - regs => ccr1, cpar1, cmar1, cndtr1, + regs => ch1, fields => tcif1, htif1, teif1, gif1, tcif1, htif1, teif1, gif1, dmamux => c0cr, c8cr, ), ( Stream1, 1, - regs => ccr2, cpar2, cmar2, cndtr2, + regs => ch2, fields => tcif2, htif2, teif2, gif2, tcif2, htif2, teif2, gif2, dmamux => c1cr, c9cr, ), ( Stream2, 2, - regs => ccr3, cpar3, cmar3, cndtr3, + regs => ch3, fields => tcif3, htif3, teif3, gif3, tcif3, htif3, teif3, gif3, dmamux => c2cr, c10cr, ), ( Stream3, 3, - regs => ccr4, cpar4, cmar4, cndtr4, + regs => ch4, fields => tcif4, htif4, teif4, gif4, tcif4, htif4, teif4, gif4, dmamux => c3cr, c11cr, ), ( Stream4, 4, - regs => ccr5, cpar5, cmar5, cndtr5, + regs => ch5, fields => tcif5, htif5, teif5, gif5, tcif5, htif5, teif5, gif5, dmamux => c4cr, c12cr, ), ( Stream5, 5, - regs => ccr6, cpar6, cmar6, cndtr6, + regs => ch6, fields => tcif6, htif6, teif6, gif6, tcif6, htif6, teif6, gif6, dmamux => c5cr, c13cr, ), ( Stream6, 6, - regs => ccr7, cpar7, cmar7, cndtr7, + regs => ch7, fields => tcif7, htif7, teif7, gif7, tcif7, htif7, teif7, gif7, dmamux => c6cr, c14cr, ), ( Stream7, 7, - regs => ccr8, cpar8, cmar8, cndtr8, + regs => ch8, fields => tcif8, htif8, teif8, gif8, tcif8, htif8, teif8, gif8, dmamux => c7cr, c15cr, ), From f5bedb37453018a9226810321cd1012ef9a4a98d Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 16 Dec 2023 23:45:26 +0100 Subject: [PATCH 03/88] Update for new pac --- examples/flash_with_rtic.rs | 2 +- src/adc.rs | 222 ++++++------ src/can.rs | 4 +- src/comparator.rs | 26 +- src/dac.rs | 38 +- src/dma/stream.rs | 684 ++++++++++++++++-------------------- src/exti.rs | 32 +- src/fdcan.rs | 120 +++---- src/flash.rs | 26 +- src/gpio.rs | 118 +++---- src/i2c.rs | 61 ++-- src/independent_watchdog.rs | 69 ++-- src/opamp.rs | 84 ++--- src/pwm.rs | 92 ++--- src/pwr.rs | 10 +- src/rcc/clockout.rs | 12 +- src/rcc/mod.rs | 92 ++--- src/serial/usart.rs | 118 +++---- src/spi.rs | 21 +- src/syscfg.rs | 2 +- src/timer.rs | 36 +- 21 files changed, 909 insertions(+), 960 deletions(-) diff --git a/examples/flash_with_rtic.rs b/examples/flash_with_rtic.rs index 9e2d00e8..9db939d1 100644 --- a/examples/flash_with_rtic.rs +++ b/examples/flash_with_rtic.rs @@ -73,7 +73,7 @@ mod app { unsafe { let mut flash = &(*stm32g4xx_hal::stm32::FLASH::ptr()); - flash.acr.modify(|_, w| { + flash.acr().modify(|_, w| { w.latency().bits(0b1000) // 8 wait states }); } diff --git a/src/adc.rs b/src/adc.rs index b40df49a..d490adea 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -1301,7 +1301,7 @@ impl Conversion { /// /// //Channel 1 /// //Disable the channel before configuring it -/// tim.ccer.modify(|_, w| w.cc1e().clear_bit()); +/// tim.ccer().modify(|_, w| w.cc1e().clear_bit()); /// /// tim.ccmr1_output().modify(|_, w| w /// //Preload enable for channel @@ -1313,14 +1313,14 @@ impl Conversion { /// /// //Set the duty cycle, 0 won't work in pwm mode but might be ok in /// //toggle mode or match mode -/// let max_duty = tim.arr.read().arr().bits() as u16; -/// tim.ccr1.modify(|_, w| w.ccr().bits(max_duty / 2)); +/// let max_duty = tim.arr().read().arr().bits() as u16; +/// tim.ccr1().modify(|_, w| w.ccr().bits(max_duty / 2)); /// /// //Enable the channel -/// tim.ccer.modify(|_, w| w.cc1e().set_bit()); +/// tim.ccer().modify(|_, w| w.cc1e().set_bit()); /// /// //Enable the TIM main Output -/// tim.bdtr.modify(|_, w| w.moe().set_bit()); +/// tim.bdtr().modify(|_, w| w.moe().set_bit()); /// } /// ``` #[derive(Clone, Copy)] @@ -1413,7 +1413,7 @@ pub trait TriggerType { #[inline(always)] fn configure_clock_source12(cs: ClockSource, rcc: &Rcc) { // Select system clock as ADC clock source - rcc.rb.ccipr.modify(|_, w| { + rcc.rb.ccipr().modify(|_, w| { // This is sound, as `0b10` is a valid value for this field. unsafe { w.adc12sel().bits(cs.into()); @@ -1427,7 +1427,7 @@ fn configure_clock_source12(cs: ClockSource, rcc: &Rcc) { #[allow(dead_code)] fn configure_clock_source345(cs: ClockSource, rcc: &Rcc) { // Select system clock as ADC clock source - rcc.rb.ccipr.modify(|_, w| { + rcc.rb.ccipr().modify(|_, w| { // This is sound, as `0b10` is a valid value for this field. unsafe { w.adc345sel().bits(cs.into()); @@ -1608,21 +1608,21 @@ macro_rules! adc { /// Enables the Deep Power Down Modus #[inline(always)] pub fn enable_deeppwd_down(&mut self) { - self.adc_reg.cr.modify(|_, w| w.deeppwd().set_bit()); + self.adc_reg.cr().modify(|_, w| w.deeppwd().set_bit()); } /// Disables the Deep Power Down Modus #[inline(always)] pub fn disable_deeppwd_down(&mut self) { - self.adc_reg.cr.modify(|_, w| w.deeppwd().clear_bit()); + self.adc_reg.cr().modify(|_, w| w.deeppwd().clear_bit()); } /// Enables the Voltage Regulator #[inline(always)] pub fn enable_vreg(&mut self, delay: &mut impl DelayUs) { - self.adc_reg.cr.modify(|_, w| w.advregen().set_bit()); - while !self.adc_reg.cr.read().advregen().bit_is_set() {} + self.adc_reg.cr().modify(|_, w| w.advregen().set_bit()); + while !self.adc_reg.cr().read().advregen().bit_is_set() {} // According to the STM32G4xx Reference Manual, section 21.4.6, we need // to wait for T_ADCVREG_STUP after enabling the internal voltage @@ -1634,13 +1634,13 @@ macro_rules! adc { /// Disables the Voltage Regulator #[inline(always)] pub fn disable_vreg(&mut self) { - self.adc_reg.cr.modify(|_, w| w.advregen().clear_bit()); + self.adc_reg.cr().modify(|_, w| w.advregen().clear_bit()); } /// Returns if the ADC is enabled (ADEN) #[inline(always)] pub fn is_enabled(&self) -> bool { - self.adc_reg.cr.read().aden().bit_is_set() + self.adc_reg.cr().read().aden().bit_is_set() } /// Disables the adc, since we don't know in what state we get it. @@ -1650,11 +1650,11 @@ macro_rules! adc { self.cancel_conversion(); // Turn off ADC - self.adc_reg.cr.modify(|_, w| w.addis().set_bit()); - while self.adc_reg.cr.read().addis().bit_is_set() {} + self.adc_reg.cr().modify(|_, w| w.addis().set_bit()); + while self.adc_reg.cr().read().addis().bit_is_set() {} // Wait until the ADC has turned off - while self.adc_reg.cr.read().aden().bit_is_set() {} + while self.adc_reg.cr().read().aden().bit_is_set() {} } /// Enables the adc @@ -1663,14 +1663,14 @@ macro_rules! adc { self.calibrate_all(); self.apply_config(self.config); - self.adc_reg.isr.modify(|_, w| w.adrdy().set_bit()); - self.adc_reg.cr.modify(|_, w| w.aden().set_bit()); + self.adc_reg.isr().modify(|_, w| w.adrdy().set_bit()); + self.adc_reg.cr().modify(|_, w| w.aden().set_bit()); // Wait for adc to get ready - while !self.adc_reg.isr.read().adrdy().bit_is_set() {} + while !self.adc_reg.isr().read().adrdy().bit_is_set() {} // Clear ready flag - self.adc_reg.isr.modify(|_, w| w.adrdy().set_bit()); + self.adc_reg.isr().modify(|_, w| w.adrdy().set_bit()); self.clear_end_of_conversion_flag(); } @@ -1709,7 +1709,7 @@ macro_rules! adc { self.config.clock_mode = clock_mode; unsafe { let common = &(*stm32::$common_type::ptr()); - common.ccr.modify(|_, w| w.ckmode().bits(clock_mode.into())); + common.ccr().modify(|_, w| w.ckmode().bits(clock_mode.into())); } } @@ -1719,7 +1719,7 @@ macro_rules! adc { self.config.clock = clock; unsafe { let common = &(*stm32::$common_type::ptr()); - common.ccr.modify(|_, w| w.presc().bits(clock.into())); + common.ccr().modify(|_, w| w.presc().bits(clock.into())); } } @@ -1727,30 +1727,34 @@ macro_rules! adc { #[inline(always)] pub fn set_resolution(&mut self, resolution: config::Resolution) { self.config.resolution = resolution; - self.adc_reg.cfgr.modify(|_, w| w.res().bits(resolution.into())); + unsafe { + self.adc_reg.cfgr().modify(|_, w| w.res().bits(resolution.into())); + } } /// Enable oversampling #[inline(always)] pub fn set_oversampling(&mut self, oversampling: config::OverSampling, shift: config::OverSamplingShift) { - self.adc_reg.cfgr2.modify(|_, w| unsafe { w.ovsr().bits(oversampling.into()) - .ovss().bits(shift.into()) - .rovse().set_bit()}); + self.adc_reg.cfgr2().modify(|_, w| unsafe { + w.ovsr().bits(oversampling.into()) + .ovss().bits(shift.into()) + .rovse().set_bit() + }); } /// Sets the DR register alignment to left or right #[inline(always)] pub fn set_align(&mut self, align: config::Align) { self.config.align = align; - self.adc_reg.cfgr.modify(|_, w| w.align().bit(align.into())); + self.adc_reg.cfgr().modify(|_, w| w.align().bit(align.into())); } /// Sets which external trigger to use and if it is disabled, rising, falling or both #[inline(always)] pub fn set_external_trigger(&mut self, (edge, extsel): (config::TriggerMode, $trigger_type)) { self.config.external_trigger = (edge, extsel); - self.adc_reg.cfgr.modify(|_, w| unsafe { w + self.adc_reg.cfgr().modify(|_, w| unsafe { w .extsel().bits(extsel.into()) .exten().bits(edge.into()) }); @@ -1760,14 +1764,14 @@ macro_rules! adc { #[inline(always)] pub fn set_auto_delay(&mut self, delay: bool) { self.config.auto_delay = delay; - self.adc_reg.cfgr.modify(|_, w| w.autdly().bit(delay) ); + self.adc_reg.cfgr().modify(|_, w| w.autdly().bit(delay) ); } /// Enables and disables dis-/continuous mode #[inline(always)] pub fn set_continuous(&mut self, continuous: config::Continuous) { self.config.continuous = continuous; - self.adc_reg.cfgr.modify(|_, w| w + self.adc_reg.cfgr().modify(|_, w| w .cont().bit(continuous == config::Continuous::Continuous) .discen().bit(continuous == config::Continuous::Discontinuous) ); @@ -1777,7 +1781,9 @@ macro_rules! adc { // NOTE: The software is allowed to write these bits only when ADSTART = 0 fn set_subgroup_len(&mut self, subgroup_len: config::SubGroupLength) { self.config.subgroup_len = subgroup_len; - self.adc_reg.cfgr.modify(|_, w| w.discnum().bits(subgroup_len as u8)) + unsafe { + self.adc_reg.cfgr().modify(|_, w| w.discnum().bits(subgroup_len as u8)); + } } /// Sets DMA to disabled, single or continuous @@ -1789,7 +1795,7 @@ macro_rules! adc { config::Dma::Single => (false, true), config::Dma::Continuous => (true, true), }; - self.adc_reg.cfgr.modify(|_, w| w + self.adc_reg.cfgr().modify(|_, w| w //DDS stands for "DMA disable selection" //0 means do one DMA then stop //1 means keep sending DMA requests as long as DMA=1 @@ -1808,7 +1814,7 @@ macro_rules! adc { config::Eoc::Conversion => (true, true), config::Eoc::Sequence => (true, false), }; - self.adc_reg.ier.modify(|_, w|w + self.adc_reg.ier().modify(|_, w|w .eosie().bit(eocs) .eocie().bit(en) ); @@ -1818,7 +1824,7 @@ macro_rules! adc { /// /// This is triggered when the AD finishes a conversion before the last value was read by CPU/DMA pub fn set_overrun_interrupt(&mut self, enable: bool) { - self.adc_reg.ier.modify(|_, w| w.ovrie().bit(enable)); + self.adc_reg.ier().modify(|_, w| w.ovrie().bit(enable)); } /// Sets the default sample time that is used for one-shot conversions. @@ -1834,7 +1840,7 @@ macro_rules! adc { pub fn set_channel_input_type(&mut self, df: config::DifferentialSelection) { self.config.difsel = df; - self.adc_reg.difsel.modify(|_, w| {w + self.adc_reg.difsel().modify(|_, w| {w .difsel_0().bit(df.get_channel(0).into() ) .difsel_1().bit(df.get_channel(1).into() ) .difsel_2().bit(df.get_channel(2).into() ) @@ -1861,19 +1867,19 @@ macro_rules! adc { #[inline(always)] pub fn reset_sequence(&mut self) { //The reset state is One conversion selected - self.adc_reg.sqr1.modify(|_, w| w.l().bits(config::Sequence::One.into())); + self.adc_reg.sqr1().modify(|_, w| unsafe { w.l().bits(config::Sequence::One.into()) }); } /// Returns the current sequence length. Primarily useful for configuring DMA. #[inline(always)] pub fn sequence_length(&mut self) -> u8 { - self.adc_reg.sqr1.read().l().bits() + 1 + self.adc_reg.sqr1().read().l().bits() + 1 } /// Returns the address of the ADC data register. Primarily useful for configuring DMA. #[inline(always)] pub fn data_register_address(&self) -> u32 { - &self.adc_reg.dr as *const _ as u32 + &self.adc_reg.dr() as *const _ as u32 } /// Calibrate the adc for @@ -1881,15 +1887,15 @@ macro_rules! adc { pub fn calibrate(&mut self, it: config::InputType) { match it { config::InputType::SingleEnded => { - self.adc_reg.cr.modify(|_, w| w.adcaldif().clear_bit() ); + self.adc_reg.cr().modify(|_, w| w.adcaldif().clear_bit() ); }, config::InputType::Differential => { - self.adc_reg.cr.modify(|_, w| w.adcaldif().set_bit() ); + self.adc_reg.cr().modify(|_, w| w.adcaldif().set_bit() ); }, } - self.adc_reg.cr.modify(|_, w| w.adcal().set_bit() ); - while self.adc_reg.cr.read().adcal().bit_is_set() {} + self.adc_reg.cr().modify(|_, w| w.adcal().set_bit() ); + while self.adc_reg.cr().read().adcal().bit_is_set() {} } /// Calibrate the Adc for all Input Types @@ -1912,7 +1918,7 @@ macro_rules! adc { { //Check the sequence is long enough - self.adc_reg.sqr1.modify(|r, w| { + self.adc_reg.sqr1().modify(|r, w| unsafe { let prev: config::Sequence = r.l().bits().into(); if prev < sequence { w.l().bits(sequence.into()) @@ -1925,47 +1931,49 @@ macro_rules! adc { //Set the channel in the right sequence field match sequence { - config::Sequence::One => self.adc_reg.sqr1.modify(|_, w| unsafe {w.sq1().bits(channel) }), - config::Sequence::Two => self.adc_reg.sqr1.modify(|_, w| unsafe {w.sq2().bits(channel) }), - config::Sequence::Three => self.adc_reg.sqr1.modify(|_, w| unsafe {w.sq3().bits(channel) }), - config::Sequence::Four => self.adc_reg.sqr1.modify(|_, w| unsafe {w.sq4().bits(channel) }), - config::Sequence::Five => self.adc_reg.sqr2.modify(|_, w| unsafe {w.sq5().bits(channel) }), - config::Sequence::Six => self.adc_reg.sqr2.modify(|_, w| unsafe {w.sq6().bits(channel) }), - config::Sequence::Seven => self.adc_reg.sqr2.modify(|_, w| unsafe {w.sq7().bits(channel) }), - config::Sequence::Eight => self.adc_reg.sqr2.modify(|_, w| unsafe {w.sq8().bits(channel) }), - config::Sequence::Nine => self.adc_reg.sqr2.modify(|_, w| unsafe {w.sq9().bits(channel) }), - config::Sequence::Ten => self.adc_reg.sqr3.modify(|_, w| unsafe {w.sq10().bits(channel) }), - config::Sequence::Eleven => self.adc_reg.sqr3.modify(|_, w| unsafe {w.sq11().bits(channel) }), - config::Sequence::Twelve => self.adc_reg.sqr3.modify(|_, w| unsafe {w.sq12().bits(channel) }), - config::Sequence::Thirteen => self.adc_reg.sqr3.modify(|_, w| unsafe {w.sq13().bits(channel) }), - config::Sequence::Fourteen => self.adc_reg.sqr3.modify(|_, w| unsafe {w.sq14().bits(channel) }), - config::Sequence::Fifteen => self.adc_reg.sqr4.modify(|_, w| unsafe {w.sq15().bits(channel) }), - config::Sequence::Sixteen => self.adc_reg.sqr4.modify(|_, w| unsafe {w.sq16().bits(channel) }), + config::Sequence::One => self.adc_reg.sqr1().modify(|_, w| unsafe {w.sq1().bits(channel) }), + config::Sequence::Two => self.adc_reg.sqr1().modify(|_, w| unsafe {w.sq2().bits(channel) }), + config::Sequence::Three => self.adc_reg.sqr1().modify(|_, w| unsafe {w.sq3().bits(channel) }), + config::Sequence::Four => self.adc_reg.sqr1().modify(|_, w| unsafe {w.sq4().bits(channel) }), + config::Sequence::Five => self.adc_reg.sqr2().modify(|_, w| unsafe {w.sq5().bits(channel) }), + config::Sequence::Six => self.adc_reg.sqr2().modify(|_, w| unsafe {w.sq6().bits(channel) }), + config::Sequence::Seven => self.adc_reg.sqr2().modify(|_, w| unsafe {w.sq7().bits(channel) }), + config::Sequence::Eight => self.adc_reg.sqr2().modify(|_, w| unsafe {w.sq8().bits(channel) }), + config::Sequence::Nine => self.adc_reg.sqr2().modify(|_, w| unsafe {w.sq9().bits(channel) }), + config::Sequence::Ten => self.adc_reg.sqr3().modify(|_, w| unsafe {w.sq10().bits(channel) }), + config::Sequence::Eleven => self.adc_reg.sqr3().modify(|_, w| unsafe {w.sq11().bits(channel) }), + config::Sequence::Twelve => self.adc_reg.sqr3().modify(|_, w| unsafe {w.sq12().bits(channel) }), + config::Sequence::Thirteen => self.adc_reg.sqr3().modify(|_, w| unsafe {w.sq13().bits(channel) }), + config::Sequence::Fourteen => self.adc_reg.sqr3().modify(|_, w| unsafe {w.sq14().bits(channel) }), + config::Sequence::Fifteen => self.adc_reg.sqr4().modify(|_, w| unsafe {w.sq15().bits(channel) }), + config::Sequence::Sixteen => self.adc_reg.sqr4().modify(|_, w| unsafe {w.sq16().bits(channel) }), } //Set the sample time for the channel let st = u8::from(sample_time); - match channel { - 0 => self.adc_reg.smpr1.modify(|_, w| w.smp0().bits(st) ), - 1 => self.adc_reg.smpr1.modify(|_, w| w.smp1().bits(st) ), - 2 => self.adc_reg.smpr1.modify(|_, w| w.smp2().bits(st) ), - 3 => self.adc_reg.smpr1.modify(|_, w| w.smp3().bits(st) ), - 4 => self.adc_reg.smpr1.modify(|_, w| w.smp4().bits(st) ), - 5 => self.adc_reg.smpr1.modify(|_, w| w.smp5().bits(st) ), - 6 => self.adc_reg.smpr1.modify(|_, w| w.smp6().bits(st) ), - 7 => self.adc_reg.smpr1.modify(|_, w| w.smp7().bits(st) ), - 8 => self.adc_reg.smpr1.modify(|_, w| w.smp8().bits(st) ), - 9 => self.adc_reg.smpr1.modify(|_, w| w.smp9().bits(st) ), - 10 => self.adc_reg.smpr2.modify(|_, w| w.smp10().bits(st) ), - 11 => self.adc_reg.smpr2.modify(|_, w| w.smp11().bits(st) ), - 12 => self.adc_reg.smpr2.modify(|_, w| w.smp12().bits(st) ), - 13 => self.adc_reg.smpr2.modify(|_, w| w.smp13().bits(st) ), - 14 => self.adc_reg.smpr2.modify(|_, w| w.smp14().bits(st) ), - 15 => self.adc_reg.smpr2.modify(|_, w| w.smp15().bits(st) ), - 16 => self.adc_reg.smpr2.modify(|_, w| w.smp16().bits(st) ), - 17 => self.adc_reg.smpr2.modify(|_, w| w.smp17().bits(st) ), - 18 => self.adc_reg.smpr2.modify(|_, w| w.smp18().bits(st) ), - _ => unimplemented!(), + unsafe { + match channel { + 0 => self.adc_reg.smpr1().modify(|_, w| w.smp0().bits(st) ), + 1 => self.adc_reg.smpr1().modify(|_, w| w.smp1().bits(st) ), + 2 => self.adc_reg.smpr1().modify(|_, w| w.smp2().bits(st) ), + 3 => self.adc_reg.smpr1().modify(|_, w| w.smp3().bits(st) ), + 4 => self.adc_reg.smpr1().modify(|_, w| w.smp4().bits(st) ), + 5 => self.adc_reg.smpr1().modify(|_, w| w.smp5().bits(st) ), + 6 => self.adc_reg.smpr1().modify(|_, w| w.smp6().bits(st) ), + 7 => self.adc_reg.smpr1().modify(|_, w| w.smp7().bits(st) ), + 8 => self.adc_reg.smpr1().modify(|_, w| w.smp8().bits(st) ), + 9 => self.adc_reg.smpr1().modify(|_, w| w.smp9().bits(st) ), + 10 => self.adc_reg.smpr2().modify(|_, w| w.smp10().bits(st) ), + 11 => self.adc_reg.smpr2().modify(|_, w| w.smp11().bits(st) ), + 12 => self.adc_reg.smpr2().modify(|_, w| w.smp12().bits(st) ), + 13 => self.adc_reg.smpr2().modify(|_, w| w.smp13().bits(st) ), + 14 => self.adc_reg.smpr2().modify(|_, w| w.smp14().bits(st) ), + 15 => self.adc_reg.smpr2().modify(|_, w| w.smp15().bits(st) ), + 16 => self.adc_reg.smpr2().modify(|_, w| w.smp16().bits(st) ), + 17 => self.adc_reg.smpr2().modify(|_, w| w.smp17().bits(st) ), + 18 => self.adc_reg.smpr2().modify(|_, w| w.smp18().bits(st) ), + _ => unimplemented!(), + } } } /// Synchronously convert a single sample @@ -1975,12 +1983,14 @@ macro_rules! adc { PIN: Channel { let saved_config = self.config; - self.adc_reg.cfgr.modify(|_, w| w - .dmaen().clear_bit() //Disable dma - .cont().clear_bit() //Disable continuous mode - .exten().bits(config::TriggerMode::Disabled.into()) //Disable trigger - ); - self.adc_reg.ier.modify(|_, w| w + unsafe { + self.adc_reg.cfgr().modify(|_, w| w + .dmaen().clear_bit() //Disable dma + .cont().clear_bit() //Disable continuous mode + .exten().bits(config::TriggerMode::Disabled.into()) //Disable trigger + ); + } + self.adc_reg.ier().modify(|_, w| w .eocie().clear_bit() //Disable end of conversion interrupt ); @@ -2005,116 +2015,116 @@ macro_rules! adc { /// Resets the end-of-conversion flag #[inline(always)] pub fn clear_end_of_conversion_flag(&mut self) { - self.adc_reg.isr.modify(|_, w| w.eoc().set_bit()); + self.adc_reg.isr().modify(|_, w| w.eoc().set_bit()); } /// Block until the conversion is completed and return to configured pub fn wait_for_conversion_sequence(&mut self) { - while !self.adc_reg.isr.read().eoc().bit_is_set() {} + while !self.adc_reg.isr().read().eoc().bit_is_set() {} } /// get current sample #[inline(always)] pub fn current_sample(&self) -> u16 { - self.adc_reg.dr.read().rdata().bits() + self.adc_reg.dr().read().rdata().bits() } /// Starts conversion sequence. Waits for the hardware to indicate it's actually started. #[inline(always)] pub fn start_conversion(&mut self) { //Start conversion - self.adc_reg.cr.modify(|_, w| w.adstart().set_bit()); + self.adc_reg.cr().modify(|_, w| w.adstart().set_bit()); } /// Cancels an ongoing conversion #[inline(always)] pub fn cancel_conversion(&mut self) { - self.adc_reg.cr.modify(|_, w| w.adstp().set_bit()); - while self.adc_reg.cr.read().adstart().bit_is_set() {} + self.adc_reg.cr().modify(|_, w| w.adstp().set_bit()); + while self.adc_reg.cr().read().adstart().bit_is_set() {} } /// Returns if the Voltage Regulator is enabled #[inline(always)] pub fn is_vreg_enabled(&self) -> bool { - self.adc_reg.cr.read().advregen().bit_is_set() + self.adc_reg.cr().read().advregen().bit_is_set() } /// Returns if Deep Power Down is enabled #[inline(always)] pub fn is_deeppwd_enabled(&self) -> bool { - self.adc_reg.cr.read().deeppwd().bit_is_set() + self.adc_reg.cr().read().deeppwd().bit_is_set() } /// Returns if a conversion is active #[inline(always)] pub fn is_conversion_active(&self) -> bool { - self.adc_reg.cr.read().adstart().bit_is_set() + self.adc_reg.cr().read().adstart().bit_is_set() } /// Enables the vbat internal channel #[inline(always)] pub fn enable_vbat(&self, common: &stm32::$common_type) { - common.ccr.modify(|_, w| w.vbatsel().set_bit()); + common.ccr().modify(|_, w| w.vbatsel().set_bit()); } /// Enables the vbat internal channel #[inline(always)] pub fn disable_vbat(&self, common: &stm32::$common_type) { - common.ccr.modify(|_, w| w.vbatsel().clear_bit()); + common.ccr().modify(|_, w| w.vbatsel().clear_bit()); } /// Returns if the vbat internal channel is enabled #[inline(always)] pub fn is_vbat_enabled(&mut self, common: &stm32::$common_type) -> bool { - common.ccr.read().vbatsel().bit_is_set() + common.ccr().read().vbatsel().bit_is_set() } /// Enables the temp internal channel. #[inline(always)] pub fn enable_temperature(&mut self, common: &stm32::$common_type) { - common.ccr.modify(|_, w| w.vsensesel().set_bit()); + common.ccr().modify(|_, w| w.vsensesel().set_bit()); } /// Disables the temp internal channel #[inline(always)] pub fn disable_temperature(&mut self, common: &stm32::$common_type) { - common.ccr.modify(|_, w| w.vsensesel().clear_bit()); + common.ccr().modify(|_, w| w.vsensesel().clear_bit()); } /// Returns if the temp internal channel is enabled #[inline(always)] pub fn is_temperature_enabled(&mut self, common: &stm32::$common_type) -> bool { - common.ccr.read().vsensesel().bit_is_set() + common.ccr().read().vsensesel().bit_is_set() } /// Enables the vref internal channel. #[inline(always)] pub fn enable_vref(&mut self, common: &stm32::$common_type) { - common.ccr.modify(|_, w| w.vrefen().set_bit()); + common.ccr().modify(|_, w| w.vrefen().set_bit()); } /// Disables the vref internal channel #[inline(always)] pub fn disable_vref(&mut self, common: &stm32::$common_type) { - common.ccr.modify(|_, w| w.vrefen().clear_bit()); + common.ccr().modify(|_, w| w.vrefen().clear_bit()); } /// Returns if the vref internal channel is enabled #[inline(always)] pub fn is_vref_enabled(&mut self, common: &stm32::$common_type) -> bool { - common.ccr.read().vrefen().bit_is_set() + common.ccr().read().vrefen().bit_is_set() } /// Read overrun flag #[inline(always)] pub fn get_overrun_flag(&self) -> bool { - self.adc_reg.isr.read().ovr().bit() + self.adc_reg.isr().read().ovr().bit() } /// Resets the overrun flag #[inline(always)] pub fn clear_overrun_flag(&mut self) { - self.adc_reg.isr.modify(|_, w| w.ovr().set_bit()); + self.adc_reg.isr().modify(|_, w| w.ovr().set_bit()); } } diff --git a/src/can.rs b/src/can.rs index 697df9c4..15d171a2 100644 --- a/src/can.rs +++ b/src/can.rs @@ -55,9 +55,9 @@ where { Self::enable(&rcc.rb); - if rcc.rb.ccipr.read().fdcansel().is_hse() { + if rcc.rb.ccipr().read().fdcansel().is_hse() { // Select P clock as FDCAN clock source - rcc.rb.ccipr.modify(|_, w| { + rcc.rb.ccipr().modify(|_, w| { // This is sound, as `FdCanClockSource` only contains valid values for this field. unsafe { w.fdcansel().bits(FdCanClockSource::PCLK as u8); diff --git a/src/comparator.rs b/src/comparator.rs index d0597ea7..e9eb1788 100644 --- a/src/comparator.rs +++ b/src/comparator.rs @@ -55,26 +55,26 @@ impl EnabledState for Enabled {} impl EnabledState for Locked {} macro_rules! impl_comp { - ($($t:ident: $reg_t:ident, $reg:ident,)+) => {$( + ($($t:ident: $reg:ident,)+) => {$( pub struct $t { _rb: PhantomData<()>, } impl $t { - pub fn csr(&self) -> &$crate::stm32::comp::$reg_t { + pub fn csr(&self) -> &$crate::stm32::comp::CCSR { // SAFETY: The COMP1 type is only constructed with logical ownership of // these registers. - &unsafe { &*COMP::ptr() }.$reg + &unsafe { &*COMP::ptr() }.$reg() } } )+}; } impl_comp! { - COMP1: C1CSR, c1csr, - COMP2: C2CSR, c2csr, - COMP3: C3CSR, c3csr, - COMP4: C4CSR, c4csr, + COMP1: c1csr, + COMP2: c2csr, + COMP3: c3csr, + COMP4: c4csr, } #[cfg(any( feature = "stm32g473", @@ -83,9 +83,9 @@ impl_comp! { feature = "stm32g484" ))] impl_comp! { - COMP5: C5CSR, c5csr, - COMP6: C6CSR, c6csr, - COMP7: C7CSR, c7csr, + COMP5: c5csr, + COMP6: c6csr, + COMP7: c7csr, } // TODO: Split COMP in PAC @@ -541,11 +541,11 @@ type Comparators = (COMP1, COMP2, COMP3, COMP4, COMP5, COMP6, COMP7); /// Enables the comparator peripheral, and splits the [`COMP`] into independent [`COMP1`] and [`COMP2`] pub fn split(_comp: COMP, rcc: &mut Rcc) -> Comparators { // Enable COMP, SYSCFG, VREFBUF clocks - rcc.rb.apb2enr.modify(|_, w| w.syscfgen().set_bit()); + rcc.rb.apb2enr().modify(|_, w| w.syscfgen().set_bit()); // Reset COMP, SYSCFG, VREFBUF - rcc.rb.apb2rstr.modify(|_, w| w.syscfgrst().set_bit()); - rcc.rb.apb2rstr.modify(|_, w| w.syscfgrst().clear_bit()); + rcc.rb.apb2rstr().modify(|_, w| w.syscfgrst().set_bit()); + rcc.rb.apb2rstr().modify(|_, w| w.syscfgrst().clear_bit()); ( COMP1 { _rb: PhantomData }, diff --git a/src/dac.rs b/src/dac.rs index 109374c0..991e8467 100644 --- a/src/dac.rs +++ b/src/dac.rs @@ -179,7 +179,7 @@ macro_rules! dac_helper { $trim:ident, $mode:ident, $dhrx:ident, - $dac_dor:ident, + $dor:ident, $daccxdhr:ident, $wave:ident, $mamp:ident, @@ -193,8 +193,8 @@ macro_rules! dac_helper { pub fn enable(self) -> $CX { let dac = unsafe { &(*<$DAC>::ptr()) }; - dac.dac_mcr.modify(|_, w| unsafe { w.$mode().bits(MODE_BITS) }); - dac.dac_cr.modify(|_, w| w.$en().set_bit()); + dac.mcr().modify(|_, w| unsafe { w.$mode().bits(MODE_BITS) }); + dac.cr().modify(|_, w| w.$en().set_bit()); $CX { _enabled: PhantomData, @@ -204,8 +204,8 @@ macro_rules! dac_helper { pub fn enable_generator(self, config: GeneratorConfig) -> $CX { let dac = unsafe { &(*<$DAC>::ptr()) }; - dac.dac_mcr.modify(|_, w| unsafe { w.$mode().bits(MODE_BITS) }); - dac.dac_cr.modify(|_, w| unsafe { + dac.mcr().modify(|_, w| unsafe { w.$mode().bits(MODE_BITS) }); + dac.cr().modify(|_, w| unsafe { w.$wave().bits(config.mode); w.$ten().set_bit(); w.$mamp().bits(config.amp); @@ -235,19 +235,19 @@ macro_rules! dac_helper { T: DelayUs, { let dac = unsafe { &(*<$DAC>::ptr()) }; - dac.dac_cr.modify(|_, w| w.$en().clear_bit()); - dac.dac_mcr.modify(|_, w| unsafe { w.$mode().bits(0) }); - dac.dac_cr.modify(|_, w| w.$cen().set_bit()); + dac.cr().modify(|_, w| w.$en().clear_bit()); + dac.mcr().modify(|_, w| unsafe { w.$mode().bits(0) }); + dac.cr().modify(|_, w| w.$cen().set_bit()); let mut trim = 0; while true { - dac.dac_ccr.modify(|_, w| unsafe { w.$trim().bits(trim) }); + dac.ccr().modify(|_, w| unsafe { w.$trim().bits(trim) }); delay.delay_us(64_u32); - if dac.dac_sr.read().$cal_flag().bit() { + if dac.sr().read().$cal_flag().bit() { break; } trim += 1; } - dac.dac_cr.modify(|_, w| w.$cen().clear_bit()); + dac.cr().modify(|_, w| w.$cen().clear_bit()); $CX { _enabled: PhantomData, @@ -257,7 +257,7 @@ macro_rules! dac_helper { /// Disable the DAC channel pub fn disable(self) -> $CX { let dac = unsafe { &(*<$DAC>::ptr()) }; - dac.dac_cr.modify(|_, w| unsafe { + dac.cr().modify(|_, w| unsafe { w.$en().clear_bit().$wave().bits(0).$ten().clear_bit() }); @@ -272,12 +272,12 @@ macro_rules! dac_helper { impl DacOut for $CX { fn set_value(&mut self, val: u16) { let dac = unsafe { &(*<$DAC>::ptr()) }; - dac.$dhrx.write(|w| unsafe { w.bits(val as u32) }); + dac.$dhrx().write(|w| unsafe { w.bits(val as u32) }); } fn get_value(&mut self) -> u16 { let dac = unsafe { &(*<$DAC>::ptr()) }; - dac.$dac_dor.read().bits() as u16 + dac.$dor().read().bits() as u16 } } @@ -285,7 +285,7 @@ macro_rules! dac_helper { impl $CX { pub fn trigger(&mut self) { let dac = unsafe { &(*<$DAC>::ptr()) }; - dac.dac_swtrgr.write(|w| { w.$swtrig().set_bit() }); + dac.swtrgr().write(|w| { w.$swtrig().set_bit() }); } } )+ @@ -300,8 +300,8 @@ macro_rules! dac { cal_flag1, otrim1, mode1, - dac_dhr12r1, - dac_dor1, + dhr12r1, + dor1, dacc1dhr, wave1, mamp1, @@ -314,8 +314,8 @@ macro_rules! dac { cal_flag2, otrim2, mode2, - dac_dhr12r2, - dac_dor2, + dhr12r2, + dor2, dacc2dhr, wave2, mamp2, diff --git a/src/dma/stream.rs b/src/dma/stream.rs index a6a41661..a889939d 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -131,13 +131,13 @@ pub trait DMAExt { impl DMAExt for DMA1 { fn split(self, rcc: &Rcc) -> StreamsTuple { // Enable DMAMux is not yet enabled - if !rcc.rb.ahb1enr.read().dmamuxen().bit_is_set() { + if !rcc.rb.ahb1enr().read().dmamuxen().bit_is_set() { // Enable peripheral - rcc.rb.ahb1enr.modify(|_, w| w.dmamuxen().set_bit()); + rcc.rb.ahb1enr().modify(|_, w| w.dmamuxen().set_bit()); } // Enable peripheral - rcc.rb.ahb1enr.modify(|_, w| w.dma1en().set_bit()); + rcc.rb.ahb1enr().modify(|_, w| w.dma1en().set_bit()); StreamsTuple::new(self) } @@ -146,13 +146,13 @@ impl DMAExt for DMA1 { impl DMAExt for DMA2 { fn split(self, rcc: &Rcc) -> StreamsTuple { // Enable DMAMux is not yet enabled - if !rcc.rb.ahb1enr.read().dmamuxen().bit_is_set() { + if !rcc.rb.ahb1enr().read().dmamuxen().bit_is_set() { // Enable peripheral - rcc.rb.ahb1enr.modify(|_, w| w.dmamuxen().set_bit()); + rcc.rb.ahb1enr().modify(|_, w| w.dmamuxen().set_bit()); } // Enable peripheral - rcc.rb.ahb1enr.modify(|_, w| w.dma2en().set_bit()); + rcc.rb.ahb1enr().modify(|_, w| w.dma2en().set_bit()); StreamsTuple::new(self) } @@ -181,442 +181,374 @@ impl StreamsTuple { // The implementation does the heavy lifting of mapping to the right fields on // the stream macro_rules! dma_stream { - ($(($name:ident, $number:expr, - regs => $chX:ident, - fields => $tcif:ident, $htif:ident, $teif:ident, $gif:ident, $tcisr:ident, $htisr:ident, $teisr:ident, $gisr:ident, - dmamux => $dma1_cXcr:ident, $dma2_cXcr:ident, ) - ),+$(,)*) => { - $( - impl Stream for $name { - - const NUMBER: usize = $number; - type Config = DmaConfig; - type Interrupts = DmaInterrupts; - - fn apply_config(&mut self, config: DmaConfig) { - self.set_priority(config.priority); - self.set_memory_increment(config.memory_increment); - self.set_peripheral_increment(config.peripheral_increment); - self.set_circular_buffer(config.circular_buffer); - self.set_transfer_complete_interrupt_enable( - config.transfer_complete_interrupt - ); - self.set_half_transfer_interrupt_enable(config.half_transfer_interrupt); - self.set_transfer_error_interrupt_enable( - config.transfer_error_interrupt - ); - } - - #[inline(always)] - fn clear_interrupts(&mut self) { - //NOTE(unsafe) Atomic write with no side-effects and we only access the bits - // that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; - dma.ifcr.write(|w| w - .$tcif().set_bit() //Clear transfer complete interrupt flag - .$htif().set_bit() //Clear half transfer interrupt flag - .$teif().set_bit() //Clear transfer error interrupt flag - .$gif().set_bit() //Clear global interrupt flag - ); - let _ = dma.isr.read(); - let _ = dma.isr.read(); // Delay 2 peripheral clocks - } - - #[inline(always)] - fn clear_transfer_complete_flag(&mut self) { - //NOTE(unsafe) Atomic write with no side-effects and we only access the bits - // that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; - dma.ifcr.write(|w| w.$tcif().set_bit()); - } + ($(($name:ident, $number:expr, $x:literal)),+$(,)*) => { + paste::paste!{ + $( + impl Stream for $name { + + const NUMBER: usize = $number; + type Config = DmaConfig; + type Interrupts = DmaInterrupts; + + fn apply_config(&mut self, config: DmaConfig) { + self.set_priority(config.priority); + self.set_memory_increment(config.memory_increment); + self.set_peripheral_increment(config.peripheral_increment); + self.set_circular_buffer(config.circular_buffer); + self.set_transfer_complete_interrupt_enable( + config.transfer_complete_interrupt + ); + self.set_half_transfer_interrupt_enable(config.half_transfer_interrupt); + self.set_transfer_error_interrupt_enable( + config.transfer_error_interrupt + ); + } - #[inline(always)] - fn clear_transfer_complete_interrupt(&mut self) { - self.clear_transfer_complete_flag(); - //NOTE(unsafe) Atomic read with no side-effects. - let dma = unsafe { &*I::ptr() }; - let _ = dma.isr.read(); - let _ = dma.isr.read(); // Delay 2 peripheral clocks - } + #[inline(always)] + fn clear_interrupts(&mut self) { + //NOTE(unsafe) Atomic write with no side-effects and we only access the bits + // that belongs to the StreamX + let dma = unsafe { &*I::ptr() }; + dma.ifcr().write(|w| w + .[]().set_bit() //Clear transfer complete interrupt flag + .[]().set_bit() //Clear half transfer interrupt flag + .[]().set_bit() //Clear transfer error interrupt flag + .[]().set_bit() //Clear global interrupt flag + ); + let _ = dma.isr().read(); + let _ = dma.isr().read(); // Delay 2 peripheral clocks + } - #[inline(always)] - fn clear_transfer_error_interrupt(&mut self) { - //NOTE(unsafe) Atomic write with no side-effects and we only access the bits - // that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; - dma.ifcr.write(|w| w.$teif().set_bit()); - let _ = dma.isr.read(); - let _ = dma.isr.read(); // Delay 2 peripheral clocks - } + #[inline(always)] + fn clear_transfer_complete_flag(&mut self) { + //NOTE(unsafe) Atomic write with no side-effects and we only access the bits + // that belongs to the StreamX + let dma = unsafe { &*I::ptr() }; + dma.ifcr().write(|w| w.[]().set_bit()); + } - #[inline(always)] - fn get_transfer_complete_flag() -> bool { - //NOTE(unsafe) Atomic read with no side effects - let dma = unsafe { &*I::ptr() }; - dma.isr.read().$tcisr().bit_is_set() - } + #[inline(always)] + fn clear_transfer_complete_interrupt(&mut self) { + self.clear_transfer_complete_flag(); + //NOTE(unsafe) Atomic read with no side-effects. + let dma = unsafe { &*I::ptr() }; + let _ = dma.isr().read(); + let _ = dma.isr().read(); // Delay 2 peripheral clocks + } - #[inline(always)] - fn get_transfer_error_flag() -> bool { - //NOTE(unsafe) Atomic read with no side effects - let dma = unsafe { &*I::ptr() }; - dma.isr.read().$teisr().bit_is_set() - } + #[inline(always)] + fn clear_transfer_error_interrupt(&mut self) { + //NOTE(unsafe) Atomic write with no side-effects and we only access the bits + // that belongs to the StreamX + let dma = unsafe { &*I::ptr() }; + dma.ifcr().write(|w| w.[]().set_bit()); + let _ = dma.isr().read(); + let _ = dma.isr().read(); // Delay 2 peripheral clocks + } - #[inline(always)] - unsafe fn enable(&mut self) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = &unsafe { &*I::ptr() }.$chX(); - dma_ch.cr.modify(|_, w| w.en().set_bit()); - } + #[inline(always)] + fn get_transfer_complete_flag() -> bool { + //NOTE(unsafe) Atomic read with no side effects + let dma = unsafe { &*I::ptr() }; + dma.isr().read().[]().bit_is_set() + } - #[inline(always)] - fn is_enabled() -> bool { - //NOTE(unsafe) Atomic read with no side effects - let dma_ch = &unsafe { &*I::ptr() }.$chX(); - dma_ch.cr.read().en().bit_is_set() - } + #[inline(always)] + fn get_transfer_error_flag() -> bool { + //NOTE(unsafe) Atomic read with no side effects + let dma = unsafe { &*I::ptr() }; + dma.isr().read().[]().bit_is_set() + } - fn disable(&mut self) { - if Self::is_enabled() { + #[inline(always)] + unsafe fn enable(&mut self) { //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = &unsafe { &*I::ptr() }.$chX(); + let dma_ch = &unsafe { &*I::ptr() }.[](); + dma_ch.cr().modify(|_, w| w.en().set_bit()); + } + + #[inline(always)] + fn is_enabled() -> bool { + //NOTE(unsafe) Atomic read with no side effects + let dma_ch = &unsafe { &*I::ptr() }.[](); + dma_ch.cr().read().en().bit_is_set() + } + + fn disable(&mut self) { + if Self::is_enabled() { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = &unsafe { &*I::ptr() }.[](); - // Aborting an on-going transfer might cause interrupts to fire, disable - // them - let interrupts = Self::get_interrupts_enable(); - self.disable_interrupts(); + // Aborting an on-going transfer might cause interrupts to fire, disable + // them + let interrupts = Self::get_interrupts_enable(); + self.disable_interrupts(); - dma_ch.cr.modify(|_, w| w.en().clear_bit()); - while Self::is_enabled() {} + dma_ch.cr().modify(|_, w| w.en().clear_bit()); + while Self::is_enabled() {} - self.clear_interrupts(); - self.enable_interrupts(interrupts); + self.clear_interrupts(); + self.enable_interrupts(interrupts); + } } - } - #[inline(always)] - fn set_request_line(&mut self, request_line: u8) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dmamux = unsafe { &*I::mux_ptr() }; - unsafe { - if I::IS_DMA1 { - dmamux.$dma1_cXcr - .modify(|_, w| w.dmareq_id().bits(request_line)); - } else { - dmamux.$dma2_cXcr + #[inline(always)] + fn set_request_line(&mut self, request_line: u8) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dmamux = unsafe { &*I::mux_ptr() }; + unsafe { + dmamux.ccr($number) .modify(|_, w| w.dmareq_id().bits(request_line)); - }; + } } - } - #[inline(always)] - fn set_priority(&mut self, priority: config::Priority) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = &unsafe { &*I::ptr() }.$chX(); - dma_ch.cr.modify(|_, w| unsafe { w.pl().bits(priority.bits()) }); - } + #[inline(always)] + fn set_priority(&mut self, priority: config::Priority) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = &unsafe { &*I::ptr() }.[](); + dma_ch.cr().modify(|_, w| unsafe { w.pl().bits(priority.bits()) }); + } - #[inline(always)] - fn disable_interrupts(&mut self) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dmacr = &unsafe { &*I::ptr() }.$chX().cr; - dmacr.modify(|_, w| w - .tcie().clear_bit() - .teie().clear_bit() - .htie().clear_bit()); - let _ = dmacr.read(); - let _ = dmacr.read(); // Delay 2 peripheral clocks - } + #[inline(always)] + fn disable_interrupts(&mut self) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dmacr = &unsafe { &*I::ptr() }.[]().cr(); + dmacr.modify(|_, w| w + .tcie().clear_bit() + .teie().clear_bit() + .htie().clear_bit()); + let _ = dmacr.read(); + let _ = dmacr.read(); // Delay 2 peripheral clocks + } - #[inline(always)] - fn enable_interrupts(&mut self, interrupt: Self::Interrupts) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = &unsafe { &*I::ptr() }.$chX(); - dma_ch.cr.modify(|_, w| w - .tcie().bit(interrupt.transfer_complete) - .teie().bit(interrupt.transfer_error) - .htie().bit(interrupt.half_transfer) - ); - } + #[inline(always)] + fn enable_interrupts(&mut self, interrupt: Self::Interrupts) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = &unsafe { &*I::ptr() }.[](); + dma_ch.cr().modify(|_, w| w + .tcie().bit(interrupt.transfer_complete) + .teie().bit(interrupt.transfer_error) + .htie().bit(interrupt.half_transfer) + ); + } - #[inline(always)] - fn get_interrupts_enable() -> Self::Interrupts { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.$chX(); - let cr = dma_ch.cr.read(); + #[inline(always)] + fn get_interrupts_enable() -> Self::Interrupts { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.[](); + let cr = dma_ch.cr().read(); - DmaInterrupts { - transfer_complete: cr.tcie().bit_is_set(), - half_transfer: cr.htie().bit_is_set(), - transfer_error: cr.teie().bit_is_set() + DmaInterrupts { + transfer_complete: cr.tcie().bit_is_set(), + half_transfer: cr.htie().bit_is_set(), + transfer_error: cr.teie().bit_is_set() + } } - } - #[inline(always)] - fn set_transfer_complete_interrupt_enable(&mut self, transfer_complete_interrupt: bool) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dmacr = &unsafe { &*I::ptr() }.$chX().cr; - dmacr.modify(|_, w| w.tcie().bit(transfer_complete_interrupt)); - let _ = dmacr.read(); - let _ = dmacr.read(); // Delay 2 peripheral clocks - } + #[inline(always)] + fn set_transfer_complete_interrupt_enable(&mut self, transfer_complete_interrupt: bool) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dmacr = &unsafe { &*I::ptr() }.[]().cr(); + dmacr.modify(|_, w| w.tcie().bit(transfer_complete_interrupt)); + let _ = dmacr.read(); + let _ = dmacr.read(); // Delay 2 peripheral clocks + } - #[inline(always)] - fn set_transfer_error_interrupt_enable(&mut self, transfer_error_interrupt: bool) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dmacr = &unsafe { &*I::ptr() }.$chX().cr; - dmacr.modify(|_, w| w.teie().bit(transfer_error_interrupt)); - let _ = dmacr.read(); - let _ = dmacr.read(); // Delay 2 peripheral clocks - } + #[inline(always)] + fn set_transfer_error_interrupt_enable(&mut self, transfer_error_interrupt: bool) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dmacr = &unsafe { &*I::ptr() }.[]().cr(); + dmacr.modify(|_, w| w.teie().bit(transfer_error_interrupt)); + let _ = dmacr.read(); + let _ = dmacr.read(); // Delay 2 peripheral clocks + } - #[inline(always)] - fn set_half_transfer_interrupt_enable(&mut self, half_transfer_interrupt: bool) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dmacr = &unsafe { &*I::ptr() }.$chX().cr; - dmacr.modify(|_, w| w.htie().bit(half_transfer_interrupt)); - let _ = dmacr.read(); - let _ = dmacr.read(); // Delay 2 peripheral clocks - } + #[inline(always)] + fn set_half_transfer_interrupt_enable(&mut self, half_transfer_interrupt: bool) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dmacr = &unsafe { &*I::ptr() }.[]().cr(); + dmacr.modify(|_, w| w.htie().bit(half_transfer_interrupt)); + let _ = dmacr.read(); + let _ = dmacr.read(); // Delay 2 peripheral clocks + } - #[inline(always)] - fn get_half_transfer_flag() -> bool { - //NOTE(unsafe) Atomic read with no side effects - let dma = unsafe { &*I::ptr() }; - dma.isr.read().$htisr().bit_is_set() - } + #[inline(always)] + fn get_half_transfer_flag() -> bool { + //NOTE(unsafe) Atomic read with no side effects + let dma = unsafe { &*I::ptr() }; + dma.isr().read().[]().bit_is_set() + } - #[inline(always)] - fn clear_half_transfer_interrupt(&mut self) { - //NOTE(unsafe) Atomic write with no side-effects and we only access the bits - // that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; - dma.ifcr.write(|w| w.$htif().set_bit()); - let _ = dma.isr.read(); - let _ = dma.isr.read(); // Delay 2 peripheral clocks - } + #[inline(always)] + fn clear_half_transfer_interrupt(&mut self) { + //NOTE(unsafe) Atomic write with no side-effects and we only access the bits + // that belongs to the StreamX + let dma = unsafe { &*I::ptr() }; + dma.ifcr().write(|w| w.[]().set_bit()); + let _ = dma.isr().read(); + let _ = dma.isr().read(); // Delay 2 peripheral clocks + } - #[inline(always)] - unsafe fn set_peripheral_address(&mut self, value: u32) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.$chX(); - dma_ch.par.write(|w| w.pa().bits(value)); - } + #[inline(always)] + unsafe fn set_peripheral_address(&mut self, value: u32) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.[](); + dma_ch.par().write(|w| w.pa().bits(value)); + } - #[inline(always)] - unsafe fn set_memory_address(&mut self, value: u32) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.$chX(); - dma_ch.mar.write(|w| w.ma().bits(value) ); - } + #[inline(always)] + unsafe fn set_memory_address(&mut self, value: u32) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.[](); + dma_ch.mar().write(|w| w.ma().bits(value) ); + } - #[inline(always)] - fn get_memory_address(&self) -> u32 { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.$chX(); - dma_ch.mar.read().ma().bits() - } + #[inline(always)] + fn get_memory_address(&self) -> u32 { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.[](); + dma_ch.mar().read().ma().bits() + } - #[inline(always)] - fn set_number_of_transfers(&mut self, value: u16) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.$chX(); - dma_ch.ndtr.write(|w| unsafe {w.ndt().bits(value) }); - } + #[inline(always)] + fn set_number_of_transfers(&mut self, value: u16) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.[](); + dma_ch.ndtr().write(|w| unsafe {w.ndt().bits(value) }); + } - #[inline(always)] - fn get_number_of_transfers() -> u16 { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.$chX(); - dma_ch.ndtr.read().ndt().bits() - } - #[inline(always)] - unsafe fn set_memory_size(&mut self, size: u8) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.$chX(); - dma_ch.cr.modify(|_, w| w.msize().bits(size)); - } + #[inline(always)] + fn get_number_of_transfers() -> u16 { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.[](); + dma_ch.ndtr().read().ndt().bits() + } + #[inline(always)] + unsafe fn set_memory_size(&mut self, size: u8) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.[](); + dma_ch.cr().modify(|_, w| w.msize().bits(size)); + } - #[inline(always)] - unsafe fn set_peripheral_size(&mut self, size: u8) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.$chX(); - dma_ch.cr.modify(|_, w| w.psize().bits(size)); - } + #[inline(always)] + unsafe fn set_peripheral_size(&mut self, size: u8) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.[](); + dma_ch.cr().modify(|_, w| w.psize().bits(size)); + } - #[inline(always)] - fn set_memory_increment(&mut self, increment: bool) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.$chX(); - dma_ch.cr.modify(|_, w| w.minc().bit(increment)); - } + #[inline(always)] + fn set_memory_increment(&mut self, increment: bool) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.[](); + dma_ch.cr().modify(|_, w| w.minc().bit(increment)); + } - #[inline(always)] - fn set_peripheral_increment(&mut self, increment: bool) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.$chX(); - dma_ch.cr.modify(|_, w| w.pinc().bit(increment)); - } + #[inline(always)] + fn set_peripheral_increment(&mut self, increment: bool) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.[](); + dma_ch.cr().modify(|_, w| w.pinc().bit(increment)); + } - #[inline(always)] - fn set_direction(&mut self, direction: DmaDirection) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.$chX(); - dma_ch.cr.modify(|_, w| { - match direction { - DmaDirection::PeripheralToMemory => - w.dir().clear_bit().mem2mem().clear_bit(), - DmaDirection::MemoryToPeripheral => - w.dir().set_bit().mem2mem().clear_bit(), - DmaDirection::MemoryToMemory => - w.mem2mem().set_bit().dir().clear_bit(), - } - }); - } + #[inline(always)] + fn set_direction(&mut self, direction: DmaDirection) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.[](); + dma_ch.cr().modify(|_, w| { + match direction { + DmaDirection::PeripheralToMemory => + w.dir().clear_bit().mem2mem().clear_bit(), + DmaDirection::MemoryToPeripheral => + w.dir().set_bit().mem2mem().clear_bit(), + DmaDirection::MemoryToMemory => + w.mem2mem().set_bit().dir().clear_bit(), + } + }); + } - #[inline(always)] - fn set_circular_buffer(&mut self, circular_buffer: bool) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.$chX(); - dma_ch.cr.modify(|_, w| w.circ().bit(circular_buffer)); - } - } - - impl $name { - #[inline(always)] - pub fn clear_half_transfer_interrupt(&mut self) { - //NOTE(unsafe) Atomic write with no side-effects and we only access the bits - // that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; - dma.ifcr.write(|w| w.$htif().set_bit()); - let _ = dma.isr.read(); - let _ = dma.isr.read(); // Delay 2 peripheral clocks + #[inline(always)] + fn set_circular_buffer(&mut self, circular_buffer: bool) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.[](); + dma_ch.cr().modify(|_, w| w.circ().bit(circular_buffer)); + } } - #[inline(always)] - pub fn get_half_transfer_flag() -> bool { - //NOTE(unsafe) Atomic read with no side effects - let dma = unsafe { &*I::ptr() }; - dma.isr.read().$htisr().bit_is_set() - } + impl $name { + #[inline(always)] + pub fn clear_half_transfer_interrupt(&mut self) { + //NOTE(unsafe) Atomic write with no side-effects and we only access the bits + // that belongs to the StreamX + let dma = unsafe { &*I::ptr() }; + dma.ifcr().write(|w| w.[]().set_bit()); + let _ = dma.isr().read(); + let _ = dma.isr().read(); // Delay 2 peripheral clocks + } - #[inline(always)] - pub fn set_half_transfer_interrupt_enable(&mut self, half_transfer_interrupt: bool) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dmacr = &unsafe { &*I::ptr() }.$chX().cr; - dmacr.modify(|_, w| w.htie().bit(half_transfer_interrupt)); - let _ = dmacr.read(); - let _ = dmacr.read(); // Delay 2 peripheral clocks + #[inline(always)] + pub fn get_half_transfer_flag() -> bool { + //NOTE(unsafe) Atomic read with no side effects + let dma = unsafe { &*I::ptr() }; + dma.isr().read().[]().bit_is_set() + } + + #[inline(always)] + pub fn set_half_transfer_interrupt_enable(&mut self, half_transfer_interrupt: bool) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dmacr = &unsafe { &*I::ptr() }.[]().cr(); + dmacr.modify(|_, w| w.htie().bit(half_transfer_interrupt)); + let _ = dmacr.read(); + let _ = dmacr.read(); // Delay 2 peripheral clocks + } } - } - )+ + )+ + } }; } -// Cat 3 and 4 devices -#[cfg(any( - feature = "stm32g471", - feature = "stm32g473", - feature = "stm32g474", - feature = "stm32g483", - feature = "stm32g484", - feature = "stm32g491", - feature = "stm32g4a1", -))] + dma_stream!( // Note: the field names start from one, unlike the RM where they start from // zero. May need updating if it gets fixed upstream. ( - Stream0, 0, - regs => ch1, - fields => tcif1, htif1, teif1, gif1, tcif1, htif1, teif1, gif1, - dmamux => c0cr, c8cr, - ), - ( - Stream1, 1, - regs => ch2, - fields => tcif2, htif2, teif2, gif2, tcif2, htif2, teif2, gif2, - dmamux => c1cr, c9cr, - ), - ( - Stream2, 2, - regs => ch3, - fields => tcif3, htif3, teif3, gif3, tcif3, htif3, teif3, gif3, - dmamux => c2cr, c10cr, + Stream0, 0, 1 ), ( - Stream3, 3, - regs => ch4, - fields => tcif4, htif4, teif4, gif4, tcif4, htif4, teif4, gif4, - dmamux => c3cr, c11cr, + Stream1, 1, 2 ), ( - Stream4, 4, - regs => ch5, - fields => tcif5, htif5, teif5, gif5, tcif5, htif5, teif5, gif5, - dmamux => c4cr, c12cr, + Stream2, 2, 3 ), ( - Stream5, 5, - regs => ch6, - fields => tcif6, htif6, teif6, gif6, tcif6, htif6, teif6, gif6, - dmamux => c5cr, c13cr, + Stream3, 3, 4 ), ( - Stream6, 6, - regs => ch7, - fields => tcif7, htif7, teif7, gif7, tcif7, htif7, teif7, gif7, - dmamux => c6cr, c14cr, + Stream4, 4, 5 ), ( - Stream7, 7, - regs => ch8, - fields => tcif8, htif8, teif8, gif8, tcif8, htif8, teif8, gif8, - dmamux => c7cr, c15cr, + Stream5, 5, 6 ), ); -// Cat 2 devices -#[cfg(any(feature = "stm32g431", feature = "stm32g441",))] +// Cat 3 and 4 devices +#[cfg(any( + feature = "stm32g471", + feature = "stm32g473", + feature = "stm32g474", + feature = "stm32g483", + feature = "stm32g484", + feature = "stm32g491", + feature = "stm32g4a1", +))] dma_stream!( // Note: the field names start from one, unlike the RM where they start from // zero. May need updating if it gets fixed upstream. ( - Stream0, 0, - regs => ccr1, cpar1, cmar1, cndtr1, - fields => tcif1, htif1, teif1, gif1, tcif1, htif1, teif1, gif1, - dmamux => c0cr, c6cr, - ), - ( - Stream1, 1, - regs => ccr2, cpar2, cmar2, cndtr2, - fields => tcif2, htif2, teif2, gif2, tcif2, htif2, teif2, gif2, - dmamux => c1cr, c7cr, - ), - ( - Stream2, 2, - regs => ccr3, cpar3, cmar3, cndtr3, - fields => tcif3, htif3, teif3, gif3, tcif3, htif3, teif3, gif3, - dmamux => c2cr, c8cr, - ), - ( - Stream3, 3, - regs => ccr4, cpar4, cmar4, cndtr4, - fields => tcif4, htif4, teif4, gif4, tcif4, htif4, teif4, gif4, - dmamux => c3cr, c9cr, - ), - ( - Stream4, 4, - regs => ccr5, cpar5, cmar5, cndtr5, - fields => tcif5, htif5, teif5, gif5, tcif5, htif5, teif5, gif5, - dmamux => c4cr, c10cr, + Stream6, 6, 7 ), ( - Stream5, 5, - regs => ccr6, cpar6, cmar6, cndtr6, - fields => tcif6, htif6, teif6, gif6, tcif6, htif6, teif6, gif6, - dmamux => c5cr, c11cr, + Stream7, 7, 8 ), ); diff --git a/src/exti.rs b/src/exti.rs index bbdaffb7..7249a6db 100644 --- a/src/exti.rs +++ b/src/exti.rs @@ -88,14 +88,18 @@ impl ExtiExt for EXTI { let mask = 1 << line; match edge { SignalEdge::Rising => { - self.rtsr1.modify(|r, w| unsafe { w.bits(r.bits() | mask) }); + self.rtsr1() + .modify(|r, w| unsafe { w.bits(r.bits() | mask) }); } SignalEdge::Falling => { - self.ftsr1.modify(|r, w| unsafe { w.bits(r.bits() | mask) }); + self.ftsr1() + .modify(|r, w| unsafe { w.bits(r.bits() | mask) }); } SignalEdge::RisingFalling => { - self.rtsr1.modify(|r, w| unsafe { w.bits(r.bits() | mask) }); - self.ftsr1.modify(|r, w| unsafe { w.bits(r.bits() | mask) }); + self.rtsr1() + .modify(|r, w| unsafe { w.bits(r.bits() | mask) }); + self.ftsr1() + .modify(|r, w| unsafe { w.bits(r.bits() | mask) }); } } self.wakeup(ev); @@ -104,10 +108,10 @@ impl ExtiExt for EXTI { fn wakeup(&self, ev: Event) { match ev as u8 { line if line < 32 => self - .imr1 + .imr1() .modify(|r, w| unsafe { w.bits(r.bits() | 1 << line) }), line => self - .imr2 + .imr2() .modify(|r, w| unsafe { w.bits(r.bits() | 1 << (line - 32)) }), } } @@ -117,15 +121,19 @@ impl ExtiExt for EXTI { match ev as u8 { line if line < 32 => { let mask = !(1 << line); - self.imr1.modify(|r, w| unsafe { w.bits(r.bits() & mask) }); + self.imr1() + .modify(|r, w| unsafe { w.bits(r.bits() & mask) }); if line <= 18 { - self.rtsr1.modify(|r, w| unsafe { w.bits(r.bits() & mask) }); - self.ftsr1.modify(|r, w| unsafe { w.bits(r.bits() & mask) }); + self.rtsr1() + .modify(|r, w| unsafe { w.bits(r.bits() & mask) }); + self.ftsr1() + .modify(|r, w| unsafe { w.bits(r.bits() & mask) }); } } line => { let mask = !(1 << (line - 32)); - self.imr2.modify(|r, w| unsafe { w.bits(r.bits() & mask) }) + self.imr2() + .modify(|r, w| unsafe { w.bits(r.bits() & mask) }) } } } @@ -136,13 +144,13 @@ impl ExtiExt for EXTI { return false; } let mask = 1 << line; - self.pr1.read().bits() & mask != 0 + self.pr1().read().bits() & mask != 0 } fn unpend(&self, ev: Event) { let line = ev as u8; if line <= 18 { - self.pr1.modify(|_, w| unsafe { w.bits(1 << line) }); + self.pr1().modify(|_, w| unsafe { w.bits(1 << line) }); } } } diff --git a/src/fdcan.rs b/src/fdcan.rs index 24e42088..d0b9b540 100644 --- a/src/fdcan.rs +++ b/src/fdcan.rs @@ -286,9 +286,9 @@ where fn enter_init_mode(&mut self) { let can = self.registers(); - can.cccr.modify(|_, w| w.init().set_bit()); - while can.cccr.read().init().bit_is_clear() {} - can.cccr.modify(|_, w| w.cce().set_bit()); + can.cccr().modify(|_, w| w.init().set_bit()); + while can.cccr().read().init().bit_is_clear() {} + can.cccr().modify(|_, w| w.cce().set_bit()); } /// Returns the current FDCAN config settings @@ -311,20 +311,20 @@ where self.set_bus_monitoring_mode(mon); let can = self.registers(); - can.test.modify(|_, w| w.lbck().bit(lbck)); + can.test().modify(|_, w| w.lbck().bit(lbck)); } /// Enables or disables silent mode: Disconnects the TX signal from the pin. #[inline] fn set_bus_monitoring_mode(&mut self, enabled: bool) { let can = self.registers(); - can.cccr.modify(|_, w| w.mon().bit(enabled)); + can.cccr().modify(|_, w| w.mon().bit(enabled)); } #[inline] fn set_restricted_operations(&mut self, enabled: bool) { let can = self.registers(); - can.cccr.modify(|_, w| w.asm().bit(enabled)); + can.cccr().modify(|_, w| w.asm().bit(enabled)); } #[inline] @@ -335,14 +335,14 @@ where #[inline] fn set_test_mode(&mut self, enabled: bool) { let can = self.registers(); - can.cccr.modify(|_, w| w.test().bit(enabled)); + can.cccr().modify(|_, w| w.test().bit(enabled)); } #[inline] fn set_power_down_mode(&mut self, enabled: bool) { let can = self.registers(); - can.cccr.modify(|_, w| w.csr().bit(enabled)); - while can.cccr.read().csa().bit() != enabled {} + can.cccr().modify(|_, w| w.csr().bit(enabled)); + while can.cccr().read().csa().bit() != enabled {} } /// Enable/Disable the specific Interrupt Line @@ -350,8 +350,8 @@ where pub fn enable_interrupt_line(&mut self, line: InterruptLine, enabled: bool) { let can = self.registers(); match line { - InterruptLine::_0 => can.ile.modify(|_, w| w.eint1().bit(enabled)), - InterruptLine::_1 => can.ile.modify(|_, w| w.eint0().bit(enabled)), + InterruptLine::_0 => can.ile().modify(|_, w| w.eint1().bit(enabled)), + InterruptLine::_1 => can.ile().modify(|_, w| w.eint0().bit(enabled)), } } @@ -422,7 +422,7 @@ where /// Retrieve the current protocol status pub fn get_protocol_status(&self) -> ProtocolStatus { - let psr = self.registers().psr.read(); + let psr = self.registers().psr().read(); ProtocolStatus { activity: Activity::try_from(0 /*psr.act().bits()*/).unwrap(), //TODO: stm32g4 does not allow reading from this register transmitter_delay_comp: psr.tdcv().bits(), @@ -526,9 +526,9 @@ where { I::enable(&rcc.rb); - if rcc.rb.ccipr.read().fdcansel().is_hse() { + if rcc.rb.ccipr().read().fdcansel().is_hse() { // Select P clock as FDCAN clock source - rcc.rb.ccipr.modify(|_, w| { + rcc.rb.ccipr().modify(|_, w| { // This is sound, as `FdCanClockSource` only contains valid values for this field. unsafe { w.fdcansel().bits(FdCanClockSource::PCLK as u8); @@ -541,7 +541,7 @@ where let can = Self::create_can(FdCanConfig::default(), can_instance); let reg = can.registers(); - assert!(reg.endn.read().bits() == 0x87654321_u32); + assert!(reg.endn().read().bits() == 0x87654321_u32); can } @@ -562,7 +562,7 @@ where TX: sealed::Tx, RX: sealed::Rx, { - rcc.rb.ccipr.modify(|_, w| { + rcc.rb.ccipr().modify(|_, w| { // This is sound, as `FdCanClockSource` only contains valid values for this field. unsafe { w.fdcansel().bits(clock_source as u8); @@ -588,17 +588,17 @@ where // set TxBuffer to Queue Mode; // TODO: don't require this. - // can.txbc.write(|w| w.tfqm().set_bit()); + // can.txbc().write(|w| w.tfqm().set_bit()); //FIXME: stm32g4 has the wrong layout here! //We should be able to use the above, //But right now, we just set the 24th bit. - can.txbc.write(|w| unsafe { w.bits(1_u32 << 24) }); + can.txbc().write(|w| unsafe { w.bits(1_u32 << 24) }); // set standard filters list size to 28 // set extended filters list size to 8 // REQUIRED: we use the memory map as if these settings are set // instead of re-calculating them. - can.rxgfc.modify(|_, w| unsafe { + can.rxgfc().modify(|_, w| unsafe { w.lse() .bits(EXTENDED_FILTER_MAX) .lss() @@ -635,9 +635,9 @@ where self.apply_config(self.control.config); let can = self.registers(); - can.cccr.modify(|_, w| w.cce().clear_bit()); - can.cccr.modify(|_, w| w.init().clear_bit()); - while can.cccr.read().init().bit_is_set() {} + can.cccr().modify(|_, w| w.cce().clear_bit()); + can.cccr().modify(|_, w| w.init().clear_bit()); + while can.cccr().read().init().bit_is_set() {} } /// Moves out of ConfigMode and into InternalLoopbackMode @@ -736,7 +736,7 @@ where self.control.config.nbtr = btr; let can = self.registers(); - can.nbtp.write(|w| unsafe { + can.nbtp().write(|w| unsafe { w.nbrp() .bits(btr.nbrp() - 1) .ntseg1() @@ -755,7 +755,7 @@ where self.control.config.dbtr = btr; let can = self.registers(); - can.dbtp.write(|w| unsafe { + can.dbtp().write(|w| unsafe { w.dbrp() .bits(btr.dbrp() - 1) .dtseg1() @@ -776,7 +776,7 @@ where #[inline] pub fn set_automatic_retransmit(&mut self, enabled: bool) { let can = self.registers(); - can.cccr.modify(|_, w| w.dar().bit(!enabled)); + can.cccr().modify(|_, w| w.dar().bit(!enabled)); self.control.config.automatic_retransmit = enabled; } @@ -785,7 +785,7 @@ where #[inline] pub fn set_transmit_pause(&mut self, enabled: bool) { let can = self.registers(); - can.cccr.modify(|_, w| w.dar().bit(!enabled)); + can.cccr().modify(|_, w| w.dar().bit(!enabled)); self.control.config.transmit_pause = enabled; } @@ -794,7 +794,7 @@ where #[inline] pub fn set_non_iso_mode(&mut self, enabled: bool) { let can = self.registers(); - can.cccr.modify(|_, w| w.niso().bit(enabled)); + can.cccr().modify(|_, w| w.niso().bit(enabled)); self.control.config.non_iso_mode = enabled; } @@ -803,7 +803,7 @@ where #[inline] pub fn set_edge_filtering(&mut self, enabled: bool) { let can = self.registers(); - can.cccr.modify(|_, w| w.efbi().bit(enabled)); + can.cccr().modify(|_, w| w.efbi().bit(enabled)); self.control.config.edge_filtering = enabled; } @@ -818,7 +818,7 @@ where }; let can = self.registers(); - can.cccr.modify(|_, w| w.fdoe().bit(fdoe).brse().bit(brse)); + can.cccr().modify(|_, w| w.fdoe().bit(fdoe).brse().bit(brse)); self.control.config.frame_transmit = fts; } @@ -829,7 +829,7 @@ where pub fn set_interrupt_line_config(&mut self, l0int: Interrupts) { let can = self.registers(); - can.ils.modify(|_, w| unsafe { w.bits(l0int.bits()) }); + can.ils().modify(|_, w| unsafe { w.bits(l0int.bits()) }); self.control.config.interrupt_line_config = l0int; } @@ -839,7 +839,7 @@ where pub fn set_protocol_exception_handling(&mut self, enabled: bool) { let can = self.registers(); - can.cccr.modify(|_, w| w.pxhd().bit(!enabled)); + can.cccr().modify(|_, w| w.pxhd().bit(!enabled)); self.control.config.protocol_exception_handling = enabled; } @@ -850,7 +850,7 @@ where pub fn set_clock_divider(&mut self, div: ClockDivider) { let can = self.registers(); - can.ckdiv.write(|w| unsafe { w.pdiv().bits(div as u8) }); + can.ckdiv().write(|w| unsafe { w.pdiv().bits(div as u8) }); self.control.config.clock_divider = div; } @@ -873,7 +873,7 @@ where /// Configures the global filter settings #[inline] pub fn set_global_filter(&mut self, filter: GlobalFilter) { - self.registers().rxgfc.modify(|_, w| { + self.registers().rxgfc().modify(|_, w| { unsafe { w.anfs() .bits(filter.handle_standard_frames as u8) @@ -993,7 +993,7 @@ where pub fn get_receive_pin(&mut self) -> bool { let can = self.registers(); - can.test.read().rx().bit_is_set() + can.test().read().rx().bit_is_set() } /// Sets the state of the transmit pin according to TestTransmitPinState @@ -1001,7 +1001,7 @@ where let can = self.registers(); //SAFE: state has all possible values, and this can only occur in TestMode - can.test.modify(|_, w| unsafe { w.tx().bits(state as u8) }); + can.test().modify(|_, w| unsafe { w.tx().bits(state as u8) }); } } @@ -1159,10 +1159,10 @@ where #[inline] pub fn error_counters(&self) -> ErrorCounters { let can = self.registers(); - let cel: u8 = can.ecr.read().cel().bits(); - let rp: bool = can.ecr.read().rp().bit(); - let rec: u8 = can.ecr.read().rec().bits(); - let tec: u8 = can.ecr.read().tec().bits(); + let cel: u8 = can.ecr().read().cel().bits(); + let rp: bool = can.ecr().read().rp().bit(); + let rec: u8 = can.ecr().read().rec().bits(); + let tec: u8 = can.ecr().read().tec().bits(); ErrorCounters { can_errors: cel, @@ -1177,28 +1177,28 @@ where /// Returns the current FdCan Timestamp counter #[inline] pub fn timestamp(&self) -> u16 { - self.registers().tscv.read().tsc().bits() + self.registers().tscv().read().tsc().bits() } /// Check if the interrupt is triggered #[inline] pub fn has_interrupt(&mut self, interrupt: Interrupt) -> bool { let can = self.registers(); - can.ir.read().bits() & (interrupt as u32) > 0 + can.ir().read().bits() & (interrupt as u32) > 0 } /// Clear specified interrupt #[inline] pub fn clear_interrupt(&mut self, interrupt: Interrupt) { let can = self.registers(); - can.ir.write(|w| unsafe { w.bits(interrupt as u32) }); + can.ir().write(|w| unsafe { w.bits(interrupt as u32) }); } /// Clear specified interrupts #[inline] pub fn clear_interrupts(&mut self, interrupts: Interrupts) { let can = self.registers(); - can.ir.write(|w| unsafe { w.bits(interrupts.bits()) }); + can.ir().write(|w| unsafe { w.bits(interrupts.bits()) }); } } @@ -1310,7 +1310,7 @@ where } } else { // Read the Write Pointer - let idx = can.txfqs.read().tfqpi().bits(); + let idx = can.txfqs().read().tfqpi().bits(); (Mailbox::new(idx), None) }; @@ -1323,7 +1323,7 @@ where /// Returns if the tx queue is able to accept new messages without having to cancel an existing one #[inline] pub fn tx_queue_is_full(&self) -> bool { - self.registers().txfqs.read().tfqf().bit() + self.registers().txfqs().read().tfqf().bit() } /// Returns `Ok` when the mailbox is free or if it contains pending frame with a @@ -1405,13 +1405,13 @@ where let idx = 1u8 << idx; // Abort Request - can.txbcr.write(|w| unsafe { w.cr().bits(idx) }); + can.txbcr().write(|w| unsafe { w.cr().bits(idx) }); // Wait for the abort request to be finished. loop { - if can.txbcf.read().cf().bits() & idx != 0 { + if can.txbcf().read().cf().bits() & idx != 0 { // Return false when a transmission has occured - break can.txbto.read().to().bits() & idx == 0; + break can.txbto().read().to().bits() & idx == 0; } } } else { @@ -1425,28 +1425,28 @@ where let idx: u8 = idx.into(); let idx = 1u8 << idx; - can.txbrp.read().trp().bits() & idx != 0 + can.txbrp().read().trp().bits() & idx != 0 } /// Returns `true` if no frame is pending for transmission. #[inline] pub fn is_idle(&self) -> bool { let can = self.registers(); - can.txbrp.read().trp().bits() == 0x0 + can.txbrp().read().trp().bits() == 0x0 } /// Clears the transmission complete flag. #[inline] pub fn clear_transmission_completed_flag(&mut self) { let can = self.registers(); - can.ir.write(|w| w.tc().set_bit()); + can.ir().write(|w| w.tc().set_bit()); } /// Clears the transmission cancelled flag. #[inline] pub fn clear_transmission_cancelled_flag(&mut self) { let can = self.registers(); - can.ir.write(|w| w.tcf().set_bit()); + can.ir().write(|w| w.tcf().set_bit()); } } @@ -1570,8 +1570,8 @@ where fn has_overrun(&self) -> bool { let can = self.registers(); match FIFONR::NR { - 0 => can.rxf0s.read().rf0l().bit(), - 1 => can.rxf1s.read().rf1l().bit(), + 0 => can.rxf0s().read().rf0l().bit(), + 1 => can.rxf1s().read().rf1l().bit(), _ => unreachable!(), } } @@ -1581,8 +1581,8 @@ where pub fn rx_fifo_is_empty(&self) -> bool { let can = self.registers(); match FIFONR::NR { - 0 => can.rxf0s.read().f0fl().bits() == 0, - 1 => can.rxf1s.read().f1fl().bits() == 0, + 0 => can.rxf0s().read().f0fl().bits() == 0, + 1 => can.rxf1s().read().f1fl().bits() == 0, _ => unreachable!(), } } @@ -1595,8 +1595,8 @@ where let can = self.registers(); match FIFONR::NR { - 0 => can.rxf0a.write(|w| unsafe { w.f0ai().bits(idx.into()) }), - 1 => can.rxf1a.write(|w| unsafe { w.f1ai().bits(idx.into()) }), + 0 => can.rxf0a().write(|w| unsafe { w.f0ai().bits(idx.into()) }), + 1 => can.rxf1a().write(|w| unsafe { w.f1ai().bits(idx.into()) }), _ => unreachable!(), } } @@ -1605,8 +1605,8 @@ where fn get_rx_mailbox(&self) -> Mailbox { let can = self.registers(); let idx = match FIFONR::NR { - 0 => can.rxf0s.read().f0gi().bits(), - 1 => can.rxf1s.read().f1gi().bits(), + 0 => can.rxf0s().read().f0gi().bits(), + 1 => can.rxf1s().read().f1gi().bits(), _ => unreachable!(), }; Mailbox::new(idx) diff --git a/src/flash.rs b/src/flash.rs index 26b60484..59cc9b9d 100644 --- a/src/flash.rs +++ b/src/flash.rs @@ -465,7 +465,7 @@ pub struct ACR { impl ACR { pub(crate) fn acr(&mut self) -> &flash::ACR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).acr } + unsafe { &(*FLASH::ptr()).acr() } } } @@ -478,7 +478,7 @@ pub struct CR { impl CR { pub(crate) fn cr(&mut self) -> &flash::CR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).cr } + unsafe { &(*FLASH::ptr()).cr() } } } @@ -491,7 +491,7 @@ pub struct ECCR { impl ECCR { pub(crate) fn eccr(&mut self) -> &flash::ECCR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).eccr } + unsafe { &(*FLASH::ptr()).eccr() } } } @@ -504,7 +504,7 @@ pub struct KEYR { impl KEYR { pub(crate) fn keyr(&mut self) -> &flash::KEYR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).keyr } + unsafe { &(*FLASH::ptr()).keyr() } } } @@ -517,7 +517,7 @@ pub struct OPTKEYR { impl OPTKEYR { pub(crate) fn optkeyr(&mut self) -> &flash::OPTKEYR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).optkeyr } + unsafe { &(*FLASH::ptr()).optkeyr() } } } @@ -530,7 +530,7 @@ pub struct OPTR { impl OPTR { pub(crate) fn optr(&mut self) -> &flash::OPTR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).optr } + unsafe { &(*FLASH::ptr()).optr() } } } @@ -543,7 +543,7 @@ pub struct PCROP1SR { impl PCROP1SR { pub(crate) fn pcrop1sr(&mut self) -> &flash::PCROP1SR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).pcrop1sr } + unsafe { &(*FLASH::ptr()).pcrop1sr() } } } @@ -556,7 +556,7 @@ pub struct PCROP1ER { impl PCROP1ER { pub(crate) fn pcrop1er(&mut self) -> &flash::PCROP1ER { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).pcrop1er } + unsafe { &(*FLASH::ptr()).pcrop1er() } } } @@ -569,7 +569,7 @@ pub struct PDKEYR { impl PDKEYR { pub(crate) fn pdkeyr(&mut self) -> &flash::PDKEYR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).pdkeyr } + unsafe { &(*FLASH::ptr()).pdkeyr() } } } @@ -582,7 +582,7 @@ pub struct SEC1R { impl SEC1R { pub(crate) fn sec1r(&mut self) -> &flash::SEC1R { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).sec1r } + unsafe { &(*FLASH::ptr()).sec1r() } } } @@ -595,7 +595,7 @@ pub struct SR { impl SR { pub(crate) fn sr(&mut self) -> &flash::SR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).sr } + unsafe { &(*FLASH::ptr()).sr() } } } @@ -608,7 +608,7 @@ pub struct WRP1AR { impl WRP1AR { pub(crate) fn wrp1ar(&mut self) -> &flash::WRP1AR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).wrp1ar } + unsafe { &(*FLASH::ptr()).wrp1ar() } } } @@ -621,6 +621,6 @@ pub struct WRP1BR { impl WRP1BR { pub(crate) fn wrp1br(&mut self) -> &flash::WRP1BR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).wrp1br } + unsafe { &(*FLASH::ptr()).wrp1br() } } } diff --git a/src/gpio.rs b/src/gpio.rs index bd43df0c..4d081cf0 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -99,22 +99,22 @@ macro_rules! exti_erased { let offset = 4 * (self.i % 4); match self.i { 0..=3 => { - syscfg.exticr1.modify(|r, w| unsafe { + syscfg.exticr1().modify(|r, w| unsafe { w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset)) }); } 4..=7 => { - syscfg.exticr2.modify(|r, w| unsafe { + syscfg.exticr2().modify(|r, w| unsafe { w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset)) }); } 8..=11 => { - syscfg.exticr3.modify(|r, w| unsafe { + syscfg.exticr3().modify(|r, w| unsafe { w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset)) }); } 12..=15 => { - syscfg.exticr4.modify(|r, w| unsafe { + syscfg.exticr4().modify(|r, w| unsafe { w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset)) }); } @@ -126,21 +126,21 @@ macro_rules! exti_erased { fn trigger_on_edge(&mut self, exti: &mut EXTI, edge: SignalEdge) { match edge { SignalEdge::Rising => { - exti.rtsr1 + exti.rtsr1() .modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) }); - exti.ftsr1 + exti.ftsr1() .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) }); } SignalEdge::Falling => { - exti.ftsr1 + exti.ftsr1() .modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) }); - exti.rtsr1 + exti.rtsr1() .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) }); } SignalEdge::RisingFalling => { - exti.rtsr1 + exti.rtsr1() .modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) }); - exti.ftsr1 + exti.ftsr1() .modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) }); } } @@ -148,24 +148,24 @@ macro_rules! exti_erased { /// Enable external interrupts from this pin. fn enable_interrupt(&mut self, exti: &mut EXTI) { - exti.imr1 + exti.imr1() .modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) }); } /// Disable external interrupts from this pin fn disable_interrupt(&mut self, exti: &mut EXTI) { - exti.imr1 + exti.imr1() .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) }); } /// Clear the interrupt pending bit for this pin fn clear_interrupt_pending_bit(&mut self) { - unsafe { (*EXTI::ptr()).pr1.write(|w| w.bits(1 << self.i)) }; + unsafe { (*EXTI::ptr()).pr1().write(|w| w.bits(1 << self.i)) }; } /// Reads the interrupt pending bit for this pin fn check_interrupt(&self) -> bool { - unsafe { ((*EXTI::ptr()).pr1.read().bits() & (1 << self.i)) != 0 } + unsafe { ((*EXTI::ptr()).pr1().read().bits() & (1 << self.i)) != 0 } } } }; @@ -177,7 +177,7 @@ macro_rules! exti { /// Configure EXTI Line $i to trigger from this pin. fn make_interrupt_source(&mut self, syscfg: &mut SysCfg) { let offset = 4 * ($i % 4); - syscfg.$exticri.modify(|r, w| unsafe { + syscfg.$exticri().modify(|r, w| unsafe { let mut exticr = r.bits(); exticr = (exticr & !(0xf << offset)) | ($extigpionr << offset); //FIXME: clears other pins w.bits(exticr) @@ -188,21 +188,21 @@ macro_rules! exti { fn trigger_on_edge(&mut self, exti: &mut EXTI, edge: SignalEdge) { match edge { SignalEdge::Rising => { - exti.rtsr1 + exti.rtsr1() .modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) }); - exti.ftsr1 + exti.ftsr1() .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) }); } SignalEdge::Falling => { - exti.ftsr1 + exti.ftsr1() .modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) }); - exti.rtsr1 + exti.rtsr1() .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) }); } SignalEdge::RisingFalling => { - exti.rtsr1 + exti.rtsr1() .modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) }); - exti.ftsr1 + exti.ftsr1() .modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) }); } } @@ -210,24 +210,24 @@ macro_rules! exti { /// Enable external interrupts from this pin. fn enable_interrupt(&mut self, exti: &mut EXTI) { - exti.imr1 + exti.imr1() .modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) }); } /// Disable external interrupts from this pin fn disable_interrupt(&mut self, exti: &mut EXTI) { - exti.imr1 + exti.imr1() .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) }); } /// Clear the interrupt pending bit for this pin fn clear_interrupt_pending_bit(&mut self) { - unsafe { (*EXTI::ptr()).pr1.write(|w| w.bits(1 << $i)) }; + unsafe { (*EXTI::ptr()).pr1().write(|w| w.bits(1 << $i)) }; } /// Reads the interrupt pending bit for this pin fn check_interrupt(&self) -> bool { - unsafe { ((*EXTI::ptr()).pr1.read().bits() & (1 << $i)) != 0 } + unsafe { ((*EXTI::ptr()).pr1().read().bits() & (1 << $i)) != 0 } } } }; @@ -257,7 +257,7 @@ macro_rules! gpio { type Parts = Parts; fn split(self, rcc: &mut Rcc) -> Parts { - rcc.rb.ahb2enr.modify(|_, w| w.$iopxenr().set_bit()); + rcc.rb.ahb2enr().modify(|_, w| w.$iopxenr().set_bit()); Parts { $( $pxi: $PXi { _mode: PhantomData }, @@ -277,13 +277,13 @@ macro_rules! gpio { fn set_high(&mut self) -> Result<(), ()> { // NOTE(unsafe) atomic write to a stateless register - unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << self.i)) }; + unsafe { (*$GPIOX::ptr()).bsrr().write(|w| w.bits(1 << self.i)) }; Ok(()) } fn set_low(&mut self) -> Result<(), ()> { // NOTE(unsafe) atomic write to a stateless register - unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (self.i + 16))) }; + unsafe { (*$GPIOX::ptr()).bsrr().write(|w| w.bits(1 << (self.i + 16))) }; Ok(()) } } @@ -296,7 +296,7 @@ macro_rules! gpio { fn is_set_low(&self) -> Result { // NOTE(unsafe) atomic read with no side effects - let is_set_low = unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << self.i) == 0 }; + let is_set_low = unsafe { (*$GPIOX::ptr()).odr().read().bits() & (1 << self.i) == 0 }; Ok(is_set_low) } } @@ -314,7 +314,7 @@ macro_rules! gpio { fn is_low(&self) -> Result { // NOTE(unsafe) atomic read with no side effects - let is_low = unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 }; + let is_low = unsafe { (*$GPIOX::ptr()).idr().read().bits() & (1 << self.i) == 0 }; Ok(is_low) } } @@ -329,7 +329,7 @@ macro_rules! gpio { fn is_low(&self) -> Result { // NOTE(unsafe) atomic read with no side effects - let is_low = unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 }; + let is_low = unsafe { (*$GPIOX::ptr()).idr().read().bits() & (1 << self.i) == 0 }; Ok(is_low) } } @@ -385,10 +385,10 @@ macro_rules! gpio { let offset = 2 * $i; unsafe { let gpio = &(*$GPIOX::ptr()); - gpio.pupdr.modify(|r, w| { + gpio.pupdr().modify(|r, w| { w.bits(r.bits() & !(0b11 << offset)) }); - gpio.moder.modify(|r, w| { + gpio.moder().modify(|r, w| { w.bits(r.bits() & !(0b11 << offset)) }) }; @@ -400,10 +400,10 @@ macro_rules! gpio { let offset = 2 * $i; unsafe { let gpio = &(*$GPIOX::ptr()); - gpio.pupdr.modify(|r, w| { + gpio.pupdr().modify(|r, w| { w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset)) }); - gpio.moder.modify(|r, w| { + gpio.moder().modify(|r, w| { w.bits(r.bits() & !(0b11 << offset)) }) }; @@ -415,10 +415,10 @@ macro_rules! gpio { let offset = 2 * $i; unsafe { let gpio = &(*$GPIOX::ptr()); - gpio.pupdr.modify(|r, w| { + gpio.pupdr().modify(|r, w| { w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset)) }); - gpio.moder.modify(|r, w| { + gpio.moder().modify(|r, w| { w.bits(r.bits() & !(0b11 << offset)) }) }; @@ -430,10 +430,10 @@ macro_rules! gpio { let offset = 2 * $i; unsafe { let gpio = &(*$GPIOX::ptr()); - gpio.pupdr.modify(|r, w| { + gpio.pupdr().modify(|r, w| { w.bits(r.bits() & !(0b11 << offset)) }); - gpio.moder.modify(|r, w| { + gpio.moder().modify(|r, w| { w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset)) }); } @@ -445,13 +445,13 @@ macro_rules! gpio { let offset = 2 * $i; unsafe { let gpio = &(*$GPIOX::ptr()); - gpio.pupdr.modify(|r, w| { + gpio.pupdr().modify(|r, w| { w.bits(r.bits() & !(0b11 << offset)) }); - gpio.otyper.modify(|r, w| { + gpio.otyper().modify(|r, w| { w.bits(r.bits() | (0b1 << $i)) }); - gpio.moder.modify(|r, w| { + gpio.moder().modify(|r, w| { w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset)) }) }; @@ -463,13 +463,13 @@ macro_rules! gpio { let offset = 2 * $i; unsafe { let gpio = &(*$GPIOX::ptr()); - gpio.pupdr.modify(|r, w| { + gpio.pupdr().modify(|r, w| { w.bits(r.bits() & !(0b11 << offset)) }); - gpio.otyper.modify(|r, w| { + gpio.otyper().modify(|r, w| { w.bits(r.bits() & !(0b1 << $i)) }); - gpio.moder.modify(|r, w| { + gpio.moder().modify(|r, w| { w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset)) }) }; @@ -486,7 +486,7 @@ macro_rules! gpio { pub fn set_speed(self, speed: Speed) -> Self { let offset = 2 * $i; unsafe { - (*$GPIOX::ptr()).ospeedr.modify(|r, w| { + (*$GPIOX::ptr()).ospeedr().modify(|r, w| { w.bits((r.bits() & !(0b11 << offset)) | ((speed as u32) << offset)) }) } @@ -500,19 +500,19 @@ macro_rules! gpio { unsafe { let gpio = &(*$GPIOX::ptr()); if offset2 < 32 { - gpio.afrl.modify(|r, w| { + gpio.afrl().modify(|r, w| { w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2)) }); } else { let offset2 = offset2 - 32; - gpio.afrh.modify(|r, w| { + gpio.afrh().modify(|r, w| { w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2)) }); } - gpio.moder.modify(|r, w| { + gpio.moder().modify(|r, w| { w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset)) }); - gpio.otyper.modify(|r, w| { + gpio.otyper().modify(|r, w| { w.bits(r.bits() & !(0b1 << $i)) }); } @@ -526,19 +526,19 @@ macro_rules! gpio { unsafe { let gpio = &(*$GPIOX::ptr()); if offset2 < 32 { - gpio.afrl.modify(|r, w| { + gpio.afrl().modify(|r, w| { w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2)) }); } else { let offset2 = offset2 - 32; - gpio.afrh.modify(|r, w| { + gpio.afrh().modify(|r, w| { w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2)) }); } - gpio.otyper.modify(|r, w| { + gpio.otyper().modify(|r, w| { w.bits(r.bits() | (0b1 << $i)) }); - gpio.moder.modify(|r, w| { + gpio.moder().modify(|r, w| { w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset)) }); } @@ -561,13 +561,13 @@ macro_rules! gpio { fn set_high(&mut self) -> Result<(), ()> { // NOTE(unsafe) atomic write to a stateless register - unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i)) }; + unsafe { (*$GPIOX::ptr()).bsrr().write(|w| w.bits(1 << $i)) }; Ok(()) } fn set_low(&mut self) -> Result<(), ()>{ // NOTE(unsafe) atomic write to a stateless register - unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << ($i + 16))) }; + unsafe { (*$GPIOX::ptr()).bsrr().write(|w| w.bits(1 << ($i + 16))) }; Ok(()) } } @@ -580,7 +580,7 @@ macro_rules! gpio { fn is_set_low(&self) -> Result { // NOTE(unsafe) atomic read with no side effects - let is_set_low = unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << $i) == 0 }; + let is_set_low = unsafe { (*$GPIOX::ptr()).odr().read().bits() & (1 << $i) == 0 }; Ok(is_set_low) } } @@ -598,7 +598,7 @@ macro_rules! gpio { fn is_low(&self) -> Result { // NOTE(unsafe) atomic read with no side effects - let is_low = unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 }; + let is_low = unsafe { (*$GPIOX::ptr()).idr().read().bits() & (1 << $i) == 0 }; Ok(is_low) } } @@ -623,7 +623,7 @@ macro_rules! gpio { fn is_low(&self) -> Result { // NOTE(unsafe) atomic read with no side effects - let is_low = unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 }; + let is_low = unsafe { (*$GPIOX::ptr()).idr().read().bits() & (1 << $i) == 0 }; Ok(is_low) } } diff --git a/src/i2c.rs b/src/i2c.rs index 33fa7a65..09477d9a 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -136,13 +136,15 @@ pub trait I2cExt { macro_rules! flush_txdr { ($i2c:expr) => { // If a pending TXIS flag is set, write dummy data to TXDR - if $i2c.isr.read().txis().bit_is_set() { - $i2c.txdr.write(|w| w.txdata().bits(0)); + if $i2c.isr().read().txis().bit_is_set() { + unsafe { + $i2c.txdr().write(|w| w.txdata().bits(0)); + } } // If TXDR is not flagged as empty, write 1 to flush it - if $i2c.isr.read().txe().bit_is_set() { - $i2c.isr.write(|w| w.txe().set_bit()); + if $i2c.isr().read().txe().bit_is_set() { + $i2c.isr().write(|w| w.txe().set_bit()); } }; } @@ -150,18 +152,19 @@ macro_rules! flush_txdr { macro_rules! busy_wait { ($i2c:expr, $flag:ident, $variant:ident) => { loop { - let isr = $i2c.isr.read(); + let isr = $i2c.isr().read(); if isr.$flag().$variant() { break; } else if isr.berr().bit_is_set() { - $i2c.icr.write(|w| w.berrcf().set_bit()); + $i2c.icr().write(|w| w.berrcf().set_bit()); return Err(Error::BusError); } else if isr.arlo().bit_is_set() { - $i2c.icr.write(|w| w.arlocf().set_bit()); + $i2c.icr().write(|w| w.arlocf().set_bit()); return Err(Error::ArbitrationLost); } else if isr.nackf().bit_is_set() { - $i2c.icr.write(|w| w.stopcf().set_bit().nackcf().set_bit()); + $i2c.icr() + .write(|w| w.stopcf().set_bit().nackcf().set_bit()); flush_txdr!($i2c); return Err(Error::Nack); } else { @@ -220,21 +223,23 @@ macro_rules! i2c { } // Make sure the I2C unit is disabled so we can configure it - i2c.cr1.modify(|_, w| w.pe().clear_bit()); + i2c.cr1().modify(|_, w| w.pe().clear_bit()); // Setup protocol timings let timing_bits = config.timing_bits(<$I2CX as RccBus>::Bus::get_frequency(&rcc.clocks)); - i2c.timingr.write(|w| unsafe { w.bits(timing_bits) }); + i2c.timingr().write(|w| unsafe { w.bits(timing_bits) }); // Enable the I2C processing - i2c.cr1.modify(|_, w| { - w.pe() - .set_bit() - .dnf() - .bits(config.digital_filter) - .anfoff() - .bit(!config.analog_filter) - }); + unsafe { + i2c.cr1().modify(|_, w| { + w.pe() + .set_bit() + .dnf() + .bits(config.digital_filter) + .anfoff() + .bit(!config.analog_filter) + }); + } I2c { i2c, sda, scl } } @@ -267,12 +272,12 @@ macro_rules! i2c { // Wait for any previous address sequence to end automatically. // This could be up to 50% of a bus cycle (ie. up to 0.5/freq) - while self.i2c.cr2.read().start().bit_is_set() {}; + while self.i2c.cr2().read().start().bit_is_set() {}; // Set START and prepare to send `bytes`. // The START bit can be set even if the bus is BUSY or // I2C is in slave mode. - self.i2c.cr2.write(|w| { + self.i2c.cr2().write(|w| unsafe { w // Start transfer .start().set_bit() @@ -294,14 +299,14 @@ macro_rules! i2c { busy_wait!(self.i2c, txis, bit_is_set); // Put byte on the wire - self.i2c.txdr.write(|w| { w.txdata().bits(*byte) }); + self.i2c.txdr().write(|w| unsafe { w.txdata().bits(*byte) }); } // Wait until the write finishes before beginning to read. busy_wait!(self.i2c, tc, bit_is_set); // reSTART and prepare to receive bytes into `buffer` - self.i2c.cr2.write(|w| { + self.i2c.cr2().write(|w| unsafe { w // Start transfer .start().set_bit() @@ -321,7 +326,7 @@ macro_rules! i2c { // Wait until we have received something busy_wait!(self.i2c, rxne, bit_is_set); - *byte = self.i2c.rxdr.read().rxdata().bits(); + *byte = self.i2c.rxdr().read().rxdata().bits(); } // automatic STOP @@ -336,7 +341,7 @@ macro_rules! i2c { fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> { assert!(bytes.len() < 256 && bytes.len() > 0); - self.i2c.cr2.modify(|_, w| { + self.i2c.cr2().modify(|_, w| unsafe { w // Start transfer .start().set_bit() @@ -356,7 +361,7 @@ macro_rules! i2c { busy_wait!(self.i2c, txis, bit_is_set); // Put byte on the wire - self.i2c.txdr.write(|w| w.txdata().bits(*byte) ); + self.i2c.txdr().write(|w| unsafe { w.txdata().bits(*byte) } ); } // automatic STOP @@ -374,12 +379,12 @@ macro_rules! i2c { // Wait for any previous address sequence to end automatically. // This could be up to 50% of a bus cycle (ie. up to 0.5/freq) - while self.i2c.cr2.read().start().bit_is_set() {}; + while self.i2c.cr2().read().start().bit_is_set() {}; // Set START and prepare to receive bytes into `buffer`. // The START bit can be set even if the bus // is BUSY or I2C is in slave mode. - self.i2c.cr2.modify(|_, w| { + self.i2c.cr2().modify(|_, w| unsafe { w // Start transfer .start().set_bit() @@ -397,7 +402,7 @@ macro_rules! i2c { // Wait until we have received something busy_wait!(self.i2c, rxne, bit_is_set); - *byte = self.i2c.rxdr.read().rxdata().bits(); + *byte = self.i2c.rxdr().read().rxdata().bits(); } // automatic STOP diff --git a/src/independent_watchdog.rs b/src/independent_watchdog.rs index 051047cb..a3a33838 100644 --- a/src/independent_watchdog.rs +++ b/src/independent_watchdog.rs @@ -12,7 +12,7 @@ //! //! Originally from stm32h7-hal, adapted for stm32g4xx-hal use crate::{ - stm32::{iwdg::pr::PR_A, IWDG}, + stm32::{iwdg::pr::PR, IWDG}, time::MicroSecond, }; use fugit::ExtU32; @@ -25,37 +25,33 @@ pub struct IndependentWatchdog { impl IndependentWatchdog { const CLOCK_SPEED: u32 = 32000; const MAX_COUNTER_VALUE: u32 = 0x00000FFF; - const MAX_MILLIS_FOR_PRESCALER: [(PR_A, u32); 8] = [ + const MAX_MILLIS_FOR_PRESCALER: [(PR, u32); 7] = [ ( - PR_A::DivideBy4, + PR::DivideBy4, (Self::MAX_COUNTER_VALUE * 1000) / (Self::CLOCK_SPEED / 4), ), ( - PR_A::DivideBy8, + PR::DivideBy8, (Self::MAX_COUNTER_VALUE * 1000) / (Self::CLOCK_SPEED / 8), ), ( - PR_A::DivideBy16, + PR::DivideBy16, (Self::MAX_COUNTER_VALUE * 1000) / (Self::CLOCK_SPEED / 16), ), ( - PR_A::DivideBy32, + PR::DivideBy32, (Self::MAX_COUNTER_VALUE * 1000) / (Self::CLOCK_SPEED / 32), ), ( - PR_A::DivideBy64, + PR::DivideBy64, (Self::MAX_COUNTER_VALUE * 1000) / (Self::CLOCK_SPEED / 64), ), ( - PR_A::DivideBy128, + PR::DivideBy128, (Self::MAX_COUNTER_VALUE * 1000) / (Self::CLOCK_SPEED / 128), ), ( - PR_A::DivideBy256, - (Self::MAX_COUNTER_VALUE * 1000) / (Self::CLOCK_SPEED / 256), - ), - ( - PR_A::DivideBy256bis, + PR::DivideBy256, (Self::MAX_COUNTER_VALUE * 1000) / (Self::CLOCK_SPEED / 256), ), ]; @@ -67,7 +63,7 @@ impl IndependentWatchdog { /// Feed the watchdog, resetting the timer to 0 pub fn feed(&mut self) { - self.iwdg.kr.write(|w| w.key().reset()); + self.iwdg.kr().write(|w| w.key().feed()); } /// Start the watchdog where it must be fed before the max time is over and @@ -77,27 +73,27 @@ impl IndependentWatchdog { let max_window_time: MicroSecond = max_window_time.into(); // Start the watchdog - self.iwdg.kr.write(|w| w.key().start()); + self.iwdg.kr().write(|w| w.key().start()); // Enable register access - self.iwdg.kr.write(|w| w.key().enable()); + self.iwdg.kr().write(|w| w.key().unlock()); // Set the prescaler let (prescaler, _) = Self::MAX_MILLIS_FOR_PRESCALER .iter() .find(|(_, max_millis)| *max_millis >= max_window_time.to_millis()) .expect("IWDG max time is greater than is possible"); - while self.iwdg.sr.read().pvu().bit_is_set() { + while self.iwdg.sr().read().pvu().bit_is_set() { cortex_m::asm::nop(); } - self.iwdg.pr.write(|w| w.pr().variant(*prescaler)); + self.iwdg.pr().write(|w| w.pr().variant(*prescaler)); // Reset the window value - while self.iwdg.sr.read().wvu().bit_is_set() { + while self.iwdg.sr().read().wvu().bit_is_set() { cortex_m::asm::nop(); } self.iwdg - .winr - .write(|w| w.win().bits(Self::MAX_COUNTER_VALUE as u16)); + .winr() + .write(|w| unsafe { w.win().bits(Self::MAX_COUNTER_VALUE as u16) } ); // Calculate the counter values let reload_value = max_window_time.to_millis() * (Self::CLOCK_SPEED / 1000) @@ -106,25 +102,25 @@ impl IndependentWatchdog { / Self::get_prescaler_divider(prescaler); // Set the reload value - while self.iwdg.sr.read().rvu().bit_is_set() { + while self.iwdg.sr().read().rvu().bit_is_set() { cortex_m::asm::nop(); } - self.iwdg.rlr.write(|w| w.rl().bits(reload_value as u16)); + self.iwdg.rlr().write(|w| unsafe { w.rl().bits(reload_value as u16) }); self.feed(); // Enable register access - self.iwdg.kr.write(|w| w.key().enable()); + self.iwdg.kr().write(|w| w.key().unlock()); // Set the window value - while self.iwdg.sr.read().wvu().bit_is_set() { + while self.iwdg.sr().read().wvu().bit_is_set() { cortex_m::asm::nop(); } self.iwdg - .winr - .write(|w| w.win().bits((reload_value - window_value) as u16)); + .winr() + .write(|w| unsafe { w.win().bits((reload_value - window_value) as u16) }); // Wait until everything is set - while self.iwdg.sr.read().bits() != 0 { + while self.iwdg.sr().read().bits() != 0 { cortex_m::asm::nop(); } @@ -136,16 +132,15 @@ impl IndependentWatchdog { self.start_windowed(0_u32.millis(), max_time.into()); } - fn get_prescaler_divider(prescaler: &PR_A) -> u32 { + fn get_prescaler_divider(prescaler: &PR) -> u32 { match prescaler { - PR_A::DivideBy4 => 4, - PR_A::DivideBy8 => 8, - PR_A::DivideBy16 => 16, - PR_A::DivideBy32 => 32, - PR_A::DivideBy64 => 64, - PR_A::DivideBy128 => 128, - PR_A::DivideBy256 => 256, - PR_A::DivideBy256bis => 256, + PR::DivideBy4 => 4, + PR::DivideBy8 => 8, + PR::DivideBy16 => 16, + PR::DivideBy32 => 32, + PR::DivideBy64 => 64, + PR::DivideBy128 => 128, + PR::DivideBy256 => 256, } } } diff --git a/src/opamp.rs b/src/opamp.rs index 0b549229..24f60a28 100644 --- a/src/opamp.rs +++ b/src/opamp.rs @@ -290,36 +290,36 @@ macro_rules! opamps { pub struct $opamp; impl LookupPgaGain for $opamp { - type PgaGainReg = crate::stm32::opamp::[<$opampreg _csr>]::PGA_GAIN_A; + type PgaGainReg = crate::stm32::opamp::[<$opampreg _csr>]::PGA_GAIN; fn pga_gain(mode: PgaMode, gain: Gain) -> Self::PgaGainReg { - use crate::stm32::opamp::[<$opampreg _csr>]::PGA_GAIN_A; + use crate::stm32::opamp::[<$opampreg _csr>]::PGA_GAIN; match (mode, gain) { - (PgaMode::Pga, Gain::Gain2) => PGA_GAIN_A::Gain2, - (PgaMode::Pga, Gain::Gain4) => PGA_GAIN_A::Gain4, - (PgaMode::Pga, Gain::Gain8) => PGA_GAIN_A::Gain8, - (PgaMode::Pga, Gain::Gain16) => PGA_GAIN_A::Gain16, - (PgaMode::Pga, Gain::Gain32) => PGA_GAIN_A::Gain32, - (PgaMode::Pga, Gain::Gain64) => PGA_GAIN_A::Gain64, - (PgaMode::PgaExternalFilter, Gain::Gain2) => PGA_GAIN_A::Gain2FilteringVinm0, - (PgaMode::PgaExternalFilter, Gain::Gain4) => PGA_GAIN_A::Gain4FilteringVinm0, - (PgaMode::PgaExternalFilter, Gain::Gain8) => PGA_GAIN_A::Gain8FilteringVinm0, - (PgaMode::PgaExternalFilter, Gain::Gain16) => PGA_GAIN_A::Gain16FilteringVinm0, - (PgaMode::PgaExternalFilter, Gain::Gain32) => PGA_GAIN_A::Gain32FilteringVinm0, - (PgaMode::PgaExternalFilter, Gain::Gain64) => PGA_GAIN_A::Gain64FilteringVinm0, - (PgaMode::PgaExternalBias, Gain::Gain2) => PGA_GAIN_A::Gain2InputVinm0, - (PgaMode::PgaExternalBias, Gain::Gain4) => PGA_GAIN_A::Gain4InputVinm0, - (PgaMode::PgaExternalBias, Gain::Gain8) => PGA_GAIN_A::Gain8InputVinm0, - (PgaMode::PgaExternalBias, Gain::Gain16) => PGA_GAIN_A::Gain16InputVinm0, - (PgaMode::PgaExternalBias, Gain::Gain32) => PGA_GAIN_A::Gain32InputVinm0, - (PgaMode::PgaExternalBias, Gain::Gain64) => PGA_GAIN_A::Gain64InputVinm0, - (PgaMode::PgaExternalBiasAndFilter, Gain::Gain2) => PGA_GAIN_A::Gain2InputVinm0filteringVinm1, - (PgaMode::PgaExternalBiasAndFilter, Gain::Gain4) => PGA_GAIN_A::Gain4InputVinm0filteringVinm1, - (PgaMode::PgaExternalBiasAndFilter, Gain::Gain8) => PGA_GAIN_A::Gain8InputVinm0filteringVinm1, - (PgaMode::PgaExternalBiasAndFilter, Gain::Gain16) => PGA_GAIN_A::Gain16InputVinm0filteringVinm1, - (PgaMode::PgaExternalBiasAndFilter, Gain::Gain32) => PGA_GAIN_A::Gain32InputVinm0filteringVinm1, - (PgaMode::PgaExternalBiasAndFilter, Gain::Gain64) => PGA_GAIN_A::Gain64InputVinm0filteringVinm1, + (PgaMode::Pga, Gain::Gain2) => PGA_GAIN::Gain2, + (PgaMode::Pga, Gain::Gain4) => PGA_GAIN::Gain4, + (PgaMode::Pga, Gain::Gain8) => PGA_GAIN::Gain8, + (PgaMode::Pga, Gain::Gain16) => PGA_GAIN::Gain16, + (PgaMode::Pga, Gain::Gain32) => PGA_GAIN::Gain32, + (PgaMode::Pga, Gain::Gain64) => PGA_GAIN::Gain64, + (PgaMode::PgaExternalFilter, Gain::Gain2) => PGA_GAIN::Gain2FilteringVinm0, + (PgaMode::PgaExternalFilter, Gain::Gain4) => PGA_GAIN::Gain4FilteringVinm0, + (PgaMode::PgaExternalFilter, Gain::Gain8) => PGA_GAIN::Gain8FilteringVinm0, + (PgaMode::PgaExternalFilter, Gain::Gain16) => PGA_GAIN::Gain16FilteringVinm0, + (PgaMode::PgaExternalFilter, Gain::Gain32) => PGA_GAIN::Gain32FilteringVinm0, + (PgaMode::PgaExternalFilter, Gain::Gain64) => PGA_GAIN::Gain64FilteringVinm0, + (PgaMode::PgaExternalBias, Gain::Gain2) => PGA_GAIN::Gain2InputVinm0, + (PgaMode::PgaExternalBias, Gain::Gain4) => PGA_GAIN::Gain4InputVinm0, + (PgaMode::PgaExternalBias, Gain::Gain8) => PGA_GAIN::Gain8InputVinm0, + (PgaMode::PgaExternalBias, Gain::Gain16) => PGA_GAIN::Gain16InputVinm0, + (PgaMode::PgaExternalBias, Gain::Gain32) => PGA_GAIN::Gain32InputVinm0, + (PgaMode::PgaExternalBias, Gain::Gain64) => PGA_GAIN::Gain64InputVinm0, + (PgaMode::PgaExternalBiasAndFilter, Gain::Gain2) => PGA_GAIN::Gain2InputVinm0filteringVinm1, + (PgaMode::PgaExternalBiasAndFilter, Gain::Gain4) => PGA_GAIN::Gain4InputVinm0filteringVinm1, + (PgaMode::PgaExternalBiasAndFilter, Gain::Gain8) => PGA_GAIN::Gain8InputVinm0filteringVinm1, + (PgaMode::PgaExternalBiasAndFilter, Gain::Gain16) => PGA_GAIN::Gain16InputVinm0filteringVinm1, + (PgaMode::PgaExternalBiasAndFilter, Gain::Gain32) => PGA_GAIN::Gain32InputVinm0filteringVinm1, + (PgaMode::PgaExternalBiasAndFilter, Gain::Gain64) => PGA_GAIN::Gain64InputVinm0filteringVinm1, } } } @@ -327,31 +327,31 @@ macro_rules! opamps { impl $opamp { #[inline(always)] unsafe fn _reset() { - (*crate::stm32::OPAMP::ptr()).[<$opampreg _csr>].reset() + (*crate::stm32::OPAMP::ptr()).[<$opampreg _csr>]().reset() } #[inline(always)] unsafe fn _disable_output() { - (*crate::stm32::OPAMP::ptr()).[<$opampreg _csr>].modify(|_, w| + (*crate::stm32::OPAMP::ptr()).[<$opampreg _csr>]().modify(|_, w| w.opaintoen().adcchannel()) } #[inline(always)] unsafe fn _enable_output() { - (*crate::stm32::OPAMP::ptr()).[<$opampreg _csr>].modify(|_, w| + (*crate::stm32::OPAMP::ptr()).[<$opampreg _csr>]().modify(|_, w| w.opaintoen().output_pin()) } #[inline(always)] unsafe fn _lock() { // Write the lock bit - (*crate::stm32::OPAMP::ptr()).[<$opampreg _csr>].modify(|_, w| + (*crate::stm32::OPAMP::ptr()).[<$opampreg _csr>]().modify(|_, w| w.lock().set_bit()); // Write the lock bit for the corresponding TCMR register. // We don't currently expose TCMR functionality, but presumably // the user doesn't want anything changing if they care to set // the lock bit. - (*crate::stm32::OPAMP::ptr()).[<$opampreg _tcmr>].modify(|_, w| + (*crate::stm32::OPAMP::ptr()).[<$opampreg _tcmr>]().modify(|_, w| w.lock().set_bit()) } } @@ -531,7 +531,7 @@ macro_rules! opamps { ) -> ( $(Disabled::<$opamp>,)* ) { - rcc.rb.apb2enr.modify(|_, w| w.syscfgen().set_bit()); + rcc.rb.apb2enr().modify(|_, w| w.syscfgen().set_bit()); ( $(Disabled::<$opamp> { opamp: PhantomData },)* @@ -581,9 +581,9 @@ macro_rules! opamps { ) -> Follower<$opamp, $input, InternalOutput> { let input = input.into(); unsafe { - use crate::stm32::opamp::[<$opampreg _csr>]::OPAINTOEN_A; + use crate::stm32::opamp::[<$opampreg _csr>]::OPAINTOEN; (*crate::stm32::OPAMP::ptr()) - .[<$opampreg _csr>] + .[<$opampreg _csr>]() .write(|csr_w| csr_w .vp_sel() @@ -591,7 +591,7 @@ macro_rules! opamps { .vm_sel() .output() .opaintoen() - .variant(OPAINTOEN_A::Adcchannel) + .variant(OPAINTOEN::Adcchannel) .opaen() .enabled() ); @@ -665,16 +665,16 @@ macro_rules! opamps { let non_inverting = non_inverting.into(); let inverting = inverting.into(); unsafe { - use crate::stm32::opamp::[<$opampreg _csr>]::OPAINTOEN_A; + use crate::stm32::opamp::[<$opampreg _csr>]::OPAINTOEN; (*crate::stm32::OPAMP::ptr()) - .[<$opampreg _csr>] + .[<$opampreg _csr>]() .write(|csr_w| csr_w.vp_sel() .$non_inverting_mask() .vm_sel() .$inverting_mask() .opaintoen() - .variant(OPAINTOEN_A::Adcchannel) + .variant(OPAINTOEN::Adcchannel) .opaen() .enabled() ); @@ -725,10 +725,10 @@ macro_rules! opamps { /// Configures the opamp for programmable gain operation. unsafe fn write_pga_reg(gain: Gain, mode: PgaMode, output_enable: bool) { - use crate::stm32::opamp::[<$opampreg _csr>]::OPAINTOEN_A; + use crate::stm32::opamp::[<$opampreg _csr>]::OPAINTOEN; (*crate::stm32::OPAMP::ptr()) - .[<$opampreg _csr>] + .[<$opampreg _csr>]() .write(|csr_w| csr_w.vp_sel() .$non_inverting_mask() @@ -738,8 +738,8 @@ macro_rules! opamps { .variant($opamp::pga_gain(mode, gain)) .opaintoen() .variant(match output_enable { - true => OPAINTOEN_A::OutputPin, - false => OPAINTOEN_A::Adcchannel, + true => OPAINTOEN::OutputPin, + false => OPAINTOEN::Adcchannel, }) .opaen() .enabled() diff --git a/src/pwm.rs b/src/pwm.rs index 5f27211d..b7be1e06 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -1174,21 +1174,21 @@ macro_rules! tim_hal { }; // Write prescale - tim.psc.write(|w| { unsafe { w.psc().bits(prescale as u16) } }); + tim.psc().write(|w| { unsafe { w.psc().bits(prescale as u16) } }); // Write period - tim.arr.write(|w| { unsafe { w.arr().bits(period.into()) } }); + tim.arr().write(|w| { unsafe { w.arr().bits(period.into()) } }); // BDTR: Advanced-control timers $( // Set CCxP = OCxREF / CCxNP = !OCxREF // Refer to RM0433 Rev 6 - Table 324. - tim.$bdtr.write(|w| + tim.$bdtr().write(|w| w.moe().$moe_set() ); )* - tim.cr1.write(|w| w.cen().set_bit()); + tim.cr1().write(|w| w.cen().set_bit()); unsafe { MaybeUninit::::uninit().assume_init() } } @@ -1246,18 +1246,18 @@ macro_rules! tim_hal { }; // Write prescaler - tim.psc.write(|w| unsafe { w.psc().bits(prescaler as u16) }); + tim.psc().write(|w| unsafe { w.psc().bits(prescaler as u16) }); // Write period - tim.arr.write(|w| unsafe { w.arr().bits(period.into()) }); + tim.arr().write(|w| unsafe { w.arr().bits(period.into()) }); $( let (dtg, ckd) = calculate_deadtime(self.base_freq, self.deadtime); match ckd { - 1 => tim.cr1.modify(|_, w| unsafe { w.ckd().bits(0) }), - 2 => tim.cr1.modify(|_, w| unsafe { w.ckd().bits(1) }), - 4 => tim.cr1.modify(|_, w| unsafe { w.ckd().bits(2) }), + 1 => tim.cr1().modify(|_, w| unsafe { w.ckd().bits(0) }), + 2 => tim.cr1().modify(|_, w| unsafe { w.ckd().bits(1) }), + 4 => tim.cr1().modify(|_, w| unsafe { w.ckd().bits(2) }), _ => panic!("Should be unreachable, invalid deadtime prescaler"), } @@ -1273,12 +1273,12 @@ macro_rules! tim_hal { // BKE = 1 -> break is enabled // BKP = 0 for active low, 1 for active high // Safety: bkf is set to a constant value (1) that is a valid value for the field per the reference manual - unsafe { tim.$bdtr.write(|w| w.dtg().bits(dtg).bkf().bits(1).aoe().clear_bit().bke().set_bit().bkp().bit(bkp).moe().$moe_set()); } + unsafe { tim.$bdtr().write(|w| w.dtg().bits(dtg).bkf().bits(1).aoe().clear_bit().bke().set_bit().bkp().bit(bkp).moe().$moe_set()); } // AF1: // BKINE = 1 -> break input enabled // BKINP should make input active high (BDTR BKP will set polarity), bit value varies timer to timer - tim.$af1.write(|w| w.bkine().set_bit().bkinp().$bkinp_setting()); + tim.$af1().write(|w| w.bkine().set_bit().bkinp().$bkinp_setting()); } $( // Not all timers that have break inputs have break2 inputs @@ -1289,37 +1289,37 @@ macro_rules! tim_hal { // BK2E = 1 -> break is enabled // BK2P = 0 for active low, 1 for active high // Safety: bkf is set to a constant value (1) that is a valid value for the field per the reference manual - unsafe { tim.$bdtr.write(|w| w.dtg().bits(dtg).bk2f().bits(1).aoe().clear_bit().bk2e().set_bit().bk2p().bit(bkp).moe().$moe_set()); } + unsafe { tim.$bdtr().write(|w| w.dtg().bits(dtg).bk2f().bits(1).aoe().clear_bit().bk2e().set_bit().bk2p().bit(bkp).moe().$moe_set()); } // AF2: // BKINE = 1 -> break input enabled // BKINP should make input active high (BDTR BKP will set polarity), bit value varies timer to timer - tim.af2.write(|w| w.bkine().set_bit().bk2inp().$bk2inp_setting()); + tim.af2().write(|w| w.bkine().set_bit().bk2inp().$bk2inp_setting()); } )* else { // Safety: the DTG field of BDTR allows any 8-bit deadtime value and the dtg variable is u8 unsafe { - tim.$bdtr.write(|w| w.dtg().bits(dtg).aoe().clear_bit().moe().$moe_set()); + tim.$bdtr().write(|w| w.dtg().bits(dtg).aoe().clear_bit().moe().$moe_set()); } } // BDTR: Advanced-control timers // Set CCxP = OCxREF / CCxNP = !OCxREF // Refer to RM0433 Rev 6 - Table 324. - tim.$bdtr.modify(|_, w| w.moe().$moe_set()); + tim.$bdtr().modify(|_, w| w.moe().$moe_set()); )* $( match self.alignment { Alignment::Left => { }, - Alignment::Right => { tim.cr1.modify(|_, w| w.dir().set_bit()); }, // Downcounter - Alignment::Center => { tim.cr1.modify(|_, w| unsafe { w.$cms().bits(3) }); } // Center-aligned mode 3 + Alignment::Right => { tim.cr1().modify(|_, w| w.dir().set_bit()); }, // Downcounter + Alignment::Center => { tim.cr1().modify(|_, w| unsafe { w.$cms().bits(3) }); } // Center-aligned mode 3 } )* - tim.cr1.modify(|_, w| w.cen().set_bit()); + tim.cr1().modify(|_, w| w.cen().set_bit()); unsafe { MaybeUninit::<(PwmControl<$TIMX, FAULT>, PINS::Channel)>::uninit() @@ -1427,19 +1427,19 @@ macro_rules! tim_hal { fn is_fault_active(&self) -> bool { let tim = unsafe { &*$TIMX::ptr() }; - !tim.$bdtr.read().moe().bit() + !tim.$bdtr().read().moe().bit() } fn clear_fault(&mut self) { let tim = unsafe { &*$TIMX::ptr() }; - tim.$bdtr.modify(|_, w| w.moe().set_bit()); + tim.$bdtr().modify(|_, w| w.moe().set_bit()); } fn set_fault(&mut self) { let tim = unsafe { &*$TIMX::ptr() }; - tim.$bdtr.modify(|_, w| w.moe().clear_bit()); + tim.$bdtr().modify(|_, w| w.moe().clear_bit()); } } )* @@ -1532,7 +1532,7 @@ macro_rules! tim_pin_hal { // Even though the field is 20 bits long for 16-bit counters, only 16 bits are // valid, so we convert to the appropriate type. - let arr = tim.arr.read().arr().bits() as $typ; + let arr = tim.arr().read().arr().bits() as $typ; // One PWM cycle is ARR+1 counts long // Valid PWM duty cycles are 0 to ARR+1 @@ -1558,12 +1558,12 @@ macro_rules! tim_pin_hal { fn ccer_enable(&mut self) { let tim = unsafe { &*$TIMX::ptr() }; - tim.ccer.modify(|_, w| w.$ccxe().set_bit()); + tim.ccer().modify(|_, w| w.$ccxe().set_bit()); } fn ccer_disable(&mut self) { let tim = unsafe { &*$TIMX::ptr() }; - tim.ccer.modify(|_, w| w.$ccxe().clear_bit()); + tim.ccer().modify(|_, w| w.$ccxe().clear_bit()); } } @@ -1571,7 +1571,7 @@ macro_rules! tim_pin_hal { pub fn into_active_low(self) -> Pwm<$TIMX, $CH, COMP, ActiveLow, NPOL> { let tim = unsafe { &*$TIMX::ptr() }; - tim.ccer.modify(|_, w| w.$ccxp().set_bit()); + tim.ccer().modify(|_, w| w.$ccxp().set_bit()); Pwm { _channel: PhantomData, @@ -1587,7 +1587,7 @@ macro_rules! tim_pin_hal { pub fn into_active_high(self) -> Pwm<$TIMX, $CH, COMP, ActiveHigh, NPOL> { let tim = unsafe { &*$TIMX::ptr() }; - tim.ccer.modify(|_, w| w.$ccxp().clear_bit()); + tim.ccer().modify(|_, w| w.$ccxp().clear_bit()); Pwm { _channel: PhantomData, @@ -1606,12 +1606,12 @@ macro_rules! tim_pin_hal { fn ccer_enable(&mut self) { let tim = unsafe { &*$TIMX::ptr() }; - tim.ccer.modify(|_, w| w.$ccxe().set_bit()); + tim.ccer().modify(|_, w| w.$ccxe().set_bit()); } fn ccer_disable(&mut self) { let tim = unsafe { &*$TIMX::ptr() }; - tim.ccer.modify(|_, w| w.$ccxe().clear_bit()); + tim.ccer().modify(|_, w| w.$ccxe().clear_bit()); } } @@ -1620,12 +1620,12 @@ macro_rules! tim_pin_hal { fn ccer_enable(&mut self) { let tim = unsafe { &*$TIMX::ptr() }; - tim.ccer.modify(|_, w| w.$ccxe().set_bit().$ccxne().set_bit()); + tim.ccer().modify(|_, w| w.$ccxe().set_bit().$ccxne().set_bit()); } fn ccer_disable(&mut self) { let tim = unsafe { &*$TIMX::ptr() }; - tim.ccer.modify(|_, w| w.$ccxe().clear_bit().$ccxne().clear_bit()); + tim.ccer().modify(|_, w| w.$ccxe().clear_bit().$ccxne().clear_bit()); } } @@ -1635,7 +1635,7 @@ macro_rules! tim_pin_hal { // Make sure we aren't switching to complementary after we enable the channel let tim = unsafe { &*$TIMX::ptr() }; - let enabled = tim.ccer.read().$ccxe().bit(); + let enabled = tim.ccer().read().$ccxe().bit(); assert!(!enabled); @@ -1653,7 +1653,7 @@ macro_rules! tim_pin_hal { pub fn into_comp_active_low(self) -> Pwm<$TIMX, $CH, ComplementaryEnabled, POL, ActiveLow> { let tim = unsafe { &*$TIMX::ptr() }; - tim.ccer.modify(|_, w| w.$ccxnp().set_bit()); + tim.ccer().modify(|_, w| w.$ccxnp().set_bit()); Pwm { _channel: PhantomData, @@ -1669,7 +1669,7 @@ macro_rules! tim_pin_hal { pub fn into_comp_active_high(self) -> Pwm<$TIMX, $CH, ComplementaryEnabled, POL, ActiveHigh> { let tim = unsafe { &*$TIMX::ptr() }; - tim.ccer.modify(|_, w| w.$ccxnp().clear_bit()); + tim.ccer().modify(|_, w| w.$ccxnp().clear_bit()); Pwm { _channel: PhantomData, @@ -1806,19 +1806,19 @@ macro_rules! lptim_hal { assert!(arr > 0); // CFGR - tim.cfgr.modify(|_, w| unsafe { w.presc().bits(prescale) }); + tim.cfgr().modify(|_, w| unsafe { w.presc().bits(prescale) }); // Enable - tim.cr.modify(|_, w| w.enable().set_bit()); + tim.cr().modify(|_, w| w.enable().set_bit()); // Write ARR: LPTIM must be enabled - tim.arr.write(|w| unsafe { w.arr().bits(arr as u16) }); - while !tim.isr.read().arrok().bit_is_set() {} - tim.icr.write(|w| w.arrokcf().set_bit()); + tim.arr().write(|w| unsafe { w.arr().bits(arr as u16) }); + while !tim.isr().read().arrok().bit_is_set() {} + tim.icr().write(|w| w.arrokcf().set_bit()); // PWM output is disabled by default, disable the // entire timer - tim.cr.modify(|_, w| w.enable().clear_bit()); + tim.cr().modify(|_, w| w.enable().clear_bit()); unsafe { MaybeUninit::::uninit().assume_init() } } @@ -1834,33 +1834,33 @@ macro_rules! lptim_hal { // LPTIM only has one output, so we disable the // entire timer - tim.cr.modify(|_, w| w.enable().clear_bit()); + tim.cr().modify(|_, w| w.enable().clear_bit()); } fn enable(&mut self) { let tim = unsafe { &*$TIMX::ptr() }; - tim.cr.modify(|_, w| w.cntstrt().set_bit().enable().set_bit()); + tim.cr().modify(|_, w| w.cntstrt().set_bit().enable().set_bit()); } fn get_duty(&self) -> u16 { let tim = unsafe { &*$TIMX::ptr() }; - tim.cmp.read().cmp().bits() + tim.cmp().read().cmp().bits() } fn get_max_duty(&self) -> u16 { let tim = unsafe { &*$TIMX::ptr() }; - tim.arr.read().arr().bits() + tim.arr().read().arr().bits() } fn set_duty(&mut self, duty: u16) { let tim = unsafe { &*$TIMX::ptr() }; - tim.cmp.write(|w| unsafe { w.cmp().bits(duty) }); - while !tim.isr.read().cmpok().bit_is_set() {} - tim.icr.write(|w| w.cmpokcf().set_bit()); + tim.cmp().write(|w| unsafe { w.cmp().bits(duty) }); + while !tim.isr().read().cmpok().bit_is_set() {} + tim.icr().write(|w| w.cmpokcf().set_bit()); } } )+ diff --git a/src/pwr.rs b/src/pwr.rs index bc5d8d0d..f451fbc7 100644 --- a/src/pwr.rs +++ b/src/pwr.rs @@ -103,10 +103,10 @@ pub(crate) fn current_vos() -> VoltageScale { // NOTE(unsafe): Read-only access let pwr = unsafe { &*PWR::ptr() }; - match pwr.cr1.read().vos().bits() { + match pwr.cr1().read().vos().bits() { 0b00 => unreachable!(), 0b01 => VoltageScale::Range1 { - enable_boost: pwr.cr5.read().r1mode().bit(), + enable_boost: pwr.cr5().read().r1mode().bit(), }, 0b10 => VoltageScale::Range2, 0b11 => unreachable!(), @@ -129,10 +129,10 @@ pub(crate) unsafe fn set_vos(vos: VoltageScale) { VoltageScale::Range1 { .. } => 0b01, VoltageScale::Range2 => 0b10, }; - pwr.cr1.modify(|_r, w| w.vos().bits(vos)); + pwr.cr1().modify(|_r, w| w.vos().bits(vos)); // Wait for ready - while pwr.sr2.read().vosf().bit() {} + while pwr.sr2().read().vosf().bit() {} } /// Set new voltage scale @@ -143,5 +143,5 @@ pub(crate) unsafe fn set_vos(vos: VoltageScale) { pub(crate) unsafe fn set_boost(enable_boost: bool) { let pwr = unsafe { &*PWR::ptr() }; let r1mode = !enable_boost; - pwr.cr5.modify(|_r, w| w.r1mode().bit(r1mode)); + pwr.cr5().modify(|_r, w| w.r1mode().bit(r1mode)); } diff --git a/src/rcc/clockout.rs b/src/rcc/clockout.rs index 07a3cdd9..b9f49944 100644 --- a/src/rcc/clockout.rs +++ b/src/rcc/clockout.rs @@ -11,12 +11,12 @@ pub struct Lsco { impl Lsco { pub fn enable(&self) { let rcc = unsafe { &(*RCC::ptr()) }; - rcc.bdcr.modify(|_, w| w.lscoen().set_bit()); + rcc.bdcr().modify(|_, w| w.lscoen().set_bit()); } pub fn disable(&self) { let rcc = unsafe { &(*RCC::ptr()) }; - rcc.bdcr.modify(|_, w| w.lscoen().clear_bit()); + rcc.bdcr().modify(|_, w| w.lscoen().clear_bit()); } pub fn release(self) -> LscoPin { @@ -41,7 +41,7 @@ impl LSCOExt for LscoPin { false } }; - rcc.rb.bdcr.modify(|_, w| w.lscosel().bit(src_select_bit)); + rcc.rb.bdcr().modify(|_, w| w.lscosel().bit(src_select_bit)); Lsco { pin: self.into_alternate(), } @@ -56,13 +56,13 @@ pub struct Mco { impl Mco { pub fn enable(&self) { let rcc = unsafe { &(*RCC::ptr()) }; - rcc.cfgr + rcc.cfgr() .modify(|_, w| unsafe { w.mcosel().bits(self.src_bits) }); } pub fn disable(&self) { let rcc = unsafe { &(*RCC::ptr()) }; - rcc.cfgr.modify(|_, w| unsafe { w.mcosel().bits(0) }); + rcc.cfgr().modify(|_, w| unsafe { w.mcosel().bits(0) }); } pub fn release(self) -> PIN { @@ -89,7 +89,7 @@ macro_rules! mco { Prescaler::Div64 => 0b110, _ => 0b111, }; - rcc.rb.cfgr.modify(|r, w| unsafe { + rcc.rb.cfgr().modify(|r, w| unsafe { w.bits((r.bits() & !(0b111 << 28)) | (psc_bits << 28)) }); diff --git a/src/rcc/mod.rs b/src/rcc/mod.rs index c901ee7e..4bf9d65c 100644 --- a/src/rcc/mod.rs +++ b/src/rcc/mod.rs @@ -188,7 +188,7 @@ impl Rcc { Self::configure_wait_states(&pwr_cfg, sys_freq); - self.rb.cfgr.modify(|_, w| unsafe { + self.rb.cfgr().modify(|_, w| unsafe { w.hpre() .bits(ahb_psc_bits) .ppre1() @@ -199,7 +199,7 @@ impl Rcc { .bits(sw_bits) }); - while self.rb.cfgr.read().sws().bits() != sw_bits {} + while self.rb.cfgr().read().sws().bits() != sw_bits {} // From RM: // The timer clock frequencies are automatically defined by hardware. There are two cases: @@ -232,15 +232,15 @@ impl Rcc { } pub fn unlock_rtc(&mut self) { - self.rb.apb1enr1.modify(|_, w| w.pwren().set_bit()); + self.rb.apb1enr1().modify(|_, w| w.pwren().set_bit()); let pwr = unsafe { &(*PWR::ptr()) }; - pwr.cr1.modify(|_, w| w.dbp().set_bit()); + pwr.cr1().modify(|_, w| w.dbp().set_bit()); } fn config_pll(&self, pll_cfg: PllConfig) -> PLLClocks { // Disable PLL - self.rb.cr.modify(|_, w| w.pllon().clear_bit()); - while self.rb.cr.read().pllrdy().bit_is_set() {} + self.rb.cr().modify(|_, w| w.pllon().clear_bit()); + while self.rb.cr().read().pllrdy().bit_is_set() {} // Enable the input clock feeding the PLL let (pll_input_freq, pll_src_bits) = match pll_cfg.mux { @@ -275,7 +275,7 @@ impl Rcc { .map(|r| ((pll_freq / r.divisor()).Hz(), r.register_setting())); // Set the M input divider, the N multiplier for the PLL, and the PLL source. - self.rb.pllcfgr.modify(|_, w| unsafe { + self.rb.pllcfgr().modify(|_, w| unsafe { // Set N, M, and source let w = w .plln() @@ -309,8 +309,8 @@ impl Rcc { }); // Enable PLL - self.rb.cr.modify(|_, w| w.pllon().set_bit()); - while self.rb.cr.read().pllrdy().bit_is_clear() {} + self.rb.cr().modify(|_, w| w.pllon().set_bit()); + while self.rb.cr().read().pllrdy().bit_is_clear() {} PLLClocks { r: r.map(|r| r.0), @@ -362,7 +362,7 @@ impl Rcc { unsafe { // Adjust flash wait states let flash = &(*FLASH::ptr()); - flash.acr.modify(|_, w| w.latency().bits(latency)) + flash.acr().modify(|_, w| w.latency().bits(latency)) } } @@ -379,11 +379,11 @@ impl Rcc { // The sequence to switch from Range11 normal mode to Range1 boost mode is: // 1. The system clock must be divided by 2 using the AHB prescaler before switching to a // higher system frequency. - let half_apb = (self.rb.cfgr.read().hpre().bits() + 1).clamp(0b1000, 0b1111); + let half_apb = (self.rb.cfgr().read().hpre().bits() + 1).clamp(0b1000, 0b1111); self.rb - .cfgr + .cfgr() .modify(|_r, w| unsafe { w.hpre().bits(half_apb) }); - while self.rb.cfgr.read().hpre().bits() != half_apb {} + while self.rb.cfgr().read().hpre().bits() != half_apb {} // 2. Clear the R1MODE bit is in the PWR_CR5 register. unsafe { pwr::set_boost(true) }; @@ -392,7 +392,7 @@ impl Rcc { Self::configure_wait_states(pwr_cfg, sys_freq); // 4. Configure and switch to new system frequency. - self.rb.cfgr.modify(|_, w| unsafe { + self.rb.cfgr().modify(|_, w| unsafe { w.ppre1() .bits(apb1_psc_bits) .ppre2() @@ -401,7 +401,7 @@ impl Rcc { .bits(sw_bits) }); - while self.rb.cfgr.read().sws().bits() != sw_bits {} + while self.rb.cfgr().read().sws().bits() != sw_bits {} // 5. Wait for at least 1us and then reconfigure the AHB prescaler to get the needed HCLK // clock frequency. @@ -412,41 +412,41 @@ impl Rcc { cortex_m::asm::delay(delay_cycles); self.rb - .cfgr + .cfgr() .modify(|_, w| unsafe { w.hpre().bits(ahb_psc_bits) }); } pub(crate) fn enable_hsi(&self) { - self.rb.cr.modify(|_, w| w.hsion().set_bit()); - while self.rb.cr.read().hsirdy().bit_is_clear() {} + self.rb.cr().modify(|_, w| w.hsion().set_bit()); + while self.rb.cr().read().hsirdy().bit_is_clear() {} } pub(crate) fn enable_hse(&self, bypass: bool) { self.rb - .cr + .cr() .modify(|_, w| w.hseon().set_bit().hsebyp().bit(bypass)); - while self.rb.cr.read().hserdy().bit_is_clear() {} + while self.rb.cr().read().hserdy().bit_is_clear() {} } pub(crate) fn enable_lse(&self, bypass: bool) { self.rb - .bdcr + .bdcr() .modify(|_, w| w.lseon().set_bit().lsebyp().bit(bypass)); - while self.rb.bdcr.read().lserdy().bit_is_clear() {} + while self.rb.bdcr().read().lserdy().bit_is_clear() {} } pub(crate) fn enable_lsi(&self) { - self.rb.csr.modify(|_, w| w.lsion().set_bit()); - while self.rb.csr.read().lsirdy().bit_is_clear() {} + self.rb.csr().modify(|_, w| w.lsion().set_bit()); + while self.rb.csr().read().lsirdy().bit_is_clear() {} } pub fn enable_hsi48(&self) { - self.rb.crrcr.modify(|_, w| w.hsi48on().set_bit()); - while self.rb.crrcr.read().hsi48rdy().bit_is_clear() {} + self.rb.crrcr().modify(|_, w| w.hsi48on().set_bit()); + while self.rb.crrcr().read().hsi48rdy().bit_is_clear() {} } pub fn get_reset_reason(&self) -> ResetReason { - let csr = self.rb.csr.read(); + let csr = self.rb.csr().read(); ResetReason { low_power: csr.lpwrstf().bit(), @@ -460,7 +460,7 @@ impl Rcc { } pub fn clear_reset_reason(&mut self) { - self.rb.csr.modify(|_, w| w.rmvf().set_bit()); + self.rb.csr().modify(|_, w| w.rmvf().set_bit()); } } @@ -531,16 +531,16 @@ pub struct AHB1 { impl AHB1 { #[inline(always)] fn enr(rcc: &RccRB) -> &rcc::AHB1ENR { - &rcc.ahb1enr + &rcc.ahb1enr() } #[inline(always)] fn rstr(rcc: &RccRB) -> &rcc::AHB1RSTR { - &rcc.ahb1rstr + &rcc.ahb1rstr() } #[allow(unused)] #[inline(always)] fn smenr(rcc: &RccRB) -> &rcc::AHB1SMENR { - &rcc.ahb1smenr + &rcc.ahb1smenr() } } @@ -550,16 +550,16 @@ pub struct AHB2 { impl AHB2 { #[inline(always)] fn enr(rcc: &RccRB) -> &rcc::AHB2ENR { - &rcc.ahb2enr + &rcc.ahb2enr() } #[inline(always)] fn rstr(rcc: &RccRB) -> &rcc::AHB2RSTR { - &rcc.ahb2rstr + &rcc.ahb2rstr() } #[allow(unused)] #[inline(always)] fn smenr(rcc: &RccRB) -> &rcc::AHB2SMENR { - &rcc.ahb2smenr + &rcc.ahb2smenr() } } @@ -570,17 +570,17 @@ impl AHB3 { #[allow(unused)] #[inline(always)] fn enr(rcc: &RccRB) -> &rcc::AHB3ENR { - &rcc.ahb3enr + &rcc.ahb3enr() } #[allow(unused)] #[inline(always)] fn rstr(rcc: &RccRB) -> &rcc::AHB3RSTR { - &rcc.ahb3rstr + &rcc.ahb3rstr() } #[allow(unused)] #[inline(always)] fn smenr(rcc: &RccRB) -> &rcc::AHB3SMENR { - &rcc.ahb3smenr + &rcc.ahb3smenr() } } @@ -590,16 +590,16 @@ pub struct APB1_1 { impl APB1_1 { #[inline(always)] fn enr(rcc: &RccRB) -> &rcc::APB1ENR1 { - &rcc.apb1enr1 + &rcc.apb1enr1() } #[inline(always)] fn rstr(rcc: &RccRB) -> &rcc::APB1RSTR1 { - &rcc.apb1rstr1 + &rcc.apb1rstr1() } #[allow(unused)] #[inline(always)] fn smenr(rcc: &RccRB) -> &rcc::APB1SMENR1 { - &rcc.apb1smenr1 + &rcc.apb1smenr1() } } @@ -609,16 +609,16 @@ pub struct APB1_2 { impl APB1_2 { #[inline(always)] fn enr(rcc: &RccRB) -> &rcc::APB1ENR2 { - &rcc.apb1enr2 + &rcc.apb1enr2() } #[inline(always)] fn rstr(rcc: &RccRB) -> &rcc::APB1RSTR2 { - &rcc.apb1rstr2 + &rcc.apb1rstr2() } #[allow(unused)] #[inline(always)] fn smenr(rcc: &RccRB) -> &rcc::APB1SMENR2 { - &rcc.apb1smenr2 + &rcc.apb1smenr2() } } @@ -628,16 +628,16 @@ pub struct APB2 { impl APB2 { #[inline(always)] fn enr(rcc: &RccRB) -> &rcc::APB2ENR { - &rcc.apb2enr + &rcc.apb2enr() } #[inline(always)] fn rstr(rcc: &RccRB) -> &rcc::APB2RSTR { - &rcc.apb2rstr + &rcc.apb2rstr() } #[allow(unused)] #[inline(always)] fn smenr(rcc: &RccRB) -> &rcc::APB2SMENR { - &rcc.apb2smenr + &rcc.apb2smenr() } } diff --git a/src/serial/usart.rs b/src/serial/usart.rs index d5779131..3aa78272 100644 --- a/src/serial/usart.rs +++ b/src/serial/usart.rs @@ -166,25 +166,25 @@ macro_rules! uart_shared { /// Starts listening for an interrupt event pub fn listen(&mut self) { let usart = unsafe { &(*$USARTX::ptr()) }; - usart.cr1.modify(|_, w| w.rxneie().set_bit()); + usart.cr1().modify(|_, w| w.rxneie().set_bit()); } /// Stop listening for an interrupt event pub fn unlisten(&mut self) { let usart = unsafe { &(*$USARTX::ptr()) }; - usart.cr1.modify(|_, w| w.rxneie().clear_bit()); + usart.cr1().modify(|_, w| w.rxneie().clear_bit()); } /// Return true if the rx register is not empty (and can be read) pub fn is_rxne(&self) -> bool { let usart = unsafe { &(*$USARTX::ptr()) }; - usart.isr.read().rxne().bit_is_set() + usart.isr().read().rxne().bit_is_set() } /// Returns true if the rx fifo threshold has been reached. pub fn fifo_threshold_reached(&self) -> bool { let usart = unsafe { &(*$USARTX::ptr()) }; - usart.isr.read().rxft().bit_is_set() + usart.isr().read().rxft().bit_is_set() } } @@ -192,7 +192,7 @@ macro_rules! uart_shared { pub fn enable_dma(self) -> Rx<$USARTX, Pin, DMA> { // NOTE(unsafe) critical section prevents races cortex_m::interrupt::free(|_| unsafe { - let cr3 = &(*$USARTX::ptr()).cr3; + let cr3 = &(*$USARTX::ptr()).cr3(); cr3.modify(|_, w| w.dmar().set_bit()); }); @@ -208,7 +208,7 @@ macro_rules! uart_shared { pub fn disable_dma(self) -> Rx<$USARTX, Pin, NoDMA> { // NOTE(unsafe) critical section prevents races interrupt::free(|_| unsafe { - let cr3 = &(*$USARTX::ptr()).cr3; + let cr3 = &(*$USARTX::ptr()).cr3(); cr3.modify(|_, w| w.dmar().clear_bit()); }); @@ -225,22 +225,22 @@ macro_rules! uart_shared { fn read(&mut self) -> nb::Result { let usart = unsafe { &(*$USARTX::ptr()) }; - let isr = usart.isr.read(); + let isr = usart.isr().read(); Err( if isr.pe().bit_is_set() { - usart.icr.write(|w| w.pecf().set_bit()); + usart.icr().write(|w| w.pecf().set_bit()); nb::Error::Other(Error::Parity) } else if isr.fe().bit_is_set() { - usart.icr.write(|w| w.fecf().set_bit()); + usart.icr().write(|w| w.fecf().set_bit()); nb::Error::Other(Error::Framing) } else if isr.nf().bit_is_set() { - usart.icr.write(|w| w.ncf().set_bit()); + usart.icr().write(|w| w.ncf().set_bit()); nb::Error::Other(Error::Noise) } else if isr.ore().bit_is_set() { - usart.icr.write(|w| w.orecf().set_bit()); + usart.icr().write(|w| w.orecf().set_bit()); nb::Error::Other(Error::Overrun) } else if isr.rxne().bit_is_set() { - return Ok(usart.rdr.read().bits() as u8) + return Ok(usart.rdr().read().bits() as u8) } else { nb::Error::WouldBlock } @@ -260,25 +260,25 @@ macro_rules! uart_shared { /// Starts listening for an interrupt event pub fn listen(&mut self) { let usart = unsafe { &(*$USARTX::ptr()) }; - usart.cr1.modify(|_, w| w.txeie().set_bit()); + usart.cr1().modify(|_, w| w.txeie().set_bit()); } /// Stop listening for an interrupt event pub fn unlisten(&mut self) { let usart = unsafe { &(*$USARTX::ptr()) }; - usart.cr1.modify(|_, w| w.txeie().clear_bit()); + usart.cr1().modify(|_, w| w.txeie().clear_bit()); } /// Return true if the tx register is empty (and can accept data) pub fn is_txe(&self) -> bool { let usart = unsafe { &(*$USARTX::ptr()) }; - usart.isr.read().txe().bit_is_set() + usart.isr().read().txe().bit_is_set() } /// Returns true if the tx fifo threshold has been reached. pub fn fifo_threshold_reached(&self) -> bool { let usart = unsafe { &(*$USARTX::ptr()) }; - usart.isr.read().txft().bit_is_set() + usart.isr().read().txft().bit_is_set() } } @@ -286,7 +286,7 @@ macro_rules! uart_shared { pub fn enable_dma(self) -> Tx<$USARTX, Pin, DMA> { // NOTE(unsafe) critical section prevents races interrupt::free(|_| unsafe { - let cr3 = &(*$USARTX::ptr()).cr3; + let cr3 = &(*$USARTX::ptr()).cr3(); cr3.modify(|_, w| w.dmat().set_bit()); }); @@ -302,7 +302,7 @@ macro_rules! uart_shared { pub fn disable_dma(self) -> Tx<$USARTX, Pin, NoDMA> { // NOTE(unsafe) critical section prevents races interrupt::free(|_| unsafe { - let cr3 = &(*$USARTX::ptr()).cr3; + let cr3 = &(*$USARTX::ptr()).cr3(); cr3.modify(|_, w| w.dmat().clear_bit()); }); @@ -319,7 +319,7 @@ macro_rules! uart_shared { fn flush(&mut self) -> nb::Result<(), Self::Error> { let usart = unsafe { &(*$USARTX::ptr()) }; - if usart.isr.read().tc().bit_is_set() { + if usart.isr().read().tc().bit_is_set() { Ok(()) } else { Err(nb::Error::WouldBlock) @@ -328,8 +328,8 @@ macro_rules! uart_shared { fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> { let usart = unsafe { &(*$USARTX::ptr()) }; - if usart.isr.read().txe().bit_is_set() { - usart.tdr.write(|w| unsafe { w.bits(byte as u32) }); + if usart.isr().read().txe().bit_is_set() { + usart.tdr().write(|w| unsafe { w.bits(byte as u32) }); Ok(()) } else { Err(nb::Error::WouldBlock) @@ -379,7 +379,7 @@ macro_rules! uart_shared { /// changes. pub fn release(self) -> ($USARTX, TX, RX) { // Disable the UART as well as its clock. - self.tx.usart.cr1.modify(|_, w| w.ue().clear_bit()); + self.tx.usart.cr1().modify(|_, w| w.ue().clear_bit()); unsafe { let rcc_ptr = &(*RCC::ptr()); $USARTX::disable(rcc_ptr); @@ -392,7 +392,7 @@ macro_rules! uart_shared { #[inline(always)] fn address(&self) -> u32 { // unsafe: only the Tx part accesses the Tx register - &unsafe { &*<$USARTX>::ptr() }.tdr as *const _ as u32 + &unsafe { &*<$USARTX>::ptr() }.tdr() as *const _ as u32 } type MemSize = u8; @@ -404,7 +404,7 @@ macro_rules! uart_shared { #[inline(always)] fn address(&self) -> u32 { // unsafe: only the Rx part accesses the Rx register - &unsafe { &*<$USARTX>::ptr() }.rdr as *const _ as u32 + &unsafe { &*<$USARTX>::ptr() }.rdr() as *const _ as u32 } type MemSize = u8; @@ -464,21 +464,21 @@ macro_rules! uart_lp { // We need 16x oversampling. return Err(InvalidConfig); } - usart.brr.write(|w| unsafe { w.bits(div as u32) }); + usart.brr().write(|w| unsafe { w.bits(div as u32) }); // Reset the UART and disable it (UE=0) - usart.cr1.reset(); + usart.cr1().reset(); // Reset other registers to disable advanced USART features - usart.cr2.reset(); - usart.cr3.reset(); + usart.cr2().reset(); + usart.cr3().reset(); - usart.cr2.write(|w| unsafe { + usart.cr2().write(|w| unsafe { w.stop() .bits(config.stopbits.bits()) .swap() .bit(config.swap) }); - usart.cr3.write(|w| unsafe { + usart.cr3().write(|w| unsafe { w.txftcfg() .bits(config.tx_fifo_threshold.bits()) .rxftcfg() @@ -490,7 +490,7 @@ macro_rules! uart_lp { }); // Enable the UART and perform remaining configuration. - usart.cr1.write(|w| { + usart.cr1().write(|w| { w.ue() .set_bit() .te() @@ -526,9 +526,9 @@ macro_rules! uart_lp { /// Starts listening for an interrupt event pub fn listen(&mut self, event: Event) { match event { - Event::Rxne => self.tx.usart.cr1.modify(|_, w| w.rxneie().set_bit()), - Event::Txe => self.tx.usart.cr1.modify(|_, w| w.txeie().set_bit()), - Event::Idle => self.tx.usart.cr1.modify(|_, w| w.idleie().set_bit()), + Event::Rxne => self.tx.usart.cr1().modify(|_, w| w.rxneie().set_bit()), + Event::Txe => self.tx.usart.cr1().modify(|_, w| w.txeie().set_bit()), + Event::Idle => self.tx.usart.cr1().modify(|_, w| w.idleie().set_bit()), _ => {} } } @@ -536,16 +536,16 @@ macro_rules! uart_lp { /// Stop listening for an interrupt event pub fn unlisten(&mut self, event: Event) { match event { - Event::Rxne => self.tx.usart.cr1.modify(|_, w| w.rxneie().clear_bit()), - Event::Txe => self.tx.usart.cr1.modify(|_, w| w.txeie().clear_bit()), - Event::Idle => self.tx.usart.cr1.modify(|_, w| w.idleie().clear_bit()), + Event::Rxne => self.tx.usart.cr1().modify(|_, w| w.rxneie().clear_bit()), + Event::Txe => self.tx.usart.cr1().modify(|_, w| w.txeie().clear_bit()), + Event::Idle => self.tx.usart.cr1().modify(|_, w| w.idleie().clear_bit()), _ => {} } } /// Check if interrupt event is pending pub fn is_pending(&mut self, event: Event) -> bool { - (self.tx.usart.isr.read().bits() & event.val()) != 0 + (self.tx.usart.isr().read().bits() & event.val()) != 0 } /// Clear pending interrupt @@ -554,7 +554,7 @@ macro_rules! uart_lp { let mask: u32 = 0x123BFF; self.tx .usart - .icr + .icr() .write(|w| unsafe { w.bits(event.val() & mask) }); } } @@ -612,14 +612,14 @@ macro_rules! uart_full { // We need 16x oversampling. return Err(InvalidConfig); } - usart.brr.write(|w| unsafe { w.bits(div as u32) }); + usart.brr().write(|w| unsafe { w.bits(div as u32) }); // Reset the UART and disable it (UE=0) - usart.cr1.reset(); - usart.cr2.reset(); - usart.cr3.reset(); + usart.cr1().reset(); + usart.cr2().reset(); + usart.cr3().reset(); - usart.cr2.write(|w| unsafe { + usart.cr2().write(|w| unsafe { w.stop() .bits(config.stopbits.bits()) .swap() @@ -627,12 +627,12 @@ macro_rules! uart_full { }); if let Some(timeout) = config.receiver_timeout { - usart.cr1.write(|w| w.rtoie().set_bit()); - usart.cr2.modify(|_, w| w.rtoen().set_bit()); - usart.rtor.write(|w| unsafe { w.rto().bits(timeout) }); + usart.cr1().write(|w| w.rtoie().set_bit()); + usart.cr2().modify(|_, w| w.rtoen().set_bit()); + usart.rtor().write(|w| unsafe { w.rto().bits(timeout) }); } - usart.cr3.write(|w| unsafe { + usart.cr3().write(|w| unsafe { w.txftcfg() .bits(config.tx_fifo_threshold.bits()) .rxftcfg() @@ -644,7 +644,7 @@ macro_rules! uart_full { }); // Enable the UART and perform remaining configuration. - usart.cr1.modify(|_, w| { + usart.cr1().modify(|_, w| { w.ue() .set_bit() .te() @@ -680,9 +680,9 @@ macro_rules! uart_full { /// Starts listening for an interrupt event pub fn listen(&mut self, event: Event) { match event { - Event::Rxne => self.tx.usart.cr1.modify(|_, w| w.rxneie().set_bit()), - Event::Txe => self.tx.usart.cr1.modify(|_, w| w.txeie().set_bit()), - Event::Idle => self.tx.usart.cr1.modify(|_, w| w.idleie().set_bit()), + Event::Rxne => self.tx.usart.cr1().modify(|_, w| w.rxneie().set_bit()), + Event::Txe => self.tx.usart.cr1().modify(|_, w| w.txeie().set_bit()), + Event::Idle => self.tx.usart.cr1().modify(|_, w| w.idleie().set_bit()), _ => {} } } @@ -690,16 +690,16 @@ macro_rules! uart_full { /// Stop listening for an interrupt event pub fn unlisten(&mut self, event: Event) { match event { - Event::Rxne => self.tx.usart.cr1.modify(|_, w| w.rxneie().clear_bit()), - Event::Txe => self.tx.usart.cr1.modify(|_, w| w.txeie().clear_bit()), - Event::Idle => self.tx.usart.cr1.modify(|_, w| w.idleie().clear_bit()), + Event::Rxne => self.tx.usart.cr1().modify(|_, w| w.rxneie().clear_bit()), + Event::Txe => self.tx.usart.cr1().modify(|_, w| w.txeie().clear_bit()), + Event::Idle => self.tx.usart.cr1().modify(|_, w| w.idleie().clear_bit()), _ => {} } } /// Check if interrupt event is pending pub fn is_pending(&mut self, event: Event) -> bool { - (self.tx.usart.isr.read().bits() & event.val()) != 0 + (self.tx.usart.isr().read().bits() & event.val()) != 0 } /// Clear pending interrupt @@ -708,7 +708,7 @@ macro_rules! uart_full { let mask: u32 = 0x123BFF; self.tx .usart - .icr + .icr() .write(|w| unsafe { w.bits(event.val() & mask) }); } } @@ -718,13 +718,13 @@ macro_rules! uart_full { /// Returns the current state of the ISR RTOF bit pub fn timeout_lapsed(&self) -> bool { let usart = unsafe { &(*$USARTX::ptr()) }; - usart.isr.read().rtof().bit_is_set() + usart.isr().read().rtof().bit_is_set() } /// Clear pending receiver timeout interrupt pub fn clear_timeout(&mut self) { let usart = unsafe { &(*$USARTX::ptr()) }; - usart.icr.write(|w| w.rtocf().set_bit()); + usart.icr().write(|w| w.rtocf().set_bit()); } } }; diff --git a/src/spi.rs b/src/spi.rs index 78cda675..27d94718 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -21,7 +21,6 @@ use crate::rcc::{Enable, GetBusFreq, Rcc, RccBus, Reset}; use crate::stm32::SPI4; use crate::stm32::{RCC, SPI1, SPI2, SPI3}; use crate::time::Hertz; -use core::cell::UnsafeCell; use core::ptr; pub use hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; @@ -118,7 +117,7 @@ macro_rules! spi { } // disable SS output - spi.cr2.write(|w| w.ssoe().clear_bit()); + spi.cr2().write(|w| w.ssoe().clear_bit()); let spi_freq = speed.into().raw(); let bus_freq = <$SPIX as RccBus>::Bus::get_frequency(&rcc.clocks).raw(); @@ -134,11 +133,11 @@ macro_rules! spi { _ => 0b111, }; - spi.cr2.write(|w| unsafe { + spi.cr2().write(|w| unsafe { w.frxth().set_bit().ds().bits(0b111).ssoe().clear_bit() }); - spi.cr1.write(|w| unsafe { + spi.cr1().write(|w| unsafe { w.cpha() .bit(mode.phase == Phase::CaptureOnSecondTransition) .cpol() @@ -173,7 +172,7 @@ macro_rules! spi { } pub fn enable_tx_dma(self) -> Spi<$SPIX, PINS> { - self.spi.cr2.modify(|_, w| w.txdmaen().set_bit()); + self.spi.cr2().modify(|_, w| w.txdmaen().set_bit()); Spi { spi: self.spi, pins: self.pins, @@ -195,7 +194,7 @@ macro_rules! spi { type Error = Error; fn read(&mut self) -> nb::Result { - let sr = self.spi.sr.read(); + let sr = self.spi.sr().read(); Err(if sr.ovr().bit_is_set() { nb::Error::Other(Error::Overrun) @@ -207,7 +206,7 @@ macro_rules! spi { // NOTE(read_volatile) read only 1 byte (the svd2rust API only allows // reading a half-word) return Ok(unsafe { - ptr::read_volatile(&self.spi.dr as *const _ as *const u8) + ptr::read_volatile(&self.spi.dr() as *const _ as *const u8) }); } else { nb::Error::WouldBlock @@ -215,7 +214,7 @@ macro_rules! spi { } fn send(&mut self, byte: u8) -> nb::Result<(), Error> { - let sr = self.spi.sr.read(); + let sr = self.spi.sr().read(); Err(if sr.ovr().bit_is_set() { nb::Error::Other(Error::Overrun) @@ -224,9 +223,9 @@ macro_rules! spi { } else if sr.crcerr().bit_is_set() { nb::Error::Other(Error::Crc) } else if sr.txe().bit_is_set() { - let dr = &self.spi.dr as *const _ as *const UnsafeCell; + let dr = self.spi.dr().as_ptr() as *mut u8; // NOTE(write_volatile) see note above - unsafe { ptr::write_volatile(UnsafeCell::raw_get(dr), byte) }; + unsafe { ptr::write_volatile(dr, byte) }; return Ok(()); } else { nb::Error::WouldBlock @@ -237,7 +236,7 @@ macro_rules! spi { #[inline(always)] fn address(&self) -> u32 { // unsafe: only the Tx part accesses the Tx register - &unsafe { &*<$SPIX>::ptr() }.dr as *const _ as u32 + &unsafe { &*<$SPIX>::ptr() }.dr() as *const _ as u32 } type MemSize = u8; diff --git a/src/syscfg.rs b/src/syscfg.rs index 19427bd8..b13833bb 100644 --- a/src/syscfg.rs +++ b/src/syscfg.rs @@ -15,7 +15,7 @@ impl SysCfgExt for SYSCFG { let rcc = &(*RCC::ptr()); // Enable clock. - bb::set(&rcc.apb2enr, 0); + bb::set(&rcc.apb2enr(), 0); // Stall the pipeline to work around erratum 2.1.13 (DM00037591) cortex_m::asm::dsb(); diff --git a/src/timer.rs b/src/timer.rs index b3d72267..26b89008 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -232,7 +232,7 @@ macro_rules! hal_ext_trgo { $( impl Timer<$TIM> { pub fn set_trigger_source(&mut self, trigger_source: TriggerSource) { - self.tim.cr2.modify(|_, w| unsafe {w.$mms().bits(trigger_source as u8)}); + self.tim.cr2().modify(|_, w| unsafe {w.$mms().bits(trigger_source as u8)}); } } )+ @@ -253,7 +253,7 @@ macro_rules! hal { match event { Event::TimeOut => { // Enable update event interrupt - self.tim.dier.write(|w| w.uie().set_bit()); + self.tim.dier().write(|w| w.uie().set_bit()); } } } @@ -266,7 +266,7 @@ macro_rules! hal { match event { Event::TimeOut => { // Clear interrupt flag - self.tim.sr.write(|w| w.uif().clear_bit()); + self.tim.sr().write(|w| w.uif().clear_bit()); } } } @@ -276,7 +276,7 @@ macro_rules! hal { match event { Event::TimeOut => { // Enable update event interrupt - self.tim.dier.write(|w| w.uie().clear_bit()); + self.tim.dier().write(|w| w.uie().clear_bit()); } } } @@ -284,7 +284,7 @@ macro_rules! hal { /// Releases the TIM peripheral pub fn release(self) -> $TIM { // pause counter - self.tim.cr1.modify(|_, w| w.cen().clear_bit()); + self.tim.cr1().modify(|_, w| w.cen().clear_bit()); self.tim } } @@ -297,33 +297,33 @@ macro_rules! hal { T: Into, { // pause - self.tim.cr1.modify(|_, w| w.cen().clear_bit()); + self.tim.cr1().modify(|_, w| w.cen().clear_bit()); // reset counter - self.tim.cnt.reset(); + self.tim.cnt().reset(); let ticks = crate::time::cycles(timeout.into(), self.clk); let psc = u16((ticks - 1) / (1 << 16)).unwrap(); - self.tim.psc.write(|w| unsafe {w.psc().bits(psc)} ); + self.tim.psc().write(|w| unsafe {w.psc().bits(psc)} ); // TODO: TIM2 and TIM5 are 32 bit let arr = u16(ticks / u32(psc + 1)).unwrap(); - self.tim.arr.write(|w| unsafe { w.bits(u32(arr)) }); + self.tim.arr().write(|w| unsafe { w.bits(u32(arr)) }); // Trigger update event to load the registers - self.tim.cr1.modify(|_, w| w.urs().set_bit()); - self.tim.egr.write(|w| w.ug().set_bit()); - self.tim.cr1.modify(|_, w| w.urs().clear_bit()); + self.tim.cr1().modify(|_, w| w.urs().set_bit()); + self.tim.egr().write(|w| w.ug().set_bit()); + self.tim.cr1().modify(|_, w| w.urs().clear_bit()); // start counter - self.tim.cr1.modify(|_, w| w.cen().set_bit()); + self.tim.cr1().modify(|_, w| w.cen().set_bit()); } fn wait(&mut self) -> nb::Result<(), Void> { - if self.tim.sr.read().uif().bit_is_clear() { + if self.tim.sr().read().uif().bit_is_clear() { Err(nb::Error::WouldBlock) } else { - self.tim.sr.modify(|_, w| w.uif().clear_bit()); + self.tim.sr().modify(|_, w| w.uif().clear_bit()); Ok(()) } } @@ -341,14 +341,14 @@ macro_rules! hal { type Error = Error; fn cancel(&mut self) -> Result<(), Self::Error> { - // let is_counter_enabled = self.tim.cr1.read().cen().is_enabled(); - let is_counter_enabled = self.tim.cr1.read().cen().bit_is_set(); + // let is_counter_enabled = self.tim.cr1().read().cen().is_enabled(); + let is_counter_enabled = self.tim.cr1().read().cen().bit_is_set(); if !is_counter_enabled { return Err(Self::Error::Disabled); } // disable counter - self.tim.cr1.modify(|_, w| w.cen().clear_bit()); + self.tim.cr1().modify(|_, w| w.cen().clear_bit()); Ok(()) } } From 48db23bfc405042079a95bb7c0b0fbd795a28ce6 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 18 Dec 2023 22:59:25 +0100 Subject: [PATCH 04/88] Fix clippy warnings --- src/flash.rs | 26 +++++++++++++------------- src/rcc/mod.rs | 36 ++++++++++++++++++------------------ 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/flash.rs b/src/flash.rs index 59cc9b9d..9edf1bfa 100644 --- a/src/flash.rs +++ b/src/flash.rs @@ -465,7 +465,7 @@ pub struct ACR { impl ACR { pub(crate) fn acr(&mut self) -> &flash::ACR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).acr() } + unsafe { (*FLASH::ptr()).acr() } } } @@ -478,7 +478,7 @@ pub struct CR { impl CR { pub(crate) fn cr(&mut self) -> &flash::CR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).cr() } + unsafe { (*FLASH::ptr()).cr() } } } @@ -491,7 +491,7 @@ pub struct ECCR { impl ECCR { pub(crate) fn eccr(&mut self) -> &flash::ECCR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).eccr() } + unsafe { (*FLASH::ptr()).eccr() } } } @@ -504,7 +504,7 @@ pub struct KEYR { impl KEYR { pub(crate) fn keyr(&mut self) -> &flash::KEYR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).keyr() } + unsafe { (*FLASH::ptr()).keyr() } } } @@ -517,7 +517,7 @@ pub struct OPTKEYR { impl OPTKEYR { pub(crate) fn optkeyr(&mut self) -> &flash::OPTKEYR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).optkeyr() } + unsafe { (*FLASH::ptr()).optkeyr() } } } @@ -530,7 +530,7 @@ pub struct OPTR { impl OPTR { pub(crate) fn optr(&mut self) -> &flash::OPTR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).optr() } + unsafe { (*FLASH::ptr()).optr() } } } @@ -543,7 +543,7 @@ pub struct PCROP1SR { impl PCROP1SR { pub(crate) fn pcrop1sr(&mut self) -> &flash::PCROP1SR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).pcrop1sr() } + unsafe { (*FLASH::ptr()).pcrop1sr() } } } @@ -556,7 +556,7 @@ pub struct PCROP1ER { impl PCROP1ER { pub(crate) fn pcrop1er(&mut self) -> &flash::PCROP1ER { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).pcrop1er() } + unsafe { (*FLASH::ptr()).pcrop1er() } } } @@ -569,7 +569,7 @@ pub struct PDKEYR { impl PDKEYR { pub(crate) fn pdkeyr(&mut self) -> &flash::PDKEYR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).pdkeyr() } + unsafe { (*FLASH::ptr()).pdkeyr() } } } @@ -582,7 +582,7 @@ pub struct SEC1R { impl SEC1R { pub(crate) fn sec1r(&mut self) -> &flash::SEC1R { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).sec1r() } + unsafe { (*FLASH::ptr()).sec1r() } } } @@ -595,7 +595,7 @@ pub struct SR { impl SR { pub(crate) fn sr(&mut self) -> &flash::SR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).sr() } + unsafe { (*FLASH::ptr()).sr() } } } @@ -608,7 +608,7 @@ pub struct WRP1AR { impl WRP1AR { pub(crate) fn wrp1ar(&mut self) -> &flash::WRP1AR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).wrp1ar() } + unsafe { (*FLASH::ptr()).wrp1ar() } } } @@ -621,6 +621,6 @@ pub struct WRP1BR { impl WRP1BR { pub(crate) fn wrp1br(&mut self) -> &flash::WRP1BR { // NOTE(unsafe) this proxy grants exclusive access to this register - unsafe { &(*FLASH::ptr()).wrp1br() } + unsafe { (*FLASH::ptr()).wrp1br() } } } diff --git a/src/rcc/mod.rs b/src/rcc/mod.rs index 4bf9d65c..c223e353 100644 --- a/src/rcc/mod.rs +++ b/src/rcc/mod.rs @@ -531,16 +531,16 @@ pub struct AHB1 { impl AHB1 { #[inline(always)] fn enr(rcc: &RccRB) -> &rcc::AHB1ENR { - &rcc.ahb1enr() + rcc.ahb1enr() } #[inline(always)] fn rstr(rcc: &RccRB) -> &rcc::AHB1RSTR { - &rcc.ahb1rstr() + rcc.ahb1rstr() } #[allow(unused)] #[inline(always)] fn smenr(rcc: &RccRB) -> &rcc::AHB1SMENR { - &rcc.ahb1smenr() + rcc.ahb1smenr() } } @@ -550,16 +550,16 @@ pub struct AHB2 { impl AHB2 { #[inline(always)] fn enr(rcc: &RccRB) -> &rcc::AHB2ENR { - &rcc.ahb2enr() + rcc.ahb2enr() } #[inline(always)] fn rstr(rcc: &RccRB) -> &rcc::AHB2RSTR { - &rcc.ahb2rstr() + rcc.ahb2rstr() } #[allow(unused)] #[inline(always)] fn smenr(rcc: &RccRB) -> &rcc::AHB2SMENR { - &rcc.ahb2smenr() + rcc.ahb2smenr() } } @@ -570,17 +570,17 @@ impl AHB3 { #[allow(unused)] #[inline(always)] fn enr(rcc: &RccRB) -> &rcc::AHB3ENR { - &rcc.ahb3enr() + rcc.ahb3enr() } #[allow(unused)] #[inline(always)] fn rstr(rcc: &RccRB) -> &rcc::AHB3RSTR { - &rcc.ahb3rstr() + rcc.ahb3rstr() } #[allow(unused)] #[inline(always)] fn smenr(rcc: &RccRB) -> &rcc::AHB3SMENR { - &rcc.ahb3smenr() + rcc.ahb3smenr() } } @@ -590,16 +590,16 @@ pub struct APB1_1 { impl APB1_1 { #[inline(always)] fn enr(rcc: &RccRB) -> &rcc::APB1ENR1 { - &rcc.apb1enr1() + rcc.apb1enr1() } #[inline(always)] fn rstr(rcc: &RccRB) -> &rcc::APB1RSTR1 { - &rcc.apb1rstr1() + rcc.apb1rstr1() } #[allow(unused)] #[inline(always)] fn smenr(rcc: &RccRB) -> &rcc::APB1SMENR1 { - &rcc.apb1smenr1() + rcc.apb1smenr1() } } @@ -609,16 +609,16 @@ pub struct APB1_2 { impl APB1_2 { #[inline(always)] fn enr(rcc: &RccRB) -> &rcc::APB1ENR2 { - &rcc.apb1enr2() + rcc.apb1enr2() } #[inline(always)] fn rstr(rcc: &RccRB) -> &rcc::APB1RSTR2 { - &rcc.apb1rstr2() + rcc.apb1rstr2() } #[allow(unused)] #[inline(always)] fn smenr(rcc: &RccRB) -> &rcc::APB1SMENR2 { - &rcc.apb1smenr2() + rcc.apb1smenr2() } } @@ -628,16 +628,16 @@ pub struct APB2 { impl APB2 { #[inline(always)] fn enr(rcc: &RccRB) -> &rcc::APB2ENR { - &rcc.apb2enr() + rcc.apb2enr() } #[inline(always)] fn rstr(rcc: &RccRB) -> &rcc::APB2RSTR { - &rcc.apb2rstr() + rcc.apb2rstr() } #[allow(unused)] #[inline(always)] fn smenr(rcc: &RccRB) -> &rcc::APB2SMENR { - &rcc.apb2smenr() + rcc.apb2smenr() } } From 75500fe3b35b192e45470fe9248eff969cff1555 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 6 Aug 2024 13:29:25 +0200 Subject: [PATCH 05/88] fmt --- src/dma/stream.rs | 33 ++++++++------------------------- src/independent_watchdog.rs | 6 ++++-- 2 files changed, 12 insertions(+), 27 deletions(-) diff --git a/src/dma/stream.rs b/src/dma/stream.rs index a889939d..eb5f1acf 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -508,28 +508,15 @@ macro_rules! dma_stream { }; } - dma_stream!( // Note: the field names start from one, unlike the RM where they start from // zero. May need updating if it gets fixed upstream. - ( - Stream0, 0, 1 - ), - ( - Stream1, 1, 2 - ), - ( - Stream2, 2, 3 - ), - ( - Stream3, 3, 4 - ), - ( - Stream4, 4, 5 - ), - ( - Stream5, 5, 6 - ), + (Stream0, 0, 1), + (Stream1, 1, 2), + (Stream2, 2, 3), + (Stream3, 3, 4), + (Stream4, 4, 5), + (Stream5, 5, 6), ); // Cat 3 and 4 devices @@ -545,10 +532,6 @@ dma_stream!( dma_stream!( // Note: the field names start from one, unlike the RM where they start from // zero. May need updating if it gets fixed upstream. - ( - Stream6, 6, 7 - ), - ( - Stream7, 7, 8 - ), + (Stream6, 6, 7), + (Stream7, 7, 8), ); diff --git a/src/independent_watchdog.rs b/src/independent_watchdog.rs index a3a33838..3462f92a 100644 --- a/src/independent_watchdog.rs +++ b/src/independent_watchdog.rs @@ -93,7 +93,7 @@ impl IndependentWatchdog { } self.iwdg .winr() - .write(|w| unsafe { w.win().bits(Self::MAX_COUNTER_VALUE as u16) } ); + .write(|w| unsafe { w.win().bits(Self::MAX_COUNTER_VALUE as u16) }); // Calculate the counter values let reload_value = max_window_time.to_millis() * (Self::CLOCK_SPEED / 1000) @@ -105,7 +105,9 @@ impl IndependentWatchdog { while self.iwdg.sr().read().rvu().bit_is_set() { cortex_m::asm::nop(); } - self.iwdg.rlr().write(|w| unsafe { w.rl().bits(reload_value as u16) }); + self.iwdg + .rlr() + .write(|w| unsafe { w.rl().bits(reload_value as u16) }); self.feed(); // Enable register access From 23d0c6630cda81dd20dd5e2774dedbade0db735b Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 6 Aug 2024 13:36:47 +0200 Subject: [PATCH 06/88] Add G91 and G4A1 to CI --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index db7b1060..61c78cb6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,8 +22,8 @@ jobs: - stm32g474 - stm32g483 - stm32g484 - #- stm32g491 # Does not seem ready yet - #- stm32g4a1 # Does not seem ready yet + - stm32g491 # Does not seem ready yet + - stm32g4a1 # Does not seem ready yet features: - log-rtt,defmt # TODO: -log-rtt # log-rtt without defmt, more combos? From 04c2bb3a6b241ef75286f536f60b815379b58bba Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 6 Aug 2024 18:28:48 +0200 Subject: [PATCH 07/88] Add support for G491 and G4A1 --- src/opamp.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++++- src/pwm.rs | 2 +- src/rcc/enable.rs | 33 ++++++++++++++++++++++---- 3 files changed, 89 insertions(+), 6 deletions(-) diff --git a/src/opamp.rs b/src/opamp.rs index 24f60a28..dbd0c7d0 100644 --- a/src/opamp.rs +++ b/src/opamp.rs @@ -864,7 +864,8 @@ macro_rules! opamps { }; } -#[cfg(any(feature = "stm32g431", feature = "stm32g441", feature = "stm32g471",))] +// TODO: Figure out a way to not duplicate this 3 times +#[cfg(any(feature = "stm32g431", feature = "stm32g441"))] opamps! { Opamp1 => opamp1: { vinm0: crate::gpio::gpioa::PA3, @@ -911,6 +912,63 @@ opamps! { }, } +#[cfg(any(feature = "stm32g471", feature = "stm32g491", feature = "stm32g4a1"))] +opamps! { + opamp1: { + vinm0: PA3, + inverting: { + crate::gpio::gpioa::PA3: vinm0, + crate::gpio::gpioc::PC5: vinm1, + }, + non_inverting: { + crate::gpio::gpioa::PA1: vinp0, + crate::gpio::gpioa::PA3: vinp1, + crate::gpio::gpioa::PA7: vinp2, + }, + output: crate::gpio::gpioa::PA2, + }, + opamp2: { + vinm0: PA5, + inverting: { + crate::gpio::gpioa::PA5: vinm0, + crate::gpio::gpioc::PC5: vinm1, + }, + non_inverting: { + crate::gpio::gpioa::PA7: vinp0, + crate::gpio::gpiob::PB14: vinp1, + crate::gpio::gpiob::PB0: vinp2, + crate::gpio::gpiod::PD14: vinp3, + }, + output: crate::gpio::gpioa::PA6, + }, + opamp3: { + vinm0: PB2, + inverting: { + crate::gpio::gpiob::PB2: vinm0, + crate::gpio::gpiob::PB10: vinm1, + }, + non_inverting: { + crate::gpio::gpiob::PB0: vinp0, + crate::gpio::gpiob::PB13: vinp1, + crate::gpio::gpioa::PA1: vinp2, + }, + output: crate::gpio::gpiob::PB1, + }, + opamp6: { + vinm0: PA1, + inverting: { + crate::gpio::gpioa::PA1: vinm0, + crate::gpio::gpiob::PB1: vinm1, + }, + non_inverting: { + crate::gpio::gpiob::PB12: vinp0, + crate::gpio::gpiod::PD9: vinp1, + crate::gpio::gpiob::PB13: vinp2, + }, + output: crate::gpio::gpiob::PB11, + }, +} + #[cfg(any( feature = "stm32g473", feature = "stm32g474", diff --git a/src/pwm.rs b/src/pwm.rs index b7be1e06..81362570 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -874,7 +874,7 @@ pins! { feature = "stm32g483", feature = "stm32g484", feature = "stm32g491", - feature = "stm32g4a1" + feature = "stm32g4a1", ))] pins! { TIM20: diff --git a/src/rcc/enable.rs b/src/rcc/enable.rs index 4ab3d330..d8e4defc 100644 --- a/src/rcc/enable.rs +++ b/src/rcc/enable.rs @@ -89,7 +89,9 @@ bus! { feature = "stm32g473", feature = "stm32g474", feature = "stm32g483", - feature = "stm32g484" + feature = "stm32g484", + feature = "stm32g491", + feature = "stm32g4a1", ))] bus! { ADC3 => (AHB2, 14), @@ -158,6 +160,16 @@ bus! { FDCAN2 => (APB1_1, 25), } +#[cfg(any( + feature = "stm32g473", + feature = "stm32g474", + feature = "stm32g483", + feature = "stm32g484", +))] +bus! { + FDCAN3 => (APB1_1, 25), +} + #[cfg(any( feature = "stm32g471", feature = "stm32g473", @@ -167,10 +179,22 @@ bus! { ))] bus! { TIM5 => (APB1_1, 3), - UART5 => (APB1_1, 20), I2C4 => (APB1_2, 1), } +#[cfg(any( + feature = "stm32g471", + feature = "stm32g473", + feature = "stm32g474", + feature = "stm32g483", + feature = "stm32g484", + feature = "stm32g491", + feature = "stm32g4a1", +))] +bus! { + UART5 => (APB1_1, 20), +} + bus! { SYSCFG => (APB2, 0), TIM1 => (APB2, 11), @@ -198,10 +222,11 @@ bus! { feature = "stm32g473", feature = "stm32g474", feature = "stm32g483", - feature = "stm32g484" + feature = "stm32g484", + feature = "stm32g491", + feature = "stm32g4a1", ))] bus! { - FDCAN3 => (APB1_1, 25), TIM20 => (APB2, 20), } From 82864557ef74daad03eda37d25b2d99b3807a2c6 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 7 Aug 2024 12:14:38 +0200 Subject: [PATCH 08/88] rename device feature --- src/fdcan.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fdcan.rs b/src/fdcan.rs index d0b9b540..ae983f29 100644 --- a/src/fdcan.rs +++ b/src/fdcan.rs @@ -1712,7 +1712,7 @@ mod impls { feature = "stm32g483", feature = "stm32g484", feature = "stm32g491", - feature = "stm32g4A1", + feature = "stm32g4a1", ))] mod fdcan2 { use crate::fdcan; From 369754d372abb404cc47747d0772c5793ab98d62 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 7 Nov 2024 19:19:35 +0100 Subject: [PATCH 09/88] Update for new pac with write and modify not returning unit type --- Cargo.toml | 3 ++- src/adc.rs | 4 ++-- src/comparator.rs | 10 +++++----- src/exti.rs | 4 ++-- src/gpio.rs | 2 +- src/pwm.rs | 2 +- src/rcc/mod.rs | 2 +- src/serial/usart.rs | 16 ++++++++-------- 8 files changed, 22 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5e683b15..8bac4fc7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,8 @@ version = "0.0.2" [dependencies] nb = "0.1.1" -stm32g4 = { git = "https://github.com/stm32-rs/stm32-rs-nightlies" } #"0.15.1" +#stm32g4 = { git = "https://github.com/stm32-rs/stm32-rs-nightlies" } #"0.15.1" +stm32g4 = { version = "0.17.0", package = "stm32g4-staging" } paste = "1.0" bitflags = "1.2" vcell = "0.1" diff --git a/src/adc.rs b/src/adc.rs index d490adea..9f2dbd38 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -1947,7 +1947,7 @@ macro_rules! adc { config::Sequence::Fourteen => self.adc_reg.sqr3().modify(|_, w| unsafe {w.sq14().bits(channel) }), config::Sequence::Fifteen => self.adc_reg.sqr4().modify(|_, w| unsafe {w.sq15().bits(channel) }), config::Sequence::Sixteen => self.adc_reg.sqr4().modify(|_, w| unsafe {w.sq16().bits(channel) }), - } + }; //Set the sample time for the channel let st = u8::from(sample_time); @@ -1973,7 +1973,7 @@ macro_rules! adc { 17 => self.adc_reg.smpr2().modify(|_, w| w.smp17().bits(st) ), 18 => self.adc_reg.smpr2().modify(|_, w| w.smp18().bits(st) ), _ => unimplemented!(), - } + }; } } /// Synchronously convert a single sample diff --git a/src/comparator.rs b/src/comparator.rs index e9eb1788..b5e80fc4 100644 --- a/src/comparator.rs +++ b/src/comparator.rs @@ -162,13 +162,13 @@ macro_rules! positive_input_pin { ($COMP:ident, $pin_0:ident, $pin_1:ident) => { impl PositiveInput<$COMP> for &$pin_0 { fn setup(&self, comp: &$COMP) { - comp.csr().modify(|_, w| w.inpsel().bit(false)) + comp.csr().modify(|_, w| w.inpsel().bit(false)); } } impl PositiveInput<$COMP> for &$pin_1 { fn setup(&self, comp: &$COMP) { - comp.csr().modify(|_, w| w.inpsel().bit(true)) + comp.csr().modify(|_, w| w.inpsel().bit(true)); } } }; @@ -213,7 +213,7 @@ macro_rules! negative_input_pin_helper { } fn setup(&self, comp: &$COMP) { - comp.csr().modify(|_, w| unsafe { w.inmsel().bits($bits) }) + comp.csr().modify(|_, w| unsafe { w.inmsel().bits($bits) }); } } }; @@ -268,7 +268,7 @@ macro_rules! refint_input { fn setup(&self, comp: &$COMP) { comp.csr() - .modify(|_, w| unsafe { w.inmsel().bits(*self as u8) }) + .modify(|_, w| unsafe { w.inmsel().bits(*self as u8) }); } } )+}; @@ -294,7 +294,7 @@ macro_rules! dac_input_helper { } fn setup(&self, comp: &$COMP) { - comp.csr().modify(|_, w| unsafe { w.inmsel().bits($bits) }) + comp.csr().modify(|_, w| unsafe { w.inmsel().bits($bits) }); } } }; diff --git a/src/exti.rs b/src/exti.rs index 7249a6db..83abc5af 100644 --- a/src/exti.rs +++ b/src/exti.rs @@ -113,7 +113,7 @@ impl ExtiExt for EXTI { line => self .imr2() .modify(|r, w| unsafe { w.bits(r.bits() | 1 << (line - 32)) }), - } + }; } fn unlisten(&self, ev: Event) { @@ -133,7 +133,7 @@ impl ExtiExt for EXTI { line => { let mask = !(1 << (line - 32)); self.imr2() - .modify(|r, w| unsafe { w.bits(r.bits() & mask) }) + .modify(|r, w| unsafe { w.bits(r.bits() & mask) }); } } } diff --git a/src/gpio.rs b/src/gpio.rs index 4d081cf0..7bb05cef 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -488,7 +488,7 @@ macro_rules! gpio { unsafe { (*$GPIOX::ptr()).ospeedr().modify(|r, w| { w.bits((r.bits() & !(0b11 << offset)) | ((speed as u32) << offset)) - }) + }); } self } diff --git a/src/pwm.rs b/src/pwm.rs index 81362570..102e1185 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -1259,7 +1259,7 @@ macro_rules! tim_hal { 2 => tim.cr1().modify(|_, w| unsafe { w.ckd().bits(1) }), 4 => tim.cr1().modify(|_, w| unsafe { w.ckd().bits(2) }), _ => panic!("Should be unreachable, invalid deadtime prescaler"), - } + }; let bkp = match self.fault_polarity { Polarity::ActiveLow => false, diff --git a/src/rcc/mod.rs b/src/rcc/mod.rs index c223e353..0503f574 100644 --- a/src/rcc/mod.rs +++ b/src/rcc/mod.rs @@ -362,7 +362,7 @@ impl Rcc { unsafe { // Adjust flash wait states let flash = &(*FLASH::ptr()); - flash.acr().modify(|_, w| w.latency().bits(latency)) + flash.acr().modify(|_, w| w.latency().bits(latency)); } } diff --git a/src/serial/usart.rs b/src/serial/usart.rs index 3aa78272..893b735d 100644 --- a/src/serial/usart.rs +++ b/src/serial/usart.rs @@ -529,8 +529,8 @@ macro_rules! uart_lp { Event::Rxne => self.tx.usart.cr1().modify(|_, w| w.rxneie().set_bit()), Event::Txe => self.tx.usart.cr1().modify(|_, w| w.txeie().set_bit()), Event::Idle => self.tx.usart.cr1().modify(|_, w| w.idleie().set_bit()), - _ => {} - } + _ => unimplemented!(), + }; } /// Stop listening for an interrupt event @@ -539,8 +539,8 @@ macro_rules! uart_lp { Event::Rxne => self.tx.usart.cr1().modify(|_, w| w.rxneie().clear_bit()), Event::Txe => self.tx.usart.cr1().modify(|_, w| w.txeie().clear_bit()), Event::Idle => self.tx.usart.cr1().modify(|_, w| w.idleie().clear_bit()), - _ => {} - } + _ => unimplemented!(), + }; } /// Check if interrupt event is pending @@ -683,8 +683,8 @@ macro_rules! uart_full { Event::Rxne => self.tx.usart.cr1().modify(|_, w| w.rxneie().set_bit()), Event::Txe => self.tx.usart.cr1().modify(|_, w| w.txeie().set_bit()), Event::Idle => self.tx.usart.cr1().modify(|_, w| w.idleie().set_bit()), - _ => {} - } + _ => unimplemented!(), + }; } /// Stop listening for an interrupt event @@ -693,8 +693,8 @@ macro_rules! uart_full { Event::Rxne => self.tx.usart.cr1().modify(|_, w| w.rxneie().clear_bit()), Event::Txe => self.tx.usart.cr1().modify(|_, w| w.txeie().clear_bit()), Event::Idle => self.tx.usart.cr1().modify(|_, w| w.idleie().clear_bit()), - _ => {} - } + _ => unimplemented!(), + }; } /// Check if interrupt event is pending From 851dd97576bf51a68a5d8d2f31eecfdda9b91993 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 7 Nov 2024 19:45:27 +0100 Subject: [PATCH 10/88] Update for new pac with write and modify not returning unit type - for G431 and friends --- src/opamp.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/opamp.rs b/src/opamp.rs index dbd0c7d0..66e6eb6c 100644 --- a/src/opamp.rs +++ b/src/opamp.rs @@ -333,13 +333,13 @@ macro_rules! opamps { #[inline(always)] unsafe fn _disable_output() { (*crate::stm32::OPAMP::ptr()).[<$opampreg _csr>]().modify(|_, w| - w.opaintoen().adcchannel()) + w.opaintoen().adcchannel()); } #[inline(always)] unsafe fn _enable_output() { (*crate::stm32::OPAMP::ptr()).[<$opampreg _csr>]().modify(|_, w| - w.opaintoen().output_pin()) + w.opaintoen().output_pin()); } #[inline(always)] @@ -352,7 +352,7 @@ macro_rules! opamps { // the user doesn't want anything changing if they care to set // the lock bit. (*crate::stm32::OPAMP::ptr()).[<$opampreg _tcmr>]().modify(|_, w| - w.lock().set_bit()) + w.lock().set_bit()); } } From d3744e66766d0e1738678566479331a04137838c Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 7 Nov 2024 20:19:01 +0100 Subject: [PATCH 11/88] Fix some leftover G491 things --- src/opamp.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/opamp.rs b/src/opamp.rs index 66e6eb6c..98cf644b 100644 --- a/src/opamp.rs +++ b/src/opamp.rs @@ -914,8 +914,9 @@ opamps! { #[cfg(any(feature = "stm32g471", feature = "stm32g491", feature = "stm32g4a1"))] opamps! { - opamp1: { - vinm0: PA3, + Opamp1 => opamp1: { + vinm0: crate::gpio::gpioa::PA3, + vinm1: crate::gpio::gpioc::PC5, inverting: { crate::gpio::gpioa::PA3: vinm0, crate::gpio::gpioc::PC5: vinm1, @@ -927,8 +928,9 @@ opamps! { }, output: crate::gpio::gpioa::PA2, }, - opamp2: { - vinm0: PA5, + Opamp2 => opamp2: { + vinm0: crate::gpio::gpioa::PA5, + vinm1: crate::gpio::gpioc::PC5, inverting: { crate::gpio::gpioa::PA5: vinm0, crate::gpio::gpioc::PC5: vinm1, @@ -941,8 +943,9 @@ opamps! { }, output: crate::gpio::gpioa::PA6, }, - opamp3: { - vinm0: PB2, + Opamp3 => opamp3: { + vinm0: crate::gpio::gpiob::PB2, + vinm1: crate::gpio::gpiob::PB10, inverting: { crate::gpio::gpiob::PB2: vinm0, crate::gpio::gpiob::PB10: vinm1, @@ -954,8 +957,9 @@ opamps! { }, output: crate::gpio::gpiob::PB1, }, - opamp6: { - vinm0: PA1, + Opamp6 => opamp6: { + vinm0: crate::gpio::gpioa::PA1, + vinm1: crate::gpio::gpiob::PB1, inverting: { crate::gpio::gpioa::PA1: vinm0, crate::gpio::gpiob::PB1: vinm1, From 698b932536a04ccc1a3973afcb0b3df97cfe3460 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 7 Nov 2024 20:35:32 +0100 Subject: [PATCH 12/88] g491 and g4a1 does not have ADC4 and 5 --- src/adc.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/adc.rs b/src/adc.rs index 9f2dbd38..600e8bcf 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -2844,6 +2844,15 @@ adc_opamp!( ))] adc_opamp!( opamp::Opamp3 => (ADC3, 13), +); + +#[cfg(any( + feature = "stm32g473", + feature = "stm32g474", + feature = "stm32g483", + feature = "stm32g484", +))] +adc_opamp!( opamp::Opamp4 => (ADC5, 5), opamp::Opamp5 => (ADC5, 3), opamp::Opamp6 => (ADC4, 17), From 9a6f41eecc590aedf03ef6c7d7dcb93f5e78e911 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 7 Nov 2024 21:37:36 +0100 Subject: [PATCH 13/88] Update src/fdcan.rs Co-authored-by: Zgarbul Andrey --- src/fdcan.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/fdcan.rs b/src/fdcan.rs index ae983f29..997e11b9 100644 --- a/src/fdcan.rs +++ b/src/fdcan.rs @@ -1159,10 +1159,11 @@ where #[inline] pub fn error_counters(&self) -> ErrorCounters { let can = self.registers(); - let cel: u8 = can.ecr().read().cel().bits(); - let rp: bool = can.ecr().read().rp().bit(); - let rec: u8 = can.ecr().read().rec().bits(); - let tec: u8 = can.ecr().read().tec().bits(); + let ecr = can.ecr().read(); + let cel: u8 = ecr.cel().bits(); + let rp: bool = ecr.rp().bit(); + let rec: u8 = ecr.rec().bits(); + let tec: u8 = ecr.tec().bits(); ErrorCounters { can_errors: cel, From f9cfab95fbe2243d3fbadeac5e6d5cd868c9750e Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 7 Nov 2024 22:03:02 +0100 Subject: [PATCH 14/88] Slightly demacrofy DMA --- src/dma/stream.rs | 564 +++++++++++++++++++++++----------------------- 1 file changed, 282 insertions(+), 282 deletions(-) diff --git a/src/dma/stream.rs b/src/dma/stream.rs index eb5f1acf..76cf60c6 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -182,329 +182,329 @@ impl StreamsTuple { // the stream macro_rules! dma_stream { ($(($name:ident, $number:expr, $x:literal)),+$(,)*) => { - paste::paste!{ - $( - impl Stream for $name { - - const NUMBER: usize = $number; - type Config = DmaConfig; - type Interrupts = DmaInterrupts; - - fn apply_config(&mut self, config: DmaConfig) { - self.set_priority(config.priority); - self.set_memory_increment(config.memory_increment); - self.set_peripheral_increment(config.peripheral_increment); - self.set_circular_buffer(config.circular_buffer); - self.set_transfer_complete_interrupt_enable( - config.transfer_complete_interrupt - ); - self.set_half_transfer_interrupt_enable(config.half_transfer_interrupt); - self.set_transfer_error_interrupt_enable( - config.transfer_error_interrupt - ); - } + $( + impl Stream for $name { + + const NUMBER: usize = $number; + type Config = DmaConfig; + type Interrupts = DmaInterrupts; + + fn apply_config(&mut self, config: DmaConfig) { + self.set_priority(config.priority); + self.set_memory_increment(config.memory_increment); + self.set_peripheral_increment(config.peripheral_increment); + self.set_circular_buffer(config.circular_buffer); + self.set_transfer_complete_interrupt_enable( + config.transfer_complete_interrupt + ); + self.set_half_transfer_interrupt_enable(config.half_transfer_interrupt); + self.set_transfer_error_interrupt_enable( + config.transfer_error_interrupt + ); + } - #[inline(always)] - fn clear_interrupts(&mut self) { - //NOTE(unsafe) Atomic write with no side-effects and we only access the bits - // that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; - dma.ifcr().write(|w| w - .[]().set_bit() //Clear transfer complete interrupt flag - .[]().set_bit() //Clear half transfer interrupt flag - .[]().set_bit() //Clear transfer error interrupt flag - .[]().set_bit() //Clear global interrupt flag - ); - let _ = dma.isr().read(); - let _ = dma.isr().read(); // Delay 2 peripheral clocks - } + #[inline(always)] + fn clear_interrupts(&mut self) { + let num = Self::NUMBER as u8; + + //NOTE(unsafe) Atomic write with no side-effects and we only access the bits + // that belongs to the StreamX + let dma = unsafe { &*I::ptr() }; + dma.ifcr().write(|w| w + .ctcif(num).set_bit() //Clear transfer complete interrupt flag + .chtif(num).set_bit() //Clear half transfer interrupt flag + .cteif(num).set_bit() //Clear transfer error interrupt flag + .cgif(num).set_bit() //Clear global interrupt flag + ); + let _ = dma.isr().read(); + let _ = dma.isr().read(); // Delay 2 peripheral clocks + } - #[inline(always)] - fn clear_transfer_complete_flag(&mut self) { - //NOTE(unsafe) Atomic write with no side-effects and we only access the bits - // that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; - dma.ifcr().write(|w| w.[]().set_bit()); - } + #[inline(always)] + fn clear_transfer_complete_flag(&mut self) { + //NOTE(unsafe) Atomic write with no side-effects and we only access the bits + // that belongs to the StreamX + let dma = unsafe { &*I::ptr() }; + dma.ifcr().write(|w| w.ctcif(Self::NUMBER as u8).set_bit()); + } - #[inline(always)] - fn clear_transfer_complete_interrupt(&mut self) { - self.clear_transfer_complete_flag(); - //NOTE(unsafe) Atomic read with no side-effects. - let dma = unsafe { &*I::ptr() }; - let _ = dma.isr().read(); - let _ = dma.isr().read(); // Delay 2 peripheral clocks - } + #[inline(always)] + fn clear_transfer_complete_interrupt(&mut self) { + self.clear_transfer_complete_flag(); + //NOTE(unsafe) Atomic read with no side-effects. + let dma = unsafe { &*I::ptr() }; + let _ = dma.isr().read(); + let _ = dma.isr().read(); // Delay 2 peripheral clocks + } - #[inline(always)] - fn clear_transfer_error_interrupt(&mut self) { - //NOTE(unsafe) Atomic write with no side-effects and we only access the bits - // that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; - dma.ifcr().write(|w| w.[]().set_bit()); - let _ = dma.isr().read(); - let _ = dma.isr().read(); // Delay 2 peripheral clocks - } + #[inline(always)] + fn clear_transfer_error_interrupt(&mut self) { + //NOTE(unsafe) Atomic write with no side-effects and we only access the bits + // that belongs to the StreamX + let dma = unsafe { &*I::ptr() }; + dma.ifcr().write(|w| w.ctcif(Self::NUMBER as u8).set_bit()); + let _ = dma.isr().read(); + let _ = dma.isr().read(); // Delay 2 peripheral clocks + } - #[inline(always)] - fn get_transfer_complete_flag() -> bool { - //NOTE(unsafe) Atomic read with no side effects - let dma = unsafe { &*I::ptr() }; - dma.isr().read().[]().bit_is_set() - } + #[inline(always)] + fn get_transfer_complete_flag() -> bool { + //NOTE(unsafe) Atomic read with no side effects + let dma = unsafe { &*I::ptr() }; + dma.isr().read().tcif(Self::NUMBER as u8).bit_is_set() + } - #[inline(always)] - fn get_transfer_error_flag() -> bool { - //NOTE(unsafe) Atomic read with no side effects - let dma = unsafe { &*I::ptr() }; - dma.isr().read().[]().bit_is_set() - } + #[inline(always)] + fn get_transfer_error_flag() -> bool { + //NOTE(unsafe) Atomic read with no side effects + let dma = unsafe { &*I::ptr() }; + dma.isr().read().tcif(Self::NUMBER as u8).bit_is_set() + } - #[inline(always)] - unsafe fn enable(&mut self) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = &unsafe { &*I::ptr() }.[](); - dma_ch.cr().modify(|_, w| w.en().set_bit()); - } + #[inline(always)] + unsafe fn enable(&mut self) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = &unsafe { &*I::ptr() }.ch(Self::NUMBER); + dma_ch.cr().modify(|_, w| w.en().set_bit()); + } - #[inline(always)] - fn is_enabled() -> bool { - //NOTE(unsafe) Atomic read with no side effects - let dma_ch = &unsafe { &*I::ptr() }.[](); - dma_ch.cr().read().en().bit_is_set() - } + #[inline(always)] + fn is_enabled() -> bool { + //NOTE(unsafe) Atomic read with no side effects + let dma_ch = &unsafe { &*I::ptr() }.ch(Self::NUMBER); + dma_ch.cr().read().en().bit_is_set() + } - fn disable(&mut self) { - if Self::is_enabled() { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = &unsafe { &*I::ptr() }.[](); + fn disable(&mut self) { + if Self::is_enabled() { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = &unsafe { &*I::ptr() }.ch(Self::NUMBER); - // Aborting an on-going transfer might cause interrupts to fire, disable - // them - let interrupts = Self::get_interrupts_enable(); - self.disable_interrupts(); + // Aborting an on-going transfer might cause interrupts to fire, disable + // them + let interrupts = Self::get_interrupts_enable(); + self.disable_interrupts(); - dma_ch.cr().modify(|_, w| w.en().clear_bit()); - while Self::is_enabled() {} + dma_ch.cr().modify(|_, w| w.en().clear_bit()); + while Self::is_enabled() {} - self.clear_interrupts(); - self.enable_interrupts(interrupts); - } + self.clear_interrupts(); + self.enable_interrupts(interrupts); } + } - #[inline(always)] - fn set_request_line(&mut self, request_line: u8) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dmamux = unsafe { &*I::mux_ptr() }; - unsafe { - dmamux.ccr($number) - .modify(|_, w| w.dmareq_id().bits(request_line)); - } + #[inline(always)] + fn set_request_line(&mut self, request_line: u8) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dmamux = unsafe { &*I::mux_ptr() }; + unsafe { + dmamux.ccr($number) + .modify(|_, w| w.dmareq_id().bits(request_line)); } + } - #[inline(always)] - fn set_priority(&mut self, priority: config::Priority) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = &unsafe { &*I::ptr() }.[](); - dma_ch.cr().modify(|_, w| unsafe { w.pl().bits(priority.bits()) }); - } + #[inline(always)] + fn set_priority(&mut self, priority: config::Priority) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = &unsafe { &*I::ptr() }.ch(Self::NUMBER); + dma_ch.cr().modify(|_, w| unsafe { w.pl().bits(priority.bits()) }); + } - #[inline(always)] - fn disable_interrupts(&mut self) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dmacr = &unsafe { &*I::ptr() }.[]().cr(); - dmacr.modify(|_, w| w - .tcie().clear_bit() - .teie().clear_bit() - .htie().clear_bit()); - let _ = dmacr.read(); - let _ = dmacr.read(); // Delay 2 peripheral clocks - } + #[inline(always)] + fn disable_interrupts(&mut self) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dmacr = &unsafe { &*I::ptr() }.ch(Self::NUMBER).cr(); + dmacr.modify(|_, w| w + .tcie().clear_bit() + .teie().clear_bit() + .htie().clear_bit()); + let _ = dmacr.read(); + let _ = dmacr.read(); // Delay 2 peripheral clocks + } - #[inline(always)] - fn enable_interrupts(&mut self, interrupt: Self::Interrupts) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = &unsafe { &*I::ptr() }.[](); - dma_ch.cr().modify(|_, w| w - .tcie().bit(interrupt.transfer_complete) - .teie().bit(interrupt.transfer_error) - .htie().bit(interrupt.half_transfer) - ); - } + #[inline(always)] + fn enable_interrupts(&mut self, interrupt: Self::Interrupts) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = &unsafe { &*I::ptr() }.ch(Self::NUMBER); + dma_ch.cr().modify(|_, w| w + .tcie().bit(interrupt.transfer_complete) + .teie().bit(interrupt.transfer_error) + .htie().bit(interrupt.half_transfer) + ); + } - #[inline(always)] - fn get_interrupts_enable() -> Self::Interrupts { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.[](); - let cr = dma_ch.cr().read(); + #[inline(always)] + fn get_interrupts_enable() -> Self::Interrupts { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.ch(Self::NUMBER); + let cr = dma_ch.cr().read(); - DmaInterrupts { - transfer_complete: cr.tcie().bit_is_set(), - half_transfer: cr.htie().bit_is_set(), - transfer_error: cr.teie().bit_is_set() - } + DmaInterrupts { + transfer_complete: cr.tcie().bit_is_set(), + half_transfer: cr.htie().bit_is_set(), + transfer_error: cr.teie().bit_is_set() } + } - #[inline(always)] - fn set_transfer_complete_interrupt_enable(&mut self, transfer_complete_interrupt: bool) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dmacr = &unsafe { &*I::ptr() }.[]().cr(); - dmacr.modify(|_, w| w.tcie().bit(transfer_complete_interrupt)); - let _ = dmacr.read(); - let _ = dmacr.read(); // Delay 2 peripheral clocks - } - - #[inline(always)] - fn set_transfer_error_interrupt_enable(&mut self, transfer_error_interrupt: bool) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dmacr = &unsafe { &*I::ptr() }.[]().cr(); - dmacr.modify(|_, w| w.teie().bit(transfer_error_interrupt)); - let _ = dmacr.read(); - let _ = dmacr.read(); // Delay 2 peripheral clocks - } + #[inline(always)] + fn set_transfer_complete_interrupt_enable(&mut self, transfer_complete_interrupt: bool) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dmacr = &unsafe { &*I::ptr() }.ch(Self::NUMBER).cr(); + dmacr.modify(|_, w| w.tcie().bit(transfer_complete_interrupt)); + let _ = dmacr.read(); + let _ = dmacr.read(); // Delay 2 peripheral clocks + } - #[inline(always)] - fn set_half_transfer_interrupt_enable(&mut self, half_transfer_interrupt: bool) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dmacr = &unsafe { &*I::ptr() }.[]().cr(); - dmacr.modify(|_, w| w.htie().bit(half_transfer_interrupt)); - let _ = dmacr.read(); - let _ = dmacr.read(); // Delay 2 peripheral clocks - } + #[inline(always)] + fn set_transfer_error_interrupt_enable(&mut self, transfer_error_interrupt: bool) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dmacr = &unsafe { &*I::ptr() }.ch(Self::NUMBER).cr(); + dmacr.modify(|_, w| w.teie().bit(transfer_error_interrupt)); + let _ = dmacr.read(); + let _ = dmacr.read(); // Delay 2 peripheral clocks + } - #[inline(always)] - fn get_half_transfer_flag() -> bool { - //NOTE(unsafe) Atomic read with no side effects - let dma = unsafe { &*I::ptr() }; - dma.isr().read().[]().bit_is_set() - } + #[inline(always)] + fn set_half_transfer_interrupt_enable(&mut self, half_transfer_interrupt: bool) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dmacr = &unsafe { &*I::ptr() }.ch(Self::NUMBER).cr(); + dmacr.modify(|_, w| w.htie().bit(half_transfer_interrupt)); + let _ = dmacr.read(); + let _ = dmacr.read(); // Delay 2 peripheral clocks + } - #[inline(always)] - fn clear_half_transfer_interrupt(&mut self) { - //NOTE(unsafe) Atomic write with no side-effects and we only access the bits - // that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; - dma.ifcr().write(|w| w.[]().set_bit()); - let _ = dma.isr().read(); - let _ = dma.isr().read(); // Delay 2 peripheral clocks - } + #[inline(always)] + fn get_half_transfer_flag() -> bool { + //NOTE(unsafe) Atomic read with no side effects + let dma = unsafe { &*I::ptr() }; + dma.isr().read().htif(Self::NUMBER as u8).bit_is_set() + } - #[inline(always)] - unsafe fn set_peripheral_address(&mut self, value: u32) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.[](); - dma_ch.par().write(|w| w.pa().bits(value)); - } + #[inline(always)] + fn clear_half_transfer_interrupt(&mut self) { + //NOTE(unsafe) Atomic write with no side-effects and we only access the bits + // that belongs to the StreamX + let dma = unsafe { &*I::ptr() }; + dma.ifcr().write(|w| w.chtif(Self::NUMBER as u8).set_bit()); + let _ = dma.isr().read(); + let _ = dma.isr().read(); // Delay 2 peripheral clocks + } - #[inline(always)] - unsafe fn set_memory_address(&mut self, value: u32) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.[](); - dma_ch.mar().write(|w| w.ma().bits(value) ); - } + #[inline(always)] + unsafe fn set_peripheral_address(&mut self, value: u32) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.ch(Self::NUMBER); + dma_ch.par().write(|w| w.pa().bits(value)); + } - #[inline(always)] - fn get_memory_address(&self) -> u32 { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.[](); - dma_ch.mar().read().ma().bits() - } + #[inline(always)] + unsafe fn set_memory_address(&mut self, value: u32) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.ch(Self::NUMBER); + dma_ch.mar().write(|w| w.ma().bits(value) ); + } - #[inline(always)] - fn set_number_of_transfers(&mut self, value: u16) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.[](); - dma_ch.ndtr().write(|w| unsafe {w.ndt().bits(value) }); - } + #[inline(always)] + fn get_memory_address(&self) -> u32 { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.ch(Self::NUMBER); + dma_ch.mar().read().ma().bits() + } - #[inline(always)] - fn get_number_of_transfers() -> u16 { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.[](); - dma_ch.ndtr().read().ndt().bits() - } - #[inline(always)] - unsafe fn set_memory_size(&mut self, size: u8) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.[](); - dma_ch.cr().modify(|_, w| w.msize().bits(size)); - } + #[inline(always)] + fn set_number_of_transfers(&mut self, value: u16) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.ch(Self::NUMBER); + dma_ch.ndtr().write(|w| unsafe {w.ndt().bits(value) }); + } - #[inline(always)] - unsafe fn set_peripheral_size(&mut self, size: u8) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.[](); - dma_ch.cr().modify(|_, w| w.psize().bits(size)); - } + #[inline(always)] + fn get_number_of_transfers() -> u16 { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.ch(Self::NUMBER); + dma_ch.ndtr().read().ndt().bits() + } + #[inline(always)] + unsafe fn set_memory_size(&mut self, size: u8) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.ch(Self::NUMBER); + dma_ch.cr().modify(|_, w| w.msize().bits(size)); + } - #[inline(always)] - fn set_memory_increment(&mut self, increment: bool) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.[](); - dma_ch.cr().modify(|_, w| w.minc().bit(increment)); - } + #[inline(always)] + unsafe fn set_peripheral_size(&mut self, size: u8) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.ch(Self::NUMBER); + dma_ch.cr().modify(|_, w| w.psize().bits(size)); + } - #[inline(always)] - fn set_peripheral_increment(&mut self, increment: bool) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.[](); - dma_ch.cr().modify(|_, w| w.pinc().bit(increment)); - } + #[inline(always)] + fn set_memory_increment(&mut self, increment: bool) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.ch(Self::NUMBER); + dma_ch.cr().modify(|_, w| w.minc().bit(increment)); + } - #[inline(always)] - fn set_direction(&mut self, direction: DmaDirection) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.[](); - dma_ch.cr().modify(|_, w| { - match direction { - DmaDirection::PeripheralToMemory => - w.dir().clear_bit().mem2mem().clear_bit(), - DmaDirection::MemoryToPeripheral => - w.dir().set_bit().mem2mem().clear_bit(), - DmaDirection::MemoryToMemory => - w.mem2mem().set_bit().dir().clear_bit(), - } - }); - } + #[inline(always)] + fn set_peripheral_increment(&mut self, increment: bool) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.ch(Self::NUMBER); + dma_ch.cr().modify(|_, w| w.pinc().bit(increment)); + } - #[inline(always)] - fn set_circular_buffer(&mut self, circular_buffer: bool) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dma_ch = unsafe { &*I::ptr() }.[](); - dma_ch.cr().modify(|_, w| w.circ().bit(circular_buffer)); - } + #[inline(always)] + fn set_direction(&mut self, direction: DmaDirection) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.ch(Self::NUMBER); + dma_ch.cr().modify(|_, w| { + match direction { + DmaDirection::PeripheralToMemory => + w.dir().clear_bit().mem2mem().clear_bit(), + DmaDirection::MemoryToPeripheral => + w.dir().set_bit().mem2mem().clear_bit(), + DmaDirection::MemoryToMemory => + w.mem2mem().set_bit().dir().clear_bit(), + } + }); } - impl $name { - #[inline(always)] - pub fn clear_half_transfer_interrupt(&mut self) { - //NOTE(unsafe) Atomic write with no side-effects and we only access the bits - // that belongs to the StreamX - let dma = unsafe { &*I::ptr() }; - dma.ifcr().write(|w| w.[]().set_bit()); - let _ = dma.isr().read(); - let _ = dma.isr().read(); // Delay 2 peripheral clocks - } + #[inline(always)] + fn set_circular_buffer(&mut self, circular_buffer: bool) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dma_ch = unsafe { &*I::ptr() }.ch(Self::NUMBER); + dma_ch.cr().modify(|_, w| w.circ().bit(circular_buffer)); + } + } + + impl $name { + #[inline(always)] + pub fn clear_half_transfer_interrupt(&mut self) { + //NOTE(unsafe) Atomic write with no side-effects and we only access the bits + // that belongs to the StreamX + let dma = unsafe { &*I::ptr() }; + dma.ifcr().write(|w| w.chtif(Self::NUMBER as u8).set_bit()); + let _ = dma.isr().read(); + let _ = dma.isr().read(); // Delay 2 peripheral clocks + } - #[inline(always)] - pub fn get_half_transfer_flag() -> bool { - //NOTE(unsafe) Atomic read with no side effects - let dma = unsafe { &*I::ptr() }; - dma.isr().read().[]().bit_is_set() - } + #[inline(always)] + pub fn get_half_transfer_flag() -> bool { + //NOTE(unsafe) Atomic read with no side effects + let dma = unsafe { &*I::ptr() }; + dma.isr().read().htif(Self::NUMBER as u8).bit_is_set() + } - #[inline(always)] - pub fn set_half_transfer_interrupt_enable(&mut self, half_transfer_interrupt: bool) { - //NOTE(unsafe) We only access the registers that belongs to the StreamX - let dmacr = &unsafe { &*I::ptr() }.[]().cr(); - dmacr.modify(|_, w| w.htie().bit(half_transfer_interrupt)); - let _ = dmacr.read(); - let _ = dmacr.read(); // Delay 2 peripheral clocks - } + #[inline(always)] + pub fn set_half_transfer_interrupt_enable(&mut self, half_transfer_interrupt: bool) { + //NOTE(unsafe) We only access the registers that belongs to the StreamX + let dmacr = &unsafe { &*I::ptr() }.ch(Self::NUMBER).cr(); + dmacr.modify(|_, w| w.htie().bit(half_transfer_interrupt)); + let _ = dmacr.read(); + let _ = dmacr.read(); // Delay 2 peripheral clocks } - )+ - } + } + )+ }; } From 5f8052b6cbb830691364e2938ec4abafa98d0cbd Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 9 May 2023 23:55:39 +0200 Subject: [PATCH 15/88] WIP --- examples/hrtim.rs | 70 ++++++++++++ src/pwm.rs | 221 ++++++++++++++++++++++-------------- src/pwm/hrtim.rs | 280 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 487 insertions(+), 84 deletions(-) create mode 100644 examples/hrtim.rs create mode 100644 src/pwm/hrtim.rs diff --git a/examples/hrtim.rs b/examples/hrtim.rs new file mode 100644 index 00000000..08fc890a --- /dev/null +++ b/examples/hrtim.rs @@ -0,0 +1,70 @@ +//This example puts the timer in PWM mode using the specified pin with a frequency of 100Hz and a duty cycle of 50%. +#![no_main] +#![no_std] + +use cortex_m_rt::entry; +use hal::gpio::AF13; +use hal::gpio::gpioa::PA8; +use hal::gpio::Alternate; +use hal::gpio::AF6; +use hal::gpio::gpioa::PA9; +use hal::prelude::*; +use hal::rcc; +use hal::stm32; +use hal::time::RateExtU32; +use stm32g4xx_hal as hal; +mod utils; +extern crate cortex_m_rt as rt; + +#[entry] +fn main() -> ! { + let dp = stm32::Peripherals::take().expect("cannot take peripherals"); + + //Set system frequency to 16MHz * 75/4/2 = 150MHz + let mut rcc = dp.RCC.freeze(rcc::Config::pll().pll_cfg(rcc::PllConfig { + n: rcc::PllNMul::MUL_75, + m: rcc::PllMDiv::DIV_4, + r: Some(rcc::PllRDiv::DIV_2), + ..Default::default() + })); + + let gpioa = dp.GPIOA.split(&mut rcc); + let pin_a: PA8> = gpioa.pa8.into_alternate(); + let pin_b: PA9> = gpioa.pa9.into_alternate(); + + // . . + // . 30% . + // ---- . ---- + //out1 | | . | | + // | | . | | + // -------- ---------------------------- -------------------- + // . ---- . ---- + //out2 . | | | | + // . | | | | + // ------------------------ ---------------------------- ---- + + type Prescaler = Pscl4; // Prescaler of 4 + let (timer, cr1, _cr2, _cr3, _cr4, (out1, out2)) = dp.HRTIM_TIMA.pwm_hrtim::((pin_a, pin_b), rcc) + .period(0xFFFF) + .mode(Mode::PushPull) // Set push pull mode, out1 and out2 are + // alternated every period with one being + // inactive and the other getting to output its wave form + // as normal + .finalize(); + + out1.rst_event(EventSource::Cr1); // Set low on compare match with cr1 + out2.rst_event(EventSource::Cr1); + + out1.set_event(EventSource::Period); // Set high at new period + out2.set_event(EventSource::Period); + // ^ + // | + // *---- Perhaps multiple EventSources could be Or:ed together? + + cr1.set_duty(timer.get_period() / 3); + timer.set_period(foo); + + loop { + cortex_m::asm::nop() + } +} diff --git a/src/pwm.rs b/src/pwm.rs index 102e1185..4aa5aa56 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -169,6 +169,12 @@ //! This code has been taken from the stm32h7xx-hal project and modified slightly to support //! STM32G4xx MCUs. It has originally been licensed under the 0-clause BSD license. +#[cfg(any( + feature = "stm32g474", + feature = "stm32g484" +))] +pub mod hrtim; + use core::marker::PhantomData; use core::mem::MaybeUninit; @@ -1025,40 +1031,55 @@ pins! { ] } -// Period and prescaler calculator for 32-bit timers -// Returns (arr, psc) -fn calculate_frequency_32bit(base_freq: Hertz, freq: Hertz, alignment: Alignment) -> (u32, u16) { - let divisor = if let Alignment::Center = alignment { - freq * 2 - } else { - freq - }; +trait TimerType { + /// Returns (arr, psc) bits + fn calculate_frequency(base_freq: Hertz, freq: Hertz, alignment: Alignment) -> (u32, u16); +} - // Round to the nearest period - let arr = (base_freq + (divisor / 2)) / divisor - 1; +/// Any 32-bit timer +struct Timer32Bit; + +impl TimerType for Timer32Bit { + // Period and prescaler calculator for 32-bit timers + // Returns (arr, psc) bits + fn calculate_frequency(base_freq: Hertz, freq: Hertz, alignment: Alignment) -> (u32, u16) { + let divisor = if let Alignment::Center = alignment { + freq * 2 + } else { + freq + }; + + // Round to the nearest period + let arr = (base_freq + (divisor / 2)) / divisor - 1; - (arr, 0) + (arr, 0) + } } -// Period and prescaler calculator for 16-bit timers -// Returns (arr, psc) -// Returns as (u32, u16) to be compatible but arr will always be a valid u16 -fn calculate_frequency_16bit(base_freq: Hertz, freq: Hertz, alignment: Alignment) -> (u32, u16) { - let ideal_period = calculate_frequency_32bit(base_freq, freq, alignment).0 + 1; +/// Any 16-bit timer except for HrTim +struct Timer16Bit; - // Division factor is (PSC + 1) - let prescale = (ideal_period - 1) / (1 << 16); +impl TimerType for Timer16Bit { + // Period and prescaler calculator for 16-bit timers + // Returns (arr, psc) + // Returns as (u32, u16) to be compatible but arr will always be a valid u16 + fn calculate_frequency(base_freq: Hertz, freq: Hertz, alignment: Alignment) -> (u32, u16) { + let ideal_period = Timer32Bit::calculate_frequency(base_freq, freq, alignment).0 + 1; - // This will always fit in a 16-bit value because u32::MAX / (1 << 16) fits in a 16 bit + // Division factor is (PSC + 1) + let prescale = (ideal_period - 1) / (1 << 16); - // Round to the nearest period - let period = (ideal_period + (prescale >> 1)) / (prescale + 1) - 1; + // This will always fit in a 16-bit value because u32::MAX / (1 << 16) fits in a 16 bit - // It should be impossible to fail these asserts - assert!(period <= 0xFFFF); - assert!(prescale <= 0xFFFF); + // Round to the nearest period + let period = (ideal_period + (prescale >> 1)) / (prescale + 1) - 1; - (period, prescale as u16) + // It should be impossible to fail these asserts + assert!(period <= 0xFFFF); + assert!(prescale <= 0xFFFF); + + (period, prescale as u16) + } } // Deadtime calculator helper function @@ -1130,68 +1151,82 @@ pub trait PwmAdvExt: Sized { // Implement PwmExt trait for timer macro_rules! pwm_ext_hal { - ($TIMX:ident: $timX:ident) => { - impl PwmExt for $TIMX { + ($TIMX:ident: $timX:ident $(, $HrTimPsc:tt)*) => { + impl $(<$HrTimPsc>)* PwmExt for $TIMX { fn pwm(self, pins: PINS, frequency: T, rcc: &mut Rcc) -> PINS::Channel where PINS: Pins, T: Into, { - $timX(self, pins, frequency.into(), rcc) + $timX::<_, _, _ $(, $HrTimPsc )*>(self, pins, frequency.into(), rcc) } } }; } -// Implement PWM configuration for timer -macro_rules! tim_hal { - ($($TIMX:ident: ($timX:ident, - $typ:ty, $bits:expr $(, DIR: $cms:ident)* $(, BDTR: $bdtr:ident, $moe_set:ident, $af1:ident, $bkinp_setting:ident $(, $bk2inp_setting:ident)*)*),)+) => { - $( - pwm_ext_hal!($TIMX: $timX); +macro_rules! simple_tim_hal { + ($TIMX:ident: ( + $timX:ident, + $bits:ident, + $(, BDTR: $bdtr:ident, $moe_set:ident)* + )) => { + pwm_ext_hal!($TIMX: $timX); + + /// Configures PWM + fn $timX( + tim: $TIMX, + _pins: PINS, + freq: Hertz, + rcc: &mut Rcc, + ) -> PINS::Channel + where + PINS: Pins<$TIMX, T, U>, + { + unsafe { + let rcc_ptr = &(*RCC::ptr()); + $TIMX::enable(rcc_ptr); + $TIMX::reset(rcc_ptr); + } - /// Configures PWM - fn $timX( - tim: $TIMX, - _pins: PINS, - freq: Hertz, - rcc: &mut Rcc, - ) -> PINS::Channel - where - PINS: Pins<$TIMX, T, U>, - { - unsafe { - let rcc_ptr = &(*RCC::ptr()); - $TIMX::enable(rcc_ptr); - $TIMX::reset(rcc_ptr); - } + let clk = $TIMX::get_timer_frequency(&rcc.clocks); - let clk = $TIMX::get_timer_frequency(&rcc.clocks); + let (period, prescale) = <$bits>::calculate_frequency(clk, freq, Alignment::Left); - let (period, prescale) = match $bits { - 16 => calculate_frequency_16bit(clk, freq, Alignment::Left), - _ => calculate_frequency_32bit(clk, freq, Alignment::Left), - }; + // Write prescale + tim.psc().write(|w| { unsafe { w.psc().bits(prescale as u16) } }); - // Write prescale - tim.psc().write(|w| { unsafe { w.psc().bits(prescale as u16) } }); + // Write period + tim.arr().write(|w| { unsafe { w.arr().bits(period.into()) } }); - // Write period - tim.arr().write(|w| { unsafe { w.arr().bits(period.into()) } }); + // BDTR: Advanced-control timers + $( + // Set CCxP = OCxREF / CCxNP = !OCxREF + // Refer to RM0433 Rev 6 - Table 324. + tim.$bdtr().write(|w| + w.moe().$moe_set() + ); + )* - // BDTR: Advanced-control timers - $( - // Set CCxP = OCxREF / CCxNP = !OCxREF - // Refer to RM0433 Rev 6 - Table 324. - tim.$bdtr().write(|w| - w.moe().$moe_set() - ); - )* + tim.cr1().write(|w| w.cen().set_bit()); - tim.cr1().write(|w| w.cen().set_bit()); + unsafe { MaybeUninit::::uninit().assume_init() } + } + }; +} - unsafe { MaybeUninit::::uninit().assume_init() } - } +// Implement PWM configuration for timer +macro_rules! tim_hal { + ($($TIMX:ident: ( + $timX:ident, + $typ:ty, $bits:ident $( <$HrTimPsc:tt> )* $(, DIR: $cms:ident)* + $(, BDTR: $bdtr:ident, $moe_set:ident, $af1:ident, $bkinp_setting:ident $(, $bk2inp_setting:ident)*)* + ),)+) => { + $( + simple_tim_hal!($TIMX: ( + $timX, + $bits, + $(, BDTR: $bdtr, $moe_set)* + )); impl PwmAdvExt<$typ> for $TIMX { fn pwm_advanced( @@ -1238,10 +1273,7 @@ macro_rules! tim_hal { let (period, prescaler) = match self.count { CountSettings::Explicit { period, prescaler } => (period as u32, prescaler), CountSettings::Frequency( freq ) => { - match $bits { - 16 => calculate_frequency_16bit(self.base_freq, freq, self.alignment), - _ => calculate_frequency_32bit(self.base_freq, freq, self.alignment), - } + <$bits>::calculate_frequency(self.base_freq, freq, self.alignment) }, }; @@ -1344,7 +1376,12 @@ macro_rules! tim_hal { self.count = CountSettings::Explicit { period, prescaler }; - self + self; + + todo!() // This needs function needs to be disabled for HrTim since HrTim's prescaler is different: + // * is only on the form (1 << N) (N: 1..=7), thus no arbitrary 16-bit numbers. + // * since HrTimers can only work with HrTimer's with the same prescaler(work as in control and sync to with other, this is yet to be exposed) + // * This + the fact that "The prescaler can not be changed while the HrTimer is running" led me to implement the prescaler as a type parameter } /// Set the period; PWM count runs from 0 to period, repeating every (period+1) counts @@ -1448,10 +1485,10 @@ macro_rules! tim_hal { } tim_hal! { - TIM1: (tim1, u16, 16, DIR: cms, BDTR: bdtr, set_bit, af1, clear_bit, clear_bit), - TIM2: (tim2, u32, 32, DIR: cms), - TIM3: (tim3, u16, 16, DIR: cms), - TIM4: (tim4, u16, 16, DIR: cms), + TIM1: (tim1, u16, Timer16Bit, DIR: cms, BDTR: bdtr, set_bit, af1, clear_bit, clear_bit), + TIM2: (tim2, u32, Timer32Bit, DIR: cms), + TIM3: (tim3, u16, Timer16Bit, DIR: cms), + TIM4: (tim4, u16, Timer16Bit, DIR: cms), } #[cfg(any( feature = "stm32g471", @@ -1461,13 +1498,13 @@ tim_hal! { feature = "stm32g484" ))] tim_hal! { - TIM5: (tim5, u32, 32, DIR: cms), + TIM5: (tim5, u32, Timer32Bit, DIR: cms), } tim_hal! { - TIM8: (tim8, u16, 16, DIR: cms, BDTR: bdtr, set_bit, af1, clear_bit, clear_bit), - TIM15: (tim15, u16, 16, BDTR: bdtr, set_bit, af1, set_bit), - TIM16: (tim16, u16, 16, BDTR: bdtr, set_bit, af1, set_bit), - TIM17: (tim17, u16, 16, BDTR: bdtr, set_bit, af1, set_bit), + TIM8: (tim8, u16, Timer16Bit, DIR: cms, BDTR: bdtr, set_bit, af1, clear_bit, clear_bit), + TIM15: (tim15, u16, Timer16Bit, BDTR: bdtr, set_bit, af1, set_bit), + TIM16: (tim16, u16, Timer16Bit, BDTR: bdtr, set_bit, af1, set_bit), + TIM17: (tim17, u16, Timer16Bit, BDTR: bdtr, set_bit, af1, set_bit), } #[cfg(any( @@ -1479,7 +1516,23 @@ tim_hal! { feature = "stm32g4a1" ))] tim_hal! { - TIM20: (tim20, u16, 16, BDTR: bdtr, set_bit, af1, set_bit), + TIM20: (tim20, u16, Timer16Bit, BDTR: bdtr, set_bit, af1, set_bit), +} + +macro_rules! tim_hal_foreach_timer { + ($($TIMX:ident: $timX:ident,)+) => {$( + tim_hal!{ + // TODO: HRTIM_MASTER + $TIMX: ($timX, u16, TimerHrTim), + $TIMX: ($timX, u16, TimerHrTim), + $TIMX: ($timX, u16, TimerHrTim), + $TIMX: ($timX, u16, TimerHrTim), + $TIMX: ($timX, u16, TimerHrTim), + $TIMX: ($timX, u16, TimerHrTim), + $TIMX: ($timX, u16, TimerHrTim), + $TIMX: ($timX, u16, TimerHrTim), + } + )+}; } pub trait PwmPinEnable { diff --git a/src/pwm/hrtim.rs b/src/pwm/hrtim.rs new file mode 100644 index 00000000..882b3e3d --- /dev/null +++ b/src/pwm/hrtim.rs @@ -0,0 +1,280 @@ +/* +period: HRTIM_PERAR +enable output: HRTIM_OENR +enable preload: PREEN, +prescaler per timer: CKPSC[2:0] kan bara sättas en gång/när timern är disablad +NOTE: Timrar som kommunicerar output set/clear, counter reset, update, external event filter eller capture triggers måste ha samma prescaler + +continous mode: CONT in TIMxCR + +crossbar config for SET events: HRTIM_SETR +crossbar config for RST events: HRTIM_RSTR +att sätta ett event i båda register betyder "TOGGLE"-event + +tvinga 50% duty: HALF in HRTIM_TIMxCR smidigt vid variabel frekvens. Var gång HRTIM_PERxR(perioden) skrivs så kommer compare1-värdet bli halva perioden. +För att detta ska fungera måste utgången vara konfigurerad för en övergång för "compare1" och en vid "period". Se sida 856 + +Triggered-half mode: TRGHLF in HRTIM_TIMxCR2 + + +**** push-pull mode ****: PSHPLL in HRTIM_TIMxCR, detta verkar styra två utgångar på ett sätt som alternerande, varannan period skickar ut signal på ena utgången och håller andra utgången inaktiv och virse versa. se sida 864 + + +reset timers counters: TxRST in HRTIM_CR2 reset sker inte förens timrarna är enablade +polaritet: POLx 0: pos, 1:neg + +starta timer: MCEN or TxCEN oklart... +*/ + +use core::marker::PhantomData; + +use crate::gpio::gpioa::{PA8, PA9}; +use crate::gpio::{self, Alternate, AF13}; +use crate::stm32::{ + HRTIM_COMMON, HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, + HRTIM_TIMF, +}; + +use super::{ActiveHigh, Alignment, ComplementaryImpossible, Pins, Pwm, TimerType}; +use crate::rcc::{Enable, GetBusFreq, Rcc, Reset}; +use crate::stm32::RCC; +use crate::time::Hertz; + +struct CH1(PhantomData); +struct CH2(PhantomData); + +macro_rules! pins { + ($($TIMX:ty: + CH1: [$($( #[ $pmeta1:meta ] )* $CH1:ty),*] CH2: [$($( #[ $pmeta2:meta ] )* $CH2:ty),*])+) => { + $( + $( + $( #[ $pmeta1 ] )* + impl Pins<$TIMX, CH1, ComplementaryImpossible> for $CH1 { + type Channel = Pwm<$TIMX, CH1, ComplementaryImpossible, ActiveHigh, ActiveHigh>; + } + )* + $( + $( #[ $pmeta2 ] )* + impl Pins<$TIMX, CH2, ComplementaryImpossible> for $CH2 { + type Channel = Pwm<$TIMX, CH2, ComplementaryImpossible, ActiveHigh, ActiveHigh>; + } + )* + )+ + } +} + +pins! { + HRTIM_TIMA: + CH1: [ + PA8> + ] + CH2: [ + PA9> + ] +} + +pub struct Hrtimer { + _prescaler: PhantomData, + _timer: PhantomData, + period: u16, + + cmp_value1: u16, + cmp_value2: u16, + cmp_value3: u16, + cmp_value4: u16, +} + +impl TimerType for CH1 +where + PSCL: HrtimPrescaler, +{ + fn calculate_frequency(base_freq: Hertz, freq: Hertz, alignment: Alignment) -> (u32, u16) { + >::calculate_frequency(base_freq, freq, alignment) + } +} + +impl TimerType for CH2 +where + PSCL: HrtimPrescaler, +{ + fn calculate_frequency(base_freq: Hertz, freq: Hertz, alignment: Alignment) -> (u32, u16) { + >::calculate_frequency(base_freq, freq, alignment) + } +} + +// Implement PWM configuration for timer +macro_rules! hrtim_hal { + ($($TIMX:ident: ($timX:ident, $timXcr:ident, $perXr:ident, $tXcen:ident),)+) => { + $( + //pwm_ext_hal!($TIMX: $timX); + + /// Configures PWM + fn $timX( + tim: $TIMX, + master: &mut HRTIM_MASTER, + common: &mut HRTIM_COMMON, + _pins: PINS, + freq: Hertz, + rcc: &mut Rcc, + ) -> PINS::Channel + where + PINS: super::Pins<$TIMX, T, U>, + T: TimerType, + { + unsafe { + let rcc_ptr = &(*RCC::ptr()); + $TIMX::enable(rcc_ptr); + $TIMX::reset(rcc_ptr); + } + + let clk = $TIMX::get_timer_frequency(&rcc.clocks); + + let (period, psc) = ::calculate_frequency(clk, freq, Alignment::Left); + + // Write prescaler + tim.$timXcr.write(|w| { unsafe { w.cont().set_bit().ck_pscx().bits(psc as u8) } }); + + // Write period + tim.$perXr.write(|w| { unsafe { w.perx().bits(period as u16) } }); + + // Start timer + master.mcr.modify(|_r, w| { unsafe { w.$tXcen().set_bit() }}); + + // Enable output 1 + //self.enable(); + + // Enable output 2 + //common.oenr.modify(|_r, w| { unsafe { w.tX2oen().set_bit() } }); + + todo!() + } + )+ + } +} + +macro_rules! hrtim_pin_hal { + ($($TIMX:ident: + ($CH:ty, $ccxe:ident, $ccxp:ident, $ccmrx_output:ident, $ocxpe:ident, $ocxm:ident, + $ccrx:ident, $typ:ident $(,$ccxne:ident, $ccxnp:ident)*),)+ + ) => { + $( + impl hal::PwmPin for Pwm<$TIMX, $CH, COMP, POL, NPOL> + where Pwm<$TIMX, $CH, COMP, POL, NPOL>: PwmPinEnable { + type Duty = u16; + + // You may not access self in the following methods! + // See unsafe above + + fn disable(&mut self) { + // TODO: How do we do this while preventing data race due to shared register + + // Disable output Y on channel X + //HRTIM_COMMON.oenr.modify(|_r, w| { unsafe { w.$tXYoen().clear_bit() } }); + } + + fn enable(&mut self) { + // TODO: How do we do this while preventing data race due to shared register + + // Enable output Y on channel X + //HRTIM_COMMON.oenr.modify(|_r, w| { unsafe { w.$tXYoen().set_bit() } }); + } + + fn get_duty(&self) -> Self::Duty { + let tim = unsafe { &*$TIMX::ptr() }; + + // Even though the field is 20 bits long for 16-bit counters, only 16 bits are + // valid, so we convert to the appropriate type. + tim.$ccrx().read().ccr().bits() as $typ + } + + fn get_max_duty(&self) -> Self::Duty { + let tim = unsafe { &*$TIMX::ptr() }; + + // Even though the field is 20 bits long for 16-bit counters, only 16 bits are + // valid, so we convert to the appropriate type. + let arr = tim.arr.read().arr().bits() as $typ; + + // One PWM cycle is ARR+1 counts long + // Valid PWM duty cycles are 0 to ARR+1 + // However, if ARR is 65535 on a 16-bit timer, we can't add 1 + // In that case, 100% duty cycle is not possible, only 65535/65536 + if arr == Self::Duty::MAX { + arr + } + else { + arr + 1 + } + } + + fn set_duty(&mut self, duty: Self::Duty) { + let tim = unsafe { &*$TIMX::ptr() }; + + tim.$ccrx().write(|w| unsafe { w.ccr().bits(duty.into()) }); + } + } + )+ + } +} + +hrtim_hal! { + // TODO: HRTIM_MASTER + HRTIM_TIMA: (hrtim_tima, timacr, perar, tacen), + HRTIM_TIMB: (hrtim_timb, timbcr, perbr, tbcen), + HRTIM_TIMC: (hrtim_timc, timccr, percr, tccen), + HRTIM_TIMD: (hrtim_timd, timdcr, perdr, tdcen), + HRTIM_TIME: (hrtim_time, timecr, perer, tecen), + HRTIM_TIMF: (hrtim_timf, timfcr, perfr, tfcen), +} + +hrtim_pin_hal! { + HRTIM_TIMA: (CH1), + HRTIM_TIMA: (CH2) +} + +trait HrtimPrescaler { + const BITS: u8; + const VALUE: u8; +} + +macro_rules! impl_pscl { + ($($t:ident => $b:literal, $c:literal,)+) => {$( + struct $t; + impl HrtimPrescaler for $t { + const BITS: u8 = $b; + const VALUE: u8 = $c; + } + )+}; +} + +impl_pscl! { + Pscl1 => 0b000, 1, + Pscl2 => 0b001, 2, + Pscl4 => 0b010, 4, + Pscl8 => 0b011, 8, + Pscl16 => 0b100, 16, + Pscl32 => 0b101, 32, + Pscl64 => 0b110, 64, + Pscl128 => 0b111, 128, +} + +/// HrTim timer +struct TimerHrTim(PhantomData); + +impl super::TimerType for TimerHrTim { + // Period calculator for 16-bit hrtimers + // + // NOTE: This function will panic if the calculated period can not fit into 16 bits + fn calculate_frequency(base_freq: Hertz, freq: Hertz, alignment: Alignment) -> (u32, u16) { + let ideal_period = super::Timer32Bit::calculate_frequency(base_freq, freq, alignment).0 + 1; + + let prescale = u32::from(PSC::VALUE); + + // Round to the nearest period + let period = (ideal_period + (prescale >> 1)) / prescale - 1; + + // It IS possible to fail this assert + assert!(period <= 0xFFFF); + + (period, PSC::BITS.into()) + } +} From 5228780aec1209788d654c9ae2cfc2bdf3ce5004 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 20 May 2023 11:25:42 +0200 Subject: [PATCH 16/88] Untested sort of maybe working chaos --- examples/hrtim.rs | 15 ++-- src/pwm.rs | 23 +------ src/pwm/hrtim.rs | 171 +++++++++++++++++++++++++++++++++------------- 3 files changed, 135 insertions(+), 74 deletions(-) diff --git a/examples/hrtim.rs b/examples/hrtim.rs index 08fc890a..5bfa8064 100644 --- a/examples/hrtim.rs +++ b/examples/hrtim.rs @@ -3,15 +3,16 @@ #![no_std] use cortex_m_rt::entry; +use fugit::RateExtU32; use hal::gpio::AF13; use hal::gpio::gpioa::PA8; use hal::gpio::Alternate; -use hal::gpio::AF6; use hal::gpio::gpioa::PA9; use hal::prelude::*; +use hal::pwm::hrtim::HrPwmExt; +use hal::pwm::hrtim::Pscl4; use hal::rcc; use hal::stm32; -use hal::time::RateExtU32; use stm32g4xx_hal as hal; mod utils; extern crate cortex_m_rt as rt; @@ -44,7 +45,13 @@ fn main() -> ! { // ------------------------ ---------------------------- ---- type Prescaler = Pscl4; // Prescaler of 4 - let (timer, cr1, _cr2, _cr3, _cr4, (out1, out2)) = dp.HRTIM_TIMA.pwm_hrtim::((pin_a, pin_b), rcc) + + let mut p = dp.HRTIM_TIMA.pwm::<_, _, Prescaler, _, _>(pin_a, 10_u32.kHz(), &mut rcc); + p.set_duty(0xEFFF); + p.enable(); + + + /*let (timer, cr1, _cr2, _cr3, _cr4, (out1, out2)) = dp.HRTIM_TIMA.pwm_hrtim::<_, Prescaler>((pin_a, pin_b), 10_u32.kHz(), &mut rcc) .period(0xFFFF) .mode(Mode::PushPull) // Set push pull mode, out1 and out2 are // alternated every period with one being @@ -62,7 +69,7 @@ fn main() -> ! { // *---- Perhaps multiple EventSources could be Or:ed together? cr1.set_duty(timer.get_period() / 3); - timer.set_period(foo); + timer.set_period(foo);*/ loop { cortex_m::asm::nop() diff --git a/src/pwm.rs b/src/pwm.rs index 4aa5aa56..74316d35 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -1376,12 +1376,7 @@ macro_rules! tim_hal { self.count = CountSettings::Explicit { period, prescaler }; - self; - - todo!() // This needs function needs to be disabled for HrTim since HrTim's prescaler is different: - // * is only on the form (1 << N) (N: 1..=7), thus no arbitrary 16-bit numbers. - // * since HrTimers can only work with HrTimer's with the same prescaler(work as in control and sync to with other, this is yet to be exposed) - // * This + the fact that "The prescaler can not be changed while the HrTimer is running" led me to implement the prescaler as a type parameter + self } /// Set the period; PWM count runs from 0 to period, repeating every (period+1) counts @@ -1519,22 +1514,6 @@ tim_hal! { TIM20: (tim20, u16, Timer16Bit, BDTR: bdtr, set_bit, af1, set_bit), } -macro_rules! tim_hal_foreach_timer { - ($($TIMX:ident: $timX:ident,)+) => {$( - tim_hal!{ - // TODO: HRTIM_MASTER - $TIMX: ($timX, u16, TimerHrTim), - $TIMX: ($timX, u16, TimerHrTim), - $TIMX: ($timX, u16, TimerHrTim), - $TIMX: ($timX, u16, TimerHrTim), - $TIMX: ($timX, u16, TimerHrTim), - $TIMX: ($timX, u16, TimerHrTim), - $TIMX: ($timX, u16, TimerHrTim), - $TIMX: ($timX, u16, TimerHrTim), - } - )+}; -} - pub trait PwmPinEnable { fn ccer_enable(&mut self); fn ccer_disable(&mut self); diff --git a/src/pwm/hrtim.rs b/src/pwm/hrtim.rs index 882b3e3d..34c9201b 100644 --- a/src/pwm/hrtim.rs +++ b/src/pwm/hrtim.rs @@ -29,19 +29,19 @@ starta timer: MCEN or TxCEN oklart... use core::marker::PhantomData; use crate::gpio::gpioa::{PA8, PA9}; -use crate::gpio::{self, Alternate, AF13}; +use crate::gpio::{Alternate, AF13}; use crate::stm32::{ HRTIM_COMMON, HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF, }; -use super::{ActiveHigh, Alignment, ComplementaryImpossible, Pins, Pwm, TimerType}; +use super::{ActiveHigh, Alignment, ComplementaryImpossible, Pins, Pwm, PwmPinEnable, TimerType}; use crate::rcc::{Enable, GetBusFreq, Rcc, Reset}; use crate::stm32::RCC; use crate::time::Hertz; -struct CH1(PhantomData); -struct CH2(PhantomData); +pub struct CH1(PhantomData); +pub struct CH2(PhantomData); macro_rules! pins { ($($TIMX:ty: @@ -84,67 +84,88 @@ pub struct Hrtimer { cmp_value4: u16, } -impl TimerType for CH1 +/*impl TimerType for PSCL where PSCL: HrtimPrescaler, { fn calculate_frequency(base_freq: Hertz, freq: Hertz, alignment: Alignment) -> (u32, u16) { - >::calculate_frequency(base_freq, freq, alignment) + ::calculate_frequency(base_freq, freq, alignment) } +}*/ + +// HrPwmExt trait +/// Allows the pwm() method to be added to the peripheral register structs from the device crate +pub trait HrPwmExt: Sized { + /// The requested frequency will be rounded to the nearest achievable frequency; the actual frequency may be higher or lower than requested. + fn pwm(self, _pins: PINS, frequency: T, rcc: &mut Rcc) -> PINS::Channel + where + PINS: Pins, + T: Into, + U: HrtimChannel, + PSCL: HrtimPrescaler; } -impl TimerType for CH2 -where - PSCL: HrtimPrescaler, -{ - fn calculate_frequency(base_freq: Hertz, freq: Hertz, alignment: Alignment) -> (u32, u16) { - >::calculate_frequency(base_freq, freq, alignment) - } +// Implement HrPwmExt trait for hrtimer +macro_rules! pwm_ext_hal { + ($TIMX:ident: $timX:ident) => { + impl HrPwmExt for $TIMX { + fn pwm( + self, + pins: PINS, + frequency: T, + rcc: &mut Rcc, + ) -> PINS::Channel + where + PINS: Pins, + T: Into, + U: HrtimChannel, + PSCL: HrtimPrescaler, + { + $timX(self, pins, frequency.into(), rcc) + } + } + }; } // Implement PWM configuration for timer macro_rules! hrtim_hal { ($($TIMX:ident: ($timX:ident, $timXcr:ident, $perXr:ident, $tXcen:ident),)+) => { $( - //pwm_ext_hal!($TIMX: $timX); + pwm_ext_hal!($TIMX: $timX); /// Configures PWM - fn $timX( + fn $timX( tim: $TIMX, - master: &mut HRTIM_MASTER, - common: &mut HRTIM_COMMON, _pins: PINS, freq: Hertz, rcc: &mut Rcc, ) -> PINS::Channel where PINS: super::Pins<$TIMX, T, U>, - T: TimerType, + T: HrtimChannel, + PSCL: HrtimPrescaler, { unsafe { - let rcc_ptr = &(*RCC::ptr()); + let rcc_ptr = &*RCC::ptr(); $TIMX::enable(rcc_ptr); $TIMX::reset(rcc_ptr); } let clk = $TIMX::get_timer_frequency(&rcc.clocks); - let (period, psc) = ::calculate_frequency(clk, freq, Alignment::Left); + let (period, psc) = >::calculate_frequency(clk, freq, Alignment::Left); // Write prescaler - tim.$timXcr.write(|w| { unsafe { w.cont().set_bit().ck_pscx().bits(psc as u8) } }); + tim.$timXcr.write(|w| unsafe { w.cont().set_bit().ck_pscx().bits(psc as u8) }); // Write period - tim.$perXr.write(|w| { unsafe { w.perx().bits(period as u16) } }); + tim.$perXr.write(|w| unsafe { w.perx().bits(period as u16) }); // Start timer - master.mcr.modify(|_r, w| { unsafe { w.$tXcen().set_bit() }}); - - // Enable output 1 - //self.enable(); - - // Enable output 2 - //common.oenr.modify(|_r, w| { unsafe { w.tX2oen().set_bit() } }); + cortex_m::interrupt::free(|_| { + let master = unsafe { &*HRTIM_MASTER::ptr() }; + master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); + }); todo!() } @@ -154,29 +175,22 @@ macro_rules! hrtim_hal { macro_rules! hrtim_pin_hal { ($($TIMX:ident: - ($CH:ty, $ccxe:ident, $ccxp:ident, $ccmrx_output:ident, $ocxpe:ident, $ocxm:ident, - $ccrx:ident, $typ:ident $(,$ccxne:ident, $ccxnp:ident)*),)+ + ($CH:ident, $perXr:ident, $cmpXYr:ident, $cmpYx:ident, $cmpY:ident, $tXYoen:ident, $setXYr:ident, $rstXYr:ident),)+ ) => { $( - impl hal::PwmPin for Pwm<$TIMX, $CH, COMP, POL, NPOL> - where Pwm<$TIMX, $CH, COMP, POL, NPOL>: PwmPinEnable { + impl hal::PwmPin for Pwm<$TIMX, $CH, COMP, POL, NPOL> + where Pwm<$TIMX, $CH, COMP, POL, NPOL>: PwmPinEnable { type Duty = u16; // You may not access self in the following methods! // See unsafe above fn disable(&mut self) { - // TODO: How do we do this while preventing data race due to shared register - - // Disable output Y on channel X - //HRTIM_COMMON.oenr.modify(|_r, w| { unsafe { w.$tXYoen().clear_bit() } }); + self.ccer_disable(); } fn enable(&mut self) { - // TODO: How do we do this while preventing data race due to shared register - - // Enable output Y on channel X - //HRTIM_COMMON.oenr.modify(|_r, w| { unsafe { w.$tXYoen().set_bit() } }); + self.ccer_enable(); } fn get_duty(&self) -> Self::Duty { @@ -184,7 +198,7 @@ macro_rules! hrtim_pin_hal { // Even though the field is 20 bits long for 16-bit counters, only 16 bits are // valid, so we convert to the appropriate type. - tim.$ccrx().read().ccr().bits() as $typ + tim.$cmpXYr.read().$cmpYx().bits() } fn get_max_duty(&self) -> Self::Duty { @@ -192,7 +206,7 @@ macro_rules! hrtim_pin_hal { // Even though the field is 20 bits long for 16-bit counters, only 16 bits are // valid, so we convert to the appropriate type. - let arr = tim.arr.read().arr().bits() as $typ; + let arr = tim.$perXr.read().perx().bits(); // One PWM cycle is ARR+1 counts long // Valid PWM duty cycles are 0 to ARR+1 @@ -209,7 +223,41 @@ macro_rules! hrtim_pin_hal { fn set_duty(&mut self, duty: Self::Duty) { let tim = unsafe { &*$TIMX::ptr() }; - tim.$ccrx().write(|w| unsafe { w.ccr().bits(duty.into()) }); + tim.$cmpXYr.write(|w| unsafe { w.$cmpYx().bits(duty) }); + } + } + + // Enable implementation for ComplementaryImpossible + impl PwmPinEnable for Pwm<$TIMX, $CH, ComplementaryImpossible, POL, NPOL> { + fn ccer_enable(&mut self) { + let tim = unsafe { &*$TIMX::ptr() }; + // Select period as a SET-event + tim.$setXYr.write(|w| { w.per().set_bit() } ); + + // Select cmpY as a RESET-event + tim.$rstXYr.write(|w| { w.$cmpY().set_bit() } ); + + // TODO: Should this part only be in Pwm::enable? + // Enable output Y on channel X + // NOTE(unsafe) critical section prevents races + cortex_m::interrupt::free(|_| { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.oenr.modify(|_r, w| { w.$tXYoen().set_bit() }); + }); + } + fn ccer_disable(&mut self) { + let tim = unsafe { &*$TIMX::ptr() }; + // Clear SET-events + tim.$setXYr.reset(); + + // TODO: Should this part only be in Pwm::disable + // Do we want a potentially floating output after after disable? + // Disable output Y on channel X + // NOTE(unsafe) critical section prevents races + cortex_m::interrupt::free(|_| { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.oenr.modify(|_r, w| { w.$tXYoen().clear_bit() }); + }); } } )+ @@ -223,22 +271,44 @@ hrtim_hal! { HRTIM_TIMC: (hrtim_timc, timccr, percr, tccen), HRTIM_TIMD: (hrtim_timd, timdcr, perdr, tdcen), HRTIM_TIME: (hrtim_time, timecr, perer, tecen), + + // TODO: why is there no rstf1r? + //HRTIM_TIMF: (hrtim_timf1, timfcr, perfr, tfcen, setf1r, rstf1r, cmp1), HRTIM_TIMF: (hrtim_timf, timfcr, perfr, tfcen), } hrtim_pin_hal! { - HRTIM_TIMA: (CH1), - HRTIM_TIMA: (CH2) + HRTIM_TIMA: (CH1, perar, cmp1ar, cmp1x, cmp1, ta1oen, seta1r, rsta1r), + HRTIM_TIMA: (CH2, perar, cmp3ar, cmp3x, cmp3, ta2oen, seta2r, rsta2r), + + HRTIM_TIMB: (CH1, perbr, cmp1br, cmp1x, cmp1, tb1oen, setb1r, rstb1r), + HRTIM_TIMB: (CH2, perbr, cmp3br, cmp3x, cmp3, tb2oen, setb2r, rstb2r), + + HRTIM_TIMC: (CH1, percr, cmp1cr, cmp1x, cmp1, tc1oen, setc1r, rstc1r), + HRTIM_TIMC: (CH2, percr, cmp3cr, cmp3x, cmp3, tc2oen, setc2r, rstc2r), + + + HRTIM_TIMD: (CH1, perdr, cmp1dr, cmp1x, cmp1, td1oen, setd1r, rstd1r), + HRTIM_TIMD: (CH2, perdr, cmp3dr, cmp3x, cmp3, td2oen, setd2r, rstd2r), + + HRTIM_TIME: (CH1, perer, cmp1er, cmp1x, cmp1, te1oen, sete1r, rste1r), + HRTIM_TIME: (CH2, perer, cmp3er, cmp3x, cmp3, te2oen, sete2r, rste2r), + + // TODO: tf1oen and rstf1r are not defined + //HRTIM_TIMF: (CH1, perfr, cmp1fr, cmp1x, cmp1, tf1oen, setf1r, rstf1r), + + // TODO: tf2oen is not defined + //HRTIM_TIMF: (CH2, perfr, cmp3fr, cmp3x, cmp3, tf2oen, setf2r, rstf2r), } -trait HrtimPrescaler { +pub trait HrtimPrescaler { const BITS: u8; const VALUE: u8; } macro_rules! impl_pscl { ($($t:ident => $b:literal, $c:literal,)+) => {$( - struct $t; + pub struct $t; impl HrtimPrescaler for $t { const BITS: u8 = $b; const VALUE: u8 = $c; @@ -278,3 +348,8 @@ impl super::TimerType for TimerHrTim { (period, PSC::BITS.into()) } } + +pub trait HrtimChannel {} + +impl HrtimChannel for CH1{} +impl HrtimChannel for CH2{} \ No newline at end of file From 14cb9d2c6bb56658c6bd89732e8bc3eec66bb5c5 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 20 May 2023 13:13:36 +0200 Subject: [PATCH 17/88] Dual channel support and cargo fmt --- examples/hrtim.rs | 31 ++++++++++++++------------ src/pwm.rs | 5 +---- src/pwm/hrtim.rs | 55 ++++++++++++++++++++++++++++------------------- 3 files changed, 51 insertions(+), 40 deletions(-) diff --git a/examples/hrtim.rs b/examples/hrtim.rs index 5bfa8064..c6e97894 100644 --- a/examples/hrtim.rs +++ b/examples/hrtim.rs @@ -4,10 +4,10 @@ use cortex_m_rt::entry; use fugit::RateExtU32; -use hal::gpio::AF13; use hal::gpio::gpioa::PA8; -use hal::gpio::Alternate; use hal::gpio::gpioa::PA9; +use hal::gpio::Alternate; +use hal::gpio::AF13; use hal::prelude::*; use hal::pwm::hrtim::HrPwmExt; use hal::pwm::hrtim::Pscl4; @@ -20,7 +20,7 @@ extern crate cortex_m_rt as rt; #[entry] fn main() -> ! { let dp = stm32::Peripherals::take().expect("cannot take peripherals"); - + //Set system frequency to 16MHz * 75/4/2 = 150MHz let mut rcc = dp.RCC.freeze(rcc::Config::pll().pll_cfg(rcc::PllConfig { n: rcc::PllNMul::MUL_75, @@ -33,27 +33,30 @@ fn main() -> ! { let pin_a: PA8> = gpioa.pa8.into_alternate(); let pin_b: PA9> = gpioa.pa9.into_alternate(); + type Prescaler = Pscl4; // Prescaler of 4 + + let (mut p1, mut p2) = + dp.HRTIM_TIMA + .pwm::<_, _, Prescaler, _, _>((pin_a, pin_b), 10_u32.kHz(), &mut rcc); + p1.set_duty(0x1FFF); + p2.set_duty(0xEFFF); + + p1.enable(); + p2.enable(); + // . . // . 30% . // ---- . ---- - //out1 | | . | | - // | | . | | + //out1 | | . | | + // | | . | | // -------- ---------------------------- -------------------- // . ---- . ---- //out2 . | | | | // . | | | | // ------------------------ ---------------------------- ---- - - type Prescaler = Pscl4; // Prescaler of 4 - - let mut p = dp.HRTIM_TIMA.pwm::<_, _, Prescaler, _, _>(pin_a, 10_u32.kHz(), &mut rcc); - p.set_duty(0xEFFF); - p.enable(); - - /*let (timer, cr1, _cr2, _cr3, _cr4, (out1, out2)) = dp.HRTIM_TIMA.pwm_hrtim::<_, Prescaler>((pin_a, pin_b), 10_u32.kHz(), &mut rcc) .period(0xFFFF) - .mode(Mode::PushPull) // Set push pull mode, out1 and out2 are + .mode(Mode::PushPull) // Set push pull mode, out1 and out2 are // alternated every period with one being // inactive and the other getting to output its wave form // as normal diff --git a/src/pwm.rs b/src/pwm.rs index 74316d35..7d4e9b55 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -169,10 +169,7 @@ //! This code has been taken from the stm32h7xx-hal project and modified slightly to support //! STM32G4xx MCUs. It has originally been licensed under the 0-clause BSD license. -#[cfg(any( - feature = "stm32g474", - feature = "stm32g484" -))] +#[cfg(any(feature = "stm32g474", feature = "stm32g484"))] pub mod hrtim; use core::marker::PhantomData; diff --git a/src/pwm/hrtim.rs b/src/pwm/hrtim.rs index 34c9201b..d8180317 100644 --- a/src/pwm/hrtim.rs +++ b/src/pwm/hrtim.rs @@ -27,6 +27,7 @@ starta timer: MCEN or TxCEN oklart... */ use core::marker::PhantomData; +use core::mem::MaybeUninit; use crate::gpio::gpioa::{PA8, PA9}; use crate::gpio::{Alternate, AF13}; @@ -73,24 +74,38 @@ pins! { ] } -pub struct Hrtimer { - _prescaler: PhantomData, - _timer: PhantomData, - period: u16, +// automatically implement Pins trait for tuples of individual pins +macro_rules! pins_tuples { + // Tuple of two pins + ($(($CHA:ident, $CHB:ident)),*) => { + $( + impl Pins, $CHB), (TA, TB)> for (CHA, CHB) + where + CHA: Pins, TA>, + CHB: Pins, TB>, + { + type Channel = (Pwm, TA, ActiveHigh, ActiveHigh>, Pwm, TB, ActiveHigh, ActiveHigh>); + } + + impl HrtimChannel for ($CHA, $CHB) {} + )* + }; +} - cmp_value1: u16, - cmp_value2: u16, - cmp_value3: u16, - cmp_value4: u16, +pins_tuples! { + (CH1, CH2), + (CH2, CH1) } -/*impl TimerType for PSCL -where - PSCL: HrtimPrescaler, -{ - fn calculate_frequency(base_freq: Hertz, freq: Hertz, alignment: Alignment) -> (u32, u16) { - ::calculate_frequency(base_freq, freq, alignment) - } +/*pub struct Hrtimer { + _prescaler: PhantomData, + _timer: PhantomData, + period: u16, // $perXr.perx + + cmp_value1: u16, // $cmpX1r.cmp1x + cmp_value2: u16, // $cmpX2r.cmp2x + cmp_value3: u16, // $cmpX3r.cmp3x + cmp_value4: u16, // $cmpX4r.cmp4x }*/ // HrPwmExt trait @@ -167,7 +182,7 @@ macro_rules! hrtim_hal { master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); }); - todo!() + unsafe { MaybeUninit::::uninit().assume_init() } } )+ } @@ -196,16 +211,12 @@ macro_rules! hrtim_pin_hal { fn get_duty(&self) -> Self::Duty { let tim = unsafe { &*$TIMX::ptr() }; - // Even though the field is 20 bits long for 16-bit counters, only 16 bits are - // valid, so we convert to the appropriate type. tim.$cmpXYr.read().$cmpYx().bits() } fn get_max_duty(&self) -> Self::Duty { let tim = unsafe { &*$TIMX::ptr() }; - // Even though the field is 20 bits long for 16-bit counters, only 16 bits are - // valid, so we convert to the appropriate type. let arr = tim.$perXr.read().perx().bits(); // One PWM cycle is ARR+1 counts long @@ -351,5 +362,5 @@ impl super::TimerType for TimerHrTim { pub trait HrtimChannel {} -impl HrtimChannel for CH1{} -impl HrtimChannel for CH2{} \ No newline at end of file +impl HrtimChannel for CH1 {} +impl HrtimChannel for CH2 {} From 4ca91c79d593d1d0ef1b9ac942cfcc689699eb66 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 20 May 2023 22:01:03 +0200 Subject: [PATCH 18/88] Almost... --- examples/hrtim.rs | 67 +++--- examples/hrtim_simple.rs | 70 ++++++ src/pwm.rs | 17 +- src/pwm/hrtim.rs | 479 ++++++++++++++++++++++++++++++++++++--- 4 files changed, 572 insertions(+), 61 deletions(-) create mode 100644 examples/hrtim_simple.rs diff --git a/examples/hrtim.rs b/examples/hrtim.rs index c6e97894..1c7b42d8 100644 --- a/examples/hrtim.rs +++ b/examples/hrtim.rs @@ -2,14 +2,21 @@ #![no_main] #![no_std] +use cortex_m::delay; use cortex_m_rt::entry; +use fugit::ExtU32; use fugit::RateExtU32; use hal::gpio::gpioa::PA8; use hal::gpio::gpioa::PA9; use hal::gpio::Alternate; use hal::gpio::AF13; use hal::prelude::*; +use hal::pwm::hrtim::EventSource; +use hal::pwm::hrtim::HrCompareRegister; +use hal::pwm::hrtim::HrOutput; +use hal::pwm::hrtim::HrPwmAdvExt; use hal::pwm::hrtim::HrPwmExt; +use hal::pwm::hrtim::HrTimer; use hal::pwm::hrtim::Pscl4; use hal::rcc; use hal::stm32; @@ -20,8 +27,9 @@ extern crate cortex_m_rt as rt; #[entry] fn main() -> ! { let dp = stm32::Peripherals::take().expect("cannot take peripherals"); - - //Set system frequency to 16MHz * 75/4/2 = 150MHz + let cp = stm32::CorePeripherals::take().expect("cannot take core"); + // Set system frequency to 16MHz * 75/4/2 = 150MHz + // This would lead to HrTim running at 150MHz * 32 = 4.8GHz... let mut rcc = dp.RCC.freeze(rcc::Config::pll().pll_cfg(rcc::PllConfig { n: rcc::PllNMul::MUL_75, m: rcc::PllMDiv::DIV_4, @@ -29,20 +37,15 @@ fn main() -> ! { ..Default::default() })); - let gpioa = dp.GPIOA.split(&mut rcc); - let pin_a: PA8> = gpioa.pa8.into_alternate(); - let pin_b: PA9> = gpioa.pa9.into_alternate(); + let mut delay = cp.SYST.delay(&rcc.clocks); + // ...with a prescaler of 4 this gives us a HrTimer with a tick rate of 1.2GHz + // With max the max period set, this would be 1.2GHz/2^16 ~= 18kHz... type Prescaler = Pscl4; // Prescaler of 4 - let (mut p1, mut p2) = - dp.HRTIM_TIMA - .pwm::<_, _, Prescaler, _, _>((pin_a, pin_b), 10_u32.kHz(), &mut rcc); - p1.set_duty(0x1FFF); - p2.set_duty(0xEFFF); - - p1.enable(); - p2.enable(); + let gpioa = dp.GPIOA.split(&mut rcc); + let pin_a: PA8> = gpioa.pa8.into_alternate(); + let pin_b: PA9> = gpioa.pa9.into_alternate(); // . . // . 30% . @@ -54,27 +57,33 @@ fn main() -> ! { //out2 . | | | | // . | | | | // ------------------------ ---------------------------- ---- - /*let (timer, cr1, _cr2, _cr3, _cr4, (out1, out2)) = dp.HRTIM_TIMA.pwm_hrtim::<_, Prescaler>((pin_a, pin_b), 10_u32.kHz(), &mut rcc) + let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp + .HRTIM_TIMA + .pwm_advanced(pin_a, &mut rcc) .period(0xFFFF) - .mode(Mode::PushPull) // Set push pull mode, out1 and out2 are - // alternated every period with one being - // inactive and the other getting to output its wave form - // as normal + .push_pull_mode(true) // Set push pull mode, out1 and out2 are + // alternated every period with one being + // inactive and the other getting to output its wave form + // as normal .finalize(); - out1.rst_event(EventSource::Cr1); // Set low on compare match with cr1 - out2.rst_event(EventSource::Cr1); - - out1.set_event(EventSource::Period); // Set high at new period - out2.set_event(EventSource::Period); - // ^ - // | - // *---- Perhaps multiple EventSources could be Or:ed together? + out1.enable_rst_event(EventSource::Cr1); // Set low on compare match with cr1 + //out2.rst_event(EventSource::Cr1); - cr1.set_duty(timer.get_period() / 3); - timer.set_period(foo);*/ + out1.enable_set_event(EventSource::Period); // Set high at new period + //out2.set_event(EventSource::Period); + // ^ + // | + // *---- Perhaps multiple EventSources could be Or:ed together? loop { - cortex_m::asm::nop() + for i in 1..10 { + let new_period = u16::MAX / i; + + cr1.set_duty(new_period / 3); + timer.set_period(new_period / i); + + delay.delay(500_u32.millis()); + } } } diff --git a/examples/hrtim_simple.rs b/examples/hrtim_simple.rs new file mode 100644 index 00000000..2e380769 --- /dev/null +++ b/examples/hrtim_simple.rs @@ -0,0 +1,70 @@ +//This example puts the timer in PWM mode using the specified pin with a frequency of 100Hz and a duty cycle of 50%. +#![no_main] +#![no_std] + +use cortex_m_rt::entry; +use fugit::RateExtU32; +use hal::gpio::gpioa::PA8; +use hal::gpio::gpioa::PA9; +use hal::gpio::Alternate; +use hal::gpio::AF13; +use hal::prelude::*; +use hal::pwm::hrtim::HrPwmExt; +use hal::pwm::hrtim::Pscl4; +use hal::rcc; +use hal::stm32; +use stm32g4xx_hal as hal; +mod utils; +extern crate cortex_m_rt as rt; + +#[entry] +fn main() -> ! { + let dp = stm32::Peripherals::take().expect("cannot take peripherals"); + + // Set system frequency to 16MHz * 75/4/2 = 150MHz + // This would lead to HrTim running at 150MHz * 32 = 4.8GHz... + let mut rcc = dp.RCC.freeze(rcc::Config::pll().pll_cfg(rcc::PllConfig { + n: rcc::PllNMul::MUL_75, + m: rcc::PllMDiv::DIV_4, + r: Some(rcc::PllRDiv::DIV_2), + ..Default::default() + })); + + // ...with a prescaler of 4 this gives us a HrTimer with a tick rate of 1.2GHz + // With max the max period set, this would be 1.2GHz/2^16 ~= 18kHz... + type Prescaler = Pscl4; // Prescaler of 4 + + let gpioa = dp.GPIOA.split(&mut rcc); + let pin_a: PA8> = gpioa.pa8.into_alternate(); + let pin_b: PA9> = gpioa.pa9.into_alternate(); + + // . . + // . 33% . + // ---- . ---- + //out1 | | . | | + // | | . | | + // -------- ---------------------------- -------------------- + // . + // 50% . + // -------- . -------- + //out2 | | . | | + // | | . | | + // -------- ------------------------ ---------------- + + // ...Meaning that we will have plenty of resolution when producing a 20kHz waveform + let (mut p1, mut p2) = + dp.HRTIM_TIMA + .pwm::<_, _, Prescaler, _, _>((pin_a, pin_b), 20_u32.kHz(), &mut rcc); + let max_duty = p1.get_max_duty(); + + p1.set_duty(max_duty / 3); // Set output 1 to about 33% + p2.set_duty(max_duty / 2); // Set output 2 to 50% + + // Enable the outputs + p1.enable(); + p2.enable(); + + loop { + cortex_m::asm::nop() + } +} diff --git a/src/pwm.rs b/src/pwm.rs index 7d4e9b55..219ab16d 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -175,6 +175,8 @@ pub mod hrtim; use core::marker::PhantomData; use core::mem::MaybeUninit; +use fugit::HertzU64; + use crate::hal; use crate::stm32::LPTIMER1; use crate::stm32::RCC; @@ -1030,7 +1032,7 @@ pins! { trait TimerType { /// Returns (arr, psc) bits - fn calculate_frequency(base_freq: Hertz, freq: Hertz, alignment: Alignment) -> (u32, u16); + fn calculate_frequency(base_freq: HertzU64, freq: Hertz, alignment: Alignment) -> (u32, u16); } /// Any 32-bit timer @@ -1039,7 +1041,8 @@ struct Timer32Bit; impl TimerType for Timer32Bit { // Period and prescaler calculator for 32-bit timers // Returns (arr, psc) bits - fn calculate_frequency(base_freq: Hertz, freq: Hertz, alignment: Alignment) -> (u32, u16) { + fn calculate_frequency(base_freq: HertzU64, freq: Hertz, alignment: Alignment) -> (u32, u16) { + let freq = HertzU64::from(freq); let divisor = if let Alignment::Center = alignment { freq * 2 } else { @@ -1049,7 +1052,9 @@ impl TimerType for Timer32Bit { // Round to the nearest period let arr = (base_freq + (divisor / 2)) / divisor - 1; - (arr, 0) + assert!(arr <= u32::MAX as u64); + + (arr as u32, 0) } } @@ -1060,7 +1065,7 @@ impl TimerType for Timer16Bit { // Period and prescaler calculator for 16-bit timers // Returns (arr, psc) // Returns as (u32, u16) to be compatible but arr will always be a valid u16 - fn calculate_frequency(base_freq: Hertz, freq: Hertz, alignment: Alignment) -> (u32, u16) { + fn calculate_frequency(base_freq: HertzU64, freq: Hertz, alignment: Alignment) -> (u32, u16) { let ideal_period = Timer32Bit::calculate_frequency(base_freq, freq, alignment).0 + 1; // Division factor is (PSC + 1) @@ -1187,7 +1192,7 @@ macro_rules! simple_tim_hal { let clk = $TIMX::get_timer_frequency(&rcc.clocks); - let (period, prescale) = <$bits>::calculate_frequency(clk, freq, Alignment::Left); + let (period, prescale) = <$bits>::calculate_frequency(clk.into(), freq, Alignment::Left); // Write prescale tim.psc().write(|w| { unsafe { w.psc().bits(prescale as u16) } }); @@ -1270,7 +1275,7 @@ macro_rules! tim_hal { let (period, prescaler) = match self.count { CountSettings::Explicit { period, prescaler } => (period as u32, prescaler), CountSettings::Frequency( freq ) => { - <$bits>::calculate_frequency(self.base_freq, freq, self.alignment) + <$bits>::calculate_frequency(self.base_freq.into(), freq, self.alignment) }, }; diff --git a/src/pwm/hrtim.rs b/src/pwm/hrtim.rs index d8180317..1b955df6 100644 --- a/src/pwm/hrtim.rs +++ b/src/pwm/hrtim.rs @@ -29,6 +29,8 @@ starta timer: MCEN or TxCEN oklart... use core::marker::PhantomData; use core::mem::MaybeUninit; +use fugit::HertzU64; + use crate::gpio::gpioa::{PA8, PA9}; use crate::gpio::{Alternate, AF13}; use crate::stm32::{ @@ -36,7 +38,10 @@ use crate::stm32::{ HRTIM_TIMF, }; -use super::{ActiveHigh, Alignment, ComplementaryImpossible, Pins, Pwm, PwmPinEnable, TimerType}; +use super::{ + ActiveHigh, Alignment, ComplementaryImpossible, FaultDisabled, Pins, Pwm, PwmPinEnable, + TimerType, +}; use crate::rcc::{Enable, GetBusFreq, Rcc, Reset}; use crate::stm32::RCC; use crate::time::Hertz; @@ -44,34 +49,36 @@ use crate::time::Hertz; pub struct CH1(PhantomData); pub struct CH2(PhantomData); +/// Internal enum that keeps track of the count settings before PWM is finalized +enum CountSettings { + Frequency(Hertz), + Period(u16), +} + macro_rules! pins { - ($($TIMX:ty: - CH1: [$($( #[ $pmeta1:meta ] )* $CH1:ty),*] CH2: [$($( #[ $pmeta2:meta ] )* $CH2:ty),*])+) => { + ($($TIMX:ty: CH1: $CH1:ty, CH2: $CH2:ty)+) => { $( - $( - $( #[ $pmeta1 ] )* - impl Pins<$TIMX, CH1, ComplementaryImpossible> for $CH1 { - type Channel = Pwm<$TIMX, CH1, ComplementaryImpossible, ActiveHigh, ActiveHigh>; - } - )* - $( - $( #[ $pmeta2 ] )* - impl Pins<$TIMX, CH2, ComplementaryImpossible> for $CH2 { - type Channel = Pwm<$TIMX, CH2, ComplementaryImpossible, ActiveHigh, ActiveHigh>; - } - )* + impl Pins<$TIMX, CH1, ComplementaryImpossible> for $CH1 { + type Channel = Pwm<$TIMX, CH1, ComplementaryImpossible, ActiveHigh, ActiveHigh>; + } + + impl Pins<$TIMX, CH2, ComplementaryImpossible> for $CH2 { + type Channel = Pwm<$TIMX, CH2, ComplementaryImpossible, ActiveHigh, ActiveHigh>; + } + + impl ToHrOut for $CH1 { + type Out = HrOut1<$TIMX>; + } + + impl ToHrOut for $CH2 { + type Out = HrOut2<$TIMX>; + } )+ } } pins! { - HRTIM_TIMA: - CH1: [ - PA8> - ] - CH2: [ - PA9> - ] + HRTIM_TIMA: CH1: PA8>, CH2: PA9> } // automatically implement Pins trait for tuples of individual pins @@ -120,6 +127,124 @@ pub trait HrPwmExt: Sized { PSCL: HrtimPrescaler; } +pub trait HrPwmAdvExt: Sized { + fn pwm_advanced( + self, + _pins: PINS, + rcc: &mut Rcc, + ) -> HrPwmBuilder + where + PINS: Pins; +} + +/// HrPwmBuilder is used to configure advanced HrTim PWM features +pub struct HrPwmBuilder { + _tim: PhantomData, + _pins: PhantomData, + _channel: PhantomData, + _fault: PhantomData, + _prescaler: PhantomData, + alignment: Alignment, + base_freq: HertzU64, + count: CountSettings, + enable_push_pull: bool, + //bkin_enabled: bool, // If the FAULT type parameter is FaultEnabled, either bkin or bkin2 must be enabled + //bkin2_enabled: bool, + //fault_polarity: Polarity, + //deadtime: NanoSecond, +} + +pub trait HrCompareRegister{ + fn get_duty(&self) -> u16; + fn set_duty(&mut self, duty: u16); +} + +pub struct HrCr1(PhantomData); +pub struct HrCr2(PhantomData); +pub struct HrCr3(PhantomData); +pub struct HrCr4(PhantomData); + +pub struct HrTim{ + _timer: PhantomData, + _prescaler: PhantomData, +} + +pub trait HrTimer { + fn get_period(&self) -> u16; + fn set_period(&mut self, period: u16); +} + +pub trait HrOutput{ + fn enable(&mut self); + fn disable(&mut self); + + fn enable_set_event(&mut self, set_event: EventSource); + fn disable_set_event(&mut self, set_event: EventSource); + + fn enable_rst_event(&mut self, reset_event: EventSource); + fn disable_rst_event(&mut self, reset_event: EventSource); +} + +pub enum EventSource { + /// Compare match with compare register 1 of this timer + Cr1, + + /// Compare match with compare register 2 of this timer + Cr2, + + /// Compare match with compare register 3 of this timer + Cr3, + + /// Compare match with compare register 4 of this timer + Cr4, + + Period, + + /* + /// Compare match with compare register 1 of master timer + MasterCr1, + + /// Compare match with compare register 2 of master timer + MasterCr2, + + /// Compare match with compare register 3 of master timer + MasterCr3, + + /// Compare match with compare register 4 of master timer + MasterCr4, + + MasterPeriod,*/ + + // TODO: These are unique for every timer output + //Extra(E) +} +pub trait ToHrOut { + type Out: HrOutput; +} + +/*impl ToHrOut for (TIM, CH1) + where HrOut1: HrOutput +{ + type Out = HrOut1; +} + +impl ToHrOut for (TIM, CH2) +where HrOut2: HrOutput{ + type Out = HrOut2; +}*/ + +impl ToHrOut for (CHA, CHB) +where + CHA: ToHrOut, + CHB: ToHrOut, + (CHA::Out, CHA::Out): HrOutput +{ + type Out = (CHA::Out, CHA::Out); +} + +pub struct HrOut1(PhantomData); +pub struct HrOut2(PhantomData); + // Implement HrPwmExt trait for hrtimer macro_rules! pwm_ext_hal { ($TIMX:ident: $timX:ident) => { @@ -166,12 +291,15 @@ macro_rules! hrtim_hal { $TIMX::reset(rcc_ptr); } - let clk = $TIMX::get_timer_frequency(&rcc.clocks); + // TODO: That 32x factor... Is that done by $TIMX::get_timer_frequency + // or should we do that? Also that will likely risk overflowing u32 since + // 170MHz * 32 = 5.44GHz > u32::MAX.Hz() + let clk = HertzU64::from($TIMX::get_timer_frequency(&rcc.clocks)) * 32; - let (period, psc) = >::calculate_frequency(clk, freq, Alignment::Left); + let (period, prescaler_bits) = >::calculate_frequency(clk, freq, Alignment::Left); // Write prescaler - tim.$timXcr.write(|w| unsafe { w.cont().set_bit().ck_pscx().bits(psc as u8) }); + tim.$timXcr.write(|w| unsafe { w.cont().set_bit().ck_pscx().bits(prescaler_bits as u8) }); // Write period tim.$perXr.write(|w| unsafe { w.perx().bits(period as u16) }); @@ -184,6 +312,173 @@ macro_rules! hrtim_hal { unsafe { MaybeUninit::::uninit().assume_init() } } + + impl HrPwmAdvExt for $TIMX { + fn pwm_advanced( + self, + _pins: PINS, + rcc: &mut Rcc, + ) -> HrPwmBuilder + where + PINS: Pins + { + unsafe { + let rcc_ptr = &(*RCC::ptr()); + $TIMX::enable(rcc_ptr); + $TIMX::reset(rcc_ptr); + } + + // 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($TIMX::get_timer_frequency(&rcc.clocks)) * 32; + + HrPwmBuilder { + _tim: PhantomData, + _pins: PhantomData, + _channel: PhantomData, + _fault: PhantomData, + _prescaler: PhantomData, + alignment: Alignment::Left, + base_freq: clk, + count: CountSettings::Period(65535), + enable_push_pull: false, + //bkin_enabled: false, + //bkin2_enabled: false, + //fault_polarity: Polarity::ActiveLow, + //deadtime: 0.nanos(), + } + } + } + + impl + HrPwmBuilder<$TIMX, PSCL, PINS, CHANNEL, FAULT> + where + PSCL: HrtimPrescaler, + PINS: Pins<$TIMX, CHANNEL, ComplementaryImpossible> + ToHrOut, + { + pub fn finalize(self) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX>, HrCr2<$TIMX>, HrCr3<$TIMX>, HrCr4<$TIMX>), ::Out) { + let tim = unsafe { &*$TIMX::ptr() }; + + let (period, prescaler_bits) = match self.count { + CountSettings::Period(period) => (period as u32, PSCL::BITS as u16), + CountSettings::Frequency( freq ) => { + >::calculate_frequency(self.base_freq, freq, self.alignment) + }, + }; + + // Write prescaler and any special modes + tim.$timXcr.write(|w| unsafe { + w + // Enable Continous mode + .cont().set_bit() + + // Push-Pull mode + .pshpll().bit(self.enable_push_pull) + + // TODO: add support for more modes + + // Set prescaler + .ck_pscx().bits(prescaler_bits as u8) + }); + + // Write period + tim.$perXr.write(|w| unsafe { w.perx().bits(period as u16) }); + + // Start timer + cortex_m::interrupt::free(|_| { + let master = unsafe { &*HRTIM_MASTER::ptr() }; + master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); + }); + + unsafe { + MaybeUninit::uninit().assume_init() + } + } + + /// Set the PWM frequency; will overwrite the previous prescaler and period + /// The requested frequency will be rounded to the nearest achievable frequency; the actual frequency may be higher or lower than requested. + pub fn frequency>(mut self, freq: T) -> Self { + self.count = CountSettings::Frequency( freq.into() ); + + self + } + + /// Set the prescaler; PWM count runs at base_frequency/(prescaler+1) + pub fn prescaler

(self, _prescaler: P) -> HrPwmBuilder<$TIMX, P, PINS, CHANNEL, FAULT> + where P: HrtimPrescaler { + let HrPwmBuilder { + _tim, + _pins, + _channel, + _fault, + _prescaler: _, + enable_push_pull, + alignment, + base_freq, + count, + } = self; + + let period = match count { + CountSettings::Frequency(_) => u16::MAX, + CountSettings::Period(period) => period, + }; + + let count = CountSettings::Period(period); + + HrPwmBuilder { + _tim, + _pins, + _channel, + _fault, + _prescaler: PhantomData, + enable_push_pull, + alignment, + base_freq, + count, + //bkin_enabled: false, + //bkin2_enabled: false, + //fault_polarity: Polarity::ActiveLow, + //deadtime: 0.nanos(), + } + } + + /// 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 + } + + /// 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 { + self.enable_push_pull = enable; + + self + } + + //pub fn half_mode(mut self, enable: bool) -> Self + + //pub fn interleaved_mode(mut self, mode: _) -> Self + + //pub fn swap_mode(mut self, enable: bool) -> Self + } )+ } } @@ -275,6 +570,138 @@ macro_rules! hrtim_pin_hal { } } +macro_rules! hrtim_out_common { + ($TIMX:ident, $set_event:ident, $register:ident, $action:ident) => {{ + let tim = unsafe { &*$TIMX::ptr() }; + + match $set_event { + EventSource::Cr1 => tim.$register.modify(|_r, w| { w.cmp1().$action() } ), + EventSource::Cr2 => tim.$register.modify(|_r, w| { w.cmp2().$action() } ), + EventSource::Cr3 => tim.$register.modify(|_r, w| { w.cmp3().$action() } ), + EventSource::Cr4 => tim.$register.modify(|_r, w| { w.cmp4().$action() } ), + EventSource::Period => tim.$register.modify(|_r, w| { w.per().$action() } ), + } + }}; +} + +macro_rules! hrtim_out { + ($($TIMX:ident: $out_type:ident: $tXYoen:ident, $setXYr:ident, $rstXYr:ident,)+) => {$( + impl HrOutput for $out_type<$TIMX> { + fn enable(&mut self) { + cortex_m::interrupt::free(|_| { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.oenr.modify(|_r, w| { w.$tXYoen().set_bit() }); + }); + } + + fn disable(&mut self) { + cortex_m::interrupt::free(|_| { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.oenr.modify(|_r, w| { w.$tXYoen().clear_bit() }); + }); + } + + fn enable_set_event(&mut self, set_event: EventSource) { + hrtim_out_common!($TIMX, set_event, $setXYr, set_bit) + } + fn disable_set_event(&mut self, set_event: EventSource) { + hrtim_out_common!($TIMX, set_event, $setXYr, clear_bit) + } + + fn enable_rst_event(&mut self, reset_event: EventSource) { + hrtim_out_common!($TIMX, reset_event, $rstXYr, set_bit) + } + fn disable_rst_event(&mut self, reset_event: EventSource) { + hrtim_out_common!($TIMX, reset_event, $rstXYr, clear_bit) + } + } + )+}; +} + +hrtim_out!{ + HRTIM_TIMA: HrOut1: ta1oen, seta1r, rsta1r, + HRTIM_TIMA: HrOut2: ta2oen, seta2r, rsta2r, + + HRTIM_TIMB: HrOut1: tb1oen, setb1r, rstb1r, + HRTIM_TIMB: HrOut2: tb2oen, setb2r, rstb2r, + + HRTIM_TIMC: HrOut1: tc1oen, setc1r, rstc1r, + HRTIM_TIMC: HrOut2: tc2oen, setc2r, rstc2r, + + HRTIM_TIMD: HrOut1: td1oen, setd1r, rstd1r, + HRTIM_TIMD: HrOut2: td2oen, setd2r, rstd2r, + + HRTIM_TIME: HrOut1: te1oen, sete1r, rste1r, + HRTIM_TIME: HrOut2: te2oen, sete2r, rste2r, + + // TODO: Somehow, there is no rstf1r + //HRTIM_TIMF: HrOut1: tf1oen, setf1r, rstf1r, + + // TODO: Somehow, there is no tf2oen + //HRTIM_TIMF: HrOut2: tf2oen, setf2r, rstf2r, +} + +macro_rules! hrtim_cr_helper { + ($TIMX:ident: $cr_type:ident: $cmpXYr:ident, $cmpYx:ident) => { + impl HrCompareRegister for $cr_type<$TIMX> { + fn get_duty(&self) -> u16 { + let tim = unsafe { &*$TIMX::ptr() }; + + tim.$cmpXYr.read().$cmpYx().bits() + } + fn set_duty(&mut self, duty: u16) { + let tim = unsafe { &*$TIMX::ptr() }; + + tim.$cmpXYr.write(|w| unsafe { w.$cmpYx().bits(duty) }); + } + } + }; +} + +macro_rules! hrtim_cr { + ($($TIMX:ident: [$cmpX1r:ident, $cmpX2r:ident, $cmpX3r:ident, $cmpX4r:ident],)+) => {$( + hrtim_cr_helper!($TIMX: HrCr1: $cmpX1r, cmp1x); + hrtim_cr_helper!($TIMX: HrCr2: $cmpX2r, cmp2x); + hrtim_cr_helper!($TIMX: HrCr3: $cmpX3r, cmp3x); + hrtim_cr_helper!($TIMX: HrCr4: $cmpX4r, cmp4x); + )+}; +} + +macro_rules! hrtim_timer { + ($($TIMX:ident: $perXr:ident,)+) => {$( + impl HrTimer<$TIMX, PSCL> for HrTim<$TIMX, PSCL> { + fn get_period(&self) -> u16 { + let tim = unsafe { &*$TIMX::ptr() }; + + tim.$perXr.read().perx().bits() + } + fn set_period(&mut self, period: u16) { + let tim = unsafe { &*$TIMX::ptr() }; + + tim.$perXr.write(|w| unsafe { w.perx().bits(period as u16) }); + } + } + )+}; +} + +hrtim_timer!{ + HRTIM_TIMA: perar, + HRTIM_TIMB: perbr, + HRTIM_TIMC: percr, + HRTIM_TIMD: perdr, + HRTIM_TIME: perer, + HRTIM_TIMF: perfr, +} + +hrtim_cr!{ + HRTIM_TIMA: [cmp1ar, cmp2ar, cmp3ar, cmp4ar], + HRTIM_TIMB: [cmp1br, cmp2br, cmp3br, cmp4br], + HRTIM_TIMC: [cmp1cr, cmp2cr, cmp3cr, cmp4cr], + HRTIM_TIMD: [cmp1dr, cmp2dr, cmp3dr, cmp4dr], + HRTIM_TIME: [cmp1er, cmp2er, cmp3er, cmp4er], + HRTIM_TIMF: [cmp1fr, cmp2fr, cmp3fr, cmp4fr], +} + hrtim_hal! { // TODO: HRTIM_MASTER HRTIM_TIMA: (hrtim_tima, timacr, perar, tacen), @@ -345,7 +772,7 @@ impl super::TimerType for TimerHrTim { // Period calculator for 16-bit hrtimers // // NOTE: This function will panic if the calculated period can not fit into 16 bits - fn calculate_frequency(base_freq: Hertz, freq: Hertz, alignment: Alignment) -> (u32, u16) { + fn calculate_frequency(base_freq: HertzU64, freq: Hertz, alignment: Alignment) -> (u32, u16) { let ideal_period = super::Timer32Bit::calculate_frequency(base_freq, freq, alignment).0 + 1; let prescale = u32::from(PSC::VALUE); From 24b782f414afe3bce563bee8ded2ae2b0b59de9b Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 20 May 2023 23:14:28 +0200 Subject: [PATCH 19/88] Still untested but might actually work, maybe --- examples/hrtim.rs | 17 +++----- src/pwm/hrtim.rs | 99 ++++++++++++++++++++--------------------------- 2 files changed, 48 insertions(+), 68 deletions(-) diff --git a/examples/hrtim.rs b/examples/hrtim.rs index 1c7b42d8..6e2c0a05 100644 --- a/examples/hrtim.rs +++ b/examples/hrtim.rs @@ -2,10 +2,8 @@ #![no_main] #![no_std] -use cortex_m::delay; use cortex_m_rt::entry; use fugit::ExtU32; -use fugit::RateExtU32; use hal::gpio::gpioa::PA8; use hal::gpio::gpioa::PA9; use hal::gpio::Alternate; @@ -15,7 +13,6 @@ use hal::pwm::hrtim::EventSource; use hal::pwm::hrtim::HrCompareRegister; use hal::pwm::hrtim::HrOutput; use hal::pwm::hrtim::HrPwmAdvExt; -use hal::pwm::hrtim::HrPwmExt; use hal::pwm::hrtim::HrTimer; use hal::pwm::hrtim::Pscl4; use hal::rcc; @@ -41,7 +38,7 @@ fn main() -> ! { // ...with a prescaler of 4 this gives us a HrTimer with a tick rate of 1.2GHz // With max the max period set, this would be 1.2GHz/2^16 ~= 18kHz... - type Prescaler = Pscl4; // Prescaler of 4 + let prescaler = Pscl4; let gpioa = dp.GPIOA.split(&mut rcc); let pin_a: PA8> = gpioa.pa8.into_alternate(); @@ -57,9 +54,10 @@ fn main() -> ! { //out2 . | | | | // . | | | | // ------------------------ ---------------------------- ---- - let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp + let (mut timer, (mut cr1, _cr2, _cr3, _cr4), (mut out1, mut out2)) = dp .HRTIM_TIMA - .pwm_advanced(pin_a, &mut rcc) + .pwm_advanced((pin_a, pin_b), &mut rcc) + .prescaler(prescaler) .period(0xFFFF) .push_pull_mode(true) // Set push pull mode, out1 and out2 are // alternated every period with one being @@ -68,13 +66,10 @@ fn main() -> ! { .finalize(); out1.enable_rst_event(EventSource::Cr1); // Set low on compare match with cr1 - //out2.rst_event(EventSource::Cr1); + out2.enable_rst_event(EventSource::Cr1); out1.enable_set_event(EventSource::Period); // Set high at new period - //out2.set_event(EventSource::Period); - // ^ - // | - // *---- Perhaps multiple EventSources could be Or:ed together? + out2.enable_set_event(EventSource::Period); loop { for i in 1..10 { diff --git a/src/pwm/hrtim.rs b/src/pwm/hrtim.rs index 1b955df6..1aea856f 100644 --- a/src/pwm/hrtim.rs +++ b/src/pwm/hrtim.rs @@ -61,7 +61,7 @@ macro_rules! pins { impl Pins<$TIMX, CH1, ComplementaryImpossible> for $CH1 { type Channel = Pwm<$TIMX, CH1, ComplementaryImpossible, ActiveHigh, ActiveHigh>; } - + impl Pins<$TIMX, CH2, ComplementaryImpossible> for $CH2 { type Channel = Pwm<$TIMX, CH2, ComplementaryImpossible, ActiveHigh, ActiveHigh>; } @@ -128,22 +128,22 @@ pub trait HrPwmExt: Sized { } pub trait HrPwmAdvExt: Sized { - fn pwm_advanced( + fn pwm_advanced( self, _pins: PINS, rcc: &mut Rcc, - ) -> HrPwmBuilder + ) -> HrPwmBuilder where - PINS: Pins; + PINS: Pins + ToHrOut, + CHANNEL: HrtimChannel; } /// HrPwmBuilder is used to configure advanced HrTim PWM features -pub struct HrPwmBuilder { +pub struct HrPwmBuilder { _tim: PhantomData, - _pins: PhantomData, - _channel: PhantomData, _fault: PhantomData, _prescaler: PhantomData, + _out: PhantomData, alignment: Alignment, base_freq: HertzU64, count: CountSettings, @@ -154,7 +154,7 @@ pub struct HrPwmBuilder { //deadtime: NanoSecond, } -pub trait HrCompareRegister{ +pub trait HrCompareRegister { fn get_duty(&self) -> u16; fn set_duty(&mut self, duty: u16); } @@ -164,7 +164,7 @@ pub struct HrCr2(PhantomData); pub struct HrCr3(PhantomData); pub struct HrCr4(PhantomData); -pub struct HrTim{ +pub struct HrTim { _timer: PhantomData, _prescaler: PhantomData, } @@ -174,7 +174,7 @@ pub trait HrTimer { fn set_period(&mut self, period: u16); } -pub trait HrOutput{ +pub trait HrOutput { fn enable(&mut self); fn disable(&mut self); @@ -199,7 +199,6 @@ pub enum EventSource { Cr4, Period, - /* /// Compare match with compare register 1 of master timer MasterCr1, @@ -214,32 +213,19 @@ pub enum EventSource { MasterCr4, MasterPeriod,*/ - // TODO: These are unique for every timer output //Extra(E) } pub trait ToHrOut { - type Out: HrOutput; -} - -/*impl ToHrOut for (TIM, CH1) - where HrOut1: HrOutput -{ - type Out = HrOut1; + type Out; } -impl ToHrOut for (TIM, CH2) -where HrOut2: HrOutput{ - type Out = HrOut2; -}*/ - -impl ToHrOut for (CHA, CHB) +impl ToHrOut for (PA, PB) where - CHA: ToHrOut, - CHB: ToHrOut, - (CHA::Out, CHA::Out): HrOutput + PA: ToHrOut, + PB: ToHrOut, { - type Out = (CHA::Out, CHA::Out); + type Out = (PA::Out, PB::Out); } pub struct HrOut1(PhantomData); @@ -314,13 +300,14 @@ macro_rules! hrtim_hal { } impl HrPwmAdvExt for $TIMX { - fn pwm_advanced( + fn pwm_advanced( self, _pins: PINS, rcc: &mut Rcc, - ) -> HrPwmBuilder + ) -> HrPwmBuilder where - PINS: Pins + PINS: Pins + ToHrOut, + CHANNEL: HrtimChannel { unsafe { let rcc_ptr = &(*RCC::ptr()); @@ -335,13 +322,12 @@ macro_rules! hrtim_hal { HrPwmBuilder { _tim: PhantomData, - _pins: PhantomData, - _channel: PhantomData, _fault: PhantomData, _prescaler: PhantomData, + _out: PhantomData, alignment: Alignment::Left, base_freq: clk, - count: CountSettings::Period(65535), + count: CountSettings::Period(u16::MAX), enable_push_pull: false, //bkin_enabled: false, //bkin2_enabled: false, @@ -351,13 +337,12 @@ macro_rules! hrtim_hal { } } - impl - HrPwmBuilder<$TIMX, PSCL, PINS, CHANNEL, FAULT> + impl + HrPwmBuilder<$TIMX, PSCL, FAULT, OUT> where PSCL: HrtimPrescaler, - PINS: Pins<$TIMX, CHANNEL, ComplementaryImpossible> + ToHrOut, { - pub fn finalize(self) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX>, HrCr2<$TIMX>, HrCr3<$TIMX>, HrCr4<$TIMX>), ::Out) { + pub fn finalize(self) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX>, HrCr2<$TIMX>, HrCr3<$TIMX>, HrCr4<$TIMX>), OUT) { let tim = unsafe { &*$TIMX::ptr() }; let (period, prescaler_bits) = match self.count { @@ -368,7 +353,7 @@ macro_rules! hrtim_hal { }; // Write prescaler and any special modes - tim.$timXcr.write(|w| unsafe { + tim.$timXcr.write(|w| unsafe { w // Enable Continous mode .cont().set_bit() @@ -405,14 +390,15 @@ macro_rules! hrtim_hal { } /// Set the prescaler; PWM count runs at base_frequency/(prescaler+1) - pub fn prescaler

(self, _prescaler: P) -> HrPwmBuilder<$TIMX, P, PINS, CHANNEL, FAULT> - where P: HrtimPrescaler { + pub fn prescaler

(self, _prescaler: P) -> HrPwmBuilder<$TIMX, P, FAULT, OUT> + where + P: HrtimPrescaler, + { let HrPwmBuilder { _tim, - _pins, - _channel, _fault, _prescaler: _, + _out, enable_push_pull, alignment, base_freq, @@ -428,10 +414,9 @@ macro_rules! hrtim_hal { HrPwmBuilder { _tim, - _pins, - _channel, _fault, _prescaler: PhantomData, + _out, enable_push_pull, alignment, base_freq, @@ -451,12 +436,12 @@ macro_rules! hrtim_hal { } /// 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 | | . | | /// | | . | | @@ -465,7 +450,7 @@ macro_rules! hrtim_hal { ///out2 . | | . | | /// . | | . | | /// ------------------------ ---------------------------- -- - /// + /// /// NOTE: setting this will overide any 'Swap Mode' set pub fn push_pull_mode(mut self, enable: bool) -> Self { self.enable_push_pull = enable; @@ -575,11 +560,11 @@ macro_rules! hrtim_out_common { let tim = unsafe { &*$TIMX::ptr() }; match $set_event { - EventSource::Cr1 => tim.$register.modify(|_r, w| { w.cmp1().$action() } ), - EventSource::Cr2 => tim.$register.modify(|_r, w| { w.cmp2().$action() } ), - EventSource::Cr3 => tim.$register.modify(|_r, w| { w.cmp3().$action() } ), - EventSource::Cr4 => tim.$register.modify(|_r, w| { w.cmp4().$action() } ), - EventSource::Period => tim.$register.modify(|_r, w| { w.per().$action() } ), + EventSource::Cr1 => tim.$register.modify(|_r, w| w.cmp1().$action()), + EventSource::Cr2 => tim.$register.modify(|_r, w| w.cmp2().$action()), + EventSource::Cr3 => tim.$register.modify(|_r, w| w.cmp3().$action()), + EventSource::Cr4 => tim.$register.modify(|_r, w| w.cmp4().$action()), + EventSource::Period => tim.$register.modify(|_r, w| w.per().$action()), } }}; } @@ -618,7 +603,7 @@ macro_rules! hrtim_out { )+}; } -hrtim_out!{ +hrtim_out! { HRTIM_TIMA: HrOut1: ta1oen, seta1r, rsta1r, HRTIM_TIMA: HrOut2: ta2oen, seta2r, rsta2r, @@ -684,7 +669,7 @@ macro_rules! hrtim_timer { )+}; } -hrtim_timer!{ +hrtim_timer! { HRTIM_TIMA: perar, HRTIM_TIMB: perbr, HRTIM_TIMC: percr, @@ -693,7 +678,7 @@ hrtim_timer!{ HRTIM_TIMF: perfr, } -hrtim_cr!{ +hrtim_cr! { HRTIM_TIMA: [cmp1ar, cmp2ar, cmp3ar, cmp4ar], HRTIM_TIMB: [cmp1br, cmp2br, cmp3br, cmp4br], HRTIM_TIMC: [cmp1cr, cmp2cr, cmp3cr, cmp4cr], From f86bb6442c562f2c183e94b1f777f0b7dca21098 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 20 May 2023 23:37:02 +0200 Subject: [PATCH 20/88] Adjust doc --- examples/hrtim.rs | 19 +++++++++++-------- examples/hrtim_simple.rs | 26 ++++++++++++++------------ 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/examples/hrtim.rs b/examples/hrtim.rs index 6e2c0a05..4d62ccdd 100644 --- a/examples/hrtim.rs +++ b/examples/hrtim.rs @@ -44,16 +44,18 @@ fn main() -> ! { let pin_a: PA8> = gpioa.pa8.into_alternate(); let pin_b: PA9> = gpioa.pa9.into_alternate(); - // . . - // . 30% . - // ---- . ---- - //out1 | | . | | - // | | . | | + // . . . . + // . 30% . . . + // ---- . .---- . + //out1 | | . | | . + // | | . | | . // -------- ---------------------------- -------------------- - // . ---- . ---- - //out2 . | | | | - // . | | | | + // . .---- . .---- + //out2 . | | . | | + // . | | . | | // ------------------------ ---------------------------- ---- + // . . . . + // . . . . let (mut timer, (mut cr1, _cr2, _cr3, _cr4), (mut out1, mut out2)) = dp .HRTIM_TIMA .pwm_advanced((pin_a, pin_b), &mut rcc) @@ -72,6 +74,7 @@ fn main() -> ! { out2.enable_set_event(EventSource::Period); loop { + // Step frequency from 18kHz to about 180kHz for i in 1..10 { let new_period = u16::MAX / i; diff --git a/examples/hrtim_simple.rs b/examples/hrtim_simple.rs index 2e380769..8d81a267 100644 --- a/examples/hrtim_simple.rs +++ b/examples/hrtim_simple.rs @@ -38,18 +38,20 @@ fn main() -> ! { let pin_a: PA8> = gpioa.pa8.into_alternate(); let pin_b: PA9> = gpioa.pa9.into_alternate(); - // . . - // . 33% . - // ---- . ---- - //out1 | | . | | - // | | . | | - // -------- ---------------------------- -------------------- - // . - // 50% . - // -------- . -------- - //out2 | | . | | - // | | . | | - // -------- ------------------------ ---------------- + // . . . + // . 33% . . + // ---- .---- .---- + //out1 | | | | | | + // | | | | | | + // ------ ------------ ------------ --------- + // . . + // 50% . . + // -------- .-------- .-------- + //out2 | | | | | | + // | | | | | | + // ------ -------- -------- ----- + // . . . + // . . . // ...Meaning that we will have plenty of resolution when producing a 20kHz waveform let (mut p1, mut p2) = From 96a8cb649cdb72c17c6b178428bd53169bbc2141 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 20 May 2023 23:39:25 +0200 Subject: [PATCH 21/88] Enable outputs in example --- examples/hrtim.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/hrtim.rs b/examples/hrtim.rs index 4d62ccdd..d6761240 100644 --- a/examples/hrtim.rs +++ b/examples/hrtim.rs @@ -73,6 +73,9 @@ fn main() -> ! { out1.enable_set_event(EventSource::Period); // Set high at new period out2.enable_set_event(EventSource::Period); + out1.enable(); + out2.enable(); + loop { // Step frequency from 18kHz to about 180kHz for i in 1..10 { From 7b655c07bb538b0a70ee2899ec43a67434b46663 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 20 May 2023 23:52:18 +0200 Subject: [PATCH 22/88] Further cleanup --- src/pwm/hrtim.rs | 50 +++++++++++++++++++++--------------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/src/pwm/hrtim.rs b/src/pwm/hrtim.rs index 1aea856f..e5094568 100644 --- a/src/pwm/hrtim.rs +++ b/src/pwm/hrtim.rs @@ -1,31 +1,3 @@ -/* -period: HRTIM_PERAR -enable output: HRTIM_OENR -enable preload: PREEN, -prescaler per timer: CKPSC[2:0] kan bara sättas en gång/när timern är disablad -NOTE: Timrar som kommunicerar output set/clear, counter reset, update, external event filter eller capture triggers måste ha samma prescaler - -continous mode: CONT in TIMxCR - -crossbar config for SET events: HRTIM_SETR -crossbar config for RST events: HRTIM_RSTR -att sätta ett event i båda register betyder "TOGGLE"-event - -tvinga 50% duty: HALF in HRTIM_TIMxCR smidigt vid variabel frekvens. Var gång HRTIM_PERxR(perioden) skrivs så kommer compare1-värdet bli halva perioden. -För att detta ska fungera måste utgången vara konfigurerad för en övergång för "compare1" och en vid "period". Se sida 856 - -Triggered-half mode: TRGHLF in HRTIM_TIMxCR2 - - -**** push-pull mode ****: PSHPLL in HRTIM_TIMxCR, detta verkar styra två utgångar på ett sätt som alternerande, varannan period skickar ut signal på ena utgången och håller andra utgången inaktiv och virse versa. se sida 864 - - -reset timers counters: TxRST in HRTIM_CR2 reset sker inte förens timrarna är enablade -polaritet: POLx 0: pos, 1:neg - -starta timer: MCEN or TxCEN oklart... -*/ - use core::marker::PhantomData; use core::mem::MaybeUninit; @@ -170,18 +142,40 @@ pub struct HrTim { } pub trait HrTimer { + /// Get period of timer in number of ticks + /// + /// This is also the maximum duty usable for `HrCompareRegister::set_duty` fn get_period(&self) -> u16; + + /// Set period of timer in number of ticks + /// + /// NOTE: This will affect the maximum duty usable for `HrCompareRegister::set_duty` fn set_period(&mut self, period: u16); } pub trait HrOutput { + /// Enable this output fn enable(&mut self); + + /// Disable this output fn disable(&mut self); + /// Set this output to active every time the specified event occurs + /// + /// NOTE: Enabling the same event for both SET and RESET + /// will make that event TOGGLE the output fn enable_set_event(&mut self, set_event: EventSource); + + /// Stop listening to the specified event fn disable_set_event(&mut self, set_event: EventSource); + /// Set this output to *not* active every time the specified event occurs + /// + /// NOTE: Enabling the same event for both SET and RESET + /// will make that event TOGGLE the output fn enable_rst_event(&mut self, reset_event: EventSource); + + /// Stop listening to the specified event fn disable_rst_event(&mut self, reset_event: EventSource); } From c6100ce33338ee31b175f03011d1fa89bd59a286 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 7 Jun 2023 15:50:35 +0200 Subject: [PATCH 23/88] Tested and verified on NUCLEO-G474RE --- examples/hrtim.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/hrtim.rs b/examples/hrtim.rs index d6761240..6c913f37 100644 --- a/examples/hrtim.rs +++ b/examples/hrtim.rs @@ -77,12 +77,12 @@ fn main() -> ! { out2.enable(); loop { - // Step frequency from 18kHz to about 180kHz + // Step frequency from 18kHz to about 180kHz(half of that when only looking at one pin) for i in 1..10 { let new_period = u16::MAX / i; cr1.set_duty(new_period / 3); - timer.set_period(new_period / i); + timer.set_period(new_period); delay.delay(500_u32.millis()); } From 279c1e23e19a9e66289448909ab0075adb3b952c Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 7 Jun 2023 15:55:26 +0200 Subject: [PATCH 24/88] hrtim_simple also tested and verified on NUCLEO-G474RE --- examples/hrtim_simple.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/hrtim_simple.rs b/examples/hrtim_simple.rs index 8d81a267..17c04ba2 100644 --- a/examples/hrtim_simple.rs +++ b/examples/hrtim_simple.rs @@ -17,6 +17,8 @@ use stm32g4xx_hal as hal; mod utils; extern crate cortex_m_rt as rt; +use defmt_rtt as _; // global logger + #[entry] fn main() -> ! { let dp = stm32::Peripherals::take().expect("cannot take peripherals"); From 0daad6604e9243d9c0e82c7db0b9be14def61607 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 9 Jun 2023 17:34:57 +0200 Subject: [PATCH 25/88] Hrtim cleanup, add pins for all timers but HRTIM_TIMF --- examples/hrtim.rs | 44 +++++++++++++++++++++++++--------------- examples/hrtim_simple.rs | 32 ++++++++++++++++++----------- src/pwm/hrtim.rs | 14 +++++++++++-- 3 files changed, 60 insertions(+), 30 deletions(-) diff --git a/examples/hrtim.rs b/examples/hrtim.rs index 6c913f37..796b9d26 100644 --- a/examples/hrtim.rs +++ b/examples/hrtim.rs @@ -3,26 +3,38 @@ #![no_std] use cortex_m_rt::entry; -use fugit::ExtU32; -use hal::gpio::gpioa::PA8; -use hal::gpio::gpioa::PA9; -use hal::gpio::Alternate; -use hal::gpio::AF13; -use hal::prelude::*; -use hal::pwm::hrtim::EventSource; -use hal::pwm::hrtim::HrCompareRegister; -use hal::pwm::hrtim::HrOutput; -use hal::pwm::hrtim::HrPwmAdvExt; -use hal::pwm::hrtim::HrTimer; -use hal::pwm::hrtim::Pscl4; -use hal::rcc; -use hal::stm32; -use stm32g4xx_hal as hal; + mod utils; -extern crate cortex_m_rt as rt; +use defmt_rtt as _; // global logger + +#[cfg(not(any(feature = "stm32g474", feature = "stm32g484")))] #[entry] fn main() -> ! { + #[allow(clippy::empty_loop)] + loop {} +} + +#[cfg(any(feature = "stm32g474", feature = "stm32g484"))] +#[entry] +fn main() -> ! { + use fugit::ExtU32; + use hal::gpio::gpioa::PA8; + use hal::gpio::gpioa::PA9; + use hal::gpio::Alternate; + use hal::gpio::AF13; + use hal::prelude::*; + use hal::pwm::hrtim::EventSource; + use hal::pwm::hrtim::HrCompareRegister; + use hal::pwm::hrtim::HrOutput; + use hal::pwm::hrtim::HrPwmAdvExt; + use hal::pwm::hrtim::HrTimer; + use hal::pwm::hrtim::Pscl4; + use hal::rcc; + use hal::stm32; + use stm32g4xx_hal as hal; + extern crate cortex_m_rt as rt; + let dp = stm32::Peripherals::take().expect("cannot take peripherals"); let cp = stm32::CorePeripherals::take().expect("cannot take core"); // Set system frequency to 16MHz * 75/4/2 = 150MHz diff --git a/examples/hrtim_simple.rs b/examples/hrtim_simple.rs index 17c04ba2..fa7b69e6 100644 --- a/examples/hrtim_simple.rs +++ b/examples/hrtim_simple.rs @@ -3,24 +3,32 @@ #![no_std] use cortex_m_rt::entry; -use fugit::RateExtU32; -use hal::gpio::gpioa::PA8; -use hal::gpio::gpioa::PA9; -use hal::gpio::Alternate; -use hal::gpio::AF13; -use hal::prelude::*; -use hal::pwm::hrtim::HrPwmExt; -use hal::pwm::hrtim::Pscl4; -use hal::rcc; -use hal::stm32; -use stm32g4xx_hal as hal; + mod utils; -extern crate cortex_m_rt as rt; use defmt_rtt as _; // global logger +#[cfg(not(any(feature = "stm32g474", feature = "stm32g484")))] +#[entry] +fn main() -> ! { + #[allow(clippy::empty_loop)] + loop {} +} + +#[cfg(any(feature = "stm32g474", feature = "stm32g484"))] #[entry] fn main() -> ! { + use hal::gpio::gpioa::PA8; + use hal::gpio::gpioa::PA9; + use hal::gpio::Alternate; + use hal::gpio::AF13; + use hal::prelude::*; + use hal::pwm::hrtim::{HrPwmExt, Pscl4}; + use hal::rcc; + use hal::stm32; + use hal::time::RateExtU32; + use stm32g4xx_hal as hal; + extern crate cortex_m_rt as rt; let dp = stm32::Peripherals::take().expect("cannot take peripherals"); // Set system frequency to 16MHz * 75/4/2 = 150MHz diff --git a/src/pwm/hrtim.rs b/src/pwm/hrtim.rs index e5094568..7330b8ac 100644 --- a/src/pwm/hrtim.rs +++ b/src/pwm/hrtim.rs @@ -3,8 +3,10 @@ use core::mem::MaybeUninit; use fugit::HertzU64; -use crate::gpio::gpioa::{PA8, PA9}; -use crate::gpio::{Alternate, AF13}; +use crate::gpio::gpioa::{PA10, PA11, PA12, PA13, PA8, PA9}; +use crate::gpio::gpiob::{PB14, PB15}; +use crate::gpio::gpioc::{PC8, PC9}; +use crate::gpio::{Alternate, AF13, AF3}; use crate::stm32::{ HRTIM_COMMON, HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF, @@ -51,6 +53,13 @@ macro_rules! pins { pins! { HRTIM_TIMA: CH1: PA8>, CH2: PA9> + + HRTIM_TIMB: CH1: PA10>, CH2: PA11> + HRTIM_TIMC: CH1: PA12>, CH2: PA13> + HRTIM_TIMD: CH1: PB14>, CH2: PB15> + + HRTIM_TIME: CH1: PC8>, CH2: PC9> + //HRTIM_TIMF: CH1: PC6>, CH2: PC7> } // automatically implement Pins trait for tuples of individual pins @@ -725,6 +734,7 @@ pub trait HrtimPrescaler { macro_rules! impl_pscl { ($($t:ident => $b:literal, $c:literal,)+) => {$( + #[derive(Copy, Clone)] pub struct $t; impl HrtimPrescaler for $t { const BITS: u8 = $b; From 72aab8b917be796a5efd3b5d236325011fda12df Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 20 Jun 2023 14:37:07 +0200 Subject: [PATCH 26/88] Several changes and fixes * Rcc enable is now handled for the entire HRTIM peripheral by dp.HRTIM_COMMON.hr_control() instead of by every timer * HRTIM calibration is now mandatory, also handled by `dp.HRTIM_COMMON.hr_control()` but also by running on that result `_.wait_for_calibration(). * Add `get_state` for `HrOutput` to check what state an output is in: `Idle`, `Running` or `Fault` --- examples/hrtim.rs | 7 +- examples/hrtim_simple.rs | 13 +- src/pwm/hrtim.rs | 287 +++++++++++++++++++++++---------------- src/rcc/enable.rs | 7 +- 4 files changed, 183 insertions(+), 131 deletions(-) diff --git a/examples/hrtim.rs b/examples/hrtim.rs index 796b9d26..a3b41713 100644 --- a/examples/hrtim.rs +++ b/examples/hrtim.rs @@ -4,9 +4,8 @@ use cortex_m_rt::entry; -mod utils; - use defmt_rtt as _; // global logger +use panic_probe as _; #[cfg(not(any(feature = "stm32g474", feature = "stm32g484")))] #[entry] @@ -26,6 +25,7 @@ fn main() -> ! { use hal::prelude::*; use hal::pwm::hrtim::EventSource; use hal::pwm::hrtim::HrCompareRegister; + use hal::pwm::hrtim::HrControltExt; use hal::pwm::hrtim::HrOutput; use hal::pwm::hrtim::HrPwmAdvExt; use hal::pwm::hrtim::HrTimer; @@ -68,6 +68,7 @@ fn main() -> ! { // ------------------------ ---------------------------- ---- // . . . . // . . . . + let (mut fault_control, _) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); let (mut timer, (mut cr1, _cr2, _cr3, _cr4), (mut out1, mut out2)) = dp .HRTIM_TIMA .pwm_advanced((pin_a, pin_b), &mut rcc) @@ -77,7 +78,7 @@ fn main() -> ! { // alternated every period with one being // inactive and the other getting to output its wave form // as normal - .finalize(); + .finalize(&mut fault_control); out1.enable_rst_event(EventSource::Cr1); // Set low on compare match with cr1 out2.enable_rst_event(EventSource::Cr1); diff --git a/examples/hrtim_simple.rs b/examples/hrtim_simple.rs index fa7b69e6..a022b48f 100644 --- a/examples/hrtim_simple.rs +++ b/examples/hrtim_simple.rs @@ -4,9 +4,10 @@ use cortex_m_rt::entry; -mod utils; +//mod utils; use defmt_rtt as _; // global logger +use panic_probe as _; #[cfg(not(any(feature = "stm32g474", feature = "stm32g484")))] #[entry] @@ -23,7 +24,7 @@ fn main() -> ! { use hal::gpio::Alternate; use hal::gpio::AF13; use hal::prelude::*; - use hal::pwm::hrtim::{HrPwmExt, Pscl4}; + use hal::pwm::hrtim::{HrPwmExt, HrControltExt}; use hal::rcc; use hal::stm32; use hal::time::RateExtU32; @@ -40,10 +41,6 @@ fn main() -> ! { ..Default::default() })); - // ...with a prescaler of 4 this gives us a HrTimer with a tick rate of 1.2GHz - // With max the max period set, this would be 1.2GHz/2^16 ~= 18kHz... - type Prescaler = Pscl4; // Prescaler of 4 - let gpioa = dp.GPIOA.split(&mut rcc); let pin_a: PA8> = gpioa.pa8.into_alternate(); let pin_b: PA9> = gpioa.pa9.into_alternate(); @@ -63,10 +60,10 @@ fn main() -> ! { // . . . // . . . - // ...Meaning that we will have plenty of resolution when producing a 20kHz waveform + let (mut control, _) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); let (mut p1, mut p2) = dp.HRTIM_TIMA - .pwm::<_, _, Prescaler, _, _>((pin_a, pin_b), 20_u32.kHz(), &mut rcc); + .pwm((pin_a, pin_b), 20_u32.kHz(), &mut control, &mut rcc); let max_duty = p1.get_max_duty(); p1.set_duty(max_duty / 3); // Set output 1 to about 33% diff --git a/src/pwm/hrtim.rs b/src/pwm/hrtim.rs index 7330b8ac..afe4e7dc 100644 --- a/src/pwm/hrtim.rs +++ b/src/pwm/hrtim.rs @@ -100,12 +100,11 @@ pins_tuples! { /// Allows the pwm() method to be added to the peripheral register structs from the device crate pub trait HrPwmExt: Sized { /// The requested frequency will be rounded to the nearest achievable frequency; the actual frequency may be higher or lower than requested. - fn pwm(self, _pins: PINS, frequency: T, rcc: &mut Rcc) -> PINS::Channel + fn pwm(self, _pins: PINS, frequency: T, control: &mut HrPwmControl, rcc: &mut Rcc) -> PINS::Channel where - PINS: Pins, + PINS: Pins + ToHrOut, T: Into, - U: HrtimChannel, - PSCL: HrtimPrescaler; + U: HrtimChannel; } pub trait HrPwmAdvExt: Sized { @@ -186,6 +185,17 @@ pub trait HrOutput { /// Stop listening to the specified event fn disable_rst_event(&mut self, reset_event: EventSource); + + /// Get current state of the output + fn get_state(&self) -> State; +} + +#[derive(Debug, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum State { + Idle, + Running, + Fault, } pub enum EventSource { @@ -234,72 +244,29 @@ where pub struct HrOut1(PhantomData); pub struct HrOut2(PhantomData); -// Implement HrPwmExt trait for hrtimer -macro_rules! pwm_ext_hal { - ($TIMX:ident: $timX:ident) => { - impl HrPwmExt for $TIMX { - fn pwm( - self, - pins: PINS, - frequency: T, - rcc: &mut Rcc, - ) -> PINS::Channel - where - PINS: Pins, - T: Into, - U: HrtimChannel, - PSCL: HrtimPrescaler, - { - $timX(self, pins, frequency.into(), rcc) - } - } - }; -} - // Implement PWM configuration for timer macro_rules! hrtim_hal { ($($TIMX:ident: ($timX:ident, $timXcr:ident, $perXr:ident, $tXcen:ident),)+) => { $( - pwm_ext_hal!($TIMX: $timX); - - /// Configures PWM - fn $timX( - tim: $TIMX, - _pins: PINS, - freq: Hertz, - rcc: &mut Rcc, - ) -> PINS::Channel - where - PINS: super::Pins<$TIMX, T, U>, - T: HrtimChannel, - PSCL: HrtimPrescaler, - { - unsafe { - let rcc_ptr = &*RCC::ptr(); - $TIMX::enable(rcc_ptr); - $TIMX::reset(rcc_ptr); - } - - // TODO: That 32x factor... Is that done by $TIMX::get_timer_frequency - // or should we do that? Also that will likely risk overflowing u32 since - // 170MHz * 32 = 5.44GHz > u32::MAX.Hz() - let clk = HertzU64::from($TIMX::get_timer_frequency(&rcc.clocks)) * 32; - - let (period, prescaler_bits) = >::calculate_frequency(clk, freq, Alignment::Left); - - // Write prescaler - tim.$timXcr.write(|w| unsafe { w.cont().set_bit().ck_pscx().bits(prescaler_bits as u8) }); - - // Write period - tim.$perXr.write(|w| unsafe { w.perx().bits(period as u16) }); - // Start timer - cortex_m::interrupt::free(|_| { - let master = unsafe { &*HRTIM_MASTER::ptr() }; - master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); - }); + // Implement HrPwmExt trait for hrtimer + impl HrPwmExt for $TIMX { + fn pwm( + self, + pins: PINS, + frequency: T, + control: &mut HrPwmControl, + rcc: &mut Rcc, + ) -> PINS::Channel + where + PINS: Pins + ToHrOut, + T: Into, + U: HrtimChannel, + { + let _= self.pwm_advanced(pins, rcc).frequency(frequency).finalize(control); unsafe { MaybeUninit::::uninit().assume_init() } + } } impl HrPwmAdvExt for $TIMX { @@ -312,16 +279,10 @@ macro_rules! hrtim_hal { PINS: Pins + ToHrOut, CHANNEL: HrtimChannel { - unsafe { - let rcc_ptr = &(*RCC::ptr()); - $TIMX::enable(rcc_ptr); - $TIMX::reset(rcc_ptr); - } - // 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($TIMX::get_timer_frequency(&rcc.clocks)) * 32; + let clk = HertzU64::from(HRTIM_COMMON::get_timer_frequency(&rcc.clocks)) * 32; HrPwmBuilder { _tim: PhantomData, @@ -345,7 +306,7 @@ macro_rules! hrtim_hal { where PSCL: HrtimPrescaler, { - pub fn finalize(self) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX>, HrCr2<$TIMX>, HrCr3<$TIMX>, HrCr4<$TIMX>), OUT) { + pub fn finalize(self, _control: &mut HrPwmControl) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX>, HrCr2<$TIMX>, HrCr3<$TIMX>, HrCr4<$TIMX>), OUT) { let tim = unsafe { &*$TIMX::ptr() }; let (period, prescaler_bits) = match self.count { @@ -424,10 +385,6 @@ macro_rules! hrtim_hal { alignment, base_freq, count, - //bkin_enabled: false, - //bkin2_enabled: false, - //fault_polarity: Polarity::ActiveLow, - //deadtime: 0.nanos(), } } @@ -473,7 +430,7 @@ macro_rules! hrtim_hal { macro_rules! hrtim_pin_hal { ($($TIMX:ident: - ($CH:ident, $perXr:ident, $cmpXYr:ident, $cmpYx:ident, $cmpY:ident, $tXYoen:ident, $setXYr:ident, $rstXYr:ident),)+ + ($CH:ident, $perXr:ident, $cmpXYr:ident, $cmpYx:ident, $cmpY:ident, $tXYoen:ident, $tXYodis:ident, $setXYr:ident, $rstXYr:ident),)+ ) => { $( impl hal::PwmPin for Pwm<$TIMX, $CH, COMP, POL, NPOL> @@ -533,11 +490,9 @@ macro_rules! hrtim_pin_hal { // TODO: Should this part only be in Pwm::enable? // Enable output Y on channel X - // NOTE(unsafe) critical section prevents races - cortex_m::interrupt::free(|_| { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.oenr.modify(|_r, w| { w.$tXYoen().set_bit() }); - }); + // This is a set-only register, no risk for data race + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.oenr.write(|w| { w.$tXYoen().set_bit() }); } fn ccer_disable(&mut self) { let tim = unsafe { &*$TIMX::ptr() }; @@ -545,13 +500,10 @@ macro_rules! hrtim_pin_hal { tim.$setXYr.reset(); // TODO: Should this part only be in Pwm::disable - // Do we want a potentially floating output after after disable? // Disable output Y on channel X - // NOTE(unsafe) critical section prevents races - cortex_m::interrupt::free(|_| { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.oenr.modify(|_r, w| { w.$tXYoen().clear_bit() }); - }); + // This is a write only register, no risk for data race + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.odisr.write(|w| { w.$tXYodis().set_bit() }); } } )+ @@ -573,19 +525,19 @@ macro_rules! hrtim_out_common { } macro_rules! hrtim_out { - ($($TIMX:ident: $out_type:ident: $tXYoen:ident, $setXYr:ident, $rstXYr:ident,)+) => {$( + ($($TIMX:ident: $out_type:ident: $tXYoen:ident, $tXYodis:ident, $tXYods:ident, $setXYr:ident, $rstXYr:ident,)+) => {$( impl HrOutput for $out_type<$TIMX> { fn enable(&mut self) { cortex_m::interrupt::free(|_| { let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.oenr.modify(|_r, w| { w.$tXYoen().set_bit() }); + common.oenr.write(|w| { w.$tXYoen().set_bit() }); }); } fn disable(&mut self) { cortex_m::interrupt::free(|_| { let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.oenr.modify(|_r, w| { w.$tXYoen().clear_bit() }); + common.odisr.write(|w| { w.$tXYodis().set_bit() }); }); } @@ -602,31 +554,48 @@ macro_rules! hrtim_out { fn disable_rst_event(&mut self, reset_event: EventSource) { hrtim_out_common!($TIMX, reset_event, $rstXYr, clear_bit) } + + 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(); + } + + match (oen, ods) { + (true, _) => State::Running, + (false, false) => State::Idle, + (false, true) => State::Fault + } + } } )+}; } hrtim_out! { - HRTIM_TIMA: HrOut1: ta1oen, seta1r, rsta1r, - HRTIM_TIMA: HrOut2: ta2oen, seta2r, rsta2r, + HRTIM_TIMA: HrOut1: ta1oen, ta1odis, ta1ods, seta1r, rsta1r, + HRTIM_TIMA: HrOut2: ta2oen, ta1odis, ta2ods, seta2r, rsta2r, - HRTIM_TIMB: HrOut1: tb1oen, setb1r, rstb1r, - HRTIM_TIMB: HrOut2: tb2oen, setb2r, rstb2r, + HRTIM_TIMB: HrOut1: tb1oen, tb1odis, tb1ods, setb1r, rstb1r, + HRTIM_TIMB: HrOut2: tb2oen, tb2odis, tb2ods, setb2r, rstb2r, - HRTIM_TIMC: HrOut1: tc1oen, setc1r, rstc1r, - HRTIM_TIMC: HrOut2: tc2oen, setc2r, rstc2r, + HRTIM_TIMC: HrOut1: tc1oen, tc1odis, tc1ods, setc1r, rstc1r, + HRTIM_TIMC: HrOut2: tc2oen, tc2odis, tc2ods, setc2r, rstc2r, - HRTIM_TIMD: HrOut1: td1oen, setd1r, rstd1r, - HRTIM_TIMD: HrOut2: td2oen, setd2r, rstd2r, + HRTIM_TIMD: HrOut1: td1oen, td1odis, td1ods, setd1r, rstd1r, + HRTIM_TIMD: HrOut2: td2oen, td2odis, td2ods, setd2r, rstd2r, - HRTIM_TIME: HrOut1: te1oen, sete1r, rste1r, - HRTIM_TIME: HrOut2: te2oen, sete2r, rste2r, + HRTIM_TIME: HrOut1: te1oen, te1odis, te1ods, sete1r, rste1r, + HRTIM_TIME: HrOut2: te2oen, te2odis, te2ods, sete2r, rste2r, // TODO: Somehow, there is no rstf1r - //HRTIM_TIMF: HrOut1: tf1oen, setf1r, rstf1r, + //HRTIM_TIMF: HrOut1: tf1oen, tf1odis, tf1ods, setf1r, rstf1r, // TODO: Somehow, there is no tf2oen - //HRTIM_TIMF: HrOut2: tf2oen, setf2r, rstf2r, + //HRTIM_TIMF: HrOut2: tf2oen, tf2odis, tf2ods, setf2r, rstf2r, } macro_rules! hrtim_cr_helper { @@ -704,27 +673,27 @@ hrtim_hal! { } hrtim_pin_hal! { - HRTIM_TIMA: (CH1, perar, cmp1ar, cmp1x, cmp1, ta1oen, seta1r, rsta1r), - HRTIM_TIMA: (CH2, perar, cmp3ar, cmp3x, cmp3, ta2oen, seta2r, rsta2r), + HRTIM_TIMA: (CH1, perar, cmp1ar, cmp1x, cmp1, ta1oen, ta1odis, seta1r, rsta1r), + HRTIM_TIMA: (CH2, perar, cmp3ar, cmp3x, cmp3, ta2oen, ta2odis, seta2r, rsta2r), - HRTIM_TIMB: (CH1, perbr, cmp1br, cmp1x, cmp1, tb1oen, setb1r, rstb1r), - HRTIM_TIMB: (CH2, perbr, cmp3br, cmp3x, cmp3, tb2oen, setb2r, rstb2r), + HRTIM_TIMB: (CH1, perbr, cmp1br, cmp1x, cmp1, tb1oen, tb1odis, setb1r, rstb1r), + HRTIM_TIMB: (CH2, perbr, cmp3br, cmp3x, cmp3, tb2oen, tb2odis, setb2r, rstb2r), - HRTIM_TIMC: (CH1, percr, cmp1cr, cmp1x, cmp1, tc1oen, setc1r, rstc1r), - HRTIM_TIMC: (CH2, percr, cmp3cr, cmp3x, cmp3, tc2oen, setc2r, rstc2r), + HRTIM_TIMC: (CH1, percr, cmp1cr, cmp1x, cmp1, tc1oen, tc1odis, setc1r, rstc1r), + HRTIM_TIMC: (CH2, percr, cmp3cr, cmp3x, cmp3, tc2oen, tc2odis, setc2r, rstc2r), - HRTIM_TIMD: (CH1, perdr, cmp1dr, cmp1x, cmp1, td1oen, setd1r, rstd1r), - HRTIM_TIMD: (CH2, perdr, cmp3dr, cmp3x, cmp3, td2oen, setd2r, rstd2r), + HRTIM_TIMD: (CH1, perdr, cmp1dr, cmp1x, cmp1, td1oen, td1odis, setd1r, rstd1r), + HRTIM_TIMD: (CH2, perdr, cmp3dr, cmp3x, cmp3, td2oen, td2odis, setd2r, rstd2r), - HRTIM_TIME: (CH1, perer, cmp1er, cmp1x, cmp1, te1oen, sete1r, rste1r), - HRTIM_TIME: (CH2, perer, cmp3er, cmp3x, cmp3, te2oen, sete2r, rste2r), + HRTIM_TIME: (CH1, perer, cmp1er, cmp1x, cmp1, te1oen, te1odis, sete1r, rste1r), + HRTIM_TIME: (CH2, perer, cmp3er, cmp3x, cmp3, te2oen, te2odis, sete2r, rste2r), // TODO: tf1oen and rstf1r are not defined - //HRTIM_TIMF: (CH1, perfr, cmp1fr, cmp1x, cmp1, tf1oen, setf1r, rstf1r), + //HRTIM_TIMF: (CH1, perfr, cmp1fr, cmp1x, cmp1, tf1oen, tf1odis, setf1r, rstf1r), // TODO: tf2oen is not defined - //HRTIM_TIMF: (CH2, perfr, cmp3fr, cmp3x, cmp3, tf2oen, setf2r, rstf2r), + //HRTIM_TIMF: (CH2, perfr, cmp3fr, cmp3x, cmp3, tf2oen, tf2odis, setf2r, rstf2r), } pub trait HrtimPrescaler { @@ -780,3 +749,93 @@ pub trait HrtimChannel {} impl HrtimChannel for CH1 {} impl HrtimChannel for CH2 {} + +pub struct HrPwmControl { + _x: PhantomData<()>, +} + +/// The divsion ratio between f_hrtim and the fault signal sampling clock for digital filters +pub enum FaultSamplingClkDiv { + /// No division + /// + /// fault signal sampling clock = f_hrtim + None = 0b00, + + /// 1/2 + /// + /// fault signal sampling clock = f_hrtim / 2 + Two = 0b01, + + /// 1/4 + /// + /// fault signal sampling clock = f_hrtim / 4 + Four = 0b10, + + /// 1/8 + /// + /// fault signal sampling clock = f_hrtim / 8 + Eight = 0b11, +} + +pub struct FaultInputs { + _x: (), +} + +pub trait HrControltExt { + fn hr_control(self, _rcc: &mut Rcc) -> HrTimOngoingCalibration; +} + +impl HrControltExt for HRTIM_COMMON { + fn hr_control(self, _rcc: &mut Rcc) -> HrTimOngoingCalibration { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + + unsafe { + let rcc_ptr = &*RCC::ptr(); + + HRTIM_COMMON::enable(rcc_ptr); + HRTIM_COMMON::reset(rcc_ptr); + } + + // Start calibration procedure + common + .dllcr + .write(|w| w.cal().set_bit().calen().clear_bit()); + + HrTimOngoingCalibration { + divider: FaultSamplingClkDiv::None, + } + } +} + +pub struct HrTimOngoingCalibration { + divider: FaultSamplingClkDiv, +} + +impl HrTimOngoingCalibration { + /// SAFETY: Calibration needs to be done before calling this + unsafe fn init(self) -> (HrPwmControl, FaultInputs) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + + unsafe { + // Enable periodic calibration + // with f_hrtim at 170MHz, these settings leads to + // a period of about 6.2ms + common + .dllcr + .modify(|_r, w| w.calrte().bits(0b00).cal().set_bit().calen().clear_bit()); + common.fltinr2.write(|w| w.fltsd().bits(self.divider as u8)); + } + + (HrPwmControl { _x: PhantomData }, FaultInputs { _x: () }) + } + + pub fn wait_for_calibration(self) -> (HrPwmControl, FaultInputs) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + while common.isr.read().dllrdy().bit_is_clear() { + // Wait until ready + } + + // Calibration is now done, it is safe to continue + unsafe { self.init() } + } +} diff --git a/src/rcc/enable.rs b/src/rcc/enable.rs index d8e4defc..8bd3db1d 100644 --- a/src/rcc/enable.rs +++ b/src/rcc/enable.rs @@ -232,10 +232,5 @@ bus! { #[cfg(any(feature = "stm32g474", feature = "stm32g484"))] bus! { - HRTIM_TIMA => (APB2, 26), - HRTIM_TIMB => (APB2, 26), - HRTIM_TIMC => (APB2, 26), - HRTIM_TIMD => (APB2, 26), - HRTIM_TIME => (APB2, 26), - HRTIM_TIMF => (APB2, 26), + HRTIM_COMMON => (APB2, 26), } From 43a105877dc461a213fa3efc510966f184f3849d Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 12 Jun 2023 22:23:09 +0200 Subject: [PATCH 27/88] Start work on hrtim fault --- examples/hrtim_simple.rs | 8 +- src/pwm.rs | 1 + src/pwm/hrtim.rs | 339 ++++++++++++++++++++++++++++++++++----- 3 files changed, 307 insertions(+), 41 deletions(-) diff --git a/examples/hrtim_simple.rs b/examples/hrtim_simple.rs index a022b48f..df142cd2 100644 --- a/examples/hrtim_simple.rs +++ b/examples/hrtim_simple.rs @@ -24,7 +24,7 @@ fn main() -> ! { use hal::gpio::Alternate; use hal::gpio::AF13; use hal::prelude::*; - use hal::pwm::hrtim::{HrPwmExt, HrControltExt}; + use hal::pwm::hrtim::{HrControltExt, HrPwmExt}; use hal::rcc; use hal::stm32; use hal::time::RateExtU32; @@ -61,9 +61,9 @@ fn main() -> ! { // . . . let (mut control, _) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); - let (mut p1, mut p2) = - dp.HRTIM_TIMA - .pwm((pin_a, pin_b), 20_u32.kHz(), &mut control, &mut rcc); + let (mut p1, mut p2) = dp + .HRTIM_TIMA + .pwm((pin_a, pin_b), 20_u32.kHz(), &mut control, &mut rcc); let max_duty = p1.get_max_duty(); p1.set_duty(max_duty / 3); // Set output 1 to about 33% diff --git a/src/pwm.rs b/src/pwm.rs index 219ab16d..166389b0 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -258,6 +258,7 @@ pub struct ComplementaryDisabled; pub struct ComplementaryEnabled; /// Enum for IO polarity +#[derive(Debug, PartialEq)] pub enum Polarity { ActiveHigh, ActiveLow, diff --git a/src/pwm/hrtim.rs b/src/pwm/hrtim.rs index afe4e7dc..0348e4f1 100644 --- a/src/pwm/hrtim.rs +++ b/src/pwm/hrtim.rs @@ -3,17 +3,18 @@ use core::mem::MaybeUninit; use fugit::HertzU64; -use crate::gpio::gpioa::{PA10, PA11, PA12, PA13, PA8, PA9}; -use crate::gpio::gpiob::{PB14, PB15}; -use crate::gpio::gpioc::{PC8, PC9}; -use crate::gpio::{Alternate, AF13, AF3}; +use crate::gpio::gpioa::{PA10, PA11, PA12, PA13, PA15, PA8, PA9}; +use crate::gpio::gpiob::{PB0, PB10, PB11, PB14, PB15}; +use crate::gpio::gpioc::{PC10, PC7, PC8, PC9}; +use crate::gpio::{self, AF3}; +use crate::gpio::{Alternate, AF13}; use crate::stm32::{ HRTIM_COMMON, HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF, }; use super::{ - ActiveHigh, Alignment, ComplementaryImpossible, FaultDisabled, Pins, Pwm, PwmPinEnable, + ActiveHigh, Alignment, ComplementaryImpossible, FaultMonitor, Pins, Pwm, PwmPinEnable, TimerType, }; use crate::rcc::{Enable, GetBusFreq, Rcc, Reset}; @@ -100,7 +101,13 @@ pins_tuples! { /// Allows the pwm() method to be added to the peripheral register structs from the device crate pub trait HrPwmExt: Sized { /// The requested frequency will be rounded to the nearest achievable frequency; the actual frequency may be higher or lower than requested. - fn pwm(self, _pins: PINS, frequency: T, control: &mut HrPwmControl, rcc: &mut Rcc) -> PINS::Channel + fn pwm( + self, + _pins: PINS, + frequency: T, + control: &mut HrPwmControl, + rcc: &mut Rcc, + ) -> PINS::Channel where PINS: Pins + ToHrOut, T: Into, @@ -112,25 +119,24 @@ pub trait HrPwmAdvExt: Sized { self, _pins: PINS, rcc: &mut Rcc, - ) -> HrPwmBuilder + ) -> HrPwmBuilder where PINS: Pins + ToHrOut, CHANNEL: HrtimChannel; } /// HrPwmBuilder is used to configure advanced HrTim PWM features -pub struct HrPwmBuilder { +pub struct HrPwmBuilder { _tim: PhantomData, - _fault: PhantomData, _prescaler: PhantomData, _out: PhantomData, alignment: Alignment, base_freq: HertzU64, count: CountSettings, + fault_enable_bits: u8, + fault1_bits: u8, + fault2_bits: u8, enable_push_pull: bool, - //bkin_enabled: bool, // If the FAULT type parameter is FaultEnabled, either bkin or bkin2 must be enabled - //bkin2_enabled: bool, - //fault_polarity: Polarity, //deadtime: NanoSecond, } @@ -246,7 +252,7 @@ pub struct HrOut2(PhantomData); // Implement PWM configuration for timer macro_rules! hrtim_hal { - ($($TIMX:ident: ($timX:ident, $timXcr:ident, $perXr:ident, $tXcen:ident),)+) => { + ($($TIMX:ident: ($timX:ident, $timXcr:ident, $perXr:ident, $tXcen:ident, $fltXr:ident, $outXr:ident),)+) => { $( // Implement HrPwmExt trait for hrtimer @@ -274,7 +280,7 @@ macro_rules! hrtim_hal { self, _pins: PINS, rcc: &mut Rcc, - ) -> HrPwmBuilder + ) -> HrPwmBuilder where PINS: Pins + ToHrOut, CHANNEL: HrtimChannel @@ -286,23 +292,22 @@ macro_rules! hrtim_hal { HrPwmBuilder { _tim: PhantomData, - _fault: PhantomData, _prescaler: PhantomData, _out: PhantomData, + fault_enable_bits: 0b000000, + fault1_bits: 0b00, + fault2_bits: 0b00, alignment: Alignment::Left, base_freq: clk, count: CountSettings::Period(u16::MAX), enable_push_pull: false, - //bkin_enabled: false, - //bkin2_enabled: false, - //fault_polarity: Polarity::ActiveLow, //deadtime: 0.nanos(), } } } - impl - HrPwmBuilder<$TIMX, PSCL, FAULT, OUT> + impl + HrPwmBuilder<$TIMX, PSCL, OUT> where PSCL: HrtimPrescaler, { @@ -334,6 +339,29 @@ macro_rules! hrtim_hal { // Write period tim.$perXr.write(|w| unsafe { w.perx().bits(period as u16) }); + // Enable fault sources and lock configuration + unsafe { + // Enable fault sources + let fault_enable_bits = self.fault_enable_bits as u32; + tim.$fltXr.write(|w| w + .flt1en().bit(fault_enable_bits & (1 << 0) != 0) + .flt2en().bit(fault_enable_bits & (1 << 1) != 0) + .flt3en().bit(fault_enable_bits & (1 << 2) != 0) + .flt4en().bit(fault_enable_bits & (1 << 3) != 0) + .flt5en().bit(fault_enable_bits & (1 << 4) != 0) + .flt6en().bit(fault_enable_bits & (1 << 5) != 0) + ); + + // ... and lock configuration + tim.$fltXr.modify(|_r, w| w.fltlck().set_bit()); + + // Set actions on fault for both outputs + tim.$outXr.modify(|_r, w| w + .fault1().bits(self.fault1_bits) + .fault2().bits(self.fault2_bits) + ); + } + // Start timer cortex_m::interrupt::free(|_| { let master = unsafe { &*HRTIM_MASTER::ptr() }; @@ -354,15 +382,17 @@ macro_rules! hrtim_hal { } /// Set the prescaler; PWM count runs at base_frequency/(prescaler+1) - pub fn prescaler

(self, _prescaler: P) -> HrPwmBuilder<$TIMX, P, FAULT, OUT> + pub fn prescaler

(self, _prescaler: P) -> HrPwmBuilder<$TIMX, P, OUT> where P: HrtimPrescaler, { let HrPwmBuilder { _tim, - _fault, _prescaler: _, _out, + fault_enable_bits, + fault1_bits, + fault2_bits, enable_push_pull, alignment, base_freq, @@ -378,7 +408,40 @@ macro_rules! hrtim_hal { HrPwmBuilder { _tim, - _fault, + _prescaler: PhantomData, + _out, + fault_enable_bits, + fault1_bits, + fault2_bits, + enable_push_pull, + alignment, + base_freq, + count, + //deadtime: 0.nanos(), + } + } + + pub fn with_fault_source(self, _fault_source: FS) -> HrPwmBuilder<$TIMX, PSCL, OUT> + where FS: FaultSource + { + let HrPwmBuilder { + _tim, + _prescaler: _, + _out, + fault_enable_bits, + fault1_bits, + fault2_bits, + enable_push_pull, + alignment, + base_freq, + count, + } = self; + + HrPwmBuilder { + _tim, + fault_enable_bits: fault_enable_bits | FS::ENABLE_BITS, + fault1_bits, + fault2_bits, _prescaler: PhantomData, _out, enable_push_pull, @@ -388,6 +451,16 @@ macro_rules! hrtim_hal { } } + 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 + } + /// 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); @@ -661,15 +734,12 @@ hrtim_cr! { hrtim_hal! { // TODO: HRTIM_MASTER - HRTIM_TIMA: (hrtim_tima, timacr, perar, tacen), - HRTIM_TIMB: (hrtim_timb, timbcr, perbr, tbcen), - HRTIM_TIMC: (hrtim_timc, timccr, percr, tccen), - HRTIM_TIMD: (hrtim_timd, timdcr, perdr, tdcen), - HRTIM_TIME: (hrtim_time, timecr, perer, tecen), - - // TODO: why is there no rstf1r? - //HRTIM_TIMF: (hrtim_timf1, timfcr, perfr, tfcen, setf1r, rstf1r, cmp1), - HRTIM_TIMF: (hrtim_timf, timfcr, perfr, tfcen), + HRTIM_TIMA: (hrtim_tima, timacr, perar, tacen, fltar, outar), + HRTIM_TIMB: (hrtim_timb, timbcr, perbr, tbcen, fltbr, outbr), + HRTIM_TIMC: (hrtim_timc, timccr, percr, tccen, fltcr, outcr), + HRTIM_TIMD: (hrtim_timd, timdcr, perdr, tdcen, fltdr, outdr), + HRTIM_TIME: (hrtim_time, timecr, perer, tecen, flter, outer), + HRTIM_TIMF: (hrtim_timf, timfcr, perfr, tfcen, fltfr, outfr), } hrtim_pin_hal! { @@ -750,8 +820,153 @@ pub trait HrtimChannel {} impl HrtimChannel for CH1 {} impl HrtimChannel for CH2 {} +pub enum FaultAction { + /// Output never enters fault mode + None = 0b00, + + /// Output forced to `active` level on fault + ForceActive = 0b01, + + /// Output forced to `inactive` level on fault + ForceInactive = 0b10, + + /// The output is floating/tri stated on fault + Floating = 0b11, +} + +pub trait FaultSource: Copy { + const ENABLE_BITS: u8; +} + +pub struct SourceBuilder { + _input: I, + src_bits: u8, + is_active_high: bool, + filter_bits: u8, +} + +impl SourceBuilder { + unsafe fn new(input: I, src_bits: u8) -> Self { + SourceBuilder { + _input: input, + src_bits, + is_active_high: false, + filter_bits: 0b0000, + } + } +} + +macro_rules! impl_faults { + ($( + $input:ident => $source:ident: + PINS=[($pin:ident, $af:ident), $(($pin_b:ident, $af_b:ident),)*], + COMP=$compX:ident, $enable_bits:literal, + $fltinrZ:ident, $fltWsrc_0:ident, $fltWsrc_1:ident, $fltWp:ident, $fltWf:ident, $fltWe:ident, $fltWlck:ident, + )+) => {$( + + // This should NOT be Copy/Clone + pub struct $input { + _x: PhantomData<()> + } + + #[derive(Copy, Clone)] + pub struct $source { + _x: PhantomData<()> + } + + impl $input { + pub fn bind_pin(self, pin: $pin>) -> SourceBuilder<$input> { + pin.into_alternate::<$af>(); + unsafe { SourceBuilder::new(self, 0b00) } + } + + $( + pub fn bind_pin_b(self, pin: $pin_b>) -> SourceBuilder<$input> { + pin.into_alternate::<$af_b>(); + unsafe { SourceBuilder::new(self, 0b00) } + } + )* + + /*pub fn bind_comp(self, comp: $compX) -> SourceBuilder<$input> { + unsafe { SourceBuilder::new(self, 0b01) } + }*/ + + /*pub fn bind_external(?) { + SourceBuilder::new(self, 0b10); + }*/ + } + + impl SourceBuilder<$input> { + pub fn finalize(self, _control: &mut HrPwmControl) -> $source { + let SourceBuilder{ _input, src_bits, is_active_high, filter_bits } = self; + + // Setup fault source + unsafe { + let common = &*HRTIM_COMMON::ptr(); + + common.fltinr2.modify(|_r, w| w.$fltWsrc_1().bit(src_bits & 0b10 != 0)); + common.$fltinrZ.modify(|_r, w| w + .$fltWsrc_0().bit(src_bits & 0b01 != 0) + .$fltWp().bit(is_active_high) + .$fltWf().bits(filter_bits) + .$fltWe().set_bit() // Enable + ); + + // ... and lock configuration + common.$fltinrZ.modify(|_r, w| w.$fltWlck().set_bit()); + } + + $source { + _x: PhantomData + } + } + + pub fn polarity(mut self, polarity: super::Polarity) -> Self { + self.is_active_high = polarity == super::Polarity::ActiveHigh; + self + } + + // TODO: add more settings + /* pub fn filter(?) -> Self */ + /* pub fn blanking(?) -> Self */ + } + + impl FaultSource for $source { + const ENABLE_BITS: u8 = $enable_bits; + } + )+} +} + +// TODO: Lookup to ensure the alternate function are the same for other devices than stm32g474 +#[cfg(feature = "stm32g474")] +impl_faults!( + FaultInput1 => FaultSource1: PINS=[(PA12, AF13),], COMP=COMP2, 0b000001, fltinr1, flt1src, flt1src_1, flt1p, flt1f, flt1e, flt1lck, + FaultInput2 => FaultSource2: PINS=[(PA15, AF13),], COMP=COMP4, 0b000010, fltinr1, flt2src, flt2src_1, flt2p, flt2f, flt2e, flt2lck, + FaultInput3 => FaultSource3: PINS=[(PB10, AF13),], COMP=COMP6, 0b000100, fltinr1, flt3src, flt3src_1, flt3p, flt3f, flt3e, flt3lck, + FaultInput4 => FaultSource4: PINS=[(PB11, AF13),], COMP=COMP1, 0b001000, fltinr1, flt4src, flt4src_1, flt4p, flt4f, flt4e, flt4lck, + FaultInput5 => FaultSource5: PINS=[(PB0, AF13), (PC7, AF3),], COMP=COMP3, 0b010000, fltinr2, flt5src, flt5src_1, flt5p, flt5f, flt5e, flt5lck, + FaultInput6 => FaultSource6: PINS=[(PC10, AF13),], COMP=COMP5, 0b100000, fltinr2, flt6src_0, flt6src_1, flt6p, flt6f, flt6e, flt6lck, +); + +pub struct FaultInputs { + pub fault_input1: FaultInput1, + pub fault_input2: FaultInput2, + pub fault_input3: FaultInput3, + pub fault_input4: FaultInput4, + pub fault_input5: FaultInput5, + pub fault_input6: FaultInput6, +} + pub struct HrPwmControl { _x: PhantomData<()>, + + pub fault_sys: FltMonitorSys, + pub fault_1: FltMonitor1, + pub fault_2: FltMonitor2, + pub fault_3: FltMonitor3, + pub fault_4: FltMonitor4, + pub fault_5: FltMonitor5, + pub fault_6: FltMonitor6, } /// The divsion ratio between f_hrtim and the fault signal sampling clock for digital filters @@ -777,10 +992,6 @@ pub enum FaultSamplingClkDiv { Eight = 0b11, } -pub struct FaultInputs { - _x: (), -} - pub trait HrControltExt { fn hr_control(self, _rcc: &mut Rcc) -> HrTimOngoingCalibration; } @@ -826,7 +1037,26 @@ impl HrTimOngoingCalibration { common.fltinr2.write(|w| w.fltsd().bits(self.divider as u8)); } - (HrPwmControl { _x: PhantomData }, FaultInputs { _x: () }) + ( + HrPwmControl { + _x: PhantomData, + fault_sys: FltMonitorSys { _x: PhantomData }, + fault_1: FltMonitor1 { _x: PhantomData }, + fault_2: FltMonitor2 { _x: PhantomData }, + fault_3: FltMonitor3 { _x: PhantomData }, + fault_4: FltMonitor4 { _x: PhantomData }, + fault_5: FltMonitor5 { _x: PhantomData }, + fault_6: FltMonitor6 { _x: PhantomData }, + }, + FaultInputs { + fault_input1: FaultInput1 { _x: PhantomData }, + fault_input2: FaultInput2 { _x: PhantomData }, + fault_input3: FaultInput3 { _x: PhantomData }, + fault_input4: FaultInput4 { _x: PhantomData }, + fault_input5: FaultInput5 { _x: PhantomData }, + fault_input6: FaultInput6 { _x: PhantomData }, + }, + ) } pub fn wait_for_calibration(self) -> (HrPwmControl, FaultInputs) { @@ -839,3 +1069,38 @@ impl HrTimOngoingCalibration { unsafe { self.init() } } } + +macro_rules! impl_flt_monitor { + ($($t:ident: ($fltx:ident, $fltxc:ident),)+) => {$( + pub struct $t { + _x: PhantomData<()> + } + + impl FaultMonitor for $t { + fn is_fault_active(&self) -> bool { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.isr.read().$fltx().bit() + } + + fn clear_fault(&mut self) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.icr.write(|w| w.$fltxc().set_bit()); + } + + // TODO: Should we have our own trait since it does not seem possible to implement this + fn set_fault(&mut self) { + todo!() + } + } + )+}; +} + +impl_flt_monitor!( + FltMonitorSys: (sysflt, sysfltc), + FltMonitor1: (flt1, flt1c), + FltMonitor2: (flt2, flt2c), + FltMonitor3: (flt3, flt3c), + FltMonitor4: (flt4, flt4c), + FltMonitor5: (flt5, flt5c), + FltMonitor6: (flt6, flt6c), +); From 06ecbec5dd72da74f71a32d259d52d24c5d6e9fd Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 20 Jun 2023 15:20:37 +0200 Subject: [PATCH 28/88] Add hrtim fault example --- examples/hrtim_flt.rs | 113 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 examples/hrtim_flt.rs diff --git a/examples/hrtim_flt.rs b/examples/hrtim_flt.rs new file mode 100644 index 00000000..a219e1bb --- /dev/null +++ b/examples/hrtim_flt.rs @@ -0,0 +1,113 @@ +//This example puts the timer in PWM mode using the specified pin with a frequency of 100Hz and a duty cycle of 50%. +#![no_main] +#![no_std] + +use cortex_m_rt::entry; +use fugit::ExtU32; +use hal::gpio::gpioa::PA8; +use hal::gpio::Alternate; +use hal::gpio::AF13; +use hal::prelude::*; +use hal::pwm::hrtim::EventSource; +use hal::pwm::hrtim::FaultAction; +use hal::pwm::hrtim::FaultSamplingClkDiv; +use hal::pwm::hrtim::HrCompareRegister; +use hal::pwm::hrtim::HrPwmAdvExt; +use hal::pwm::hrtim::HrTimer; +use hal::pwm::hrtim::Pscl4; +use hal::pwm::hrtim::{HrControltExt, HrOutput}; +use hal::pwm::FaultMonitor; +use hal::rcc; +use hal::stm32; +use stm32g4::stm32g474::HRTIM_COMMON; +use stm32g4xx_hal as hal; +//mod utils; + +use defmt_rtt as _; // global logger +use panic_probe as _; + +#[entry] +fn main() -> ! { + let dp = stm32::Peripherals::take().expect("cannot take peripherals"); + let cp = stm32::CorePeripherals::take().expect("cannot take core"); + // Set system frequency to 16MHz * 75/4/2 = 150MHz + // This would lead to HrTim running at 150MHz * 32 = 4.8GHz... + let mut rcc = dp.RCC.freeze(rcc::Config::pll().pll_cfg(rcc::PllConfig { + mux: rcc::PLLSrc::HSI, + n: rcc::PllNMul::MUL_75, + m: rcc::PllMDiv::DIV_4, + r: Some(rcc::PllRDiv::DIV_2), + ..Default::default() + })); + + let mut delay = cp.SYST.delay(&rcc.clocks); + + let gpioa = dp.GPIOA.split(&mut rcc); + let gpiob = dp.GPIOB.split(&mut rcc); + let (mut fault_control, flt_inputs) = + dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); + + let fault_source3 = flt_inputs + .fault_input3 + .bind_pin(gpiob.pb10.into_pull_down_input()) + .polarity(hal::pwm::Polarity::ActiveHigh) + .finalize(&mut fault_control); + + // ...with a prescaler of 4 this gives us a HrTimer with a tick rate of 1.2GHz + // With max the max period set, this would be 1.2GHz/2^16 ~= 18kHz... + let prescaler = Pscl4; + + let pin_a: PA8> = gpioa.pa8.into_alternate(); + + // . . . * + // . 33% . . * . . + // .-----. .-----. .--. . . + //out1 | | | | | | . . + // | | | | | | . . + // ------ ----------- ----------- ----------------------------------- + // . . . * . . + // . . . * . . + // . . . *-------- . . + //fault . . . | | . . + // . . . | | . . + // ----------------------------------------- -------------------------- + // . . . * . . + // . . . * . . + let (timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp + .HRTIM_TIMA + .pwm_advanced(pin_a, &mut rcc) + .prescaler(prescaler) + .period(0xFFFF) + //.with_fault_source(fault_source1) + //.with_fault_source(fault_source2) + .with_fault_source(fault_source3) // Set fault source + //.with_fault_source(fault_source4) + //.with_fault_source(fault_source5) + //.with_fault_source(fault_source6) + .fault_action1(FaultAction::ForceInactive) + .fault_action2(FaultAction::ForceInactive) + // alternated every period with one being + // inactive and the other getting to output its wave form + // as normal + .finalize(&mut fault_control); + + out1.enable_rst_event(EventSource::Cr1); // Set low on compare match with cr1 + out1.enable_set_event(EventSource::Period); // Set high at new period + cr1.set_duty(timer.get_period() / 3); + //unsafe {((HRTIM_COMMON::ptr() as *mut u8).offset(0x14) as *mut u32).write_volatile(1); } + out1.enable(); + + defmt::info!("Started"); + + loop { + for _ in 0..5 { + delay.delay(500_u32.millis()); + defmt::info!("State: {}", out1.get_state()); + } + if fault_control.fault_3.is_fault_active() { + fault_control.fault_3.clear_fault(); // Clear fault every 5s + out1.enable(); + defmt::info!("failt cleared, and output reenabled"); + } + } +} From 9b25a6f9809fa1159a5102e0092bcebb127c011f Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 28 Jun 2023 17:58:47 +0200 Subject: [PATCH 29/88] TOO MANY CHANGES * dma - update for new pac * adc - triggers * hrtim --- examples/adc-one-shot.rs | 2 +- examples/hrtim-adc-trigger.rs | 83 +++++ examples/hrtim.rs | 10 +- examples/hrtim_flt.rs | 2 - examples/hrtim_flt_comp.rs | 132 ++++++++ src/adc.rs | 5 + src/pwm/hrtim.rs | 560 ++++++++++++++++++++++++++++++---- 7 files changed, 734 insertions(+), 60 deletions(-) create mode 100644 examples/hrtim-adc-trigger.rs create mode 100644 examples/hrtim_flt_comp.rs diff --git a/examples/adc-one-shot.rs b/examples/adc-one-shot.rs index 7e727430..d67e338d 100644 --- a/examples/adc-one-shot.rs +++ b/examples/adc-one-shot.rs @@ -13,7 +13,7 @@ use stm32g4xx_hal as hal; use cortex_m_rt::entry; -use log::info; +use utils::logger::info; #[macro_use] mod utils; diff --git a/examples/hrtim-adc-trigger.rs b/examples/hrtim-adc-trigger.rs new file mode 100644 index 00000000..a83e7846 --- /dev/null +++ b/examples/hrtim-adc-trigger.rs @@ -0,0 +1,83 @@ +#![no_std] +#![no_main] + +use cortex_m_rt::entry; +use hal::adc::{self, config::ExternalTrigger12}; + +use crate::hal::{ + adc::{ + config::{Continuous, Dma as AdcDma, SampleTime, Sequence}, + AdcClaim, ClockSource, Temperature, Vref, + }, + delay::SYSTDelayExt, + dma::{config::DmaConfig, stream::DMAExt, TransferExt}, + gpio::GpioExt, + rcc::{Config, RccExt}, + stm32::Peripherals, +}; +use stm32g4xx_hal as hal; + +use log::info; + +#[macro_use] +mod utils; + +#[entry] +fn main() -> ! { + utils::logger::init(); + + info!("start"); + + let dp = Peripherals::take().unwrap(); + let cp = cortex_m::Peripherals::take().expect("cannot take core peripherals"); + + info!("rcc"); + let rcc = dp.RCC.constrain(); + let mut rcc = rcc.freeze(Config::hsi()); + + let streams = dp.DMA1.split(&rcc); + let config = DmaConfig::default() + .transfer_complete_interrupt(false) + .circular_buffer(true) + .memory_increment(true); + + info!("Setup Gpio"); + let gpioa = dp.GPIOA.split(&mut rcc); + let pa0 = gpioa.pa0.into_analog(); + + info!("Setup Adc1"); + let mut delay = cp.SYST.delay(&rcc.clocks); + let mut adc = dp + .ADC1 + .claim(ClockSource::SystemClock, &rcc, &mut delay, true); + + adc.set_external_trigger((adc::config::TriggerMode::RisingEdge, ExternalTrigger12::Hrtim_adc_trg_1)); + adc.enable_temperature(&dp.ADC12_COMMON); + adc.set_continuous(Continuous::Continuous); + adc.reset_sequence(); + adc.configure_channel(&pa0, Sequence::One, SampleTime::Cycles_640_5); + adc.configure_channel(&Temperature, Sequence::Two, SampleTime::Cycles_640_5); + + info!("Setup DMA"); + let first_buffer = cortex_m::singleton!(: [u16; 10] = [0; 10]).unwrap(); + let mut transfer = streams.0.into_circ_peripheral_to_memory_transfer( + adc.enable_dma(AdcDma::Continuous), + &mut first_buffer[..], + config, + ); + + transfer.start(|adc| adc.start_conversion()); + + loop { + let mut b = [0_u16; 4]; + let r = transfer.read_exact(&mut b); + + info!("read: {}", r); + assert!(r == b.len()); + + let millivolts = Vref::sample_to_millivolts((b[0] + b[2]) / 2); + info!("pa3: {}mV", millivolts); + let temp = Temperature::temperature_to_degrees_centigrade((b[1] + b[3]) / 2); + info!("temp: {}℃C", temp); // Note: Temperature seems quite low... + } +} diff --git a/examples/hrtim.rs b/examples/hrtim.rs index a3b41713..57e1e161 100644 --- a/examples/hrtim.rs +++ b/examples/hrtim.rs @@ -37,12 +37,14 @@ fn main() -> ! { let dp = stm32::Peripherals::take().expect("cannot take peripherals"); let cp = stm32::CorePeripherals::take().expect("cannot take core"); - // Set system frequency to 16MHz * 75/4/2 = 150MHz - // This would lead to HrTim running at 150MHz * 32 = 4.8GHz... + // Set system frequency to 16MHz * 15/1/2 = 120MHz + // This would lead to HrTim running at 120MHz * 32 = 3.84... let mut rcc = dp.RCC.freeze(rcc::Config::pll().pll_cfg(rcc::PllConfig { - n: rcc::PllNMul::MUL_75, - m: rcc::PllMDiv::DIV_4, + mux: rcc::PLLSrc::HSI, + n: rcc::PllNMul::MUL_15, + m: rcc::PllMDiv::DIV_1, r: Some(rcc::PllRDiv::DIV_2), + ..Default::default() })); diff --git a/examples/hrtim_flt.rs b/examples/hrtim_flt.rs index a219e1bb..a9c1f4ee 100644 --- a/examples/hrtim_flt.rs +++ b/examples/hrtim_flt.rs @@ -10,7 +10,6 @@ use hal::gpio::AF13; use hal::prelude::*; use hal::pwm::hrtim::EventSource; use hal::pwm::hrtim::FaultAction; -use hal::pwm::hrtim::FaultSamplingClkDiv; use hal::pwm::hrtim::HrCompareRegister; use hal::pwm::hrtim::HrPwmAdvExt; use hal::pwm::hrtim::HrTimer; @@ -19,7 +18,6 @@ use hal::pwm::hrtim::{HrControltExt, HrOutput}; use hal::pwm::FaultMonitor; use hal::rcc; use hal::stm32; -use stm32g4::stm32g474::HRTIM_COMMON; use stm32g4xx_hal as hal; //mod utils; diff --git a/examples/hrtim_flt_comp.rs b/examples/hrtim_flt_comp.rs new file mode 100644 index 00000000..816dd8ef --- /dev/null +++ b/examples/hrtim_flt_comp.rs @@ -0,0 +1,132 @@ +//This example puts the timer in PWM mode using the specified pin with a frequency of 100Hz and a duty cycle of 50%. +#![no_main] +#![no_std] + +use cortex_m_rt::entry; +use fugit::ExtU32; +use hal::comparator::{ComparatorExt, ComparatorSplit, Config, Hysteresis, RefintInput}; +use hal::dac::{Dac1IntSig1, DacExt, DacOut}; +use hal::gpio::gpioa::PA8; +use hal::gpio::Alternate; +use hal::gpio::AF13; +use hal::prelude::*; +use hal::pwm::hrtim::EventSource; +use hal::pwm::hrtim::FaultAction; +use hal::pwm::hrtim::HrCompareRegister; +use hal::pwm::hrtim::HrPwmAdvExt; +use hal::pwm::hrtim::HrTimer; +use hal::pwm::hrtim::Pscl4; +use hal::pwm::hrtim::{HrControltExt, HrOutput}; +use hal::pwm::FaultMonitor; +use hal::rcc; +use hal::stm32; +use stm32g4xx_hal as hal; +//mod utils; + +use defmt_rtt as _; // global logger +use panic_probe as _; + +#[entry] +fn main() -> ! { + let dp = stm32::Peripherals::take().expect("cannot take peripherals"); + let cp = stm32::CorePeripherals::take().expect("cannot take core"); + // Set system frequency to 16MHz * 75/4/2 = 150MHz + // This would lead to HrTim running at 150MHz * 32 = 4.8GHz... + let mut rcc = dp.RCC.freeze(rcc::Config::pll().pll_cfg(rcc::PllConfig { + mux: rcc::PLLSrc::HSI, + n: rcc::PllNMul::MUL_75, + m: rcc::PllMDiv::DIV_4, + r: Some(rcc::PllRDiv::DIV_2), + ..Default::default() + })); + + let mut delay = cp.SYST.delay(&rcc.clocks); + + let gpioa = dp.GPIOA.split(&mut rcc); + + let dac1ch1 = dp.DAC1.constrain(Dac1IntSig1, &mut rcc); + let mut dac = dac1ch1.calibrate_buffer(&mut delay).enable(); + + // Use dac to define the fault threshold + // 2^12 / 2 = 2^11 for about half of VCC + let fault_limit = 1 << 11; + dac.set_value(fault_limit); + + let (comp1, ..) = dp.COMP.split(&mut rcc); + + let pa1 = gpioa.pa1.into_analog(); + let comp1 = comp1 + .comparator( + &pa1, + &dac, + Config::default() + .hysteresis(Hysteresis::None) + .output_inverted(), + &rcc.clocks, + ) + .enable(); + + let (mut fault_control, flt_inputs) = + dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); + + let fault_source4 = flt_inputs + .fault_input4 + .bind_comp(&comp1) + .polarity(hal::pwm::Polarity::ActiveLow) + .finalize(&mut fault_control); + + // ...with a prescaler of 4 this gives us a HrTimer with a tick rate of 1.2GHz + // With max the max period set, this would be 1.2GHz/2^16 ~= 18kHz... + let prescaler = Pscl4; + + let pin_a: PA8> = gpioa.pa8.into_alternate(); + + // . . . * + // . 33% . . * . . + // .-----. .-----. .--. . . + //out1 | | | | | | . . + // | | | | | | . . + // ------ ----------- ----------- ----------------------------------- + // . . . * . . + // . . . * . . + // . . . *-------- . . + //fault . . . | | . . + // . . . | | . . + // ----------------------------------------- -------------------------- + // . . . * . . + // . . . * . . + let (timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp + .HRTIM_TIMA + .pwm_advanced(pin_a, &mut rcc) + .prescaler(prescaler) + .period(0xFFFF) + .with_fault_source(fault_source4) // Set fault source + .fault_action1(FaultAction::ForceInactive) + .fault_action2(FaultAction::ForceInactive) + .finalize(&mut fault_control); + + out1.enable_rst_event(EventSource::Cr1); // Set low on compare match with cr1 + out1.enable_set_event(EventSource::Period); // Set high at new period + cr1.set_duty(timer.get_period() / 3); + //unsafe {((HRTIM_COMMON::ptr() as *mut u8).offset(0x14) as *mut u32).write_volatile(1); } + out1.enable(); + + defmt::info!("Started"); + + loop { + for _ in 0..5 { + delay.delay(500_u32.millis()); + defmt::info!( + "State: {}, comp: {}, is_fault_active: {}", + out1.get_state(), + comp1.output(), + fault_control.fault_4.is_fault_active() + ); + } + if fault_control.fault_4.is_fault_active() { + fault_control.fault_4.clear_fault(); // Clear fault every 5s + out1.enable(); + defmt::info!("failt cleared, and output reenabled"); + } + } +} diff --git a/src/adc.rs b/src/adc.rs index 600e8bcf..08a9a73a 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -1885,6 +1885,11 @@ macro_rules! adc { /// Calibrate the adc for #[inline(always)] pub fn calibrate(&mut self, it: config::InputType) { + let cr = self.adc_reg.cr().read(); + assert!(cr.aden().bit_is_clear()); + assert!(cr.adstart().bit_is_clear()); + assert!(cr.jadstart().bit_is_clear()); + match it { config::InputType::SingleEnded => { self.adc_reg.cr().modify(|_, w| w.adcaldif().clear_bit() ); diff --git a/src/pwm/hrtim.rs b/src/pwm/hrtim.rs index 0348e4f1..fe0cb66a 100644 --- a/src/pwm/hrtim.rs +++ b/src/pwm/hrtim.rs @@ -3,9 +3,10 @@ use core::mem::MaybeUninit; use fugit::HertzU64; +use crate::comparator::{COMP1, COMP2, COMP3, COMP4, COMP5, COMP6}; use crate::gpio::gpioa::{PA10, PA11, PA12, PA13, PA15, PA8, PA9}; use crate::gpio::gpiob::{PB0, PB10, PB11, PB14, PB15}; -use crate::gpio::gpioc::{PC10, PC7, PC8, PC9}; +use crate::gpio::gpioc::{PC10, PC6, PC7, PC8, PC9}; use crate::gpio::{self, AF3}; use crate::gpio::{Alternate, AF13}; use crate::stm32::{ @@ -60,7 +61,7 @@ pins! { HRTIM_TIMD: CH1: PB14>, CH2: PB15> HRTIM_TIME: CH1: PC8>, CH2: PC9> - //HRTIM_TIMF: CH1: PC6>, CH2: PC7> + HRTIM_TIMF: CH1: PC6>, CH2: PC7> } // automatically implement Pins trait for tuples of individual pins @@ -133,6 +134,7 @@ pub struct HrPwmBuilder { alignment: Alignment, base_freq: HertzU64, count: CountSettings, + preload_source: Option, fault_enable_bits: u8, fault1_bits: u8, fault2_bits: u8, @@ -140,6 +142,11 @@ pub struct HrPwmBuilder { //deadtime: NanoSecond, } +pub enum PreloadSource { + /// Preloaded registers are updated on counter roll over or counter reset + OnCounterReset, +} + pub trait HrCompareRegister { fn get_duty(&self) -> u16; fn set_duty(&mut self, duty: u16); @@ -271,7 +278,7 @@ macro_rules! hrtim_hal { { let _= self.pwm_advanced(pins, rcc).frequency(frequency).finalize(control); - unsafe { MaybeUninit::::uninit().assume_init() } + unsafe { MaybeUninit::::uninit().assume_init() } } } @@ -300,6 +307,7 @@ macro_rules! hrtim_hal { alignment: Alignment::Left, base_freq: clk, count: CountSettings::Period(u16::MAX), + preload_source: None, enable_push_pull: false, //deadtime: 0.nanos(), } @@ -360,13 +368,21 @@ macro_rules! hrtim_hal { .fault1().bits(self.fault1_bits) .fault2().bits(self.fault2_bits) ); + + match self.preload_source { + Some(PreloadSource::OnCounterReset) => { + tim.$timXcr.modify(|_r, w| w + .tx_rstu().set_bit() + .preen().set_bit() + ) + }, + None => () + } } // Start timer - cortex_m::interrupt::free(|_| { - let master = unsafe { &*HRTIM_MASTER::ptr() }; - master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); - }); + let master = unsafe { &*HRTIM_MASTER::ptr() }; + master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); unsafe { MaybeUninit::uninit().assume_init() @@ -397,6 +413,7 @@ macro_rules! hrtim_hal { alignment, base_freq, count, + preload_source, } = self; let period = match count { @@ -417,47 +434,35 @@ macro_rules! hrtim_hal { alignment, base_freq, count, + preload_source, //deadtime: 0.nanos(), } } - pub fn with_fault_source(self, _fault_source: FS) -> HrPwmBuilder<$TIMX, PSCL, OUT> + // TODO: Allow setting multiple? + pub fn preload(mut self, preload_source: PreloadSource) -> Self { + self.preload_source = Some(preload_source); + + self + } + + pub fn with_fault_source(mut self, _fault_source: FS) -> Self where FS: FaultSource { - let HrPwmBuilder { - _tim, - _prescaler: _, - _out, - fault_enable_bits, - fault1_bits, - fault2_bits, - enable_push_pull, - alignment, - base_freq, - count, - } = self; + self.fault_enable_bits = self.fault_enable_bits | FS::ENABLE_BITS; - HrPwmBuilder { - _tim, - fault_enable_bits: fault_enable_bits | FS::ENABLE_BITS, - fault1_bits, - fault2_bits, - _prescaler: PhantomData, - _out, - enable_push_pull, - alignment, - base_freq, - count, - } + 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 } @@ -601,17 +606,13 @@ macro_rules! hrtim_out { ($($TIMX:ident: $out_type:ident: $tXYoen:ident, $tXYodis:ident, $tXYods:ident, $setXYr:ident, $rstXYr:ident,)+) => {$( impl HrOutput for $out_type<$TIMX> { fn enable(&mut self) { - cortex_m::interrupt::free(|_| { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.oenr.write(|w| { w.$tXYoen().set_bit() }); - }); + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.oenr.write(|w| { w.$tXYoen().set_bit() }); } fn disable(&mut self) { - cortex_m::interrupt::free(|_| { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.odisr.write(|w| { w.$tXYodis().set_bit() }); - }); + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.odisr.write(|w| { w.$tXYodis().set_bit() }); } fn enable_set_event(&mut self, set_event: EventSource) { @@ -664,11 +665,8 @@ hrtim_out! { HRTIM_TIME: HrOut1: te1oen, te1odis, te1ods, sete1r, rste1r, HRTIM_TIME: HrOut2: te2oen, te2odis, te2ods, sete2r, rste2r, - // TODO: Somehow, there is no rstf1r - //HRTIM_TIMF: HrOut1: tf1oen, tf1odis, tf1ods, setf1r, rstf1r, - - // TODO: Somehow, there is no tf2oen - //HRTIM_TIMF: HrOut2: tf2oen, tf2odis, tf2ods, setf2r, rstf2r, + HRTIM_TIMF: HrOut1: tf1oen, tf1odis, tf1ods, setf1r, rstf1r, + HRTIM_TIMF: HrOut2: tf2oen, tf2odis, tf2ods, setf2r, rstf2r, } macro_rules! hrtim_cr_helper { @@ -759,11 +757,8 @@ hrtim_pin_hal! { HRTIM_TIME: (CH1, perer, cmp1er, cmp1x, cmp1, te1oen, te1odis, sete1r, rste1r), HRTIM_TIME: (CH2, perer, cmp3er, cmp3x, cmp3, te2oen, te2odis, sete2r, rste2r), - // TODO: tf1oen and rstf1r are not defined - //HRTIM_TIMF: (CH1, perfr, cmp1fr, cmp1x, cmp1, tf1oen, tf1odis, setf1r, rstf1r), - - // TODO: tf2oen is not defined - //HRTIM_TIMF: (CH2, perfr, cmp3fr, cmp3x, cmp3, tf2oen, tf2odis, setf2r, rstf2r), + HRTIM_TIMF: (CH1, perfr, cmp1fr, cmp1x, cmp1, tf1oen, tf1odis, setf1r, rstf1r), + HRTIM_TIMF: (CH2, perfr, cmp3fr, cmp3x, cmp3, tf2oen, tf2odis, setf2r, rstf2r), } pub trait HrtimPrescaler { @@ -887,9 +882,9 @@ macro_rules! impl_faults { } )* - /*pub fn bind_comp(self, comp: $compX) -> SourceBuilder<$input> { + pub fn bind_comp(self, _comp: &crate::comparator::Comparator<$compX, crate::comparator::Enabled>) -> SourceBuilder<$input> { unsafe { SourceBuilder::new(self, 0b01) } - }*/ + } /*pub fn bind_external(?) { SourceBuilder::new(self, 0b10); @@ -1013,20 +1008,57 @@ impl HrControltExt for HRTIM_COMMON { .write(|w| w.cal().set_bit().calen().clear_bit()); HrTimOngoingCalibration { + adc_trigger1_bits: 0, + adc_trigger2_bits: 0, + adc_trigger3_bits: 0, + adc_trigger4_bits: 0, + + adc_trigger1_postscaler: AdcTriggerPostscaler::None, + adc_trigger2_postscaler: AdcTriggerPostscaler::None, + adc_trigger3_postscaler: AdcTriggerPostscaler::None, + adc_trigger4_postscaler: AdcTriggerPostscaler::None, + divider: FaultSamplingClkDiv::None, } } } pub struct HrTimOngoingCalibration { + adc_trigger1_bits: u32, + adc_trigger2_bits: u32, + adc_trigger3_bits: u32, + adc_trigger4_bits: u32, + + adc_trigger1_postscaler: AdcTriggerPostscaler, + adc_trigger2_postscaler: AdcTriggerPostscaler, + adc_trigger3_postscaler: AdcTriggerPostscaler, + adc_trigger4_postscaler: AdcTriggerPostscaler, + divider: FaultSamplingClkDiv, } impl HrTimOngoingCalibration { /// SAFETY: Calibration needs to be done before calling this unsafe fn init(self) -> (HrPwmControl, FaultInputs) { + use Adc13Trigger as Ad13T; + use Adc24Trigger as Ad24T; + let common = unsafe { &*HRTIM_COMMON::ptr() }; + let Self { + adc_trigger1_bits: ad1_bits, + adc_trigger2_bits: ad2_bits, + adc_trigger3_bits: ad3_bits, + adc_trigger4_bits: ad4_bits, + + adc_trigger1_postscaler, + adc_trigger2_postscaler, + adc_trigger3_postscaler, + adc_trigger4_postscaler, + + divider, + } = self; + unsafe { // Enable periodic calibration // with f_hrtim at 170MHz, these settings leads to @@ -1034,7 +1066,156 @@ impl HrTimOngoingCalibration { common .dllcr .modify(|_r, w| w.calrte().bits(0b00).cal().set_bit().calen().clear_bit()); - common.fltinr2.write(|w| w.fltsd().bits(self.divider as u8)); + common.fltinr2.write(|w| w.fltsd().bits(divider as u8)); + + common.adc1r.write(|w| w + .eper().bit(ad1_bits | Ad13T::TimEPeriod as u32 != 0) + .ec4().bit(ad1_bits | Ad13T::TimECmp4 as u32 != 0) + .ec3().bit(ad1_bits | Ad13T::TimECmp3 as u32 != 0) + //.frst() + .dper().bit(ad1_bits | Ad13T::TimDPeriod as u32 != 0) + .dc4().bit(ad1_bits | Ad13T::TimDCmp4 as u32 != 0) + .dc3().bit(ad1_bits | Ad13T::TimDCmp3 as u32 != 0) + .fper().bit(ad1_bits | Ad13T::TimFPeriod as u32 != 0) + .cper().bit(ad1_bits | Ad13T::TimCPeriod as u32 != 0) + .cc4().bit(ad1_bits | Ad13T::TimCCmp4 as u32 != 0) + .cc3().bit(ad1_bits | Ad13T::TimCCmp3 as u32 != 0) + .fc4().bit(ad1_bits | Ad13T::TimFCmp4 as u32 != 0) + //.brst() + .bper().bit(ad1_bits | Ad13T::TimBPeriod as u32 != 0) + .bc4().bit(ad1_bits | Ad13T::TimBCmp4 as u32 != 0) + .bc3().bit(ad1_bits | Ad13T::TimBCmp3 as u32 != 0) + .fc3().bit(ad1_bits | Ad13T::TimFCmp3 as u32 != 0) + //.arst() + .aper().bit(ad1_bits | Ad13T::TimAPeriod as u32 != 0) + .ac4().bit(ad1_bits | Ad13T::TimACmp4 as u32 != 0) + .ac3().bit(ad1_bits | Ad13T::TimACmp3 as u32 != 0) + .fc2().bit(ad1_bits | Ad13T::TimFCmp2 as u32 != 0) + //.eev5().bit(ad1_bits | Ad13T::_ as u32) + //.eev4().bit(ad1_bits | Ad13T::_ as u32) + //.eev3().bit(ad1_bits | Ad13T::_ as u32) + //.eev2().bit(ad1_bits | Ad13T::_ as u32) + //.eev1().bit(ad1_bits | Ad13T::_ as u32) + .mper().bit(ad1_bits | Ad13T::MasterPeriod as u32 != 0) + .mc4().bit(ad1_bits | Ad13T::MasterCmp4 as u32 != 0) + .mc3().bit(ad1_bits | Ad13T::MasterCmp3 as u32 != 0) + .mc2().bit(ad1_bits | Ad13T::MasterCmp2 as u32 != 0) + .mc1().bit(ad1_bits | Ad13T::MasterCmp1 as u32 != 0) + ); + + common.adc3r.write(|w| w + .eper().bit(ad3_bits | Ad13T::TimEPeriod as u32 != 0) + .ec4().bit(ad3_bits | Ad13T::TimECmp4 as u32 != 0) + .ec3().bit(ad3_bits | Ad13T::TimECmp3 as u32 != 0) + //.frst() + .dper().bit(ad3_bits | Ad13T::TimDPeriod as u32 != 0) + .dc4().bit(ad3_bits | Ad13T::TimDCmp4 as u32 != 0) + .dc3().bit(ad3_bits | Ad13T::TimDCmp3 as u32 != 0) + .fper().bit(ad3_bits | Ad13T::TimFPeriod as u32 != 0) + .cper().bit(ad3_bits | Ad13T::TimCPeriod as u32 != 0) + .cc4().bit(ad3_bits | Ad13T::TimCCmp4 as u32 != 0) + .cc3().bit(ad3_bits | Ad13T::TimCCmp3 as u32 != 0) + .fc4().bit(ad3_bits | Ad13T::TimFCmp4 as u32 != 0) + //.brst() + .bper().bit(ad3_bits | Ad13T::TimBPeriod as u32 != 0) + .bc4().bit(ad3_bits | Ad13T::TimBCmp4 as u32 != 0) + .bc3().bit(ad3_bits | Ad13T::TimBCmp3 as u32 != 0) + .fc3().bit(ad3_bits | Ad13T::TimFCmp3 as u32 != 0) + //.arst() + .aper().bit(ad3_bits | Ad13T::TimAPeriod as u32 != 0) + .ac4().bit(ad3_bits | Ad13T::TimACmp4 as u32 != 0) + .ac3().bit(ad3_bits | Ad13T::TimACmp3 as u32 != 0) + .fc2().bit(ad3_bits | Ad13T::TimFCmp2 as u32 != 0) + //.eev5().bit(ad3_bits | Ad13T::_ as u32) + //.eev4().bit(ad3_bits | Ad13T::_ as u32) + //.eev3().bit(ad3_bits | Ad13T::_ as u32) + //.eev2().bit(ad3_bits | Ad13T::_ as u32) + //.eev1().bit(ad3_bits | Ad13T::_ as u32) + .mper().bit(ad3_bits | Ad13T::MasterPeriod as u32 != 0) + .mc4().bit(ad3_bits | Ad13T::MasterCmp4 as u32 != 0) + .mc3().bit(ad3_bits | Ad13T::MasterCmp3 as u32 != 0) + .mc2().bit(ad3_bits | Ad13T::MasterCmp2 as u32 != 0) + .mc1().bit(ad3_bits | Ad13T::MasterCmp1 as u32 != 0) + ); + + common.adc2r.write(|w| w + //.erst() + .ec4().bit(ad2_bits | Ad24T::TimECmp4 as u32 != 0) + .ec3().bit(ad2_bits | Ad24T::TimECmp3 as u32 != 0) + .ec2().bit(ad2_bits | Ad24T::TimECmp2 as u32 != 0) + //.drst().bit(ad2_bits | Ad24T::_ as u32 != 0) + .dper().bit(ad2_bits | Ad24T::TimDPeriod as u32 != 0) + .dc4().bit(ad2_bits | Ad24T::TimDCmp4 as u32 != 0) + .fper().bit(ad2_bits | Ad24T::TimFPeriod as u32 != 0) + .dc2().bit(ad2_bits | Ad24T::TimACmp2 as u32 != 0) + //.crst().bit(ad2_bits | Ad24T::_ as u32 != 0) + .cper().bit(ad2_bits | Ad24T::TimCPeriod as u32 != 0) + .cc4().bit(ad2_bits | Ad24T::TimCCmp4 as u32 != 0) + .fc4().bit(ad2_bits | Ad24T::TimFCmp4 as u32 != 0) + .cc2().bit(ad2_bits | Ad24T::TimCCmp2 as u32 != 0) + .bper().bit(ad2_bits | Ad24T::TimBPeriod as u32 != 0) + .bc4().bit(ad2_bits | Ad24T::TimBCmp4 as u32 != 0) + .fc3().bit(ad2_bits | Ad24T::TimFCmp3 as u32 != 0) + .bc2().bit(ad2_bits | Ad24T::TimBCmp2 as u32 != 0) + .aper().bit(ad2_bits | Ad24T::TimAPeriod as u32 != 0) + .ac4().bit(ad2_bits | Ad24T::TimACmp4 as u32 != 0) + .fc2().bit(ad2_bits | Ad24T::TimFCmp2 as u32 != 0) + .ac2().bit(ad2_bits | Ad24T::TimACmp2 as u32 != 0) + //.eev10() + //.eev9() + //.eev8() + //.eev7() + //.eev6() + .mper().bit(ad2_bits | Ad24T::MasterPeriod as u32 != 0) + .mc4().bit(ad2_bits | Ad24T::MasterCmp4 as u32 != 0) + .mc3().bit(ad2_bits | Ad24T::MasterCmp3 as u32 != 0) + .mc2().bit(ad2_bits | Ad24T::MasterCmp2 as u32 != 0) + .mc1().bit(ad2_bits | Ad24T::MasterCmp1 as u32 != 0) + ); + + common.adc4r.write(|w| w + //.erst() + .ec4().bit(ad4_bits | Ad24T::TimECmp4 as u32 != 0) + .ec3().bit(ad4_bits | Ad24T::TimECmp3 as u32 != 0) + .ec2().bit(ad4_bits | Ad24T::TimECmp2 as u32 != 0) + //.drst().bit(ad4_bits | Ad24T::_ as u32 != 0) + .dper().bit(ad4_bits | Ad24T::TimDPeriod as u32 != 0) + .dc4().bit(ad4_bits | Ad24T::TimDCmp4 as u32 != 0) + .fper().bit(ad4_bits | Ad24T::TimFPeriod as u32 != 0) + .dc2().bit(ad4_bits | Ad24T::TimACmp2 as u32 != 0) + //.crst().bit(ad4_bits | Ad24T::_ as u32 != 0) + .cper().bit(ad4_bits | Ad24T::TimCPeriod as u32 != 0) + .cc4().bit(ad4_bits | Ad24T::TimCCmp4 as u32 != 0) + .fc4().bit(ad4_bits | Ad24T::TimFCmp4 as u32 != 0) + .cc2().bit(ad4_bits | Ad24T::TimCCmp2 as u32 != 0) + .bper().bit(ad4_bits | Ad24T::TimBPeriod as u32 != 0) + .bc4().bit(ad4_bits | Ad24T::TimBCmp4 as u32 != 0) + .fc3().bit(ad4_bits | Ad24T::TimFCmp3 as u32 != 0) + .bc2().bit(ad4_bits | Ad24T::TimBCmp2 as u32 != 0) + .aper().bit(ad4_bits | Ad24T::TimAPeriod as u32 != 0) + .ac4().bit(ad4_bits | Ad24T::TimACmp4 as u32 != 0) + .fc2().bit(ad4_bits | Ad24T::TimFCmp2 as u32 != 0) + .ac2().bit(ad4_bits | Ad24T::TimACmp2 as u32 != 0) + //.eev10() + //.eev9() + //.eev8() + //.eev7() + //.eev6() + .mper().bit(ad4_bits | Ad24T::MasterPeriod as u32 != 0) + .mc4().bit(ad4_bits | Ad24T::MasterCmp4 as u32 != 0) + .mc3().bit(ad4_bits | Ad24T::MasterCmp3 as u32 != 0) + .mc2().bit(ad4_bits | Ad24T::MasterCmp2 as u32 != 0) + .mc1().bit(ad4_bits | Ad24T::MasterCmp1 as u32 != 0) + ); + + common.adcps1.write(|w| w + .adc1psc().bits(adc_trigger1_postscaler as u8) + .adc2psc().bits(adc_trigger2_postscaler as u8) + .adc3psc().bits(adc_trigger3_postscaler as u8) + .adc4psc().bits(adc_trigger4_postscaler as u8) + ); + + // TODO: Adc trigger 5-10 } ( @@ -1068,6 +1249,279 @@ impl HrTimOngoingCalibration { // Calibration is now done, it is safe to continue unsafe { self.init() } } + + pub fn set_adc_trigger1(mut self, trigger: Adc13Trigger) -> Self { + self.adc_trigger1_bits |= trigger as u32; + self + } + + pub fn set_adc_trigger2(mut self, trigger: Adc24Trigger) -> Self { + self.adc_trigger2_bits |= trigger as u32; + self + } + + pub fn set_adc_trigger3(mut self, trigger: Adc13Trigger) -> Self { + self.adc_trigger3_bits |= trigger as u32; + self + } + + pub fn set_adc_trigger4(mut self, trigger: Adc24Trigger) -> Self { + self.adc_trigger4_bits |= trigger as u32; + self + } + + pub fn set_adc1_trigger_psc(mut self, post_scaler: AdcTriggerPostscaler) -> Self { + self.adc_trigger1_postscaler = post_scaler; + self + } + + pub fn set_adc2_trigger_psc(mut self, post_scaler: AdcTriggerPostscaler) -> Self { + self.adc_trigger2_postscaler = post_scaler; + self + } + + pub fn set_adc3_trigger_psc(mut self, post_scaler: AdcTriggerPostscaler) -> Self { + self.adc_trigger3_postscaler = post_scaler; + self + } + + pub fn set_adc4_trigger_psc(mut self, post_scaler: AdcTriggerPostscaler) -> Self { + self.adc_trigger4_postscaler = post_scaler; + self + } + + // TODO: Adc trigger 5-10 +} + +pub enum Adc13Trigger { + /// bit 31 ADCxTEPER - Trigger on HRTIM_TIME period + TimEPeriod = 1 << 31, + + /// bit 30 ADCxTEC4 - Trigger on HRTIM_TIME compare match for compare register 4 + TimECmp4 = 1 << 30, + + /// bit 29 ADCxTEC3 - Trigger on HRTIM_TIME compare match for compare register 3 + TimECmp3 = 1 << 29, + + // /// bit 28 ADCxTFRST + // _ = 1 << 28, + + /// bit 27 ADCxTDPER - Trigger on HRTIM_TIMD period + TimDPeriod = 1 << 27, + + /// bit 26 ADCxTDC4 - Trigger on HRTIM_TIMD compare match for compare register 4 + TimDCmp4 = 1 << 26, + + /// bit 25 ADCxTDC3 - Trigger on HRTIM_TIMD compare match for compare register 3 + TimDCmp3 = 1 << 25, + + /// bit 24 ADCxTFPER - Trigger on HRTIM_TIMF period + TimFPeriod = 1 << 24, + + /// bit 23 ADCxTCPER - Trigger on HRTIM_TIMC period + TimCPeriod = 1 << 23, + + /// bit 22 ADCxTCC4 - Trigger on HRTIM_TIMC compare match for compare register 4 + TimCCmp4 = 1 << 22, + + /// bit 21 ADCxTCC3 - Trigger on HRTIM_TIMC compare match for compare register 3 + TimCCmp3 = 1 << 21, + + /// bit 20 ADCxTFC4 - Trigger on HRTIM_TIMF compare match for compare register 4 + TimFCmp4 = 1 << 20, + + // /// bit 19 ADCxTBRST + // _ = 1 << 19, + + /// bit 18 ADCxTBPER - Trigger on HRTIM_TIMB period + TimBPeriod = 1 << 18, + + /// bit 17 ADCxTBC4 - Trigger on HRTIM_TIMB compare match for compare register 4 + TimBCmp4 = 1 << 17, + + /// bit 16 ADCxTBC3 - Trigger on HRTIM_TIMB compare match for compare register 3 + TimBCmp3 = 1 << 16, + + /// bit 15 ADCxTFC3 - Trigger on HRTIM_TIMF compare match for compare register 3 + TimFCmp3 = 1 << 15, + + // /// bit 14 ADCxTARST + // _ = 1 << 14, + + /// bit 13 ADCxTAPER - Trigger on HRTIM_TIMA period + TimAPeriod = 1 << 13, + + /// bit 12 ADCxTAC4 - Trigger on HRTIM_TIMA compare match for compare register 4 + TimACmp4 = 1 << 12, + + /// bit 11 ADCxTAC3 - Trigger on HRTIM_TIMA compare match for compare register 3 + TimACmp3 = 1 << 11, + + /// bit 10 ADCxTFC2 - Trigger on HRTIM_TIMF compare match for compare register 2 + TimFCmp2 = 1 << 10, + + // /// bit 9 ADCxEEV5 + // _ = 1 << 9, + + // /// bit 8 ADCxEEV4 + // _ = 1 << 8, + + // /// bit 7 ADCxEEV3 + // _ = 1 << 7, + + // /// bit 6 ADCxEEV2 + // _ = 1 << 6, + + /// bit 5 ADCxEEV1 + // _ = 1 << 5, + + /// bit 4 ADCxMPER - Trigger on HRTIM_MASTER period + MasterPeriod = 1 << 4, + + /// bit 3 ADCxMC4 - Trigger on HRTIM_MASTER compare match for compare register 4 + MasterCmp4 = 1 << 3, + + /// bit 2 ADCxMC3 - Trigger on HRTIM_MASTER compare match for compare register 3 + MasterCmp3 = 1 << 2, + + /// bit 1 ADCxMC2 - Trigger on HRTIM_MASTER compare match for compare register 2 + MasterCmp2 = 1 << 1, + + /// bit 0 ADCxMC1 - Trigger on HRTIM_MASTER compare match for compare register 1 + MasterCmp1 = 1 << 0, +} + +pub enum AdcTriggerPostscaler { + None = 0, + Div2 = 1, + Div3 = 2, + Div4 = 3, + Div5 = 4, + Div6 = 5, + Div7 = 6, + Div8 = 7, + Div9 = 8, + Div10 = 9, + Div11 = 10, + Div12 = 11, + Div13 = 12, + Div14 = 13, + Div15 = 14, + Div16 = 15, + Div17 = 16, + Div18 = 17, + Div19 = 18, + Div20 = 19, + Div21 = 20, + Div22 = 21, + Div23 = 22, + Div24 = 23, + Div25 = 24, + Div26 = 25, + Div27 = 26, + Div28 = 27, + Div29 = 28, + Div30 = 29, + Div31 = 30, + Div32 = 31, +} + +pub enum Adc24Trigger { + // /// bit 31 ADCxTERST + // _ = 1 << 31, + + /// bit 30 ADCxTEC4 - Trigger on HRTIM_TIME compare match for compare register 4 + TimECmp4 = 1 << 30, + + /// bit 29 ADCxTEC3 - Trigger on HRTIM_TIME compare match for compare register 3 + TimECmp3 = 1 << 29, + + /// bit 28 ADCxTEC2 - Trigger on HRTIM_TIME compare match for compare register 2 + TimECmp2 = 1 << 28, + + // /// bit 27 ADCxTDRST + // _ = 1 << 27, + + /// bit 26 ADCxTDPER - Trigger on HRTIM_TIMD period + TimDPeriod = 1 << 26, + + /// bit 25 ADCxTDC4 - Trigger on HRTIM_TIMD compare match for compare register 4 + TimDCmp4 = 1 << 25, + + /// bit 24 ADCxTFPER - Trigger on HRTIM_TIMF period + TimFPeriod = 1 << 24, + + /// bit 23 ADCxTDC2 - Trigger on HRTIM_TIMD compare match for compare register 2 + TimDCmp2 = 1 << 23, + + /// bit 22 ADCxTCRST + // _ = 1 << 22, + + /// bit 21 ADCxTCPER - Trigger on HRTIM_TIMC period + TimCPeriod = 1 << 21, + + /// bit 20 ADCxTCC4 - Trigger on HRTIM_TIMC compare match for compare register 4 + TimCCmp4 = 1 << 20, + + /// bit 19 ADCxTFC4 - Trigger on HRTIM_TIMF compare match for compare register 4 + TimFCmp4 = 1 << 19, + + /// bit 18 ADCxTCC2 - Trigger on HRTIM_TIMC compare match for compare register 2 + TimCCmp2 = 1 << 18, + + /// bit 17 ADCxTBPER - Trigger on HRTIM_TIMB period + TimBPeriod = 1 << 17, + + /// bit 16 ADCxTBC4 - Trigger on HRTIM_TIMB compare match for compare register 4 + TimBCmp4 = 1 << 16, + + /// bit 15 ADCxTFC3 - Trigger on HRTIM_TIMF compare match for compare register 3 + TimFCmp3 = 1 << 15, + + /// bit 14 ADCxTBC2 - Trigger on HRTIM_TIMB compare match for compare register 2 + TimBCmp2 = 1 << 14, + + /// bit 13 ADCxTAPER - Trigger on HRTIM_TIMA period + TimAPeriod = 1 << 13, + + /// bit 12 ADCxTAC4 - Trigger on HRTIM_TIMA compare match for compare register 4 + TimACmp4 = 1 << 12, + + /// bit 11 ADCxTFC2 - Trigger on HRTIM_TIMF compare match for compare register 2 + TimFCmp2 = 1 << 11, + + /// bit 10 ADCxTAC2 - Trigger on HRTIM_TIMA compare match for compare register 2 + TimACmp2 = 1 << 10, + + // /// bit 9 ADCxEEV10 + // _ = 1 << 9, + + // /// bit 8 ADCxEEV9 + // _ = 1 << 8, + + // /// bit 7 ADCxEEV8 + // _ = 1 << 7, + + // /// bit 6 ADCxEEV7 + // _ = 1 << 6, + + // /// bit 5 ADCxEEV6 + // _ = 1 << 5, + + /// bit 4 ADCxMPER - Trigger on HRTIM_MASTER period + MasterPeriod = 1 << 4, + + /// bit 3 ADCxMC4 - Trigger on HRTIM_MASTER compare match for compare register 4 + MasterCmp4 = 1 << 3, + + /// bit 2 ADCxMC3 - Trigger on HRTIM_MASTER compare match for compare register 3 + MasterCmp3 = 1 << 2, + + /// bit 1 ADCxMC2 - Trigger on HRTIM_MASTER compare match for compare register 2 + MasterCmp2 = 1 << 1, + + /// bit 0 ADCxMC1 - Trigger on HRTIM_MASTER compare match for compare register 1 + MasterCmp1 = 1 << 0, } macro_rules! impl_flt_monitor { From 021143835aab413afcaea36507d4799b606d7ed2 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 25 Aug 2023 17:08:00 +0200 Subject: [PATCH 30/88] Add ADC triggers among a lot of things to hrtim --- examples/hrtim-adc-trigger.rs | 37 +- examples/hrtim-master.rs | 129 ++++ examples/hrtim.rs | 4 +- examples/hrtim_flt_comp.rs | 58 +- src/pwm/hrtim.rs | 1321 ++++++++++++++++++++++++--------- src/rcc/config.rs | 24 +- 6 files changed, 1175 insertions(+), 398 deletions(-) create mode 100644 examples/hrtim-master.rs diff --git a/examples/hrtim-adc-trigger.rs b/examples/hrtim-adc-trigger.rs index a83e7846..9c9f0eb8 100644 --- a/examples/hrtim-adc-trigger.rs +++ b/examples/hrtim-adc-trigger.rs @@ -51,9 +51,12 @@ fn main() -> ! { .ADC1 .claim(ClockSource::SystemClock, &rcc, &mut delay, true); - adc.set_external_trigger((adc::config::TriggerMode::RisingEdge, ExternalTrigger12::Hrtim_adc_trg_1)); + adc.set_external_trigger(( + adc::config::TriggerMode::RisingEdge, + ExternalTrigger12::Hrtim_adc_trg_1, + )); adc.enable_temperature(&dp.ADC12_COMMON); - adc.set_continuous(Continuous::Continuous); + adc.set_continuous(Continuous::Discontinuous); adc.reset_sequence(); adc.configure_channel(&pa0, Sequence::One, SampleTime::Cycles_640_5); adc.configure_channel(&Temperature, Sequence::Two, SampleTime::Cycles_640_5); @@ -68,6 +71,36 @@ fn main() -> ! { transfer.start(|adc| adc.start_conversion()); + // . . + // . 50% . + // ------ ------ + //out1 | | | | + // | | | | + // -------- ---------- -------- + let (mut fault_control, _) = dp + .HRTIM_COMMON + .hr_control(&mut rcc) + .set_adc_trigger1(Adc13Trigger::) + .wait_for_calibration(); + let (mut timer, (mut cr1, _cr2, _cr3, _cr4), (mut out1, mut out2)) = dp + .HRTIM_TIMA + .pwm_advanced((pin_a, pin_b), &mut rcc) + .prescaler(prescaler) + .period(0xFFFF) + // alternated every period with one being + // inactive and the other getting to output its wave form + // as normal + .finalize(&mut fault_control); + + out1.enable_rst_event(EventSource::Cr1); // Set low on compare match with cr1 + out2.enable_rst_event(EventSource::Cr1); + + out1.enable_set_event(EventSource::Period); // Set high at new period + out2.enable_set_event(EventSource::Period); + + out1.enable(); + out2.enable(); + loop { let mut b = [0_u16; 4]; let r = transfer.read_exact(&mut b); diff --git a/examples/hrtim-master.rs b/examples/hrtim-master.rs new file mode 100644 index 00000000..3a0d35c5 --- /dev/null +++ b/examples/hrtim-master.rs @@ -0,0 +1,129 @@ +//This example puts the timer in PWM mode using the specified pin with a frequency of 100Hz and a duty cycle of 50%. +#![no_main] +#![no_std] + +use cortex_m_rt::entry; + +#[cfg(not(any(feature = "stm32g474", feature = "stm32g484")))] +#[entry] +fn main() -> ! { + #[allow(clippy::empty_loop)] + loop {} +} + +use utils::logger::info; + +#[macro_use] +mod utils; + +#[cfg(any(feature = "stm32g474", feature = "stm32g484"))] +#[entry] +fn main() -> ! { + utils::logger::init(); + + use fugit::ExtU32; + use hal::gpio::gpioa::PA8; + use hal::gpio::gpioa::PA9; + use hal::gpio::Alternate; + use hal::gpio::AF13; + use hal::prelude::*; + use hal::pwm::hrtim::EventSource; + use hal::pwm::hrtim::HrCompareRegister; + use hal::pwm::hrtim::HrControltExt; + use hal::pwm::hrtim::HrOutput; + use hal::pwm::hrtim::HrPwmAdvExt; + use hal::pwm::hrtim::HrTimer; + use hal::pwm::hrtim::{Pscl4, MasterPreloadSource}; + use hal::rcc; + use hal::stm32; + use stm32g4xx_hal as hal; + extern crate cortex_m_rt as rt; + + let dp = stm32::Peripherals::take().expect("cannot take peripherals"); + let cp = stm32::CorePeripherals::take().expect("cannot take core"); + // Set system frequency to 16MHz * 15/1/2 = 120MHz + // This would lead to HrTim running at 120MHz * 32 = 3.84... + let mut rcc = dp.RCC.freeze(rcc::Config::pll().pll_cfg(rcc::PllConfig { + mux: rcc::PLLSrc::HSI, + n: rcc::PllNMul::MUL_15, + m: rcc::PllMDiv::DIV_1, + r: Some(rcc::PllRDiv::DIV_2), + + ..Default::default() + })); + + let mut delay = cp.SYST.delay(&rcc.clocks); + + // ...with a prescaler of 4 this gives us a HrTimer with a tick rate of 960MHz + // With max the max period set, this would be 960MHz/2^16 ~= 15kHz... + let prescaler = Pscl4; + + let gpioa = dp.GPIOA.split(&mut rcc); + let pin_a: PA8> = gpioa.pa8.into_alternate(); + let pin_b: PA9> = gpioa.pa9.into_alternate(); + + // . . . . + // . 30% . . . + // ---- . .---- . + //out1 | | . | | . + // | | . | | . + // -------- ---------------------------- -------------------- + // . .---- . .---- + //out2 . | | . | | + // . | | . | | + // ------------------------ ---------------------------- ---- + // . . . . + // . . . . + let (mut fault_control, _) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); + let (mut timer, (mut cr1, _cr2, _cr3, _cr4), (mut out1, mut out2)) = dp + .HRTIM_TIMA + .pwm_advanced((pin_a, pin_b), &mut rcc) + .prescaler(prescaler) + .push_pull_mode(true) // Set push pull mode, out1 and out2 are + // alternated every period with one being + // inactive and the other getting to output its wave form + // as normal + .finalize(&mut fault_control); + + let (mut mtimer, (mut mcr1, cr2, cr3, cr4)) = dp + .HRTIM_MASTER + .pwm_advanced((), &mut rcc) + .prescaler(prescaler) + .preload(MasterPreloadSource::OnMasterRepetitionUpdate) + .period(0xFFFF) + .finalize(&mut fault_control); + + out1.enable_rst_event(EventSource::MasterCr1); // Set low on compare match with cr1 + out2.enable_rst_event(EventSource::MasterCr1); + + out1.enable_set_event(EventSource::Period); // Set high at new period + out2.enable_set_event(EventSource::Period); + + out1.enable(); + out2.enable(); + + let tima = unsafe { &*stm32g4xx_hal::stm32::HRTIM_TIMA::ptr() }; + info!("set1r: {}", tima.seta1r.read().bits()); + info!("set2r: {}", tima.seta2r.read().bits()); + + info!("rst1r: {}", tima.rsta1r.read().bits()); + info!("rst2r: {}", tima.rsta2r.read().bits()); + + info!("Running"); + + loop { + // Step frequency from 18kHz to about 180kHz(half of that when only looking at one pin) + for i in 1..10 { + let new_period = u16::MAX / i; + + mcr1.set_duty(new_period / 3); + //cr1.set_duty(new_period / 3); + mtimer.set_period(new_period); + //timer.set_period(new_period); + + info!("period: {}, duty: {}, get_duty: {}, get_period: {}", new_period, new_period / 3, mcr1.get_duty(), mtimer.get_period()); + + delay.delay(5000_u32.millis()); + } + } +} diff --git a/examples/hrtim.rs b/examples/hrtim.rs index 57e1e161..58cb0f8b 100644 --- a/examples/hrtim.rs +++ b/examples/hrtim.rs @@ -50,8 +50,8 @@ fn main() -> ! { let mut delay = cp.SYST.delay(&rcc.clocks); - // ...with a prescaler of 4 this gives us a HrTimer with a tick rate of 1.2GHz - // With max the max period set, this would be 1.2GHz/2^16 ~= 18kHz... + // ...with a prescaler of 4 this gives us a HrTimer with a tick rate of 960MHz + // With max the max period set, this would be 960MHz/2^16 ~= 15kHz... let prescaler = Pscl4; let gpioa = dp.GPIOA.split(&mut rcc); diff --git a/examples/hrtim_flt_comp.rs b/examples/hrtim_flt_comp.rs index 816dd8ef..ece2cbeb 100644 --- a/examples/hrtim_flt_comp.rs +++ b/examples/hrtim_flt_comp.rs @@ -5,7 +5,7 @@ use cortex_m_rt::entry; use fugit::ExtU32; use hal::comparator::{ComparatorExt, ComparatorSplit, Config, Hysteresis, RefintInput}; -use hal::dac::{Dac1IntSig1, DacExt, DacOut}; +use hal::dac::{Dac3IntSig1, DacExt, DacOut}; use hal::gpio::gpioa::PA8; use hal::gpio::Alternate; use hal::gpio::AF13; @@ -28,36 +28,47 @@ use panic_probe as _; #[entry] fn main() -> ! { + use stm32g4xx_hal::adc::AdcClaim; + let dp = stm32::Peripherals::take().expect("cannot take peripherals"); let cp = stm32::CorePeripherals::take().expect("cannot take core"); - // Set system frequency to 16MHz * 75/4/2 = 150MHz - // This would lead to HrTim running at 150MHz * 32 = 4.8GHz... + // Set system frequency to 16MHz * 15/1/2 = 120MHz + // This would lead to HrTim running at 120MHz * 32 = 3.84GHz... let mut rcc = dp.RCC.freeze(rcc::Config::pll().pll_cfg(rcc::PllConfig { mux: rcc::PLLSrc::HSI, - n: rcc::PllNMul::MUL_75, - m: rcc::PllMDiv::DIV_4, + n: rcc::PllNMul::MUL_15, + m: rcc::PllMDiv::DIV_1, r: Some(rcc::PllRDiv::DIV_2), ..Default::default() })); let mut delay = cp.SYST.delay(&rcc.clocks); + let mut adc1 = dp.ADC1.claim_and_configure( + hal::adc::ClockSource::SystemClock, + &rcc, + hal::adc::config::AdcConfig::default().clock_mode(hal::adc::config::ClockMode::Synchronous_Div_4), + &mut delay, + false, + ); + let gpioa = dp.GPIOA.split(&mut rcc); + let gpioc = dp.GPIOC.split(&mut rcc); - let dac1ch1 = dp.DAC1.constrain(Dac1IntSig1, &mut rcc); - let mut dac = dac1ch1.calibrate_buffer(&mut delay).enable(); + let dac3ch1 = dp.DAC3.constrain(Dac3IntSig1, &mut rcc); + let mut dac = dac3ch1.enable(); // Use dac to define the fault threshold // 2^12 / 2 = 2^11 for about half of VCC - let fault_limit = 1 << 11; + let fault_limit = 60; dac.set_value(fault_limit); - let (comp1, ..) = dp.COMP.split(&mut rcc); + let (_comp1, _comp2, comp3, ..) = dp.COMP.split(&mut rcc); - let pa1 = gpioa.pa1.into_analog(); - let comp1 = comp1 + let pc1 = gpioc.pc1.into_analog(); + let comp3 = comp3 .comparator( - &pa1, + &pc1, &dac, Config::default() .hysteresis(Hysteresis::None) @@ -69,10 +80,10 @@ fn main() -> ! { let (mut fault_control, flt_inputs) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); - let fault_source4 = flt_inputs - .fault_input4 - .bind_comp(&comp1) - .polarity(hal::pwm::Polarity::ActiveLow) + let fault_source5 = flt_inputs + .fault_input5 + .bind_comp(&comp3) + .polarity(hal::pwm::Polarity::ActiveHigh) .finalize(&mut fault_control); // ...with a prescaler of 4 this gives us a HrTimer with a tick rate of 1.2GHz @@ -100,7 +111,7 @@ fn main() -> ! { .pwm_advanced(pin_a, &mut rcc) .prescaler(prescaler) .period(0xFFFF) - .with_fault_source(fault_source4) // Set fault source + .with_fault_source(fault_source5) // Set fault source .fault_action1(FaultAction::ForceInactive) .fault_action2(FaultAction::ForceInactive) .finalize(&mut fault_control); @@ -115,16 +126,17 @@ fn main() -> ! { loop { for _ in 0..5 { - delay.delay(500_u32.millis()); + //delay.delay(500_u32.millis()); defmt::info!( - "State: {}, comp: {}, is_fault_active: {}", + "State: {}, comp: {}, is_fault_active: {}, pc1: {}", out1.get_state(), - comp1.output(), - fault_control.fault_4.is_fault_active() + comp3.output(), + fault_control.fault_5.is_fault_active(), + adc1.convert(&pc1, hal::adc::config::SampleTime::Cycles_92_5) ); } - if fault_control.fault_4.is_fault_active() { - fault_control.fault_4.clear_fault(); // Clear fault every 5s + if fault_control.fault_5.is_fault_active() { + fault_control.fault_5.clear_fault(); // Clear fault every 5s out1.enable(); defmt::info!("failt cleared, and output reenabled"); } diff --git a/src/pwm/hrtim.rs b/src/pwm/hrtim.rs index fe0cb66a..bff6ff08 100644 --- a/src/pwm/hrtim.rs +++ b/src/pwm/hrtim.rs @@ -64,6 +64,14 @@ pins! { HRTIM_TIMF: CH1: PC6>, CH2: PC7> } +impl Pins for () { + type Channel = (); +} + +impl ToHrOut for () { + type Out = (); +} + // automatically implement Pins trait for tuples of individual pins macro_rules! pins_tuples { // Tuple of two pins @@ -87,10 +95,12 @@ pins_tuples! { (CH2, CH1) } +impl HrtimChannel for () {} + /*pub struct Hrtimer { _prescaler: PhantomData, _timer: PhantomData, - period: u16, // $perXr.perx + period: u16, // $perXr.$perx cmp_value1: u16, // $cmpX1r.cmp1x cmp_value2: u16, // $cmpX2r.cmp2x @@ -116,25 +126,27 @@ pub trait HrPwmExt: Sized { } pub trait HrPwmAdvExt: Sized { + type PreloadSource; + fn pwm_advanced( self, _pins: PINS, rcc: &mut Rcc, - ) -> HrPwmBuilder + ) -> HrPwmBuilder where PINS: Pins + ToHrOut, CHANNEL: HrtimChannel; } /// HrPwmBuilder is used to configure advanced HrTim PWM features -pub struct HrPwmBuilder { +pub struct HrPwmBuilder { _tim: PhantomData, _prescaler: PhantomData, _out: PhantomData, alignment: Alignment, base_freq: HertzU64, count: CountSettings, - preload_source: Option, + preload_source: Option, fault_enable_bits: u8, fault1_bits: u8, fault2_bits: u8, @@ -147,6 +159,11 @@ pub enum PreloadSource { OnCounterReset, } +pub enum MasterPreloadSource { + /// Prealoaded registers are updaten when the master counter rolls over and the master repetition counter is 0 + OnMasterRepetitionUpdate, +} + pub trait HrCompareRegister { fn get_duty(&self) -> u16; fn set_duty(&mut self, duty: u16); @@ -224,8 +241,9 @@ pub enum EventSource { /// Compare match with compare register 4 of this timer Cr4, + /// On complete period Period, - /* + /// Compare match with compare register 1 of master timer MasterCr1, @@ -238,7 +256,8 @@ pub enum EventSource { /// Compare match with compare register 4 of master timer MasterCr4, - MasterPeriod,*/ + /// On complete master period + MasterPeriod, // TODO: These are unique for every timer output //Extra(E) } @@ -257,9 +276,174 @@ where pub struct HrOut1(PhantomData); pub struct HrOut2(PhantomData); +macro_rules! hrtim_finalize_body { + ($this:expr, $PreloadSource:ident, $TIMX:ident: ( + $timXcr:ident, $ck_psc:ident, $perXr:ident, $perx:ident, $tXcen:ident $(, $fltXr:ident, $outXr:ident)*), + ) => {{ + let tim = unsafe { &*$TIMX::ptr() }; + let (period, prescaler_bits) = match $this.count { + CountSettings::Period(period) => (period as u32, PSCL::BITS as u16), + CountSettings::Frequency( freq ) => { + >::calculate_frequency($this.base_freq, freq, $this.alignment) + }, + }; + + // Write prescaler and any special modes + tim.$timXcr.modify(|_r, w| unsafe { + w + // Enable Continous mode + .cont().set_bit() + + // TODO: add support for more modes + + // Set prescaler + .$ck_psc().bits(prescaler_bits as u8) + }); + + $( + // Only available for timers with outputs(not HRTIM_MASTER) + let _ = tim.$outXr; + tim.$timXcr.modify(|_r, w| + // Push-Pull mode + w.pshpll().bit($this.enable_push_pull) + ); + )* + + // Write period + tim.$perXr.write(|w| unsafe { w.$perx().bits(period as u16) }); + + // Enable fault sources and lock configuration + + $(unsafe { + // Enable fault sources + let fault_enable_bits = $this.fault_enable_bits as u32; + tim.$fltXr.write(|w| w + .flt1en().bit(fault_enable_bits & (1 << 0) != 0) + .flt2en().bit(fault_enable_bits & (1 << 1) != 0) + .flt3en().bit(fault_enable_bits & (1 << 2) != 0) + .flt4en().bit(fault_enable_bits & (1 << 3) != 0) + .flt5en().bit(fault_enable_bits & (1 << 4) != 0) + .flt6en().bit(fault_enable_bits & (1 << 5) != 0) + ); + + // ... and lock configuration + tim.$fltXr.modify(|_r, w| w.fltlck().set_bit()); + + // Set actions on fault for both outputs + tim.$outXr.modify(|_r, w| w + .fault1().bits($this.fault1_bits) + .fault2().bits($this.fault2_bits) + ); + })* + + + hrtim_finalize_body!($PreloadSource, $this, tim, $timXcr); + + // Start timer + let master = unsafe { &*HRTIM_MASTER::ptr() }; + master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); + + unsafe { + MaybeUninit::uninit().assume_init() + } + }}; + + (PreloadSource, $this:expr, $tim:expr, $timXcr:ident) => {{ + match $this.preload_source { + Some(PreloadSource::OnCounterReset) => { + $tim.$timXcr.modify(|_r, w| w + .tx_rstu().set_bit() + .preen().set_bit() + ) + }, + None => () + } + }}; + + (MasterPreloadSource, $this:expr, $tim:expr, $timXcr:ident) => {{ + match $this.preload_source { + Some(MasterPreloadSource::OnMasterRepetitionUpdate) => { + $tim.$timXcr.modify(|_r, w| w + .mrepu().set_bit() + .preen().set_bit() + ) + } + None => () + } + }}; +} + +macro_rules! hrtim_common_methods { + ($TIMX:ident, $PS:ident) => { + /// Set the PWM frequency; will overwrite the previous prescaler and period + /// The requested frequency will be rounded to the nearest achievable frequency; the actual frequency may be higher or lower than requested. + pub fn frequency>(mut self, freq: T) -> Self { + self.count = CountSettings::Frequency(freq.into()); + + self + } + + /// Set the prescaler; PWM count runs at base_frequency/(prescaler+1) + pub fn prescaler

(self, _prescaler: P) -> HrPwmBuilder<$TIMX, P, $PS, OUT> + where + P: HrtimPrescaler, + { + let HrPwmBuilder { + _tim, + _prescaler: _, + _out, + fault_enable_bits, + fault1_bits, + fault2_bits, + enable_push_pull, + alignment, + base_freq, + count, + preload_source, + } = self; + + let period = match count { + CountSettings::Frequency(_) => u16::MAX, + CountSettings::Period(period) => period, + }; + + let count = CountSettings::Period(period); + + HrPwmBuilder { + _tim, + _prescaler: PhantomData, + _out, + fault_enable_bits, + fault1_bits, + fault2_bits, + enable_push_pull, + alignment, + base_freq, + count, + preload_source, + //deadtime: 0.nanos(), + } + } + + // 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 + } + }; +} + // Implement PWM configuration for timer macro_rules! hrtim_hal { - ($($TIMX:ident: ($timX:ident, $timXcr:ident, $perXr:ident, $tXcen:ident, $fltXr:ident, $outXr:ident),)+) => { + ($($TIMX:ident: ($timXcr:ident, $perXr:ident, $tXcen:ident, $fltXr:ident, $outXr:ident),)+) => { $( // Implement HrPwmExt trait for hrtimer @@ -283,11 +467,13 @@ macro_rules! hrtim_hal { } impl HrPwmAdvExt for $TIMX { + type PreloadSource = PreloadSource; + fn pwm_advanced( self, _pins: PINS, rcc: &mut Rcc, - ) -> HrPwmBuilder + ) -> HrPwmBuilder where PINS: Pins + ToHrOut, CHANNEL: HrtimChannel @@ -315,136 +501,15 @@ macro_rules! hrtim_hal { } impl - HrPwmBuilder<$TIMX, PSCL, OUT> + HrPwmBuilder<$TIMX, PSCL, PreloadSource, OUT> where PSCL: HrtimPrescaler, { pub fn finalize(self, _control: &mut HrPwmControl) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX>, HrCr2<$TIMX>, HrCr3<$TIMX>, HrCr4<$TIMX>), OUT) { - let tim = unsafe { &*$TIMX::ptr() }; - - let (period, prescaler_bits) = match self.count { - CountSettings::Period(period) => (period as u32, PSCL::BITS as u16), - CountSettings::Frequency( freq ) => { - >::calculate_frequency(self.base_freq, freq, self.alignment) - }, - }; - - // Write prescaler and any special modes - tim.$timXcr.write(|w| unsafe { - w - // Enable Continous mode - .cont().set_bit() - - // Push-Pull mode - .pshpll().bit(self.enable_push_pull) - - // TODO: add support for more modes - - // Set prescaler - .ck_pscx().bits(prescaler_bits as u8) - }); - - // Write period - tim.$perXr.write(|w| unsafe { w.perx().bits(period as u16) }); - - // Enable fault sources and lock configuration - unsafe { - // Enable fault sources - let fault_enable_bits = self.fault_enable_bits as u32; - tim.$fltXr.write(|w| w - .flt1en().bit(fault_enable_bits & (1 << 0) != 0) - .flt2en().bit(fault_enable_bits & (1 << 1) != 0) - .flt3en().bit(fault_enable_bits & (1 << 2) != 0) - .flt4en().bit(fault_enable_bits & (1 << 3) != 0) - .flt5en().bit(fault_enable_bits & (1 << 4) != 0) - .flt6en().bit(fault_enable_bits & (1 << 5) != 0) - ); - - // ... and lock configuration - tim.$fltXr.modify(|_r, w| w.fltlck().set_bit()); - - // Set actions on fault for both outputs - tim.$outXr.modify(|_r, w| w - .fault1().bits(self.fault1_bits) - .fault2().bits(self.fault2_bits) - ); - - match self.preload_source { - Some(PreloadSource::OnCounterReset) => { - tim.$timXcr.modify(|_r, w| w - .tx_rstu().set_bit() - .preen().set_bit() - ) - }, - None => () - } - } - - // Start timer - let master = unsafe { &*HRTIM_MASTER::ptr() }; - master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); - - unsafe { - MaybeUninit::uninit().assume_init() - } - } - - /// Set the PWM frequency; will overwrite the previous prescaler and period - /// The requested frequency will be rounded to the nearest achievable frequency; the actual frequency may be higher or lower than requested. - pub fn frequency>(mut self, freq: T) -> Self { - self.count = CountSettings::Frequency( freq.into() ); - - self + hrtim_finalize_body!(self, PreloadSource, $TIMX: ($timXcr, ck_pscx, $perXr, perx, $tXcen, $fltXr, $outXr),) } - /// Set the prescaler; PWM count runs at base_frequency/(prescaler+1) - pub fn prescaler

(self, _prescaler: P) -> HrPwmBuilder<$TIMX, P, OUT> - where - P: HrtimPrescaler, - { - let HrPwmBuilder { - _tim, - _prescaler: _, - _out, - fault_enable_bits, - fault1_bits, - fault2_bits, - enable_push_pull, - alignment, - base_freq, - count, - preload_source, - } = self; - - let period = match count { - CountSettings::Frequency(_) => u16::MAX, - CountSettings::Period(period) => period, - }; - - let count = CountSettings::Period(period); - - HrPwmBuilder { - _tim, - _prescaler: PhantomData, - _out, - fault_enable_bits, - fault1_bits, - fault2_bits, - enable_push_pull, - alignment, - base_freq, - count, - preload_source, - //deadtime: 0.nanos(), - } - } - - // TODO: Allow setting multiple? - pub fn preload(mut self, preload_source: PreloadSource) -> Self { - self.preload_source = Some(preload_source); - - self - } + hrtim_common_methods!($TIMX, PreloadSource); pub fn with_fault_source(mut self, _fault_source: FS) -> Self where FS: FaultSource @@ -466,13 +531,6 @@ macro_rules! hrtim_hal { 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 - } - /// Enable or disable Push-Pull mode /// /// Enabling Push-Pull mode will make output 1 and 2 @@ -503,12 +561,62 @@ macro_rules! hrtim_hal { //pub fn swap_mode(mut self, enable: bool) -> Self } )+ - } + }; +} + +macro_rules! hrtim_hal_master { + ($($TIMX:ident: ($timXcr:ident, $ck_psc:ident, $perXr:ident, $perx:ident, $tXcen:ident),)+) => {$( + impl HrPwmAdvExt for $TIMX { + type PreloadSource = MasterPreloadSource; + + fn pwm_advanced( + self, + _pins: PINS, + rcc: &mut Rcc, + ) -> HrPwmBuilder + where + PINS: /*Pins +*/ ToHrOut, + CHANNEL: HrtimChannel + { + // 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, + _out: PhantomData, + fault_enable_bits: 0b000000, + fault1_bits: 0b00, + fault2_bits: 0b00, + alignment: Alignment::Left, + base_freq: clk, + count: CountSettings::Period(u16::MAX), + preload_source: None, + enable_push_pull: false, + //deadtime: 0.nanos(), + } + } + } + + impl + HrPwmBuilder<$TIMX, PSCL, MasterPreloadSource, OUT> + where + PSCL: HrtimPrescaler, + { + pub fn finalize(self, _control: &mut HrPwmControl) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX>, HrCr2<$TIMX>, HrCr3<$TIMX>, HrCr4<$TIMX>)) { + hrtim_finalize_body!(self, MasterPreloadSource, $TIMX: ($timXcr, $ck_psc, $perXr, $perx, $tXcen),) + } + + hrtim_common_methods!($TIMX, MasterPreloadSource); + } + )*} } macro_rules! hrtim_pin_hal { ($($TIMX:ident: - ($CH:ident, $perXr:ident, $cmpXYr:ident, $cmpYx:ident, $cmpY:ident, $tXYoen:ident, $tXYodis:ident, $setXYr:ident, $rstXYr:ident),)+ + ($CH:ident, $perXr:ident, $cmpXYr:ident, $cmpYx:ident, $cmpY:ident, $tXYoen:ident, $tXYodis:ident),)+ ) => { $( impl hal::PwmPin for Pwm<$TIMX, $CH, COMP, POL, NPOL> @@ -549,6 +657,21 @@ macro_rules! hrtim_pin_hal { } } + /// Set duty cycle + /// + /// NOTE: Please observe limits: + /// | Prescaler | Min duty | Max duty | + /// |-----------|----------|----------| + /// | 1 | 0x0060 | 0xFFDF | + /// | 2 | 0x0030 | 0xFFEF | + /// | 4 | 0x0018 | 0xFFF7 | + /// | 8 | 0x000C | 0xFFFB | + /// | 16 | 0x0006 | 0xFFFD | + /// | 32 | 0x0003 | 0xFFFD | + /// | 64 | 0x0003 | 0xFFFD | + /// | 128 | 0x0003 | 0xFFFD | + /// + /// Also, writing 0 as duty is only valid for CR1 and CR3 fn set_duty(&mut self, duty: Self::Duty) { let tim = unsafe { &*$TIMX::ptr() }; @@ -559,13 +682,6 @@ macro_rules! hrtim_pin_hal { // Enable implementation for ComplementaryImpossible impl PwmPinEnable for Pwm<$TIMX, $CH, ComplementaryImpossible, POL, NPOL> { fn ccer_enable(&mut self) { - let tim = unsafe { &*$TIMX::ptr() }; - // Select period as a SET-event - tim.$setXYr.write(|w| { w.per().set_bit() } ); - - // Select cmpY as a RESET-event - tim.$rstXYr.write(|w| { w.$cmpY().set_bit() } ); - // TODO: Should this part only be in Pwm::enable? // Enable output Y on channel X // This is a set-only register, no risk for data race @@ -573,10 +689,6 @@ macro_rules! hrtim_pin_hal { common.oenr.write(|w| { w.$tXYoen().set_bit() }); } fn ccer_disable(&mut self) { - let tim = unsafe { &*$TIMX::ptr() }; - // Clear SET-events - tim.$setXYr.reset(); - // TODO: Should this part only be in Pwm::disable // Disable output Y on channel X // This is a write only register, no risk for data race @@ -598,6 +710,12 @@ macro_rules! hrtim_out_common { EventSource::Cr3 => tim.$register.modify(|_r, w| w.cmp3().$action()), EventSource::Cr4 => tim.$register.modify(|_r, w| w.cmp4().$action()), EventSource::Period => tim.$register.modify(|_r, w| w.per().$action()), + + EventSource::MasterCr1 => tim.$register.modify(|_r, w| w.mstcmp1().$action()), + EventSource::MasterCr2 => tim.$register.modify(|_r, w| w.mstcmp2().$action()), + EventSource::MasterCr3 => tim.$register.modify(|_r, w| w.mstcmp3().$action()), + EventSource::MasterCr4 => tim.$register.modify(|_r, w| w.mstcmp4().$action()), + EventSource::MasterPeriod => tim.$register.modify(|_r, w| w.mstper().$action()), } }}; } @@ -651,7 +769,7 @@ macro_rules! hrtim_out { hrtim_out! { HRTIM_TIMA: HrOut1: ta1oen, ta1odis, ta1ods, seta1r, rsta1r, - HRTIM_TIMA: HrOut2: ta2oen, ta1odis, ta2ods, seta2r, rsta2r, + HRTIM_TIMA: HrOut2: ta2oen, ta2odis, ta2ods, seta2r, rsta2r, HRTIM_TIMB: HrOut1: tb1oen, tb1odis, tb1ods, setb1r, rstb1r, HRTIM_TIMB: HrOut2: tb2oen, tb2odis, tb2ods, setb2r, rstb2r, @@ -687,105 +805,124 @@ macro_rules! hrtim_cr_helper { } macro_rules! hrtim_cr { - ($($TIMX:ident: [$cmpX1r:ident, $cmpX2r:ident, $cmpX3r:ident, $cmpX4r:ident],)+) => {$( - hrtim_cr_helper!($TIMX: HrCr1: $cmpX1r, cmp1x); - hrtim_cr_helper!($TIMX: HrCr2: $cmpX2r, cmp2x); - hrtim_cr_helper!($TIMX: HrCr3: $cmpX3r, cmp3x); - hrtim_cr_helper!($TIMX: HrCr4: $cmpX4r, cmp4x); + ($($TIMX:ident: [ + $cmpX1r:ident, $cmpX2r:ident, $cmpX3r:ident, $cmpX4r:ident, + $cmp1x:ident, $cmp2x:ident, $cmp3x:ident, $cmp4x:ident + ],)+) => {$( + hrtim_cr_helper!($TIMX: HrCr1: $cmpX1r, $cmp1x); + hrtim_cr_helper!($TIMX: HrCr2: $cmpX2r, $cmp2x); + hrtim_cr_helper!($TIMX: HrCr3: $cmpX3r, $cmp3x); + hrtim_cr_helper!($TIMX: HrCr4: $cmpX4r, $cmp4x); )+}; } macro_rules! hrtim_timer { - ($($TIMX:ident: $perXr:ident,)+) => {$( + ($($TIMX:ident: $perXr:ident, $perx:ident,)+) => {$( impl HrTimer<$TIMX, PSCL> for HrTim<$TIMX, PSCL> { fn get_period(&self) -> u16 { let tim = unsafe { &*$TIMX::ptr() }; - tim.$perXr.read().perx().bits() + tim.$perXr.read().$perx().bits() } fn set_period(&mut self, period: u16) { let tim = unsafe { &*$TIMX::ptr() }; - tim.$perXr.write(|w| unsafe { w.perx().bits(period as u16) }); + tim.$perXr.write(|w| unsafe { w.$perx().bits(period as u16) }); } } )+}; } hrtim_timer! { - HRTIM_TIMA: perar, - HRTIM_TIMB: perbr, - HRTIM_TIMC: percr, - HRTIM_TIMD: perdr, - HRTIM_TIME: perer, - HRTIM_TIMF: perfr, + HRTIM_MASTER: mper, mper, + + HRTIM_TIMA: perar, perx, + HRTIM_TIMB: perbr, perx, + HRTIM_TIMC: percr, perx, + HRTIM_TIMD: perdr, perx, + HRTIM_TIME: perer, perx, + HRTIM_TIMF: perfr, perx, } hrtim_cr! { - HRTIM_TIMA: [cmp1ar, cmp2ar, cmp3ar, cmp4ar], - HRTIM_TIMB: [cmp1br, cmp2br, cmp3br, cmp4br], - HRTIM_TIMC: [cmp1cr, cmp2cr, cmp3cr, cmp4cr], - HRTIM_TIMD: [cmp1dr, cmp2dr, cmp3dr, cmp4dr], - HRTIM_TIME: [cmp1er, cmp2er, cmp3er, cmp4er], - HRTIM_TIMF: [cmp1fr, cmp2fr, cmp3fr, cmp4fr], + HRTIM_MASTER: [mcmp1r, mcmp2r, mcmp3r, mcmp4r, mcmp1, mcmp2, mcmp3, mcmp4], + + HRTIM_TIMA: [cmp1ar, cmp2ar, cmp3ar, cmp4ar, cmp1x, cmp2x, cmp3x, cmp4x], + HRTIM_TIMB: [cmp1br, cmp2br, cmp3br, cmp4br, cmp1x, cmp2x, cmp3x, cmp4x], + HRTIM_TIMC: [cmp1cr, cmp2cr, cmp3cr, cmp4cr, cmp1x, cmp2x, cmp3x, cmp4x], + HRTIM_TIMD: [cmp1dr, cmp2dr, cmp3dr, cmp4dr, cmp1x, cmp2x, cmp3x, cmp4x], + HRTIM_TIME: [cmp1er, cmp2er, cmp3er, cmp4er, cmp1x, cmp2x, cmp3x, cmp4x], + HRTIM_TIMF: [cmp1fr, cmp2fr, cmp3fr, cmp4fr, cmp1x, cmp2x, cmp3x, cmp4x], } hrtim_hal! { - // TODO: HRTIM_MASTER - HRTIM_TIMA: (hrtim_tima, timacr, perar, tacen, fltar, outar), - HRTIM_TIMB: (hrtim_timb, timbcr, perbr, tbcen, fltbr, outbr), - HRTIM_TIMC: (hrtim_timc, timccr, percr, tccen, fltcr, outcr), - HRTIM_TIMD: (hrtim_timd, timdcr, perdr, tdcen, fltdr, outdr), - HRTIM_TIME: (hrtim_time, timecr, perer, tecen, flter, outer), - HRTIM_TIMF: (hrtim_timf, timfcr, perfr, tfcen, fltfr, outfr), + HRTIM_TIMA: (timacr, perar, tacen, fltar, outar), + HRTIM_TIMB: (timbcr, perbr, tbcen, fltbr, outbr), + HRTIM_TIMC: (timccr, percr, tccen, fltcr, outcr), + HRTIM_TIMD: (timdcr, perdr, tdcen, fltdr, outdr), + HRTIM_TIME: (timecr, perer, tecen, flter, outer), + HRTIM_TIMF: (timfcr, perfr, tfcen, fltfr, outfr), } -hrtim_pin_hal! { - HRTIM_TIMA: (CH1, perar, cmp1ar, cmp1x, cmp1, ta1oen, ta1odis, seta1r, rsta1r), - HRTIM_TIMA: (CH2, perar, cmp3ar, cmp3x, cmp3, ta2oen, ta2odis, seta2r, rsta2r), +hrtim_hal_master! { + HRTIM_MASTER: (mcr, ck_psc, mper, mper, mcen), +} - HRTIM_TIMB: (CH1, perbr, cmp1br, cmp1x, cmp1, tb1oen, tb1odis, setb1r, rstb1r), - HRTIM_TIMB: (CH2, perbr, cmp3br, cmp3x, cmp3, tb2oen, tb2odis, setb2r, rstb2r), +hrtim_pin_hal! { + HRTIM_TIMA: (CH1, perar, cmp1ar, cmp1x, cmp1, ta1oen, ta1odis), + HRTIM_TIMA: (CH2, perar, cmp3ar, cmp3x, cmp3, ta2oen, ta2odis), - HRTIM_TIMC: (CH1, percr, cmp1cr, cmp1x, cmp1, tc1oen, tc1odis, setc1r, rstc1r), - HRTIM_TIMC: (CH2, percr, cmp3cr, cmp3x, cmp3, tc2oen, tc2odis, setc2r, rstc2r), + HRTIM_TIMB: (CH1, perbr, cmp1br, cmp1x, cmp1, tb1oen, tb1odis), + HRTIM_TIMB: (CH2, perbr, cmp3br, cmp3x, cmp3, tb2oen, tb2odis), + HRTIM_TIMC: (CH1, percr, cmp1cr, cmp1x, cmp1, tc1oen, tc1odis), + HRTIM_TIMC: (CH2, percr, cmp3cr, cmp3x, cmp3, tc2oen, tc2odis), - HRTIM_TIMD: (CH1, perdr, cmp1dr, cmp1x, cmp1, td1oen, td1odis, setd1r, rstd1r), - HRTIM_TIMD: (CH2, perdr, cmp3dr, cmp3x, cmp3, td2oen, td2odis, setd2r, rstd2r), + HRTIM_TIMD: (CH1, perdr, cmp1dr, cmp1x, cmp1, td1oen, td1odis), + HRTIM_TIMD: (CH2, perdr, cmp3dr, cmp3x, cmp3, td2oen, td2odis), - HRTIM_TIME: (CH1, perer, cmp1er, cmp1x, cmp1, te1oen, te1odis, sete1r, rste1r), - HRTIM_TIME: (CH2, perer, cmp3er, cmp3x, cmp3, te2oen, te2odis, sete2r, rste2r), + HRTIM_TIME: (CH1, perer, cmp1er, cmp1x, cmp1, te1oen, te1odis), + HRTIM_TIME: (CH2, perer, cmp3er, cmp3x, cmp3, te2oen, te2odis), - HRTIM_TIMF: (CH1, perfr, cmp1fr, cmp1x, cmp1, tf1oen, tf1odis, setf1r, rstf1r), - HRTIM_TIMF: (CH2, perfr, cmp3fr, cmp3x, cmp3, tf2oen, tf2odis, setf2r, rstf2r), + HRTIM_TIMF: (CH1, perfr, cmp1fr, cmp1x, cmp1, tf1oen, tf1odis), + HRTIM_TIMF: (CH2, perfr, cmp3fr, cmp3x, cmp3, tf2oen, tf2odis), } pub trait HrtimPrescaler { const BITS: u8; const VALUE: u8; + + /// Minimum allowed value for compare registers used with the timer with this prescaler + /// + /// NOTE: That for CR1 and CR3, 0 is also allowed + const MIN_CR: u16; + + /// Maximum allowed value for compare registers used with the timer with this prescaler + const MAX_CR: u16; } macro_rules! impl_pscl { - ($($t:ident => $b:literal, $c:literal,)+) => {$( - #[derive(Copy, Clone)] + ($($t:ident => $b:literal, $v:literal, $min:literal, $max:literal)+) => {$( + #[derive(Copy, Clone, Default)] pub struct $t; impl HrtimPrescaler for $t { const BITS: u8 = $b; - const VALUE: u8 = $c; + const VALUE: u8 = $v; + const MIN_CR: u16 = $min; + const MAX_CR: u16 = $max; } )+}; } impl_pscl! { - Pscl1 => 0b000, 1, - Pscl2 => 0b001, 2, - Pscl4 => 0b010, 4, - Pscl8 => 0b011, 8, - Pscl16 => 0b100, 16, - Pscl32 => 0b101, 32, - Pscl64 => 0b110, 64, - Pscl128 => 0b111, 128, + Pscl1 => 0b000, 1, 0x0060, 0xFFDF + Pscl2 => 0b001, 2, 0x0030, 0xFFEF + Pscl4 => 0b010, 4, 0x0018, 0xFFF7 + Pscl8 => 0b011, 8, 0x000C, 0xFFFB + Pscl16 => 0b100, 16, 0x0006, 0xFFFD + Pscl32 => 0b101, 32, 0x0003, 0xFFFD + Pscl64 => 0b110, 64, 0x0003, 0xFFFD + Pscl128 => 0b111, 128, 0x0003, 0xFFFD } /// HrTim timer @@ -836,7 +973,11 @@ pub trait FaultSource: Copy { pub struct SourceBuilder { _input: I, src_bits: u8, + + /// FLTxP is_active_high: bool, + + /// FLTxF[3:0] filter_bits: u8, } @@ -922,8 +1063,12 @@ macro_rules! impl_faults { } // TODO: add more settings - /* pub fn filter(?) -> Self */ /* pub fn blanking(?) -> Self */ + + pub fn filter(mut self, filter: FaultSamplingFilter) -> Self { + self.filter_bits = filter as u8; + self + } } impl FaultSource for $source { @@ -968,25 +1113,83 @@ pub struct HrPwmControl { pub enum FaultSamplingClkDiv { /// No division /// - /// fault signal sampling clock = f_hrtim + /// fault signal sampling clock f_flts = f_hrtim None = 0b00, /// 1/2 /// - /// fault signal sampling clock = f_hrtim / 2 + /// fault signal sampling clock f_flts = f_hrtim / 2 Two = 0b01, /// 1/4 /// - /// fault signal sampling clock = f_hrtim / 4 + /// fault signal sampling clock f_flts = f_hrtim / 4 Four = 0b10, /// 1/8 /// - /// fault signal sampling clock = f_hrtim / 8 + /// fault signal sampling clock f_flts = f_hrtim / 8 Eight = 0b11, } +pub enum FaultSamplingFilter { + /// No filtering, fault acts asynchronously + /// + /// Note that this bypasses any f_flts (FaultSamplingClkDiv) + None = 0b0000, + + /// Sample directly at rate f_hrtim, with a count of 2 + /// + /// Note that this bypasses: any f_flts (FaultSamplingClkDiv) + HrtimN2 = 0b0001, + + /// Sample directly at rate f_hrtim, with a count of 4 + /// + /// Note that this bypasses any f_flts (FaultSamplingClkDiv) + HrtimN4 = 0b0010, + + /// Sample directly at rate f_hrtim, with a count of 8 + /// + /// Note that this bypasses any f_flts (FaultSamplingClkDiv) + HrtimN8 = 0b0011, + + /// Sample at rate f_flts / 2, with a count of 6 + FltsDiv2N6 = 0b0100, + + /// Sample at rate f_flts / 2, with a count of 8 + FltsDiv2N8 = 0b0101, + + /// Sample at rate f_flts / 4, with a count of 6 + FltsDiv4N6 = 0b0110, + + /// Sample at rate f_flts / 4, with a count of 8 + FltsDiv4N8 = 0b0111, + + /// Sample at rate f_flts / 8, with a count of 6 + FltsDiv8N6 = 0b1000, + + /// Sample at rate f_flts / 8, with a count of 8 + FltsDiv8N8 = 0b1001, + + /// Sample at rate f_flts / 16, with a count of 5 + FltsDiv16N5 = 0b1010, + + /// Sample at rate f_flts / 16, with a count of 6 + FltsDiv16N6 = 0b1011, + + /// Sample at rate f_flts / 16, with a count of 8 + FltsDiv16N8 = 0b1100, + + /// Sample at rate f_flts / 32, with a count of 5 + FltsDiv32N5 = 0b1101, + + /// Sample at rate f_flts / 32, with a count of 6 + FltsDiv32N6 = 0b1110, + + /// Sample at rate f_flts / 32, with a count of 8 + FltsDiv32N8 = 0b1111, +} + pub trait HrControltExt { fn hr_control(self, _rcc: &mut Rcc) -> HrTimOngoingCalibration; } @@ -1013,11 +1216,25 @@ impl HrControltExt for HRTIM_COMMON { adc_trigger3_bits: 0, adc_trigger4_bits: 0, + adc_trigger5_bits: 0, + adc_trigger6_bits: 0, + adc_trigger7_bits: 0, + adc_trigger8_bits: 0, + adc_trigger9_bits: 0, + adc_trigger10_bits: 0, + adc_trigger1_postscaler: AdcTriggerPostscaler::None, adc_trigger2_postscaler: AdcTriggerPostscaler::None, adc_trigger3_postscaler: AdcTriggerPostscaler::None, adc_trigger4_postscaler: AdcTriggerPostscaler::None, + adc_trigger5_postscaler: AdcTriggerPostscaler::None, + adc_trigger6_postscaler: AdcTriggerPostscaler::None, + adc_trigger7_postscaler: AdcTriggerPostscaler::None, + adc_trigger8_postscaler: AdcTriggerPostscaler::None, + adc_trigger9_postscaler: AdcTriggerPostscaler::None, + adc_trigger10_postscaler: AdcTriggerPostscaler::None, + divider: FaultSamplingClkDiv::None, } } @@ -1029,11 +1246,25 @@ pub struct HrTimOngoingCalibration { adc_trigger3_bits: u32, adc_trigger4_bits: u32, + adc_trigger5_bits: u8, + adc_trigger6_bits: u8, + adc_trigger7_bits: u8, + adc_trigger8_bits: u8, + adc_trigger9_bits: u8, + adc_trigger10_bits: u8, + adc_trigger1_postscaler: AdcTriggerPostscaler, adc_trigger2_postscaler: AdcTriggerPostscaler, adc_trigger3_postscaler: AdcTriggerPostscaler, adc_trigger4_postscaler: AdcTriggerPostscaler, + adc_trigger5_postscaler: AdcTriggerPostscaler, + adc_trigger6_postscaler: AdcTriggerPostscaler, + adc_trigger7_postscaler: AdcTriggerPostscaler, + adc_trigger8_postscaler: AdcTriggerPostscaler, + adc_trigger9_postscaler: AdcTriggerPostscaler, + adc_trigger10_postscaler: AdcTriggerPostscaler, + divider: FaultSamplingClkDiv, } @@ -1051,11 +1282,25 @@ impl HrTimOngoingCalibration { adc_trigger3_bits: ad3_bits, adc_trigger4_bits: ad4_bits, - adc_trigger1_postscaler, - adc_trigger2_postscaler, + adc_trigger5_bits: ad5_bits, + adc_trigger6_bits: ad6_bits, + adc_trigger7_bits: ad7_bits, + adc_trigger8_bits: ad8_bits, + adc_trigger9_bits: ad9_bits, + adc_trigger10_bits: ad10_bits, + + adc_trigger1_postscaler, + adc_trigger2_postscaler, adc_trigger3_postscaler, adc_trigger4_postscaler, + adc_trigger5_postscaler, + adc_trigger6_postscaler, + adc_trigger7_postscaler, + adc_trigger8_postscaler, + adc_trigger9_postscaler, + adc_trigger10_postscaler, + divider, } = self; @@ -1068,152 +1313,284 @@ impl HrTimOngoingCalibration { .modify(|_r, w| w.calrte().bits(0b00).cal().set_bit().calen().clear_bit()); common.fltinr2.write(|w| w.fltsd().bits(divider as u8)); - common.adc1r.write(|w| w - .eper().bit(ad1_bits | Ad13T::TimEPeriod as u32 != 0) - .ec4().bit(ad1_bits | Ad13T::TimECmp4 as u32 != 0) - .ec3().bit(ad1_bits | Ad13T::TimECmp3 as u32 != 0) - //.frst() - .dper().bit(ad1_bits | Ad13T::TimDPeriod as u32 != 0) - .dc4().bit(ad1_bits | Ad13T::TimDCmp4 as u32 != 0) - .dc3().bit(ad1_bits | Ad13T::TimDCmp3 as u32 != 0) - .fper().bit(ad1_bits | Ad13T::TimFPeriod as u32 != 0) - .cper().bit(ad1_bits | Ad13T::TimCPeriod as u32 != 0) - .cc4().bit(ad1_bits | Ad13T::TimCCmp4 as u32 != 0) - .cc3().bit(ad1_bits | Ad13T::TimCCmp3 as u32 != 0) - .fc4().bit(ad1_bits | Ad13T::TimFCmp4 as u32 != 0) - //.brst() - .bper().bit(ad1_bits | Ad13T::TimBPeriod as u32 != 0) - .bc4().bit(ad1_bits | Ad13T::TimBCmp4 as u32 != 0) - .bc3().bit(ad1_bits | Ad13T::TimBCmp3 as u32 != 0) - .fc3().bit(ad1_bits | Ad13T::TimFCmp3 as u32 != 0) - //.arst() - .aper().bit(ad1_bits | Ad13T::TimAPeriod as u32 != 0) - .ac4().bit(ad1_bits | Ad13T::TimACmp4 as u32 != 0) - .ac3().bit(ad1_bits | Ad13T::TimACmp3 as u32 != 0) - .fc2().bit(ad1_bits | Ad13T::TimFCmp2 as u32 != 0) - //.eev5().bit(ad1_bits | Ad13T::_ as u32) - //.eev4().bit(ad1_bits | Ad13T::_ as u32) - //.eev3().bit(ad1_bits | Ad13T::_ as u32) - //.eev2().bit(ad1_bits | Ad13T::_ as u32) - //.eev1().bit(ad1_bits | Ad13T::_ as u32) - .mper().bit(ad1_bits | Ad13T::MasterPeriod as u32 != 0) - .mc4().bit(ad1_bits | Ad13T::MasterCmp4 as u32 != 0) - .mc3().bit(ad1_bits | Ad13T::MasterCmp3 as u32 != 0) - .mc2().bit(ad1_bits | Ad13T::MasterCmp2 as u32 != 0) - .mc1().bit(ad1_bits | Ad13T::MasterCmp1 as u32 != 0) - ); - - common.adc3r.write(|w| w - .eper().bit(ad3_bits | Ad13T::TimEPeriod as u32 != 0) - .ec4().bit(ad3_bits | Ad13T::TimECmp4 as u32 != 0) - .ec3().bit(ad3_bits | Ad13T::TimECmp3 as u32 != 0) - //.frst() - .dper().bit(ad3_bits | Ad13T::TimDPeriod as u32 != 0) - .dc4().bit(ad3_bits | Ad13T::TimDCmp4 as u32 != 0) - .dc3().bit(ad3_bits | Ad13T::TimDCmp3 as u32 != 0) - .fper().bit(ad3_bits | Ad13T::TimFPeriod as u32 != 0) - .cper().bit(ad3_bits | Ad13T::TimCPeriod as u32 != 0) - .cc4().bit(ad3_bits | Ad13T::TimCCmp4 as u32 != 0) - .cc3().bit(ad3_bits | Ad13T::TimCCmp3 as u32 != 0) - .fc4().bit(ad3_bits | Ad13T::TimFCmp4 as u32 != 0) - //.brst() - .bper().bit(ad3_bits | Ad13T::TimBPeriod as u32 != 0) - .bc4().bit(ad3_bits | Ad13T::TimBCmp4 as u32 != 0) - .bc3().bit(ad3_bits | Ad13T::TimBCmp3 as u32 != 0) - .fc3().bit(ad3_bits | Ad13T::TimFCmp3 as u32 != 0) - //.arst() - .aper().bit(ad3_bits | Ad13T::TimAPeriod as u32 != 0) - .ac4().bit(ad3_bits | Ad13T::TimACmp4 as u32 != 0) - .ac3().bit(ad3_bits | Ad13T::TimACmp3 as u32 != 0) - .fc2().bit(ad3_bits | Ad13T::TimFCmp2 as u32 != 0) - //.eev5().bit(ad3_bits | Ad13T::_ as u32) - //.eev4().bit(ad3_bits | Ad13T::_ as u32) - //.eev3().bit(ad3_bits | Ad13T::_ as u32) - //.eev2().bit(ad3_bits | Ad13T::_ as u32) - //.eev1().bit(ad3_bits | Ad13T::_ as u32) - .mper().bit(ad3_bits | Ad13T::MasterPeriod as u32 != 0) - .mc4().bit(ad3_bits | Ad13T::MasterCmp4 as u32 != 0) - .mc3().bit(ad3_bits | Ad13T::MasterCmp3 as u32 != 0) - .mc2().bit(ad3_bits | Ad13T::MasterCmp2 as u32 != 0) - .mc1().bit(ad3_bits | Ad13T::MasterCmp1 as u32 != 0) - ); - - common.adc2r.write(|w| w - //.erst() - .ec4().bit(ad2_bits | Ad24T::TimECmp4 as u32 != 0) - .ec3().bit(ad2_bits | Ad24T::TimECmp3 as u32 != 0) - .ec2().bit(ad2_bits | Ad24T::TimECmp2 as u32 != 0) - //.drst().bit(ad2_bits | Ad24T::_ as u32 != 0) - .dper().bit(ad2_bits | Ad24T::TimDPeriod as u32 != 0) - .dc4().bit(ad2_bits | Ad24T::TimDCmp4 as u32 != 0) - .fper().bit(ad2_bits | Ad24T::TimFPeriod as u32 != 0) - .dc2().bit(ad2_bits | Ad24T::TimACmp2 as u32 != 0) - //.crst().bit(ad2_bits | Ad24T::_ as u32 != 0) - .cper().bit(ad2_bits | Ad24T::TimCPeriod as u32 != 0) - .cc4().bit(ad2_bits | Ad24T::TimCCmp4 as u32 != 0) - .fc4().bit(ad2_bits | Ad24T::TimFCmp4 as u32 != 0) - .cc2().bit(ad2_bits | Ad24T::TimCCmp2 as u32 != 0) - .bper().bit(ad2_bits | Ad24T::TimBPeriod as u32 != 0) - .bc4().bit(ad2_bits | Ad24T::TimBCmp4 as u32 != 0) - .fc3().bit(ad2_bits | Ad24T::TimFCmp3 as u32 != 0) - .bc2().bit(ad2_bits | Ad24T::TimBCmp2 as u32 != 0) - .aper().bit(ad2_bits | Ad24T::TimAPeriod as u32 != 0) - .ac4().bit(ad2_bits | Ad24T::TimACmp4 as u32 != 0) - .fc2().bit(ad2_bits | Ad24T::TimFCmp2 as u32 != 0) - .ac2().bit(ad2_bits | Ad24T::TimACmp2 as u32 != 0) - //.eev10() - //.eev9() - //.eev8() - //.eev7() - //.eev6() - .mper().bit(ad2_bits | Ad24T::MasterPeriod as u32 != 0) - .mc4().bit(ad2_bits | Ad24T::MasterCmp4 as u32 != 0) - .mc3().bit(ad2_bits | Ad24T::MasterCmp3 as u32 != 0) - .mc2().bit(ad2_bits | Ad24T::MasterCmp2 as u32 != 0) - .mc1().bit(ad2_bits | Ad24T::MasterCmp1 as u32 != 0) - ); - - common.adc4r.write(|w| w - //.erst() - .ec4().bit(ad4_bits | Ad24T::TimECmp4 as u32 != 0) - .ec3().bit(ad4_bits | Ad24T::TimECmp3 as u32 != 0) - .ec2().bit(ad4_bits | Ad24T::TimECmp2 as u32 != 0) - //.drst().bit(ad4_bits | Ad24T::_ as u32 != 0) - .dper().bit(ad4_bits | Ad24T::TimDPeriod as u32 != 0) - .dc4().bit(ad4_bits | Ad24T::TimDCmp4 as u32 != 0) - .fper().bit(ad4_bits | Ad24T::TimFPeriod as u32 != 0) - .dc2().bit(ad4_bits | Ad24T::TimACmp2 as u32 != 0) - //.crst().bit(ad4_bits | Ad24T::_ as u32 != 0) - .cper().bit(ad4_bits | Ad24T::TimCPeriod as u32 != 0) - .cc4().bit(ad4_bits | Ad24T::TimCCmp4 as u32 != 0) - .fc4().bit(ad4_bits | Ad24T::TimFCmp4 as u32 != 0) - .cc2().bit(ad4_bits | Ad24T::TimCCmp2 as u32 != 0) - .bper().bit(ad4_bits | Ad24T::TimBPeriod as u32 != 0) - .bc4().bit(ad4_bits | Ad24T::TimBCmp4 as u32 != 0) - .fc3().bit(ad4_bits | Ad24T::TimFCmp3 as u32 != 0) - .bc2().bit(ad4_bits | Ad24T::TimBCmp2 as u32 != 0) - .aper().bit(ad4_bits | Ad24T::TimAPeriod as u32 != 0) - .ac4().bit(ad4_bits | Ad24T::TimACmp4 as u32 != 0) - .fc2().bit(ad4_bits | Ad24T::TimFCmp2 as u32 != 0) - .ac2().bit(ad4_bits | Ad24T::TimACmp2 as u32 != 0) - //.eev10() - //.eev9() - //.eev8() - //.eev7() - //.eev6() - .mper().bit(ad4_bits | Ad24T::MasterPeriod as u32 != 0) - .mc4().bit(ad4_bits | Ad24T::MasterCmp4 as u32 != 0) - .mc3().bit(ad4_bits | Ad24T::MasterCmp3 as u32 != 0) - .mc2().bit(ad4_bits | Ad24T::MasterCmp2 as u32 != 0) - .mc1().bit(ad4_bits | Ad24T::MasterCmp1 as u32 != 0) - ); - - common.adcps1.write(|w| w - .adc1psc().bits(adc_trigger1_postscaler as u8) - .adc2psc().bits(adc_trigger2_postscaler as u8) - .adc3psc().bits(adc_trigger3_postscaler as u8) - .adc4psc().bits(adc_trigger4_postscaler as u8) - ); + common.adc1r.write(|w| { + w.eper() + .bit(ad1_bits | Ad13T::TimEPeriod as u32 != 0) + .ec4() + .bit(ad1_bits | Ad13T::TimECmp4 as u32 != 0) + .ec3() + .bit(ad1_bits | Ad13T::TimECmp3 as u32 != 0) + //.frst() + .dper() + .bit(ad1_bits | Ad13T::TimDPeriod as u32 != 0) + .dc4() + .bit(ad1_bits | Ad13T::TimDCmp4 as u32 != 0) + .dc3() + .bit(ad1_bits | Ad13T::TimDCmp3 as u32 != 0) + .fper() + .bit(ad1_bits | Ad13T::TimFPeriod as u32 != 0) + .cper() + .bit(ad1_bits | Ad13T::TimCPeriod as u32 != 0) + .cc4() + .bit(ad1_bits | Ad13T::TimCCmp4 as u32 != 0) + .cc3() + .bit(ad1_bits | Ad13T::TimCCmp3 as u32 != 0) + .fc4() + .bit(ad1_bits | Ad13T::TimFCmp4 as u32 != 0) + //.brst() + .bper() + .bit(ad1_bits | Ad13T::TimBPeriod as u32 != 0) + .bc4() + .bit(ad1_bits | Ad13T::TimBCmp4 as u32 != 0) + .bc3() + .bit(ad1_bits | Ad13T::TimBCmp3 as u32 != 0) + .fc3() + .bit(ad1_bits | Ad13T::TimFCmp3 as u32 != 0) + //.arst() + .aper() + .bit(ad1_bits | Ad13T::TimAPeriod as u32 != 0) + .ac4() + .bit(ad1_bits | Ad13T::TimACmp4 as u32 != 0) + .ac3() + .bit(ad1_bits | Ad13T::TimACmp3 as u32 != 0) + .fc2() + .bit(ad1_bits | Ad13T::TimFCmp2 as u32 != 0) + //.eev5().bit(ad1_bits | Ad13T::_ as u32) + //.eev4().bit(ad1_bits | Ad13T::_ as u32) + //.eev3().bit(ad1_bits | Ad13T::_ as u32) + //.eev2().bit(ad1_bits | Ad13T::_ as u32) + //.eev1().bit(ad1_bits | Ad13T::_ as u32) + .mper() + .bit(ad1_bits | Ad13T::MasterPeriod as u32 != 0) + .mc4() + .bit(ad1_bits | Ad13T::MasterCmp4 as u32 != 0) + .mc3() + .bit(ad1_bits | Ad13T::MasterCmp3 as u32 != 0) + .mc2() + .bit(ad1_bits | Ad13T::MasterCmp2 as u32 != 0) + .mc1() + .bit(ad1_bits | Ad13T::MasterCmp1 as u32 != 0) + }); + + common.adc3r.write(|w| { + w.eper() + .bit(ad3_bits | Ad13T::TimEPeriod as u32 != 0) + .ec4() + .bit(ad3_bits | Ad13T::TimECmp4 as u32 != 0) + .ec3() + .bit(ad3_bits | Ad13T::TimECmp3 as u32 != 0) + //.frst() + .dper() + .bit(ad3_bits | Ad13T::TimDPeriod as u32 != 0) + .dc4() + .bit(ad3_bits | Ad13T::TimDCmp4 as u32 != 0) + .dc3() + .bit(ad3_bits | Ad13T::TimDCmp3 as u32 != 0) + .fper() + .bit(ad3_bits | Ad13T::TimFPeriod as u32 != 0) + .cper() + .bit(ad3_bits | Ad13T::TimCPeriod as u32 != 0) + .cc4() + .bit(ad3_bits | Ad13T::TimCCmp4 as u32 != 0) + .cc3() + .bit(ad3_bits | Ad13T::TimCCmp3 as u32 != 0) + .fc4() + .bit(ad3_bits | Ad13T::TimFCmp4 as u32 != 0) + //.brst() + .bper() + .bit(ad3_bits | Ad13T::TimBPeriod as u32 != 0) + .bc4() + .bit(ad3_bits | Ad13T::TimBCmp4 as u32 != 0) + .bc3() + .bit(ad3_bits | Ad13T::TimBCmp3 as u32 != 0) + .fc3() + .bit(ad3_bits | Ad13T::TimFCmp3 as u32 != 0) + //.arst() + .aper() + .bit(ad3_bits | Ad13T::TimAPeriod as u32 != 0) + .ac4() + .bit(ad3_bits | Ad13T::TimACmp4 as u32 != 0) + .ac3() + .bit(ad3_bits | Ad13T::TimACmp3 as u32 != 0) + .fc2() + .bit(ad3_bits | Ad13T::TimFCmp2 as u32 != 0) + //.eev5().bit(ad3_bits | Ad13T::_ as u32) + //.eev4().bit(ad3_bits | Ad13T::_ as u32) + //.eev3().bit(ad3_bits | Ad13T::_ as u32) + //.eev2().bit(ad3_bits | Ad13T::_ as u32) + //.eev1().bit(ad3_bits | Ad13T::_ as u32) + .mper() + .bit(ad3_bits | Ad13T::MasterPeriod as u32 != 0) + .mc4() + .bit(ad3_bits | Ad13T::MasterCmp4 as u32 != 0) + .mc3() + .bit(ad3_bits | Ad13T::MasterCmp3 as u32 != 0) + .mc2() + .bit(ad3_bits | Ad13T::MasterCmp2 as u32 != 0) + .mc1() + .bit(ad3_bits | Ad13T::MasterCmp1 as u32 != 0) + }); + + common.adc2r.write(|w| { + w + //.erst() + .ec4() + .bit(ad2_bits | Ad24T::TimECmp4 as u32 != 0) + .ec3() + .bit(ad2_bits | Ad24T::TimECmp3 as u32 != 0) + .ec2() + .bit(ad2_bits | Ad24T::TimECmp2 as u32 != 0) + //.drst().bit(ad2_bits | Ad24T::_ as u32 != 0) + .dper() + .bit(ad2_bits | Ad24T::TimDPeriod as u32 != 0) + .dc4() + .bit(ad2_bits | Ad24T::TimDCmp4 as u32 != 0) + .fper() + .bit(ad2_bits | Ad24T::TimFPeriod as u32 != 0) + .dc2() + .bit(ad2_bits | Ad24T::TimDCmp2 as u32 != 0) + //.crst().bit(ad2_bits | Ad24T::_ as u32 != 0) + .cper() + .bit(ad2_bits | Ad24T::TimCPeriod as u32 != 0) + .cc4() + .bit(ad2_bits | Ad24T::TimCCmp4 as u32 != 0) + .fc4() + .bit(ad2_bits | Ad24T::TimFCmp4 as u32 != 0) + .cc2() + .bit(ad2_bits | Ad24T::TimCCmp2 as u32 != 0) + .bper() + .bit(ad2_bits | Ad24T::TimBPeriod as u32 != 0) + .bc4() + .bit(ad2_bits | Ad24T::TimBCmp4 as u32 != 0) + .fc3() + .bit(ad2_bits | Ad24T::TimFCmp3 as u32 != 0) + .bc2() + .bit(ad2_bits | Ad24T::TimBCmp2 as u32 != 0) + .aper() + .bit(ad2_bits | Ad24T::TimAPeriod as u32 != 0) + .ac4() + .bit(ad2_bits | Ad24T::TimACmp4 as u32 != 0) + .fc2() + .bit(ad2_bits | Ad24T::TimFCmp2 as u32 != 0) + .ac2() + .bit(ad2_bits | Ad24T::TimACmp2 as u32 != 0) + //.eev10() + //.eev9() + //.eev8() + //.eev7() + //.eev6() + .mper() + .bit(ad2_bits | Ad24T::MasterPeriod as u32 != 0) + .mc4() + .bit(ad2_bits | Ad24T::MasterCmp4 as u32 != 0) + .mc3() + .bit(ad2_bits | Ad24T::MasterCmp3 as u32 != 0) + .mc2() + .bit(ad2_bits | Ad24T::MasterCmp2 as u32 != 0) + .mc1() + .bit(ad2_bits | Ad24T::MasterCmp1 as u32 != 0) + }); + + common.adc4r.write(|w| { + w + //.erst() + .ec4() + .bit(ad4_bits | Ad24T::TimECmp4 as u32 != 0) + .ec3() + .bit(ad4_bits | Ad24T::TimECmp3 as u32 != 0) + .ec2() + .bit(ad4_bits | Ad24T::TimECmp2 as u32 != 0) + //.drst().bit(ad4_bits | Ad24T::_ as u32 != 0) + .dper() + .bit(ad4_bits | Ad24T::TimDPeriod as u32 != 0) + .dc4() + .bit(ad4_bits | Ad24T::TimDCmp4 as u32 != 0) + .fper() + .bit(ad4_bits | Ad24T::TimFPeriod as u32 != 0) + .dc2() + .bit(ad4_bits | Ad24T::TimDCmp2 as u32 != 0) + //.crst().bit(ad4_bits | Ad24T::_ as u32 != 0) + .cper() + .bit(ad4_bits | Ad24T::TimCPeriod as u32 != 0) + .cc4() + .bit(ad4_bits | Ad24T::TimCCmp4 as u32 != 0) + .fc4() + .bit(ad4_bits | Ad24T::TimFCmp4 as u32 != 0) + .cc2() + .bit(ad4_bits | Ad24T::TimCCmp2 as u32 != 0) + .bper() + .bit(ad4_bits | Ad24T::TimBPeriod as u32 != 0) + .bc4() + .bit(ad4_bits | Ad24T::TimBCmp4 as u32 != 0) + .fc3() + .bit(ad4_bits | Ad24T::TimFCmp3 as u32 != 0) + .bc2() + .bit(ad4_bits | Ad24T::TimBCmp2 as u32 != 0) + .aper() + .bit(ad4_bits | Ad24T::TimAPeriod as u32 != 0) + .ac4() + .bit(ad4_bits | Ad24T::TimACmp4 as u32 != 0) + .fc2() + .bit(ad4_bits | Ad24T::TimFCmp2 as u32 != 0) + .ac2() + .bit(ad4_bits | Ad24T::TimACmp2 as u32 != 0) + //.eev10() + //.eev9() + //.eev8() + //.eev7() + //.eev6() + .mper() + .bit(ad4_bits | Ad24T::MasterPeriod as u32 != 0) + .mc4() + .bit(ad4_bits | Ad24T::MasterCmp4 as u32 != 0) + .mc3() + .bit(ad4_bits | Ad24T::MasterCmp3 as u32 != 0) + .mc2() + .bit(ad4_bits | Ad24T::MasterCmp2 as u32 != 0) + .mc1() + .bit(ad4_bits | Ad24T::MasterCmp1 as u32 != 0) + }); + + common.adcer.write(|w| { + w.adc5trg() + .variant(ad5_bits) + .adc6trg() + .variant(ad6_bits) + .adc7trg() + .variant(ad7_bits) + .adc8trg() + .variant(ad8_bits) + .adc9trg() + .variant(ad9_bits) + .adc10trg() + .variant(ad10_bits) + }); + + common.adcps1.write(|w| { + w.adc1psc() + .bits(adc_trigger1_postscaler as u8) + .adc2psc() + .bits(adc_trigger2_postscaler as u8) + .adc3psc() + .bits(adc_trigger3_postscaler as u8) + .adc4psc() + .bits(adc_trigger4_postscaler as u8) + .adc5psc() + .bits(adc_trigger5_postscaler as u8) + }); + + common.adcps2.write(|w| { + w.adc6psc() + .bits(adc_trigger6_postscaler as u8) + .adc7psc() + .bits(adc_trigger7_postscaler as u8) + .adc8psc() + .bits(adc_trigger8_postscaler as u8) + .adc9psc() + .bits(adc_trigger9_postscaler as u8) + .adc10psc() + .bits(adc_trigger10_postscaler as u8) + }); // TODO: Adc trigger 5-10 } @@ -1270,6 +1647,36 @@ impl HrTimOngoingCalibration { self } + pub fn set_adc_trigger5(mut self, trigger: Adc579Trigger) -> Self { + self.adc_trigger5_bits = trigger as u8; + self + } + + pub fn set_adc_trigger6(mut self, trigger: Adc6810Trigger) -> Self { + self.adc_trigger6_bits = trigger as u8; + self + } + + pub fn set_adc_trigger7(mut self, trigger: Adc579Trigger) -> Self { + self.adc_trigger7_bits = trigger as u8; + self + } + + pub fn set_adc_trigger8(mut self, trigger: Adc6810Trigger) -> Self { + self.adc_trigger8_bits = trigger as u8; + self + } + + pub fn set_adc_trigger9(mut self, trigger: Adc579Trigger) -> Self { + self.adc_trigger9_bits = trigger as u8; + self + } + + pub fn set_adc_trigger10(mut self, trigger: Adc6810Trigger) -> Self { + self.adc_trigger10_bits = trigger as u8; + self + } + pub fn set_adc1_trigger_psc(mut self, post_scaler: AdcTriggerPostscaler) -> Self { self.adc_trigger1_postscaler = post_scaler; self @@ -1290,6 +1697,11 @@ impl HrTimOngoingCalibration { self } + pub fn set_fault_sampling_division(mut self, divider: FaultSamplingClkDiv) -> Self { + self.divider = divider; + self + } + // TODO: Adc trigger 5-10 } @@ -1305,7 +1717,6 @@ pub enum Adc13Trigger { // /// bit 28 ADCxTFRST // _ = 1 << 28, - /// bit 27 ADCxTDPER - Trigger on HRTIM_TIMD period TimDPeriod = 1 << 27, @@ -1332,7 +1743,6 @@ pub enum Adc13Trigger { // /// bit 19 ADCxTBRST // _ = 1 << 19, - /// bit 18 ADCxTBPER - Trigger on HRTIM_TIMB period TimBPeriod = 1 << 18, @@ -1347,7 +1757,6 @@ pub enum Adc13Trigger { // /// bit 14 ADCxTARST // _ = 1 << 14, - /// bit 13 ADCxTAPER - Trigger on HRTIM_TIMA period TimAPeriod = 1 << 13, @@ -1371,7 +1780,6 @@ pub enum Adc13Trigger { // /// bit 6 ADCxEEV2 // _ = 1 << 6, - /// bit 5 ADCxEEV1 // _ = 1 << 5, @@ -1429,7 +1837,6 @@ pub enum AdcTriggerPostscaler { pub enum Adc24Trigger { // /// bit 31 ADCxTERST // _ = 1 << 31, - /// bit 30 ADCxTEC4 - Trigger on HRTIM_TIME compare match for compare register 4 TimECmp4 = 1 << 30, @@ -1441,7 +1848,6 @@ pub enum Adc24Trigger { // /// bit 27 ADCxTDRST // _ = 1 << 27, - /// bit 26 ADCxTDPER - Trigger on HRTIM_TIMD period TimDPeriod = 1 << 26, @@ -1507,7 +1913,6 @@ pub enum Adc24Trigger { // /// bit 5 ADCxEEV6 // _ = 1 << 5, - /// bit 4 ADCxMPER - Trigger on HRTIM_MASTER period MasterPeriod = 1 << 4, @@ -1524,6 +1929,194 @@ pub enum Adc24Trigger { MasterCmp1 = 1 << 0, } +pub enum Adc579Trigger { + // /// Trigger on F reset and counter roll-over + // _ = 31 + /// Trigger on HRTIM_TIMF period + TimFPeriod = 30, + + /// Trigger on HRTIM_TIMF compare match for compare register 4 + TimFCmp4 = 29, + + /// Trigger on HRTIM_TIMF compare match for compare register 3 + TimFCmp3 = 28, + + /// Trigger on HRTIM_TIMF compare match for compare register 2 + TimFCmp2 = 27, + + /// Trigger on HRTIM_TIME period + TimEPeriod = 26, + + /// Trigger on HRTIM_TIME compare match for compare register 4 + TimECmp4 = 25, + + /// Trigger on HRTIM_TIME compare match for compare register 3 + TimECmp3 = 24, + + /// Trigger on HRTIM_TIMD period + TimDPeriod = 23, + + /// Trigger on HRTIM_TIMD compare match for compare register 4 + TimDCmp4 = 22, + + /// Trigger on HRTIM_TIMD compare match for compare register 3 + TimDCmp3 = 21, + + /// Trigger on HRTIM_TIMC period + TimCPeriod = 20, + + /// Trigger on HRTIM_TIMC compare match for compare register 4 + TimCCmp4 = 19, + + /// Trigger on HRTIM_TIMC compare match for compare register 3 + TimCCmp3 = 18, + + // /// Trigger on B reset and counter roll-over + // _ = 17 + /// Trigger on HRTIM_TIMB period + TimBPeriod = 16, + + /// Trigger on HRTIM_TIMB compare match for compare register 4 + TimBCmp4 = 15, + + /// Trigger on HRTIM_TIMB compare match for compare register 3 + TimBCmp3 = 14, + + // /// Trigger on A reset and counter roll-over + // _ = 13 + /// Trigger on HRTIM_TIMA period + TimAPeriod = 12, + + /// Trigger on HRTIM_TIMA compare match for compare register 4 + TimACmp4 = 11, + + /// Trigger on HRTIM_TIMA compare match for compare register 3 + TimACmp3 = 10, + + // /// Trigger on EEV5 + // _ = 9, + + // /// Trigger on EEV4 + // _ = 8, + + // /// Trigger on EEV3 + // _ = 7, + + // /// Trigger on EEV2 + // _ = 6, + + // /// Trigger on EEV1 + // _ = 5, + /// Trigger on HRTIM_MASTER period + MasterPeriod = 4, + + /// Trigger on HRTIM_MASTER compare match for compare register 4 + MasterCmp4 = 3, + + /// Trigger on HRTIM_MASTER compare match for compare register 3 + MasterCmp3 = 2, + + /// Trigger on HRTIM_MASTER compare match for compare register 2 + MasterCmp2 = 1, + + /// Trigger on HRTIM_MASTER compare match for compare register 1 + MasterCmp1 = 0, +} + +pub enum Adc6810Trigger { + /// Trigger on HRTIM_TIMF period + TimFPeriod = 31, + + /// Trigger on HRTIM_TIMF compare match for compare register 4 + TimFCmp4 = 30, + + /// Trigger on HRTIM_TIMF compare match for compare register 3 + TimFCmp3 = 29, + + /// Trigger on HRTIM_TIMF compare match for compare register 2 + TimFCmp2 = 28, + + // /// Trigger on E reset and counter roll-over + // _ = 27 + /// Trigger on HRTIM_TIME compare match for compare register 4 + TimECmp4 = 26, + + /// Trigger on HRTIM_TIME compare match for compare register 3 + TimECmp3 = 25, + + /// Trigger on HRTIM_TIME compare match for compare register 2 + TimECmp2 = 24, + + // /// Trigger on D reset and counter roll-over + // _ = 23 + /// Trigger on HRTIM_TIMD period + TimDPeriod = 22, + + /// Trigger on HRTIM_TIMD compare match for compare register 4 + TimDCmp4 = 21, + + /// Trigger on HRTIM_TIMD compare match for compare register 2 + TimDCmp2 = 20, + + // /// Trigger on D reset and counter roll-over + // _ = 19 + /// Trigger on HRTIM_TIMC period + TimCPeriod = 18, + + /// Trigger on HRTIM_TIMC compare match for compare register 4 + TimCCmp4 = 17, + + /// Trigger on HRTIM_TIMC compare match for compare register 2 + TimCCmp2 = 16, + + /// Trigger on HRTIM_TIMB period + TimBPeriod = 15, + + /// Trigger on HRTIM_TIMB compare match for compare register 4 + TimBCmp4 = 14, + + /// Trigger on HRTIM_TIMB compare match for compare register 2 + TimBCmp2 = 13, + + /// Trigger on HRTIM_TIMA period + TimAPeriod = 12, + + /// Trigger on HRTIM_TIMA compare match for compare register 4 + TimACmp4 = 11, + + /// Trigger on HRTIM_TIMA compare match for compare register 2 + TimACmp2 = 10, + + // /// Trigger on EEV10 + // _ = 9, + + // /// Trigger on EEV9 + // _ = 8, + + // /// Trigger on EEV8 + // _ = 7, + + // /// Trigger on EEV7 + // _ = 6, + + // /// Trigger on EEV6 + // _ = 5, + /// Trigger on HRTIM_MASTER period + MasterPeriod = 4, + + /// Trigger on HRTIM_MASTER compare match for compare register 4 + MasterCmp4 = 3, + + /// Trigger on HRTIM_MASTER compare match for compare register 3 + MasterCmp3 = 2, + + /// Trigger on HRTIM_MASTER compare match for compare register 2 + MasterCmp2 = 1, + + /// Trigger on HRTIM_MASTER compare match for compare register 1 + MasterCmp1 = 0, +} + macro_rules! impl_flt_monitor { ($($t:ident: ($fltx:ident, $fltxc:ident),)+) => {$( pub struct $t { diff --git a/src/rcc/config.rs b/src/rcc/config.rs index a2ab3443..4af1dcb1 100644 --- a/src/rcc/config.rs +++ b/src/rcc/config.rs @@ -46,6 +46,16 @@ pub enum PllSrc { HSE_BYPASS(Hertz), } +impl PLLSrc { + pub const fn frequency(self) -> Hertz { + match self { + PLLSrc::HSI => Hertz::MHz(16), + PLLSrc::HSE(f) => f, + PLLSrc::HSE_BYPASS(f) => f, + } + } +} + /// Divider for the PLL clock input (M) /// This must be set based on the input clock to keep the PLL input frequency within the limits /// specified in the datasheet. @@ -70,11 +80,11 @@ pub enum PllMDiv { } impl PllMDiv { - pub fn divisor(&self) -> u32 { + pub const fn divisor(&self) -> u32 { (*self as u32) + 1 } - pub fn register_setting(&self) -> u8 { + pub const fn register_setting(&self) -> u8 { *self as u8 } } @@ -108,11 +118,11 @@ pub enum PllRDiv { } impl PllRDiv { - pub fn divisor(&self) -> u32 { + pub const fn divisor(&self) -> u32 { ((*self as u32) + 1) * 2 } - pub fn register_setting(&self) -> u8 { + pub const fn register_setting(&self) -> u8 { *self as u8 } } @@ -157,11 +167,11 @@ pub enum PllPDiv { } impl PllPDiv { - pub fn divisor(&self) -> u32 { + pub const fn divisor(&self) -> u32 { *self as u32 } - pub fn register_setting(&self) -> u8 { + pub const fn register_setting(&self) -> u8 { *self as u8 } } @@ -292,7 +302,7 @@ pub enum PllNMul { } impl PllNMul { - pub fn multiplier(&self) -> u32 { + pub const fn multiplier(&self) -> u32 { *self as u32 } From 125620711f49f9ec0c7769ac9c809a1a92c7e547 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 25 Aug 2023 17:26:01 +0200 Subject: [PATCH 31/88] Disable push pull --- examples/hrtim-master.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/hrtim-master.rs b/examples/hrtim-master.rs index 3a0d35c5..6a9b62cb 100644 --- a/examples/hrtim-master.rs +++ b/examples/hrtim-master.rs @@ -79,7 +79,7 @@ fn main() -> ! { .HRTIM_TIMA .pwm_advanced((pin_a, pin_b), &mut rcc) .prescaler(prescaler) - .push_pull_mode(true) // Set push pull mode, out1 and out2 are + //.push_pull_mode(true) // Set push pull mode, out1 and out2 are // alternated every period with one being // inactive and the other getting to output its wave form // as normal @@ -96,17 +96,17 @@ fn main() -> ! { out1.enable_rst_event(EventSource::MasterCr1); // Set low on compare match with cr1 out2.enable_rst_event(EventSource::MasterCr1); - out1.enable_set_event(EventSource::Period); // Set high at new period - out2.enable_set_event(EventSource::Period); + out1.enable_set_event(EventSource::MasterPeriod); // Set high at new period + out2.enable_set_event(EventSource::MasterPeriod); out1.enable(); out2.enable(); let tima = unsafe { &*stm32g4xx_hal::stm32::HRTIM_TIMA::ptr() }; info!("set1r: {}", tima.seta1r.read().bits()); - info!("set2r: {}", tima.seta2r.read().bits()); - info!("rst1r: {}", tima.rsta1r.read().bits()); + + info!("set2r: {}", tima.seta2r.read().bits()); info!("rst2r: {}", tima.rsta2r.read().bits()); info!("Running"); @@ -117,9 +117,9 @@ fn main() -> ! { let new_period = u16::MAX / i; mcr1.set_duty(new_period / 3); - //cr1.set_duty(new_period / 3); + cr1.set_duty(new_period / 3 - 1000); mtimer.set_period(new_period); - //timer.set_period(new_period); + timer.set_period(new_period - 1000); info!("period: {}, duty: {}, get_duty: {}, get_period: {}", new_period, new_period / 3, mcr1.get_duty(), mtimer.get_period()); From 799e1665acbb18c66fe6181f185223f08779c01b Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 4 Sep 2023 18:55:59 +0200 Subject: [PATCH 32/88] NOT DONE - Losts of hrtim stuff --- src/pwm/hrtim.rs | 712 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 661 insertions(+), 51 deletions(-) diff --git a/src/pwm/hrtim.rs b/src/pwm/hrtim.rs index bff6ff08..2c1d588c 100644 --- a/src/pwm/hrtim.rs +++ b/src/pwm/hrtim.rs @@ -31,6 +31,117 @@ enum CountSettings { Period(u16), } +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum HrTimerMode { + SingleShotNonRetriggerable, + SingleShotRetriggerable, + Continuous, +} + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum HrCountingDirection { + /// Asymetrical up counting mode + /// + /// + + /// * * + /// Counting up * | * | + /// * * + /// * | * | + /// * * + /// * | * | + /// * * + /// -------------------------------------- + /// + /// ```txt + /// | *-------* *------ + /// | | | + /// | | | | + /// | | | + /// ----------* *------------------* + /// ``` + /// + /// This is the most common mode with least amount of quirks + Up, + + /// Symmetrical up-down counting mode + /// + /// + /// ```txt + /// Period--> * Counting * + /// Counting up * | * Counting Up * | + /// * * down * + /// * | * * | + /// * * * + /// * | * * | + /// 0 -->* * + /// --------------------------------------------------------------------------- + /// | *---------------* | *---------------* + /// | | | | | | + /// | | | | | | + /// | | | | | | + /// ----------* *-------------------* *--- + /// ``` + /// + /// NOTE: This is incompatible with + /// * Auto-delay + /// * Balanded Idle + /// * Triggered-half mode + /// + /// There is also differences in (including but not limited to) the following areas: + /// * Counter roll over event + /// * The events registered with `enable_set_event` will work as normal wen counting up, however when counting down, they will work as rst events. + /// * The events registered with `enable_rst_event` will work as normal wen counting up, however when counting down, they will work as set events. + UpDown, +} + +// Needed to calculate frequency +impl Into for HrCountingDirection { + fn into(self) -> super::Alignment { + match self { + HrCountingDirection::Up => super::Alignment::Left, + HrCountingDirection::UpDown => super::Alignment::Center, + } + } +} + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum InterleavedMode { + Disabled, + + /// Dual interleaved or Half mode + /// + /// Automatically force + /// * Cr1 to PERIOD / 2 (not visable through `get_duty`). + /// Automatically updates when changing period + /// + /// NOTE: Affects Cr1 + Dual, + + /// Triple interleaved mode + /// + /// Automatically force + /// * Cr1 to 1 * PERIOD / 3 and + /// * Cr2 to 2 * PERIOD / 3 + /// (not visable through `get_duty`). Automatically updates when changing period. + /// + /// NOTE: Must not be used simultaneously with other modes + /// using CMP2 (dual channel dac trigger and triggered-half modes). + Triple, + + /// Quad interleaved mode + /// + /// Automatically force + /// * Cr1 to 1 * PERIOD / 4, + /// * Cr2 to 2 * PERIOD / 4 and + /// * Cr3 to 3 * PERIOD / 4 + /// (not visable through `get_duty`). Automatically updates when changing period. + /// + /// NOTE: Must not be used simultaneously with other modes + /// using CMP2 (dual channel dac trigger and triggered-half modes). + Quad, +} + macro_rules! pins { ($($TIMX:ty: CH1: $CH1:ty, CH2: $CH2:ty)+) => { $( @@ -42,11 +153,11 @@ macro_rules! pins { type Channel = Pwm<$TIMX, CH2, ComplementaryImpossible, ActiveHigh, ActiveHigh>; } - impl ToHrOut for $CH1 { + unsafe impl ToHrOut for $CH1 { type Out = HrOut1<$TIMX>; } - impl ToHrOut for $CH2 { + unsafe impl ToHrOut for $CH2 { type Out = HrOut2<$TIMX>; } )+ @@ -68,7 +179,7 @@ impl Pins for () { type Channel = (); } -impl ToHrOut for () { +unsafe impl ToHrOut for () { type Out = (); } @@ -143,7 +254,8 @@ pub struct HrPwmBuilder { _tim: PhantomData, _prescaler: PhantomData, _out: PhantomData, - alignment: Alignment, + timer_mode: HrTimerMode, + counting_direction: HrCountingDirection, base_freq: HertzU64, count: CountSettings, preload_source: Option, @@ -151,12 +263,21 @@ pub struct HrPwmBuilder { fault1_bits: u8, fault2_bits: u8, enable_push_pull: bool, + interleaved_mode: InterleavedMode, // Also includes half mode + repetition_counter: u8, //deadtime: NanoSecond, + enable_repetition_interrupt: bool, } pub enum PreloadSource { /// Preloaded registers are updated on counter roll over or counter reset OnCounterReset, + + /// Preloaded registers are updated by master timer update + OnMasterTimerUpdate, + + /// Prealoaded registers are updaten when the counter rolls over and the repetition counter is 0 + OnRepetitionUpdate, } pub enum MasterPreloadSource { @@ -261,11 +382,371 @@ pub enum EventSource { // TODO: These are unique for every timer output //Extra(E) } -pub trait ToHrOut { + +macro_rules! hr_timer_reset_event_source_common { + ($(#[$($attrss:tt)*])* pub enum $t:ident { [COMMON], $(#[$($attrss2:tt)*] $vals:tt = 1 << $x:literal,)*}) => { + $(#[$($attrss)*])* + pub enum $t { + $(#[$($attrss2)*] $vals = 1 << $x,)* + + /// The timer counter is reset upon external event 10. + Eevnt10 = 1 << 18, + + /// The timer counter is reset upon external event 9. + Eevnt9 = 1 << 17, + + /// The timer counter is reset upon external event 8. + Eevnt8 = 1 << 16, + + /// The timer counter is reset upon external event 7. + Eevnt7 = 1 << 15, + + /// The timer counter is reset upon external event 6. + Eevnt6 = 1 << 14, + + /// The timer counter is reset upon external event 5. + Eevnt5 = 1 << 13, + + /// The timer counter is reset upon external event 4. + Eevnt4 = 1 << 12, + + /// The timer counter is reset upon external event 3. + Eevnt3 = 1 << 11, + + /// The timer counter is reset upon external event 2. + Eevnt2 = 1 << 10, + + /// The timer counter is reset upon external event 1. + Eevnt1 = 1 << 9, + + /// The timer counter is reset upon master timer compare 4 event. + MasterCmp4 = 1 << 8, + + /// The timer counter is reset upon master timer compare 3 event. + MasterCmp3 = 1 << 7, + + /// The timer counter is reset upon master timer compare 2 event. + MasterCmp2 = 1 << 6, + + /// The timer counter is reset upon master timer compare 1 event. + MasterCmp1 = 1 << 5, + + /// The timer counter is reset upon master timer period event. + MasterPeriod = 1 << 4, + + /// The timer counter is reset upon timer its own compare 4 event + Cmp4 = 1 << 3, + + /// The timer counter is reset upon timer its own compare 2 event + Cmp2 = 1 << 2, + + /// The timer counter is reset upon update event. + Update = 1 << 1, + } + }; +} + +hr_timer_reset_event_source_common!( + /// A + pub enum TimerAResetEventSource { + [COMMON], + /// The timer counter is reset upon timer F compare 2 event. + TimFCmp2 = 1 << 31, + + /// The timer counter is reset upon timer E compare 4 event. + TimECmp4 = 1 << 30, + + /// The timer counter is reset upon timer E compare 2 event. + TimECmp2 = 1 << 29, + + /// The timer counter is reset upon timer E compare 1 event. + TimECmp1 = 1 << 28, + + /// The timer counter is reset upon timer D compare 4 event. + TimDCmp4 = 1 << 27, + + /// The timer counter is reset upon timer D compare 2 event. + TimDCmp2 = 1 << 26, + + /// The timer counter is reset upon timer D compare 1 event. + TimDCmp1 = 1 << 25, + + /// The timer counter is reset upon timer C compare 4 event. + TimCCmp4 = 1 << 24, + + /// The timer counter is reset upon timer C compare 2 event. + TimCCmp2 = 1 << 23, + + /// The timer counter is reset upon timer C compare 1 event. + TimCCmp1 = 1 << 22, + + /// The timer counter is reset upon timer B compare 4 event. + TimBCmp4 = 1 << 21, + + /// The timer counter is reset upon timer B compare 2 event. + TimBCmp2 = 1 << 20, + + /// The timer counter is reset upon timer B compare 1 event. + TimBCmp1 = 1 << 19, + + /// The timer counter is reset upon timer F compare 1 event. + TimFCmp1 = 1 << 0, + } +); + +hr_timer_reset_event_source_common!( + /// B + pub enum TimerBResetEventSource { + [COMMON], + + /// The timer counter is reset upon timer F compare 2 event. + TimFCmp2 = 1 << 31, + + /// The timer counter is reset upon timer E compare 4 event. + TimECmp4 = 1 << 30, + + /// The timer counter is reset upon timer E compare 2 event. + TimECmp2 = 1 << 29, + + /// The timer counter is reset upon timer E compare 1 event. + TimECmp1 = 1 << 28, + + /// The timer counter is reset upon timer D compare 4 event. + TimDCmp4 = 1 << 27, + + /// The timer counter is reset upon timer D compare 2 event. + TimDCmp2 = 1 << 26, + + /// The timer counter is reset upon timer D compare 1 event. + TimDCmp1 = 1 << 25, + + /// The timer counter is reset upon timer C compare 4 event. + TimCCmp4 = 1 << 24, + + /// The timer counter is reset upon timer C compare 2 event. + TimCCmp2 = 1 << 23, + + /// The timer counter is reset upon timer C compare 1 event. + TimCCmp1 = 1 << 22, + + /// The timer counter is reset upon timer A compare 4 event. + TimACmp4 = 1 << 21, + + /// The timer counter is reset upon timer A compare 2 event. + TimACmp2 = 1 << 20, + + /// The timer counter is reset upon timer A compare 1 event. + TimACmp1 = 1 << 19, + + + /// The timer counter is reset upon timer F compare 1 event. + TimFCmp1 = 1 << 0, + } +); + +hr_timer_reset_event_source_common!( + /// C + pub enum TimerCResetEventSource { + [COMMON], + + /// The timer counter is reset upon timer F compare 2 event. + TimFCmp2 = 1 << 31, + + /// The timer counter is reset upon timer E compare 4 event. + TimECmp4 = 1 << 30, + + /// The timer counter is reset upon timer E compare 2 event. + TimECmp2 = 1 << 29, + + /// The timer counter is reset upon timer E compare 1 event. + TimECmp1 = 1 << 28, + + /// The timer counter is reset upon timer D compare 4 event. + TimDCmp4 = 1 << 27, + + /// The timer counter is reset upon timer D compare 2 event. + TimDCmp2 = 1 << 26, + + /// The timer counter is reset upon timer D compare 1 event. + TimDCmp1 = 1 << 25, + + /// The timer counter is reset upon timer B compare 4 event. + TimBCmp4 = 1 << 24, + + /// The timer counter is reset upon timer B compare 2 event. + TimBCmp2 = 1 << 23, + + /// The timer counter is reset upon timer B compare 1 event. + TimBCmp1 = 1 << 22, + + /// The timer counter is reset upon timer A compare 4 event. + TimACmp4 = 1 << 21, + + /// The timer counter is reset upon timer A compare 2 event. + TimACmp2 = 1 << 20, + + /// The timer counter is reset upon timer A compare 1 event. + TimACmp1 = 1 << 19, + + + /// The timer counter is reset upon timer F compare 1 event. + TimFCmp1 = 1 << 0, + } +); + +hr_timer_reset_event_source_common!( + /// D + pub enum TimerDResetEventSource { + [COMMON], + + /// The timer counter is reset upon timer F compare 2 event. + TimFCmp2 = 1 << 31, + + /// The timer counter is reset upon timer E compare 4 event. + TimECmp4 = 1 << 30, + + /// The timer counter is reset upon timer E compare 2 event. + TimECmp2 = 1 << 29, + + /// The timer counter is reset upon timer E compare 1 event. + TimECmp1 = 1 << 28, + + /// The timer counter is reset upon timer C compare 4 event. + TimCCmp4 = 1 << 27, + + /// The timer counter is reset upon timer C compare 2 event. + TimCCmp2 = 1 << 26, + + /// The timer counter is reset upon timer C compare 1 event. + TimCCmp1 = 1 << 25, + + /// The timer counter is reset upon timer B compare 4 event. + TimBCmp4 = 1 << 24, + + /// The timer counter is reset upon timer B compare 2 event. + TimBCmp2 = 1 << 23, + + /// The timer counter is reset upon timer B compare 1 event. + TimBCmp1 = 1 << 22, + + /// The timer counter is reset upon timer A compare 4 event. + TimACmp4 = 1 << 21, + + /// The timer counter is reset upon timer A compare 2 event. + TimACmp2 = 1 << 20, + + /// The timer counter is reset upon timer A compare 1 event. + TimACmp1 = 1 << 19, + + /// The timer counter is reset upon timer F compare 1 event. + TimFCmp1 = 1 << 0, + } +); + +hr_timer_reset_event_source_common!( + /// E + pub enum TimerEResetEventSource { + [COMMON], + + /// The timer counter is reset upon timer F compare 2 event. + TimFCmp2 = 1 << 31, + + /// The timer counter is reset upon timer D compare 4 event. + TimDCmp4 = 1 << 30, + + /// The timer counter is reset upon timer D compare 2 event. + TimDCmp2 = 1 << 29, + + /// The timer counter is reset upon timer D compare 1 event. + TimDCmp1 = 1 << 28, + + /// The timer counter is reset upon timer C compare 4 event. + TimCCmp4 = 1 << 27, + + /// The timer counter is reset upon timer C compare 2 event. + TimCCmp2 = 1 << 26, + + /// The timer counter is reset upon timer C compare 1 event. + TimCCmp1 = 1 << 25, + + /// The timer counter is reset upon timer B compare 4 event. + TimBCmp4 = 1 << 24, + + /// The timer counter is reset upon timer B compare 2 event. + TimBCmp2 = 1 << 23, + + /// The timer counter is reset upon timer B compare 1 event. + TimBCmp1 = 1 << 22, + + /// The timer counter is reset upon timer A compare 4 event. + TimACmp4 = 1 << 21, + + /// The timer counter is reset upon timer A compare 2 event. + TimACmp2 = 1 << 20, + + /// The timer counter is reset upon timer A compare 1 event. + TimACmp1 = 1 << 19, + + + /// The timer counter is reset upon timer F compare 1 event. + TimFCmp1 = 1 << 0, + } +); + +hr_timer_reset_event_source_common!( + /// F + pub enum TimerFResetEventSource { + [COMMON], + + /// The timer counter is reset upon timer E compare 2 event. + TimECmp2 = 1 << 31, + + /// The timer counter is reset upon timer D compare 4 event. + TimDCmp4 = 1 << 30, + + /// The timer counter is reset upon timer D compare 2 event. + TimDCmp2 = 1 << 29, + + /// The timer counter is reset upon timer D compare 1 event. + TimDCmp1 = 1 << 28, + + /// The timer counter is reset upon timer C compare 4 event. + TimCCmp4 = 1 << 27, + + /// The timer counter is reset upon timer C compare 2 event. + TimCCmp2 = 1 << 26, + + /// The timer counter is reset upon timer C compare 1 event. + TimCCmp1 = 1 << 25, + + /// The timer counter is reset upon timer B compare 4 event. + TimBCmp4 = 1 << 24, + + /// The timer counter is reset upon timer B compare 2 event. + TimBCmp2 = 1 << 23, + + /// The timer counter is reset upon timer B compare 1 event. + TimBCmp1 = 1 << 22, + + /// The timer counter is reset upon timer A compare 4 event. + TimACmp4 = 1 << 21, + + /// The timer counter is reset upon timer A compare 2 event. + TimACmp2 = 1 << 20, + + /// The timer counter is reset upon timer A compare 1 event. + TimACmp1 = 1 << 19, + + /// The timer counter is reset upon timer E compare 1 event. + TimECmp1 = 1 << 0, + } +); + +pub unsafe trait ToHrOut { type Out; } -impl ToHrOut for (PA, PB) +unsafe impl ToHrOut for (PA, PB) where PA: ToHrOut, PB: ToHrOut, @@ -278,29 +759,48 @@ pub struct HrOut2(PhantomData); macro_rules! hrtim_finalize_body { ($this:expr, $PreloadSource:ident, $TIMX:ident: ( - $timXcr:ident, $ck_psc:ident, $perXr:ident, $perx:ident, $tXcen:ident $(, $fltXr:ident, $outXr:ident)*), + $timXcr:ident, $ck_psc:ident, $perXr:ident, $perx:ident, $tXcen:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident $(, $timXcr2:ident, $fltXr:ident, $outXr:ident)*), ) => {{ let tim = unsafe { &*$TIMX::ptr() }; let (period, prescaler_bits) = match $this.count { CountSettings::Period(period) => (period as u32, PSCL::BITS as u16), CountSettings::Frequency( freq ) => { - >::calculate_frequency($this.base_freq, freq, $this.alignment) + >::calculate_frequency($this.base_freq, freq, $this.counting_direction.into()) }, }; + let (half, intlvd) = match $this.interleaved_mode { + InterleavedMode::Disabled => (false, 0b00), + InterleavedMode::Dual => (true, 0b00), + InterleavedMode::Triple => (false, 0b01), + InterleavedMode::Quad => (false, 0b10), + }; + // Write prescaler and any special modes tim.$timXcr.modify(|_r, w| unsafe { w - // Enable Continous mode - .cont().set_bit() + // Enable Continuous mode + .cont().bit($this.timer_mode == HrTimerMode::Continuous) + .retrig().bit($this.timer_mode == HrTimerMode::SingleShotRetriggerable) // TODO: add support for more modes + // Interleaved mode + .intlvd().bits(intlvd) + + // half/double interleaved mode + .half().bit(half) + // Set prescaler .$ck_psc().bits(prescaler_bits as u8) }); $( + tim.$timXcr2.modify(|_r, w| unsafe { + // Set counting direction + w.udm().bit($this.counting_direction == HrCountingDirection::UpDown) + }); + // Only available for timers with outputs(not HRTIM_MASTER) let _ = tim.$outXr; tim.$timXcr.modify(|_r, w| @@ -339,6 +839,12 @@ macro_rules! hrtim_finalize_body { hrtim_finalize_body!($PreloadSource, $this, tim, $timXcr); + // Set repetition counter + unsafe { tim.$rep.write(|w| w.$repx().bits($this.repetition_counter)); } + + // Enable interrupts + tim.$dier.modify(|_r, w| w.$repie().bit($this.enable_repetition_interrupt)); + // Start timer let master = unsafe { &*HRTIM_MASTER::ptr() }; master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); @@ -356,6 +862,18 @@ macro_rules! hrtim_finalize_body { .preen().set_bit() ) }, + Some(PreloadSource::OnMasterTimerUpdate) => { + $tim.$timXcr.modify(|_r, w| w + .mstu().set_bit() + .preen().set_bit() + ) + } + Some(PreloadSource::OnRepetitionUpdate) => { + $tim.$timXcr.modify(|_r, w| w + .tx_repu().set_bit() + .preen().set_bit() + ) + } None => () } }}; @@ -392,14 +910,19 @@ macro_rules! hrtim_common_methods { _tim, _prescaler: _, _out, + timer_mode, fault_enable_bits, fault1_bits, fault2_bits, enable_push_pull, - alignment, + interleaved_mode, + counting_direction, base_freq, count, preload_source, + repetition_counter, + + enable_repetition_interrupt, } = self; let period = match count { @@ -413,18 +936,28 @@ macro_rules! hrtim_common_methods { _tim, _prescaler: PhantomData, _out, + timer_mode, fault_enable_bits, fault1_bits, fault2_bits, enable_push_pull, - alignment, + interleaved_mode, + counting_direction, base_freq, count, preload_source, + repetition_counter, //deadtime: 0.nanos(), + enable_repetition_interrupt, } } + 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); @@ -438,12 +971,26 @@ macro_rules! hrtim_common_methods { 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 + } }; } // Implement PWM configuration for timer macro_rules! hrtim_hal { - ($($TIMX:ident: ($timXcr:ident, $perXr:ident, $tXcen:ident, $fltXr:ident, $outXr:ident),)+) => { + ($($TIMX:ident: ($timXcr:ident, $timXcr2:ident, $perXr:ident, $tXcen:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident, $fltXr:ident, $outXr:ident),)+) => { $( // Implement HrPwmExt trait for hrtimer @@ -487,15 +1034,19 @@ macro_rules! hrtim_hal { _tim: PhantomData, _prescaler: PhantomData, _out: PhantomData, + timer_mode: HrTimerMode::Continuous, fault_enable_bits: 0b000000, fault1_bits: 0b00, fault2_bits: 0b00, - alignment: Alignment::Left, + 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: 0.nanos(), + enable_repetition_interrupt: false, } } } @@ -506,7 +1057,7 @@ macro_rules! hrtim_hal { PSCL: HrtimPrescaler, { pub fn finalize(self, _control: &mut HrPwmControl) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX>, HrCr2<$TIMX>, HrCr3<$TIMX>, HrCr4<$TIMX>), OUT) { - hrtim_finalize_body!(self, PreloadSource, $TIMX: ($timXcr, ck_pscx, $perXr, perx, $tXcen, $fltXr, $outXr),) + hrtim_finalize_body!(self, PreloadSource, $TIMX: ($timXcr, ck_pscx, $perXr, perx, $tXcen, $rep, $repx, $dier, $repie, $timXcr2, $fltXr, $outXr),) } hrtim_common_methods!($TIMX, PreloadSource); @@ -549,14 +1100,20 @@ macro_rules! hrtim_hal { /// /// 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 } - //pub fn half_mode(mut self, enable: bool) -> 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; - //pub fn interleaved_mode(mut self, mode: _) -> Self + self + } //pub fn swap_mode(mut self, enable: bool) -> Self } @@ -565,7 +1122,7 @@ macro_rules! hrtim_hal { } macro_rules! hrtim_hal_master { - ($($TIMX:ident: ($timXcr:ident, $ck_psc:ident, $perXr:ident, $perx:ident, $tXcen:ident),)+) => {$( + ($($TIMX:ident: ($timXcr:ident, $ck_psc:ident, $perXr:ident, $perx:ident, $rep:ident, $tXcen:ident, $dier:ident, $repie:ident),)+) => {$( impl HrPwmAdvExt for $TIMX { type PreloadSource = MasterPreloadSource; @@ -575,7 +1132,7 @@ macro_rules! hrtim_hal_master { rcc: &mut Rcc, ) -> HrPwmBuilder where - PINS: /*Pins +*/ ToHrOut, + PINS: Pins + ToHrOut, // TODO: figure out CHANNEL: HrtimChannel { // TODO: That 32x factor... Is that included below, or should we @@ -587,15 +1144,19 @@ macro_rules! hrtim_hal_master { _tim: PhantomData, _prescaler: PhantomData, _out: PhantomData, + timer_mode: HrTimerMode::Continuous, fault_enable_bits: 0b000000, fault1_bits: 0b00, fault2_bits: 0b00, - alignment: Alignment::Left, + 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: 0.nanos(), + enable_repetition_interrupt: false, } } } @@ -606,7 +1167,7 @@ macro_rules! hrtim_hal_master { PSCL: HrtimPrescaler, { pub fn finalize(self, _control: &mut HrPwmControl) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX>, HrCr2<$TIMX>, HrCr3<$TIMX>, HrCr4<$TIMX>)) { - hrtim_finalize_body!(self, MasterPreloadSource, $TIMX: ($timXcr, $ck_psc, $perXr, $perx, $tXcen),) + hrtim_finalize_body!(self, MasterPreloadSource, $TIMX: ($timXcr, $ck_psc, $perXr, $perx, $tXcen, $rep, $rep, $dier, $repie),) } hrtim_common_methods!($TIMX, MasterPreloadSource); @@ -817,7 +1378,7 @@ macro_rules! hrtim_cr { } macro_rules! hrtim_timer { - ($($TIMX:ident: $perXr:ident, $perx:ident,)+) => {$( + ($($TIMX:ident: $perXr:ident, $perx:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident, $icr:ident, $repc:ident, $([$rstXr:ident, $TimerXResetEventSource:ident],)*)+) => {$( impl HrTimer<$TIMX, PSCL> for HrTim<$TIMX, PSCL> { fn get_period(&self) -> u16 { let tim = unsafe { &*$TIMX::ptr() }; @@ -830,18 +1391,67 @@ macro_rules! hrtim_timer { tim.$perXr.write(|w| unsafe { w.$perx().bits(period as u16) }); } } + + impl HrTim<$TIMX, PSCL> { + $( + /// 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 + pub fn enable_reset_event(&mut self, set_event: $TimerXResetEventSource) { + let tim = unsafe { &*$TIMX::ptr() }; + + unsafe { tim.$rstXr.modify(|r, w| w.bits(r.bits() | set_event as u32)); } + } + + /// Stop listening to the specified event + pub fn disable_reset_event(&mut self, set_event: $TimerXResetEventSource) { + let tim = unsafe { &*$TIMX::ptr() }; + + unsafe { tim.$rstXr.modify(|r, w| w.bits(r.bits() & !(set_event as u32))); } + })* + + pub fn set_repetition_counter(&mut self, repetition_counter: u8) { + let tim = unsafe { &*$TIMX::ptr() }; + + unsafe { tim.$rep.write(|w| w.$repx().bits(repetition_counter)); } + } + + pub fn enable_repetition_interrupt(&mut self, enable: bool) { + let tim = unsafe { &*$TIMX::ptr() }; + + tim.$dier.modify(|_r, w| w.$repie().bit(enable)); + } + + pub fn clear_repetition_interrupt(&mut self) { + let tim = unsafe { &*$TIMX::ptr() }; + + tim.$icr.write(|w| w.$repc().set_bit()); + } + } )+}; } hrtim_timer! { - HRTIM_MASTER: mper, mper, - - HRTIM_TIMA: perar, perx, - HRTIM_TIMB: perbr, perx, - HRTIM_TIMC: percr, perx, - HRTIM_TIMD: perdr, perx, - HRTIM_TIME: perer, perx, - HRTIM_TIMF: perfr, perx, + HRTIM_MASTER: mper, mper, mrep, mrep, mdier, mrepie, micr, mrepc, + + HRTIM_TIMA: perar, perx, repar, repx, timadier, repie, timaicr, repc, [rstar, TimerAResetEventSource], + HRTIM_TIMB: perbr, perx, repbr, repx, timbdier, repie, timbicr, repc, [rstbr, TimerBResetEventSource], + HRTIM_TIMC: percr, perx, repcr, repx, timcdier, repie, timcicr, repc, [rstcr, TimerCResetEventSource], + HRTIM_TIMD: perdr, perx, repdr, repx, timddier, repie, timdicr, repc, [rstdr, TimerDResetEventSource], + HRTIM_TIME: perer, perx, reper, repx, timedier, repie, timeicr, repc, [rster, TimerEResetEventSource], + HRTIM_TIMF: perfr, perx, repfr, repx, timfdier, repie, timficr, repc, [rstfr, TimerFResetEventSource], } hrtim_cr! { @@ -856,16 +1466,16 @@ hrtim_cr! { } hrtim_hal! { - HRTIM_TIMA: (timacr, perar, tacen, fltar, outar), - HRTIM_TIMB: (timbcr, perbr, tbcen, fltbr, outbr), - HRTIM_TIMC: (timccr, percr, tccen, fltcr, outcr), - HRTIM_TIMD: (timdcr, perdr, tdcen, fltdr, outdr), - HRTIM_TIME: (timecr, perer, tecen, flter, outer), - HRTIM_TIMF: (timfcr, perfr, tfcen, fltfr, outfr), + HRTIM_TIMA: (timacr, timacr2, perar, tacen, repar, repx, timadier, repie, fltar, outar), + HRTIM_TIMB: (timbcr, timbcr2, perbr, tbcen, repbr, repx, timbdier, repie, fltbr, outbr), + HRTIM_TIMC: (timccr, timccr2, percr, tccen, repcr, repx, timcdier, repie, fltcr, outcr), + HRTIM_TIMD: (timdcr, timdcr2, perdr, tdcen, repdr, repx, timddier, repie, fltdr, outdr), + HRTIM_TIME: (timecr, timecr2, perer, tecen, reper, repx, timedier, repie, flter, outer), + HRTIM_TIMF: (timfcr, timfcr2, perfr, tfcen, repfr, repx, timfdier, repie, fltfr, outfr), } hrtim_hal_master! { - HRTIM_MASTER: (mcr, ck_psc, mper, mper, mcen), + HRTIM_MASTER: (mcr, ck_psc, mper, mper, mrep, mcen, mdier, mrepie), } hrtim_pin_hal! { @@ -888,7 +1498,7 @@ hrtim_pin_hal! { HRTIM_TIMF: (CH2, perfr, cmp3fr, cmp3x, cmp3, tf2oen, tf2odis), } -pub trait HrtimPrescaler { +pub unsafe trait HrtimPrescaler { const BITS: u8; const VALUE: u8; @@ -905,7 +1515,7 @@ macro_rules! impl_pscl { ($($t:ident => $b:literal, $v:literal, $min:literal, $max:literal)+) => {$( #[derive(Copy, Clone, Default)] pub struct $t; - impl HrtimPrescaler for $t { + unsafe impl HrtimPrescaler for $t { const BITS: u8 = $b; const VALUE: u8 = $v; const MIN_CR: u16 = $min; @@ -966,7 +1576,7 @@ pub enum FaultAction { Floating = 0b11, } -pub trait FaultSource: Copy { +pub unsafe trait FaultSource: Copy { const ENABLE_BITS: u8; } @@ -1071,7 +1681,7 @@ macro_rules! impl_faults { } } - impl FaultSource for $source { + unsafe impl FaultSource for $source { const ENABLE_BITS: u8 = $enable_bits; } )+} @@ -1627,52 +2237,52 @@ impl HrTimOngoingCalibration { unsafe { self.init() } } - pub fn set_adc_trigger1(mut self, trigger: Adc13Trigger) -> Self { + pub fn enable_adc_trigger1_source(mut self, trigger: Adc13Trigger) -> Self { self.adc_trigger1_bits |= trigger as u32; self } - pub fn set_adc_trigger2(mut self, trigger: Adc24Trigger) -> Self { + pub fn enable_adc_trigger2_source(mut self, trigger: Adc24Trigger) -> Self { self.adc_trigger2_bits |= trigger as u32; self } - pub fn set_adc_trigger3(mut self, trigger: Adc13Trigger) -> Self { + pub fn enable_adc_trigger3_source(mut self, trigger: Adc13Trigger) -> Self { self.adc_trigger3_bits |= trigger as u32; self } - pub fn set_adc_trigger4(mut self, trigger: Adc24Trigger) -> Self { + pub fn enable_adc_trigger4_source(mut self, trigger: Adc24Trigger) -> Self { self.adc_trigger4_bits |= trigger as u32; self } - pub fn set_adc_trigger5(mut self, trigger: Adc579Trigger) -> Self { + pub fn enable_adc_trigger5_source(mut self, trigger: Adc579Trigger) -> Self { self.adc_trigger5_bits = trigger as u8; self } - pub fn set_adc_trigger6(mut self, trigger: Adc6810Trigger) -> Self { + pub fn enable_adc_trigger6_source(mut self, trigger: Adc6810Trigger) -> Self { self.adc_trigger6_bits = trigger as u8; self } - pub fn set_adc_trigger7(mut self, trigger: Adc579Trigger) -> Self { + pub fn enable_adc_trigger7_source(mut self, trigger: Adc579Trigger) -> Self { self.adc_trigger7_bits = trigger as u8; self } - pub fn set_adc_trigger8(mut self, trigger: Adc6810Trigger) -> Self { + pub fn enable_adc_trigger8_source(mut self, trigger: Adc6810Trigger) -> Self { self.adc_trigger8_bits = trigger as u8; self } - pub fn set_adc_trigger9(mut self, trigger: Adc579Trigger) -> Self { + pub fn enable_adc_trigger9_source(mut self, trigger: Adc579Trigger) -> Self { self.adc_trigger9_bits = trigger as u8; self } - pub fn set_adc_trigger10(mut self, trigger: Adc6810Trigger) -> Self { + pub fn enable_adc_trigger10_source(mut self, trigger: Adc6810Trigger) -> Self { self.adc_trigger10_bits = trigger as u8; self } From d426e521af0eae0df5b0da190ca501a66aa093a4 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 24 Oct 2023 10:32:19 +0200 Subject: [PATCH 33/88] Multiple hrtim changes * Add output polarity * Add counting direction * Do not start timer directly when created, helps when used as AD trigger * Add methods for starting/stopping timers * Add some adc triggers --- src/pwm/hrtim.rs | 140 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 110 insertions(+), 30 deletions(-) diff --git a/src/pwm/hrtim.rs b/src/pwm/hrtim.rs index 2c1d588c..90354cc0 100644 --- a/src/pwm/hrtim.rs +++ b/src/pwm/hrtim.rs @@ -15,8 +15,8 @@ use crate::stm32::{ }; use super::{ - ActiveHigh, Alignment, ComplementaryImpossible, FaultMonitor, Pins, Pwm, PwmPinEnable, - TimerType, + ActiveHigh, Alignment, ComplementaryImpossible, FaultMonitor, Pins, Polarity, Pwm, + PwmPinEnable, TimerType, }; use crate::rcc::{Enable, GetBusFreq, Rcc, Reset}; use crate::stm32::RCC; @@ -267,6 +267,8 @@ pub struct HrPwmBuilder { repetition_counter: u8, //deadtime: NanoSecond, enable_repetition_interrupt: bool, + out1_polarity: Polarity, + out2_polarity: Polarity, } pub enum PreloadSource { @@ -310,6 +312,15 @@ pub trait HrTimer { /// /// NOTE: This will affect the maximum duty usable for `HrCompareRegister::set_duty` fn set_period(&mut self, period: u16); + + /// Start timer + fn start(&mut self, _hr_control: &mut HrPwmControl); + + /// Stop timer + fn stop(&mut self, _hr_control: &mut HrPwmControl); + + /// Stop timer and reset counter + fn stop_and_reset(&mut self, _hr_control: &mut HrPwmControl); } pub trait HrOutput { @@ -796,10 +807,10 @@ macro_rules! hrtim_finalize_body { }); $( - tim.$timXcr2.modify(|_r, w| unsafe { + tim.$timXcr2.modify(|_r, w| // Set counting direction w.udm().bit($this.counting_direction == HrCountingDirection::UpDown) - }); + ); // Only available for timers with outputs(not HRTIM_MASTER) let _ = tim.$outXr; @@ -829,10 +840,14 @@ macro_rules! hrtim_finalize_body { // ... and lock configuration tim.$fltXr.modify(|_r, w| w.fltlck().set_bit()); - // Set actions on fault for both outputs tim.$outXr.modify(|_r, w| w + // Set actions on fault for both outputs .fault1().bits($this.fault1_bits) .fault2().bits($this.fault2_bits) + + // Set output polarity for both outputs + .pol1().bit($this.out1_polarity == Polarity::ActiveLow) + .pol2().bit($this.out2_polarity == Polarity::ActiveLow) ); })* @@ -846,8 +861,8 @@ macro_rules! hrtim_finalize_body { tim.$dier.modify(|_r, w| w.$repie().bit($this.enable_repetition_interrupt)); // Start timer - let master = unsafe { &*HRTIM_MASTER::ptr() }; - master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); + //let master = unsafe { &*HRTIM_MASTER::ptr() }; + //master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); unsafe { MaybeUninit::uninit().assume_init() @@ -923,6 +938,8 @@ macro_rules! hrtim_common_methods { repetition_counter, enable_repetition_interrupt, + out1_polarity, + out2_polarity, } = self; let period = match count { @@ -949,6 +966,8 @@ macro_rules! hrtim_common_methods { repetition_counter, //deadtime: 0.nanos(), enable_repetition_interrupt, + out1_polarity, + out2_polarity, } } @@ -1047,6 +1066,8 @@ macro_rules! hrtim_hal { repetition_counter: 0, //deadtime: 0.nanos(), enable_repetition_interrupt: false, + out1_polarity: Polarity::ActiveHigh, + out2_polarity: Polarity::ActiveHigh, } } } @@ -1082,6 +1103,18 @@ macro_rules! hrtim_hal { 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 @@ -1106,6 +1139,15 @@ macro_rules! hrtim_hal { self } + /// 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 @@ -1157,6 +1199,8 @@ macro_rules! hrtim_hal_master { repetition_counter: 0, //deadtime: 0.nanos(), enable_repetition_interrupt: false, + out1_polarity: Polarity::ActiveHigh, + out2_polarity: Polarity::ActiveHigh, } } } @@ -1220,7 +1264,7 @@ macro_rules! hrtim_pin_hal { /// Set duty cycle /// - /// NOTE: Please observe limits: + /// NOTE: Please observe limits(RM0440 "Period and compare registers min and max values"): /// | Prescaler | Min duty | Max duty | /// |-----------|----------|----------| /// | 1 | 0x0060 | 0xFFDF | @@ -1232,7 +1276,12 @@ macro_rules! hrtim_pin_hal { /// | 64 | 0x0003 | 0xFFFD | /// | 128 | 0x0003 | 0xFFFD | /// - /// Also, writing 0 as duty is only valid for CR1 and CR3 + /// Also, writing 0 as duty is only valid for CR1 and CR3 during a set of + /// specific conditions(see RM0440 "Null duty cycle exception case"): + /// – the output SET event is generated by the PERIOD event + /// – the output RESET if generated by the compare 1 (respectively compare 3) event + /// – the compare 1 (compare 3) event is active within the timer unit itself, and not used + /// for other timing units fn set_duty(&mut self, duty: Self::Duty) { let tim = unsafe { &*$TIMX::ptr() }; @@ -1378,7 +1427,7 @@ macro_rules! hrtim_cr { } macro_rules! hrtim_timer { - ($($TIMX:ident: $perXr:ident, $perx:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident, $icr:ident, $repc:ident, $([$rstXr:ident, $TimerXResetEventSource:ident],)*)+) => {$( + ($($TIMX:ident: $cntXr:ident, $cntx:ident, $perXr:ident, $tXcen:ident, $perx:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident, $icr:ident, $repc:ident, $([$rstXr:ident, $TimerXResetEventSource:ident],)*)+) => {$( impl HrTimer<$TIMX, PSCL> for HrTim<$TIMX, PSCL> { fn get_period(&self) -> u16 { let tim = unsafe { &*$TIMX::ptr() }; @@ -1390,6 +1439,32 @@ macro_rules! hrtim_timer { tim.$perXr.write(|w| unsafe { w.$perx().bits(period as u16) }); } + + /// Start timer + fn start(&mut self, _hr_control: &mut HrPwmControl) { + // Start timer + + // SAFETY: Since we hold _hr_control there is no risk for a race condition + let master = unsafe { &*HRTIM_MASTER::ptr() }; + master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); + } + + /// Stop timer + fn stop(&mut self, _hr_control: &mut HrPwmControl) { + // Stop counter + // SAFETY: Since we hold _hr_control there is no risk for a race condition + let master = unsafe { &*HRTIM_MASTER::ptr() }; + master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); + } + + /// Stop timer and reset counter + fn stop_and_reset(&mut self, _hr_control: &mut HrPwmControl) { + self.stop(_hr_control); + + // Reset counter + let tim = unsafe { &*$TIMX::ptr() }; + unsafe { tim.$cntXr.write(|w| w.$cntx().bits(0)); } + } } impl HrTim<$TIMX, PSCL> { @@ -1444,14 +1519,14 @@ macro_rules! hrtim_timer { } hrtim_timer! { - HRTIM_MASTER: mper, mper, mrep, mrep, mdier, mrepie, micr, mrepc, + HRTIM_MASTER: mcntr, mcnt, mper, mcen, mper, mrep, mrep, mdier, mrepie, micr, mrepc, - HRTIM_TIMA: perar, perx, repar, repx, timadier, repie, timaicr, repc, [rstar, TimerAResetEventSource], - HRTIM_TIMB: perbr, perx, repbr, repx, timbdier, repie, timbicr, repc, [rstbr, TimerBResetEventSource], - HRTIM_TIMC: percr, perx, repcr, repx, timcdier, repie, timcicr, repc, [rstcr, TimerCResetEventSource], - HRTIM_TIMD: perdr, perx, repdr, repx, timddier, repie, timdicr, repc, [rstdr, TimerDResetEventSource], - HRTIM_TIME: perer, perx, reper, repx, timedier, repie, timeicr, repc, [rster, TimerEResetEventSource], - HRTIM_TIMF: perfr, perx, repfr, repx, timfdier, repie, timficr, repc, [rstfr, TimerFResetEventSource], + HRTIM_TIMA: cntar, cntx, perar, tacen, perx, repar, repx, timadier, repie, timaicr, repc, [rstar, TimerAResetEventSource], + HRTIM_TIMB: cntr, cntx, perbr, tbcen, perx, repbr, repx, timbdier, repie, timbicr, repc, [rstbr, TimerBResetEventSource], + HRTIM_TIMC: cntcr, cntx, percr, tccen, perx, repcr, repx, timcdier, repie, timcicr, repc, [rstcr, TimerCResetEventSource], + HRTIM_TIMD: cntdr, cntx, perdr, tdcen, perx, repdr, repx, timddier, repie, timdicr, repc, [rstdr, TimerDResetEventSource], + HRTIM_TIME: cnter, cntx, perer, tecen, perx, reper, repx, timedier, repie, timeicr, repc, [rster, TimerEResetEventSource], + HRTIM_TIMF: cntfr, cntx, perfr, tfcen, perx, repfr, repx, timfdier, repie, timficr, repc, [rstfr, TimerFResetEventSource], } hrtim_cr! { @@ -1498,7 +1573,7 @@ hrtim_pin_hal! { HRTIM_TIMF: (CH2, perfr, cmp3fr, cmp3x, cmp3, tf2oen, tf2odis), } -pub unsafe trait HrtimPrescaler { +pub unsafe trait HrtimPrescaler: Default { const BITS: u8; const VALUE: u8; @@ -2325,8 +2400,9 @@ pub enum Adc13Trigger { /// bit 29 ADCxTEC3 - Trigger on HRTIM_TIME compare match for compare register 3 TimECmp3 = 1 << 29, - // /// bit 28 ADCxTFRST - // _ = 1 << 28, + /// bit 28 ADCxTFRST - Trigger on HRTIM_TIMF reset or counter roll-over + TimFRst = 1 << 28, + /// bit 27 ADCxTDPER - Trigger on HRTIM_TIMD period TimDPeriod = 1 << 27, @@ -2351,8 +2427,9 @@ pub enum Adc13Trigger { /// bit 20 ADCxTFC4 - Trigger on HRTIM_TIMF compare match for compare register 4 TimFCmp4 = 1 << 20, - // /// bit 19 ADCxTBRST - // _ = 1 << 19, + /// bit 19 ADCxTBRST - Trigger on HRTIM_TIMB reset or counter roll-over + TimBRst = 1 << 19, + /// bit 18 ADCxTBPER - Trigger on HRTIM_TIMB period TimBPeriod = 1 << 18, @@ -2365,8 +2442,9 @@ pub enum Adc13Trigger { /// bit 15 ADCxTFC3 - Trigger on HRTIM_TIMF compare match for compare register 3 TimFCmp3 = 1 << 15, - // /// bit 14 ADCxTARST - // _ = 1 << 14, + /// bit 14 ADCxTARST - Trigger on HRTIM_TIMA reset or counter roll-over + TimARst = 1 << 14, + /// bit 13 ADCxTAPER - Trigger on HRTIM_TIMA period TimAPeriod = 1 << 13, @@ -2445,8 +2523,9 @@ pub enum AdcTriggerPostscaler { } pub enum Adc24Trigger { - // /// bit 31 ADCxTERST - // _ = 1 << 31, + /// bit 31 ADCxTERST - Trigger on HRTIM_TIME reset or counter roll-over + TimERst = 1 << 31, + /// bit 30 ADCxTEC4 - Trigger on HRTIM_TIME compare match for compare register 4 TimECmp4 = 1 << 30, @@ -2456,8 +2535,9 @@ pub enum Adc24Trigger { /// bit 28 ADCxTEC2 - Trigger on HRTIM_TIME compare match for compare register 2 TimECmp2 = 1 << 28, - // /// bit 27 ADCxTDRST - // _ = 1 << 27, + /// bit 27 ADCxTDRST - Trigger on HRTIM_TIMD reset or counter roll-over + TimDRst = 1 << 27, + /// bit 26 ADCxTDPER - Trigger on HRTIM_TIMD period TimDPeriod = 1 << 26, @@ -2470,8 +2550,8 @@ pub enum Adc24Trigger { /// bit 23 ADCxTDC2 - Trigger on HRTIM_TIMD compare match for compare register 2 TimDCmp2 = 1 << 23, - /// bit 22 ADCxTCRST - // _ = 1 << 22, + /// bit 22 ADCxTCRST - Trigger on HRTIM_TIMC reset or counter roll-over + TimCRst = 1 << 22, /// bit 21 ADCxTCPER - Trigger on HRTIM_TIMC period TimCPeriod = 1 << 21, From 41e8774b4f80b0f53617f35ad94b7755c8e32aa9 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 24 Oct 2023 17:36:54 +0200 Subject: [PATCH 34/88] HRTIM: Fix bad pin mapping --- src/pwm/hrtim.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pwm/hrtim.rs b/src/pwm/hrtim.rs index 90354cc0..44f29a96 100644 --- a/src/pwm/hrtim.rs +++ b/src/pwm/hrtim.rs @@ -168,7 +168,7 @@ pins! { HRTIM_TIMA: CH1: PA8>, CH2: PA9> HRTIM_TIMB: CH1: PA10>, CH2: PA11> - HRTIM_TIMC: CH1: PA12>, CH2: PA13> + HRTIM_TIMC: CH1: PB12>, CH2: PB13> HRTIM_TIMD: CH1: PB14>, CH2: PB15> HRTIM_TIME: CH1: PC8>, CH2: PC9> From 982524a2fafa3f03795ecc7b406f7dceae030915 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 24 Oct 2023 17:46:47 +0200 Subject: [PATCH 35/88] HRTIM - Rework EventSource system and add deadtime support * One does no longer specify an EventSource variant manually, instead the user can pass the actual object that will emit the signal. For example pass a reference to HrCr1 to output.enable_reset_event to make output listen to HrCr1 * Added support for deadtime --- src/pwm/hrtim.rs | 494 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 419 insertions(+), 75 deletions(-) diff --git a/src/pwm/hrtim.rs b/src/pwm/hrtim.rs index 44f29a96..61689ed4 100644 --- a/src/pwm/hrtim.rs +++ b/src/pwm/hrtim.rs @@ -4,8 +4,8 @@ use core::mem::MaybeUninit; use fugit::HertzU64; use crate::comparator::{COMP1, COMP2, COMP3, COMP4, COMP5, COMP6}; -use crate::gpio::gpioa::{PA10, PA11, PA12, PA13, PA15, PA8, PA9}; -use crate::gpio::gpiob::{PB0, PB10, PB11, PB14, PB15}; +use crate::gpio::gpioa::{PA10, PA11, PA12, PA15, PA8, PA9}; +use crate::gpio::gpiob::{PB0, PB10, PB11, PB12, PB13, PB14, PB15}; use crate::gpio::gpioc::{PC10, PC6, PC7, PC8, PC9}; use crate::gpio::{self, AF3}; use crate::gpio::{Alternate, AF13}; @@ -154,11 +154,19 @@ macro_rules! pins { } unsafe impl ToHrOut for $CH1 { - type Out = HrOut1<$TIMX>; + type Out = HrOut1<$TIMX, PSCL>; } unsafe impl ToHrOut for $CH2 { - type Out = HrOut2<$TIMX>; + type Out = HrOut2<$TIMX, PSCL>; + } + + unsafe impl ToHrOut for HrOut1<$TIMX, PSCL> { + type Out

= HrOut1<$TIMX, P>; + } + + unsafe impl ToHrOut for HrOut2<$TIMX, PSCL> { + type Out

= HrOut2<$TIMX, P>; } )+ } @@ -180,7 +188,7 @@ impl Pins for () { } unsafe impl ToHrOut for () { - type Out = (); + type Out = (); } // automatically implement Pins trait for tuples of individual pins @@ -243,7 +251,7 @@ pub trait HrPwmAdvExt: Sized { self, _pins: PINS, rcc: &mut Rcc, - ) -> HrPwmBuilder + ) -> HrPwmBuilder> where PINS: Pins + ToHrOut, CHANNEL: HrtimChannel; @@ -265,7 +273,7 @@ pub struct HrPwmBuilder { enable_push_pull: bool, interleaved_mode: InterleavedMode, // Also includes half mode repetition_counter: u8, - //deadtime: NanoSecond, + deadtime: Option, enable_repetition_interrupt: bool, out1_polarity: Polarity, out2_polarity: Polarity, @@ -282,6 +290,86 @@ pub enum PreloadSource { OnRepetitionUpdate, } +#[derive(Copy, Clone, Debug)] +pub struct DeadtimeConfig { + /// Prescaler for both rising and falling deadtime + prescaler: DeadtimePrescaler, + + /// 9-bits + deadtime_rising_value: u16, + + /// Is deadtime negative + deadtime_rising_sign: bool, + + /// 9-bits + deadtime_falling_value: u16, + + /// Is deadtime negative + deadtime_falling_sign: bool, +} + +impl DeadtimeConfig { + /// See RM0440 Table 221 'Deadtime resolution and max absolute values' + pub fn prescaler(mut self, value: DeadtimePrescaler) -> Self { + self.prescaler = value; + self + } + + /// Panic if value can not fit in 9 bits + pub fn deadtime_rising_value(mut self, value: u16) -> Self { + // 9 bits + assert!(value < (1 << 9)); + + self.deadtime_rising_value = value; + + self + } + + pub fn deadtime_rising_sign(mut self, is_negative: bool) -> Self { + self.deadtime_rising_sign = is_negative; + self + } + + /// Panic if value can not fit in 9 bits + pub fn deadtime_falling_value(mut self, value: u16) -> Self { + // 9 bits + assert!(value < (1 << 9)); + + self.deadtime_falling_value = value; + + self + } + + pub fn deadtime_falling_sign(mut self, is_negative: bool) -> Self { + self.deadtime_falling_sign = is_negative; + self + } +} + +impl Default for DeadtimeConfig { + fn default() -> Self { + Self { + prescaler: DeadtimePrescaler::Thrtim, + deadtime_rising_value: 170, // about 1us when f_sys = 170MHz + deadtime_rising_sign: false, + deadtime_falling_value: 170, // about 1us when f_sys = 170MHz + deadtime_falling_sign: false, + } + } +} + +#[derive(Copy, Clone, Debug)] +pub enum DeadtimePrescaler { + ThrtimDiv8 = 0b000, + ThrtimDiv4 = 0b001, + ThrtimDiv2 = 0b010, + Thrtim = 0b011, + ThrtimMul2 = 0b100, + ThrtimMul4 = 0b101, + ThrtimMul8 = 0b110, + ThrtimMul16 = 0b111, +} + pub enum MasterPreloadSource { /// Prealoaded registers are updaten when the master counter rolls over and the master repetition counter is 0 OnMasterRepetitionUpdate, @@ -292,10 +380,10 @@ pub trait HrCompareRegister { fn set_duty(&mut self, duty: u16); } -pub struct HrCr1(PhantomData); -pub struct HrCr2(PhantomData); -pub struct HrCr3(PhantomData); -pub struct HrCr4(PhantomData); +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 HrTim { _timer: PhantomData, @@ -323,7 +411,126 @@ pub trait HrTimer { fn stop_and_reset(&mut self, _hr_control: &mut HrPwmControl); } -pub trait HrOutput { +macro_rules! impl_into_es { + ($dst:ident: [$(($t:ty, $ES:ident),)*]) => {$( + impl_into_es!($dst, $t, $ES); + )*}; + + ($dst:ident, $t:ty, $ES:ident) => { + impl Into> for &$t { + fn into(self) -> EventSource { + EventSource::$ES(PhantomData) + } + } + }; + ($dst:ident) => { + impl_into_es! { + $dst: [ + (HrCr1<$dst, PSCL>, Cr1), + (HrCr2<$dst, PSCL>, Cr2), + (HrCr3<$dst, PSCL>, Cr3), + (HrCr4<$dst, PSCL>, Cr4), + (HrTim<$dst, PSCL>, Period), + + (HrCr1, MasterCr1), + (HrCr2, MasterCr2), + (HrCr3, MasterCr3), + (HrCr4, MasterCr4), + (HrTim, MasterPeriod), + ] + } + }; +} + +impl_into_es!(HRTIM_TIMA); +impl_into_es!(HRTIM_TIMB); +impl_into_es!(HRTIM_TIMC); +impl_into_es!(HRTIM_TIMD); +impl_into_es!(HRTIM_TIME); +impl_into_es!(HRTIM_TIMF); + +macro_rules! impl_into_neighbor_es { + ( + DST: $dst:ident: [ + ($src1:ident, $cr1:ident), + ($src2:ident, $cr2:ident), + ($src3:ident, $cr3:ident), + ($src4:ident, $cr4:ident), + ($src5:ident, $cr5:ident), + ($src6:ident, $cr6:ident), + ($src7:ident, $cr7:ident), + ($src8:ident, $cr8:ident), + ($src9:ident, $cr9:ident), + ] + ) => { + impl_into_neighbor_es!($dst, $src1, $cr1, TimEvent1); + impl_into_neighbor_es!($dst, $src2, $cr2, TimEvent2); + impl_into_neighbor_es!($dst, $src3, $cr3, TimEvent3); + impl_into_neighbor_es!($dst, $src4, $cr4, TimEvent4); + impl_into_neighbor_es!($dst, $src5, $cr5, TimEvent5); + impl_into_neighbor_es!($dst, $src6, $cr6, TimEvent6); + impl_into_neighbor_es!($dst, $src7, $cr7, TimEvent7); + impl_into_neighbor_es!($dst, $src8, $cr8, TimEvent8); + impl_into_neighbor_es!($dst, $src9, $cr9, TimEvent9); + }; + + ($dst:ident, $src:ident, $cr:ident, $TimEventX:ident) => { + impl Into> for &$cr<$src, PSCL> { + fn into(self) -> EventSource { + EventSource::NeighborTimer(NeighborTimerEventSource::$TimEventX(PhantomData)) + } + } + }; +} + +impl_into_neighbor_es! { + DST: HRTIM_TIMA: [ + // src + (HRTIM_TIMB, HrCr1), + (HRTIM_TIMB, HrCr2), + (HRTIM_TIMC, HrCr2), + (HRTIM_TIMC, HrCr3), + (HRTIM_TIMD, HrCr1), + (HRTIM_TIMD, HrCr2), + (HRTIM_TIME, HrCr3), + (HRTIM_TIME, HrCr4), + (HRTIM_TIMF, HrCr4), + ] +} + +impl_into_neighbor_es! { + DST: HRTIM_TIMB: [ + // src + (HRTIM_TIMA, HrCr1), + (HRTIM_TIMA, HrCr2), + (HRTIM_TIMC, HrCr3), + (HRTIM_TIMC, HrCr4), + (HRTIM_TIMD, HrCr3), + (HRTIM_TIMD, HrCr4), + (HRTIM_TIME, HrCr1), + (HRTIM_TIME, HrCr2), + (HRTIM_TIMF, HrCr3), + ] +} + +impl_into_neighbor_es! { + DST: HRTIM_TIMC: [ + // src + (HRTIM_TIMA, HrCr2), + (HRTIM_TIMA, HrCr3), + (HRTIM_TIMB, HrCr2), + (HRTIM_TIMB, HrCr3), + (HRTIM_TIMD, HrCr2), + (HRTIM_TIMD, HrCr4), + (HRTIM_TIME, HrCr3), + (HRTIM_TIME, HrCr4), + (HRTIM_TIMF, HrCr2), + ] +} + +// TODO: Continue for TIMD, TIME and TIMF, see RM0440 Table 218. 'Events mapping across timer A to F' + +pub trait HrOutput { /// Enable this output fn enable(&mut self); @@ -334,19 +541,19 @@ pub trait HrOutput { /// /// NOTE: Enabling the same event for both SET and RESET /// will make that event TOGGLE the output - fn enable_set_event(&mut self, set_event: EventSource); + fn enable_set_event(&mut self, set_event: impl Into>); /// Stop listening to the specified event - fn disable_set_event(&mut self, set_event: EventSource); + fn disable_set_event(&mut self, set_event: impl Into>); /// Set this output to *not* active every time the specified event occurs /// /// NOTE: Enabling the same event for both SET and RESET /// will make that event TOGGLE the output - fn enable_rst_event(&mut self, reset_event: EventSource); + fn enable_rst_event(&mut self, reset_event: impl Into>); /// Stop listening to the specified event - fn disable_rst_event(&mut self, reset_event: EventSource); + fn disable_rst_event(&mut self, reset_event: impl Into>); /// Get current state of the output fn get_state(&self) -> State; @@ -360,38 +567,115 @@ pub enum State { Fault, } -pub enum EventSource { +pub enum EventSource { /// Compare match with compare register 1 of this timer - Cr1, + Cr1(PhantomData<(PSCL, DST)>), /// Compare match with compare register 2 of this timer - Cr2, + Cr2(PhantomData<(PSCL, DST)>), /// Compare match with compare register 3 of this timer - Cr3, + Cr3(PhantomData<(PSCL, DST)>), /// Compare match with compare register 4 of this timer - Cr4, + Cr4(PhantomData<(PSCL, DST)>), /// On complete period - Period, + Period(PhantomData<(PSCL, DST)>), /// Compare match with compare register 1 of master timer - MasterCr1, + MasterCr1(PhantomData<(PSCL, DST)>), /// Compare match with compare register 2 of master timer - MasterCr2, + MasterCr2(PhantomData<(PSCL, DST)>), /// Compare match with compare register 3 of master timer - MasterCr3, + MasterCr3(PhantomData<(PSCL, DST)>), /// Compare match with compare register 4 of master timer - MasterCr4, + MasterCr4(PhantomData<(PSCL, DST)>), /// On complete master period - MasterPeriod, - // TODO: These are unique for every timer output - //Extra(E) + MasterPeriod(PhantomData<(PSCL, DST)>), + + NeighborTimer(NeighborTimerEventSource), +} + +/// Compare events from neighbor timers +/// +/// See RM0440 Table 218. 'Events mapping across timer A to F' +pub enum NeighborTimerEventSource { + /// Timer event 1 + /// + /// This is different depending on destination timer: + /// |dest | source | + /// |-----|--------| + /// |TimA | B CR1 | + /// |TimB | A CR1 | + /// |TimC | A CR2 | + /// |TimD | A CR1 | + /// |TimE | A CR4 | + /// |TimF | A CR3 | + TimEvent1(PhantomData<(PSCL, DST)>), + + /// Timer event x + /// + /// This is different depending on destination timer: + /// |dest | source | + /// |-----|--------| + /// |TimA | x CRy | + /// |TimB | x CRy | + /// |TimC | x CRy | + /// |TimD | x CRy | + /// |TimE | x CRy | + /// |TimF | x CRy | + //TimEventx, + + /// Timer event 2 + /// + /// This is different depending on destination timer: + /// |dest | source | + /// |-----|--------| + /// |TimA | B CR2 | + /// |TimB | A CR2 | + /// |TimC | A CR3 | + /// |TimD | A CR4 | + /// |TimE | B CR3 | + /// |TimF | B CR1 | + TimEvent2(PhantomData<(PSCL, DST)>), + + /// Timer event 3 + /// + /// This is different depending on destination timer: + /// |dest | source | + /// |-----|--------| + /// |TimA | C CR2 | + /// |TimB | C CR3 | + /// |TimC | B CR2 | + /// |TimD | B CR2 | + /// |TimE | B CR4 | + /// |TimF | B CR4 | + TimEvent3(PhantomData<(PSCL, DST)>), + + /// Timer event 4 + /// + /// This is different depending on destination timer: + /// |dest | source | + /// |-----|--------| + /// |TimA | C CR3 | + /// |TimB | C CR4 | + /// |TimC | B CR3 | + /// |TimD | B CR4 | + /// |TimE | C CR1 | + /// |TimF | C CR1 | + TimEvent4(PhantomData<(PSCL, DST)>), + + // TODO: Document those + TimEvent5(PhantomData<(PSCL, DST)>), + TimEvent6(PhantomData<(PSCL, DST)>), + TimEvent7(PhantomData<(PSCL, DST)>), + TimEvent8(PhantomData<(PSCL, DST)>), + TimEvent9(PhantomData<(PSCL, DST)>), } macro_rules! hr_timer_reset_event_source_common { @@ -754,7 +1038,7 @@ hr_timer_reset_event_source_common!( ); pub unsafe trait ToHrOut { - type Out; + type Out: ToHrOut; } unsafe impl ToHrOut for (PA, PB) @@ -762,15 +1046,15 @@ where PA: ToHrOut, PB: ToHrOut, { - type Out = (PA::Out, PB::Out); + type Out = (PA::Out, PB::Out); } -pub struct HrOut1(PhantomData); -pub struct HrOut2(PhantomData); +pub struct HrOut1(PhantomData<(TIM, PSCL)>); +pub struct HrOut2(PhantomData<(TIM, PSCL)>); macro_rules! hrtim_finalize_body { ($this:expr, $PreloadSource:ident, $TIMX:ident: ( - $timXcr:ident, $ck_psc:ident, $perXr:ident, $perx:ident, $tXcen:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident $(, $timXcr2:ident, $fltXr:ident, $outXr:ident)*), + $timXcr:ident, $ck_psc:ident, $perXr:ident, $perx:ident, $tXcen:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident $(, $timXcr2:ident, $fltXr:ident, $outXr:ident, $dtXr:ident)*), ) => {{ let tim = unsafe { &*$TIMX::ptr() }; let (period, prescaler_bits) = match $this.count { @@ -824,7 +1108,6 @@ macro_rules! hrtim_finalize_body { tim.$perXr.write(|w| unsafe { w.$perx().bits(period as u16) }); // Enable fault sources and lock configuration - $(unsafe { // Enable fault sources let fault_enable_bits = $this.fault_enable_bits as u32; @@ -849,6 +1132,26 @@ macro_rules! hrtim_finalize_body { .pol1().bit($this.out1_polarity == Polarity::ActiveLow) .pol2().bit($this.out2_polarity == Polarity::ActiveLow) ); + if let Some(deadtime) = $this.deadtime { + let DeadtimeConfig { + prescaler, + deadtime_rising_value, + deadtime_rising_sign, + deadtime_falling_value, + deadtime_falling_sign, + } = deadtime; + + // SAFETY: DeadtimeConfig makes sure rising and falling values are valid + // and DeadtimePrescaler has its own garantuee + tim.$dtXr.modify(|_r, w| w + .dtprsc().bits(prescaler as u8) + .dtrx().bits(deadtime_rising_value) + .sdtrx().bit(deadtime_rising_sign) + .dtfx().bits(deadtime_falling_value) + .sdtfx().bit(deadtime_falling_sign) + ); + tim.$outXr.modify(|_r, w| w.dten().set_bit()); + } })* @@ -917,7 +1220,10 @@ macro_rules! hrtim_common_methods { } /// Set the prescaler; PWM count runs at base_frequency/(prescaler+1) - pub fn prescaler

(self, _prescaler: P) -> HrPwmBuilder<$TIMX, P, $PS, OUT> + pub fn prescaler

( + self, + _prescaler: P, + ) -> HrPwmBuilder<$TIMX, P, $PS, ::Out

> where P: HrtimPrescaler, { @@ -936,7 +1242,7 @@ macro_rules! hrtim_common_methods { count, preload_source, repetition_counter, - + deadtime, enable_repetition_interrupt, out1_polarity, out2_polarity, @@ -952,7 +1258,7 @@ macro_rules! hrtim_common_methods { HrPwmBuilder { _tim, _prescaler: PhantomData, - _out, + _out: PhantomData, timer_mode, fault_enable_bits, fault1_bits, @@ -964,7 +1270,7 @@ macro_rules! hrtim_common_methods { count, preload_source, repetition_counter, - //deadtime: 0.nanos(), + deadtime, enable_repetition_interrupt, out1_polarity, out2_polarity, @@ -1009,7 +1315,7 @@ macro_rules! hrtim_common_methods { // Implement PWM configuration for timer macro_rules! hrtim_hal { - ($($TIMX:ident: ($timXcr:ident, $timXcr2:ident, $perXr:ident, $tXcen:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident, $fltXr:ident, $outXr:ident),)+) => { + ($($TIMX:ident: ($timXcr:ident, $timXcr2:ident, $perXr:ident, $tXcen:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident, $fltXr:ident, $outXr:ident, $dtXr:ident),)+) => { $( // Implement HrPwmExt trait for hrtimer @@ -1039,7 +1345,7 @@ macro_rules! hrtim_hal { self, _pins: PINS, rcc: &mut Rcc, - ) -> HrPwmBuilder + ) -> HrPwmBuilder> where PINS: Pins + ToHrOut, CHANNEL: HrtimChannel @@ -1064,7 +1370,7 @@ macro_rules! hrtim_hal { enable_push_pull: false, interleaved_mode: InterleavedMode::Disabled, repetition_counter: 0, - //deadtime: 0.nanos(), + deadtime: None, enable_repetition_interrupt: false, out1_polarity: Polarity::ActiveHigh, out2_polarity: Polarity::ActiveHigh, @@ -1076,9 +1382,10 @@ macro_rules! hrtim_hal { HrPwmBuilder<$TIMX, PSCL, PreloadSource, OUT> where PSCL: HrtimPrescaler, + OUT: ToHrOut, { - pub fn finalize(self, _control: &mut HrPwmControl) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX>, HrCr2<$TIMX>, HrCr3<$TIMX>, HrCr4<$TIMX>), OUT) { - hrtim_finalize_body!(self, PreloadSource, $TIMX: ($timXcr, ck_pscx, $perXr, perx, $tXcen, $rep, $repx, $dier, $repie, $timXcr2, $fltXr, $outXr),) + pub fn finalize(self, _control: &mut HrPwmControl) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX, PSCL>, HrCr2<$TIMX, PSCL>, HrCr3<$TIMX, PSCL>, HrCr4<$TIMX, PSCL>), OUT) { + hrtim_finalize_body!(self, PreloadSource, $TIMX: ($timXcr, ck_pscx, $perXr, perx, $tXcen, $rep, $repx, $dier, $repie, $timXcr2, $fltXr, $outXr, $dtXr),) } hrtim_common_methods!($TIMX, PreloadSource); @@ -1157,6 +1464,12 @@ macro_rules! hrtim_hal { self } + pub fn deadtime(mut self, deadtime: DeadtimeConfig) -> Self { + self.deadtime = Some(deadtime); + + self + } + //pub fn swap_mode(mut self, enable: bool) -> Self } )+ @@ -1172,7 +1485,7 @@ macro_rules! hrtim_hal_master { self, _pins: PINS, rcc: &mut Rcc, - ) -> HrPwmBuilder + ) -> HrPwmBuilder> where PINS: Pins + ToHrOut, // TODO: figure out CHANNEL: HrtimChannel @@ -1197,7 +1510,7 @@ macro_rules! hrtim_hal_master { enable_push_pull: false, interleaved_mode: InterleavedMode::Disabled, repetition_counter: 0, - //deadtime: 0.nanos(), + deadtime: None, enable_repetition_interrupt: false, out1_polarity: Polarity::ActiveHigh, out2_polarity: Polarity::ActiveHigh, @@ -1209,8 +1522,9 @@ macro_rules! hrtim_hal_master { HrPwmBuilder<$TIMX, PSCL, MasterPreloadSource, OUT> where PSCL: HrtimPrescaler, + OUT: ToHrOut, { - pub fn finalize(self, _control: &mut HrPwmControl) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX>, HrCr2<$TIMX>, HrCr3<$TIMX>, HrCr4<$TIMX>)) { + pub fn finalize(self, _control: &mut HrPwmControl) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX, PSCL>, HrCr2<$TIMX, PSCL>, HrCr3<$TIMX, PSCL>, HrCr4<$TIMX, PSCL>)) { hrtim_finalize_body!(self, MasterPreloadSource, $TIMX: ($timXcr, $ck_psc, $perXr, $perx, $tXcen, $rep, $rep, $dier, $repie),) } @@ -1311,28 +1625,58 @@ macro_rules! hrtim_pin_hal { } macro_rules! hrtim_out_common { - ($TIMX:ident, $set_event:ident, $register:ident, $action:ident) => {{ + ($TIMX:ident, $set_event:expr, $register:ident, $action:ident) => {{ let tim = unsafe { &*$TIMX::ptr() }; match $set_event { - EventSource::Cr1 => tim.$register.modify(|_r, w| w.cmp1().$action()), - EventSource::Cr2 => tim.$register.modify(|_r, w| w.cmp2().$action()), - EventSource::Cr3 => tim.$register.modify(|_r, w| w.cmp3().$action()), - EventSource::Cr4 => tim.$register.modify(|_r, w| w.cmp4().$action()), - EventSource::Period => tim.$register.modify(|_r, w| w.per().$action()), - - EventSource::MasterCr1 => tim.$register.modify(|_r, w| w.mstcmp1().$action()), - EventSource::MasterCr2 => tim.$register.modify(|_r, w| w.mstcmp2().$action()), - EventSource::MasterCr3 => tim.$register.modify(|_r, w| w.mstcmp3().$action()), - EventSource::MasterCr4 => tim.$register.modify(|_r, w| w.mstcmp4().$action()), - EventSource::MasterPeriod => tim.$register.modify(|_r, w| w.mstper().$action()), + EventSource::Cr1(..) => tim.$register.modify(|_r, w| w.cmp1().$action()), + EventSource::Cr2(..) => tim.$register.modify(|_r, w| w.cmp2().$action()), + EventSource::Cr3(..) => tim.$register.modify(|_r, w| w.cmp3().$action()), + EventSource::Cr4(..) => tim.$register.modify(|_r, w| w.cmp4().$action()), + EventSource::Period(..) => tim.$register.modify(|_r, w| w.per().$action()), + + EventSource::MasterCr1(..) => tim.$register.modify(|_r, w| w.mstcmp1().$action()), + EventSource::MasterCr2(..) => tim.$register.modify(|_r, w| w.mstcmp2().$action()), + EventSource::MasterCr3(..) => tim.$register.modify(|_r, w| w.mstcmp3().$action()), + EventSource::MasterCr4(..) => tim.$register.modify(|_r, w| w.mstcmp4().$action()), + EventSource::MasterPeriod(..) => tim.$register.modify(|_r, w| w.mstper().$action()), + + EventSource::NeighborTimer(es) => match es { + NeighborTimerEventSource::TimEvent1(..) => { + tim.$register.modify(|_r, w| w.timevnt1().$action()) + } + NeighborTimerEventSource::TimEvent2(..) => { + tim.$register.modify(|_r, w| w.timevnt2().$action()) + } + NeighborTimerEventSource::TimEvent3(..) => { + tim.$register.modify(|_r, w| w.timevnt3().$action()) + } + NeighborTimerEventSource::TimEvent4(..) => { + tim.$register.modify(|_r, w| w.timevnt4().$action()) + } + NeighborTimerEventSource::TimEvent5(..) => { + tim.$register.modify(|_r, w| w.timevnt5().$action()) + } + NeighborTimerEventSource::TimEvent6(..) => { + tim.$register.modify(|_r, w| w.timevnt6().$action()) + } + NeighborTimerEventSource::TimEvent7(..) => { + tim.$register.modify(|_r, w| w.timevnt7().$action()) + } + NeighborTimerEventSource::TimEvent8(..) => { + tim.$register.modify(|_r, w| w.timevnt8().$action()) + } + NeighborTimerEventSource::TimEvent9(..) => { + tim.$register.modify(|_r, w| w.timevnt9().$action()) + } + }, } }}; } macro_rules! hrtim_out { ($($TIMX:ident: $out_type:ident: $tXYoen:ident, $tXYodis:ident, $tXYods:ident, $setXYr:ident, $rstXYr:ident,)+) => {$( - impl HrOutput for $out_type<$TIMX> { + impl HrOutput for $out_type<$TIMX, PSCL> { fn enable(&mut self) { let common = unsafe { &*HRTIM_COMMON::ptr() }; common.oenr.write(|w| { w.$tXYoen().set_bit() }); @@ -1343,18 +1687,18 @@ macro_rules! hrtim_out { common.odisr.write(|w| { w.$tXYodis().set_bit() }); } - fn enable_set_event(&mut self, set_event: EventSource) { - hrtim_out_common!($TIMX, set_event, $setXYr, set_bit) + fn enable_set_event(&mut self, set_event: impl Into>) { + hrtim_out_common!($TIMX, set_event.into(), $setXYr, set_bit) } - fn disable_set_event(&mut self, set_event: EventSource) { - hrtim_out_common!($TIMX, set_event, $setXYr, clear_bit) + fn disable_set_event(&mut self, set_event: impl Into>) { + hrtim_out_common!($TIMX, set_event.into(), $setXYr, clear_bit) } - fn enable_rst_event(&mut self, reset_event: EventSource) { - hrtim_out_common!($TIMX, reset_event, $rstXYr, set_bit) + fn enable_rst_event(&mut self, reset_event: impl Into>) { + hrtim_out_common!($TIMX, reset_event.into(), $rstXYr, set_bit) } - fn disable_rst_event(&mut self, reset_event: EventSource) { - hrtim_out_common!($TIMX, reset_event, $rstXYr, clear_bit) + fn disable_rst_event(&mut self, reset_event: impl Into>) { + hrtim_out_common!($TIMX, reset_event.into(), $rstXYr, clear_bit) } fn get_state(&self) -> State { @@ -1399,7 +1743,7 @@ hrtim_out! { macro_rules! hrtim_cr_helper { ($TIMX:ident: $cr_type:ident: $cmpXYr:ident, $cmpYx:ident) => { - impl HrCompareRegister for $cr_type<$TIMX> { + impl HrCompareRegister for $cr_type<$TIMX, PSCL> { fn get_duty(&self) -> u16 { let tim = unsafe { &*$TIMX::ptr() }; @@ -1541,12 +1885,12 @@ hrtim_cr! { } hrtim_hal! { - HRTIM_TIMA: (timacr, timacr2, perar, tacen, repar, repx, timadier, repie, fltar, outar), - HRTIM_TIMB: (timbcr, timbcr2, perbr, tbcen, repbr, repx, timbdier, repie, fltbr, outbr), - HRTIM_TIMC: (timccr, timccr2, percr, tccen, repcr, repx, timcdier, repie, fltcr, outcr), - HRTIM_TIMD: (timdcr, timdcr2, perdr, tdcen, repdr, repx, timddier, repie, fltdr, outdr), - HRTIM_TIME: (timecr, timecr2, perer, tecen, reper, repx, timedier, repie, flter, outer), - HRTIM_TIMF: (timfcr, timfcr2, perfr, tfcen, repfr, repx, timfdier, repie, fltfr, outfr), + HRTIM_TIMA: (timacr, timacr2, perar, tacen, repar, repx, timadier, repie, fltar, outar, dtar), + HRTIM_TIMB: (timbcr, timbcr2, perbr, tbcen, repbr, repx, timbdier, repie, fltbr, outbr, dtbr), + HRTIM_TIMC: (timccr, timccr2, percr, tccen, repcr, repx, timcdier, repie, fltcr, outcr, dtcr), + HRTIM_TIMD: (timdcr, timdcr2, perdr, tdcen, repdr, repx, timddier, repie, fltdr, outdr, dtdr), + HRTIM_TIME: (timecr, timecr2, perer, tecen, reper, repx, timedier, repie, flter, outer, dter), + HRTIM_TIMF: (timfcr, timfcr2, perfr, tfcen, repfr, repx, timfdier, repie, fltfr, outfr, dtfr), } hrtim_hal_master! { From 2bb7b3bba30e82f80d0e4b1319f1cf25943b8ed4 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 3 Nov 2023 16:03:51 +0100 Subject: [PATCH 36/88] HRTIM refactor --- src/pwm/hrtim.rs | 1349 ++----------------------------- src/pwm/hrtim/calibration.rs | 978 ++++++++++++++++++++++ src/pwm/hrtim/external_event.rs | 138 ++++ src/pwm/hrtim/fault.rs | 248 ++++++ 4 files changed, 1453 insertions(+), 1260 deletions(-) create mode 100644 src/pwm/hrtim/calibration.rs create mode 100644 src/pwm/hrtim/external_event.rs create mode 100644 src/pwm/hrtim/fault.rs diff --git a/src/pwm/hrtim.rs b/src/pwm/hrtim.rs index 61689ed4..9108296e 100644 --- a/src/pwm/hrtim.rs +++ b/src/pwm/hrtim.rs @@ -1,25 +1,31 @@ +mod external_event; +mod fault; +mod calibration; + use core::marker::PhantomData; use core::mem::MaybeUninit; use fugit::HertzU64; -use crate::comparator::{COMP1, COMP2, COMP3, COMP4, COMP5, COMP6}; -use crate::gpio::gpioa::{PA10, PA11, PA12, PA15, PA8, PA9}; -use crate::gpio::gpiob::{PB0, PB10, PB11, PB12, PB13, PB14, PB15}; -use crate::gpio::gpioc::{PC10, PC6, PC7, PC8, PC9}; -use crate::gpio::{self, AF3}; -use crate::gpio::{Alternate, AF13}; +use crate::gpio::gpioa::{PA10, PA11, PA8, PA9}; +use crate::gpio::gpiob::{PB12, PB13, PB14, PB15}; +use crate::gpio::gpioc::{PC6, PC7, PC8, PC9}; +use crate::gpio::{Alternate, AF13, AF3}; +use crate::pwm::hrtim::fault::{FaultAction, FaultSource}; use crate::stm32::{ HRTIM_COMMON, HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF, }; +use self::calibration::HrTimOngoingCalibration; +use self::fault::{ + FltMonitor1, FltMonitor2, FltMonitor3, FltMonitor4, FltMonitor5, FltMonitor6, FltMonitorSys, +}; + use super::{ - ActiveHigh, Alignment, ComplementaryImpossible, FaultMonitor, Pins, Polarity, Pwm, - PwmPinEnable, TimerType, + ActiveHigh, Alignment, ComplementaryImpossible, Pins, Polarity, Pwm, PwmPinEnable, TimerType, }; -use crate::rcc::{Enable, GetBusFreq, Rcc, Reset}; -use crate::stm32::RCC; +use crate::rcc::{GetBusFreq, Rcc}; use crate::time::Hertz; pub struct CH1(PhantomData); @@ -419,7 +425,7 @@ macro_rules! impl_into_es { ($dst:ident, $t:ty, $ES:ident) => { impl Into> for &$t { fn into(self) -> EventSource { - EventSource::$ES(PhantomData) + EventSource::$ES{ _x: PhantomData } } } }; @@ -477,7 +483,9 @@ macro_rules! impl_into_neighbor_es { ($dst:ident, $src:ident, $cr:ident, $TimEventX:ident) => { impl Into> for &$cr<$src, PSCL> { fn into(self) -> EventSource { - EventSource::NeighborTimer(NeighborTimerEventSource::$TimEventX(PhantomData)) + EventSource::NeighborTimer { + n: NeighborTimerEventSource::$TimEventX { _x: PhantomData }, + } } } }; @@ -569,36 +577,38 @@ pub enum State { pub enum EventSource { /// Compare match with compare register 1 of this timer - Cr1(PhantomData<(PSCL, DST)>), + Cr1 { _x: PhantomData<(PSCL, DST)> }, /// Compare match with compare register 2 of this timer - Cr2(PhantomData<(PSCL, DST)>), + Cr2 { _x: PhantomData<(PSCL, DST)> }, /// Compare match with compare register 3 of this timer - Cr3(PhantomData<(PSCL, DST)>), + Cr3 { _x: PhantomData<(PSCL, DST)> }, /// Compare match with compare register 4 of this timer - Cr4(PhantomData<(PSCL, DST)>), + Cr4 { _x: PhantomData<(PSCL, DST)> }, /// On complete period - Period(PhantomData<(PSCL, DST)>), + Period { _x: PhantomData<(PSCL, DST)> }, /// Compare match with compare register 1 of master timer - MasterCr1(PhantomData<(PSCL, DST)>), + MasterCr1 { _x: PhantomData<(PSCL, DST)> }, /// Compare match with compare register 2 of master timer - MasterCr2(PhantomData<(PSCL, DST)>), + MasterCr2 { _x: PhantomData<(PSCL, DST)> }, /// Compare match with compare register 3 of master timer - MasterCr3(PhantomData<(PSCL, DST)>), + MasterCr3 { _x: PhantomData<(PSCL, DST)> }, /// Compare match with compare register 4 of master timer - MasterCr4(PhantomData<(PSCL, DST)>), + MasterCr4 { _x: PhantomData<(PSCL, DST)> }, /// On complete master period - MasterPeriod(PhantomData<(PSCL, DST)>), + MasterPeriod { _x: PhantomData<(PSCL, DST)> }, - NeighborTimer(NeighborTimerEventSource), + NeighborTimer { + n: NeighborTimerEventSource, + }, } /// Compare events from neighbor timers @@ -616,7 +626,9 @@ pub enum NeighborTimerEventSource { /// |TimD | A CR1 | /// |TimE | A CR4 | /// |TimF | A CR3 | - TimEvent1(PhantomData<(PSCL, DST)>), + TimEvent1 { + _x: PhantomData<(PSCL, DST)>, + }, /// Timer event x /// @@ -642,7 +654,9 @@ pub enum NeighborTimerEventSource { /// |TimD | A CR4 | /// |TimE | B CR3 | /// |TimF | B CR1 | - TimEvent2(PhantomData<(PSCL, DST)>), + TimEvent2 { + _x: PhantomData<(PSCL, DST)>, + }, /// Timer event 3 /// @@ -655,7 +669,9 @@ pub enum NeighborTimerEventSource { /// |TimD | B CR2 | /// |TimE | B CR4 | /// |TimF | B CR4 | - TimEvent3(PhantomData<(PSCL, DST)>), + TimEvent3 { + _x: PhantomData<(PSCL, DST)>, + }, /// Timer event 4 /// @@ -668,14 +684,26 @@ pub enum NeighborTimerEventSource { /// |TimD | B CR4 | /// |TimE | C CR1 | /// |TimF | C CR1 | - TimEvent4(PhantomData<(PSCL, DST)>), + TimEvent4 { + _x: PhantomData<(PSCL, DST)>, + }, // TODO: Document those - TimEvent5(PhantomData<(PSCL, DST)>), - TimEvent6(PhantomData<(PSCL, DST)>), - TimEvent7(PhantomData<(PSCL, DST)>), - TimEvent8(PhantomData<(PSCL, DST)>), - TimEvent9(PhantomData<(PSCL, DST)>), + TimEvent5 { + _x: PhantomData<(PSCL, DST)>, + }, + TimEvent6 { + _x: PhantomData<(PSCL, DST)>, + }, + TimEvent7 { + _x: PhantomData<(PSCL, DST)>, + }, + TimEvent8 { + _x: PhantomData<(PSCL, DST)>, + }, + TimEvent9 { + _x: PhantomData<(PSCL, DST)>, + }, } macro_rules! hr_timer_reset_event_source_common { @@ -1149,6 +1177,12 @@ macro_rules! hrtim_finalize_body { .sdtrx().bit(deadtime_rising_sign) .dtfx().bits(deadtime_falling_value) .sdtfx().bit(deadtime_falling_sign) + + // Lock configuration + .dtflkx().set_bit() + .dtfslkx().set_bit() + .dtrlkx().set_bit() + .dtrslkx().set_bit() ); tim.$outXr.modify(|_r, w| w.dten().set_bit()); } @@ -1629,44 +1663,44 @@ macro_rules! hrtim_out_common { let tim = unsafe { &*$TIMX::ptr() }; match $set_event { - EventSource::Cr1(..) => tim.$register.modify(|_r, w| w.cmp1().$action()), - EventSource::Cr2(..) => tim.$register.modify(|_r, w| w.cmp2().$action()), - EventSource::Cr3(..) => tim.$register.modify(|_r, w| w.cmp3().$action()), - EventSource::Cr4(..) => tim.$register.modify(|_r, w| w.cmp4().$action()), - EventSource::Period(..) => tim.$register.modify(|_r, w| w.per().$action()), - - EventSource::MasterCr1(..) => tim.$register.modify(|_r, w| w.mstcmp1().$action()), - EventSource::MasterCr2(..) => tim.$register.modify(|_r, w| w.mstcmp2().$action()), - EventSource::MasterCr3(..) => tim.$register.modify(|_r, w| w.mstcmp3().$action()), - EventSource::MasterCr4(..) => tim.$register.modify(|_r, w| w.mstcmp4().$action()), - EventSource::MasterPeriod(..) => tim.$register.modify(|_r, w| w.mstper().$action()), - - EventSource::NeighborTimer(es) => match es { - NeighborTimerEventSource::TimEvent1(..) => { + EventSource::Cr1 { .. } => tim.$register.modify(|_r, w| w.cmp1().$action()), + EventSource::Cr2 { .. } => tim.$register.modify(|_r, w| w.cmp2().$action()), + EventSource::Cr3 { .. } => tim.$register.modify(|_r, w| w.cmp3().$action()), + EventSource::Cr4 { .. } => tim.$register.modify(|_r, w| w.cmp4().$action()), + EventSource::Period { .. } => tim.$register.modify(|_r, w| w.per().$action()), + + EventSource::MasterCr1 { .. } => tim.$register.modify(|_r, w| w.mstcmp1().$action()), + EventSource::MasterCr2 { .. } => tim.$register.modify(|_r, w| w.mstcmp2().$action()), + EventSource::MasterCr3 { .. } => tim.$register.modify(|_r, w| w.mstcmp3().$action()), + EventSource::MasterCr4 { .. } => tim.$register.modify(|_r, w| w.mstcmp4().$action()), + EventSource::MasterPeriod { .. } => tim.$register.modify(|_r, w| w.mstper().$action()), + + EventSource::NeighborTimer { n } => match n { + NeighborTimerEventSource::TimEvent1 { .. } => { tim.$register.modify(|_r, w| w.timevnt1().$action()) } - NeighborTimerEventSource::TimEvent2(..) => { + NeighborTimerEventSource::TimEvent2 { .. } => { tim.$register.modify(|_r, w| w.timevnt2().$action()) } - NeighborTimerEventSource::TimEvent3(..) => { + NeighborTimerEventSource::TimEvent3 { .. } => { tim.$register.modify(|_r, w| w.timevnt3().$action()) } - NeighborTimerEventSource::TimEvent4(..) => { + NeighborTimerEventSource::TimEvent4 { .. } => { tim.$register.modify(|_r, w| w.timevnt4().$action()) } - NeighborTimerEventSource::TimEvent5(..) => { + NeighborTimerEventSource::TimEvent5 { .. } => { tim.$register.modify(|_r, w| w.timevnt5().$action()) } - NeighborTimerEventSource::TimEvent6(..) => { + NeighborTimerEventSource::TimEvent6 { .. } => { tim.$register.modify(|_r, w| w.timevnt6().$action()) } - NeighborTimerEventSource::TimEvent7(..) => { + NeighborTimerEventSource::TimEvent7 { .. } => { tim.$register.modify(|_r, w| w.timevnt7().$action()) } - NeighborTimerEventSource::TimEvent8(..) => { + NeighborTimerEventSource::TimEvent8 { .. } => { tim.$register.modify(|_r, w| w.timevnt8().$action()) } - NeighborTimerEventSource::TimEvent9(..) => { + NeighborTimerEventSource::TimEvent9 { .. } => { tim.$register.modify(|_r, w| w.timevnt9().$action()) } }, @@ -1979,1209 +2013,4 @@ impl super::TimerType for TimerHrTim { pub trait HrtimChannel {} impl HrtimChannel for CH1 {} -impl HrtimChannel for CH2 {} - -pub enum FaultAction { - /// Output never enters fault mode - None = 0b00, - - /// Output forced to `active` level on fault - ForceActive = 0b01, - - /// Output forced to `inactive` level on fault - ForceInactive = 0b10, - - /// The output is floating/tri stated on fault - Floating = 0b11, -} - -pub unsafe trait FaultSource: Copy { - const ENABLE_BITS: u8; -} - -pub struct SourceBuilder { - _input: I, - src_bits: u8, - - /// FLTxP - is_active_high: bool, - - /// FLTxF[3:0] - filter_bits: u8, -} - -impl SourceBuilder { - unsafe fn new(input: I, src_bits: u8) -> Self { - SourceBuilder { - _input: input, - src_bits, - is_active_high: false, - filter_bits: 0b0000, - } - } -} - -macro_rules! impl_faults { - ($( - $input:ident => $source:ident: - PINS=[($pin:ident, $af:ident), $(($pin_b:ident, $af_b:ident),)*], - COMP=$compX:ident, $enable_bits:literal, - $fltinrZ:ident, $fltWsrc_0:ident, $fltWsrc_1:ident, $fltWp:ident, $fltWf:ident, $fltWe:ident, $fltWlck:ident, - )+) => {$( - - // This should NOT be Copy/Clone - pub struct $input { - _x: PhantomData<()> - } - - #[derive(Copy, Clone)] - pub struct $source { - _x: PhantomData<()> - } - - impl $input { - pub fn bind_pin(self, pin: $pin>) -> SourceBuilder<$input> { - pin.into_alternate::<$af>(); - unsafe { SourceBuilder::new(self, 0b00) } - } - - $( - pub fn bind_pin_b(self, pin: $pin_b>) -> SourceBuilder<$input> { - pin.into_alternate::<$af_b>(); - unsafe { SourceBuilder::new(self, 0b00) } - } - )* - - pub fn bind_comp(self, _comp: &crate::comparator::Comparator<$compX, crate::comparator::Enabled>) -> SourceBuilder<$input> { - unsafe { SourceBuilder::new(self, 0b01) } - } - - /*pub fn bind_external(?) { - SourceBuilder::new(self, 0b10); - }*/ - } - - impl SourceBuilder<$input> { - pub fn finalize(self, _control: &mut HrPwmControl) -> $source { - let SourceBuilder{ _input, src_bits, is_active_high, filter_bits } = self; - - // Setup fault source - unsafe { - let common = &*HRTIM_COMMON::ptr(); - - common.fltinr2.modify(|_r, w| w.$fltWsrc_1().bit(src_bits & 0b10 != 0)); - common.$fltinrZ.modify(|_r, w| w - .$fltWsrc_0().bit(src_bits & 0b01 != 0) - .$fltWp().bit(is_active_high) - .$fltWf().bits(filter_bits) - .$fltWe().set_bit() // Enable - ); - - // ... and lock configuration - common.$fltinrZ.modify(|_r, w| w.$fltWlck().set_bit()); - } - - $source { - _x: PhantomData - } - } - - pub fn polarity(mut self, polarity: super::Polarity) -> Self { - self.is_active_high = polarity == super::Polarity::ActiveHigh; - self - } - - // TODO: add more settings - /* pub fn blanking(?) -> Self */ - - pub fn filter(mut self, filter: FaultSamplingFilter) -> Self { - self.filter_bits = filter as u8; - self - } - } - - unsafe impl FaultSource for $source { - const ENABLE_BITS: u8 = $enable_bits; - } - )+} -} - -// TODO: Lookup to ensure the alternate function are the same for other devices than stm32g474 -#[cfg(feature = "stm32g474")] -impl_faults!( - FaultInput1 => FaultSource1: PINS=[(PA12, AF13),], COMP=COMP2, 0b000001, fltinr1, flt1src, flt1src_1, flt1p, flt1f, flt1e, flt1lck, - FaultInput2 => FaultSource2: PINS=[(PA15, AF13),], COMP=COMP4, 0b000010, fltinr1, flt2src, flt2src_1, flt2p, flt2f, flt2e, flt2lck, - FaultInput3 => FaultSource3: PINS=[(PB10, AF13),], COMP=COMP6, 0b000100, fltinr1, flt3src, flt3src_1, flt3p, flt3f, flt3e, flt3lck, - FaultInput4 => FaultSource4: PINS=[(PB11, AF13),], COMP=COMP1, 0b001000, fltinr1, flt4src, flt4src_1, flt4p, flt4f, flt4e, flt4lck, - FaultInput5 => FaultSource5: PINS=[(PB0, AF13), (PC7, AF3),], COMP=COMP3, 0b010000, fltinr2, flt5src, flt5src_1, flt5p, flt5f, flt5e, flt5lck, - FaultInput6 => FaultSource6: PINS=[(PC10, AF13),], COMP=COMP5, 0b100000, fltinr2, flt6src_0, flt6src_1, flt6p, flt6f, flt6e, flt6lck, -); - -pub struct FaultInputs { - pub fault_input1: FaultInput1, - pub fault_input2: FaultInput2, - pub fault_input3: FaultInput3, - pub fault_input4: FaultInput4, - pub fault_input5: FaultInput5, - pub fault_input6: FaultInput6, -} - -pub struct HrPwmControl { - _x: PhantomData<()>, - - pub fault_sys: FltMonitorSys, - pub fault_1: FltMonitor1, - pub fault_2: FltMonitor2, - pub fault_3: FltMonitor3, - pub fault_4: FltMonitor4, - pub fault_5: FltMonitor5, - pub fault_6: FltMonitor6, -} - -/// The divsion ratio between f_hrtim and the fault signal sampling clock for digital filters -pub enum FaultSamplingClkDiv { - /// No division - /// - /// fault signal sampling clock f_flts = f_hrtim - None = 0b00, - - /// 1/2 - /// - /// fault signal sampling clock f_flts = f_hrtim / 2 - Two = 0b01, - - /// 1/4 - /// - /// fault signal sampling clock f_flts = f_hrtim / 4 - Four = 0b10, - - /// 1/8 - /// - /// fault signal sampling clock f_flts = f_hrtim / 8 - Eight = 0b11, -} - -pub enum FaultSamplingFilter { - /// No filtering, fault acts asynchronously - /// - /// Note that this bypasses any f_flts (FaultSamplingClkDiv) - None = 0b0000, - - /// Sample directly at rate f_hrtim, with a count of 2 - /// - /// Note that this bypasses: any f_flts (FaultSamplingClkDiv) - HrtimN2 = 0b0001, - - /// Sample directly at rate f_hrtim, with a count of 4 - /// - /// Note that this bypasses any f_flts (FaultSamplingClkDiv) - HrtimN4 = 0b0010, - - /// Sample directly at rate f_hrtim, with a count of 8 - /// - /// Note that this bypasses any f_flts (FaultSamplingClkDiv) - HrtimN8 = 0b0011, - - /// Sample at rate f_flts / 2, with a count of 6 - FltsDiv2N6 = 0b0100, - - /// Sample at rate f_flts / 2, with a count of 8 - FltsDiv2N8 = 0b0101, - - /// Sample at rate f_flts / 4, with a count of 6 - FltsDiv4N6 = 0b0110, - - /// Sample at rate f_flts / 4, with a count of 8 - FltsDiv4N8 = 0b0111, - - /// Sample at rate f_flts / 8, with a count of 6 - FltsDiv8N6 = 0b1000, - - /// Sample at rate f_flts / 8, with a count of 8 - FltsDiv8N8 = 0b1001, - - /// Sample at rate f_flts / 16, with a count of 5 - FltsDiv16N5 = 0b1010, - - /// Sample at rate f_flts / 16, with a count of 6 - FltsDiv16N6 = 0b1011, - - /// Sample at rate f_flts / 16, with a count of 8 - FltsDiv16N8 = 0b1100, - - /// Sample at rate f_flts / 32, with a count of 5 - FltsDiv32N5 = 0b1101, - - /// Sample at rate f_flts / 32, with a count of 6 - FltsDiv32N6 = 0b1110, - - /// Sample at rate f_flts / 32, with a count of 8 - FltsDiv32N8 = 0b1111, -} - -pub trait HrControltExt { - fn hr_control(self, _rcc: &mut Rcc) -> HrTimOngoingCalibration; -} - -impl HrControltExt for HRTIM_COMMON { - fn hr_control(self, _rcc: &mut Rcc) -> HrTimOngoingCalibration { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - - unsafe { - let rcc_ptr = &*RCC::ptr(); - - HRTIM_COMMON::enable(rcc_ptr); - HRTIM_COMMON::reset(rcc_ptr); - } - - // Start calibration procedure - common - .dllcr - .write(|w| w.cal().set_bit().calen().clear_bit()); - - HrTimOngoingCalibration { - adc_trigger1_bits: 0, - adc_trigger2_bits: 0, - adc_trigger3_bits: 0, - adc_trigger4_bits: 0, - - adc_trigger5_bits: 0, - adc_trigger6_bits: 0, - adc_trigger7_bits: 0, - adc_trigger8_bits: 0, - adc_trigger9_bits: 0, - adc_trigger10_bits: 0, - - adc_trigger1_postscaler: AdcTriggerPostscaler::None, - adc_trigger2_postscaler: AdcTriggerPostscaler::None, - adc_trigger3_postscaler: AdcTriggerPostscaler::None, - adc_trigger4_postscaler: AdcTriggerPostscaler::None, - - adc_trigger5_postscaler: AdcTriggerPostscaler::None, - adc_trigger6_postscaler: AdcTriggerPostscaler::None, - adc_trigger7_postscaler: AdcTriggerPostscaler::None, - adc_trigger8_postscaler: AdcTriggerPostscaler::None, - adc_trigger9_postscaler: AdcTriggerPostscaler::None, - adc_trigger10_postscaler: AdcTriggerPostscaler::None, - - divider: FaultSamplingClkDiv::None, - } - } -} - -pub struct HrTimOngoingCalibration { - adc_trigger1_bits: u32, - adc_trigger2_bits: u32, - adc_trigger3_bits: u32, - adc_trigger4_bits: u32, - - adc_trigger5_bits: u8, - adc_trigger6_bits: u8, - adc_trigger7_bits: u8, - adc_trigger8_bits: u8, - adc_trigger9_bits: u8, - adc_trigger10_bits: u8, - - adc_trigger1_postscaler: AdcTriggerPostscaler, - adc_trigger2_postscaler: AdcTriggerPostscaler, - adc_trigger3_postscaler: AdcTriggerPostscaler, - adc_trigger4_postscaler: AdcTriggerPostscaler, - - adc_trigger5_postscaler: AdcTriggerPostscaler, - adc_trigger6_postscaler: AdcTriggerPostscaler, - adc_trigger7_postscaler: AdcTriggerPostscaler, - adc_trigger8_postscaler: AdcTriggerPostscaler, - adc_trigger9_postscaler: AdcTriggerPostscaler, - adc_trigger10_postscaler: AdcTriggerPostscaler, - - divider: FaultSamplingClkDiv, -} - -impl HrTimOngoingCalibration { - /// SAFETY: Calibration needs to be done before calling this - unsafe fn init(self) -> (HrPwmControl, FaultInputs) { - use Adc13Trigger as Ad13T; - use Adc24Trigger as Ad24T; - - let common = unsafe { &*HRTIM_COMMON::ptr() }; - - let Self { - adc_trigger1_bits: ad1_bits, - adc_trigger2_bits: ad2_bits, - adc_trigger3_bits: ad3_bits, - adc_trigger4_bits: ad4_bits, - - adc_trigger5_bits: ad5_bits, - adc_trigger6_bits: ad6_bits, - adc_trigger7_bits: ad7_bits, - adc_trigger8_bits: ad8_bits, - adc_trigger9_bits: ad9_bits, - adc_trigger10_bits: ad10_bits, - - adc_trigger1_postscaler, - adc_trigger2_postscaler, - adc_trigger3_postscaler, - adc_trigger4_postscaler, - - adc_trigger5_postscaler, - adc_trigger6_postscaler, - adc_trigger7_postscaler, - adc_trigger8_postscaler, - adc_trigger9_postscaler, - adc_trigger10_postscaler, - - divider, - } = self; - - unsafe { - // Enable periodic calibration - // with f_hrtim at 170MHz, these settings leads to - // a period of about 6.2ms - common - .dllcr - .modify(|_r, w| w.calrte().bits(0b00).cal().set_bit().calen().clear_bit()); - common.fltinr2.write(|w| w.fltsd().bits(divider as u8)); - - common.adc1r.write(|w| { - w.eper() - .bit(ad1_bits | Ad13T::TimEPeriod as u32 != 0) - .ec4() - .bit(ad1_bits | Ad13T::TimECmp4 as u32 != 0) - .ec3() - .bit(ad1_bits | Ad13T::TimECmp3 as u32 != 0) - //.frst() - .dper() - .bit(ad1_bits | Ad13T::TimDPeriod as u32 != 0) - .dc4() - .bit(ad1_bits | Ad13T::TimDCmp4 as u32 != 0) - .dc3() - .bit(ad1_bits | Ad13T::TimDCmp3 as u32 != 0) - .fper() - .bit(ad1_bits | Ad13T::TimFPeriod as u32 != 0) - .cper() - .bit(ad1_bits | Ad13T::TimCPeriod as u32 != 0) - .cc4() - .bit(ad1_bits | Ad13T::TimCCmp4 as u32 != 0) - .cc3() - .bit(ad1_bits | Ad13T::TimCCmp3 as u32 != 0) - .fc4() - .bit(ad1_bits | Ad13T::TimFCmp4 as u32 != 0) - //.brst() - .bper() - .bit(ad1_bits | Ad13T::TimBPeriod as u32 != 0) - .bc4() - .bit(ad1_bits | Ad13T::TimBCmp4 as u32 != 0) - .bc3() - .bit(ad1_bits | Ad13T::TimBCmp3 as u32 != 0) - .fc3() - .bit(ad1_bits | Ad13T::TimFCmp3 as u32 != 0) - //.arst() - .aper() - .bit(ad1_bits | Ad13T::TimAPeriod as u32 != 0) - .ac4() - .bit(ad1_bits | Ad13T::TimACmp4 as u32 != 0) - .ac3() - .bit(ad1_bits | Ad13T::TimACmp3 as u32 != 0) - .fc2() - .bit(ad1_bits | Ad13T::TimFCmp2 as u32 != 0) - //.eev5().bit(ad1_bits | Ad13T::_ as u32) - //.eev4().bit(ad1_bits | Ad13T::_ as u32) - //.eev3().bit(ad1_bits | Ad13T::_ as u32) - //.eev2().bit(ad1_bits | Ad13T::_ as u32) - //.eev1().bit(ad1_bits | Ad13T::_ as u32) - .mper() - .bit(ad1_bits | Ad13T::MasterPeriod as u32 != 0) - .mc4() - .bit(ad1_bits | Ad13T::MasterCmp4 as u32 != 0) - .mc3() - .bit(ad1_bits | Ad13T::MasterCmp3 as u32 != 0) - .mc2() - .bit(ad1_bits | Ad13T::MasterCmp2 as u32 != 0) - .mc1() - .bit(ad1_bits | Ad13T::MasterCmp1 as u32 != 0) - }); - - common.adc3r.write(|w| { - w.eper() - .bit(ad3_bits | Ad13T::TimEPeriod as u32 != 0) - .ec4() - .bit(ad3_bits | Ad13T::TimECmp4 as u32 != 0) - .ec3() - .bit(ad3_bits | Ad13T::TimECmp3 as u32 != 0) - //.frst() - .dper() - .bit(ad3_bits | Ad13T::TimDPeriod as u32 != 0) - .dc4() - .bit(ad3_bits | Ad13T::TimDCmp4 as u32 != 0) - .dc3() - .bit(ad3_bits | Ad13T::TimDCmp3 as u32 != 0) - .fper() - .bit(ad3_bits | Ad13T::TimFPeriod as u32 != 0) - .cper() - .bit(ad3_bits | Ad13T::TimCPeriod as u32 != 0) - .cc4() - .bit(ad3_bits | Ad13T::TimCCmp4 as u32 != 0) - .cc3() - .bit(ad3_bits | Ad13T::TimCCmp3 as u32 != 0) - .fc4() - .bit(ad3_bits | Ad13T::TimFCmp4 as u32 != 0) - //.brst() - .bper() - .bit(ad3_bits | Ad13T::TimBPeriod as u32 != 0) - .bc4() - .bit(ad3_bits | Ad13T::TimBCmp4 as u32 != 0) - .bc3() - .bit(ad3_bits | Ad13T::TimBCmp3 as u32 != 0) - .fc3() - .bit(ad3_bits | Ad13T::TimFCmp3 as u32 != 0) - //.arst() - .aper() - .bit(ad3_bits | Ad13T::TimAPeriod as u32 != 0) - .ac4() - .bit(ad3_bits | Ad13T::TimACmp4 as u32 != 0) - .ac3() - .bit(ad3_bits | Ad13T::TimACmp3 as u32 != 0) - .fc2() - .bit(ad3_bits | Ad13T::TimFCmp2 as u32 != 0) - //.eev5().bit(ad3_bits | Ad13T::_ as u32) - //.eev4().bit(ad3_bits | Ad13T::_ as u32) - //.eev3().bit(ad3_bits | Ad13T::_ as u32) - //.eev2().bit(ad3_bits | Ad13T::_ as u32) - //.eev1().bit(ad3_bits | Ad13T::_ as u32) - .mper() - .bit(ad3_bits | Ad13T::MasterPeriod as u32 != 0) - .mc4() - .bit(ad3_bits | Ad13T::MasterCmp4 as u32 != 0) - .mc3() - .bit(ad3_bits | Ad13T::MasterCmp3 as u32 != 0) - .mc2() - .bit(ad3_bits | Ad13T::MasterCmp2 as u32 != 0) - .mc1() - .bit(ad3_bits | Ad13T::MasterCmp1 as u32 != 0) - }); - - common.adc2r.write(|w| { - w - //.erst() - .ec4() - .bit(ad2_bits | Ad24T::TimECmp4 as u32 != 0) - .ec3() - .bit(ad2_bits | Ad24T::TimECmp3 as u32 != 0) - .ec2() - .bit(ad2_bits | Ad24T::TimECmp2 as u32 != 0) - //.drst().bit(ad2_bits | Ad24T::_ as u32 != 0) - .dper() - .bit(ad2_bits | Ad24T::TimDPeriod as u32 != 0) - .dc4() - .bit(ad2_bits | Ad24T::TimDCmp4 as u32 != 0) - .fper() - .bit(ad2_bits | Ad24T::TimFPeriod as u32 != 0) - .dc2() - .bit(ad2_bits | Ad24T::TimDCmp2 as u32 != 0) - //.crst().bit(ad2_bits | Ad24T::_ as u32 != 0) - .cper() - .bit(ad2_bits | Ad24T::TimCPeriod as u32 != 0) - .cc4() - .bit(ad2_bits | Ad24T::TimCCmp4 as u32 != 0) - .fc4() - .bit(ad2_bits | Ad24T::TimFCmp4 as u32 != 0) - .cc2() - .bit(ad2_bits | Ad24T::TimCCmp2 as u32 != 0) - .bper() - .bit(ad2_bits | Ad24T::TimBPeriod as u32 != 0) - .bc4() - .bit(ad2_bits | Ad24T::TimBCmp4 as u32 != 0) - .fc3() - .bit(ad2_bits | Ad24T::TimFCmp3 as u32 != 0) - .bc2() - .bit(ad2_bits | Ad24T::TimBCmp2 as u32 != 0) - .aper() - .bit(ad2_bits | Ad24T::TimAPeriod as u32 != 0) - .ac4() - .bit(ad2_bits | Ad24T::TimACmp4 as u32 != 0) - .fc2() - .bit(ad2_bits | Ad24T::TimFCmp2 as u32 != 0) - .ac2() - .bit(ad2_bits | Ad24T::TimACmp2 as u32 != 0) - //.eev10() - //.eev9() - //.eev8() - //.eev7() - //.eev6() - .mper() - .bit(ad2_bits | Ad24T::MasterPeriod as u32 != 0) - .mc4() - .bit(ad2_bits | Ad24T::MasterCmp4 as u32 != 0) - .mc3() - .bit(ad2_bits | Ad24T::MasterCmp3 as u32 != 0) - .mc2() - .bit(ad2_bits | Ad24T::MasterCmp2 as u32 != 0) - .mc1() - .bit(ad2_bits | Ad24T::MasterCmp1 as u32 != 0) - }); - - common.adc4r.write(|w| { - w - //.erst() - .ec4() - .bit(ad4_bits | Ad24T::TimECmp4 as u32 != 0) - .ec3() - .bit(ad4_bits | Ad24T::TimECmp3 as u32 != 0) - .ec2() - .bit(ad4_bits | Ad24T::TimECmp2 as u32 != 0) - //.drst().bit(ad4_bits | Ad24T::_ as u32 != 0) - .dper() - .bit(ad4_bits | Ad24T::TimDPeriod as u32 != 0) - .dc4() - .bit(ad4_bits | Ad24T::TimDCmp4 as u32 != 0) - .fper() - .bit(ad4_bits | Ad24T::TimFPeriod as u32 != 0) - .dc2() - .bit(ad4_bits | Ad24T::TimDCmp2 as u32 != 0) - //.crst().bit(ad4_bits | Ad24T::_ as u32 != 0) - .cper() - .bit(ad4_bits | Ad24T::TimCPeriod as u32 != 0) - .cc4() - .bit(ad4_bits | Ad24T::TimCCmp4 as u32 != 0) - .fc4() - .bit(ad4_bits | Ad24T::TimFCmp4 as u32 != 0) - .cc2() - .bit(ad4_bits | Ad24T::TimCCmp2 as u32 != 0) - .bper() - .bit(ad4_bits | Ad24T::TimBPeriod as u32 != 0) - .bc4() - .bit(ad4_bits | Ad24T::TimBCmp4 as u32 != 0) - .fc3() - .bit(ad4_bits | Ad24T::TimFCmp3 as u32 != 0) - .bc2() - .bit(ad4_bits | Ad24T::TimBCmp2 as u32 != 0) - .aper() - .bit(ad4_bits | Ad24T::TimAPeriod as u32 != 0) - .ac4() - .bit(ad4_bits | Ad24T::TimACmp4 as u32 != 0) - .fc2() - .bit(ad4_bits | Ad24T::TimFCmp2 as u32 != 0) - .ac2() - .bit(ad4_bits | Ad24T::TimACmp2 as u32 != 0) - //.eev10() - //.eev9() - //.eev8() - //.eev7() - //.eev6() - .mper() - .bit(ad4_bits | Ad24T::MasterPeriod as u32 != 0) - .mc4() - .bit(ad4_bits | Ad24T::MasterCmp4 as u32 != 0) - .mc3() - .bit(ad4_bits | Ad24T::MasterCmp3 as u32 != 0) - .mc2() - .bit(ad4_bits | Ad24T::MasterCmp2 as u32 != 0) - .mc1() - .bit(ad4_bits | Ad24T::MasterCmp1 as u32 != 0) - }); - - common.adcer.write(|w| { - w.adc5trg() - .variant(ad5_bits) - .adc6trg() - .variant(ad6_bits) - .adc7trg() - .variant(ad7_bits) - .adc8trg() - .variant(ad8_bits) - .adc9trg() - .variant(ad9_bits) - .adc10trg() - .variant(ad10_bits) - }); - - common.adcps1.write(|w| { - w.adc1psc() - .bits(adc_trigger1_postscaler as u8) - .adc2psc() - .bits(adc_trigger2_postscaler as u8) - .adc3psc() - .bits(adc_trigger3_postscaler as u8) - .adc4psc() - .bits(adc_trigger4_postscaler as u8) - .adc5psc() - .bits(adc_trigger5_postscaler as u8) - }); - - common.adcps2.write(|w| { - w.adc6psc() - .bits(adc_trigger6_postscaler as u8) - .adc7psc() - .bits(adc_trigger7_postscaler as u8) - .adc8psc() - .bits(adc_trigger8_postscaler as u8) - .adc9psc() - .bits(adc_trigger9_postscaler as u8) - .adc10psc() - .bits(adc_trigger10_postscaler as u8) - }); - - // TODO: Adc trigger 5-10 - } - - ( - HrPwmControl { - _x: PhantomData, - fault_sys: FltMonitorSys { _x: PhantomData }, - fault_1: FltMonitor1 { _x: PhantomData }, - fault_2: FltMonitor2 { _x: PhantomData }, - fault_3: FltMonitor3 { _x: PhantomData }, - fault_4: FltMonitor4 { _x: PhantomData }, - fault_5: FltMonitor5 { _x: PhantomData }, - fault_6: FltMonitor6 { _x: PhantomData }, - }, - FaultInputs { - fault_input1: FaultInput1 { _x: PhantomData }, - fault_input2: FaultInput2 { _x: PhantomData }, - fault_input3: FaultInput3 { _x: PhantomData }, - fault_input4: FaultInput4 { _x: PhantomData }, - fault_input5: FaultInput5 { _x: PhantomData }, - fault_input6: FaultInput6 { _x: PhantomData }, - }, - ) - } - - pub fn wait_for_calibration(self) -> (HrPwmControl, FaultInputs) { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - while common.isr.read().dllrdy().bit_is_clear() { - // Wait until ready - } - - // Calibration is now done, it is safe to continue - unsafe { self.init() } - } - - pub fn enable_adc_trigger1_source(mut self, trigger: Adc13Trigger) -> Self { - self.adc_trigger1_bits |= trigger as u32; - self - } - - pub fn enable_adc_trigger2_source(mut self, trigger: Adc24Trigger) -> Self { - self.adc_trigger2_bits |= trigger as u32; - self - } - - pub fn enable_adc_trigger3_source(mut self, trigger: Adc13Trigger) -> Self { - self.adc_trigger3_bits |= trigger as u32; - self - } - - pub fn enable_adc_trigger4_source(mut self, trigger: Adc24Trigger) -> Self { - self.adc_trigger4_bits |= trigger as u32; - self - } - - pub fn enable_adc_trigger5_source(mut self, trigger: Adc579Trigger) -> Self { - self.adc_trigger5_bits = trigger as u8; - self - } - - pub fn enable_adc_trigger6_source(mut self, trigger: Adc6810Trigger) -> Self { - self.adc_trigger6_bits = trigger as u8; - self - } - - pub fn enable_adc_trigger7_source(mut self, trigger: Adc579Trigger) -> Self { - self.adc_trigger7_bits = trigger as u8; - self - } - - pub fn enable_adc_trigger8_source(mut self, trigger: Adc6810Trigger) -> Self { - self.adc_trigger8_bits = trigger as u8; - self - } - - pub fn enable_adc_trigger9_source(mut self, trigger: Adc579Trigger) -> Self { - self.adc_trigger9_bits = trigger as u8; - self - } - - pub fn enable_adc_trigger10_source(mut self, trigger: Adc6810Trigger) -> Self { - self.adc_trigger10_bits = trigger as u8; - self - } - - pub fn set_adc1_trigger_psc(mut self, post_scaler: AdcTriggerPostscaler) -> Self { - self.adc_trigger1_postscaler = post_scaler; - self - } - - pub fn set_adc2_trigger_psc(mut self, post_scaler: AdcTriggerPostscaler) -> Self { - self.adc_trigger2_postscaler = post_scaler; - self - } - - pub fn set_adc3_trigger_psc(mut self, post_scaler: AdcTriggerPostscaler) -> Self { - self.adc_trigger3_postscaler = post_scaler; - self - } - - pub fn set_adc4_trigger_psc(mut self, post_scaler: AdcTriggerPostscaler) -> Self { - self.adc_trigger4_postscaler = post_scaler; - self - } - - pub fn set_fault_sampling_division(mut self, divider: FaultSamplingClkDiv) -> Self { - self.divider = divider; - self - } - - // TODO: Adc trigger 5-10 -} - -pub enum Adc13Trigger { - /// bit 31 ADCxTEPER - Trigger on HRTIM_TIME period - TimEPeriod = 1 << 31, - - /// bit 30 ADCxTEC4 - Trigger on HRTIM_TIME compare match for compare register 4 - TimECmp4 = 1 << 30, - - /// bit 29 ADCxTEC3 - Trigger on HRTIM_TIME compare match for compare register 3 - TimECmp3 = 1 << 29, - - /// bit 28 ADCxTFRST - Trigger on HRTIM_TIMF reset or counter roll-over - TimFRst = 1 << 28, - - /// bit 27 ADCxTDPER - Trigger on HRTIM_TIMD period - TimDPeriod = 1 << 27, - - /// bit 26 ADCxTDC4 - Trigger on HRTIM_TIMD compare match for compare register 4 - TimDCmp4 = 1 << 26, - - /// bit 25 ADCxTDC3 - Trigger on HRTIM_TIMD compare match for compare register 3 - TimDCmp3 = 1 << 25, - - /// bit 24 ADCxTFPER - Trigger on HRTIM_TIMF period - TimFPeriod = 1 << 24, - - /// bit 23 ADCxTCPER - Trigger on HRTIM_TIMC period - TimCPeriod = 1 << 23, - - /// bit 22 ADCxTCC4 - Trigger on HRTIM_TIMC compare match for compare register 4 - TimCCmp4 = 1 << 22, - - /// bit 21 ADCxTCC3 - Trigger on HRTIM_TIMC compare match for compare register 3 - TimCCmp3 = 1 << 21, - - /// bit 20 ADCxTFC4 - Trigger on HRTIM_TIMF compare match for compare register 4 - TimFCmp4 = 1 << 20, - - /// bit 19 ADCxTBRST - Trigger on HRTIM_TIMB reset or counter roll-over - TimBRst = 1 << 19, - - /// bit 18 ADCxTBPER - Trigger on HRTIM_TIMB period - TimBPeriod = 1 << 18, - - /// bit 17 ADCxTBC4 - Trigger on HRTIM_TIMB compare match for compare register 4 - TimBCmp4 = 1 << 17, - - /// bit 16 ADCxTBC3 - Trigger on HRTIM_TIMB compare match for compare register 3 - TimBCmp3 = 1 << 16, - - /// bit 15 ADCxTFC3 - Trigger on HRTIM_TIMF compare match for compare register 3 - TimFCmp3 = 1 << 15, - - /// bit 14 ADCxTARST - Trigger on HRTIM_TIMA reset or counter roll-over - TimARst = 1 << 14, - - /// bit 13 ADCxTAPER - Trigger on HRTIM_TIMA period - TimAPeriod = 1 << 13, - - /// bit 12 ADCxTAC4 - Trigger on HRTIM_TIMA compare match for compare register 4 - TimACmp4 = 1 << 12, - - /// bit 11 ADCxTAC3 - Trigger on HRTIM_TIMA compare match for compare register 3 - TimACmp3 = 1 << 11, - - /// bit 10 ADCxTFC2 - Trigger on HRTIM_TIMF compare match for compare register 2 - TimFCmp2 = 1 << 10, - - // /// bit 9 ADCxEEV5 - // _ = 1 << 9, - - // /// bit 8 ADCxEEV4 - // _ = 1 << 8, - - // /// bit 7 ADCxEEV3 - // _ = 1 << 7, - - // /// bit 6 ADCxEEV2 - // _ = 1 << 6, - /// bit 5 ADCxEEV1 - // _ = 1 << 5, - - /// bit 4 ADCxMPER - Trigger on HRTIM_MASTER period - MasterPeriod = 1 << 4, - - /// bit 3 ADCxMC4 - Trigger on HRTIM_MASTER compare match for compare register 4 - MasterCmp4 = 1 << 3, - - /// bit 2 ADCxMC3 - Trigger on HRTIM_MASTER compare match for compare register 3 - MasterCmp3 = 1 << 2, - - /// bit 1 ADCxMC2 - Trigger on HRTIM_MASTER compare match for compare register 2 - MasterCmp2 = 1 << 1, - - /// bit 0 ADCxMC1 - Trigger on HRTIM_MASTER compare match for compare register 1 - MasterCmp1 = 1 << 0, -} - -pub enum AdcTriggerPostscaler { - None = 0, - Div2 = 1, - Div3 = 2, - Div4 = 3, - Div5 = 4, - Div6 = 5, - Div7 = 6, - Div8 = 7, - Div9 = 8, - Div10 = 9, - Div11 = 10, - Div12 = 11, - Div13 = 12, - Div14 = 13, - Div15 = 14, - Div16 = 15, - Div17 = 16, - Div18 = 17, - Div19 = 18, - Div20 = 19, - Div21 = 20, - Div22 = 21, - Div23 = 22, - Div24 = 23, - Div25 = 24, - Div26 = 25, - Div27 = 26, - Div28 = 27, - Div29 = 28, - Div30 = 29, - Div31 = 30, - Div32 = 31, -} - -pub enum Adc24Trigger { - /// bit 31 ADCxTERST - Trigger on HRTIM_TIME reset or counter roll-over - TimERst = 1 << 31, - - /// bit 30 ADCxTEC4 - Trigger on HRTIM_TIME compare match for compare register 4 - TimECmp4 = 1 << 30, - - /// bit 29 ADCxTEC3 - Trigger on HRTIM_TIME compare match for compare register 3 - TimECmp3 = 1 << 29, - - /// bit 28 ADCxTEC2 - Trigger on HRTIM_TIME compare match for compare register 2 - TimECmp2 = 1 << 28, - - /// bit 27 ADCxTDRST - Trigger on HRTIM_TIMD reset or counter roll-over - TimDRst = 1 << 27, - - /// bit 26 ADCxTDPER - Trigger on HRTIM_TIMD period - TimDPeriod = 1 << 26, - - /// bit 25 ADCxTDC4 - Trigger on HRTIM_TIMD compare match for compare register 4 - TimDCmp4 = 1 << 25, - - /// bit 24 ADCxTFPER - Trigger on HRTIM_TIMF period - TimFPeriod = 1 << 24, - - /// bit 23 ADCxTDC2 - Trigger on HRTIM_TIMD compare match for compare register 2 - TimDCmp2 = 1 << 23, - - /// bit 22 ADCxTCRST - Trigger on HRTIM_TIMC reset or counter roll-over - TimCRst = 1 << 22, - - /// bit 21 ADCxTCPER - Trigger on HRTIM_TIMC period - TimCPeriod = 1 << 21, - - /// bit 20 ADCxTCC4 - Trigger on HRTIM_TIMC compare match for compare register 4 - TimCCmp4 = 1 << 20, - - /// bit 19 ADCxTFC4 - Trigger on HRTIM_TIMF compare match for compare register 4 - TimFCmp4 = 1 << 19, - - /// bit 18 ADCxTCC2 - Trigger on HRTIM_TIMC compare match for compare register 2 - TimCCmp2 = 1 << 18, - - /// bit 17 ADCxTBPER - Trigger on HRTIM_TIMB period - TimBPeriod = 1 << 17, - - /// bit 16 ADCxTBC4 - Trigger on HRTIM_TIMB compare match for compare register 4 - TimBCmp4 = 1 << 16, - - /// bit 15 ADCxTFC3 - Trigger on HRTIM_TIMF compare match for compare register 3 - TimFCmp3 = 1 << 15, - - /// bit 14 ADCxTBC2 - Trigger on HRTIM_TIMB compare match for compare register 2 - TimBCmp2 = 1 << 14, - - /// bit 13 ADCxTAPER - Trigger on HRTIM_TIMA period - TimAPeriod = 1 << 13, - - /// bit 12 ADCxTAC4 - Trigger on HRTIM_TIMA compare match for compare register 4 - TimACmp4 = 1 << 12, - - /// bit 11 ADCxTFC2 - Trigger on HRTIM_TIMF compare match for compare register 2 - TimFCmp2 = 1 << 11, - - /// bit 10 ADCxTAC2 - Trigger on HRTIM_TIMA compare match for compare register 2 - TimACmp2 = 1 << 10, - - // /// bit 9 ADCxEEV10 - // _ = 1 << 9, - - // /// bit 8 ADCxEEV9 - // _ = 1 << 8, - - // /// bit 7 ADCxEEV8 - // _ = 1 << 7, - - // /// bit 6 ADCxEEV7 - // _ = 1 << 6, - - // /// bit 5 ADCxEEV6 - // _ = 1 << 5, - /// bit 4 ADCxMPER - Trigger on HRTIM_MASTER period - MasterPeriod = 1 << 4, - - /// bit 3 ADCxMC4 - Trigger on HRTIM_MASTER compare match for compare register 4 - MasterCmp4 = 1 << 3, - - /// bit 2 ADCxMC3 - Trigger on HRTIM_MASTER compare match for compare register 3 - MasterCmp3 = 1 << 2, - - /// bit 1 ADCxMC2 - Trigger on HRTIM_MASTER compare match for compare register 2 - MasterCmp2 = 1 << 1, - - /// bit 0 ADCxMC1 - Trigger on HRTIM_MASTER compare match for compare register 1 - MasterCmp1 = 1 << 0, -} - -pub enum Adc579Trigger { - // /// Trigger on F reset and counter roll-over - // _ = 31 - /// Trigger on HRTIM_TIMF period - TimFPeriod = 30, - - /// Trigger on HRTIM_TIMF compare match for compare register 4 - TimFCmp4 = 29, - - /// Trigger on HRTIM_TIMF compare match for compare register 3 - TimFCmp3 = 28, - - /// Trigger on HRTIM_TIMF compare match for compare register 2 - TimFCmp2 = 27, - - /// Trigger on HRTIM_TIME period - TimEPeriod = 26, - - /// Trigger on HRTIM_TIME compare match for compare register 4 - TimECmp4 = 25, - - /// Trigger on HRTIM_TIME compare match for compare register 3 - TimECmp3 = 24, - - /// Trigger on HRTIM_TIMD period - TimDPeriod = 23, - - /// Trigger on HRTIM_TIMD compare match for compare register 4 - TimDCmp4 = 22, - - /// Trigger on HRTIM_TIMD compare match for compare register 3 - TimDCmp3 = 21, - - /// Trigger on HRTIM_TIMC period - TimCPeriod = 20, - - /// Trigger on HRTIM_TIMC compare match for compare register 4 - TimCCmp4 = 19, - - /// Trigger on HRTIM_TIMC compare match for compare register 3 - TimCCmp3 = 18, - - // /// Trigger on B reset and counter roll-over - // _ = 17 - /// Trigger on HRTIM_TIMB period - TimBPeriod = 16, - - /// Trigger on HRTIM_TIMB compare match for compare register 4 - TimBCmp4 = 15, - - /// Trigger on HRTIM_TIMB compare match for compare register 3 - TimBCmp3 = 14, - - // /// Trigger on A reset and counter roll-over - // _ = 13 - /// Trigger on HRTIM_TIMA period - TimAPeriod = 12, - - /// Trigger on HRTIM_TIMA compare match for compare register 4 - TimACmp4 = 11, - - /// Trigger on HRTIM_TIMA compare match for compare register 3 - TimACmp3 = 10, - - // /// Trigger on EEV5 - // _ = 9, - - // /// Trigger on EEV4 - // _ = 8, - - // /// Trigger on EEV3 - // _ = 7, - - // /// Trigger on EEV2 - // _ = 6, - - // /// Trigger on EEV1 - // _ = 5, - /// Trigger on HRTIM_MASTER period - MasterPeriod = 4, - - /// Trigger on HRTIM_MASTER compare match for compare register 4 - MasterCmp4 = 3, - - /// Trigger on HRTIM_MASTER compare match for compare register 3 - MasterCmp3 = 2, - - /// Trigger on HRTIM_MASTER compare match for compare register 2 - MasterCmp2 = 1, - - /// Trigger on HRTIM_MASTER compare match for compare register 1 - MasterCmp1 = 0, -} - -pub enum Adc6810Trigger { - /// Trigger on HRTIM_TIMF period - TimFPeriod = 31, - - /// Trigger on HRTIM_TIMF compare match for compare register 4 - TimFCmp4 = 30, - - /// Trigger on HRTIM_TIMF compare match for compare register 3 - TimFCmp3 = 29, - - /// Trigger on HRTIM_TIMF compare match for compare register 2 - TimFCmp2 = 28, - - // /// Trigger on E reset and counter roll-over - // _ = 27 - /// Trigger on HRTIM_TIME compare match for compare register 4 - TimECmp4 = 26, - - /// Trigger on HRTIM_TIME compare match for compare register 3 - TimECmp3 = 25, - - /// Trigger on HRTIM_TIME compare match for compare register 2 - TimECmp2 = 24, - - // /// Trigger on D reset and counter roll-over - // _ = 23 - /// Trigger on HRTIM_TIMD period - TimDPeriod = 22, - - /// Trigger on HRTIM_TIMD compare match for compare register 4 - TimDCmp4 = 21, - - /// Trigger on HRTIM_TIMD compare match for compare register 2 - TimDCmp2 = 20, - - // /// Trigger on D reset and counter roll-over - // _ = 19 - /// Trigger on HRTIM_TIMC period - TimCPeriod = 18, - - /// Trigger on HRTIM_TIMC compare match for compare register 4 - TimCCmp4 = 17, - - /// Trigger on HRTIM_TIMC compare match for compare register 2 - TimCCmp2 = 16, - - /// Trigger on HRTIM_TIMB period - TimBPeriod = 15, - - /// Trigger on HRTIM_TIMB compare match for compare register 4 - TimBCmp4 = 14, - - /// Trigger on HRTIM_TIMB compare match for compare register 2 - TimBCmp2 = 13, - - /// Trigger on HRTIM_TIMA period - TimAPeriod = 12, - - /// Trigger on HRTIM_TIMA compare match for compare register 4 - TimACmp4 = 11, - - /// Trigger on HRTIM_TIMA compare match for compare register 2 - TimACmp2 = 10, - - // /// Trigger on EEV10 - // _ = 9, - - // /// Trigger on EEV9 - // _ = 8, - - // /// Trigger on EEV8 - // _ = 7, - - // /// Trigger on EEV7 - // _ = 6, - - // /// Trigger on EEV6 - // _ = 5, - /// Trigger on HRTIM_MASTER period - MasterPeriod = 4, - - /// Trigger on HRTIM_MASTER compare match for compare register 4 - MasterCmp4 = 3, - - /// Trigger on HRTIM_MASTER compare match for compare register 3 - MasterCmp3 = 2, - - /// Trigger on HRTIM_MASTER compare match for compare register 2 - MasterCmp2 = 1, - - /// Trigger on HRTIM_MASTER compare match for compare register 1 - MasterCmp1 = 0, -} - -macro_rules! impl_flt_monitor { - ($($t:ident: ($fltx:ident, $fltxc:ident),)+) => {$( - pub struct $t { - _x: PhantomData<()> - } - - impl FaultMonitor for $t { - fn is_fault_active(&self) -> bool { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.isr.read().$fltx().bit() - } - - fn clear_fault(&mut self) { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.icr.write(|w| w.$fltxc().set_bit()); - } - - // TODO: Should we have our own trait since it does not seem possible to implement this - fn set_fault(&mut self) { - todo!() - } - } - )+}; -} - -impl_flt_monitor!( - FltMonitorSys: (sysflt, sysfltc), - FltMonitor1: (flt1, flt1c), - FltMonitor2: (flt2, flt2c), - FltMonitor3: (flt3, flt3c), - FltMonitor4: (flt4, flt4c), - FltMonitor5: (flt5, flt5c), - FltMonitor6: (flt6, flt6c), -); +impl HrtimChannel for CH2 {} \ No newline at end of file diff --git a/src/pwm/hrtim/calibration.rs b/src/pwm/hrtim/calibration.rs new file mode 100644 index 00000000..fd77a34f --- /dev/null +++ b/src/pwm/hrtim/calibration.rs @@ -0,0 +1,978 @@ +use crate::stm32::{HRTIM_COMMON, RCC}; + +use super::HrControltExt; + +pub trait HrControltExt { + fn hr_control(self, _rcc: &mut Rcc) -> HrTimOngoingCalibration; +} + +impl HrControltExt for HRTIM_COMMON { + fn hr_control(self, _rcc: &mut Rcc) -> HrTimOngoingCalibration { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + + unsafe { + let rcc_ptr = &*RCC::ptr(); + + HRTIM_COMMON::enable(rcc_ptr); + HRTIM_COMMON::reset(rcc_ptr); + } + + // Start calibration procedure + common + .dllcr + .write(|w| w.cal().set_bit().calen().clear_bit()); + + HrTimOngoingCalibration { + adc_trigger1_bits: 0, + adc_trigger2_bits: 0, + adc_trigger3_bits: 0, + adc_trigger4_bits: 0, + + adc_trigger5_bits: 0, + adc_trigger6_bits: 0, + adc_trigger7_bits: 0, + adc_trigger8_bits: 0, + adc_trigger9_bits: 0, + adc_trigger10_bits: 0, + + adc_trigger1_postscaler: AdcTriggerPostscaler::None, + adc_trigger2_postscaler: AdcTriggerPostscaler::None, + adc_trigger3_postscaler: AdcTriggerPostscaler::None, + adc_trigger4_postscaler: AdcTriggerPostscaler::None, + + adc_trigger5_postscaler: AdcTriggerPostscaler::None, + adc_trigger6_postscaler: AdcTriggerPostscaler::None, + adc_trigger7_postscaler: AdcTriggerPostscaler::None, + adc_trigger8_postscaler: AdcTriggerPostscaler::None, + adc_trigger9_postscaler: AdcTriggerPostscaler::None, + adc_trigger10_postscaler: AdcTriggerPostscaler::None, + + flt_divider: SamplingClkDiv::None, + eev_divider: SamplingClkDiv::None, + } + } +} + +pub struct HrTimOngoingCalibration { + adc_trigger1_bits: u32, + adc_trigger2_bits: u32, + adc_trigger3_bits: u32, + adc_trigger4_bits: u32, + + adc_trigger5_bits: u8, + adc_trigger6_bits: u8, + adc_trigger7_bits: u8, + adc_trigger8_bits: u8, + adc_trigger9_bits: u8, + adc_trigger10_bits: u8, + + adc_trigger1_postscaler: AdcTriggerPostscaler, + adc_trigger2_postscaler: AdcTriggerPostscaler, + adc_trigger3_postscaler: AdcTriggerPostscaler, + adc_trigger4_postscaler: AdcTriggerPostscaler, + + adc_trigger5_postscaler: AdcTriggerPostscaler, + adc_trigger6_postscaler: AdcTriggerPostscaler, + adc_trigger7_postscaler: AdcTriggerPostscaler, + adc_trigger8_postscaler: AdcTriggerPostscaler, + adc_trigger9_postscaler: AdcTriggerPostscaler, + adc_trigger10_postscaler: AdcTriggerPostscaler, + + flt_divider: SamplingClkDiv, + eev_divider: SamplingClkDiv, +} + +impl HrTimOngoingCalibration { + /// SAFETY: Calibration needs to be done before calling this + unsafe fn init(self) -> (HrPwmControl, FaultInputs) { + use Adc13Trigger as Ad13T; + use Adc24Trigger as Ad24T; + + let common = unsafe { &*HRTIM_COMMON::ptr() }; + + let Self { + adc_trigger1_bits: ad1_bits, + adc_trigger2_bits: ad2_bits, + adc_trigger3_bits: ad3_bits, + adc_trigger4_bits: ad4_bits, + + adc_trigger5_bits: ad5_bits, + adc_trigger6_bits: ad6_bits, + adc_trigger7_bits: ad7_bits, + adc_trigger8_bits: ad8_bits, + adc_trigger9_bits: ad9_bits, + adc_trigger10_bits: ad10_bits, + + adc_trigger1_postscaler, + adc_trigger2_postscaler, + adc_trigger3_postscaler, + adc_trigger4_postscaler, + + adc_trigger5_postscaler, + adc_trigger6_postscaler, + adc_trigger7_postscaler, + adc_trigger8_postscaler, + adc_trigger9_postscaler, + adc_trigger10_postscaler, + + flt_divider, + eev_divider, + } = self; + + unsafe { + // Enable periodic calibration + // with f_hrtim at 170MHz, these settings leads to + // a period of about 6.2ms + common + .dllcr + .modify(|_r, w| w.calrte().bits(0b00).cal().set_bit().calen().clear_bit()); + common.fltinr2.write(|w| w.fltsd().bits(flt_divider as u8)); + common.eecr3.write(|w| w.eevsd().bits(eev_divider as u8)); + + common.adc1r.write(|w| { + w.eper() + .bit(ad1_bits | Ad13T::TimEPeriod as u32 != 0) + .ec4() + .bit(ad1_bits | Ad13T::TimECmp4 as u32 != 0) + .ec3() + .bit(ad1_bits | Ad13T::TimECmp3 as u32 != 0) + //.frst() + .dper() + .bit(ad1_bits | Ad13T::TimDPeriod as u32 != 0) + .dc4() + .bit(ad1_bits | Ad13T::TimDCmp4 as u32 != 0) + .dc3() + .bit(ad1_bits | Ad13T::TimDCmp3 as u32 != 0) + .fper() + .bit(ad1_bits | Ad13T::TimFPeriod as u32 != 0) + .cper() + .bit(ad1_bits | Ad13T::TimCPeriod as u32 != 0) + .cc4() + .bit(ad1_bits | Ad13T::TimCCmp4 as u32 != 0) + .cc3() + .bit(ad1_bits | Ad13T::TimCCmp3 as u32 != 0) + .fc4() + .bit(ad1_bits | Ad13T::TimFCmp4 as u32 != 0) + //.brst() + .bper() + .bit(ad1_bits | Ad13T::TimBPeriod as u32 != 0) + .bc4() + .bit(ad1_bits | Ad13T::TimBCmp4 as u32 != 0) + .bc3() + .bit(ad1_bits | Ad13T::TimBCmp3 as u32 != 0) + .fc3() + .bit(ad1_bits | Ad13T::TimFCmp3 as u32 != 0) + //.arst() + .aper() + .bit(ad1_bits | Ad13T::TimAPeriod as u32 != 0) + .ac4() + .bit(ad1_bits | Ad13T::TimACmp4 as u32 != 0) + .ac3() + .bit(ad1_bits | Ad13T::TimACmp3 as u32 != 0) + .fc2() + .bit(ad1_bits | Ad13T::TimFCmp2 as u32 != 0) + //.eev5().bit(ad1_bits | Ad13T::_ as u32) + //.eev4().bit(ad1_bits | Ad13T::_ as u32) + //.eev3().bit(ad1_bits | Ad13T::_ as u32) + //.eev2().bit(ad1_bits | Ad13T::_ as u32) + //.eev1().bit(ad1_bits | Ad13T::_ as u32) + .mper() + .bit(ad1_bits | Ad13T::MasterPeriod as u32 != 0) + .mc4() + .bit(ad1_bits | Ad13T::MasterCmp4 as u32 != 0) + .mc3() + .bit(ad1_bits | Ad13T::MasterCmp3 as u32 != 0) + .mc2() + .bit(ad1_bits | Ad13T::MasterCmp2 as u32 != 0) + .mc1() + .bit(ad1_bits | Ad13T::MasterCmp1 as u32 != 0) + }); + + common.adc3r.write(|w| { + w.eper() + .bit(ad3_bits | Ad13T::TimEPeriod as u32 != 0) + .ec4() + .bit(ad3_bits | Ad13T::TimECmp4 as u32 != 0) + .ec3() + .bit(ad3_bits | Ad13T::TimECmp3 as u32 != 0) + //.frst() + .dper() + .bit(ad3_bits | Ad13T::TimDPeriod as u32 != 0) + .dc4() + .bit(ad3_bits | Ad13T::TimDCmp4 as u32 != 0) + .dc3() + .bit(ad3_bits | Ad13T::TimDCmp3 as u32 != 0) + .fper() + .bit(ad3_bits | Ad13T::TimFPeriod as u32 != 0) + .cper() + .bit(ad3_bits | Ad13T::TimCPeriod as u32 != 0) + .cc4() + .bit(ad3_bits | Ad13T::TimCCmp4 as u32 != 0) + .cc3() + .bit(ad3_bits | Ad13T::TimCCmp3 as u32 != 0) + .fc4() + .bit(ad3_bits | Ad13T::TimFCmp4 as u32 != 0) + //.brst() + .bper() + .bit(ad3_bits | Ad13T::TimBPeriod as u32 != 0) + .bc4() + .bit(ad3_bits | Ad13T::TimBCmp4 as u32 != 0) + .bc3() + .bit(ad3_bits | Ad13T::TimBCmp3 as u32 != 0) + .fc3() + .bit(ad3_bits | Ad13T::TimFCmp3 as u32 != 0) + //.arst() + .aper() + .bit(ad3_bits | Ad13T::TimAPeriod as u32 != 0) + .ac4() + .bit(ad3_bits | Ad13T::TimACmp4 as u32 != 0) + .ac3() + .bit(ad3_bits | Ad13T::TimACmp3 as u32 != 0) + .fc2() + .bit(ad3_bits | Ad13T::TimFCmp2 as u32 != 0) + //.eev5().bit(ad3_bits | Ad13T::_ as u32) + //.eev4().bit(ad3_bits | Ad13T::_ as u32) + //.eev3().bit(ad3_bits | Ad13T::_ as u32) + //.eev2().bit(ad3_bits | Ad13T::_ as u32) + //.eev1().bit(ad3_bits | Ad13T::_ as u32) + .mper() + .bit(ad3_bits | Ad13T::MasterPeriod as u32 != 0) + .mc4() + .bit(ad3_bits | Ad13T::MasterCmp4 as u32 != 0) + .mc3() + .bit(ad3_bits | Ad13T::MasterCmp3 as u32 != 0) + .mc2() + .bit(ad3_bits | Ad13T::MasterCmp2 as u32 != 0) + .mc1() + .bit(ad3_bits | Ad13T::MasterCmp1 as u32 != 0) + }); + + common.adc2r.write(|w| { + w + //.erst() + .ec4() + .bit(ad2_bits | Ad24T::TimECmp4 as u32 != 0) + .ec3() + .bit(ad2_bits | Ad24T::TimECmp3 as u32 != 0) + .ec2() + .bit(ad2_bits | Ad24T::TimECmp2 as u32 != 0) + //.drst().bit(ad2_bits | Ad24T::_ as u32 != 0) + .dper() + .bit(ad2_bits | Ad24T::TimDPeriod as u32 != 0) + .dc4() + .bit(ad2_bits | Ad24T::TimDCmp4 as u32 != 0) + .fper() + .bit(ad2_bits | Ad24T::TimFPeriod as u32 != 0) + .dc2() + .bit(ad2_bits | Ad24T::TimDCmp2 as u32 != 0) + //.crst().bit(ad2_bits | Ad24T::_ as u32 != 0) + .cper() + .bit(ad2_bits | Ad24T::TimCPeriod as u32 != 0) + .cc4() + .bit(ad2_bits | Ad24T::TimCCmp4 as u32 != 0) + .fc4() + .bit(ad2_bits | Ad24T::TimFCmp4 as u32 != 0) + .cc2() + .bit(ad2_bits | Ad24T::TimCCmp2 as u32 != 0) + .bper() + .bit(ad2_bits | Ad24T::TimBPeriod as u32 != 0) + .bc4() + .bit(ad2_bits | Ad24T::TimBCmp4 as u32 != 0) + .fc3() + .bit(ad2_bits | Ad24T::TimFCmp3 as u32 != 0) + .bc2() + .bit(ad2_bits | Ad24T::TimBCmp2 as u32 != 0) + .aper() + .bit(ad2_bits | Ad24T::TimAPeriod as u32 != 0) + .ac4() + .bit(ad2_bits | Ad24T::TimACmp4 as u32 != 0) + .fc2() + .bit(ad2_bits | Ad24T::TimFCmp2 as u32 != 0) + .ac2() + .bit(ad2_bits | Ad24T::TimACmp2 as u32 != 0) + //.eev10() + //.eev9() + //.eev8() + //.eev7() + //.eev6() + .mper() + .bit(ad2_bits | Ad24T::MasterPeriod as u32 != 0) + .mc4() + .bit(ad2_bits | Ad24T::MasterCmp4 as u32 != 0) + .mc3() + .bit(ad2_bits | Ad24T::MasterCmp3 as u32 != 0) + .mc2() + .bit(ad2_bits | Ad24T::MasterCmp2 as u32 != 0) + .mc1() + .bit(ad2_bits | Ad24T::MasterCmp1 as u32 != 0) + }); + + common.adc4r.write(|w| { + w + //.erst() + .ec4() + .bit(ad4_bits | Ad24T::TimECmp4 as u32 != 0) + .ec3() + .bit(ad4_bits | Ad24T::TimECmp3 as u32 != 0) + .ec2() + .bit(ad4_bits | Ad24T::TimECmp2 as u32 != 0) + //.drst().bit(ad4_bits | Ad24T::_ as u32 != 0) + .dper() + .bit(ad4_bits | Ad24T::TimDPeriod as u32 != 0) + .dc4() + .bit(ad4_bits | Ad24T::TimDCmp4 as u32 != 0) + .fper() + .bit(ad4_bits | Ad24T::TimFPeriod as u32 != 0) + .dc2() + .bit(ad4_bits | Ad24T::TimDCmp2 as u32 != 0) + //.crst().bit(ad4_bits | Ad24T::_ as u32 != 0) + .cper() + .bit(ad4_bits | Ad24T::TimCPeriod as u32 != 0) + .cc4() + .bit(ad4_bits | Ad24T::TimCCmp4 as u32 != 0) + .fc4() + .bit(ad4_bits | Ad24T::TimFCmp4 as u32 != 0) + .cc2() + .bit(ad4_bits | Ad24T::TimCCmp2 as u32 != 0) + .bper() + .bit(ad4_bits | Ad24T::TimBPeriod as u32 != 0) + .bc4() + .bit(ad4_bits | Ad24T::TimBCmp4 as u32 != 0) + .fc3() + .bit(ad4_bits | Ad24T::TimFCmp3 as u32 != 0) + .bc2() + .bit(ad4_bits | Ad24T::TimBCmp2 as u32 != 0) + .aper() + .bit(ad4_bits | Ad24T::TimAPeriod as u32 != 0) + .ac4() + .bit(ad4_bits | Ad24T::TimACmp4 as u32 != 0) + .fc2() + .bit(ad4_bits | Ad24T::TimFCmp2 as u32 != 0) + .ac2() + .bit(ad4_bits | Ad24T::TimACmp2 as u32 != 0) + //.eev10() + //.eev9() + //.eev8() + //.eev7() + //.eev6() + .mper() + .bit(ad4_bits | Ad24T::MasterPeriod as u32 != 0) + .mc4() + .bit(ad4_bits | Ad24T::MasterCmp4 as u32 != 0) + .mc3() + .bit(ad4_bits | Ad24T::MasterCmp3 as u32 != 0) + .mc2() + .bit(ad4_bits | Ad24T::MasterCmp2 as u32 != 0) + .mc1() + .bit(ad4_bits | Ad24T::MasterCmp1 as u32 != 0) + }); + + common.adcer.write(|w| { + w.adc5trg() + .variant(ad5_bits) + .adc6trg() + .variant(ad6_bits) + .adc7trg() + .variant(ad7_bits) + .adc8trg() + .variant(ad8_bits) + .adc9trg() + .variant(ad9_bits) + .adc10trg() + .variant(ad10_bits) + }); + + common.adcps1.write(|w| { + w.adc1psc() + .bits(adc_trigger1_postscaler as u8) + .adc2psc() + .bits(adc_trigger2_postscaler as u8) + .adc3psc() + .bits(adc_trigger3_postscaler as u8) + .adc4psc() + .bits(adc_trigger4_postscaler as u8) + .adc5psc() + .bits(adc_trigger5_postscaler as u8) + }); + + common.adcps2.write(|w| { + w.adc6psc() + .bits(adc_trigger6_postscaler as u8) + .adc7psc() + .bits(adc_trigger7_postscaler as u8) + .adc8psc() + .bits(adc_trigger8_postscaler as u8) + .adc9psc() + .bits(adc_trigger9_postscaler as u8) + .adc10psc() + .bits(adc_trigger10_postscaler as u8) + }); + + // TODO: Adc trigger 5-10 + } + + ( + HrPwmControl { + _x: PhantomData, + fault_sys: FltMonitorSys { _x: PhantomData }, + fault_1: FltMonitor1 { _x: PhantomData }, + fault_2: FltMonitor2 { _x: PhantomData }, + fault_3: FltMonitor3 { _x: PhantomData }, + fault_4: FltMonitor4 { _x: PhantomData }, + fault_5: FltMonitor5 { _x: PhantomData }, + fault_6: FltMonitor6 { _x: PhantomData }, + }, + FaultInputs { + fault_input1: FaultInput1 { _x: PhantomData }, + fault_input2: FaultInput2 { _x: PhantomData }, + fault_input3: FaultInput3 { _x: PhantomData }, + fault_input4: FaultInput4 { _x: PhantomData }, + fault_input5: FaultInput5 { _x: PhantomData }, + fault_input6: FaultInput6 { _x: PhantomData }, + }, + ) + } + + pub fn wait_for_calibration(self) -> (HrPwmControl, FaultInputs) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + while common.isr.read().dllrdy().bit_is_clear() { + // Wait until ready + } + + // Calibration is now done, it is safe to continue + unsafe { self.init() } + } + + pub fn enable_adc_trigger1_source(mut self, trigger: Adc13Trigger) -> Self { + self.adc_trigger1_bits |= trigger as u32; + self + } + + pub fn enable_adc_trigger2_source(mut self, trigger: Adc24Trigger) -> Self { + self.adc_trigger2_bits |= trigger as u32; + self + } + + pub fn enable_adc_trigger3_source(mut self, trigger: Adc13Trigger) -> Self { + self.adc_trigger3_bits |= trigger as u32; + self + } + + pub fn enable_adc_trigger4_source(mut self, trigger: Adc24Trigger) -> Self { + self.adc_trigger4_bits |= trigger as u32; + self + } + + pub fn enable_adc_trigger5_source(mut self, trigger: Adc579Trigger) -> Self { + self.adc_trigger5_bits = trigger as u8; + self + } + + pub fn enable_adc_trigger6_source(mut self, trigger: Adc6810Trigger) -> Self { + self.adc_trigger6_bits = trigger as u8; + self + } + + pub fn enable_adc_trigger7_source(mut self, trigger: Adc579Trigger) -> Self { + self.adc_trigger7_bits = trigger as u8; + self + } + + pub fn enable_adc_trigger8_source(mut self, trigger: Adc6810Trigger) -> Self { + self.adc_trigger8_bits = trigger as u8; + self + } + + pub fn enable_adc_trigger9_source(mut self, trigger: Adc579Trigger) -> Self { + self.adc_trigger9_bits = trigger as u8; + self + } + + pub fn enable_adc_trigger10_source(mut self, trigger: Adc6810Trigger) -> Self { + self.adc_trigger10_bits = trigger as u8; + self + } + + pub fn set_adc1_trigger_psc(mut self, post_scaler: AdcTriggerPostscaler) -> Self { + self.adc_trigger1_postscaler = post_scaler; + self + } + + pub fn set_adc2_trigger_psc(mut self, post_scaler: AdcTriggerPostscaler) -> Self { + self.adc_trigger2_postscaler = post_scaler; + self + } + + pub fn set_adc3_trigger_psc(mut self, post_scaler: AdcTriggerPostscaler) -> Self { + self.adc_trigger3_postscaler = post_scaler; + self + } + + pub fn set_adc4_trigger_psc(mut self, post_scaler: AdcTriggerPostscaler) -> Self { + self.adc_trigger4_postscaler = post_scaler; + self + } + + pub fn set_fault_sampling_division(mut self, divider: SamplingClkDiv) -> Self { + self.flt_divider = divider; + self + } + + pub fn set_eev_sampling_division(mut self, divider: SamplingClkDiv) -> Self { + self.eev_divider = divider; + self + } + + // TODO: Adc trigger 5-10 +} + +pub struct HrPwmControl { + _x: PhantomData<()>, + + pub fault_sys: FltMonitorSys, + pub fault_1: FltMonitor1, + pub fault_2: FltMonitor2, + pub fault_3: FltMonitor3, + pub fault_4: FltMonitor4, + pub fault_5: FltMonitor5, + pub fault_6: FltMonitor6, +} +pub enum AdcTriggerPostscaler { + None = 0, + Div2 = 1, + Div3 = 2, + Div4 = 3, + Div5 = 4, + Div6 = 5, + Div7 = 6, + Div8 = 7, + Div9 = 8, + Div10 = 9, + Div11 = 10, + Div12 = 11, + Div13 = 12, + Div14 = 13, + Div15 = 14, + Div16 = 15, + Div17 = 16, + Div18 = 17, + Div19 = 18, + Div20 = 19, + Div21 = 20, + Div22 = 21, + Div23 = 22, + Div24 = 23, + Div25 = 24, + Div26 = 25, + Div27 = 26, + Div28 = 27, + Div29 = 28, + Div30 = 29, + Div31 = 30, + Div32 = 31, +} + +/// The divsion ratio between f_hrtim and the fault signal sampling clock for digital filters +pub enum SamplingClkDiv { + /// No division + /// + /// fault signal sampling clock f_flts = f_hrtim + None = 0b00, + + /// 1/2 + /// + /// fault signal sampling clock f_flts = f_hrtim / 2 + Two = 0b01, + + /// 1/4 + /// + /// fault signal sampling clock f_flts = f_hrtim / 4 + Four = 0b10, + + /// 1/8 + /// + /// fault signal sampling clock f_flts = f_hrtim / 8 + Eight = 0b11, +} + +pub enum Adc13Trigger { + /// bit 31 ADCxTEPER - Trigger on HRTIM_TIME period + TimEPeriod = 1 << 31, + + /// bit 30 ADCxTEC4 - Trigger on HRTIM_TIME compare match for compare register 4 + TimECmp4 = 1 << 30, + + /// bit 29 ADCxTEC3 - Trigger on HRTIM_TIME compare match for compare register 3 + TimECmp3 = 1 << 29, + + /// bit 28 ADCxTFRST - Trigger on HRTIM_TIMF reset or counter roll-over + TimFRst = 1 << 28, + + /// bit 27 ADCxTDPER - Trigger on HRTIM_TIMD period + TimDPeriod = 1 << 27, + + /// bit 26 ADCxTDC4 - Trigger on HRTIM_TIMD compare match for compare register 4 + TimDCmp4 = 1 << 26, + + /// bit 25 ADCxTDC3 - Trigger on HRTIM_TIMD compare match for compare register 3 + TimDCmp3 = 1 << 25, + + /// bit 24 ADCxTFPER - Trigger on HRTIM_TIMF period + TimFPeriod = 1 << 24, + + /// bit 23 ADCxTCPER - Trigger on HRTIM_TIMC period + TimCPeriod = 1 << 23, + + /// bit 22 ADCxTCC4 - Trigger on HRTIM_TIMC compare match for compare register 4 + TimCCmp4 = 1 << 22, + + /// bit 21 ADCxTCC3 - Trigger on HRTIM_TIMC compare match for compare register 3 + TimCCmp3 = 1 << 21, + + /// bit 20 ADCxTFC4 - Trigger on HRTIM_TIMF compare match for compare register 4 + TimFCmp4 = 1 << 20, + + /// bit 19 ADCxTBRST - Trigger on HRTIM_TIMB reset or counter roll-over + TimBRst = 1 << 19, + + /// bit 18 ADCxTBPER - Trigger on HRTIM_TIMB period + TimBPeriod = 1 << 18, + + /// bit 17 ADCxTBC4 - Trigger on HRTIM_TIMB compare match for compare register 4 + TimBCmp4 = 1 << 17, + + /// bit 16 ADCxTBC3 - Trigger on HRTIM_TIMB compare match for compare register 3 + TimBCmp3 = 1 << 16, + + /// bit 15 ADCxTFC3 - Trigger on HRTIM_TIMF compare match for compare register 3 + TimFCmp3 = 1 << 15, + + /// bit 14 ADCxTARST - Trigger on HRTIM_TIMA reset or counter roll-over + TimARst = 1 << 14, + + /// bit 13 ADCxTAPER - Trigger on HRTIM_TIMA period + TimAPeriod = 1 << 13, + + /// bit 12 ADCxTAC4 - Trigger on HRTIM_TIMA compare match for compare register 4 + TimACmp4 = 1 << 12, + + /// bit 11 ADCxTAC3 - Trigger on HRTIM_TIMA compare match for compare register 3 + TimACmp3 = 1 << 11, + + /// bit 10 ADCxTFC2 - Trigger on HRTIM_TIMF compare match for compare register 2 + TimFCmp2 = 1 << 10, + + // /// bit 9 ADCxEEV5 + // _ = 1 << 9, + + // /// bit 8 ADCxEEV4 + // _ = 1 << 8, + + // /// bit 7 ADCxEEV3 + // _ = 1 << 7, + + // /// bit 6 ADCxEEV2 + // _ = 1 << 6, + /// bit 5 ADCxEEV1 + // _ = 1 << 5, + + /// bit 4 ADCxMPER - Trigger on HRTIM_MASTER period + MasterPeriod = 1 << 4, + + /// bit 3 ADCxMC4 - Trigger on HRTIM_MASTER compare match for compare register 4 + MasterCmp4 = 1 << 3, + + /// bit 2 ADCxMC3 - Trigger on HRTIM_MASTER compare match for compare register 3 + MasterCmp3 = 1 << 2, + + /// bit 1 ADCxMC2 - Trigger on HRTIM_MASTER compare match for compare register 2 + MasterCmp2 = 1 << 1, + + /// bit 0 ADCxMC1 - Trigger on HRTIM_MASTER compare match for compare register 1 + MasterCmp1 = 1 << 0, +} + +pub enum Adc24Trigger { + /// bit 31 ADCxTERST - Trigger on HRTIM_TIME reset or counter roll-over + TimERst = 1 << 31, + + /// bit 30 ADCxTEC4 - Trigger on HRTIM_TIME compare match for compare register 4 + TimECmp4 = 1 << 30, + + /// bit 29 ADCxTEC3 - Trigger on HRTIM_TIME compare match for compare register 3 + TimECmp3 = 1 << 29, + + /// bit 28 ADCxTEC2 - Trigger on HRTIM_TIME compare match for compare register 2 + TimECmp2 = 1 << 28, + + /// bit 27 ADCxTDRST - Trigger on HRTIM_TIMD reset or counter roll-over + TimDRst = 1 << 27, + + /// bit 26 ADCxTDPER - Trigger on HRTIM_TIMD period + TimDPeriod = 1 << 26, + + /// bit 25 ADCxTDC4 - Trigger on HRTIM_TIMD compare match for compare register 4 + TimDCmp4 = 1 << 25, + + /// bit 24 ADCxTFPER - Trigger on HRTIM_TIMF period + TimFPeriod = 1 << 24, + + /// bit 23 ADCxTDC2 - Trigger on HRTIM_TIMD compare match for compare register 2 + TimDCmp2 = 1 << 23, + + /// bit 22 ADCxTCRST - Trigger on HRTIM_TIMC reset or counter roll-over + TimCRst = 1 << 22, + + /// bit 21 ADCxTCPER - Trigger on HRTIM_TIMC period + TimCPeriod = 1 << 21, + + /// bit 20 ADCxTCC4 - Trigger on HRTIM_TIMC compare match for compare register 4 + TimCCmp4 = 1 << 20, + + /// bit 19 ADCxTFC4 - Trigger on HRTIM_TIMF compare match for compare register 4 + TimFCmp4 = 1 << 19, + + /// bit 18 ADCxTCC2 - Trigger on HRTIM_TIMC compare match for compare register 2 + TimCCmp2 = 1 << 18, + + /// bit 17 ADCxTBPER - Trigger on HRTIM_TIMB period + TimBPeriod = 1 << 17, + + /// bit 16 ADCxTBC4 - Trigger on HRTIM_TIMB compare match for compare register 4 + TimBCmp4 = 1 << 16, + + /// bit 15 ADCxTFC3 - Trigger on HRTIM_TIMF compare match for compare register 3 + TimFCmp3 = 1 << 15, + + /// bit 14 ADCxTBC2 - Trigger on HRTIM_TIMB compare match for compare register 2 + TimBCmp2 = 1 << 14, + + /// bit 13 ADCxTAPER - Trigger on HRTIM_TIMA period + TimAPeriod = 1 << 13, + + /// bit 12 ADCxTAC4 - Trigger on HRTIM_TIMA compare match for compare register 4 + TimACmp4 = 1 << 12, + + /// bit 11 ADCxTFC2 - Trigger on HRTIM_TIMF compare match for compare register 2 + TimFCmp2 = 1 << 11, + + /// bit 10 ADCxTAC2 - Trigger on HRTIM_TIMA compare match for compare register 2 + TimACmp2 = 1 << 10, + + // /// bit 9 ADCxEEV10 + // _ = 1 << 9, + + // /// bit 8 ADCxEEV9 + // _ = 1 << 8, + + // /// bit 7 ADCxEEV8 + // _ = 1 << 7, + + // /// bit 6 ADCxEEV7 + // _ = 1 << 6, + + // /// bit 5 ADCxEEV6 + // _ = 1 << 5, + /// bit 4 ADCxMPER - Trigger on HRTIM_MASTER period + MasterPeriod = 1 << 4, + + /// bit 3 ADCxMC4 - Trigger on HRTIM_MASTER compare match for compare register 4 + MasterCmp4 = 1 << 3, + + /// bit 2 ADCxMC3 - Trigger on HRTIM_MASTER compare match for compare register 3 + MasterCmp3 = 1 << 2, + + /// bit 1 ADCxMC2 - Trigger on HRTIM_MASTER compare match for compare register 2 + MasterCmp2 = 1 << 1, + + /// bit 0 ADCxMC1 - Trigger on HRTIM_MASTER compare match for compare register 1 + MasterCmp1 = 1 << 0, +} + +pub enum Adc579Trigger { + // /// Trigger on F reset and counter roll-over + // _ = 31 + /// Trigger on HRTIM_TIMF period + TimFPeriod = 30, + + /// Trigger on HRTIM_TIMF compare match for compare register 4 + TimFCmp4 = 29, + + /// Trigger on HRTIM_TIMF compare match for compare register 3 + TimFCmp3 = 28, + + /// Trigger on HRTIM_TIMF compare match for compare register 2 + TimFCmp2 = 27, + + /// Trigger on HRTIM_TIME period + TimEPeriod = 26, + + /// Trigger on HRTIM_TIME compare match for compare register 4 + TimECmp4 = 25, + + /// Trigger on HRTIM_TIME compare match for compare register 3 + TimECmp3 = 24, + + /// Trigger on HRTIM_TIMD period + TimDPeriod = 23, + + /// Trigger on HRTIM_TIMD compare match for compare register 4 + TimDCmp4 = 22, + + /// Trigger on HRTIM_TIMD compare match for compare register 3 + TimDCmp3 = 21, + + /// Trigger on HRTIM_TIMC period + TimCPeriod = 20, + + /// Trigger on HRTIM_TIMC compare match for compare register 4 + TimCCmp4 = 19, + + /// Trigger on HRTIM_TIMC compare match for compare register 3 + TimCCmp3 = 18, + + // /// Trigger on B reset and counter roll-over + // _ = 17 + /// Trigger on HRTIM_TIMB period + TimBPeriod = 16, + + /// Trigger on HRTIM_TIMB compare match for compare register 4 + TimBCmp4 = 15, + + /// Trigger on HRTIM_TIMB compare match for compare register 3 + TimBCmp3 = 14, + + // /// Trigger on A reset and counter roll-over + // _ = 13 + /// Trigger on HRTIM_TIMA period + TimAPeriod = 12, + + /// Trigger on HRTIM_TIMA compare match for compare register 4 + TimACmp4 = 11, + + /// Trigger on HRTIM_TIMA compare match for compare register 3 + TimACmp3 = 10, + + // /// Trigger on EEV5 + // _ = 9, + + // /// Trigger on EEV4 + // _ = 8, + + // /// Trigger on EEV3 + // _ = 7, + + // /// Trigger on EEV2 + // _ = 6, + + // /// Trigger on EEV1 + // _ = 5, + /// Trigger on HRTIM_MASTER period + MasterPeriod = 4, + + /// Trigger on HRTIM_MASTER compare match for compare register 4 + MasterCmp4 = 3, + + /// Trigger on HRTIM_MASTER compare match for compare register 3 + MasterCmp3 = 2, + + /// Trigger on HRTIM_MASTER compare match for compare register 2 + MasterCmp2 = 1, + + /// Trigger on HRTIM_MASTER compare match for compare register 1 + MasterCmp1 = 0, +} + +pub enum Adc6810Trigger { + /// Trigger on HRTIM_TIMF period + TimFPeriod = 31, + + /// Trigger on HRTIM_TIMF compare match for compare register 4 + TimFCmp4 = 30, + + /// Trigger on HRTIM_TIMF compare match for compare register 3 + TimFCmp3 = 29, + + /// Trigger on HRTIM_TIMF compare match for compare register 2 + TimFCmp2 = 28, + + // /// Trigger on E reset and counter roll-over + // _ = 27 + /// Trigger on HRTIM_TIME compare match for compare register 4 + TimECmp4 = 26, + + /// Trigger on HRTIM_TIME compare match for compare register 3 + TimECmp3 = 25, + + /// Trigger on HRTIM_TIME compare match for compare register 2 + TimECmp2 = 24, + + // /// Trigger on D reset and counter roll-over + // _ = 23 + /// Trigger on HRTIM_TIMD period + TimDPeriod = 22, + + /// Trigger on HRTIM_TIMD compare match for compare register 4 + TimDCmp4 = 21, + + /// Trigger on HRTIM_TIMD compare match for compare register 2 + TimDCmp2 = 20, + + // /// Trigger on D reset and counter roll-over + // _ = 19 + /// Trigger on HRTIM_TIMC period + TimCPeriod = 18, + + /// Trigger on HRTIM_TIMC compare match for compare register 4 + TimCCmp4 = 17, + + /// Trigger on HRTIM_TIMC compare match for compare register 2 + TimCCmp2 = 16, + + /// Trigger on HRTIM_TIMB period + TimBPeriod = 15, + + /// Trigger on HRTIM_TIMB compare match for compare register 4 + TimBCmp4 = 14, + + /// Trigger on HRTIM_TIMB compare match for compare register 2 + TimBCmp2 = 13, + + /// Trigger on HRTIM_TIMA period + TimAPeriod = 12, + + /// Trigger on HRTIM_TIMA compare match for compare register 4 + TimACmp4 = 11, + + /// Trigger on HRTIM_TIMA compare match for compare register 2 + TimACmp2 = 10, + + // /// Trigger on EEV10 + // _ = 9, + + // /// Trigger on EEV9 + // _ = 8, + + // /// Trigger on EEV8 + // _ = 7, + + // /// Trigger on EEV7 + // _ = 6, + + // /// Trigger on EEV6 + // _ = 5, + /// Trigger on HRTIM_MASTER period + MasterPeriod = 4, + + /// Trigger on HRTIM_MASTER compare match for compare register 4 + MasterCmp4 = 3, + + /// Trigger on HRTIM_MASTER compare match for compare register 3 + MasterCmp3 = 2, + + /// Trigger on HRTIM_MASTER compare match for compare register 2 + MasterCmp2 = 1, + + /// Trigger on HRTIM_MASTER compare match for compare register 1 + MasterCmp1 = 0, +} diff --git a/src/pwm/hrtim/external_event.rs b/src/pwm/hrtim/external_event.rs new file mode 100644 index 00000000..f9da1e1a --- /dev/null +++ b/src/pwm/hrtim/external_event.rs @@ -0,0 +1,138 @@ +use crate::comparator::{Comparator, self, COMP1}; + +pub trait ExternalEventExt { + fn external_event(&self) -> ExternalEventBuilder; +} + +macro_rules! impl_eev_ext_comp { + ($comp:ident: $N:literal) => { + impl ExternalEventExt<$N, 0b10> for Comparator<$comp, E> { + fn external_event(&self) -> ExternalEventBuilder<$N, 0b10> { + ExternalEventBuilder { + edge_or_polarity_bits: 0, // Polarity sensitive + polarity_bit: false, // Active high + filter_bits: 0, // No filter + fast_bit: false, // Not fast + } + } + } + }; +} + +impl_eev_ext_comp!(COMP1: 4); + +struct ExternalEventBuilder { + edge_or_polarity_bits: u8, + polarity_bit: bool, + filter_bits: u8, + fast_bit: bool, +} + +enum EdgeOrPolarity { + Edge(Edge), + Polarity(Polarity), +} + +enum Edge { + Rising = 0b01, + Falling = 0b10, + Both = 0b11, +} + +enum Polarity { + ActiveHigh, + ActiveLow, +} + +pub enum EevSamplingFilter { + /// No filtering, fault acts asynchronously + /// + /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) + None = 0b0000, + + /// Sample directly at rate f_hrtim, with a count of 2 + /// + /// Note that this bypasses: any f_eevs (FaultSamplingClkDiv) + HrtimN2 = 0b0001, + + /// Sample directly at rate f_hrtim, with a count of 4 + /// + /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) + HrtimN4 = 0b0010, + + /// Sample directly at rate f_hrtim, with a count of 8 + /// + /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) + HrtimN8 = 0b0011, + + /// Sample at rate f_eevs / 2, with a count of 6 + EevsDiv2N6 = 0b0100, + + /// Sample at rate f_eevs / 2, with a count of 8 + EevsDiv2N8 = 0b0101, + + /// Sample at rate f_eevs / 4, with a count of 6 + EevsDiv4N6 = 0b0110, + + /// Sample at rate f_eevs / 4, with a count of 8 + EevsDiv4N8 = 0b0111, + + /// Sample at rate f_eevs / 8, with a count of 6 + EevsDiv8N6 = 0b1000, + + /// Sample at rate f_eevs / 8, with a count of 8 + EevsDiv8N8 = 0b1001, + + /// Sample at rate f_eevs / 16, with a count of 5 + EevsDiv16N5 = 0b1010, + + /// Sample at rate f_eevs / 16, with a count of 6 + EevsDiv16N6 = 0b1011, + + /// Sample at rate f_eevs / 16, with a count of 8 + EevsDiv16N8 = 0b1100, + + /// Sample at rate f_eevs / 32, with a count of 5 + EevsDiv32N5 = 0b1101, + + /// Sample at rate f_eevs / 32, with a count of 6 + EevsDiv32N6 = 0b1110, + + /// Sample at rate f_eevs / 32, with a count of 8 + EevsDiv32N8 = 0b1111, +} + +impl ExternalEventBuilder { + fn edge_or_polarity(mut self, edge_or_polarity: EdgeOrPolarity) -> Self { + (self.edge_or_polarity_bits, self.polarity_bit) = match edge_or_polarity { + EdgeOrPolarity::Polarity(Polarity::ActiveHigh) => (0b00, false), + EdgeOrPolarity::Polarity(Polarity::ActiveLow) => (0b00, true), + EdgeOrPolarity::Edge(Edge::Rising) => (0b01, false), + EdgeOrPolarity::Edge(Edge::Falling) => (0b10, false), + EdgeOrPolarity::Edge(Edge::Both) => (0b11, false), + }; + + self + } +} + +impl ExternalEventBuilder + where ExternalEventBuilder: ExternalEventBuilder1To5 +{ + fn fast(mut self) -> Self { + self.fast_bit = true; + self + } +} + +impl ExternalEventBuilder + where ExternalEventBuilder: ExternalEventBuilder6To10 +{ + fn filter(mut self, filter: EevSamplingFilter) -> Self { + self.filter_bits = filter as _; + self + } +} + +trait ExternalEventBuilder1To5 {} +trait ExternalEventBuilder6To10 {} \ No newline at end of file diff --git a/src/pwm/hrtim/fault.rs b/src/pwm/hrtim/fault.rs new file mode 100644 index 00000000..fec4b004 --- /dev/null +++ b/src/pwm/hrtim/fault.rs @@ -0,0 +1,248 @@ +use core::marker::PhantomData; + +use crate::comparator::{COMP5, COMP1, COMP6, COMP4, COMP2, COMP3}; +use crate::gpio::{self, AF13, AF3}; +use crate::gpio::gpioa::{PA12, PA15}; +use crate::gpio::gpiob::{PB0, PB11, PB10}; +use crate::gpio::gpioc::{PC10, PC7}; +use crate::pwm::FaultMonitor; +use crate::stm32::HRTIM_COMMON; +use super::calibration::HrPwmControl; + +pub enum FaultAction { + /// Output never enters fault mode + None = 0b00, + + /// Output forced to `active` level on fault + ForceActive = 0b01, + + /// Output forced to `inactive` level on fault + ForceInactive = 0b10, + + /// The output is floating/tri stated on fault + Floating = 0b11, +} + +pub unsafe trait FaultSource: Copy { + const ENABLE_BITS: u8; +} + +pub struct SourceBuilder { + _input: I, + src_bits: u8, + + /// FLTxP + is_active_high: bool, + + /// FLTxF[3:0] + filter_bits: u8, +} + +impl SourceBuilder { + unsafe fn new(input: I, src_bits: u8) -> Self { + SourceBuilder { + _input: input, + src_bits, + is_active_high: false, + filter_bits: 0b0000, + } + } +} + +macro_rules! impl_faults { + ($( + $input:ident => $source:ident: + PINS=[($pin:ident, $af:ident), $(($pin_b:ident, $af_b:ident),)*], + COMP=$compX:ident, $enable_bits:literal, + $fltinrZ:ident, $fltWsrc_0:ident, $fltWsrc_1:ident, $fltWp:ident, $fltWf:ident, $fltWe:ident, $fltWlck:ident, + )+) => {$( + + // This should NOT be Copy/Clone + pub struct $input { + _x: PhantomData<()> + } + + #[derive(Copy, Clone)] + pub struct $source { + _x: PhantomData<()> + } + + impl $input { + pub fn bind_pin(self, pin: $pin>) -> SourceBuilder<$input> { + pin.into_alternate::<$af>(); + unsafe { SourceBuilder::new(self, 0b00) } + } + + $( + pub fn bind_pin_b(self, pin: $pin_b>) -> SourceBuilder<$input> { + pin.into_alternate::<$af_b>(); + unsafe { SourceBuilder::new(self, 0b00) } + } + )* + + pub fn bind_comp(self, _comp: &crate::comparator::Comparator<$compX, crate::comparator::Enabled>) -> SourceBuilder<$input> { + unsafe { SourceBuilder::new(self, 0b01) } + } + + /*pub fn bind_external(?) { + SourceBuilder::new(self, 0b10); + }*/ + } + + impl SourceBuilder<$input> { + pub fn finalize(self, _control: &mut HrPwmControl) -> $source { + let SourceBuilder{ _input, src_bits, is_active_high, filter_bits } = self; + + // Setup fault source + unsafe { + let common = &*HRTIM_COMMON::ptr(); + + common.fltinr2.modify(|_r, w| w.$fltWsrc_1().bit(src_bits & 0b10 != 0)); + common.$fltinrZ.modify(|_r, w| w + .$fltWsrc_0().bit(src_bits & 0b01 != 0) + .$fltWp().bit(is_active_high) + .$fltWf().bits(filter_bits) + .$fltWe().set_bit() // Enable + ); + + // ... and lock configuration + common.$fltinrZ.modify(|_r, w| w.$fltWlck().set_bit()); + } + + $source { + _x: PhantomData + } + } + + pub fn polarity(mut self, polarity: super::Polarity) -> Self { + self.is_active_high = polarity == super::Polarity::ActiveHigh; + self + } + + // TODO: add more settings + /* pub fn blanking(?) -> Self */ + + pub fn filter(mut self, filter: FaultSamplingFilter) -> Self { + self.filter_bits = filter as u8; + self + } + } + + unsafe impl FaultSource for $source { + const ENABLE_BITS: u8 = $enable_bits; + } + )+} +} + +// TODO: Lookup to ensure the alternate function are the same for other devices than stm32g474 +#[cfg(feature = "stm32g474")] +impl_faults!( + FaultInput1 => FaultSource1: PINS=[(PA12, AF13),], COMP=COMP2, 0b000001, fltinr1, flt1src, flt1src_1, flt1p, flt1f, flt1e, flt1lck, + FaultInput2 => FaultSource2: PINS=[(PA15, AF13),], COMP=COMP4, 0b000010, fltinr1, flt2src, flt2src_1, flt2p, flt2f, flt2e, flt2lck, + FaultInput3 => FaultSource3: PINS=[(PB10, AF13),], COMP=COMP6, 0b000100, fltinr1, flt3src, flt3src_1, flt3p, flt3f, flt3e, flt3lck, + FaultInput4 => FaultSource4: PINS=[(PB11, AF13),], COMP=COMP1, 0b001000, fltinr1, flt4src, flt4src_1, flt4p, flt4f, flt4e, flt4lck, + FaultInput5 => FaultSource5: PINS=[(PB0, AF13), (PC7, AF3),], COMP=COMP3, 0b010000, fltinr2, flt5src, flt5src_1, flt5p, flt5f, flt5e, flt5lck, + FaultInput6 => FaultSource6: PINS=[(PC10, AF13),], COMP=COMP5, 0b100000, fltinr2, flt6src_0, flt6src_1, flt6p, flt6f, flt6e, flt6lck, +); + +pub struct FaultInputs { + pub fault_input1: FaultInput1, + pub fault_input2: FaultInput2, + pub fault_input3: FaultInput3, + pub fault_input4: FaultInput4, + pub fault_input5: FaultInput5, + pub fault_input6: FaultInput6, +} + +pub enum FaultSamplingFilter { + /// No filtering, fault acts asynchronously + /// + /// Note that this bypasses any f_flts (SamplingClkDiv) + None = 0b0000, + + /// Sample directly at rate f_hrtim, with a count of 2 + /// + /// Note that this bypasses: any f_flts (SamplingClkDiv) + HrtimN2 = 0b0001, + + /// Sample directly at rate f_hrtim, with a count of 4 + /// + /// Note that this bypasses any f_flts (SamplingClkDiv) + HrtimN4 = 0b0010, + + /// Sample directly at rate f_hrtim, with a count of 8 + /// + /// Note that this bypasses any f_flts (SamplingClkDiv) + HrtimN8 = 0b0011, + + /// Sample at rate f_flts / 2, with a count of 6 + FltsDiv2N6 = 0b0100, + + /// Sample at rate f_flts / 2, with a count of 8 + FltsDiv2N8 = 0b0101, + + /// Sample at rate f_flts / 4, with a count of 6 + FltsDiv4N6 = 0b0110, + + /// Sample at rate f_flts / 4, with a count of 8 + FltsDiv4N8 = 0b0111, + + /// Sample at rate f_flts / 8, with a count of 6 + FltsDiv8N6 = 0b1000, + + /// Sample at rate f_flts / 8, with a count of 8 + FltsDiv8N8 = 0b1001, + + /// Sample at rate f_flts / 16, with a count of 5 + FltsDiv16N5 = 0b1010, + + /// Sample at rate f_flts / 16, with a count of 6 + FltsDiv16N6 = 0b1011, + + /// Sample at rate f_flts / 16, with a count of 8 + FltsDiv16N8 = 0b1100, + + /// Sample at rate f_flts / 32, with a count of 5 + FltsDiv32N5 = 0b1101, + + /// Sample at rate f_flts / 32, with a count of 6 + FltsDiv32N6 = 0b1110, + + /// Sample at rate f_flts / 32, with a count of 8 + FltsDiv32N8 = 0b1111, +} + +macro_rules! impl_flt_monitor { + ($($t:ident: ($fltx:ident, $fltxc:ident),)+) => {$( + pub struct $t { + _x: PhantomData<()> + } + + impl FaultMonitor for $t { + fn is_fault_active(&self) -> bool { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.isr.read().$fltx().bit() + } + + fn clear_fault(&mut self) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.icr.write(|w| w.$fltxc().set_bit()); + } + + // TODO: Should we have our own trait since it does not seem possible to implement this + fn set_fault(&mut self) { + todo!() + } + } + )+}; +} + +impl_flt_monitor!( + FltMonitorSys: (sysflt, sysfltc), + FltMonitor1: (flt1, flt1c), + FltMonitor2: (flt2, flt2c), + FltMonitor3: (flt3, flt3c), + FltMonitor4: (flt4, flt4c), + FltMonitor5: (flt5, flt5c), + FltMonitor6: (flt6, flt6c), +); From 826a32cf4b21931c2b74baa0a0a92ce2016d6c32 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 4 Nov 2023 01:33:45 +0100 Subject: [PATCH 37/88] More hrtim refactor --- src/hrtim/compare_register.rs | 55 + .../hrtim/calibration.rs => hrtim/control.rs} | 74 +- src/hrtim/deadtime.rs | 79 + src/hrtim/event.rs | 619 +++++ src/hrtim/external_event.rs | 283 +++ src/{pwm => }/hrtim/fault.rs | 12 +- src/hrtim/mod.rs | 886 ++++++++ src/hrtim/output.rs | 300 +++ src/hrtim/timer.rs | 141 ++ src/lib.rs | 3 + src/pwm.rs | 7 +- src/pwm/hrtim.rs | 2016 ----------------- src/pwm/hrtim/external_event.rs | 138 -- 13 files changed, 2422 insertions(+), 2191 deletions(-) create mode 100644 src/hrtim/compare_register.rs rename src/{pwm/hrtim/calibration.rs => hrtim/control.rs} (97%) create mode 100644 src/hrtim/deadtime.rs create mode 100644 src/hrtim/event.rs create mode 100644 src/hrtim/external_event.rs rename src/{pwm => }/hrtim/fault.rs (97%) create mode 100644 src/hrtim/mod.rs create mode 100644 src/hrtim/output.rs create mode 100644 src/hrtim/timer.rs delete mode 100644 src/pwm/hrtim.rs delete mode 100644 src/pwm/hrtim/external_event.rs diff --git a/src/hrtim/compare_register.rs b/src/hrtim/compare_register.rs new file mode 100644 index 00000000..3c6b7ac9 --- /dev/null +++ b/src/hrtim/compare_register.rs @@ -0,0 +1,55 @@ +use core::marker::PhantomData; + +use crate::stm32::{ + HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF, +}; + +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)>); + +macro_rules! hrtim_cr_helper { + ($TIMX:ident: $cr_type:ident: $cmpXYr:ident, $cmpYx:ident) => { + impl HrCompareRegister for $cr_type<$TIMX, PSCL> { + fn get_duty(&self) -> u16 { + let tim = unsafe { &*$TIMX::ptr() }; + + tim.$cmpXYr.read().$cmpYx().bits() + } + fn set_duty(&mut self, duty: u16) { + let tim = unsafe { &*$TIMX::ptr() }; + + tim.$cmpXYr.write(|w| unsafe { w.$cmpYx().bits(duty) }); + } + } + }; +} + +macro_rules! hrtim_cr { + ($($TIMX:ident: [ + $cmpX1r:ident, $cmpX2r:ident, $cmpX3r:ident, $cmpX4r:ident, + $cmp1x:ident, $cmp2x:ident, $cmp3x:ident, $cmp4x:ident + ],)+) => {$( + hrtim_cr_helper!($TIMX: HrCr1: $cmpX1r, $cmp1x); + hrtim_cr_helper!($TIMX: HrCr2: $cmpX2r, $cmp2x); + hrtim_cr_helper!($TIMX: HrCr3: $cmpX3r, $cmp3x); + hrtim_cr_helper!($TIMX: HrCr4: $cmpX4r, $cmp4x); + )+}; +} + +hrtim_cr! { + HRTIM_MASTER: [mcmp1r, mcmp2r, mcmp3r, mcmp4r, mcmp1, mcmp2, mcmp3, mcmp4], + + HRTIM_TIMA: [cmp1ar, cmp2ar, cmp3ar, cmp4ar, cmp1x, cmp2x, cmp3x, cmp4x], + HRTIM_TIMB: [cmp1br, cmp2br, cmp3br, cmp4br, cmp1x, cmp2x, cmp3x, cmp4x], + HRTIM_TIMC: [cmp1cr, cmp2cr, cmp3cr, cmp4cr, cmp1x, cmp2x, cmp3x, cmp4x], + HRTIM_TIMD: [cmp1dr, cmp2dr, cmp3dr, cmp4dr, cmp1x, cmp2x, cmp3x, cmp4x], + HRTIM_TIME: [cmp1er, cmp2er, cmp3er, cmp4er, cmp1x, cmp2x, cmp3x, cmp4x], + HRTIM_TIMF: [cmp1fr, cmp2fr, cmp3fr, cmp4fr, cmp1x, cmp2x, cmp3x, cmp4x], +} diff --git a/src/pwm/hrtim/calibration.rs b/src/hrtim/control.rs similarity index 97% rename from src/pwm/hrtim/calibration.rs rename to src/hrtim/control.rs index fd77a34f..ab0fef6f 100644 --- a/src/pwm/hrtim/calibration.rs +++ b/src/hrtim/control.rs @@ -1,6 +1,15 @@ -use crate::stm32::{HRTIM_COMMON, RCC}; +use core::marker::PhantomData; -use super::HrControltExt; +use crate::{ + hrtim::fault::{ + FaultInput1, FaultInput2, FaultInput3, FaultInput4, FaultInput5, FaultInput6, FltMonitor1, + FltMonitor2, FltMonitor3, FltMonitor4, FltMonitor5, FltMonitor6, FltMonitorSys, + }, + rcc::{Enable, Rcc, Reset}, + stm32::{HRTIM_COMMON, RCC}, +}; + +use super::fault::FaultInputs; pub trait HrControltExt { fn hr_control(self, _rcc: &mut Rcc) -> HrTimOngoingCalibration; @@ -84,7 +93,7 @@ pub struct HrTimOngoingCalibration { impl HrTimOngoingCalibration { /// SAFETY: Calibration needs to be done before calling this - unsafe fn init(self) -> (HrPwmControl, FaultInputs) { + unsafe fn init(self) { use Adc13Trigger as Ad13T; use Adc24Trigger as Ad24T; @@ -410,37 +419,18 @@ impl HrTimOngoingCalibration { // TODO: Adc trigger 5-10 } - - ( - HrPwmControl { - _x: PhantomData, - fault_sys: FltMonitorSys { _x: PhantomData }, - fault_1: FltMonitor1 { _x: PhantomData }, - fault_2: FltMonitor2 { _x: PhantomData }, - fault_3: FltMonitor3 { _x: PhantomData }, - fault_4: FltMonitor4 { _x: PhantomData }, - fault_5: FltMonitor5 { _x: PhantomData }, - fault_6: FltMonitor6 { _x: PhantomData }, - }, - FaultInputs { - fault_input1: FaultInput1 { _x: PhantomData }, - fault_input2: FaultInput2 { _x: PhantomData }, - fault_input3: FaultInput3 { _x: PhantomData }, - fault_input4: FaultInput4 { _x: PhantomData }, - fault_input5: FaultInput5 { _x: PhantomData }, - fault_input6: FaultInput6 { _x: PhantomData }, - }, - ) } - pub fn wait_for_calibration(self) -> (HrPwmControl, FaultInputs) { + pub fn wait_for_calibration(self) -> HrTimCalibrated { let common = unsafe { &*HRTIM_COMMON::ptr() }; while common.isr.read().dllrdy().bit_is_clear() { // Wait until ready } // Calibration is now done, it is safe to continue - unsafe { self.init() } + unsafe { self.init() }; + + HrTimCalibrated { _x: PhantomData } } pub fn enable_adc_trigger1_source(mut self, trigger: Adc13Trigger) -> Self { @@ -526,6 +516,38 @@ impl HrTimOngoingCalibration { // TODO: Adc trigger 5-10 } +/// This object may be used for things that needs to be done before any timers have been started but after the calibration has been completed. Its existence is proof that no timers have started. +/// +/// Once done with setup, use the `constrain` to get a `HrPwmControl` which can be used to start the timers. +pub struct HrTimCalibrated { + _x: PhantomData<()>, +} + +impl HrTimCalibrated { + pub fn constrain(self) -> (HrPwmControl, FaultInputs) { + ( + HrPwmControl { + _x: PhantomData, + fault_sys: FltMonitorSys { _x: PhantomData }, + fault_1: FltMonitor1 { _x: PhantomData }, + fault_2: FltMonitor2 { _x: PhantomData }, + fault_3: FltMonitor3 { _x: PhantomData }, + fault_4: FltMonitor4 { _x: PhantomData }, + fault_5: FltMonitor5 { _x: PhantomData }, + fault_6: FltMonitor6 { _x: PhantomData }, + }, + FaultInputs { + fault_input1: FaultInput1 { _x: PhantomData }, + fault_input2: FaultInput2 { _x: PhantomData }, + fault_input3: FaultInput3 { _x: PhantomData }, + fault_input4: FaultInput4 { _x: PhantomData }, + fault_input5: FaultInput5 { _x: PhantomData }, + fault_input6: FaultInput6 { _x: PhantomData }, + }, + ) + } +} + pub struct HrPwmControl { _x: PhantomData<()>, diff --git a/src/hrtim/deadtime.rs b/src/hrtim/deadtime.rs new file mode 100644 index 00000000..dc3b3141 --- /dev/null +++ b/src/hrtim/deadtime.rs @@ -0,0 +1,79 @@ +#[derive(Copy, Clone, Debug)] +pub struct DeadtimeConfig { + /// Prescaler for both rising and falling deadtime + pub(crate) prescaler: DeadtimePrescaler, + + /// 9-bits + pub(crate) deadtime_rising_value: u16, + + /// Is deadtime negative + pub(crate) deadtime_rising_sign: bool, + + /// 9-bits + pub(crate) deadtime_falling_value: u16, + + /// Is deadtime negative + pub(crate) deadtime_falling_sign: bool, +} + +impl DeadtimeConfig { + /// See RM0440 Table 221 'Deadtime resolution and max absolute values' + pub fn prescaler(mut self, value: DeadtimePrescaler) -> Self { + self.prescaler = value; + self + } + + /// Panic if value can not fit in 9 bits + pub fn deadtime_rising_value(mut self, value: u16) -> Self { + // 9 bits + assert!(value < (1 << 9)); + + self.deadtime_rising_value = value; + + self + } + + pub fn deadtime_rising_sign(mut self, is_negative: bool) -> Self { + self.deadtime_rising_sign = is_negative; + self + } + + /// Panic if value can not fit in 9 bits + pub fn deadtime_falling_value(mut self, value: u16) -> Self { + // 9 bits + assert!(value < (1 << 9)); + + self.deadtime_falling_value = value; + + self + } + + pub fn deadtime_falling_sign(mut self, is_negative: bool) -> Self { + self.deadtime_falling_sign = is_negative; + self + } +} + +impl Default for DeadtimeConfig { + fn default() -> Self { + Self { + prescaler: DeadtimePrescaler::Thrtim, + deadtime_rising_value: 170, // about 1us when f_sys = 170MHz + deadtime_rising_sign: false, + deadtime_falling_value: 170, // about 1us when f_sys = 170MHz + deadtime_falling_sign: false, + } + } +} + +#[derive(Copy, Clone, Debug)] +pub enum DeadtimePrescaler { + ThrtimDiv8 = 0b000, + ThrtimDiv4 = 0b001, + ThrtimDiv2 = 0b010, + Thrtim = 0b011, + ThrtimMul2 = 0b100, + ThrtimMul4 = 0b101, + ThrtimMul8 = 0b110, + ThrtimMul16 = 0b111, +} \ No newline at end of file diff --git a/src/hrtim/event.rs b/src/hrtim/event.rs new file mode 100644 index 00000000..245cf255 --- /dev/null +++ b/src/hrtim/event.rs @@ -0,0 +1,619 @@ +use core::marker::PhantomData; + +use crate::stm32::{ + HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF, +}; + +use super::{compare_register::{HrCr1, HrCr2, HrCr3, HrCr4}, external_event::ExternalEventSource}; +use crate::hrtim::timer::HrTim; + +macro_rules! impl_into_es { + ($dst:ident: [$(($t:ty, $ES:ident),)*]) => {$( + impl_into_es!($dst, $t, $ES); + )*}; + + ($dst:ident, $t:ty, $ES:ident) => { + impl From<&$t> for EventSource { + fn from(_: &$t) -> Self { + EventSource::$ES{ _x: PhantomData } + } + } + }; + ($dst:ident) => { + impl_into_es! { + $dst: [ + (HrCr1<$dst, PSCL>, Cr1), + (HrCr2<$dst, PSCL>, Cr2), + (HrCr3<$dst, PSCL>, Cr3), + (HrCr4<$dst, PSCL>, Cr4), + (HrTim<$dst, PSCL>, Period), + + (HrCr1, MasterCr1), + (HrCr2, MasterCr2), + (HrCr3, MasterCr3), + (HrCr4, MasterCr4), + (HrTim, MasterPeriod), + ] + } + }; +} + +impl_into_es!(HRTIM_TIMA); +impl_into_es!(HRTIM_TIMB); +impl_into_es!(HRTIM_TIMC); +impl_into_es!(HRTIM_TIMD); +impl_into_es!(HRTIM_TIME); +impl_into_es!(HRTIM_TIMF); + +macro_rules! impl_into_neighbor_es { + ( + DST: $dst:ident: [ + ($src1:ident, $cr1:ident), + ($src2:ident, $cr2:ident), + ($src3:ident, $cr3:ident), + ($src4:ident, $cr4:ident), + ($src5:ident, $cr5:ident), + ($src6:ident, $cr6:ident), + ($src7:ident, $cr7:ident), + ($src8:ident, $cr8:ident), + ($src9:ident, $cr9:ident), + ] + ) => { + impl_into_neighbor_es!($dst, $src1, $cr1, TimEvent1); + impl_into_neighbor_es!($dst, $src2, $cr2, TimEvent2); + impl_into_neighbor_es!($dst, $src3, $cr3, TimEvent3); + impl_into_neighbor_es!($dst, $src4, $cr4, TimEvent4); + impl_into_neighbor_es!($dst, $src5, $cr5, TimEvent5); + impl_into_neighbor_es!($dst, $src6, $cr6, TimEvent6); + impl_into_neighbor_es!($dst, $src7, $cr7, TimEvent7); + impl_into_neighbor_es!($dst, $src8, $cr8, TimEvent8); + impl_into_neighbor_es!($dst, $src9, $cr9, TimEvent9); + }; + + ($dst:ident, $src:ident, $cr:ident, $TimEventX:ident) => { + impl From<&$cr<$src, PSCL>> for EventSource { + fn from(_: &$cr<$src, PSCL>) -> Self { + EventSource::NeighborTimer { + n: NeighborTimerEventSource::$TimEventX { _x: PhantomData }, + } + } + } + }; +} + +impl_into_neighbor_es! { + DST: HRTIM_TIMA: [ + // src + (HRTIM_TIMB, HrCr1), + (HRTIM_TIMB, HrCr2), + (HRTIM_TIMC, HrCr2), + (HRTIM_TIMC, HrCr3), + (HRTIM_TIMD, HrCr1), + (HRTIM_TIMD, HrCr2), + (HRTIM_TIME, HrCr3), + (HRTIM_TIME, HrCr4), + (HRTIM_TIMF, HrCr4), + ] +} + +impl_into_neighbor_es! { + DST: HRTIM_TIMB: [ + // src + (HRTIM_TIMA, HrCr1), + (HRTIM_TIMA, HrCr2), + (HRTIM_TIMC, HrCr3), + (HRTIM_TIMC, HrCr4), + (HRTIM_TIMD, HrCr3), + (HRTIM_TIMD, HrCr4), + (HRTIM_TIME, HrCr1), + (HRTIM_TIME, HrCr2), + (HRTIM_TIMF, HrCr3), + ] +} + +impl_into_neighbor_es! { + DST: HRTIM_TIMC: [ + // src + (HRTIM_TIMA, HrCr2), + (HRTIM_TIMA, HrCr3), + (HRTIM_TIMB, HrCr2), + (HRTIM_TIMB, HrCr3), + (HRTIM_TIMD, HrCr2), + (HRTIM_TIMD, HrCr4), + (HRTIM_TIME, HrCr3), + (HRTIM_TIME, HrCr4), + (HRTIM_TIMF, HrCr2), + ] +} + +// TODO: Continue for TIMD, TIME and TIMF, see RM0440 Table 218. 'Events mapping across timer A to F' + +pub enum EventSource { + /// Compare match with compare register 1 of this timer + Cr1 { _x: PhantomData<(PSCL, DST)> }, + + /// Compare match with compare register 2 of this timer + Cr2 { _x: PhantomData<(PSCL, DST)> }, + + /// Compare match with compare register 3 of this timer + Cr3 { _x: PhantomData<(PSCL, DST)> }, + + /// Compare match with compare register 4 of this timer + Cr4 { _x: PhantomData<(PSCL, DST)> }, + + /// On complete period + Period { _x: PhantomData<(PSCL, DST)> }, + + /// Compare match with compare register 1 of master timer + MasterCr1 { _x: PhantomData<(PSCL, DST)> }, + + /// Compare match with compare register 2 of master timer + MasterCr2 { _x: PhantomData<(PSCL, DST)> }, + + /// Compare match with compare register 3 of master timer + MasterCr3 { _x: PhantomData<(PSCL, DST)> }, + + /// Compare match with compare register 4 of master timer + MasterCr4 { _x: PhantomData<(PSCL, DST)> }, + + /// On complete master period + MasterPeriod { _x: PhantomData<(PSCL, DST)> }, + + ExternalEvent(ExternalEventSource), // This is fine + + NeighborTimer { + n: NeighborTimerEventSource, + }, +} + +/// Compare events from neighbor timers +/// +/// See RM0440 Table 218. 'Events mapping across timer A to F' +pub enum NeighborTimerEventSource { + /// Timer event 1 + /// + /// This is different depending on destination timer: + /// |dest | source | + /// |-----|--------| + /// |TimA | B CR1 | + /// |TimB | A CR1 | + /// |TimC | A CR2 | + /// |TimD | A CR1 | + /// |TimE | A CR4 | + /// |TimF | A CR3 | + TimEvent1 { + _x: PhantomData<(PSCL, DST)>, + }, + + /// Timer event x + /// + /// This is different depending on destination timer: + /// |dest | source | + /// |-----|--------| + /// |TimA | x CRy | + /// |TimB | x CRy | + /// |TimC | x CRy | + /// |TimD | x CRy | + /// |TimE | x CRy | + /// |TimF | x CRy | + //TimEventx, + + /// Timer event 2 + /// + /// This is different depending on destination timer: + /// |dest | source | + /// |-----|--------| + /// |TimA | B CR2 | + /// |TimB | A CR2 | + /// |TimC | A CR3 | + /// |TimD | A CR4 | + /// |TimE | B CR3 | + /// |TimF | B CR1 | + TimEvent2 { + _x: PhantomData<(PSCL, DST)>, + }, + + /// Timer event 3 + /// + /// This is different depending on destination timer: + /// |dest | source | + /// |-----|--------| + /// |TimA | C CR2 | + /// |TimB | C CR3 | + /// |TimC | B CR2 | + /// |TimD | B CR2 | + /// |TimE | B CR4 | + /// |TimF | B CR4 | + TimEvent3 { + _x: PhantomData<(PSCL, DST)>, + }, + + /// Timer event 4 + /// + /// This is different depending on destination timer: + /// |dest | source | + /// |-----|--------| + /// |TimA | C CR3 | + /// |TimB | C CR4 | + /// |TimC | B CR3 | + /// |TimD | B CR4 | + /// |TimE | C CR1 | + /// |TimF | C CR1 | + TimEvent4 { + _x: PhantomData<(PSCL, DST)>, + }, + // TODO: Document those + TimEvent5 { + _x: PhantomData<(PSCL, DST)>, + }, + TimEvent6 { + _x: PhantomData<(PSCL, DST)>, + }, + TimEvent7 { + _x: PhantomData<(PSCL, DST)>, + }, + TimEvent8 { + _x: PhantomData<(PSCL, DST)>, + }, + TimEvent9 { + _x: PhantomData<(PSCL, DST)>, + }, +} + +macro_rules! hr_timer_reset_event_source_common { + ($(#[$($attrss:tt)*])* pub enum $t:ident { [COMMON], $(#[$($attrss2:tt)*] $vals:tt = 1 << $x:literal,)*}) => { + $(#[$($attrss)*])* + pub enum $t { + $(#[$($attrss2)*] $vals = 1 << $x,)* + + /// The timer counter is reset upon external event 10. + Eevnt10 = 1 << 18, + + /// The timer counter is reset upon external event 9. + Eevnt9 = 1 << 17, + + /// The timer counter is reset upon external event 8. + Eevnt8 = 1 << 16, + + /// The timer counter is reset upon external event 7. + Eevnt7 = 1 << 15, + + /// The timer counter is reset upon external event 6. + Eevnt6 = 1 << 14, + + /// The timer counter is reset upon external event 5. + Eevnt5 = 1 << 13, + + /// The timer counter is reset upon external event 4. + Eevnt4 = 1 << 12, + + /// The timer counter is reset upon external event 3. + Eevnt3 = 1 << 11, + + /// The timer counter is reset upon external event 2. + Eevnt2 = 1 << 10, + + /// The timer counter is reset upon external event 1. + Eevnt1 = 1 << 9, + + /// The timer counter is reset upon master timer compare 4 event. + MasterCmp4 = 1 << 8, + + /// The timer counter is reset upon master timer compare 3 event. + MasterCmp3 = 1 << 7, + + /// The timer counter is reset upon master timer compare 2 event. + MasterCmp2 = 1 << 6, + + /// The timer counter is reset upon master timer compare 1 event. + MasterCmp1 = 1 << 5, + + /// The timer counter is reset upon master timer period event. + MasterPeriod = 1 << 4, + + /// The timer counter is reset upon timer its own compare 4 event + Cmp4 = 1 << 3, + + /// The timer counter is reset upon timer its own compare 2 event + Cmp2 = 1 << 2, + + /// The timer counter is reset upon update event. + Update = 1 << 1, + } + }; +} + +hr_timer_reset_event_source_common!( + /// A + pub enum TimerAResetEventSource { + [COMMON], + /// The timer counter is reset upon timer F compare 2 event. + TimFCmp2 = 1 << 31, + + /// The timer counter is reset upon timer E compare 4 event. + TimECmp4 = 1 << 30, + + /// The timer counter is reset upon timer E compare 2 event. + TimECmp2 = 1 << 29, + + /// The timer counter is reset upon timer E compare 1 event. + TimECmp1 = 1 << 28, + + /// The timer counter is reset upon timer D compare 4 event. + TimDCmp4 = 1 << 27, + + /// The timer counter is reset upon timer D compare 2 event. + TimDCmp2 = 1 << 26, + + /// The timer counter is reset upon timer D compare 1 event. + TimDCmp1 = 1 << 25, + + /// The timer counter is reset upon timer C compare 4 event. + TimCCmp4 = 1 << 24, + + /// The timer counter is reset upon timer C compare 2 event. + TimCCmp2 = 1 << 23, + + /// The timer counter is reset upon timer C compare 1 event. + TimCCmp1 = 1 << 22, + + /// The timer counter is reset upon timer B compare 4 event. + TimBCmp4 = 1 << 21, + + /// The timer counter is reset upon timer B compare 2 event. + TimBCmp2 = 1 << 20, + + /// The timer counter is reset upon timer B compare 1 event. + TimBCmp1 = 1 << 19, + + /// The timer counter is reset upon timer F compare 1 event. + TimFCmp1 = 1 << 0, + } +); + +hr_timer_reset_event_source_common!( + /// B + pub enum TimerBResetEventSource { + [COMMON], + + /// The timer counter is reset upon timer F compare 2 event. + TimFCmp2 = 1 << 31, + + /// The timer counter is reset upon timer E compare 4 event. + TimECmp4 = 1 << 30, + + /// The timer counter is reset upon timer E compare 2 event. + TimECmp2 = 1 << 29, + + /// The timer counter is reset upon timer E compare 1 event. + TimECmp1 = 1 << 28, + + /// The timer counter is reset upon timer D compare 4 event. + TimDCmp4 = 1 << 27, + + /// The timer counter is reset upon timer D compare 2 event. + TimDCmp2 = 1 << 26, + + /// The timer counter is reset upon timer D compare 1 event. + TimDCmp1 = 1 << 25, + + /// The timer counter is reset upon timer C compare 4 event. + TimCCmp4 = 1 << 24, + + /// The timer counter is reset upon timer C compare 2 event. + TimCCmp2 = 1 << 23, + + /// The timer counter is reset upon timer C compare 1 event. + TimCCmp1 = 1 << 22, + + /// The timer counter is reset upon timer A compare 4 event. + TimACmp4 = 1 << 21, + + /// The timer counter is reset upon timer A compare 2 event. + TimACmp2 = 1 << 20, + + /// The timer counter is reset upon timer A compare 1 event. + TimACmp1 = 1 << 19, + + /// The timer counter is reset upon timer F compare 1 event. + TimFCmp1 = 1 << 0, + } +); + +hr_timer_reset_event_source_common!( + /// C + pub enum TimerCResetEventSource { + [COMMON], + + /// The timer counter is reset upon timer F compare 2 event. + TimFCmp2 = 1 << 31, + + /// The timer counter is reset upon timer E compare 4 event. + TimECmp4 = 1 << 30, + + /// The timer counter is reset upon timer E compare 2 event. + TimECmp2 = 1 << 29, + + /// The timer counter is reset upon timer E compare 1 event. + TimECmp1 = 1 << 28, + + /// The timer counter is reset upon timer D compare 4 event. + TimDCmp4 = 1 << 27, + + /// The timer counter is reset upon timer D compare 2 event. + TimDCmp2 = 1 << 26, + + /// The timer counter is reset upon timer D compare 1 event. + TimDCmp1 = 1 << 25, + + /// The timer counter is reset upon timer B compare 4 event. + TimBCmp4 = 1 << 24, + + /// The timer counter is reset upon timer B compare 2 event. + TimBCmp2 = 1 << 23, + + /// The timer counter is reset upon timer B compare 1 event. + TimBCmp1 = 1 << 22, + + /// The timer counter is reset upon timer A compare 4 event. + TimACmp4 = 1 << 21, + + /// The timer counter is reset upon timer A compare 2 event. + TimACmp2 = 1 << 20, + + /// The timer counter is reset upon timer A compare 1 event. + TimACmp1 = 1 << 19, + + + /// The timer counter is reset upon timer F compare 1 event. + TimFCmp1 = 1 << 0, + } +); + +hr_timer_reset_event_source_common!( + /// D + pub enum TimerDResetEventSource { + [COMMON], + + /// The timer counter is reset upon timer F compare 2 event. + TimFCmp2 = 1 << 31, + + /// The timer counter is reset upon timer E compare 4 event. + TimECmp4 = 1 << 30, + + /// The timer counter is reset upon timer E compare 2 event. + TimECmp2 = 1 << 29, + + /// The timer counter is reset upon timer E compare 1 event. + TimECmp1 = 1 << 28, + + /// The timer counter is reset upon timer C compare 4 event. + TimCCmp4 = 1 << 27, + + /// The timer counter is reset upon timer C compare 2 event. + TimCCmp2 = 1 << 26, + + /// The timer counter is reset upon timer C compare 1 event. + TimCCmp1 = 1 << 25, + + /// The timer counter is reset upon timer B compare 4 event. + TimBCmp4 = 1 << 24, + + /// The timer counter is reset upon timer B compare 2 event. + TimBCmp2 = 1 << 23, + + /// The timer counter is reset upon timer B compare 1 event. + TimBCmp1 = 1 << 22, + + /// The timer counter is reset upon timer A compare 4 event. + TimACmp4 = 1 << 21, + + /// The timer counter is reset upon timer A compare 2 event. + TimACmp2 = 1 << 20, + + /// The timer counter is reset upon timer A compare 1 event. + TimACmp1 = 1 << 19, + + /// The timer counter is reset upon timer F compare 1 event. + TimFCmp1 = 1 << 0, + } +); + +hr_timer_reset_event_source_common!( + /// E + pub enum TimerEResetEventSource { + [COMMON], + + /// The timer counter is reset upon timer F compare 2 event. + TimFCmp2 = 1 << 31, + + /// The timer counter is reset upon timer D compare 4 event. + TimDCmp4 = 1 << 30, + + /// The timer counter is reset upon timer D compare 2 event. + TimDCmp2 = 1 << 29, + + /// The timer counter is reset upon timer D compare 1 event. + TimDCmp1 = 1 << 28, + + /// The timer counter is reset upon timer C compare 4 event. + TimCCmp4 = 1 << 27, + + /// The timer counter is reset upon timer C compare 2 event. + TimCCmp2 = 1 << 26, + + /// The timer counter is reset upon timer C compare 1 event. + TimCCmp1 = 1 << 25, + + /// The timer counter is reset upon timer B compare 4 event. + TimBCmp4 = 1 << 24, + + /// The timer counter is reset upon timer B compare 2 event. + TimBCmp2 = 1 << 23, + + /// The timer counter is reset upon timer B compare 1 event. + TimBCmp1 = 1 << 22, + + /// The timer counter is reset upon timer A compare 4 event. + TimACmp4 = 1 << 21, + + /// The timer counter is reset upon timer A compare 2 event. + TimACmp2 = 1 << 20, + + /// The timer counter is reset upon timer A compare 1 event. + TimACmp1 = 1 << 19, + + + /// The timer counter is reset upon timer F compare 1 event. + TimFCmp1 = 1 << 0, + } +); + +hr_timer_reset_event_source_common!( + /// F + pub enum TimerFResetEventSource { + [COMMON], + + /// The timer counter is reset upon timer E compare 2 event. + TimECmp2 = 1 << 31, + + /// The timer counter is reset upon timer D compare 4 event. + TimDCmp4 = 1 << 30, + + /// The timer counter is reset upon timer D compare 2 event. + TimDCmp2 = 1 << 29, + + /// The timer counter is reset upon timer D compare 1 event. + TimDCmp1 = 1 << 28, + + /// The timer counter is reset upon timer C compare 4 event. + TimCCmp4 = 1 << 27, + + /// The timer counter is reset upon timer C compare 2 event. + TimCCmp2 = 1 << 26, + + /// The timer counter is reset upon timer C compare 1 event. + TimCCmp1 = 1 << 25, + + /// The timer counter is reset upon timer B compare 4 event. + TimBCmp4 = 1 << 24, + + /// The timer counter is reset upon timer B compare 2 event. + TimBCmp2 = 1 << 23, + + /// The timer counter is reset upon timer B compare 1 event. + TimBCmp1 = 1 << 22, + + /// The timer counter is reset upon timer A compare 4 event. + TimACmp4 = 1 << 21, + + /// The timer counter is reset upon timer A compare 2 event. + TimACmp2 = 1 << 20, + + /// The timer counter is reset upon timer A compare 1 event. + TimACmp1 = 1 << 19, + + /// The timer counter is reset upon timer E compare 1 event. + TimECmp1 = 1 << 0, + } +); diff --git a/src/hrtim/external_event.rs b/src/hrtim/external_event.rs new file mode 100644 index 00000000..8d2df921 --- /dev/null +++ b/src/hrtim/external_event.rs @@ -0,0 +1,283 @@ +use core::marker::PhantomData; + +use stm32g4::stm32g474::HRTIM_COMMON; + +use crate::comparator::{self, Comparator, COMP1, COMP2, COMP4, COMP6, COMP3, COMP5, COMP7}; + +use super::{control::HrTimCalibrated, event::EventSource}; + +#[derive(Copy, Clone, PartialEq)] +pub enum ExternalEventSource { + Eevnt1 { _x: PhantomData<()> }, + Eevnt2 { _x: PhantomData<()> }, + Eevnt3 { _x: PhantomData<()> }, + Eevnt4 { _x: PhantomData<()> }, + Eevnt5 { _x: PhantomData<()> }, + Eevnt6 { _x: PhantomData<()> }, + Eevnt7 { _x: PhantomData<()> }, + Eevnt8 { _x: PhantomData<()> }, + Eevnt9 { _x: PhantomData<()> }, + Eevnt10 { _x: PhantomData<()> }, +} + +impl From for EventSource { + fn from(val: ExternalEventSource) -> Self { + EventSource::ExternalEvent(val) + } +} + +pub trait ExternalEventExt { + fn external_event(&self) -> ExternalEventBuilder; +} + +macro_rules! impl_eev_ext_comp { + ($N:literal: $comp:ident) => { + impl ExternalEventExt<$N, 0b10> for Comparator<$comp, E> { + fn external_event(&self) -> ExternalEventBuilder<$N, 0b10> { + ExternalEventBuilder { + edge_or_polarity_bits: 0, // Polarity sensitive + polarity_bit: false, // Active high + filter_bits: 0, // No filter + fast_bit: false, // Not fast + } + } + } + }; +} + +impl_eev_ext_comp!(1: COMP2); +impl_eev_ext_comp!(2: COMP4); +impl_eev_ext_comp!(3: COMP6); +impl_eev_ext_comp!(4: COMP1); +impl_eev_ext_comp!(5: COMP3); +impl_eev_ext_comp!(6: COMP2); +impl_eev_ext_comp!(7: COMP4); +impl_eev_ext_comp!(8: COMP6); +impl_eev_ext_comp!(9: COMP5); +impl_eev_ext_comp!(10: COMP7); + +impl_eev_ext_pin!(1: PC12); +impl_eev_ext_pin!(2: PC11); +impl_eev_ext_pin!(3: PB7); +impl_eev_ext_pin!(4: PB6); +impl_eev_ext_pin!(5: PB9); +impl_eev_ext_pin!(6: PB5); +impl_eev_ext_pin!(7: PB4); +impl_eev_ext_pin!(8: PB8); +impl_eev_ext_pin!(9: PB3); +impl_eev_ext_pin!(10: PC5); +impl_eev_ext_pin!(10: PC6); + + + +pub struct ExternalEventBuilder { + /// EExSNS + edge_or_polarity_bits: u8, + + /// EExPOL + polarity_bit: bool, + + /// EExF + filter_bits: u8, + + /// EExFAST + fast_bit: bool, +} + +pub enum EdgeOrPolarity { + Edge(Edge), + Polarity(Polarity), +} + +pub enum Edge { + Rising = 0b01, + Falling = 0b10, + Both = 0b11, +} + +pub enum Polarity { + ActiveHigh, + ActiveLow, +} + +pub enum EevSamplingFilter { + /// No filtering, fault acts asynchronously + /// + /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) + None = 0b0000, + + /// Sample directly at rate f_hrtim, with a count of 2 + /// + /// Note that this bypasses: any f_eevs (FaultSamplingClkDiv) + HrtimN2 = 0b0001, + + /// Sample directly at rate f_hrtim, with a count of 4 + /// + /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) + HrtimN4 = 0b0010, + + /// Sample directly at rate f_hrtim, with a count of 8 + /// + /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) + HrtimN8 = 0b0011, + + /// Sample at rate f_eevs / 2, with a count of 6 + EevsDiv2N6 = 0b0100, + + /// Sample at rate f_eevs / 2, with a count of 8 + EevsDiv2N8 = 0b0101, + + /// Sample at rate f_eevs / 4, with a count of 6 + EevsDiv4N6 = 0b0110, + + /// Sample at rate f_eevs / 4, with a count of 8 + EevsDiv4N8 = 0b0111, + + /// Sample at rate f_eevs / 8, with a count of 6 + EevsDiv8N6 = 0b1000, + + /// Sample at rate f_eevs / 8, with a count of 8 + EevsDiv8N8 = 0b1001, + + /// Sample at rate f_eevs / 16, with a count of 5 + EevsDiv16N5 = 0b1010, + + /// Sample at rate f_eevs / 16, with a count of 6 + EevsDiv16N6 = 0b1011, + + /// Sample at rate f_eevs / 16, with a count of 8 + EevsDiv16N8 = 0b1100, + + /// Sample at rate f_eevs / 32, with a count of 5 + EevsDiv32N5 = 0b1101, + + /// Sample at rate f_eevs / 32, with a count of 6 + EevsDiv32N6 = 0b1110, + + /// Sample at rate f_eevs / 32, with a count of 8 + EevsDiv32N8 = 0b1111, +} + +pub trait ExternalEventBuilder1To5 {} +pub trait ExternalEventBuilder6To10 {} + +impl ExternalEventBuilder { + pub fn edge_or_polarity(mut self, edge_or_polarity: EdgeOrPolarity) -> Self { + (self.edge_or_polarity_bits, self.polarity_bit) = match edge_or_polarity { + EdgeOrPolarity::Polarity(Polarity::ActiveHigh) => (0b00, false), + EdgeOrPolarity::Polarity(Polarity::ActiveLow) => (0b00, true), + EdgeOrPolarity::Edge(Edge::Rising) => (0b01, false), + EdgeOrPolarity::Edge(Edge::Falling) => (0b10, false), + EdgeOrPolarity::Edge(Edge::Both) => (0b11, false), + }; + + self + } +} + +impl ExternalEventBuilder +where + ExternalEventBuilder: ExternalEventBuilder1To5, +{ + pub fn fast(mut self) -> Self { + self.fast_bit = true; + self + } +} + +impl ExternalEventBuilder +where + ExternalEventBuilder: ExternalEventBuilder6To10, +{ + pub fn filter(mut self, filter: EevSamplingFilter) -> Self { + self.filter_bits = filter as _; + self + } +} + +pub trait ExternalEventToEventSource { + fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource; +} + +macro_rules! impl_eev1_5_to_es { + ($eev:ident, $N:literal, $eeXsrc:ident, $eeXpol:ident, $eeXsns:ident, $eeXfast:ident) => { + impl ExternalEventBuilder1To5 for ExternalEventBuilder<$N, SRC> {} + + impl ExternalEventToEventSource for ExternalEventBuilder<$N, SRC> { + fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource { + let ExternalEventBuilder { + edge_or_polarity_bits, + polarity_bit, + filter_bits: _, + fast_bit, + } = self; + + let common = unsafe { &*HRTIM_COMMON::ptr() }; + + // SAFETY: Thanks to, `HrTimCalibrated`, we know we have exclusive access to the register, + // we also know no timers are started. + unsafe { + common.eecr1.modify(|_r, w| { + w.$eeXsrc() + .bits(SRC) + .$eeXpol() + .bit(polarity_bit) + .$eeXsns() + .bits(edge_or_polarity_bits) + .$eeXfast() + .bit(fast_bit) + }); + } + + ExternalEventSource::$eev { _x: PhantomData } + } + } + }; +} + +macro_rules! impl_eev6_10_to_es { + ($eev:ident, $N:literal, $eeXsrc:ident, $eeXpol:ident, $eeXsns:ident, $eeXf:ident) => { + impl ExternalEventBuilder6To10 for ExternalEventBuilder<$N, SRC> {} + + impl ExternalEventToEventSource for ExternalEventBuilder<$N, SRC> { + fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource { + let ExternalEventBuilder { + edge_or_polarity_bits, + polarity_bit, + filter_bits, + fast_bit: _, + } = self; + + let common = unsafe { &*HRTIM_COMMON::ptr() }; + + // SAFETY: Thanks to, `HrTimCalibrated`, we know we have exclusive access to the register, + // we also know no timers are started. + unsafe { + common.eecr2.modify(|_r, w| { + w.$eeXsrc() + .bits(SRC) + .$eeXpol() + .bit(polarity_bit) + .$eeXsns() + .bits(edge_or_polarity_bits) + }); + common.eecr3.modify(|_r, w| w.$eeXf().bits(filter_bits)); + } + + ExternalEventSource::$eev { _x: PhantomData } + } + } + }; +} + +impl_eev1_5_to_es!(Eevnt1, 1, ee1src, ee1pol, ee1sns, ee1fast); +impl_eev1_5_to_es!(Eevnt2, 2, ee2src, ee2pol, ee2sns, ee2fast); +impl_eev1_5_to_es!(Eevnt3, 3, ee3src, ee3pol, ee3sns, ee3fast); +impl_eev1_5_to_es!(Eevnt4, 4, ee4src, ee4pol, ee4sns, ee4fast); +impl_eev1_5_to_es!(Eevnt5, 5, ee5src, ee5pol, ee5sns, ee5fast); + +impl_eev6_10_to_es!(Eevnt6, 6, ee6src, ee6pol, ee6sns, ee6f); +impl_eev6_10_to_es!(Eevnt7, 7, ee7src, ee7pol, ee7sns, ee7f); +impl_eev6_10_to_es!(Eevnt8, 8, ee8src, ee8pol, ee8sns, ee8f); +impl_eev6_10_to_es!(Eevnt9, 9, ee9src, ee9pol, ee9sns, ee9f); +impl_eev6_10_to_es!(Eevnt10, 10, ee10src, ee10pol, ee10sns, ee10f); diff --git a/src/pwm/hrtim/fault.rs b/src/hrtim/fault.rs similarity index 97% rename from src/pwm/hrtim/fault.rs rename to src/hrtim/fault.rs index fec4b004..67b1ec7c 100644 --- a/src/pwm/hrtim/fault.rs +++ b/src/hrtim/fault.rs @@ -1,13 +1,13 @@ use core::marker::PhantomData; -use crate::comparator::{COMP5, COMP1, COMP6, COMP4, COMP2, COMP3}; -use crate::gpio::{self, AF13, AF3}; +use crate::comparator::{COMP1, COMP2, COMP3, COMP4, COMP5, COMP6}; use crate::gpio::gpioa::{PA12, PA15}; -use crate::gpio::gpiob::{PB0, PB11, PB10}; +use crate::gpio::gpiob::{PB0, PB10, PB11}; use crate::gpio::gpioc::{PC10, PC7}; +use crate::gpio::{self, AF13, AF3}; +use crate::hrtim::control::HrPwmControl; use crate::pwm::FaultMonitor; use crate::stm32::HRTIM_COMMON; -use super::calibration::HrPwmControl; pub enum FaultAction { /// Output never enters fault mode @@ -59,7 +59,7 @@ macro_rules! impl_faults { // This should NOT be Copy/Clone pub struct $input { - _x: PhantomData<()> + pub(crate) _x: PhantomData<()> } #[derive(Copy, Clone)] @@ -215,7 +215,7 @@ pub enum FaultSamplingFilter { macro_rules! impl_flt_monitor { ($($t:ident: ($fltx:ident, $fltxc:ident),)+) => {$( pub struct $t { - _x: PhantomData<()> + pub(crate) _x: PhantomData<()> } impl FaultMonitor for $t { diff --git a/src/hrtim/mod.rs b/src/hrtim/mod.rs new file mode 100644 index 00000000..78f6c675 --- /dev/null +++ b/src/hrtim/mod.rs @@ -0,0 +1,886 @@ +pub mod compare_register; +pub mod control; +pub mod deadtime; +pub mod event; +pub mod external_event; +pub mod fault; +pub mod output; +pub mod timer; + +use core::marker::PhantomData; +use core::mem::MaybeUninit; + +use crate::hrtim::compare_register::{HrCr1, HrCr2, HrCr3, HrCr4}; +use crate::hrtim::fault::{FaultAction, FaultSource}; +use crate::hrtim::timer::HrTim; +use crate::stm32::{ + HRTIM_COMMON, HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, + HRTIM_TIMF, +}; +use fugit::HertzU64; + +use self::control::HrPwmControl; + +use self::deadtime::DeadtimeConfig; +use self::output::{HrtimChannel, ToHrOut, CH1, CH2}; + +use crate::pwm::{ + self, Alignment, ComplementaryImpossible, Pins, Polarity, Pwm, PwmPinEnable, TimerType, +}; +use crate::rcc::{GetBusFreq, Rcc}; +use crate::time::Hertz; + +/// Internal enum that keeps track of the count settings before PWM is finalized +enum CountSettings { + Frequency(Hertz), + Period(u16), +} + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum HrTimerMode { + SingleShotNonRetriggerable, + SingleShotRetriggerable, + Continuous, +} + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum HrCountingDirection { + /// Asymetrical up counting mode + /// + /// + + /// * * + /// Counting up * | * | + /// * * + /// * | * | + /// * * + /// * | * | + /// * * + /// -------------------------------------- + /// + /// ```txt + /// | *-------* *------ + /// | | | + /// | | | | + /// | | | + /// ----------* *------------------* + /// ``` + /// + /// This is the most common mode with least amount of quirks + Up, + + /// Symmetrical up-down counting mode + /// + /// + /// ```txt + /// Period--> * Counting * + /// Counting up * | * Counting Up * | + /// * * down * + /// * | * * | + /// * * * + /// * | * * | + /// 0 -->* * + /// --------------------------------------------------------------------------- + /// | *---------------* | *---------------* + /// | | | | | | + /// | | | | | | + /// | | | | | | + /// ----------* *-------------------* *--- + /// ``` + /// + /// NOTE: This is incompatible with + /// * Auto-delay + /// * Balanded Idle + /// * Triggered-half mode + /// + /// There is also differences in (including but not limited to) the following areas: + /// * Counter roll over event + /// * The events registered with `enable_set_event` will work as normal wen counting up, however when counting down, they will work as rst events. + /// * The events registered with `enable_rst_event` will work as normal wen counting up, however when counting down, they will work as set events. + UpDown, +} + +// Needed to calculate frequency +impl From for pwm::Alignment { + fn from(val: HrCountingDirection) -> Self { + match val { + HrCountingDirection::Up => pwm::Alignment::Left, + HrCountingDirection::UpDown => pwm::Alignment::Center, + } + } +} + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum InterleavedMode { + Disabled, + + /// Dual interleaved or Half mode + /// + /// Automatically force + /// * Cr1 to PERIOD / 2 (not visable through `get_duty`). + /// Automatically updates when changing period + /// + /// NOTE: Affects Cr1 + Dual, + + /// Triple interleaved mode + /// + /// Automatically force + /// * Cr1 to 1 * PERIOD / 3 and + /// * Cr2 to 2 * PERIOD / 3 + /// (not visable through `get_duty`). Automatically updates when changing period. + /// + /// NOTE: Must not be used simultaneously with other modes + /// using CMP2 (dual channel dac trigger and triggered-half modes). + Triple, + + /// Quad interleaved mode + /// + /// Automatically force + /// * Cr1 to 1 * PERIOD / 4, + /// * Cr2 to 2 * PERIOD / 4 and + /// * Cr3 to 3 * PERIOD / 4 + /// (not visable through `get_duty`). Automatically updates when changing period. + /// + /// NOTE: Must not be used simultaneously with other modes + /// using CMP2 (dual channel dac trigger and triggered-half modes). + Quad, +} + +// HrPwmExt trait +/// Allows the pwm() method to be added to the peripheral register structs from the device crate +pub trait HrPwmExt: Sized { + /// The requested frequency will be rounded to the nearest achievable frequency; the actual frequency may be higher or lower than requested. + fn pwm( + self, + _pins: PINS, + frequency: T, + control: &mut HrPwmControl, + rcc: &mut Rcc, + ) -> PINS::Channel + where + PINS: Pins + ToHrOut, + T: Into, + U: HrtimChannel; +} + +pub trait HrPwmAdvExt: Sized { + type PreloadSource; + + fn pwm_advanced( + self, + _pins: PINS, + rcc: &mut Rcc, + ) -> HrPwmBuilder> + where + PINS: Pins + ToHrOut, + CHANNEL: HrtimChannel; +} + +/// HrPwmBuilder is used to configure advanced HrTim PWM features +pub struct HrPwmBuilder { + _tim: PhantomData, + _prescaler: PhantomData, + _out: PhantomData, + timer_mode: HrTimerMode, + counting_direction: HrCountingDirection, + base_freq: HertzU64, + count: CountSettings, + preload_source: Option, + fault_enable_bits: u8, + fault1_bits: u8, + fault2_bits: u8, + enable_push_pull: bool, + interleaved_mode: InterleavedMode, // Also includes half mode + repetition_counter: u8, + deadtime: Option, + enable_repetition_interrupt: bool, + out1_polarity: Polarity, + out2_polarity: Polarity, +} + +pub enum PreloadSource { + /// Preloaded registers are updated on counter roll over or counter reset + OnCounterReset, + + /// Preloaded registers are updated by master timer update + OnMasterTimerUpdate, + + /// Prealoaded registers are updaten when the counter rolls over and the repetition counter is 0 + OnRepetitionUpdate, +} + +pub enum MasterPreloadSource { + /// Prealoaded registers are updaten when the master counter rolls over and the master repetition counter is 0 + OnMasterRepetitionUpdate, +} + +macro_rules! hrtim_finalize_body { + ($this:expr, $PreloadSource:ident, $TIMX:ident: ( + $timXcr:ident, $ck_psc:ident, $perXr:ident, $perx:ident, $tXcen:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident $(, $timXcr2:ident, $fltXr:ident, $outXr:ident, $dtXr:ident)*), + ) => {{ + let tim = unsafe { &*$TIMX::ptr() }; + let (period, prescaler_bits) = match $this.count { + CountSettings::Period(period) => (period as u32, PSCL::BITS as u16), + CountSettings::Frequency( freq ) => { + >::calculate_frequency($this.base_freq, freq, $this.counting_direction.into()) + }, + }; + + let (half, intlvd) = match $this.interleaved_mode { + InterleavedMode::Disabled => (false, 0b00), + InterleavedMode::Dual => (true, 0b00), + InterleavedMode::Triple => (false, 0b01), + InterleavedMode::Quad => (false, 0b10), + }; + + // Write prescaler and any special modes + tim.$timXcr.modify(|_r, w| unsafe { + w + // Enable Continuous mode + .cont().bit($this.timer_mode == HrTimerMode::Continuous) + .retrig().bit($this.timer_mode == HrTimerMode::SingleShotRetriggerable) + + // TODO: add support for more modes + + // Interleaved mode + .intlvd().bits(intlvd) + + // half/double interleaved mode + .half().bit(half) + + // Set prescaler + .$ck_psc().bits(prescaler_bits as u8) + }); + + $( + tim.$timXcr2.modify(|_r, w| + // Set counting direction + w.udm().bit($this.counting_direction == HrCountingDirection::UpDown) + ); + + // Only available for timers with outputs(not HRTIM_MASTER) + let _ = tim.$outXr; + tim.$timXcr.modify(|_r, w| + // Push-Pull mode + w.pshpll().bit($this.enable_push_pull) + ); + )* + + // Write period + tim.$perXr.write(|w| unsafe { w.$perx().bits(period as u16) }); + + // Enable fault sources and lock configuration + $(unsafe { + // Enable fault sources + let fault_enable_bits = $this.fault_enable_bits as u32; + tim.$fltXr.write(|w| w + .flt1en().bit(fault_enable_bits & (1 << 0) != 0) + .flt2en().bit(fault_enable_bits & (1 << 1) != 0) + .flt3en().bit(fault_enable_bits & (1 << 2) != 0) + .flt4en().bit(fault_enable_bits & (1 << 3) != 0) + .flt5en().bit(fault_enable_bits & (1 << 4) != 0) + .flt6en().bit(fault_enable_bits & (1 << 5) != 0) + ); + + // ... and lock configuration + tim.$fltXr.modify(|_r, w| w.fltlck().set_bit()); + + tim.$outXr.modify(|_r, w| w + // Set actions on fault for both outputs + .fault1().bits($this.fault1_bits) + .fault2().bits($this.fault2_bits) + + // Set output polarity for both outputs + .pol1().bit($this.out1_polarity == Polarity::ActiveLow) + .pol2().bit($this.out2_polarity == Polarity::ActiveLow) + ); + if let Some(deadtime) = $this.deadtime { + let DeadtimeConfig { + prescaler, + deadtime_rising_value, + deadtime_rising_sign, + deadtime_falling_value, + deadtime_falling_sign, + } = deadtime; + + // SAFETY: DeadtimeConfig makes sure rising and falling values are valid + // and DeadtimePrescaler has its own garantuee + tim.$dtXr.modify(|_r, w| w + .dtprsc().bits(prescaler as u8) + .dtrx().bits(deadtime_rising_value) + .sdtrx().bit(deadtime_rising_sign) + .dtfx().bits(deadtime_falling_value) + .sdtfx().bit(deadtime_falling_sign) + + // Lock configuration + .dtflkx().set_bit() + .dtfslkx().set_bit() + .dtrlkx().set_bit() + .dtrslkx().set_bit() + ); + tim.$outXr.modify(|_r, w| w.dten().set_bit()); + } + })* + + + hrtim_finalize_body!($PreloadSource, $this, tim, $timXcr); + + // Set repetition counter + unsafe { tim.$rep.write(|w| w.$repx().bits($this.repetition_counter)); } + + // Enable interrupts + tim.$dier.modify(|_r, w| w.$repie().bit($this.enable_repetition_interrupt)); + + // Start timer + //let master = unsafe { &*HRTIM_MASTER::ptr() }; + //master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); + + unsafe { + MaybeUninit::uninit().assume_init() + } + }}; + + (PreloadSource, $this:expr, $tim:expr, $timXcr:ident) => {{ + match $this.preload_source { + Some(PreloadSource::OnCounterReset) => { + $tim.$timXcr.modify(|_r, w| w + .tx_rstu().set_bit() + .preen().set_bit() + ) + }, + Some(PreloadSource::OnMasterTimerUpdate) => { + $tim.$timXcr.modify(|_r, w| w + .mstu().set_bit() + .preen().set_bit() + ) + } + Some(PreloadSource::OnRepetitionUpdate) => { + $tim.$timXcr.modify(|_r, w| w + .tx_repu().set_bit() + .preen().set_bit() + ) + } + None => () + } + }}; + + (MasterPreloadSource, $this:expr, $tim:expr, $timXcr:ident) => {{ + match $this.preload_source { + Some(MasterPreloadSource::OnMasterRepetitionUpdate) => { + $tim.$timXcr.modify(|_r, w| w + .mrepu().set_bit() + .preen().set_bit() + ) + } + None => () + } + }}; +} + +macro_rules! hrtim_common_methods { + ($TIMX:ident, $PS:ident) => { + /// Set the PWM frequency; will overwrite the previous prescaler and period + /// The requested frequency will be rounded to the nearest achievable frequency; the actual frequency may be higher or lower than requested. + pub fn frequency>(mut self, freq: T) -> Self { + self.count = CountSettings::Frequency(freq.into()); + + self + } + + /// Set the prescaler; PWM count runs at base_frequency/(prescaler+1) + pub fn prescaler

( + self, + _prescaler: P, + ) -> HrPwmBuilder<$TIMX, P, $PS, ::Out

> + where + P: HrtimPrescaler, + { + let HrPwmBuilder { + _tim, + _prescaler: _, + _out, + 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, + out1_polarity, + out2_polarity, + } = self; + + let period = match count { + CountSettings::Frequency(_) => u16::MAX, + CountSettings::Period(period) => period, + }; + + let count = CountSettings::Period(period); + + HrPwmBuilder { + _tim, + _prescaler: PhantomData, + _out: PhantomData, + 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, + 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 + } + }; +} + +// Implement PWM configuration for timer +macro_rules! hrtim_hal { + ($($TIMX:ident: ($timXcr:ident, $timXcr2:ident, $perXr:ident, $tXcen:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident, $fltXr:ident, $outXr:ident, $dtXr:ident),)+) => { + $( + + // Implement HrPwmExt trait for hrtimer + impl HrPwmExt for $TIMX { + fn pwm( + self, + pins: PINS, + frequency: T, + control: &mut HrPwmControl, + rcc: &mut Rcc, + ) -> PINS::Channel + where + PINS: Pins + ToHrOut, + T: Into, + U: HrtimChannel, + { + let _= self.pwm_advanced(pins, rcc).frequency(frequency).finalize(control); + + unsafe { MaybeUninit::::uninit().assume_init() } + } + } + + impl HrPwmAdvExt for $TIMX { + type PreloadSource = PreloadSource; + + fn pwm_advanced( + self, + _pins: PINS, + rcc: &mut Rcc, + ) -> HrPwmBuilder> + where + PINS: Pins + ToHrOut, + CHANNEL: HrtimChannel + { + // 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, + _out: PhantomData, + 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, + out1_polarity: Polarity::ActiveHigh, + out2_polarity: Polarity::ActiveHigh, + } + } + } + + impl + HrPwmBuilder<$TIMX, PSCL, PreloadSource, OUT> + where + PSCL: HrtimPrescaler, + OUT: ToHrOut, + { + pub fn finalize(self, _control: &mut HrPwmControl) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX, PSCL>, HrCr2<$TIMX, PSCL>, HrCr3<$TIMX, PSCL>, HrCr4<$TIMX, PSCL>), OUT) { + hrtim_finalize_body!(self, PreloadSource, $TIMX: ($timXcr, ck_pscx, $perXr, perx, $tXcen, $rep, $repx, $dier, $repie, $timXcr2, $fltXr, $outXr, $dtXr),) + } + + 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 + } + + /// 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 + } + )+ + }; +} + +macro_rules! hrtim_hal_master { + ($($TIMX:ident: ($timXcr:ident, $ck_psc:ident, $perXr:ident, $perx:ident, $rep:ident, $tXcen:ident, $dier:ident, $repie:ident),)+) => {$( + impl HrPwmAdvExt for $TIMX { + type PreloadSource = MasterPreloadSource; + + fn pwm_advanced( + self, + _pins: PINS, + rcc: &mut Rcc, + ) -> HrPwmBuilder> + where + PINS: Pins + ToHrOut, // TODO: figure out + CHANNEL: HrtimChannel + { + // 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, + _out: PhantomData, + 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, + out1_polarity: Polarity::ActiveHigh, + out2_polarity: Polarity::ActiveHigh, + } + } + } + + impl + HrPwmBuilder<$TIMX, PSCL, MasterPreloadSource, OUT> + where + PSCL: HrtimPrescaler, + OUT: ToHrOut, + { + pub fn finalize(self, _control: &mut HrPwmControl) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX, PSCL>, HrCr2<$TIMX, PSCL>, HrCr3<$TIMX, PSCL>, HrCr4<$TIMX, PSCL>)) { + hrtim_finalize_body!(self, MasterPreloadSource, $TIMX: ($timXcr, $ck_psc, $perXr, $perx, $tXcen, $rep, $rep, $dier, $repie),) + } + + hrtim_common_methods!($TIMX, MasterPreloadSource); + } + )*} +} + +macro_rules! hrtim_pin_hal { + ($($TIMX:ident: + ($CH:ident, $perXr:ident, $cmpXYr:ident, $cmpYx:ident, $cmpY:ident, $tXYoen:ident, $tXYodis:ident),)+ + ) => { + $( + impl hal::PwmPin for Pwm<$TIMX, $CH, COMP, POL, NPOL> + where Pwm<$TIMX, $CH, COMP, POL, NPOL>: PwmPinEnable { + type Duty = u16; + + // You may not access self in the following methods! + // See unsafe above + + fn disable(&mut self) { + self.ccer_disable(); + } + + fn enable(&mut self) { + self.ccer_enable(); + } + + fn get_duty(&self) -> Self::Duty { + let tim = unsafe { &*$TIMX::ptr() }; + + tim.$cmpXYr.read().$cmpYx().bits() + } + + fn get_max_duty(&self) -> Self::Duty { + let tim = unsafe { &*$TIMX::ptr() }; + + let arr = tim.$perXr.read().perx().bits(); + + // One PWM cycle is ARR+1 counts long + // Valid PWM duty cycles are 0 to ARR+1 + // However, if ARR is 65535 on a 16-bit timer, we can't add 1 + // In that case, 100% duty cycle is not possible, only 65535/65536 + if arr == Self::Duty::MAX { + arr + } + else { + arr + 1 + } + } + + /// Set duty cycle + /// + /// NOTE: Please observe limits(RM0440 "Period and compare registers min and max values"): + /// | Prescaler | Min duty | Max duty | + /// |-----------|----------|----------| + /// | 1 | 0x0060 | 0xFFDF | + /// | 2 | 0x0030 | 0xFFEF | + /// | 4 | 0x0018 | 0xFFF7 | + /// | 8 | 0x000C | 0xFFFB | + /// | 16 | 0x0006 | 0xFFFD | + /// | 32 | 0x0003 | 0xFFFD | + /// | 64 | 0x0003 | 0xFFFD | + /// | 128 | 0x0003 | 0xFFFD | + /// + /// Also, writing 0 as duty is only valid for CR1 and CR3 during a set of + /// specific conditions(see RM0440 "Null duty cycle exception case"): + /// – the output SET event is generated by the PERIOD event + /// – the output RESET if generated by the compare 1 (respectively compare 3) event + /// – the compare 1 (compare 3) event is active within the timer unit itself, and not used + /// for other timing units + fn set_duty(&mut self, duty: Self::Duty) { + let tim = unsafe { &*$TIMX::ptr() }; + + tim.$cmpXYr.write(|w| unsafe { w.$cmpYx().bits(duty) }); + } + } + + // Enable implementation for ComplementaryImpossible + impl PwmPinEnable for Pwm<$TIMX, $CH, ComplementaryImpossible, POL, NPOL> { + fn ccer_enable(&mut self) { + // TODO: Should this part only be in Pwm::enable? + // Enable output Y on channel X + // This is a set-only register, no risk for data race + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.oenr.write(|w| { w.$tXYoen().set_bit() }); + } + fn ccer_disable(&mut self) { + // TODO: Should this part only be in Pwm::disable + // Disable output Y on channel X + // This is a write only register, no risk for data race + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.odisr.write(|w| { w.$tXYodis().set_bit() }); + } + } + )+ + } +} + +hrtim_hal! { + HRTIM_TIMA: (timacr, timacr2, perar, tacen, repar, repx, timadier, repie, fltar, outar, dtar), + HRTIM_TIMB: (timbcr, timbcr2, perbr, tbcen, repbr, repx, timbdier, repie, fltbr, outbr, dtbr), + HRTIM_TIMC: (timccr, timccr2, percr, tccen, repcr, repx, timcdier, repie, fltcr, outcr, dtcr), + HRTIM_TIMD: (timdcr, timdcr2, perdr, tdcen, repdr, repx, timddier, repie, fltdr, outdr, dtdr), + HRTIM_TIME: (timecr, timecr2, perer, tecen, reper, repx, timedier, repie, flter, outer, dter), + HRTIM_TIMF: (timfcr, timfcr2, perfr, tfcen, repfr, repx, timfdier, repie, fltfr, outfr, dtfr), +} + +hrtim_hal_master! { + HRTIM_MASTER: (mcr, ck_psc, mper, mper, mrep, mcen, mdier, mrepie), +} + +hrtim_pin_hal! { + HRTIM_TIMA: (CH1, perar, cmp1ar, cmp1x, cmp1, ta1oen, ta1odis), + HRTIM_TIMA: (CH2, perar, cmp3ar, cmp3x, cmp3, ta2oen, ta2odis), + + HRTIM_TIMB: (CH1, perbr, cmp1br, cmp1x, cmp1, tb1oen, tb1odis), + HRTIM_TIMB: (CH2, perbr, cmp3br, cmp3x, cmp3, tb2oen, tb2odis), + + HRTIM_TIMC: (CH1, percr, cmp1cr, cmp1x, cmp1, tc1oen, tc1odis), + HRTIM_TIMC: (CH2, percr, cmp3cr, cmp3x, cmp3, tc2oen, tc2odis), + + HRTIM_TIMD: (CH1, perdr, cmp1dr, cmp1x, cmp1, td1oen, td1odis), + HRTIM_TIMD: (CH2, perdr, cmp3dr, cmp3x, cmp3, td2oen, td2odis), + + HRTIM_TIME: (CH1, perer, cmp1er, cmp1x, cmp1, te1oen, te1odis), + HRTIM_TIME: (CH2, perer, cmp3er, cmp3x, cmp3, te2oen, te2odis), + + HRTIM_TIMF: (CH1, perfr, cmp1fr, cmp1x, cmp1, tf1oen, tf1odis), + HRTIM_TIMF: (CH2, perfr, cmp3fr, cmp3x, cmp3, tf2oen, tf2odis), +} + +pub unsafe trait HrtimPrescaler: Default { + const BITS: u8; + const VALUE: u8; + + /// Minimum allowed value for compare registers used with the timer with this prescaler + /// + /// NOTE: That for CR1 and CR3, 0 is also allowed + const MIN_CR: u16; + + /// Maximum allowed value for compare registers used with the timer with this prescaler + const MAX_CR: u16; +} + +macro_rules! impl_pscl { + ($($t:ident => $b:literal, $v:literal, $min:literal, $max:literal)+) => {$( + #[derive(Copy, Clone, Default)] + pub struct $t; + unsafe impl HrtimPrescaler for $t { + const BITS: u8 = $b; + const VALUE: u8 = $v; + const MIN_CR: u16 = $min; + const MAX_CR: u16 = $max; + } + )+}; +} + +impl_pscl! { + Pscl1 => 0b000, 1, 0x0060, 0xFFDF + Pscl2 => 0b001, 2, 0x0030, 0xFFEF + Pscl4 => 0b010, 4, 0x0018, 0xFFF7 + Pscl8 => 0b011, 8, 0x000C, 0xFFFB + Pscl16 => 0b100, 16, 0x0006, 0xFFFD + Pscl32 => 0b101, 32, 0x0003, 0xFFFD + Pscl64 => 0b110, 64, 0x0003, 0xFFFD + Pscl128 => 0b111, 128, 0x0003, 0xFFFD +} + +/// HrTim timer +struct TimerHrTim(PhantomData); + +impl pwm::TimerType for TimerHrTim { + // Period calculator for 16-bit hrtimers + // + // NOTE: This function will panic if the calculated period can not fit into 16 bits + fn calculate_frequency(base_freq: HertzU64, freq: Hertz, alignment: Alignment) -> (u32, u16) { + let ideal_period = pwm::Timer32Bit::calculate_frequency(base_freq, freq, alignment).0 + 1; + + let prescale = u32::from(PSC::VALUE); + + // Round to the nearest period + let period = (ideal_period + (prescale >> 1)) / prescale - 1; + + // It IS possible to fail this assert + assert!(period <= 0xFFFF); + + (period, PSC::BITS.into()) + } +} diff --git a/src/hrtim/output.rs b/src/hrtim/output.rs new file mode 100644 index 00000000..d2e9854f --- /dev/null +++ b/src/hrtim/output.rs @@ -0,0 +1,300 @@ +use core::marker::PhantomData; +use stm32g4::stm32g474::{ + HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF, +}; +use crate::hrtim::external_event::ExternalEventSource; + +use super::event::{EventSource, NeighborTimerEventSource}; +use crate::{ + gpio::{ + gpioa::{PA10, PA11, PA8, PA9}, + gpiob::{PB12, PB13, PB14, PB15}, + gpioc::{PC6, PC7, PC8, PC9}, + Alternate, AF13, AF3, + }, + pwm::{ActiveHigh, ComplementaryImpossible, Pins, Pwm}, + stm32::HRTIM_COMMON, +}; + +macro_rules! hrtim_out_common { + ($TIMX:ident, $set_event:expr, $register:ident, $action:ident) => {{ + let tim = unsafe { &*$TIMX::ptr() }; + + match $set_event { + EventSource::Cr1 { .. } => tim.$register.modify(|_r, w| w.cmp1().$action()), + EventSource::Cr2 { .. } => tim.$register.modify(|_r, w| w.cmp2().$action()), + EventSource::Cr3 { .. } => tim.$register.modify(|_r, w| w.cmp3().$action()), + EventSource::Cr4 { .. } => tim.$register.modify(|_r, w| w.cmp4().$action()), + EventSource::Period { .. } => tim.$register.modify(|_r, w| w.per().$action()), + + EventSource::MasterCr1 { .. } => tim.$register.modify(|_r, w| w.mstcmp1().$action()), + EventSource::MasterCr2 { .. } => tim.$register.modify(|_r, w| w.mstcmp2().$action()), + EventSource::MasterCr3 { .. } => tim.$register.modify(|_r, w| w.mstcmp3().$action()), + EventSource::MasterCr4 { .. } => tim.$register.modify(|_r, w| w.mstcmp4().$action()), + EventSource::MasterPeriod { .. } => tim.$register.modify(|_r, w| w.mstper().$action()), + + EventSource::ExternalEvent(e) => match e { + ExternalEventSource::Eevnt1 { .. } => { + tim.$register.modify(|_r, w| w.extevnt1().$action()) + }, + ExternalEventSource::Eevnt2 { .. } => { + tim.$register.modify(|_r, w| w.extevnt2().$action()) + }, + ExternalEventSource::Eevnt3 { .. } => { + tim.$register.modify(|_r, w| w.extevnt3().$action()) + }, + ExternalEventSource::Eevnt4 { .. } => { + tim.$register.modify(|_r, w| w.extevnt4().$action()) + }, + ExternalEventSource::Eevnt5 { .. } => { + tim.$register.modify(|_r, w| w.extevnt5().$action()) + }, + ExternalEventSource::Eevnt6 { .. } => { + tim.$register.modify(|_r, w| w.extevnt6().$action()) + }, + ExternalEventSource::Eevnt7 { .. } => { + tim.$register.modify(|_r, w| w.extevnt7().$action()) + }, + ExternalEventSource::Eevnt8 { .. } => { + tim.$register.modify(|_r, w| w.extevnt8().$action()) + }, + ExternalEventSource::Eevnt9 { .. } => { + tim.$register.modify(|_r, w| w.extevnt9().$action()) + }, + ExternalEventSource::Eevnt10 { .. } => { + tim.$register.modify(|_r, w| w.extevnt10().$action()) + }, + } + + EventSource::NeighborTimer { n } => match n { + NeighborTimerEventSource::TimEvent1 { .. } => { + tim.$register.modify(|_r, w| w.timevnt1().$action()) + } + NeighborTimerEventSource::TimEvent2 { .. } => { + tim.$register.modify(|_r, w| w.timevnt2().$action()) + } + NeighborTimerEventSource::TimEvent3 { .. } => { + tim.$register.modify(|_r, w| w.timevnt3().$action()) + } + NeighborTimerEventSource::TimEvent4 { .. } => { + tim.$register.modify(|_r, w| w.timevnt4().$action()) + } + NeighborTimerEventSource::TimEvent5 { .. } => { + tim.$register.modify(|_r, w| w.timevnt5().$action()) + } + NeighborTimerEventSource::TimEvent6 { .. } => { + tim.$register.modify(|_r, w| w.timevnt6().$action()) + } + NeighborTimerEventSource::TimEvent7 { .. } => { + tim.$register.modify(|_r, w| w.timevnt7().$action()) + } + NeighborTimerEventSource::TimEvent8 { .. } => { + tim.$register.modify(|_r, w| w.timevnt8().$action()) + } + NeighborTimerEventSource::TimEvent9 { .. } => { + tim.$register.modify(|_r, w| w.timevnt9().$action()) + } + }, + } + }}; +} + +macro_rules! hrtim_out { + ($($TIMX:ident: $out_type:ident: $tXYoen:ident, $tXYodis:ident, $tXYods:ident, $setXYr:ident, $rstXYr:ident,)+) => {$( + impl HrOutput for $out_type<$TIMX, PSCL> { + fn enable(&mut self) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.oenr.write(|w| { w.$tXYoen().set_bit() }); + } + + fn disable(&mut self) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.odisr.write(|w| { w.$tXYodis().set_bit() }); + } + + fn enable_set_event(&mut self, set_event: impl Into>) { + hrtim_out_common!($TIMX, set_event.into(), $setXYr, set_bit) + } + fn disable_set_event(&mut self, set_event: impl Into>) { + hrtim_out_common!($TIMX, set_event.into(), $setXYr, clear_bit) + } + + fn enable_rst_event(&mut self, reset_event: impl Into>) { + hrtim_out_common!($TIMX, reset_event.into(), $rstXYr, set_bit) + } + fn disable_rst_event(&mut self, reset_event: impl Into>) { + hrtim_out_common!($TIMX, reset_event.into(), $rstXYr, clear_bit) + } + + 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(); + } + + match (oen, ods) { + (true, _) => State::Running, + (false, false) => State::Idle, + (false, true) => State::Fault + } + } + } + )+}; +} + +hrtim_out! { + HRTIM_TIMA: HrOut1: ta1oen, ta1odis, ta1ods, seta1r, rsta1r, + HRTIM_TIMA: HrOut2: ta2oen, ta2odis, ta2ods, seta2r, rsta2r, + + HRTIM_TIMB: HrOut1: tb1oen, tb1odis, tb1ods, setb1r, rstb1r, + HRTIM_TIMB: HrOut2: tb2oen, tb2odis, tb2ods, setb2r, rstb2r, + + HRTIM_TIMC: HrOut1: tc1oen, tc1odis, tc1ods, setc1r, rstc1r, + HRTIM_TIMC: HrOut2: tc2oen, tc2odis, tc2ods, setc2r, rstc2r, + + HRTIM_TIMD: HrOut1: td1oen, td1odis, td1ods, setd1r, rstd1r, + HRTIM_TIMD: HrOut2: td2oen, td2odis, td2ods, setd2r, rstd2r, + + HRTIM_TIME: HrOut1: te1oen, te1odis, te1ods, sete1r, rste1r, + HRTIM_TIME: HrOut2: te2oen, te2odis, te2ods, sete2r, rste2r, + + HRTIM_TIMF: HrOut1: tf1oen, tf1odis, tf1ods, setf1r, rstf1r, + HRTIM_TIMF: HrOut2: tf2oen, tf2odis, tf2ods, setf2r, rstf2r, +} + +pub trait HrOutput { + /// Enable this output + fn enable(&mut self); + + /// Disable this output + fn disable(&mut self); + + /// Set this output to active every time the specified event occurs + /// + /// NOTE: Enabling the same event for both SET and RESET + /// will make that event TOGGLE the output + fn enable_set_event(&mut self, set_event: impl Into>); + + /// Stop listening to the specified event + fn disable_set_event(&mut self, set_event: impl Into>); + + /// Set this output to *not* active every time the specified event occurs + /// + /// NOTE: Enabling the same event for both SET and RESET + /// will make that event TOGGLE the output + fn enable_rst_event(&mut self, reset_event: impl Into>); + + /// Stop listening to the specified event + fn disable_rst_event(&mut self, reset_event: impl Into>); + + /// Get current state of the output + fn get_state(&self) -> State; +} + +#[derive(Debug, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum State { + Idle, + Running, + Fault, +} + +pub unsafe trait ToHrOut { + type Out: ToHrOut; +} + +unsafe impl ToHrOut for (PA, PB) +where + PA: ToHrOut, + PB: ToHrOut, +{ + type Out = (PA::Out, PB::Out); +} + +pub struct HrOut1(PhantomData<(TIM, PSCL)>); +pub struct HrOut2(PhantomData<(TIM, PSCL)>); + +macro_rules! pins { + ($($TIMX:ty: CH1: $CH1:ty, CH2: $CH2:ty)+) => { + $( + impl Pins<$TIMX, CH1, ComplementaryImpossible> for $CH1 { + type Channel = Pwm<$TIMX, CH1, ComplementaryImpossible, ActiveHigh, ActiveHigh>; + } + + impl Pins<$TIMX, CH2, ComplementaryImpossible> for $CH2 { + type Channel = Pwm<$TIMX, CH2, ComplementaryImpossible, ActiveHigh, ActiveHigh>; + } + + unsafe impl ToHrOut for $CH1 { + type Out = HrOut1<$TIMX, PSCL>; + } + + unsafe impl ToHrOut for $CH2 { + type Out = HrOut2<$TIMX, PSCL>; + } + + unsafe impl ToHrOut for HrOut1<$TIMX, PSCL> { + type Out

= HrOut1<$TIMX, P>; + } + + unsafe impl ToHrOut for HrOut2<$TIMX, PSCL> { + type Out

= HrOut2<$TIMX, P>; + } + )+ + } +} + +pins! { + HRTIM_TIMA: CH1: PA8>, CH2: PA9> + + HRTIM_TIMB: CH1: PA10>, CH2: PA11> + HRTIM_TIMC: CH1: PB12>, CH2: PB13> + HRTIM_TIMD: CH1: PB14>, CH2: PB15> + + HRTIM_TIME: CH1: PC8>, CH2: PC9> + HRTIM_TIMF: CH1: PC6>, CH2: PC7> +} + +impl Pins for () { + type Channel = (); +} + +unsafe impl ToHrOut for () { + type Out = (); +} + +// automatically implement Pins trait for tuples of individual pins +macro_rules! pins_tuples { + // Tuple of two pins + ($(($CHA:ident, $CHB:ident)),*) => { + $( + impl Pins, $CHB), (TA, TB)> for (CHA, CHB) + where + CHA: Pins, TA>, + CHB: Pins, TB>, + { + type Channel = (Pwm, TA, ActiveHigh, ActiveHigh>, Pwm, TB, ActiveHigh, ActiveHigh>); + } + + impl HrtimChannel for ($CHA, $CHB) {} + )* + }; +} + +pins_tuples! { + (CH1, CH2), + (CH2, CH1) +} + +pub struct CH1(PhantomData); +pub struct CH2(PhantomData); + +impl HrtimChannel for () {} +pub trait HrtimChannel {} + +impl HrtimChannel for CH1 {} +impl HrtimChannel for CH2 {} diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs new file mode 100644 index 00000000..fdaffd86 --- /dev/null +++ b/src/hrtim/timer.rs @@ -0,0 +1,141 @@ +use core::marker::PhantomData; +use stm32g4::stm32g474::{ + HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF, +}; + +use super::{ + control::HrPwmControl, + event::{ + TimerAResetEventSource, TimerBResetEventSource, TimerCResetEventSource, + TimerDResetEventSource, TimerEResetEventSource, TimerFResetEventSource, + }, +}; + +pub struct HrTim { + _timer: PhantomData, + _prescaler: PhantomData, +} + +pub trait HrTimer { + /// Get period of timer in number of ticks + /// + /// This is also the maximum duty usable for `HrCompareRegister::set_duty` + fn get_period(&self) -> u16; + + /// Set period of timer in number of ticks + /// + /// NOTE: This will affect the maximum duty usable for `HrCompareRegister::set_duty` + fn set_period(&mut self, period: u16); + + /// Start timer + fn start(&mut self, _hr_control: &mut HrPwmControl); + + /// Stop timer + fn stop(&mut self, _hr_control: &mut HrPwmControl); + + /// Stop timer and reset counter + fn stop_and_reset(&mut self, _hr_control: &mut HrPwmControl); +} + +macro_rules! hrtim_timer { + ($($TIMX:ident: $cntXr:ident, $cntx:ident, $perXr:ident, $tXcen:ident, $perx:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident, $icr:ident, $repc:ident, $([$rstXr:ident, $TimerXResetEventSource:ident],)*)+) => {$( + impl HrTimer<$TIMX, PSCL> for HrTim<$TIMX, PSCL> { + fn get_period(&self) -> u16 { + let tim = unsafe { &*$TIMX::ptr() }; + + tim.$perXr.read().$perx().bits() + } + fn set_period(&mut self, period: u16) { + let tim = unsafe { &*$TIMX::ptr() }; + + tim.$perXr.write(|w| unsafe { w.$perx().bits(period as u16) }); + } + + /// Start timer + fn start(&mut self, _hr_control: &mut HrPwmControl) { + // Start timer + + // SAFETY: Since we hold _hr_control there is no risk for a race condition + let master = unsafe { &*HRTIM_MASTER::ptr() }; + master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); + } + + /// Stop timer + fn stop(&mut self, _hr_control: &mut HrPwmControl) { + // Stop counter + // SAFETY: Since we hold _hr_control there is no risk for a race condition + let master = unsafe { &*HRTIM_MASTER::ptr() }; + master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); + } + + /// Stop timer and reset counter + fn stop_and_reset(&mut self, _hr_control: &mut HrPwmControl) { + self.stop(_hr_control); + + // Reset counter + let tim = unsafe { &*$TIMX::ptr() }; + unsafe { tim.$cntXr.write(|w| w.$cntx().bits(0)); } + } + } + + impl HrTim<$TIMX, PSCL> { + $( + /// 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 + pub fn enable_reset_event(&mut self, set_event: $TimerXResetEventSource) { + let tim = unsafe { &*$TIMX::ptr() }; + + unsafe { tim.$rstXr.modify(|r, w| w.bits(r.bits() | set_event as u32)); } + } + + /// Stop listening to the specified event + pub fn disable_reset_event(&mut self, set_event: $TimerXResetEventSource) { + let tim = unsafe { &*$TIMX::ptr() }; + + unsafe { tim.$rstXr.modify(|r, w| w.bits(r.bits() & !(set_event as u32))); } + })* + + pub fn set_repetition_counter(&mut self, repetition_counter: u8) { + let tim = unsafe { &*$TIMX::ptr() }; + + unsafe { tim.$rep.write(|w| w.$repx().bits(repetition_counter)); } + } + + pub fn enable_repetition_interrupt(&mut self, enable: bool) { + let tim = unsafe { &*$TIMX::ptr() }; + + tim.$dier.modify(|_r, w| w.$repie().bit(enable)); + } + + pub fn clear_repetition_interrupt(&mut self) { + let tim = unsafe { &*$TIMX::ptr() }; + + tim.$icr.write(|w| w.$repc().set_bit()); + } + } + )+}; +} + +hrtim_timer! { + HRTIM_MASTER: mcntr, mcnt, mper, mcen, mper, mrep, mrep, mdier, mrepie, micr, mrepc, + + HRTIM_TIMA: cntar, cntx, perar, tacen, perx, repar, repx, timadier, repie, timaicr, repc, [rstar, TimerAResetEventSource], + HRTIM_TIMB: cntr, cntx, perbr, tbcen, perx, repbr, repx, timbdier, repie, timbicr, repc, [rstbr, TimerBResetEventSource], + HRTIM_TIMC: cntcr, cntx, percr, tccen, perx, repcr, repx, timcdier, repie, timcicr, repc, [rstcr, TimerCResetEventSource], + HRTIM_TIMD: cntdr, cntx, perdr, tdcen, perx, repdr, repx, timddier, repie, timdicr, repc, [rstdr, TimerDResetEventSource], + HRTIM_TIME: cnter, cntx, perer, tecen, perx, reper, repx, timedier, repie, timeicr, repc, [rster, TimerEResetEventSource], + HRTIM_TIMF: cntfr, cntx, perfr, tfcen, perx, repfr, repx, timfdier, repie, timficr, repc, [rstfr, TimerFResetEventSource], +} diff --git a/src/lib.rs b/src/lib.rs index 93c12d07..a18b3c38 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -83,6 +83,9 @@ pub mod dma; pub mod exti; pub mod flash; pub mod gpio; + +#[cfg(any(feature = "stm32g474", feature = "stm32g484"))] +pub mod hrtim; pub mod i2c; pub mod opamp; pub mod prelude; diff --git a/src/pwm.rs b/src/pwm.rs index 166389b0..25338b60 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -169,9 +169,6 @@ //! This code has been taken from the stm32h7xx-hal project and modified slightly to support //! STM32G4xx MCUs. It has originally been licensed under the 0-clause BSD license. -#[cfg(any(feature = "stm32g474", feature = "stm32g484"))] -pub mod hrtim; - use core::marker::PhantomData; use core::mem::MaybeUninit; @@ -1031,13 +1028,13 @@ pins! { ] } -trait TimerType { +pub(crate) trait TimerType { /// Returns (arr, psc) bits fn calculate_frequency(base_freq: HertzU64, freq: Hertz, alignment: Alignment) -> (u32, u16); } /// Any 32-bit timer -struct Timer32Bit; +pub(crate) struct Timer32Bit; impl TimerType for Timer32Bit { // Period and prescaler calculator for 32-bit timers diff --git a/src/pwm/hrtim.rs b/src/pwm/hrtim.rs deleted file mode 100644 index 9108296e..00000000 --- a/src/pwm/hrtim.rs +++ /dev/null @@ -1,2016 +0,0 @@ -mod external_event; -mod fault; -mod calibration; - -use core::marker::PhantomData; -use core::mem::MaybeUninit; - -use fugit::HertzU64; - -use crate::gpio::gpioa::{PA10, PA11, PA8, PA9}; -use crate::gpio::gpiob::{PB12, PB13, PB14, PB15}; -use crate::gpio::gpioc::{PC6, PC7, PC8, PC9}; -use crate::gpio::{Alternate, AF13, AF3}; -use crate::pwm::hrtim::fault::{FaultAction, FaultSource}; -use crate::stm32::{ - HRTIM_COMMON, HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, - HRTIM_TIMF, -}; - -use self::calibration::HrTimOngoingCalibration; -use self::fault::{ - FltMonitor1, FltMonitor2, FltMonitor3, FltMonitor4, FltMonitor5, FltMonitor6, FltMonitorSys, -}; - -use super::{ - ActiveHigh, Alignment, ComplementaryImpossible, Pins, Polarity, Pwm, PwmPinEnable, TimerType, -}; -use crate::rcc::{GetBusFreq, Rcc}; -use crate::time::Hertz; - -pub struct CH1(PhantomData); -pub struct CH2(PhantomData); - -/// Internal enum that keeps track of the count settings before PWM is finalized -enum CountSettings { - Frequency(Hertz), - Period(u16), -} - -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum HrTimerMode { - SingleShotNonRetriggerable, - SingleShotRetriggerable, - Continuous, -} - -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum HrCountingDirection { - /// Asymetrical up counting mode - /// - /// - - /// * * - /// Counting up * | * | - /// * * - /// * | * | - /// * * - /// * | * | - /// * * - /// -------------------------------------- - /// - /// ```txt - /// | *-------* *------ - /// | | | - /// | | | | - /// | | | - /// ----------* *------------------* - /// ``` - /// - /// This is the most common mode with least amount of quirks - Up, - - /// Symmetrical up-down counting mode - /// - /// - /// ```txt - /// Period--> * Counting * - /// Counting up * | * Counting Up * | - /// * * down * - /// * | * * | - /// * * * - /// * | * * | - /// 0 -->* * - /// --------------------------------------------------------------------------- - /// | *---------------* | *---------------* - /// | | | | | | - /// | | | | | | - /// | | | | | | - /// ----------* *-------------------* *--- - /// ``` - /// - /// NOTE: This is incompatible with - /// * Auto-delay - /// * Balanded Idle - /// * Triggered-half mode - /// - /// There is also differences in (including but not limited to) the following areas: - /// * Counter roll over event - /// * The events registered with `enable_set_event` will work as normal wen counting up, however when counting down, they will work as rst events. - /// * The events registered with `enable_rst_event` will work as normal wen counting up, however when counting down, they will work as set events. - UpDown, -} - -// Needed to calculate frequency -impl Into for HrCountingDirection { - fn into(self) -> super::Alignment { - match self { - HrCountingDirection::Up => super::Alignment::Left, - HrCountingDirection::UpDown => super::Alignment::Center, - } - } -} - -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum InterleavedMode { - Disabled, - - /// Dual interleaved or Half mode - /// - /// Automatically force - /// * Cr1 to PERIOD / 2 (not visable through `get_duty`). - /// Automatically updates when changing period - /// - /// NOTE: Affects Cr1 - Dual, - - /// Triple interleaved mode - /// - /// Automatically force - /// * Cr1 to 1 * PERIOD / 3 and - /// * Cr2 to 2 * PERIOD / 3 - /// (not visable through `get_duty`). Automatically updates when changing period. - /// - /// NOTE: Must not be used simultaneously with other modes - /// using CMP2 (dual channel dac trigger and triggered-half modes). - Triple, - - /// Quad interleaved mode - /// - /// Automatically force - /// * Cr1 to 1 * PERIOD / 4, - /// * Cr2 to 2 * PERIOD / 4 and - /// * Cr3 to 3 * PERIOD / 4 - /// (not visable through `get_duty`). Automatically updates when changing period. - /// - /// NOTE: Must not be used simultaneously with other modes - /// using CMP2 (dual channel dac trigger and triggered-half modes). - Quad, -} - -macro_rules! pins { - ($($TIMX:ty: CH1: $CH1:ty, CH2: $CH2:ty)+) => { - $( - impl Pins<$TIMX, CH1, ComplementaryImpossible> for $CH1 { - type Channel = Pwm<$TIMX, CH1, ComplementaryImpossible, ActiveHigh, ActiveHigh>; - } - - impl Pins<$TIMX, CH2, ComplementaryImpossible> for $CH2 { - type Channel = Pwm<$TIMX, CH2, ComplementaryImpossible, ActiveHigh, ActiveHigh>; - } - - unsafe impl ToHrOut for $CH1 { - type Out = HrOut1<$TIMX, PSCL>; - } - - unsafe impl ToHrOut for $CH2 { - type Out = HrOut2<$TIMX, PSCL>; - } - - unsafe impl ToHrOut for HrOut1<$TIMX, PSCL> { - type Out

= HrOut1<$TIMX, P>; - } - - unsafe impl ToHrOut for HrOut2<$TIMX, PSCL> { - type Out

= HrOut2<$TIMX, P>; - } - )+ - } -} - -pins! { - HRTIM_TIMA: CH1: PA8>, CH2: PA9> - - HRTIM_TIMB: CH1: PA10>, CH2: PA11> - HRTIM_TIMC: CH1: PB12>, CH2: PB13> - HRTIM_TIMD: CH1: PB14>, CH2: PB15> - - HRTIM_TIME: CH1: PC8>, CH2: PC9> - HRTIM_TIMF: CH1: PC6>, CH2: PC7> -} - -impl Pins for () { - type Channel = (); -} - -unsafe impl ToHrOut for () { - type Out = (); -} - -// automatically implement Pins trait for tuples of individual pins -macro_rules! pins_tuples { - // Tuple of two pins - ($(($CHA:ident, $CHB:ident)),*) => { - $( - impl Pins, $CHB), (TA, TB)> for (CHA, CHB) - where - CHA: Pins, TA>, - CHB: Pins, TB>, - { - type Channel = (Pwm, TA, ActiveHigh, ActiveHigh>, Pwm, TB, ActiveHigh, ActiveHigh>); - } - - impl HrtimChannel for ($CHA, $CHB) {} - )* - }; -} - -pins_tuples! { - (CH1, CH2), - (CH2, CH1) -} - -impl HrtimChannel for () {} - -/*pub struct Hrtimer { - _prescaler: PhantomData, - _timer: PhantomData, - period: u16, // $perXr.$perx - - cmp_value1: u16, // $cmpX1r.cmp1x - cmp_value2: u16, // $cmpX2r.cmp2x - cmp_value3: u16, // $cmpX3r.cmp3x - cmp_value4: u16, // $cmpX4r.cmp4x -}*/ - -// HrPwmExt trait -/// Allows the pwm() method to be added to the peripheral register structs from the device crate -pub trait HrPwmExt: Sized { - /// The requested frequency will be rounded to the nearest achievable frequency; the actual frequency may be higher or lower than requested. - fn pwm( - self, - _pins: PINS, - frequency: T, - control: &mut HrPwmControl, - rcc: &mut Rcc, - ) -> PINS::Channel - where - PINS: Pins + ToHrOut, - T: Into, - U: HrtimChannel; -} - -pub trait HrPwmAdvExt: Sized { - type PreloadSource; - - fn pwm_advanced( - self, - _pins: PINS, - rcc: &mut Rcc, - ) -> HrPwmBuilder> - where - PINS: Pins + ToHrOut, - CHANNEL: HrtimChannel; -} - -/// HrPwmBuilder is used to configure advanced HrTim PWM features -pub struct HrPwmBuilder { - _tim: PhantomData, - _prescaler: PhantomData, - _out: PhantomData, - timer_mode: HrTimerMode, - counting_direction: HrCountingDirection, - base_freq: HertzU64, - count: CountSettings, - preload_source: Option, - fault_enable_bits: u8, - fault1_bits: u8, - fault2_bits: u8, - enable_push_pull: bool, - interleaved_mode: InterleavedMode, // Also includes half mode - repetition_counter: u8, - deadtime: Option, - enable_repetition_interrupt: bool, - out1_polarity: Polarity, - out2_polarity: Polarity, -} - -pub enum PreloadSource { - /// Preloaded registers are updated on counter roll over or counter reset - OnCounterReset, - - /// Preloaded registers are updated by master timer update - OnMasterTimerUpdate, - - /// Prealoaded registers are updaten when the counter rolls over and the repetition counter is 0 - OnRepetitionUpdate, -} - -#[derive(Copy, Clone, Debug)] -pub struct DeadtimeConfig { - /// Prescaler for both rising and falling deadtime - prescaler: DeadtimePrescaler, - - /// 9-bits - deadtime_rising_value: u16, - - /// Is deadtime negative - deadtime_rising_sign: bool, - - /// 9-bits - deadtime_falling_value: u16, - - /// Is deadtime negative - deadtime_falling_sign: bool, -} - -impl DeadtimeConfig { - /// See RM0440 Table 221 'Deadtime resolution and max absolute values' - pub fn prescaler(mut self, value: DeadtimePrescaler) -> Self { - self.prescaler = value; - self - } - - /// Panic if value can not fit in 9 bits - pub fn deadtime_rising_value(mut self, value: u16) -> Self { - // 9 bits - assert!(value < (1 << 9)); - - self.deadtime_rising_value = value; - - self - } - - pub fn deadtime_rising_sign(mut self, is_negative: bool) -> Self { - self.deadtime_rising_sign = is_negative; - self - } - - /// Panic if value can not fit in 9 bits - pub fn deadtime_falling_value(mut self, value: u16) -> Self { - // 9 bits - assert!(value < (1 << 9)); - - self.deadtime_falling_value = value; - - self - } - - pub fn deadtime_falling_sign(mut self, is_negative: bool) -> Self { - self.deadtime_falling_sign = is_negative; - self - } -} - -impl Default for DeadtimeConfig { - fn default() -> Self { - Self { - prescaler: DeadtimePrescaler::Thrtim, - deadtime_rising_value: 170, // about 1us when f_sys = 170MHz - deadtime_rising_sign: false, - deadtime_falling_value: 170, // about 1us when f_sys = 170MHz - deadtime_falling_sign: false, - } - } -} - -#[derive(Copy, Clone, Debug)] -pub enum DeadtimePrescaler { - ThrtimDiv8 = 0b000, - ThrtimDiv4 = 0b001, - ThrtimDiv2 = 0b010, - Thrtim = 0b011, - ThrtimMul2 = 0b100, - ThrtimMul4 = 0b101, - ThrtimMul8 = 0b110, - ThrtimMul16 = 0b111, -} - -pub enum MasterPreloadSource { - /// Prealoaded registers are updaten when the master counter rolls over and the master repetition counter is 0 - OnMasterRepetitionUpdate, -} - -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 HrTim { - _timer: PhantomData, - _prescaler: PhantomData, -} - -pub trait HrTimer { - /// Get period of timer in number of ticks - /// - /// This is also the maximum duty usable for `HrCompareRegister::set_duty` - fn get_period(&self) -> u16; - - /// Set period of timer in number of ticks - /// - /// NOTE: This will affect the maximum duty usable for `HrCompareRegister::set_duty` - fn set_period(&mut self, period: u16); - - /// Start timer - fn start(&mut self, _hr_control: &mut HrPwmControl); - - /// Stop timer - fn stop(&mut self, _hr_control: &mut HrPwmControl); - - /// Stop timer and reset counter - fn stop_and_reset(&mut self, _hr_control: &mut HrPwmControl); -} - -macro_rules! impl_into_es { - ($dst:ident: [$(($t:ty, $ES:ident),)*]) => {$( - impl_into_es!($dst, $t, $ES); - )*}; - - ($dst:ident, $t:ty, $ES:ident) => { - impl Into> for &$t { - fn into(self) -> EventSource { - EventSource::$ES{ _x: PhantomData } - } - } - }; - ($dst:ident) => { - impl_into_es! { - $dst: [ - (HrCr1<$dst, PSCL>, Cr1), - (HrCr2<$dst, PSCL>, Cr2), - (HrCr3<$dst, PSCL>, Cr3), - (HrCr4<$dst, PSCL>, Cr4), - (HrTim<$dst, PSCL>, Period), - - (HrCr1, MasterCr1), - (HrCr2, MasterCr2), - (HrCr3, MasterCr3), - (HrCr4, MasterCr4), - (HrTim, MasterPeriod), - ] - } - }; -} - -impl_into_es!(HRTIM_TIMA); -impl_into_es!(HRTIM_TIMB); -impl_into_es!(HRTIM_TIMC); -impl_into_es!(HRTIM_TIMD); -impl_into_es!(HRTIM_TIME); -impl_into_es!(HRTIM_TIMF); - -macro_rules! impl_into_neighbor_es { - ( - DST: $dst:ident: [ - ($src1:ident, $cr1:ident), - ($src2:ident, $cr2:ident), - ($src3:ident, $cr3:ident), - ($src4:ident, $cr4:ident), - ($src5:ident, $cr5:ident), - ($src6:ident, $cr6:ident), - ($src7:ident, $cr7:ident), - ($src8:ident, $cr8:ident), - ($src9:ident, $cr9:ident), - ] - ) => { - impl_into_neighbor_es!($dst, $src1, $cr1, TimEvent1); - impl_into_neighbor_es!($dst, $src2, $cr2, TimEvent2); - impl_into_neighbor_es!($dst, $src3, $cr3, TimEvent3); - impl_into_neighbor_es!($dst, $src4, $cr4, TimEvent4); - impl_into_neighbor_es!($dst, $src5, $cr5, TimEvent5); - impl_into_neighbor_es!($dst, $src6, $cr6, TimEvent6); - impl_into_neighbor_es!($dst, $src7, $cr7, TimEvent7); - impl_into_neighbor_es!($dst, $src8, $cr8, TimEvent8); - impl_into_neighbor_es!($dst, $src9, $cr9, TimEvent9); - }; - - ($dst:ident, $src:ident, $cr:ident, $TimEventX:ident) => { - impl Into> for &$cr<$src, PSCL> { - fn into(self) -> EventSource { - EventSource::NeighborTimer { - n: NeighborTimerEventSource::$TimEventX { _x: PhantomData }, - } - } - } - }; -} - -impl_into_neighbor_es! { - DST: HRTIM_TIMA: [ - // src - (HRTIM_TIMB, HrCr1), - (HRTIM_TIMB, HrCr2), - (HRTIM_TIMC, HrCr2), - (HRTIM_TIMC, HrCr3), - (HRTIM_TIMD, HrCr1), - (HRTIM_TIMD, HrCr2), - (HRTIM_TIME, HrCr3), - (HRTIM_TIME, HrCr4), - (HRTIM_TIMF, HrCr4), - ] -} - -impl_into_neighbor_es! { - DST: HRTIM_TIMB: [ - // src - (HRTIM_TIMA, HrCr1), - (HRTIM_TIMA, HrCr2), - (HRTIM_TIMC, HrCr3), - (HRTIM_TIMC, HrCr4), - (HRTIM_TIMD, HrCr3), - (HRTIM_TIMD, HrCr4), - (HRTIM_TIME, HrCr1), - (HRTIM_TIME, HrCr2), - (HRTIM_TIMF, HrCr3), - ] -} - -impl_into_neighbor_es! { - DST: HRTIM_TIMC: [ - // src - (HRTIM_TIMA, HrCr2), - (HRTIM_TIMA, HrCr3), - (HRTIM_TIMB, HrCr2), - (HRTIM_TIMB, HrCr3), - (HRTIM_TIMD, HrCr2), - (HRTIM_TIMD, HrCr4), - (HRTIM_TIME, HrCr3), - (HRTIM_TIME, HrCr4), - (HRTIM_TIMF, HrCr2), - ] -} - -// TODO: Continue for TIMD, TIME and TIMF, see RM0440 Table 218. 'Events mapping across timer A to F' - -pub trait HrOutput { - /// Enable this output - fn enable(&mut self); - - /// Disable this output - fn disable(&mut self); - - /// Set this output to active every time the specified event occurs - /// - /// NOTE: Enabling the same event for both SET and RESET - /// will make that event TOGGLE the output - fn enable_set_event(&mut self, set_event: impl Into>); - - /// Stop listening to the specified event - fn disable_set_event(&mut self, set_event: impl Into>); - - /// Set this output to *not* active every time the specified event occurs - /// - /// NOTE: Enabling the same event for both SET and RESET - /// will make that event TOGGLE the output - fn enable_rst_event(&mut self, reset_event: impl Into>); - - /// Stop listening to the specified event - fn disable_rst_event(&mut self, reset_event: impl Into>); - - /// Get current state of the output - fn get_state(&self) -> State; -} - -#[derive(Debug, PartialEq)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum State { - Idle, - Running, - Fault, -} - -pub enum EventSource { - /// Compare match with compare register 1 of this timer - Cr1 { _x: PhantomData<(PSCL, DST)> }, - - /// Compare match with compare register 2 of this timer - Cr2 { _x: PhantomData<(PSCL, DST)> }, - - /// Compare match with compare register 3 of this timer - Cr3 { _x: PhantomData<(PSCL, DST)> }, - - /// Compare match with compare register 4 of this timer - Cr4 { _x: PhantomData<(PSCL, DST)> }, - - /// On complete period - Period { _x: PhantomData<(PSCL, DST)> }, - - /// Compare match with compare register 1 of master timer - MasterCr1 { _x: PhantomData<(PSCL, DST)> }, - - /// Compare match with compare register 2 of master timer - MasterCr2 { _x: PhantomData<(PSCL, DST)> }, - - /// Compare match with compare register 3 of master timer - MasterCr3 { _x: PhantomData<(PSCL, DST)> }, - - /// Compare match with compare register 4 of master timer - MasterCr4 { _x: PhantomData<(PSCL, DST)> }, - - /// On complete master period - MasterPeriod { _x: PhantomData<(PSCL, DST)> }, - - NeighborTimer { - n: NeighborTimerEventSource, - }, -} - -/// Compare events from neighbor timers -/// -/// See RM0440 Table 218. 'Events mapping across timer A to F' -pub enum NeighborTimerEventSource { - /// Timer event 1 - /// - /// This is different depending on destination timer: - /// |dest | source | - /// |-----|--------| - /// |TimA | B CR1 | - /// |TimB | A CR1 | - /// |TimC | A CR2 | - /// |TimD | A CR1 | - /// |TimE | A CR4 | - /// |TimF | A CR3 | - TimEvent1 { - _x: PhantomData<(PSCL, DST)>, - }, - - /// Timer event x - /// - /// This is different depending on destination timer: - /// |dest | source | - /// |-----|--------| - /// |TimA | x CRy | - /// |TimB | x CRy | - /// |TimC | x CRy | - /// |TimD | x CRy | - /// |TimE | x CRy | - /// |TimF | x CRy | - //TimEventx, - - /// Timer event 2 - /// - /// This is different depending on destination timer: - /// |dest | source | - /// |-----|--------| - /// |TimA | B CR2 | - /// |TimB | A CR2 | - /// |TimC | A CR3 | - /// |TimD | A CR4 | - /// |TimE | B CR3 | - /// |TimF | B CR1 | - TimEvent2 { - _x: PhantomData<(PSCL, DST)>, - }, - - /// Timer event 3 - /// - /// This is different depending on destination timer: - /// |dest | source | - /// |-----|--------| - /// |TimA | C CR2 | - /// |TimB | C CR3 | - /// |TimC | B CR2 | - /// |TimD | B CR2 | - /// |TimE | B CR4 | - /// |TimF | B CR4 | - TimEvent3 { - _x: PhantomData<(PSCL, DST)>, - }, - - /// Timer event 4 - /// - /// This is different depending on destination timer: - /// |dest | source | - /// |-----|--------| - /// |TimA | C CR3 | - /// |TimB | C CR4 | - /// |TimC | B CR3 | - /// |TimD | B CR4 | - /// |TimE | C CR1 | - /// |TimF | C CR1 | - TimEvent4 { - _x: PhantomData<(PSCL, DST)>, - }, - - // TODO: Document those - TimEvent5 { - _x: PhantomData<(PSCL, DST)>, - }, - TimEvent6 { - _x: PhantomData<(PSCL, DST)>, - }, - TimEvent7 { - _x: PhantomData<(PSCL, DST)>, - }, - TimEvent8 { - _x: PhantomData<(PSCL, DST)>, - }, - TimEvent9 { - _x: PhantomData<(PSCL, DST)>, - }, -} - -macro_rules! hr_timer_reset_event_source_common { - ($(#[$($attrss:tt)*])* pub enum $t:ident { [COMMON], $(#[$($attrss2:tt)*] $vals:tt = 1 << $x:literal,)*}) => { - $(#[$($attrss)*])* - pub enum $t { - $(#[$($attrss2)*] $vals = 1 << $x,)* - - /// The timer counter is reset upon external event 10. - Eevnt10 = 1 << 18, - - /// The timer counter is reset upon external event 9. - Eevnt9 = 1 << 17, - - /// The timer counter is reset upon external event 8. - Eevnt8 = 1 << 16, - - /// The timer counter is reset upon external event 7. - Eevnt7 = 1 << 15, - - /// The timer counter is reset upon external event 6. - Eevnt6 = 1 << 14, - - /// The timer counter is reset upon external event 5. - Eevnt5 = 1 << 13, - - /// The timer counter is reset upon external event 4. - Eevnt4 = 1 << 12, - - /// The timer counter is reset upon external event 3. - Eevnt3 = 1 << 11, - - /// The timer counter is reset upon external event 2. - Eevnt2 = 1 << 10, - - /// The timer counter is reset upon external event 1. - Eevnt1 = 1 << 9, - - /// The timer counter is reset upon master timer compare 4 event. - MasterCmp4 = 1 << 8, - - /// The timer counter is reset upon master timer compare 3 event. - MasterCmp3 = 1 << 7, - - /// The timer counter is reset upon master timer compare 2 event. - MasterCmp2 = 1 << 6, - - /// The timer counter is reset upon master timer compare 1 event. - MasterCmp1 = 1 << 5, - - /// The timer counter is reset upon master timer period event. - MasterPeriod = 1 << 4, - - /// The timer counter is reset upon timer its own compare 4 event - Cmp4 = 1 << 3, - - /// The timer counter is reset upon timer its own compare 2 event - Cmp2 = 1 << 2, - - /// The timer counter is reset upon update event. - Update = 1 << 1, - } - }; -} - -hr_timer_reset_event_source_common!( - /// A - pub enum TimerAResetEventSource { - [COMMON], - /// The timer counter is reset upon timer F compare 2 event. - TimFCmp2 = 1 << 31, - - /// The timer counter is reset upon timer E compare 4 event. - TimECmp4 = 1 << 30, - - /// The timer counter is reset upon timer E compare 2 event. - TimECmp2 = 1 << 29, - - /// The timer counter is reset upon timer E compare 1 event. - TimECmp1 = 1 << 28, - - /// The timer counter is reset upon timer D compare 4 event. - TimDCmp4 = 1 << 27, - - /// The timer counter is reset upon timer D compare 2 event. - TimDCmp2 = 1 << 26, - - /// The timer counter is reset upon timer D compare 1 event. - TimDCmp1 = 1 << 25, - - /// The timer counter is reset upon timer C compare 4 event. - TimCCmp4 = 1 << 24, - - /// The timer counter is reset upon timer C compare 2 event. - TimCCmp2 = 1 << 23, - - /// The timer counter is reset upon timer C compare 1 event. - TimCCmp1 = 1 << 22, - - /// The timer counter is reset upon timer B compare 4 event. - TimBCmp4 = 1 << 21, - - /// The timer counter is reset upon timer B compare 2 event. - TimBCmp2 = 1 << 20, - - /// The timer counter is reset upon timer B compare 1 event. - TimBCmp1 = 1 << 19, - - /// The timer counter is reset upon timer F compare 1 event. - TimFCmp1 = 1 << 0, - } -); - -hr_timer_reset_event_source_common!( - /// B - pub enum TimerBResetEventSource { - [COMMON], - - /// The timer counter is reset upon timer F compare 2 event. - TimFCmp2 = 1 << 31, - - /// The timer counter is reset upon timer E compare 4 event. - TimECmp4 = 1 << 30, - - /// The timer counter is reset upon timer E compare 2 event. - TimECmp2 = 1 << 29, - - /// The timer counter is reset upon timer E compare 1 event. - TimECmp1 = 1 << 28, - - /// The timer counter is reset upon timer D compare 4 event. - TimDCmp4 = 1 << 27, - - /// The timer counter is reset upon timer D compare 2 event. - TimDCmp2 = 1 << 26, - - /// The timer counter is reset upon timer D compare 1 event. - TimDCmp1 = 1 << 25, - - /// The timer counter is reset upon timer C compare 4 event. - TimCCmp4 = 1 << 24, - - /// The timer counter is reset upon timer C compare 2 event. - TimCCmp2 = 1 << 23, - - /// The timer counter is reset upon timer C compare 1 event. - TimCCmp1 = 1 << 22, - - /// The timer counter is reset upon timer A compare 4 event. - TimACmp4 = 1 << 21, - - /// The timer counter is reset upon timer A compare 2 event. - TimACmp2 = 1 << 20, - - /// The timer counter is reset upon timer A compare 1 event. - TimACmp1 = 1 << 19, - - - /// The timer counter is reset upon timer F compare 1 event. - TimFCmp1 = 1 << 0, - } -); - -hr_timer_reset_event_source_common!( - /// C - pub enum TimerCResetEventSource { - [COMMON], - - /// The timer counter is reset upon timer F compare 2 event. - TimFCmp2 = 1 << 31, - - /// The timer counter is reset upon timer E compare 4 event. - TimECmp4 = 1 << 30, - - /// The timer counter is reset upon timer E compare 2 event. - TimECmp2 = 1 << 29, - - /// The timer counter is reset upon timer E compare 1 event. - TimECmp1 = 1 << 28, - - /// The timer counter is reset upon timer D compare 4 event. - TimDCmp4 = 1 << 27, - - /// The timer counter is reset upon timer D compare 2 event. - TimDCmp2 = 1 << 26, - - /// The timer counter is reset upon timer D compare 1 event. - TimDCmp1 = 1 << 25, - - /// The timer counter is reset upon timer B compare 4 event. - TimBCmp4 = 1 << 24, - - /// The timer counter is reset upon timer B compare 2 event. - TimBCmp2 = 1 << 23, - - /// The timer counter is reset upon timer B compare 1 event. - TimBCmp1 = 1 << 22, - - /// The timer counter is reset upon timer A compare 4 event. - TimACmp4 = 1 << 21, - - /// The timer counter is reset upon timer A compare 2 event. - TimACmp2 = 1 << 20, - - /// The timer counter is reset upon timer A compare 1 event. - TimACmp1 = 1 << 19, - - - /// The timer counter is reset upon timer F compare 1 event. - TimFCmp1 = 1 << 0, - } -); - -hr_timer_reset_event_source_common!( - /// D - pub enum TimerDResetEventSource { - [COMMON], - - /// The timer counter is reset upon timer F compare 2 event. - TimFCmp2 = 1 << 31, - - /// The timer counter is reset upon timer E compare 4 event. - TimECmp4 = 1 << 30, - - /// The timer counter is reset upon timer E compare 2 event. - TimECmp2 = 1 << 29, - - /// The timer counter is reset upon timer E compare 1 event. - TimECmp1 = 1 << 28, - - /// The timer counter is reset upon timer C compare 4 event. - TimCCmp4 = 1 << 27, - - /// The timer counter is reset upon timer C compare 2 event. - TimCCmp2 = 1 << 26, - - /// The timer counter is reset upon timer C compare 1 event. - TimCCmp1 = 1 << 25, - - /// The timer counter is reset upon timer B compare 4 event. - TimBCmp4 = 1 << 24, - - /// The timer counter is reset upon timer B compare 2 event. - TimBCmp2 = 1 << 23, - - /// The timer counter is reset upon timer B compare 1 event. - TimBCmp1 = 1 << 22, - - /// The timer counter is reset upon timer A compare 4 event. - TimACmp4 = 1 << 21, - - /// The timer counter is reset upon timer A compare 2 event. - TimACmp2 = 1 << 20, - - /// The timer counter is reset upon timer A compare 1 event. - TimACmp1 = 1 << 19, - - /// The timer counter is reset upon timer F compare 1 event. - TimFCmp1 = 1 << 0, - } -); - -hr_timer_reset_event_source_common!( - /// E - pub enum TimerEResetEventSource { - [COMMON], - - /// The timer counter is reset upon timer F compare 2 event. - TimFCmp2 = 1 << 31, - - /// The timer counter is reset upon timer D compare 4 event. - TimDCmp4 = 1 << 30, - - /// The timer counter is reset upon timer D compare 2 event. - TimDCmp2 = 1 << 29, - - /// The timer counter is reset upon timer D compare 1 event. - TimDCmp1 = 1 << 28, - - /// The timer counter is reset upon timer C compare 4 event. - TimCCmp4 = 1 << 27, - - /// The timer counter is reset upon timer C compare 2 event. - TimCCmp2 = 1 << 26, - - /// The timer counter is reset upon timer C compare 1 event. - TimCCmp1 = 1 << 25, - - /// The timer counter is reset upon timer B compare 4 event. - TimBCmp4 = 1 << 24, - - /// The timer counter is reset upon timer B compare 2 event. - TimBCmp2 = 1 << 23, - - /// The timer counter is reset upon timer B compare 1 event. - TimBCmp1 = 1 << 22, - - /// The timer counter is reset upon timer A compare 4 event. - TimACmp4 = 1 << 21, - - /// The timer counter is reset upon timer A compare 2 event. - TimACmp2 = 1 << 20, - - /// The timer counter is reset upon timer A compare 1 event. - TimACmp1 = 1 << 19, - - - /// The timer counter is reset upon timer F compare 1 event. - TimFCmp1 = 1 << 0, - } -); - -hr_timer_reset_event_source_common!( - /// F - pub enum TimerFResetEventSource { - [COMMON], - - /// The timer counter is reset upon timer E compare 2 event. - TimECmp2 = 1 << 31, - - /// The timer counter is reset upon timer D compare 4 event. - TimDCmp4 = 1 << 30, - - /// The timer counter is reset upon timer D compare 2 event. - TimDCmp2 = 1 << 29, - - /// The timer counter is reset upon timer D compare 1 event. - TimDCmp1 = 1 << 28, - - /// The timer counter is reset upon timer C compare 4 event. - TimCCmp4 = 1 << 27, - - /// The timer counter is reset upon timer C compare 2 event. - TimCCmp2 = 1 << 26, - - /// The timer counter is reset upon timer C compare 1 event. - TimCCmp1 = 1 << 25, - - /// The timer counter is reset upon timer B compare 4 event. - TimBCmp4 = 1 << 24, - - /// The timer counter is reset upon timer B compare 2 event. - TimBCmp2 = 1 << 23, - - /// The timer counter is reset upon timer B compare 1 event. - TimBCmp1 = 1 << 22, - - /// The timer counter is reset upon timer A compare 4 event. - TimACmp4 = 1 << 21, - - /// The timer counter is reset upon timer A compare 2 event. - TimACmp2 = 1 << 20, - - /// The timer counter is reset upon timer A compare 1 event. - TimACmp1 = 1 << 19, - - /// The timer counter is reset upon timer E compare 1 event. - TimECmp1 = 1 << 0, - } -); - -pub unsafe trait ToHrOut { - type Out: ToHrOut; -} - -unsafe impl ToHrOut for (PA, PB) -where - PA: ToHrOut, - PB: ToHrOut, -{ - type Out = (PA::Out, PB::Out); -} - -pub struct HrOut1(PhantomData<(TIM, PSCL)>); -pub struct HrOut2(PhantomData<(TIM, PSCL)>); - -macro_rules! hrtim_finalize_body { - ($this:expr, $PreloadSource:ident, $TIMX:ident: ( - $timXcr:ident, $ck_psc:ident, $perXr:ident, $perx:ident, $tXcen:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident $(, $timXcr2:ident, $fltXr:ident, $outXr:ident, $dtXr:ident)*), - ) => {{ - let tim = unsafe { &*$TIMX::ptr() }; - let (period, prescaler_bits) = match $this.count { - CountSettings::Period(period) => (period as u32, PSCL::BITS as u16), - CountSettings::Frequency( freq ) => { - >::calculate_frequency($this.base_freq, freq, $this.counting_direction.into()) - }, - }; - - let (half, intlvd) = match $this.interleaved_mode { - InterleavedMode::Disabled => (false, 0b00), - InterleavedMode::Dual => (true, 0b00), - InterleavedMode::Triple => (false, 0b01), - InterleavedMode::Quad => (false, 0b10), - }; - - // Write prescaler and any special modes - tim.$timXcr.modify(|_r, w| unsafe { - w - // Enable Continuous mode - .cont().bit($this.timer_mode == HrTimerMode::Continuous) - .retrig().bit($this.timer_mode == HrTimerMode::SingleShotRetriggerable) - - // TODO: add support for more modes - - // Interleaved mode - .intlvd().bits(intlvd) - - // half/double interleaved mode - .half().bit(half) - - // Set prescaler - .$ck_psc().bits(prescaler_bits as u8) - }); - - $( - tim.$timXcr2.modify(|_r, w| - // Set counting direction - w.udm().bit($this.counting_direction == HrCountingDirection::UpDown) - ); - - // Only available for timers with outputs(not HRTIM_MASTER) - let _ = tim.$outXr; - tim.$timXcr.modify(|_r, w| - // Push-Pull mode - w.pshpll().bit($this.enable_push_pull) - ); - )* - - // Write period - tim.$perXr.write(|w| unsafe { w.$perx().bits(period as u16) }); - - // Enable fault sources and lock configuration - $(unsafe { - // Enable fault sources - let fault_enable_bits = $this.fault_enable_bits as u32; - tim.$fltXr.write(|w| w - .flt1en().bit(fault_enable_bits & (1 << 0) != 0) - .flt2en().bit(fault_enable_bits & (1 << 1) != 0) - .flt3en().bit(fault_enable_bits & (1 << 2) != 0) - .flt4en().bit(fault_enable_bits & (1 << 3) != 0) - .flt5en().bit(fault_enable_bits & (1 << 4) != 0) - .flt6en().bit(fault_enable_bits & (1 << 5) != 0) - ); - - // ... and lock configuration - tim.$fltXr.modify(|_r, w| w.fltlck().set_bit()); - - tim.$outXr.modify(|_r, w| w - // Set actions on fault for both outputs - .fault1().bits($this.fault1_bits) - .fault2().bits($this.fault2_bits) - - // Set output polarity for both outputs - .pol1().bit($this.out1_polarity == Polarity::ActiveLow) - .pol2().bit($this.out2_polarity == Polarity::ActiveLow) - ); - if let Some(deadtime) = $this.deadtime { - let DeadtimeConfig { - prescaler, - deadtime_rising_value, - deadtime_rising_sign, - deadtime_falling_value, - deadtime_falling_sign, - } = deadtime; - - // SAFETY: DeadtimeConfig makes sure rising and falling values are valid - // and DeadtimePrescaler has its own garantuee - tim.$dtXr.modify(|_r, w| w - .dtprsc().bits(prescaler as u8) - .dtrx().bits(deadtime_rising_value) - .sdtrx().bit(deadtime_rising_sign) - .dtfx().bits(deadtime_falling_value) - .sdtfx().bit(deadtime_falling_sign) - - // Lock configuration - .dtflkx().set_bit() - .dtfslkx().set_bit() - .dtrlkx().set_bit() - .dtrslkx().set_bit() - ); - tim.$outXr.modify(|_r, w| w.dten().set_bit()); - } - })* - - - hrtim_finalize_body!($PreloadSource, $this, tim, $timXcr); - - // Set repetition counter - unsafe { tim.$rep.write(|w| w.$repx().bits($this.repetition_counter)); } - - // Enable interrupts - tim.$dier.modify(|_r, w| w.$repie().bit($this.enable_repetition_interrupt)); - - // Start timer - //let master = unsafe { &*HRTIM_MASTER::ptr() }; - //master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); - - unsafe { - MaybeUninit::uninit().assume_init() - } - }}; - - (PreloadSource, $this:expr, $tim:expr, $timXcr:ident) => {{ - match $this.preload_source { - Some(PreloadSource::OnCounterReset) => { - $tim.$timXcr.modify(|_r, w| w - .tx_rstu().set_bit() - .preen().set_bit() - ) - }, - Some(PreloadSource::OnMasterTimerUpdate) => { - $tim.$timXcr.modify(|_r, w| w - .mstu().set_bit() - .preen().set_bit() - ) - } - Some(PreloadSource::OnRepetitionUpdate) => { - $tim.$timXcr.modify(|_r, w| w - .tx_repu().set_bit() - .preen().set_bit() - ) - } - None => () - } - }}; - - (MasterPreloadSource, $this:expr, $tim:expr, $timXcr:ident) => {{ - match $this.preload_source { - Some(MasterPreloadSource::OnMasterRepetitionUpdate) => { - $tim.$timXcr.modify(|_r, w| w - .mrepu().set_bit() - .preen().set_bit() - ) - } - None => () - } - }}; -} - -macro_rules! hrtim_common_methods { - ($TIMX:ident, $PS:ident) => { - /// Set the PWM frequency; will overwrite the previous prescaler and period - /// The requested frequency will be rounded to the nearest achievable frequency; the actual frequency may be higher or lower than requested. - pub fn frequency>(mut self, freq: T) -> Self { - self.count = CountSettings::Frequency(freq.into()); - - self - } - - /// Set the prescaler; PWM count runs at base_frequency/(prescaler+1) - pub fn prescaler

( - self, - _prescaler: P, - ) -> HrPwmBuilder<$TIMX, P, $PS, ::Out

> - where - P: HrtimPrescaler, - { - let HrPwmBuilder { - _tim, - _prescaler: _, - _out, - 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, - out1_polarity, - out2_polarity, - } = self; - - let period = match count { - CountSettings::Frequency(_) => u16::MAX, - CountSettings::Period(period) => period, - }; - - let count = CountSettings::Period(period); - - HrPwmBuilder { - _tim, - _prescaler: PhantomData, - _out: PhantomData, - 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, - 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 - } - }; -} - -// Implement PWM configuration for timer -macro_rules! hrtim_hal { - ($($TIMX:ident: ($timXcr:ident, $timXcr2:ident, $perXr:ident, $tXcen:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident, $fltXr:ident, $outXr:ident, $dtXr:ident),)+) => { - $( - - // Implement HrPwmExt trait for hrtimer - impl HrPwmExt for $TIMX { - fn pwm( - self, - pins: PINS, - frequency: T, - control: &mut HrPwmControl, - rcc: &mut Rcc, - ) -> PINS::Channel - where - PINS: Pins + ToHrOut, - T: Into, - U: HrtimChannel, - { - let _= self.pwm_advanced(pins, rcc).frequency(frequency).finalize(control); - - unsafe { MaybeUninit::::uninit().assume_init() } - } - } - - impl HrPwmAdvExt for $TIMX { - type PreloadSource = PreloadSource; - - fn pwm_advanced( - self, - _pins: PINS, - rcc: &mut Rcc, - ) -> HrPwmBuilder> - where - PINS: Pins + ToHrOut, - CHANNEL: HrtimChannel - { - // 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, - _out: PhantomData, - 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, - out1_polarity: Polarity::ActiveHigh, - out2_polarity: Polarity::ActiveHigh, - } - } - } - - impl - HrPwmBuilder<$TIMX, PSCL, PreloadSource, OUT> - where - PSCL: HrtimPrescaler, - OUT: ToHrOut, - { - pub fn finalize(self, _control: &mut HrPwmControl) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX, PSCL>, HrCr2<$TIMX, PSCL>, HrCr3<$TIMX, PSCL>, HrCr4<$TIMX, PSCL>), OUT) { - hrtim_finalize_body!(self, PreloadSource, $TIMX: ($timXcr, ck_pscx, $perXr, perx, $tXcen, $rep, $repx, $dier, $repie, $timXcr2, $fltXr, $outXr, $dtXr),) - } - - hrtim_common_methods!($TIMX, PreloadSource); - - pub fn with_fault_source(mut self, _fault_source: FS) -> Self - where FS: FaultSource - { - self.fault_enable_bits = 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 - } - - /// 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 - } - )+ - }; -} - -macro_rules! hrtim_hal_master { - ($($TIMX:ident: ($timXcr:ident, $ck_psc:ident, $perXr:ident, $perx:ident, $rep:ident, $tXcen:ident, $dier:ident, $repie:ident),)+) => {$( - impl HrPwmAdvExt for $TIMX { - type PreloadSource = MasterPreloadSource; - - fn pwm_advanced( - self, - _pins: PINS, - rcc: &mut Rcc, - ) -> HrPwmBuilder> - where - PINS: Pins + ToHrOut, // TODO: figure out - CHANNEL: HrtimChannel - { - // 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, - _out: PhantomData, - 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, - out1_polarity: Polarity::ActiveHigh, - out2_polarity: Polarity::ActiveHigh, - } - } - } - - impl - HrPwmBuilder<$TIMX, PSCL, MasterPreloadSource, OUT> - where - PSCL: HrtimPrescaler, - OUT: ToHrOut, - { - pub fn finalize(self, _control: &mut HrPwmControl) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX, PSCL>, HrCr2<$TIMX, PSCL>, HrCr3<$TIMX, PSCL>, HrCr4<$TIMX, PSCL>)) { - hrtim_finalize_body!(self, MasterPreloadSource, $TIMX: ($timXcr, $ck_psc, $perXr, $perx, $tXcen, $rep, $rep, $dier, $repie),) - } - - hrtim_common_methods!($TIMX, MasterPreloadSource); - } - )*} -} - -macro_rules! hrtim_pin_hal { - ($($TIMX:ident: - ($CH:ident, $perXr:ident, $cmpXYr:ident, $cmpYx:ident, $cmpY:ident, $tXYoen:ident, $tXYodis:ident),)+ - ) => { - $( - impl hal::PwmPin for Pwm<$TIMX, $CH, COMP, POL, NPOL> - where Pwm<$TIMX, $CH, COMP, POL, NPOL>: PwmPinEnable { - type Duty = u16; - - // You may not access self in the following methods! - // See unsafe above - - fn disable(&mut self) { - self.ccer_disable(); - } - - fn enable(&mut self) { - self.ccer_enable(); - } - - fn get_duty(&self) -> Self::Duty { - let tim = unsafe { &*$TIMX::ptr() }; - - tim.$cmpXYr.read().$cmpYx().bits() - } - - fn get_max_duty(&self) -> Self::Duty { - let tim = unsafe { &*$TIMX::ptr() }; - - let arr = tim.$perXr.read().perx().bits(); - - // One PWM cycle is ARR+1 counts long - // Valid PWM duty cycles are 0 to ARR+1 - // However, if ARR is 65535 on a 16-bit timer, we can't add 1 - // In that case, 100% duty cycle is not possible, only 65535/65536 - if arr == Self::Duty::MAX { - arr - } - else { - arr + 1 - } - } - - /// Set duty cycle - /// - /// NOTE: Please observe limits(RM0440 "Period and compare registers min and max values"): - /// | Prescaler | Min duty | Max duty | - /// |-----------|----------|----------| - /// | 1 | 0x0060 | 0xFFDF | - /// | 2 | 0x0030 | 0xFFEF | - /// | 4 | 0x0018 | 0xFFF7 | - /// | 8 | 0x000C | 0xFFFB | - /// | 16 | 0x0006 | 0xFFFD | - /// | 32 | 0x0003 | 0xFFFD | - /// | 64 | 0x0003 | 0xFFFD | - /// | 128 | 0x0003 | 0xFFFD | - /// - /// Also, writing 0 as duty is only valid for CR1 and CR3 during a set of - /// specific conditions(see RM0440 "Null duty cycle exception case"): - /// – the output SET event is generated by the PERIOD event - /// – the output RESET if generated by the compare 1 (respectively compare 3) event - /// – the compare 1 (compare 3) event is active within the timer unit itself, and not used - /// for other timing units - fn set_duty(&mut self, duty: Self::Duty) { - let tim = unsafe { &*$TIMX::ptr() }; - - tim.$cmpXYr.write(|w| unsafe { w.$cmpYx().bits(duty) }); - } - } - - // Enable implementation for ComplementaryImpossible - impl PwmPinEnable for Pwm<$TIMX, $CH, ComplementaryImpossible, POL, NPOL> { - fn ccer_enable(&mut self) { - // TODO: Should this part only be in Pwm::enable? - // Enable output Y on channel X - // This is a set-only register, no risk for data race - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.oenr.write(|w| { w.$tXYoen().set_bit() }); - } - fn ccer_disable(&mut self) { - // TODO: Should this part only be in Pwm::disable - // Disable output Y on channel X - // This is a write only register, no risk for data race - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.odisr.write(|w| { w.$tXYodis().set_bit() }); - } - } - )+ - } -} - -macro_rules! hrtim_out_common { - ($TIMX:ident, $set_event:expr, $register:ident, $action:ident) => {{ - let tim = unsafe { &*$TIMX::ptr() }; - - match $set_event { - EventSource::Cr1 { .. } => tim.$register.modify(|_r, w| w.cmp1().$action()), - EventSource::Cr2 { .. } => tim.$register.modify(|_r, w| w.cmp2().$action()), - EventSource::Cr3 { .. } => tim.$register.modify(|_r, w| w.cmp3().$action()), - EventSource::Cr4 { .. } => tim.$register.modify(|_r, w| w.cmp4().$action()), - EventSource::Period { .. } => tim.$register.modify(|_r, w| w.per().$action()), - - EventSource::MasterCr1 { .. } => tim.$register.modify(|_r, w| w.mstcmp1().$action()), - EventSource::MasterCr2 { .. } => tim.$register.modify(|_r, w| w.mstcmp2().$action()), - EventSource::MasterCr3 { .. } => tim.$register.modify(|_r, w| w.mstcmp3().$action()), - EventSource::MasterCr4 { .. } => tim.$register.modify(|_r, w| w.mstcmp4().$action()), - EventSource::MasterPeriod { .. } => tim.$register.modify(|_r, w| w.mstper().$action()), - - EventSource::NeighborTimer { n } => match n { - NeighborTimerEventSource::TimEvent1 { .. } => { - tim.$register.modify(|_r, w| w.timevnt1().$action()) - } - NeighborTimerEventSource::TimEvent2 { .. } => { - tim.$register.modify(|_r, w| w.timevnt2().$action()) - } - NeighborTimerEventSource::TimEvent3 { .. } => { - tim.$register.modify(|_r, w| w.timevnt3().$action()) - } - NeighborTimerEventSource::TimEvent4 { .. } => { - tim.$register.modify(|_r, w| w.timevnt4().$action()) - } - NeighborTimerEventSource::TimEvent5 { .. } => { - tim.$register.modify(|_r, w| w.timevnt5().$action()) - } - NeighborTimerEventSource::TimEvent6 { .. } => { - tim.$register.modify(|_r, w| w.timevnt6().$action()) - } - NeighborTimerEventSource::TimEvent7 { .. } => { - tim.$register.modify(|_r, w| w.timevnt7().$action()) - } - NeighborTimerEventSource::TimEvent8 { .. } => { - tim.$register.modify(|_r, w| w.timevnt8().$action()) - } - NeighborTimerEventSource::TimEvent9 { .. } => { - tim.$register.modify(|_r, w| w.timevnt9().$action()) - } - }, - } - }}; -} - -macro_rules! hrtim_out { - ($($TIMX:ident: $out_type:ident: $tXYoen:ident, $tXYodis:ident, $tXYods:ident, $setXYr:ident, $rstXYr:ident,)+) => {$( - impl HrOutput for $out_type<$TIMX, PSCL> { - fn enable(&mut self) { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.oenr.write(|w| { w.$tXYoen().set_bit() }); - } - - fn disable(&mut self) { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.odisr.write(|w| { w.$tXYodis().set_bit() }); - } - - fn enable_set_event(&mut self, set_event: impl Into>) { - hrtim_out_common!($TIMX, set_event.into(), $setXYr, set_bit) - } - fn disable_set_event(&mut self, set_event: impl Into>) { - hrtim_out_common!($TIMX, set_event.into(), $setXYr, clear_bit) - } - - fn enable_rst_event(&mut self, reset_event: impl Into>) { - hrtim_out_common!($TIMX, reset_event.into(), $rstXYr, set_bit) - } - fn disable_rst_event(&mut self, reset_event: impl Into>) { - hrtim_out_common!($TIMX, reset_event.into(), $rstXYr, clear_bit) - } - - 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(); - } - - match (oen, ods) { - (true, _) => State::Running, - (false, false) => State::Idle, - (false, true) => State::Fault - } - } - } - )+}; -} - -hrtim_out! { - HRTIM_TIMA: HrOut1: ta1oen, ta1odis, ta1ods, seta1r, rsta1r, - HRTIM_TIMA: HrOut2: ta2oen, ta2odis, ta2ods, seta2r, rsta2r, - - HRTIM_TIMB: HrOut1: tb1oen, tb1odis, tb1ods, setb1r, rstb1r, - HRTIM_TIMB: HrOut2: tb2oen, tb2odis, tb2ods, setb2r, rstb2r, - - HRTIM_TIMC: HrOut1: tc1oen, tc1odis, tc1ods, setc1r, rstc1r, - HRTIM_TIMC: HrOut2: tc2oen, tc2odis, tc2ods, setc2r, rstc2r, - - HRTIM_TIMD: HrOut1: td1oen, td1odis, td1ods, setd1r, rstd1r, - HRTIM_TIMD: HrOut2: td2oen, td2odis, td2ods, setd2r, rstd2r, - - HRTIM_TIME: HrOut1: te1oen, te1odis, te1ods, sete1r, rste1r, - HRTIM_TIME: HrOut2: te2oen, te2odis, te2ods, sete2r, rste2r, - - HRTIM_TIMF: HrOut1: tf1oen, tf1odis, tf1ods, setf1r, rstf1r, - HRTIM_TIMF: HrOut2: tf2oen, tf2odis, tf2ods, setf2r, rstf2r, -} - -macro_rules! hrtim_cr_helper { - ($TIMX:ident: $cr_type:ident: $cmpXYr:ident, $cmpYx:ident) => { - impl HrCompareRegister for $cr_type<$TIMX, PSCL> { - fn get_duty(&self) -> u16 { - let tim = unsafe { &*$TIMX::ptr() }; - - tim.$cmpXYr.read().$cmpYx().bits() - } - fn set_duty(&mut self, duty: u16) { - let tim = unsafe { &*$TIMX::ptr() }; - - tim.$cmpXYr.write(|w| unsafe { w.$cmpYx().bits(duty) }); - } - } - }; -} - -macro_rules! hrtim_cr { - ($($TIMX:ident: [ - $cmpX1r:ident, $cmpX2r:ident, $cmpX3r:ident, $cmpX4r:ident, - $cmp1x:ident, $cmp2x:ident, $cmp3x:ident, $cmp4x:ident - ],)+) => {$( - hrtim_cr_helper!($TIMX: HrCr1: $cmpX1r, $cmp1x); - hrtim_cr_helper!($TIMX: HrCr2: $cmpX2r, $cmp2x); - hrtim_cr_helper!($TIMX: HrCr3: $cmpX3r, $cmp3x); - hrtim_cr_helper!($TIMX: HrCr4: $cmpX4r, $cmp4x); - )+}; -} - -macro_rules! hrtim_timer { - ($($TIMX:ident: $cntXr:ident, $cntx:ident, $perXr:ident, $tXcen:ident, $perx:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident, $icr:ident, $repc:ident, $([$rstXr:ident, $TimerXResetEventSource:ident],)*)+) => {$( - impl HrTimer<$TIMX, PSCL> for HrTim<$TIMX, PSCL> { - fn get_period(&self) -> u16 { - let tim = unsafe { &*$TIMX::ptr() }; - - tim.$perXr.read().$perx().bits() - } - fn set_period(&mut self, period: u16) { - let tim = unsafe { &*$TIMX::ptr() }; - - tim.$perXr.write(|w| unsafe { w.$perx().bits(period as u16) }); - } - - /// Start timer - fn start(&mut self, _hr_control: &mut HrPwmControl) { - // Start timer - - // SAFETY: Since we hold _hr_control there is no risk for a race condition - let master = unsafe { &*HRTIM_MASTER::ptr() }; - master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); - } - - /// Stop timer - fn stop(&mut self, _hr_control: &mut HrPwmControl) { - // Stop counter - // SAFETY: Since we hold _hr_control there is no risk for a race condition - let master = unsafe { &*HRTIM_MASTER::ptr() }; - master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); - } - - /// Stop timer and reset counter - fn stop_and_reset(&mut self, _hr_control: &mut HrPwmControl) { - self.stop(_hr_control); - - // Reset counter - let tim = unsafe { &*$TIMX::ptr() }; - unsafe { tim.$cntXr.write(|w| w.$cntx().bits(0)); } - } - } - - impl HrTim<$TIMX, PSCL> { - $( - /// 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 - pub fn enable_reset_event(&mut self, set_event: $TimerXResetEventSource) { - let tim = unsafe { &*$TIMX::ptr() }; - - unsafe { tim.$rstXr.modify(|r, w| w.bits(r.bits() | set_event as u32)); } - } - - /// Stop listening to the specified event - pub fn disable_reset_event(&mut self, set_event: $TimerXResetEventSource) { - let tim = unsafe { &*$TIMX::ptr() }; - - unsafe { tim.$rstXr.modify(|r, w| w.bits(r.bits() & !(set_event as u32))); } - })* - - pub fn set_repetition_counter(&mut self, repetition_counter: u8) { - let tim = unsafe { &*$TIMX::ptr() }; - - unsafe { tim.$rep.write(|w| w.$repx().bits(repetition_counter)); } - } - - pub fn enable_repetition_interrupt(&mut self, enable: bool) { - let tim = unsafe { &*$TIMX::ptr() }; - - tim.$dier.modify(|_r, w| w.$repie().bit(enable)); - } - - pub fn clear_repetition_interrupt(&mut self) { - let tim = unsafe { &*$TIMX::ptr() }; - - tim.$icr.write(|w| w.$repc().set_bit()); - } - } - )+}; -} - -hrtim_timer! { - HRTIM_MASTER: mcntr, mcnt, mper, mcen, mper, mrep, mrep, mdier, mrepie, micr, mrepc, - - HRTIM_TIMA: cntar, cntx, perar, tacen, perx, repar, repx, timadier, repie, timaicr, repc, [rstar, TimerAResetEventSource], - HRTIM_TIMB: cntr, cntx, perbr, tbcen, perx, repbr, repx, timbdier, repie, timbicr, repc, [rstbr, TimerBResetEventSource], - HRTIM_TIMC: cntcr, cntx, percr, tccen, perx, repcr, repx, timcdier, repie, timcicr, repc, [rstcr, TimerCResetEventSource], - HRTIM_TIMD: cntdr, cntx, perdr, tdcen, perx, repdr, repx, timddier, repie, timdicr, repc, [rstdr, TimerDResetEventSource], - HRTIM_TIME: cnter, cntx, perer, tecen, perx, reper, repx, timedier, repie, timeicr, repc, [rster, TimerEResetEventSource], - HRTIM_TIMF: cntfr, cntx, perfr, tfcen, perx, repfr, repx, timfdier, repie, timficr, repc, [rstfr, TimerFResetEventSource], -} - -hrtim_cr! { - HRTIM_MASTER: [mcmp1r, mcmp2r, mcmp3r, mcmp4r, mcmp1, mcmp2, mcmp3, mcmp4], - - HRTIM_TIMA: [cmp1ar, cmp2ar, cmp3ar, cmp4ar, cmp1x, cmp2x, cmp3x, cmp4x], - HRTIM_TIMB: [cmp1br, cmp2br, cmp3br, cmp4br, cmp1x, cmp2x, cmp3x, cmp4x], - HRTIM_TIMC: [cmp1cr, cmp2cr, cmp3cr, cmp4cr, cmp1x, cmp2x, cmp3x, cmp4x], - HRTIM_TIMD: [cmp1dr, cmp2dr, cmp3dr, cmp4dr, cmp1x, cmp2x, cmp3x, cmp4x], - HRTIM_TIME: [cmp1er, cmp2er, cmp3er, cmp4er, cmp1x, cmp2x, cmp3x, cmp4x], - HRTIM_TIMF: [cmp1fr, cmp2fr, cmp3fr, cmp4fr, cmp1x, cmp2x, cmp3x, cmp4x], -} - -hrtim_hal! { - HRTIM_TIMA: (timacr, timacr2, perar, tacen, repar, repx, timadier, repie, fltar, outar, dtar), - HRTIM_TIMB: (timbcr, timbcr2, perbr, tbcen, repbr, repx, timbdier, repie, fltbr, outbr, dtbr), - HRTIM_TIMC: (timccr, timccr2, percr, tccen, repcr, repx, timcdier, repie, fltcr, outcr, dtcr), - HRTIM_TIMD: (timdcr, timdcr2, perdr, tdcen, repdr, repx, timddier, repie, fltdr, outdr, dtdr), - HRTIM_TIME: (timecr, timecr2, perer, tecen, reper, repx, timedier, repie, flter, outer, dter), - HRTIM_TIMF: (timfcr, timfcr2, perfr, tfcen, repfr, repx, timfdier, repie, fltfr, outfr, dtfr), -} - -hrtim_hal_master! { - HRTIM_MASTER: (mcr, ck_psc, mper, mper, mrep, mcen, mdier, mrepie), -} - -hrtim_pin_hal! { - HRTIM_TIMA: (CH1, perar, cmp1ar, cmp1x, cmp1, ta1oen, ta1odis), - HRTIM_TIMA: (CH2, perar, cmp3ar, cmp3x, cmp3, ta2oen, ta2odis), - - HRTIM_TIMB: (CH1, perbr, cmp1br, cmp1x, cmp1, tb1oen, tb1odis), - HRTIM_TIMB: (CH2, perbr, cmp3br, cmp3x, cmp3, tb2oen, tb2odis), - - HRTIM_TIMC: (CH1, percr, cmp1cr, cmp1x, cmp1, tc1oen, tc1odis), - HRTIM_TIMC: (CH2, percr, cmp3cr, cmp3x, cmp3, tc2oen, tc2odis), - - HRTIM_TIMD: (CH1, perdr, cmp1dr, cmp1x, cmp1, td1oen, td1odis), - HRTIM_TIMD: (CH2, perdr, cmp3dr, cmp3x, cmp3, td2oen, td2odis), - - HRTIM_TIME: (CH1, perer, cmp1er, cmp1x, cmp1, te1oen, te1odis), - HRTIM_TIME: (CH2, perer, cmp3er, cmp3x, cmp3, te2oen, te2odis), - - HRTIM_TIMF: (CH1, perfr, cmp1fr, cmp1x, cmp1, tf1oen, tf1odis), - HRTIM_TIMF: (CH2, perfr, cmp3fr, cmp3x, cmp3, tf2oen, tf2odis), -} - -pub unsafe trait HrtimPrescaler: Default { - const BITS: u8; - const VALUE: u8; - - /// Minimum allowed value for compare registers used with the timer with this prescaler - /// - /// NOTE: That for CR1 and CR3, 0 is also allowed - const MIN_CR: u16; - - /// Maximum allowed value for compare registers used with the timer with this prescaler - const MAX_CR: u16; -} - -macro_rules! impl_pscl { - ($($t:ident => $b:literal, $v:literal, $min:literal, $max:literal)+) => {$( - #[derive(Copy, Clone, Default)] - pub struct $t; - unsafe impl HrtimPrescaler for $t { - const BITS: u8 = $b; - const VALUE: u8 = $v; - const MIN_CR: u16 = $min; - const MAX_CR: u16 = $max; - } - )+}; -} - -impl_pscl! { - Pscl1 => 0b000, 1, 0x0060, 0xFFDF - Pscl2 => 0b001, 2, 0x0030, 0xFFEF - Pscl4 => 0b010, 4, 0x0018, 0xFFF7 - Pscl8 => 0b011, 8, 0x000C, 0xFFFB - Pscl16 => 0b100, 16, 0x0006, 0xFFFD - Pscl32 => 0b101, 32, 0x0003, 0xFFFD - Pscl64 => 0b110, 64, 0x0003, 0xFFFD - Pscl128 => 0b111, 128, 0x0003, 0xFFFD -} - -/// HrTim timer -struct TimerHrTim(PhantomData); - -impl super::TimerType for TimerHrTim { - // Period calculator for 16-bit hrtimers - // - // NOTE: This function will panic if the calculated period can not fit into 16 bits - fn calculate_frequency(base_freq: HertzU64, freq: Hertz, alignment: Alignment) -> (u32, u16) { - let ideal_period = super::Timer32Bit::calculate_frequency(base_freq, freq, alignment).0 + 1; - - let prescale = u32::from(PSC::VALUE); - - // Round to the nearest period - let period = (ideal_period + (prescale >> 1)) / prescale - 1; - - // It IS possible to fail this assert - assert!(period <= 0xFFFF); - - (period, PSC::BITS.into()) - } -} - -pub trait HrtimChannel {} - -impl HrtimChannel for CH1 {} -impl HrtimChannel for CH2 {} \ No newline at end of file diff --git a/src/pwm/hrtim/external_event.rs b/src/pwm/hrtim/external_event.rs deleted file mode 100644 index f9da1e1a..00000000 --- a/src/pwm/hrtim/external_event.rs +++ /dev/null @@ -1,138 +0,0 @@ -use crate::comparator::{Comparator, self, COMP1}; - -pub trait ExternalEventExt { - fn external_event(&self) -> ExternalEventBuilder; -} - -macro_rules! impl_eev_ext_comp { - ($comp:ident: $N:literal) => { - impl ExternalEventExt<$N, 0b10> for Comparator<$comp, E> { - fn external_event(&self) -> ExternalEventBuilder<$N, 0b10> { - ExternalEventBuilder { - edge_or_polarity_bits: 0, // Polarity sensitive - polarity_bit: false, // Active high - filter_bits: 0, // No filter - fast_bit: false, // Not fast - } - } - } - }; -} - -impl_eev_ext_comp!(COMP1: 4); - -struct ExternalEventBuilder { - edge_or_polarity_bits: u8, - polarity_bit: bool, - filter_bits: u8, - fast_bit: bool, -} - -enum EdgeOrPolarity { - Edge(Edge), - Polarity(Polarity), -} - -enum Edge { - Rising = 0b01, - Falling = 0b10, - Both = 0b11, -} - -enum Polarity { - ActiveHigh, - ActiveLow, -} - -pub enum EevSamplingFilter { - /// No filtering, fault acts asynchronously - /// - /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) - None = 0b0000, - - /// Sample directly at rate f_hrtim, with a count of 2 - /// - /// Note that this bypasses: any f_eevs (FaultSamplingClkDiv) - HrtimN2 = 0b0001, - - /// Sample directly at rate f_hrtim, with a count of 4 - /// - /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) - HrtimN4 = 0b0010, - - /// Sample directly at rate f_hrtim, with a count of 8 - /// - /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) - HrtimN8 = 0b0011, - - /// Sample at rate f_eevs / 2, with a count of 6 - EevsDiv2N6 = 0b0100, - - /// Sample at rate f_eevs / 2, with a count of 8 - EevsDiv2N8 = 0b0101, - - /// Sample at rate f_eevs / 4, with a count of 6 - EevsDiv4N6 = 0b0110, - - /// Sample at rate f_eevs / 4, with a count of 8 - EevsDiv4N8 = 0b0111, - - /// Sample at rate f_eevs / 8, with a count of 6 - EevsDiv8N6 = 0b1000, - - /// Sample at rate f_eevs / 8, with a count of 8 - EevsDiv8N8 = 0b1001, - - /// Sample at rate f_eevs / 16, with a count of 5 - EevsDiv16N5 = 0b1010, - - /// Sample at rate f_eevs / 16, with a count of 6 - EevsDiv16N6 = 0b1011, - - /// Sample at rate f_eevs / 16, with a count of 8 - EevsDiv16N8 = 0b1100, - - /// Sample at rate f_eevs / 32, with a count of 5 - EevsDiv32N5 = 0b1101, - - /// Sample at rate f_eevs / 32, with a count of 6 - EevsDiv32N6 = 0b1110, - - /// Sample at rate f_eevs / 32, with a count of 8 - EevsDiv32N8 = 0b1111, -} - -impl ExternalEventBuilder { - fn edge_or_polarity(mut self, edge_or_polarity: EdgeOrPolarity) -> Self { - (self.edge_or_polarity_bits, self.polarity_bit) = match edge_or_polarity { - EdgeOrPolarity::Polarity(Polarity::ActiveHigh) => (0b00, false), - EdgeOrPolarity::Polarity(Polarity::ActiveLow) => (0b00, true), - EdgeOrPolarity::Edge(Edge::Rising) => (0b01, false), - EdgeOrPolarity::Edge(Edge::Falling) => (0b10, false), - EdgeOrPolarity::Edge(Edge::Both) => (0b11, false), - }; - - self - } -} - -impl ExternalEventBuilder - where ExternalEventBuilder: ExternalEventBuilder1To5 -{ - fn fast(mut self) -> Self { - self.fast_bit = true; - self - } -} - -impl ExternalEventBuilder - where ExternalEventBuilder: ExternalEventBuilder6To10 -{ - fn filter(mut self, filter: EevSamplingFilter) -> Self { - self.filter_bits = filter as _; - self - } -} - -trait ExternalEventBuilder1To5 {} -trait ExternalEventBuilder6To10 {} \ No newline at end of file From d50746090efe764ce0405e51aa6150cad88589f5 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sun, 5 Nov 2023 21:35:48 +0100 Subject: [PATCH 38/88] EEV --- examples/hrtim_eev.rs | 111 +++++++++ src/hrtim/external_event.rs | 400 +++++++++++++++----------------- src/hrtim/external_event_old.rs | 285 +++++++++++++++++++++++ 3 files changed, 579 insertions(+), 217 deletions(-) create mode 100644 examples/hrtim_eev.rs create mode 100644 src/hrtim/external_event_old.rs diff --git a/examples/hrtim_eev.rs b/examples/hrtim_eev.rs new file mode 100644 index 00000000..fdfca80e --- /dev/null +++ b/examples/hrtim_eev.rs @@ -0,0 +1,111 @@ +//This example puts the timer in PWM mode using the specified pin with a frequency of 100Hz and a duty cycle of 50%. +#![no_main] +#![no_std] + +use cortex_m_rt::entry; +use fugit::ExtU32; +use hal::gpio::gpioa::PA8; +use hal::gpio::Alternate; +use hal::gpio::AF13; +use hal::prelude::*; +use hal::pwm::hrtim::EventSource; +use hal::pwm::hrtim::FaultAction; +use hal::pwm::hrtim::HrCompareRegister; +use hal::pwm::hrtim::HrPwmAdvExt; +use hal::pwm::hrtim::HrTimer; +use hal::pwm::hrtim::Pscl4; +use hal::pwm::hrtim::{HrControltExt, HrOutput}; +use hal::pwm::FaultMonitor; +use hal::rcc; +use hal::stm32; +use stm32g4xx_hal as hal; +//mod utils; + +use defmt_rtt as _; // global logger +use panic_probe as _; + +#[entry] +fn main() -> ! { + let dp = stm32::Peripherals::take().expect("cannot take peripherals"); + let cp = stm32::CorePeripherals::take().expect("cannot take core"); + // Set system frequency to 16MHz * 75/4/2 = 150MHz + // This would lead to HrTim running at 150MHz * 32 = 4.8GHz... + let mut rcc = dp.RCC.freeze(rcc::Config::pll().pll_cfg(rcc::PllConfig { + mux: rcc::PLLSrc::HSI, + n: rcc::PllNMul::MUL_75, + m: rcc::PllMDiv::DIV_4, + r: Some(rcc::PllRDiv::DIV_2), + ..Default::default() + })); + + let mut delay = cp.SYST.delay(&rcc.clocks); + + let gpioa = dp.GPIOA.split(&mut rcc); + let gpiob = dp.GPIOB.split(&mut rcc); + let (mut fault_control, flt_inputs, eev_inputs) = + dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); + + let eev_input3 = eev_inputs + .eev_input3 + .bind_pin(gpiob.pb7.into_pull_down_input()) + .polarity(hal::pwm::Polarity::ActiveHigh) + .finalize(&mut fault_control); + + // ...with a prescaler of 4 this gives us a HrTimer with a tick rate of 1.2GHz + // With max the max period set, this would be 1.2GHz/2^16 ~= 18kHz... + let prescaler = Pscl4; + + let pin_a: PA8> = gpioa.pa8.into_alternate(); + + // . . . * + // . 33% . . * . . + // .-----. .-----. .--. . . + //out1 | | | | | | . . + // | | | | | | . . + // ------ ----------- ----------- ----------------------------------- + // . . . * . . + // . . . * . . + // . . . *-------- . . + //fault . . . | | . . + // . . . | | . . + // ----------------------------------------- -------------------------- + // . . . * . . + // . . . * . . + let (timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp + .HRTIM_TIMA + .pwm_advanced(pin_a, &mut rcc) + .prescaler(prescaler) + .period(0xFFFF) + //.with_fault_source(fault_source1) + //.with_fault_source(fault_source2) + .with_fault_source(fault_source3) // Set fault source + //.with_fault_source(fault_source4) + //.with_fault_source(fault_source5) + //.with_fault_source(fault_source6) + .fault_action1(FaultAction::ForceInactive) + .fault_action2(FaultAction::ForceInactive) + // alternated every period with one being + // inactive and the other getting to output its wave form + // as normal + .finalize(&mut fault_control); + + out1.enable_rst_event(EventSource::Cr1); // Set low on compare match with cr1 + out1.enable_set_event(EventSource::Period); // Set high at new period + cr1.set_duty(timer.get_period() / 3); + //unsafe {((HRTIM_COMMON::ptr() as *mut u8).offset(0x14) as *mut u32).write_volatile(1); } + out1.enable(); + + defmt::info!("Started"); + + loop { + for _ in 0..5 { + delay.delay(500_u32.millis()); + defmt::info!("State: {}", out1.get_state()); + } + if fault_control.fault_3.is_fault_active() { + fault_control.fault_3.clear_fault(); // Clear fault every 5s + out1.enable(); + defmt::info!("failt cleared, and output reenabled"); + } + } +} diff --git a/src/hrtim/external_event.rs b/src/hrtim/external_event.rs index 8d2df921..9ae63cb4 100644 --- a/src/hrtim/external_event.rs +++ b/src/hrtim/external_event.rs @@ -1,76 +1,31 @@ use core::marker::PhantomData; -use stm32g4::stm32g474::HRTIM_COMMON; - -use crate::comparator::{self, Comparator, COMP1, COMP2, COMP4, COMP6, COMP3, COMP5, COMP7}; - -use super::{control::HrTimCalibrated, event::EventSource}; - -#[derive(Copy, Clone, PartialEq)] -pub enum ExternalEventSource { - Eevnt1 { _x: PhantomData<()> }, - Eevnt2 { _x: PhantomData<()> }, - Eevnt3 { _x: PhantomData<()> }, - Eevnt4 { _x: PhantomData<()> }, - Eevnt5 { _x: PhantomData<()> }, - Eevnt6 { _x: PhantomData<()> }, - Eevnt7 { _x: PhantomData<()> }, - Eevnt8 { _x: PhantomData<()> }, - Eevnt9 { _x: PhantomData<()> }, - Eevnt10 { _x: PhantomData<()> }, +use crate::comparator::{COMP1, COMP2, COMP3, COMP4, COMP5, COMP6}; +use crate::gpio::gpioa::{PA12, PA15}; +use crate::gpio::gpiob::{PB0, PB10, PB11}; +use crate::gpio::gpioc::{PC10, PC7}; +use crate::gpio::{self, AF13, AF3}; +use crate::hrtim::control::HrPwmControl; +use crate::pwm::FaultMonitor; +use crate::stm32::HRTIM_COMMON; + + +pub unsafe trait FaultSource: Copy { + const ENABLE_BITS: u8; } -impl From for EventSource { - fn from(val: ExternalEventSource) -> Self { - EventSource::ExternalEvent(val) - } -} +pub struct SourceBuilder { + _input: I, + src_bits: u8, -pub trait ExternalEventExt { - fn external_event(&self) -> ExternalEventBuilder; -} + /// FLTxP + is_active_high: bool, -macro_rules! impl_eev_ext_comp { - ($N:literal: $comp:ident) => { - impl ExternalEventExt<$N, 0b10> for Comparator<$comp, E> { - fn external_event(&self) -> ExternalEventBuilder<$N, 0b10> { - ExternalEventBuilder { - edge_or_polarity_bits: 0, // Polarity sensitive - polarity_bit: false, // Active high - filter_bits: 0, // No filter - fast_bit: false, // Not fast - } - } - } - }; + /// FLTxF[3:0] + filter_bits: u8, } -impl_eev_ext_comp!(1: COMP2); -impl_eev_ext_comp!(2: COMP4); -impl_eev_ext_comp!(3: COMP6); -impl_eev_ext_comp!(4: COMP1); -impl_eev_ext_comp!(5: COMP3); -impl_eev_ext_comp!(6: COMP2); -impl_eev_ext_comp!(7: COMP4); -impl_eev_ext_comp!(8: COMP6); -impl_eev_ext_comp!(9: COMP5); -impl_eev_ext_comp!(10: COMP7); - -impl_eev_ext_pin!(1: PC12); -impl_eev_ext_pin!(2: PC11); -impl_eev_ext_pin!(3: PB7); -impl_eev_ext_pin!(4: PB6); -impl_eev_ext_pin!(5: PB9); -impl_eev_ext_pin!(6: PB5); -impl_eev_ext_pin!(7: PB4); -impl_eev_ext_pin!(8: PB8); -impl_eev_ext_pin!(9: PB3); -impl_eev_ext_pin!(10: PC5); -impl_eev_ext_pin!(10: PC6); - - - -pub struct ExternalEventBuilder { +pub struct SourceBuilder { /// EExSNS edge_or_polarity_bits: u8, @@ -84,200 +39,211 @@ pub struct ExternalEventBuilder { fast_bit: bool, } -pub enum EdgeOrPolarity { - Edge(Edge), - Polarity(Polarity), +impl SourceBuilder { + unsafe fn new(input: I, src_bits: u8) -> Self { + SourceBuilder { + _input: input, + src_bits, + is_active_high: false, + filter_bits: 0b0000, + } + } } -pub enum Edge { - Rising = 0b01, - Falling = 0b10, - Both = 0b11, +macro_rules! impl_faults { + ($( + $input:ident => $source:ident: + PINS=[($pin:ident, $af:ident), $(($pin_b:ident, $af_b:ident),)*], + COMP=$compX:ident, $enable_bits:literal, + $fltinrZ:ident, $fltWsrc_0:ident, $fltWsrc_1:ident, $fltWp:ident, $fltWf:ident, $fltWe:ident, $fltWlck:ident, + )+) => {$( + + // This should NOT be Copy/Clone + pub struct $input { + pub(crate) _x: PhantomData<()> + } + + #[derive(Copy, Clone)] + pub struct $source { + _x: PhantomData<()> + } + + impl $input { + pub fn bind_pin(self, pin: $pin>) -> SourceBuilder<$input> { + pin.into_alternate::<$af>(); + unsafe { SourceBuilder::new(self, 0b00) } + } + + $( + pub fn bind_pin_b(self, pin: $pin_b>) -> SourceBuilder<$input> { + pin.into_alternate::<$af_b>(); + unsafe { SourceBuilder::new(self, 0b00) } + } + )* + + pub fn bind_comp(self, _comp: &crate::comparator::Comparator<$compX, crate::comparator::Enabled>) -> SourceBuilder<$input> { + unsafe { SourceBuilder::new(self, 0b01) } + } + + /*pub fn bind_external(?) { + SourceBuilder::new(self, 0b10); + }*/ + } + + impl SourceBuilder<$input> { + pub fn finalize(self, _control: &mut HrPwmControl) -> $source { + let SourceBuilder{ _input, src_bits, is_active_high, filter_bits } = self; + + // Setup fault source + unsafe { + let common = &*HRTIM_COMMON::ptr(); + + common.fltinr2.modify(|_r, w| w.$fltWsrc_1().bit(src_bits & 0b10 != 0)); + common.$fltinrZ.modify(|_r, w| w + .$fltWsrc_0().bit(src_bits & 0b01 != 0) + .$fltWp().bit(is_active_high) + .$fltWf().bits(filter_bits) + .$fltWe().set_bit() // Enable + ); + + // ... and lock configuration + common.$fltinrZ.modify(|_r, w| w.$fltWlck().set_bit()); + } + + $source { + _x: PhantomData + } + } + + pub fn polarity(mut self, polarity: super::Polarity) -> Self { + self.is_active_high = polarity == super::Polarity::ActiveHigh; + self + } + + // TODO: add more settings + /* pub fn blanking(?) -> Self */ + + pub fn filter(mut self, filter: FaultSamplingFilter) -> Self { + self.filter_bits = filter as u8; + self + } + } + + unsafe impl FaultSource for $source { + const ENABLE_BITS: u8 = $enable_bits; + } + )+} } -pub enum Polarity { - ActiveHigh, - ActiveLow, +// TODO: Lookup to ensure the alternate function are the same for other devices than stm32g474 +#[cfg(feature = "stm32g474")] +impl_faults!( + FaultInput1 => FaultSource1: PINS=[(PA12, AF13),], COMP=COMP2, 0b000001, fltinr1, flt1src, flt1src_1, flt1p, flt1f, flt1e, flt1lck, + FaultInput2 => FaultSource2: PINS=[(PA15, AF13),], COMP=COMP4, 0b000010, fltinr1, flt2src, flt2src_1, flt2p, flt2f, flt2e, flt2lck, + FaultInput3 => FaultSource3: PINS=[(PB10, AF13),], COMP=COMP6, 0b000100, fltinr1, flt3src, flt3src_1, flt3p, flt3f, flt3e, flt3lck, + FaultInput4 => FaultSource4: PINS=[(PB11, AF13),], COMP=COMP1, 0b001000, fltinr1, flt4src, flt4src_1, flt4p, flt4f, flt4e, flt4lck, + FaultInput5 => FaultSource5: PINS=[(PB0, AF13), (PC7, AF3),], COMP=COMP3, 0b010000, fltinr2, flt5src, flt5src_1, flt5p, flt5f, flt5e, flt5lck, + FaultInput6 => FaultSource6: PINS=[(PC10, AF13),], COMP=COMP5, 0b100000, fltinr2, flt6src_0, flt6src_1, flt6p, flt6f, flt6e, flt6lck, +); + +pub struct FaultInputs { + pub fault_input1: FaultInput1, + pub fault_input2: FaultInput2, + pub fault_input3: FaultInput3, + pub fault_input4: FaultInput4, + pub fault_input5: FaultInput5, + pub fault_input6: FaultInput6, } -pub enum EevSamplingFilter { +pub enum FaultSamplingFilter { /// No filtering, fault acts asynchronously /// - /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) + /// Note that this bypasses any f_flts (SamplingClkDiv) None = 0b0000, /// Sample directly at rate f_hrtim, with a count of 2 /// - /// Note that this bypasses: any f_eevs (FaultSamplingClkDiv) + /// Note that this bypasses: any f_flts (SamplingClkDiv) HrtimN2 = 0b0001, /// Sample directly at rate f_hrtim, with a count of 4 /// - /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) + /// Note that this bypasses any f_flts (SamplingClkDiv) HrtimN4 = 0b0010, /// Sample directly at rate f_hrtim, with a count of 8 /// - /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) + /// Note that this bypasses any f_flts (SamplingClkDiv) HrtimN8 = 0b0011, - /// Sample at rate f_eevs / 2, with a count of 6 - EevsDiv2N6 = 0b0100, - - /// Sample at rate f_eevs / 2, with a count of 8 - EevsDiv2N8 = 0b0101, - - /// Sample at rate f_eevs / 4, with a count of 6 - EevsDiv4N6 = 0b0110, - - /// Sample at rate f_eevs / 4, with a count of 8 - EevsDiv4N8 = 0b0111, - - /// Sample at rate f_eevs / 8, with a count of 6 - EevsDiv8N6 = 0b1000, + /// Sample at rate f_flts / 2, with a count of 6 + FltsDiv2N6 = 0b0100, - /// Sample at rate f_eevs / 8, with a count of 8 - EevsDiv8N8 = 0b1001, + /// Sample at rate f_flts / 2, with a count of 8 + FltsDiv2N8 = 0b0101, - /// Sample at rate f_eevs / 16, with a count of 5 - EevsDiv16N5 = 0b1010, + /// Sample at rate f_flts / 4, with a count of 6 + FltsDiv4N6 = 0b0110, - /// Sample at rate f_eevs / 16, with a count of 6 - EevsDiv16N6 = 0b1011, + /// Sample at rate f_flts / 4, with a count of 8 + FltsDiv4N8 = 0b0111, - /// Sample at rate f_eevs / 16, with a count of 8 - EevsDiv16N8 = 0b1100, + /// Sample at rate f_flts / 8, with a count of 6 + FltsDiv8N6 = 0b1000, - /// Sample at rate f_eevs / 32, with a count of 5 - EevsDiv32N5 = 0b1101, + /// Sample at rate f_flts / 8, with a count of 8 + FltsDiv8N8 = 0b1001, - /// Sample at rate f_eevs / 32, with a count of 6 - EevsDiv32N6 = 0b1110, + /// Sample at rate f_flts / 16, with a count of 5 + FltsDiv16N5 = 0b1010, - /// Sample at rate f_eevs / 32, with a count of 8 - EevsDiv32N8 = 0b1111, -} - -pub trait ExternalEventBuilder1To5 {} -pub trait ExternalEventBuilder6To10 {} + /// Sample at rate f_flts / 16, with a count of 6 + FltsDiv16N6 = 0b1011, -impl ExternalEventBuilder { - pub fn edge_or_polarity(mut self, edge_or_polarity: EdgeOrPolarity) -> Self { - (self.edge_or_polarity_bits, self.polarity_bit) = match edge_or_polarity { - EdgeOrPolarity::Polarity(Polarity::ActiveHigh) => (0b00, false), - EdgeOrPolarity::Polarity(Polarity::ActiveLow) => (0b00, true), - EdgeOrPolarity::Edge(Edge::Rising) => (0b01, false), - EdgeOrPolarity::Edge(Edge::Falling) => (0b10, false), - EdgeOrPolarity::Edge(Edge::Both) => (0b11, false), - }; + /// Sample at rate f_flts / 16, with a count of 8 + FltsDiv16N8 = 0b1100, - self - } -} + /// Sample at rate f_flts / 32, with a count of 5 + FltsDiv32N5 = 0b1101, -impl ExternalEventBuilder -where - ExternalEventBuilder: ExternalEventBuilder1To5, -{ - pub fn fast(mut self) -> Self { - self.fast_bit = true; - self - } -} + /// Sample at rate f_flts / 32, with a count of 6 + FltsDiv32N6 = 0b1110, -impl ExternalEventBuilder -where - ExternalEventBuilder: ExternalEventBuilder6To10, -{ - pub fn filter(mut self, filter: EevSamplingFilter) -> Self { - self.filter_bits = filter as _; - self - } + /// Sample at rate f_flts / 32, with a count of 8 + FltsDiv32N8 = 0b1111, } -pub trait ExternalEventToEventSource { - fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource; -} - -macro_rules! impl_eev1_5_to_es { - ($eev:ident, $N:literal, $eeXsrc:ident, $eeXpol:ident, $eeXsns:ident, $eeXfast:ident) => { - impl ExternalEventBuilder1To5 for ExternalEventBuilder<$N, SRC> {} - - impl ExternalEventToEventSource for ExternalEventBuilder<$N, SRC> { - fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource { - let ExternalEventBuilder { - edge_or_polarity_bits, - polarity_bit, - filter_bits: _, - fast_bit, - } = self; +macro_rules! impl_flt_monitor { + ($($t:ident: ($fltx:ident, $fltxc:ident),)+) => {$( + pub struct $t { + pub(crate) _x: PhantomData<()> + } + impl FaultMonitor for $t { + fn is_fault_active(&self) -> bool { let common = unsafe { &*HRTIM_COMMON::ptr() }; - - // SAFETY: Thanks to, `HrTimCalibrated`, we know we have exclusive access to the register, - // we also know no timers are started. - unsafe { - common.eecr1.modify(|_r, w| { - w.$eeXsrc() - .bits(SRC) - .$eeXpol() - .bit(polarity_bit) - .$eeXsns() - .bits(edge_or_polarity_bits) - .$eeXfast() - .bit(fast_bit) - }); - } - - ExternalEventSource::$eev { _x: PhantomData } + common.isr.read().$fltx().bit() } - } - }; -} - -macro_rules! impl_eev6_10_to_es { - ($eev:ident, $N:literal, $eeXsrc:ident, $eeXpol:ident, $eeXsns:ident, $eeXf:ident) => { - impl ExternalEventBuilder6To10 for ExternalEventBuilder<$N, SRC> {} - - impl ExternalEventToEventSource for ExternalEventBuilder<$N, SRC> { - fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource { - let ExternalEventBuilder { - edge_or_polarity_bits, - polarity_bit, - filter_bits, - fast_bit: _, - } = self; + fn clear_fault(&mut self) { let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.icr.write(|w| w.$fltxc().set_bit()); + } - // SAFETY: Thanks to, `HrTimCalibrated`, we know we have exclusive access to the register, - // we also know no timers are started. - unsafe { - common.eecr2.modify(|_r, w| { - w.$eeXsrc() - .bits(SRC) - .$eeXpol() - .bit(polarity_bit) - .$eeXsns() - .bits(edge_or_polarity_bits) - }); - common.eecr3.modify(|_r, w| w.$eeXf().bits(filter_bits)); - } - - ExternalEventSource::$eev { _x: PhantomData } + // TODO: Should we have our own trait since it does not seem possible to implement this + fn set_fault(&mut self) { + todo!() } } - }; + )+}; } -impl_eev1_5_to_es!(Eevnt1, 1, ee1src, ee1pol, ee1sns, ee1fast); -impl_eev1_5_to_es!(Eevnt2, 2, ee2src, ee2pol, ee2sns, ee2fast); -impl_eev1_5_to_es!(Eevnt3, 3, ee3src, ee3pol, ee3sns, ee3fast); -impl_eev1_5_to_es!(Eevnt4, 4, ee4src, ee4pol, ee4sns, ee4fast); -impl_eev1_5_to_es!(Eevnt5, 5, ee5src, ee5pol, ee5sns, ee5fast); - -impl_eev6_10_to_es!(Eevnt6, 6, ee6src, ee6pol, ee6sns, ee6f); -impl_eev6_10_to_es!(Eevnt7, 7, ee7src, ee7pol, ee7sns, ee7f); -impl_eev6_10_to_es!(Eevnt8, 8, ee8src, ee8pol, ee8sns, ee8f); -impl_eev6_10_to_es!(Eevnt9, 9, ee9src, ee9pol, ee9sns, ee9f); -impl_eev6_10_to_es!(Eevnt10, 10, ee10src, ee10pol, ee10sns, ee10f); +impl_flt_monitor!( + FltMonitorSys: (sysflt, sysfltc), + FltMonitor1: (flt1, flt1c), + FltMonitor2: (flt2, flt2c), + FltMonitor3: (flt3, flt3c), + FltMonitor4: (flt4, flt4c), + FltMonitor5: (flt5, flt5c), + FltMonitor6: (flt6, flt6c), +); diff --git a/src/hrtim/external_event_old.rs b/src/hrtim/external_event_old.rs new file mode 100644 index 00000000..8454a1c9 --- /dev/null +++ b/src/hrtim/external_event_old.rs @@ -0,0 +1,285 @@ +use core::marker::PhantomData; + +use crate::comparator::{self, Comparator, COMP1, COMP2, COMP3, COMP4, COMP5, COMP6, COMP7}; +use crate::gpio::{self, AF3, AF13}; +use crate::gpio::gpiob::{PB4, PB5, PB6, PB7, PB9, PB8, PB3}; +use crate::gpio::gpioc::{PC11, PC12, PC5, PC6}; +use crate::stm32::HRTIM_COMMON; + +use super::{control::HrTimCalibrated, event::EventSource}; + +#[derive(Copy, Clone, PartialEq)] +pub enum ExternalEventSource { + Eevnt1 { _x: PhantomData<()> }, + Eevnt2 { _x: PhantomData<()> }, + Eevnt3 { _x: PhantomData<()> }, + Eevnt4 { _x: PhantomData<()> }, + Eevnt5 { _x: PhantomData<()> }, + Eevnt6 { _x: PhantomData<()> }, + Eevnt7 { _x: PhantomData<()> }, + Eevnt8 { _x: PhantomData<()> }, + Eevnt9 { _x: PhantomData<()> }, + Eevnt10 { _x: PhantomData<()> }, +} + +impl From for EventSource { + fn from(val: ExternalEventSource) -> Self { + EventSource::ExternalEvent(val) + } +} + +pub trait ExternalEventExt { + fn external_event(self) -> SourceBuilder; +} + +macro_rules! impl_eev { + ($N:literal: $comp:ident, PINS=[$(($pin:ident, $af:ident)),+]) => { + impl ExternalEventExt<$N, 0b01> for &Comparator<$comp, E> { + fn external_event(self) -> ExternalEventBuilder<$N, 0b01> { + ExternalEventBuilder { + edge_or_polarity_bits: 0, // Polarity sensitive + polarity_bit: false, // Active high + filter_bits: 0, // No filter + fast_bit: false, // Not fast + } + } + } + + $( + impl ExternalEventExt<$N, 0b00> for $pin> { + fn external_event(self) -> ExternalEventBuilder<$N, 0b00> { + self.into_alternate::<$af>(); + ExternalEventBuilder { + edge_or_polarity_bits: 0, // Polarity sensitive + polarity_bit: false, // Active high + filter_bits: 0, // No filter + fast_bit: false, // Not fast + } + } + } + )* + }; +} + +impl_eev!(1: COMP2, PINS=[(PC12, AF3)]); +impl_eev!(2: COMP4, PINS=[(PC11, AF3)]); +impl_eev!(3: COMP6, PINS=[(PB7, AF13)]); +impl_eev!(4: COMP1, PINS=[(PB6, AF13)]); +impl_eev!(5: COMP3, PINS=[(PB9, AF13)]); +impl_eev!(6: COMP2, PINS=[(PB5, AF13)]); +impl_eev!(7: COMP4, PINS=[(PB4, AF13)]); +impl_eev!(8: COMP6, PINS=[(PB8, AF13)]); +impl_eev!(9: COMP5, PINS=[(PB3, AF13)]); +impl_eev!(10: COMP7, PINS=[(PC5, AF13), (PC6, AF3)]); + +pub struct SourceBuilder { + /// EExSNS + edge_or_polarity_bits: u8, + + /// EExPOL + polarity_bit: bool, + + /// EExF + filter_bits: u8, + + /// EExFAST + fast_bit: bool, +} + +pub enum EdgeOrPolarity { + Edge(Edge), + Polarity(Polarity), +} + +pub enum Edge { + Rising = 0b01, + Falling = 0b10, + Both = 0b11, +} + +pub enum Polarity { + ActiveHigh, + ActiveLow, +} + +pub enum EevSamplingFilter { + /// No filtering, fault acts asynchronously + /// + /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) + None = 0b0000, + + /// Sample directly at rate f_hrtim, with a count of 2 + /// + /// Note that this bypasses: any f_eevs (FaultSamplingClkDiv) + HrtimN2 = 0b0001, + + /// Sample directly at rate f_hrtim, with a count of 4 + /// + /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) + HrtimN4 = 0b0010, + + /// Sample directly at rate f_hrtim, with a count of 8 + /// + /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) + HrtimN8 = 0b0011, + + /// Sample at rate f_eevs / 2, with a count of 6 + EevsDiv2N6 = 0b0100, + + /// Sample at rate f_eevs / 2, with a count of 8 + EevsDiv2N8 = 0b0101, + + /// Sample at rate f_eevs / 4, with a count of 6 + EevsDiv4N6 = 0b0110, + + /// Sample at rate f_eevs / 4, with a count of 8 + EevsDiv4N8 = 0b0111, + + /// Sample at rate f_eevs / 8, with a count of 6 + EevsDiv8N6 = 0b1000, + + /// Sample at rate f_eevs / 8, with a count of 8 + EevsDiv8N8 = 0b1001, + + /// Sample at rate f_eevs / 16, with a count of 5 + EevsDiv16N5 = 0b1010, + + /// Sample at rate f_eevs / 16, with a count of 6 + EevsDiv16N6 = 0b1011, + + /// Sample at rate f_eevs / 16, with a count of 8 + EevsDiv16N8 = 0b1100, + + /// Sample at rate f_eevs / 32, with a count of 5 + EevsDiv32N5 = 0b1101, + + /// Sample at rate f_eevs / 32, with a count of 6 + EevsDiv32N6 = 0b1110, + + /// Sample at rate f_eevs / 32, with a count of 8 + EevsDiv32N8 = 0b1111, +} + +pub trait ExternalEventBuilder1To5 {} +pub trait ExternalEventBuilder6To10 {} + +impl SourceBuilder { + pub fn edge_or_polarity(mut self, edge_or_polarity: EdgeOrPolarity) -> Self { + (self.edge_or_polarity_bits, self.polarity_bit) = match edge_or_polarity { + EdgeOrPolarity::Polarity(Polarity::ActiveHigh) => (0b00, false), + EdgeOrPolarity::Polarity(Polarity::ActiveLow) => (0b00, true), + EdgeOrPolarity::Edge(Edge::Rising) => (0b01, false), + EdgeOrPolarity::Edge(Edge::Falling) => (0b10, false), + EdgeOrPolarity::Edge(Edge::Both) => (0b11, false), + }; + + self + } +} + +impl SourceBuilder +where + SourceBuilder: ExternalEventBuilder1To5, +{ + pub fn fast(mut self) -> Self { + self.fast_bit = true; + self + } +} + +impl SourceBuilder +where + SourceBuilder: ExternalEventBuilder6To10, +{ + pub fn filter(mut self, filter: EevSamplingFilter) -> Self { + self.filter_bits = filter as _; + self + } +} + +pub trait ExternalEventToEventSource { + fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource; +} + +macro_rules! impl_eev1_5_to_es { + ($eev:ident, $N:literal, $eeXsrc:ident, $eeXpol:ident, $eeXsns:ident, $eeXfast:ident) => { + impl ExternalEventBuilder1To5 for ExternalEventBuilder<$N, SRC> {} + + impl ExternalEventToEventSource for ExternalEventBuilder<$N, SRC> { + fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource { + let ExternalEventBuilder { + edge_or_polarity_bits, + polarity_bit, + filter_bits: _, + fast_bit, + } = self; + + let common = unsafe { &*HRTIM_COMMON::ptr() }; + + // SAFETY: Thanks to, `HrTimCalibrated`, we know we have exclusive access to the register, + // we also know no timers are started. + unsafe { + common.eecr1.modify(|_r, w| { + w.$eeXsrc() + .bits(SRC) + .$eeXpol() + .bit(polarity_bit) + .$eeXsns() + .bits(edge_or_polarity_bits) + .$eeXfast() + .bit(fast_bit) + }); + } + + ExternalEventSource::$eev { _x: PhantomData } + } + } + }; +} + +macro_rules! impl_eev6_10_to_es { + ($eev:ident, $N:literal, $eeXsrc:ident, $eeXpol:ident, $eeXsns:ident, $eeXf:ident) => { + impl ExternalEventBuilder6To10 for ExternalEventBuilder<$N, SRC> {} + + impl ExternalEventToEventSource for ExternalEventBuilder<$N, SRC> { + fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource { + let ExternalEventBuilder { + edge_or_polarity_bits, + polarity_bit, + filter_bits, + fast_bit: _, + } = self; + + let common = unsafe { &*HRTIM_COMMON::ptr() }; + + // SAFETY: Thanks to, `HrTimCalibrated`, we know we have exclusive access to the register, + // we also know no timers are started. + unsafe { + common.eecr2.modify(|_r, w| { + w.$eeXsrc() + .bits(SRC) + .$eeXpol() + .bit(polarity_bit) + .$eeXsns() + .bits(edge_or_polarity_bits) + }); + common.eecr3.modify(|_r, w| w.$eeXf().bits(filter_bits)); + } + + ExternalEventSource::$eev { _x: PhantomData } + } + } + }; +} + +impl_eev1_5_to_es!(Eevnt1, 1, ee1src, ee1pol, ee1sns, ee1fast); +impl_eev1_5_to_es!(Eevnt2, 2, ee2src, ee2pol, ee2sns, ee2fast); +impl_eev1_5_to_es!(Eevnt3, 3, ee3src, ee3pol, ee3sns, ee3fast); +impl_eev1_5_to_es!(Eevnt4, 4, ee4src, ee4pol, ee4sns, ee4fast); +impl_eev1_5_to_es!(Eevnt5, 5, ee5src, ee5pol, ee5sns, ee5fast); + +impl_eev6_10_to_es!(Eevnt6, 6, ee6src, ee6pol, ee6sns, ee6f); +impl_eev6_10_to_es!(Eevnt7, 7, ee7src, ee7pol, ee7sns, ee7f); +impl_eev6_10_to_es!(Eevnt8, 8, ee8src, ee8pol, ee8sns, ee8f); +impl_eev6_10_to_es!(Eevnt9, 9, ee9src, ee9pol, ee9sns, ee9f); +impl_eev6_10_to_es!(Eevnt10, 10, ee10src, ee10pol, ee10sns, ee10f); From 6a7c2703647ea42c037297f5870059ce4993e93f Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 6 Nov 2023 15:41:26 +0100 Subject: [PATCH 39/88] More work on hrtim eev --- examples/hrtim_eev.rs | 40 ++- examples/hrtim_flt_comp.rs | 3 +- src/hrtim/control.rs | 42 ++- src/hrtim/external_event.rs | 438 +++++++++++++++++++------------- src/hrtim/external_event_new.rs | 243 ++++++++++++++++++ src/hrtim/external_event_old.rs | 285 --------------------- src/hrtim/fault.rs | 30 ++- 7 files changed, 554 insertions(+), 527 deletions(-) create mode 100644 src/hrtim/external_event_new.rs delete mode 100644 src/hrtim/external_event_old.rs diff --git a/examples/hrtim_eev.rs b/examples/hrtim_eev.rs index fdfca80e..c62e2f12 100644 --- a/examples/hrtim_eev.rs +++ b/examples/hrtim_eev.rs @@ -57,39 +57,29 @@ fn main() -> ! { let pin_a: PA8> = gpioa.pa8.into_alternate(); - // . . . * - // . 33% . . * . . - // .-----. .-----. .--. . . - //out1 | | | | | | . . - // | | | | | | . . - // ------ ----------- ----------- ----------------------------------- - // . . . * . . - // . . . * . . - // . . . *-------- . . - //fault . . . | | . . - // . . . | | . . - // ----------------------------------------- -------------------------- - // . . . * . . - // . . . * . . + // . . * . + // . 33% . * . . . + // .-----. .--* .-----. .-----. .----- + //out1 | | | | | | | | | + // | | | * | | | | | + // ------ ----------- -------------- ----------- ----------- + // . . * . . . + // . . * . . . + // . . *--------* . . . + //eev . . | | . . . + // . . | | . . . + // ------------------------- ------------------------------------------ + // . . * . . . + // . . * . . . let (timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp .HRTIM_TIMA .pwm_advanced(pin_a, &mut rcc) .prescaler(prescaler) .period(0xFFFF) - //.with_fault_source(fault_source1) - //.with_fault_source(fault_source2) - .with_fault_source(fault_source3) // Set fault source - //.with_fault_source(fault_source4) - //.with_fault_source(fault_source5) - //.with_fault_source(fault_source6) - .fault_action1(FaultAction::ForceInactive) - .fault_action2(FaultAction::ForceInactive) - // alternated every period with one being - // inactive and the other getting to output its wave form - // as normal .finalize(&mut fault_control); out1.enable_rst_event(EventSource::Cr1); // Set low on compare match with cr1 + out1.enable_rst_event(&eev_input3); out1.enable_set_event(EventSource::Period); // Set high at new period cr1.set_duty(timer.get_period() / 3); //unsafe {((HRTIM_COMMON::ptr() as *mut u8).offset(0x14) as *mut u32).write_volatile(1); } diff --git a/examples/hrtim_flt_comp.rs b/examples/hrtim_flt_comp.rs index ece2cbeb..2809639a 100644 --- a/examples/hrtim_flt_comp.rs +++ b/examples/hrtim_flt_comp.rs @@ -47,7 +47,8 @@ fn main() -> ! { let mut adc1 = dp.ADC1.claim_and_configure( hal::adc::ClockSource::SystemClock, &rcc, - hal::adc::config::AdcConfig::default().clock_mode(hal::adc::config::ClockMode::Synchronous_Div_4), + hal::adc::config::AdcConfig::default() + .clock_mode(hal::adc::config::ClockMode::Synchronous_Div_4), &mut delay, false, ); diff --git a/src/hrtim/control.rs b/src/hrtim/control.rs index ab0fef6f..bbd02f52 100644 --- a/src/hrtim/control.rs +++ b/src/hrtim/control.rs @@ -9,7 +9,7 @@ use crate::{ stm32::{HRTIM_COMMON, RCC}, }; -use super::fault::FaultInputs; +use super::{fault::FaultInputs, external_event::EevInputs}; pub trait HrControltExt { fn hr_control(self, _rcc: &mut Rcc) -> HrTimOngoingCalibration; @@ -421,7 +421,7 @@ impl HrTimOngoingCalibration { } } - pub fn wait_for_calibration(self) -> HrTimCalibrated { + pub fn wait_for_calibration(self) -> (HrTimCalibrated, FaultInputs, EevInputs) { let common = unsafe { &*HRTIM_COMMON::ptr() }; while common.isr.read().dllrdy().bit_is_clear() { // Wait until ready @@ -430,7 +430,11 @@ impl HrTimOngoingCalibration { // Calibration is now done, it is safe to continue unsafe { self.init() }; - HrTimCalibrated { _x: PhantomData } + ( + HrTimCalibrated { _x: PhantomData }, + unsafe { FaultInputs::new() }, + unsafe { EevInputs::new() }, + ) } pub fn enable_adc_trigger1_source(mut self, trigger: Adc13Trigger) -> Self { @@ -524,27 +528,17 @@ pub struct HrTimCalibrated { } impl HrTimCalibrated { - pub fn constrain(self) -> (HrPwmControl, FaultInputs) { - ( - HrPwmControl { - _x: PhantomData, - fault_sys: FltMonitorSys { _x: PhantomData }, - fault_1: FltMonitor1 { _x: PhantomData }, - fault_2: FltMonitor2 { _x: PhantomData }, - fault_3: FltMonitor3 { _x: PhantomData }, - fault_4: FltMonitor4 { _x: PhantomData }, - fault_5: FltMonitor5 { _x: PhantomData }, - fault_6: FltMonitor6 { _x: PhantomData }, - }, - FaultInputs { - fault_input1: FaultInput1 { _x: PhantomData }, - fault_input2: FaultInput2 { _x: PhantomData }, - fault_input3: FaultInput3 { _x: PhantomData }, - fault_input4: FaultInput4 { _x: PhantomData }, - fault_input5: FaultInput5 { _x: PhantomData }, - fault_input6: FaultInput6 { _x: PhantomData }, - }, - ) + pub fn constrain(self) -> HrPwmControl { + HrPwmControl { + _x: PhantomData, + fault_sys: FltMonitorSys { _x: PhantomData }, + fault_1: FltMonitor1 { _x: PhantomData }, + fault_2: FltMonitor2 { _x: PhantomData }, + fault_3: FltMonitor3 { _x: PhantomData }, + fault_4: FltMonitor4 { _x: PhantomData }, + fault_5: FltMonitor5 { _x: PhantomData }, + fault_6: FltMonitor6 { _x: PhantomData }, + } } } diff --git a/src/hrtim/external_event.rs b/src/hrtim/external_event.rs index 9ae63cb4..49ae59bd 100644 --- a/src/hrtim/external_event.rs +++ b/src/hrtim/external_event.rs @@ -1,249 +1,321 @@ use core::marker::PhantomData; -use crate::comparator::{COMP1, COMP2, COMP3, COMP4, COMP5, COMP6}; -use crate::gpio::gpioa::{PA12, PA15}; -use crate::gpio::gpiob::{PB0, PB10, PB11}; -use crate::gpio::gpioc::{PC10, PC7}; +use crate::comparator::{self, Comparator, COMP1, COMP2, COMP3, COMP4, COMP5, COMP6, COMP7}; +use crate::gpio::gpiob::{PB3, PB4, PB5, PB6, PB7, PB8, PB9}; +use crate::gpio::gpioc::{PC11, PC12, PC5, PC6}; use crate::gpio::{self, AF13, AF3}; -use crate::hrtim::control::HrPwmControl; -use crate::pwm::FaultMonitor; use crate::stm32::HRTIM_COMMON; - -pub unsafe trait FaultSource: Copy { - const ENABLE_BITS: u8; +use super::{control::HrTimCalibrated, event::EventSource}; + +#[derive(Copy, Clone, PartialEq)] +pub enum ExternalEventSource { + Eevnt1 { _x: PhantomData<()> }, + Eevnt2 { _x: PhantomData<()> }, + Eevnt3 { _x: PhantomData<()> }, + Eevnt4 { _x: PhantomData<()> }, + Eevnt5 { _x: PhantomData<()> }, + Eevnt6 { _x: PhantomData<()> }, + Eevnt7 { _x: PhantomData<()> }, + Eevnt8 { _x: PhantomData<()> }, + Eevnt9 { _x: PhantomData<()> }, + Eevnt10 { _x: PhantomData<()> }, } -pub struct SourceBuilder { - _input: I, - src_bits: u8, - - /// FLTxP - is_active_high: bool, - - /// FLTxF[3:0] - filter_bits: u8, +pub struct EevInputs { + pub eev_input1: EevInput<1>, + pub eev_input2: EevInput<2>, + pub eev_input3: EevInput<3>, + pub eev_input4: EevInput<4>, + pub eev_input5: EevInput<5>, + pub eev_input6: EevInput<6>, + pub eev_input7: EevInput<7>, + pub eev_input8: EevInput<8>, + pub eev_input9: EevInput<9>, + pub eev_input10: EevInput<10>, } -pub struct SourceBuilder { - /// EExSNS - edge_or_polarity_bits: u8, - - /// EExPOL - polarity_bit: bool, - - /// EExF - filter_bits: u8, - - /// EExFAST - fast_bit: bool, -} - -impl SourceBuilder { - unsafe fn new(input: I, src_bits: u8) -> Self { - SourceBuilder { - _input: input, - src_bits, - is_active_high: false, - filter_bits: 0b0000, +impl EevInputs { + pub(crate) unsafe fn new() -> Self { + EevInputs { + eev_input1: EevInput { _x: PhantomData }, + eev_input2: EevInput { _x: PhantomData }, + eev_input3: EevInput { _x: PhantomData }, + eev_input4: EevInput { _x: PhantomData }, + eev_input5: EevInput { _x: PhantomData }, + eev_input6: EevInput { _x: PhantomData }, + eev_input7: EevInput { _x: PhantomData }, + eev_input8: EevInput { _x: PhantomData }, + eev_input9: EevInput { _x: PhantomData }, + eev_input10: EevInput { _x: PhantomData }, } } } -macro_rules! impl_faults { - ($( - $input:ident => $source:ident: - PINS=[($pin:ident, $af:ident), $(($pin_b:ident, $af_b:ident),)*], - COMP=$compX:ident, $enable_bits:literal, - $fltinrZ:ident, $fltWsrc_0:ident, $fltWsrc_1:ident, $fltWp:ident, $fltWf:ident, $fltWe:ident, $fltWlck:ident, - )+) => {$( - - // This should NOT be Copy/Clone - pub struct $input { - pub(crate) _x: PhantomData<()> - } - - #[derive(Copy, Clone)] - pub struct $source { - _x: PhantomData<()> - } +pub struct EevInput { + _x: PhantomData<()>, +} - impl $input { - pub fn bind_pin(self, pin: $pin>) -> SourceBuilder<$input> { +macro_rules! impl_eev_input { + ($N:literal: $compX:ident, PINS=[($pin:ident, $af:ident) $(, ($pin_b:ident, $af_b:ident))*]) => { + impl EevInput<$N> { + pub fn bind_pin(self, pin: $pin>) -> SourceBuilder<$N, IS_FAST> { pin.into_alternate::<$af>(); - unsafe { SourceBuilder::new(self, 0b00) } + unsafe { SourceBuilder::new(0b00) } } $( - pub fn bind_pin_b(self, pin: $pin_b>) -> SourceBuilder<$input> { + // TODO: Is there a nicer way to do this? + pub fn bind_pin_b(self, pin: $pin_b>) -> SourceBuilder<$N, IS_FAST> { pin.into_alternate::<$af_b>(); - unsafe { SourceBuilder::new(self, 0b00) } + unsafe { SourceBuilder::new(0b00) } } )* - pub fn bind_comp(self, _comp: &crate::comparator::Comparator<$compX, crate::comparator::Enabled>) -> SourceBuilder<$input> { - unsafe { SourceBuilder::new(self, 0b01) } + pub fn bind_comp(self, _comp: &crate::comparator::Comparator<$compX, crate::comparator::Enabled>) -> SourceBuilder<$N, IS_FAST> { + unsafe { SourceBuilder::new(0b01) } } - - /*pub fn bind_external(?) { - SourceBuilder::new(self, 0b10); - }*/ } + }; +} - impl SourceBuilder<$input> { - pub fn finalize(self, _control: &mut HrPwmControl) -> $source { - let SourceBuilder{ _input, src_bits, is_active_high, filter_bits } = self; - - // Setup fault source - unsafe { - let common = &*HRTIM_COMMON::ptr(); - - common.fltinr2.modify(|_r, w| w.$fltWsrc_1().bit(src_bits & 0b10 != 0)); - common.$fltinrZ.modify(|_r, w| w - .$fltWsrc_0().bit(src_bits & 0b01 != 0) - .$fltWp().bit(is_active_high) - .$fltWf().bits(filter_bits) - .$fltWe().set_bit() // Enable - ); - - // ... and lock configuration - common.$fltinrZ.modify(|_r, w| w.$fltWlck().set_bit()); - } - - $source { - _x: PhantomData - } - } - - pub fn polarity(mut self, polarity: super::Polarity) -> Self { - self.is_active_high = polarity == super::Polarity::ActiveHigh; - self - } +impl_eev_input!(1: COMP2, PINS=[(PC12, AF3)]); +impl_eev_input!(2: COMP4, PINS=[(PC11, AF3)]); +impl_eev_input!(3: COMP6, PINS=[(PB7, AF13)]); +impl_eev_input!(4: COMP1, PINS=[(PB6, AF13)]); +impl_eev_input!(5: COMP3, PINS=[(PB9, AF13)]); +impl_eev_input!(6: COMP2, PINS=[(PB5, AF13)]); +impl_eev_input!(7: COMP4, PINS=[(PB4, AF13)]); +impl_eev_input!(8: COMP6, PINS=[(PB8, AF13)]); +impl_eev_input!(9: COMP5, PINS=[(PB3, AF13)]); +impl_eev_input!(10: COMP7, PINS=[(PC5, AF13), (PC6, AF3)]); + +pub enum EdgeOrPolarity { + Edge(Edge), + Polarity(Polarity), +} - // TODO: add more settings - /* pub fn blanking(?) -> Self */ +pub enum Edge { + Rising = 0b01, + Falling = 0b10, + Both = 0b11, +} - pub fn filter(mut self, filter: FaultSamplingFilter) -> Self { - self.filter_bits = filter as u8; - self - } - } +pub enum Polarity { + ActiveHigh, + ActiveLow, +} - unsafe impl FaultSource for $source { - const ENABLE_BITS: u8 = $enable_bits; - } - )+} -} - -// TODO: Lookup to ensure the alternate function are the same for other devices than stm32g474 -#[cfg(feature = "stm32g474")] -impl_faults!( - FaultInput1 => FaultSource1: PINS=[(PA12, AF13),], COMP=COMP2, 0b000001, fltinr1, flt1src, flt1src_1, flt1p, flt1f, flt1e, flt1lck, - FaultInput2 => FaultSource2: PINS=[(PA15, AF13),], COMP=COMP4, 0b000010, fltinr1, flt2src, flt2src_1, flt2p, flt2f, flt2e, flt2lck, - FaultInput3 => FaultSource3: PINS=[(PB10, AF13),], COMP=COMP6, 0b000100, fltinr1, flt3src, flt3src_1, flt3p, flt3f, flt3e, flt3lck, - FaultInput4 => FaultSource4: PINS=[(PB11, AF13),], COMP=COMP1, 0b001000, fltinr1, flt4src, flt4src_1, flt4p, flt4f, flt4e, flt4lck, - FaultInput5 => FaultSource5: PINS=[(PB0, AF13), (PC7, AF3),], COMP=COMP3, 0b010000, fltinr2, flt5src, flt5src_1, flt5p, flt5f, flt5e, flt5lck, - FaultInput6 => FaultSource6: PINS=[(PC10, AF13),], COMP=COMP5, 0b100000, fltinr2, flt6src_0, flt6src_1, flt6p, flt6f, flt6e, flt6lck, -); - -pub struct FaultInputs { - pub fault_input1: FaultInput1, - pub fault_input2: FaultInput2, - pub fault_input3: FaultInput3, - pub fault_input4: FaultInput4, - pub fault_input5: FaultInput5, - pub fault_input6: FaultInput6, -} - -pub enum FaultSamplingFilter { +pub enum EevSamplingFilter { /// No filtering, fault acts asynchronously /// - /// Note that this bypasses any f_flts (SamplingClkDiv) + /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) None = 0b0000, /// Sample directly at rate f_hrtim, with a count of 2 /// - /// Note that this bypasses: any f_flts (SamplingClkDiv) + /// Note that this bypasses: any f_eevs (FaultSamplingClkDiv) HrtimN2 = 0b0001, /// Sample directly at rate f_hrtim, with a count of 4 /// - /// Note that this bypasses any f_flts (SamplingClkDiv) + /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) HrtimN4 = 0b0010, /// Sample directly at rate f_hrtim, with a count of 8 /// - /// Note that this bypasses any f_flts (SamplingClkDiv) + /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) HrtimN8 = 0b0011, - /// Sample at rate f_flts / 2, with a count of 6 - FltsDiv2N6 = 0b0100, + /// Sample at rate f_eevs / 2, with a count of 6 + EevsDiv2N6 = 0b0100, - /// Sample at rate f_flts / 2, with a count of 8 - FltsDiv2N8 = 0b0101, + /// Sample at rate f_eevs / 2, with a count of 8 + EevsDiv2N8 = 0b0101, - /// Sample at rate f_flts / 4, with a count of 6 - FltsDiv4N6 = 0b0110, + /// Sample at rate f_eevs / 4, with a count of 6 + EevsDiv4N6 = 0b0110, - /// Sample at rate f_flts / 4, with a count of 8 - FltsDiv4N8 = 0b0111, + /// Sample at rate f_eevs / 4, with a count of 8 + EevsDiv4N8 = 0b0111, - /// Sample at rate f_flts / 8, with a count of 6 - FltsDiv8N6 = 0b1000, + /// Sample at rate f_eevs / 8, with a count of 6 + EevsDiv8N6 = 0b1000, - /// Sample at rate f_flts / 8, with a count of 8 - FltsDiv8N8 = 0b1001, + /// Sample at rate f_eevs / 8, with a count of 8 + EevsDiv8N8 = 0b1001, - /// Sample at rate f_flts / 16, with a count of 5 - FltsDiv16N5 = 0b1010, + /// Sample at rate f_eevs / 16, with a count of 5 + EevsDiv16N5 = 0b1010, - /// Sample at rate f_flts / 16, with a count of 6 - FltsDiv16N6 = 0b1011, + /// Sample at rate f_eevs / 16, with a count of 6 + EevsDiv16N6 = 0b1011, - /// Sample at rate f_flts / 16, with a count of 8 - FltsDiv16N8 = 0b1100, + /// Sample at rate f_eevs / 16, with a count of 8 + EevsDiv16N8 = 0b1100, - /// Sample at rate f_flts / 32, with a count of 5 - FltsDiv32N5 = 0b1101, + /// Sample at rate f_eevs / 32, with a count of 5 + EevsDiv32N5 = 0b1101, - /// Sample at rate f_flts / 32, with a count of 6 - FltsDiv32N6 = 0b1110, + /// Sample at rate f_eevs / 32, with a count of 6 + EevsDiv32N6 = 0b1110, - /// Sample at rate f_flts / 32, with a count of 8 - FltsDiv32N8 = 0b1111, + /// Sample at rate f_eevs / 32, with a count of 8 + EevsDiv32N8 = 0b1111, } -macro_rules! impl_flt_monitor { - ($($t:ident: ($fltx:ident, $fltxc:ident),)+) => {$( - pub struct $t { - pub(crate) _x: PhantomData<()> +pub trait ExternalEventBuilder1To5 {} +pub trait ExternalEventBuilder6To10 {} +pub struct SourceBuilder { + /// EExSRC + src_bits: u8, + + /// EExSNS + edge_or_polarity_bits: u8, + + /// EExPOL + polarity_bit: bool, + + /// EExF + filter_bits: u8, +} + +impl SourceBuilder { + unsafe fn new(src_bits: u8) -> Self { + Self { + src_bits, + edge_or_polarity_bits: 0, // Level sensitive + polarity_bit: false, // Active high + filter_bits: 0, // No filter } + } +} + +impl SourceBuilder { + pub fn edge_or_polarity(mut self, edge_or_polarity: EdgeOrPolarity) -> Self { + (self.edge_or_polarity_bits, self.polarity_bit) = match edge_or_polarity { + EdgeOrPolarity::Polarity(Polarity::ActiveHigh) => (0b00, false), + EdgeOrPolarity::Polarity(Polarity::ActiveLow) => (0b00, true), + EdgeOrPolarity::Edge(Edge::Rising) => (0b01, false), + EdgeOrPolarity::Edge(Edge::Falling) => (0b10, false), + EdgeOrPolarity::Edge(Edge::Both) => (0b11, false), + }; + + self + } +} + +impl SourceBuilder { + /// Edge sensitivity not available in fast mode + pub fn polarity(mut self, polarity: Polarity) -> Self { + (self.edge_or_polarity_bits, self.polarity_bit) = match polarity { + Polarity::ActiveHigh => (0b00, false), + Polarity::ActiveLow => (0b00, true), + }; + + self + } +} + +impl SourceBuilder +where + SourceBuilder: ExternalEventBuilder6To10, +{ + pub fn filter(mut self, filter: EevSamplingFilter) -> Self { + self.filter_bits = filter as _; + self + } +} + +pub trait BuilderToEventSourceBuilder { + fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSourceBuilder; +} + +This is something every (timerX, eevY) pair should have.... +struct ExternalEventSourceBuilder { + filter: u8, + is_latching: bool, +} + +macro_rules! impl_eev1_5_to_es { + ($eev:ident, $N:literal, $eeXsrc:ident, $eeXpol:ident, $eeXsns:ident, $eeXfast:ident) => { + impl ExternalEventBuilder1To5 for SourceBuilder<$N, IS_FAST> {} + + impl BuilderToEventSourceBuilder for SourceBuilder<$N, IS_FAST> { + fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSourceBuilder { + let SourceBuilder { + src_bits, + edge_or_polarity_bits, + polarity_bit, + filter_bits: _, + } = self; - impl FaultMonitor for $t { - fn is_fault_active(&self) -> bool { let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.isr.read().$fltx().bit() + + // SAFETY: Thanks to, `HrTimCalibrated`, we know we have exclusive access to the register, + // we also know no timers are started. + unsafe { + common.eecr1.modify(|_r, w| { + w.$eeXsrc() + .bits(src_bits) + .$eeXpol() + .bit(polarity_bit) + .$eeXsns() + .bits(edge_or_polarity_bits) + .$eeXfast() + .bit(IS_FAST) + }); + } + + ExternalEventSource::$eev { _x: PhantomData } } + } + }; +} + +macro_rules! impl_eev6_10_to_es { + ($eev:ident, $N:literal, $eeXsrc:ident, $eeXpol:ident, $eeXsns:ident, $eeXf:ident) => { + impl ExternalEventBuilder6To10 for SourceBuilder<$N, false> {} + + impl ExternalEventToEventSource for SourceBuilder<$N, false> { + fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource { + let SourceBuilder { + src_bits, + edge_or_polarity_bits, + polarity_bit, + filter_bits, + } = self; - fn clear_fault(&mut self) { let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.icr.write(|w| w.$fltxc().set_bit()); - } - // TODO: Should we have our own trait since it does not seem possible to implement this - fn set_fault(&mut self) { - todo!() + // SAFETY: Thanks to, `HrTimCalibrated`, we know we have exclusive access to the register, + // we also know no timers are started. + unsafe { + common.eecr2.modify(|_r, w| { + w.$eeXsrc() + .bits(src_bits) + .$eeXpol() + .bit(polarity_bit) + .$eeXsns() + .bits(edge_or_polarity_bits) + }); + common.eecr3.modify(|_r, w| w.$eeXf().bits(filter_bits)); + } + + ExternalEventSource::$eev { _x: PhantomData } } } - )+}; -} - -impl_flt_monitor!( - FltMonitorSys: (sysflt, sysfltc), - FltMonitor1: (flt1, flt1c), - FltMonitor2: (flt2, flt2c), - FltMonitor3: (flt3, flt3c), - FltMonitor4: (flt4, flt4c), - FltMonitor5: (flt5, flt5c), - FltMonitor6: (flt6, flt6c), -); + }; +} + +impl_eev1_5_to_es!(Eevnt1, 1, ee1src, ee1pol, ee1sns, ee1fast); +impl_eev1_5_to_es!(Eevnt2, 2, ee2src, ee2pol, ee2sns, ee2fast); +impl_eev1_5_to_es!(Eevnt3, 3, ee3src, ee3pol, ee3sns, ee3fast); +impl_eev1_5_to_es!(Eevnt4, 4, ee4src, ee4pol, ee4sns, ee4fast); +impl_eev1_5_to_es!(Eevnt5, 5, ee5src, ee5pol, ee5sns, ee5fast); + +impl_eev6_10_to_es!(Eevnt6, 6, ee6src, ee6pol, ee6sns, ee6f); +impl_eev6_10_to_es!(Eevnt7, 7, ee7src, ee7pol, ee7sns, ee7f); +impl_eev6_10_to_es!(Eevnt8, 8, ee8src, ee8pol, ee8sns, ee8f); +impl_eev6_10_to_es!(Eevnt9, 9, ee9src, ee9pol, ee9sns, ee9f); +impl_eev6_10_to_es!(Eevnt10, 10, ee10src, ee10pol, ee10sns, ee10f); diff --git a/src/hrtim/external_event_new.rs b/src/hrtim/external_event_new.rs new file mode 100644 index 00000000..2ffa5d74 --- /dev/null +++ b/src/hrtim/external_event_new.rs @@ -0,0 +1,243 @@ +use core::marker::PhantomData; + +use crate::comparator::{COMP1, COMP2, COMP3, COMP4, COMP5, COMP6}; +use crate::gpio::gpioa::{PA12, PA15}; +use crate::gpio::gpiob::{PB0, PB10, PB11}; +use crate::gpio::gpioc::{PC10, PC7}; +use crate::gpio::{self, AF13, AF3}; +use crate::hrtim::control::HrPwmControl; +use crate::pwm::FaultMonitor; +use crate::stm32::HRTIM_COMMON; + +pub struct SourceBuilder { + /// EExSRC + src_bits: u8, + + /// EExSNS + edge_or_polarity_bits: u8, + + /// EExPOL + polarity_bit: bool, + + /// EExF + filter_bits: u8, + + /// EExFAST + fast_bit: bool, +} + +impl SourceBuilder { + unsafe fn new(src_bits: u8) -> Self { + SourceBuilder { + src_bits, + edge_or_polarity_bits: 0, // Polarity sensitive + polarity_bit: false, // Active high + filter_bits: 0, // No filter + fast_bit: false, // Not fast + } + } +} + +// This should NOT be Copy/Clone +pub struct EevInput { + pub(crate) _x: PhantomData<()> +} + +#[derive(Copy, Clone)] +pub struct EevSource { + _x: PhantomData<()> +} + +macro_rules! impl_eev { + ($( + $input:ident => $source:ident: + PINS=[($pin:ident, $af:ident), $(($pin_b:ident, $af_b:ident),)*], + COMP=$compX:ident, $enable_bits:literal, + $fltinrZ:ident, $fltWsrc_0:ident, $fltWsrc_1:ident, $fltWp:ident, $fltWf:ident, $fltWe:ident, $fltWlck:ident, + )+) => {$( + + + impl $input { + pub fn bind_pin(self, pin: $pin>) -> SourceBuilder<$input> { + pin.into_alternate::<$af>(); + unsafe { SourceBuilder::new(self, 0b00) } + } + + $( + // TODO: Is there a nicer way to do this? + pub fn bind_pin_b(self, pin: $pin_b>) -> SourceBuilder<$input> { + pin.into_alternate::<$af_b>(); + unsafe { SourceBuilder::new(self, 0b00) } + } + )* + + pub fn bind_comp(self, _comp: &crate::comparator::Comparator<$compX, crate::comparator::Enabled>) -> SourceBuilder<$input> { + unsafe { SourceBuilder::new(self, 0b01) } + } + } + + impl SourceBuilder<$input> { + pub fn finalize(self, _control: &mut HrPwmControl) -> $source { + let SourceBuilder{ _input, src_bits, is_active_high, filter_bits } = self; + + // Setup fault source + unsafe { + let common = &*HRTIM_COMMON::ptr(); + + common.fltinr2.modify(|_r, w| w.$fltWsrc_1().bit(src_bits & 0b10 != 0)); + common.$fltinrZ.modify(|_r, w| w + .$fltWsrc_0().bit(src_bits & 0b01 != 0) + .$fltWp().bit(is_active_high) + .$fltWf().bits(filter_bits) + .$fltWe().set_bit() // Enable + ); + + // ... and lock configuration + common.$fltinrZ.modify(|_r, w| w.$fltWlck().set_bit()); + } + + $source { + _x: PhantomData + } + } + + pub fn polarity(mut self, polarity: super::Polarity) -> Self { + self.is_active_high = polarity == super::Polarity::ActiveHigh; + self + } + + // TODO: add more settings + /* pub fn blanking(?) -> Self */ + + pub fn filter(mut self, filter: FaultSamplingFilter) -> Self { + self.filter_bits = filter as u8; + self + } + } + + unsafe impl FaultSource for $source { + const ENABLE_BITS: u8 = $enable_bits; + } + )+} +} + +// TODO: Lookup to ensure the alternate function are the same for other devices than stm32g474 +#[cfg(feature = "stm32g474")] +impl_faults!( + FaultInput1 => FaultSource1: PINS=[(PA12, AF13),], COMP=COMP2, 0b000001, fltinr1, flt1src, flt1src_1, flt1p, flt1f, flt1e, flt1lck, + FaultInput2 => FaultSource2: PINS=[(PA15, AF13),], COMP=COMP4, 0b000010, fltinr1, flt2src, flt2src_1, flt2p, flt2f, flt2e, flt2lck, + FaultInput3 => FaultSource3: PINS=[(PB10, AF13),], COMP=COMP6, 0b000100, fltinr1, flt3src, flt3src_1, flt3p, flt3f, flt3e, flt3lck, + FaultInput4 => FaultSource4: PINS=[(PB11, AF13),], COMP=COMP1, 0b001000, fltinr1, flt4src, flt4src_1, flt4p, flt4f, flt4e, flt4lck, + FaultInput5 => FaultSource5: PINS=[(PB0, AF13), (PC7, AF3),], COMP=COMP3, 0b010000, fltinr2, flt5src, flt5src_1, flt5p, flt5f, flt5e, flt5lck, + FaultInput6 => FaultSource6: PINS=[(PC10, AF13),], COMP=COMP5, 0b100000, fltinr2, flt6src_0, flt6src_1, flt6p, flt6f, flt6e, flt6lck, +); + +pub struct EevInputs { + pub eev_input1: EevInput<1>, + pub eev_input2: EevInput<2>, + pub eev_input3: EevInput<3>, + pub eev_input4: EevInput<4>, + pub eev_input5: EevInput<5>, + pub eev_input6: EevInput<6>, + pub eev_input7: EevInput<7>, + pub eev_input8: EevInput<8>, + pub eev_input9: EevInput<9>, + pub eev_input10: EevInput<10>, +} + +impl EevInputs { + +} + +pub enum FaultSamplingFilter { + /// No filtering, fault acts asynchronously + /// + /// Note that this bypasses any f_flts (SamplingClkDiv) + None = 0b0000, + + /// Sample directly at rate f_hrtim, with a count of 2 + /// + /// Note that this bypasses: any f_flts (SamplingClkDiv) + HrtimN2 = 0b0001, + + /// Sample directly at rate f_hrtim, with a count of 4 + /// + /// Note that this bypasses any f_flts (SamplingClkDiv) + HrtimN4 = 0b0010, + + /// Sample directly at rate f_hrtim, with a count of 8 + /// + /// Note that this bypasses any f_flts (SamplingClkDiv) + HrtimN8 = 0b0011, + + /// Sample at rate f_flts / 2, with a count of 6 + FltsDiv2N6 = 0b0100, + + /// Sample at rate f_flts / 2, with a count of 8 + FltsDiv2N8 = 0b0101, + + /// Sample at rate f_flts / 4, with a count of 6 + FltsDiv4N6 = 0b0110, + + /// Sample at rate f_flts / 4, with a count of 8 + FltsDiv4N8 = 0b0111, + + /// Sample at rate f_flts / 8, with a count of 6 + FltsDiv8N6 = 0b1000, + + /// Sample at rate f_flts / 8, with a count of 8 + FltsDiv8N8 = 0b1001, + + /// Sample at rate f_flts / 16, with a count of 5 + FltsDiv16N5 = 0b1010, + + /// Sample at rate f_flts / 16, with a count of 6 + FltsDiv16N6 = 0b1011, + + /// Sample at rate f_flts / 16, with a count of 8 + FltsDiv16N8 = 0b1100, + + /// Sample at rate f_flts / 32, with a count of 5 + FltsDiv32N5 = 0b1101, + + /// Sample at rate f_flts / 32, with a count of 6 + FltsDiv32N6 = 0b1110, + + /// Sample at rate f_flts / 32, with a count of 8 + FltsDiv32N8 = 0b1111, +} + +macro_rules! impl_flt_monitor { + ($($t:ident: ($fltx:ident, $fltxc:ident),)+) => {$( + pub struct $t { + pub(crate) _x: PhantomData<()> + } + + impl FaultMonitor for $t { + fn is_fault_active(&self) -> bool { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.isr.read().$fltx().bit() + } + + fn clear_fault(&mut self) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.icr.write(|w| w.$fltxc().set_bit()); + } + + // TODO: Should we have our own trait since it does not seem possible to implement this + fn set_fault(&mut self) { + todo!() + } + } + )+}; +} + +impl_flt_monitor!( + FltMonitorSys: (sysflt, sysfltc), + FltMonitor1: (flt1, flt1c), + FltMonitor2: (flt2, flt2c), + FltMonitor3: (flt3, flt3c), + FltMonitor4: (flt4, flt4c), + FltMonitor5: (flt5, flt5c), + FltMonitor6: (flt6, flt6c), +); diff --git a/src/hrtim/external_event_old.rs b/src/hrtim/external_event_old.rs deleted file mode 100644 index 8454a1c9..00000000 --- a/src/hrtim/external_event_old.rs +++ /dev/null @@ -1,285 +0,0 @@ -use core::marker::PhantomData; - -use crate::comparator::{self, Comparator, COMP1, COMP2, COMP3, COMP4, COMP5, COMP6, COMP7}; -use crate::gpio::{self, AF3, AF13}; -use crate::gpio::gpiob::{PB4, PB5, PB6, PB7, PB9, PB8, PB3}; -use crate::gpio::gpioc::{PC11, PC12, PC5, PC6}; -use crate::stm32::HRTIM_COMMON; - -use super::{control::HrTimCalibrated, event::EventSource}; - -#[derive(Copy, Clone, PartialEq)] -pub enum ExternalEventSource { - Eevnt1 { _x: PhantomData<()> }, - Eevnt2 { _x: PhantomData<()> }, - Eevnt3 { _x: PhantomData<()> }, - Eevnt4 { _x: PhantomData<()> }, - Eevnt5 { _x: PhantomData<()> }, - Eevnt6 { _x: PhantomData<()> }, - Eevnt7 { _x: PhantomData<()> }, - Eevnt8 { _x: PhantomData<()> }, - Eevnt9 { _x: PhantomData<()> }, - Eevnt10 { _x: PhantomData<()> }, -} - -impl From for EventSource { - fn from(val: ExternalEventSource) -> Self { - EventSource::ExternalEvent(val) - } -} - -pub trait ExternalEventExt { - fn external_event(self) -> SourceBuilder; -} - -macro_rules! impl_eev { - ($N:literal: $comp:ident, PINS=[$(($pin:ident, $af:ident)),+]) => { - impl ExternalEventExt<$N, 0b01> for &Comparator<$comp, E> { - fn external_event(self) -> ExternalEventBuilder<$N, 0b01> { - ExternalEventBuilder { - edge_or_polarity_bits: 0, // Polarity sensitive - polarity_bit: false, // Active high - filter_bits: 0, // No filter - fast_bit: false, // Not fast - } - } - } - - $( - impl ExternalEventExt<$N, 0b00> for $pin> { - fn external_event(self) -> ExternalEventBuilder<$N, 0b00> { - self.into_alternate::<$af>(); - ExternalEventBuilder { - edge_or_polarity_bits: 0, // Polarity sensitive - polarity_bit: false, // Active high - filter_bits: 0, // No filter - fast_bit: false, // Not fast - } - } - } - )* - }; -} - -impl_eev!(1: COMP2, PINS=[(PC12, AF3)]); -impl_eev!(2: COMP4, PINS=[(PC11, AF3)]); -impl_eev!(3: COMP6, PINS=[(PB7, AF13)]); -impl_eev!(4: COMP1, PINS=[(PB6, AF13)]); -impl_eev!(5: COMP3, PINS=[(PB9, AF13)]); -impl_eev!(6: COMP2, PINS=[(PB5, AF13)]); -impl_eev!(7: COMP4, PINS=[(PB4, AF13)]); -impl_eev!(8: COMP6, PINS=[(PB8, AF13)]); -impl_eev!(9: COMP5, PINS=[(PB3, AF13)]); -impl_eev!(10: COMP7, PINS=[(PC5, AF13), (PC6, AF3)]); - -pub struct SourceBuilder { - /// EExSNS - edge_or_polarity_bits: u8, - - /// EExPOL - polarity_bit: bool, - - /// EExF - filter_bits: u8, - - /// EExFAST - fast_bit: bool, -} - -pub enum EdgeOrPolarity { - Edge(Edge), - Polarity(Polarity), -} - -pub enum Edge { - Rising = 0b01, - Falling = 0b10, - Both = 0b11, -} - -pub enum Polarity { - ActiveHigh, - ActiveLow, -} - -pub enum EevSamplingFilter { - /// No filtering, fault acts asynchronously - /// - /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) - None = 0b0000, - - /// Sample directly at rate f_hrtim, with a count of 2 - /// - /// Note that this bypasses: any f_eevs (FaultSamplingClkDiv) - HrtimN2 = 0b0001, - - /// Sample directly at rate f_hrtim, with a count of 4 - /// - /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) - HrtimN4 = 0b0010, - - /// Sample directly at rate f_hrtim, with a count of 8 - /// - /// Note that this bypasses any f_eevs (FaultSamplingClkDiv) - HrtimN8 = 0b0011, - - /// Sample at rate f_eevs / 2, with a count of 6 - EevsDiv2N6 = 0b0100, - - /// Sample at rate f_eevs / 2, with a count of 8 - EevsDiv2N8 = 0b0101, - - /// Sample at rate f_eevs / 4, with a count of 6 - EevsDiv4N6 = 0b0110, - - /// Sample at rate f_eevs / 4, with a count of 8 - EevsDiv4N8 = 0b0111, - - /// Sample at rate f_eevs / 8, with a count of 6 - EevsDiv8N6 = 0b1000, - - /// Sample at rate f_eevs / 8, with a count of 8 - EevsDiv8N8 = 0b1001, - - /// Sample at rate f_eevs / 16, with a count of 5 - EevsDiv16N5 = 0b1010, - - /// Sample at rate f_eevs / 16, with a count of 6 - EevsDiv16N6 = 0b1011, - - /// Sample at rate f_eevs / 16, with a count of 8 - EevsDiv16N8 = 0b1100, - - /// Sample at rate f_eevs / 32, with a count of 5 - EevsDiv32N5 = 0b1101, - - /// Sample at rate f_eevs / 32, with a count of 6 - EevsDiv32N6 = 0b1110, - - /// Sample at rate f_eevs / 32, with a count of 8 - EevsDiv32N8 = 0b1111, -} - -pub trait ExternalEventBuilder1To5 {} -pub trait ExternalEventBuilder6To10 {} - -impl SourceBuilder { - pub fn edge_or_polarity(mut self, edge_or_polarity: EdgeOrPolarity) -> Self { - (self.edge_or_polarity_bits, self.polarity_bit) = match edge_or_polarity { - EdgeOrPolarity::Polarity(Polarity::ActiveHigh) => (0b00, false), - EdgeOrPolarity::Polarity(Polarity::ActiveLow) => (0b00, true), - EdgeOrPolarity::Edge(Edge::Rising) => (0b01, false), - EdgeOrPolarity::Edge(Edge::Falling) => (0b10, false), - EdgeOrPolarity::Edge(Edge::Both) => (0b11, false), - }; - - self - } -} - -impl SourceBuilder -where - SourceBuilder: ExternalEventBuilder1To5, -{ - pub fn fast(mut self) -> Self { - self.fast_bit = true; - self - } -} - -impl SourceBuilder -where - SourceBuilder: ExternalEventBuilder6To10, -{ - pub fn filter(mut self, filter: EevSamplingFilter) -> Self { - self.filter_bits = filter as _; - self - } -} - -pub trait ExternalEventToEventSource { - fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource; -} - -macro_rules! impl_eev1_5_to_es { - ($eev:ident, $N:literal, $eeXsrc:ident, $eeXpol:ident, $eeXsns:ident, $eeXfast:ident) => { - impl ExternalEventBuilder1To5 for ExternalEventBuilder<$N, SRC> {} - - impl ExternalEventToEventSource for ExternalEventBuilder<$N, SRC> { - fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource { - let ExternalEventBuilder { - edge_or_polarity_bits, - polarity_bit, - filter_bits: _, - fast_bit, - } = self; - - let common = unsafe { &*HRTIM_COMMON::ptr() }; - - // SAFETY: Thanks to, `HrTimCalibrated`, we know we have exclusive access to the register, - // we also know no timers are started. - unsafe { - common.eecr1.modify(|_r, w| { - w.$eeXsrc() - .bits(SRC) - .$eeXpol() - .bit(polarity_bit) - .$eeXsns() - .bits(edge_or_polarity_bits) - .$eeXfast() - .bit(fast_bit) - }); - } - - ExternalEventSource::$eev { _x: PhantomData } - } - } - }; -} - -macro_rules! impl_eev6_10_to_es { - ($eev:ident, $N:literal, $eeXsrc:ident, $eeXpol:ident, $eeXsns:ident, $eeXf:ident) => { - impl ExternalEventBuilder6To10 for ExternalEventBuilder<$N, SRC> {} - - impl ExternalEventToEventSource for ExternalEventBuilder<$N, SRC> { - fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource { - let ExternalEventBuilder { - edge_or_polarity_bits, - polarity_bit, - filter_bits, - fast_bit: _, - } = self; - - let common = unsafe { &*HRTIM_COMMON::ptr() }; - - // SAFETY: Thanks to, `HrTimCalibrated`, we know we have exclusive access to the register, - // we also know no timers are started. - unsafe { - common.eecr2.modify(|_r, w| { - w.$eeXsrc() - .bits(SRC) - .$eeXpol() - .bit(polarity_bit) - .$eeXsns() - .bits(edge_or_polarity_bits) - }); - common.eecr3.modify(|_r, w| w.$eeXf().bits(filter_bits)); - } - - ExternalEventSource::$eev { _x: PhantomData } - } - } - }; -} - -impl_eev1_5_to_es!(Eevnt1, 1, ee1src, ee1pol, ee1sns, ee1fast); -impl_eev1_5_to_es!(Eevnt2, 2, ee2src, ee2pol, ee2sns, ee2fast); -impl_eev1_5_to_es!(Eevnt3, 3, ee3src, ee3pol, ee3sns, ee3fast); -impl_eev1_5_to_es!(Eevnt4, 4, ee4src, ee4pol, ee4sns, ee4fast); -impl_eev1_5_to_es!(Eevnt5, 5, ee5src, ee5pol, ee5sns, ee5fast); - -impl_eev6_10_to_es!(Eevnt6, 6, ee6src, ee6pol, ee6sns, ee6f); -impl_eev6_10_to_es!(Eevnt7, 7, ee7src, ee7pol, ee7sns, ee7f); -impl_eev6_10_to_es!(Eevnt8, 8, ee8src, ee8pol, ee8sns, ee8f); -impl_eev6_10_to_es!(Eevnt9, 9, ee9src, ee9pol, ee9sns, ee9f); -impl_eev6_10_to_es!(Eevnt10, 10, ee10src, ee10pol, ee10sns, ee10f); diff --git a/src/hrtim/fault.rs b/src/hrtim/fault.rs index 67b1ec7c..8e8f5ae1 100644 --- a/src/hrtim/fault.rs +++ b/src/hrtim/fault.rs @@ -52,7 +52,7 @@ impl SourceBuilder { macro_rules! impl_faults { ($( $input:ident => $source:ident: - PINS=[($pin:ident, $af:ident), $(($pin_b:ident, $af_b:ident),)*], + PINS=[($pin:ident, $af:ident) $(,($pin_b:ident, $af_b:ident))*], COMP=$compX:ident, $enable_bits:literal, $fltinrZ:ident, $fltWsrc_0:ident, $fltWsrc_1:ident, $fltWp:ident, $fltWf:ident, $fltWe:ident, $fltWlck:ident, )+) => {$( @@ -74,6 +74,7 @@ macro_rules! impl_faults { } $( + // TODO: Is there a nicer way to do this? pub fn bind_pin_b(self, pin: $pin_b>) -> SourceBuilder<$input> { pin.into_alternate::<$af_b>(); unsafe { SourceBuilder::new(self, 0b00) } @@ -134,15 +135,13 @@ macro_rules! impl_faults { )+} } -// TODO: Lookup to ensure the alternate function are the same for other devices than stm32g474 -#[cfg(feature = "stm32g474")] impl_faults!( - FaultInput1 => FaultSource1: PINS=[(PA12, AF13),], COMP=COMP2, 0b000001, fltinr1, flt1src, flt1src_1, flt1p, flt1f, flt1e, flt1lck, - FaultInput2 => FaultSource2: PINS=[(PA15, AF13),], COMP=COMP4, 0b000010, fltinr1, flt2src, flt2src_1, flt2p, flt2f, flt2e, flt2lck, - FaultInput3 => FaultSource3: PINS=[(PB10, AF13),], COMP=COMP6, 0b000100, fltinr1, flt3src, flt3src_1, flt3p, flt3f, flt3e, flt3lck, - FaultInput4 => FaultSource4: PINS=[(PB11, AF13),], COMP=COMP1, 0b001000, fltinr1, flt4src, flt4src_1, flt4p, flt4f, flt4e, flt4lck, - FaultInput5 => FaultSource5: PINS=[(PB0, AF13), (PC7, AF3),], COMP=COMP3, 0b010000, fltinr2, flt5src, flt5src_1, flt5p, flt5f, flt5e, flt5lck, - FaultInput6 => FaultSource6: PINS=[(PC10, AF13),], COMP=COMP5, 0b100000, fltinr2, flt6src_0, flt6src_1, flt6p, flt6f, flt6e, flt6lck, + FaultInput1 => FaultSource1: PINS=[(PA12, AF13)], COMP=COMP2, 0b000001, fltinr1, flt1src, flt1src_1, flt1p, flt1f, flt1e, flt1lck, + FaultInput2 => FaultSource2: PINS=[(PA15, AF13)], COMP=COMP4, 0b000010, fltinr1, flt2src, flt2src_1, flt2p, flt2f, flt2e, flt2lck, + FaultInput3 => FaultSource3: PINS=[(PB10, AF13)], COMP=COMP6, 0b000100, fltinr1, flt3src, flt3src_1, flt3p, flt3f, flt3e, flt3lck, + FaultInput4 => FaultSource4: PINS=[(PB11, AF13)], COMP=COMP1, 0b001000, fltinr1, flt4src, flt4src_1, flt4p, flt4f, flt4e, flt4lck, + FaultInput5 => FaultSource5: PINS=[(PB0, AF13), (PC7, AF3)], COMP=COMP3, 0b010000, fltinr2, flt5src, flt5src_1, flt5p, flt5f, flt5e, flt5lck, + FaultInput6 => FaultSource6: PINS=[(PC10, AF13)], COMP=COMP5, 0b100000, fltinr2, flt6src_0, flt6src_1, flt6p, flt6f, flt6e, flt6lck, ); pub struct FaultInputs { @@ -154,6 +153,19 @@ pub struct FaultInputs { pub fault_input6: FaultInput6, } +impl FaultInputs { + pub(crate) unsafe fn new() -> Self { + FaultInputs { + fault_input1: FaultInput1 { _x: PhantomData }, + fault_input2: FaultInput2 { _x: PhantomData }, + fault_input3: FaultInput3 { _x: PhantomData }, + fault_input4: FaultInput4 { _x: PhantomData }, + fault_input5: FaultInput5 { _x: PhantomData }, + fault_input6: FaultInput6 { _x: PhantomData }, + } + } +} + pub enum FaultSamplingFilter { /// No filtering, fault acts asynchronously /// From fd6adea2649bc0cfe01ced9f97a04a4a120c92e8 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 6 Nov 2023 19:11:08 +0100 Subject: [PATCH 40/88] even more eev hrtim --- src/hrtim/external_event.rs | 17 ++++---- src/hrtim/mod.rs | 15 ++++++- src/hrtim/timer_eev_cfg.rs | 79 +++++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 10 deletions(-) create mode 100644 src/hrtim/timer_eev_cfg.rs diff --git a/src/hrtim/external_event.rs b/src/hrtim/external_event.rs index 49ae59bd..9cc24b39 100644 --- a/src/hrtim/external_event.rs +++ b/src/hrtim/external_event.rs @@ -227,22 +227,21 @@ where } } -pub trait BuilderToEventSourceBuilder { - fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSourceBuilder; +pub trait ToExternalEventSource { + fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource; } -This is something every (timerX, eevY) pair should have.... -struct ExternalEventSourceBuilder { - filter: u8, - is_latching: bool, +#[derive(Copy, Clone)] +struct ExternalEventMuxOut { + _x: PhantomData<()>, } macro_rules! impl_eev1_5_to_es { ($eev:ident, $N:literal, $eeXsrc:ident, $eeXpol:ident, $eeXsns:ident, $eeXfast:ident) => { impl ExternalEventBuilder1To5 for SourceBuilder<$N, IS_FAST> {} - impl BuilderToEventSourceBuilder for SourceBuilder<$N, IS_FAST> { - fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSourceBuilder { + impl ToExternalEventSource for SourceBuilder<$N, IS_FAST> { + fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource { let SourceBuilder { src_bits, edge_or_polarity_bits, @@ -277,7 +276,7 @@ macro_rules! impl_eev6_10_to_es { ($eev:ident, $N:literal, $eeXsrc:ident, $eeXpol:ident, $eeXsns:ident, $eeXf:ident) => { impl ExternalEventBuilder6To10 for SourceBuilder<$N, false> {} - impl ExternalEventToEventSource for SourceBuilder<$N, false> { + impl ToExternalEventSource for SourceBuilder<$N, false> { fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource { let SourceBuilder { src_bits, diff --git a/src/hrtim/mod.rs b/src/hrtim/mod.rs index 78f6c675..369d664f 100644 --- a/src/hrtim/mod.rs +++ b/src/hrtim/mod.rs @@ -6,6 +6,7 @@ pub mod external_event; pub mod fault; pub mod output; pub mod timer; +pub mod timer_eev_cfg; use core::marker::PhantomData; use core::mem::MaybeUninit; @@ -195,6 +196,7 @@ pub struct HrPwmBuilder { repetition_counter: u8, deadtime: Option, enable_repetition_interrupt: bool, + eev_cfg: EevCfg, out1_polarity: Polarity, out2_polarity: Polarity, } @@ -413,6 +415,7 @@ macro_rules! hrtim_common_methods { repetition_counter, deadtime, enable_repetition_interrupt, + eev_cfg, out1_polarity, out2_polarity, } = self; @@ -441,6 +444,7 @@ macro_rules! hrtim_common_methods { repetition_counter, deadtime, enable_repetition_interrupt, + eev_cfg, out1_polarity, out2_polarity, } @@ -479,6 +483,12 @@ macro_rules! hrtim_common_methods { self } + + pub fn eev_cfg(mut self, eev_cfg: Stuff) -> Self { + self.eev_cfg = eev_cfg; + + self + } }; } @@ -554,7 +564,10 @@ macro_rules! hrtim_hal { OUT: ToHrOut, { pub fn finalize(self, _control: &mut HrPwmControl) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX, PSCL>, HrCr2<$TIMX, PSCL>, HrCr3<$TIMX, PSCL>, HrCr4<$TIMX, PSCL>), OUT) { - hrtim_finalize_body!(self, PreloadSource, $TIMX: ($timXcr, ck_pscx, $perXr, perx, $tXcen, $rep, $repx, $dier, $repie, $timXcr2, $fltXr, $outXr, $dtXr),) + hrtim_finalize_body!( + self, PreloadSource, + $TIMX: ($timXcr, ck_pscx, $perXr, perx, $tXcen, $rep, $repx, $dier, $repie, $timXcr2, $fltXr, $outXr, $dtXr), + ) } hrtim_common_methods!($TIMX, PreloadSource); diff --git a/src/hrtim/timer_eev_cfg.rs b/src/hrtim/timer_eev_cfg.rs new file mode 100644 index 00000000..ffc9213c --- /dev/null +++ b/src/hrtim/timer_eev_cfg.rs @@ -0,0 +1,79 @@ +use core::marker::PhantomData; + +struct EevCfgs { + eev1: EevCfg, + eev2: EevCfg, + eev3: EevCfg, + eev4: EevCfg, + eev5: EevCfg, + eev6: EevCfg, + eev7: EevCfg, + eev8: EevCfg, + eev9: EevCfg, + eev10: EevCfg, +} + +#[derive(Default)] +struct EevCfg { + _x: PhantomData, + filter_bits: u8, + latch_bit: u8, +} + +impl EevCfg { + pub fn filter(mut self, stuff: u8) { + self.filter_bits = stuff; + self + } + + /// NOTE: This can not be set if eev is in fast mode AND using a + pub fn latching(mut self) -> Self { + self.latch_bit = true; + self + } +} + +/// Note: Whenever a compare register is used for filtering, the value must be strictly above 0. +pub enum EventFilter { + None = 0b0000, + + /// Blanking from reset/rollover to Cmp1 + BlankingResetToCmp1 = 0b0001, + + /// This depends on counter mode: + /// * Up-counting mode: Blanking from reset/rollover to Cmp2 + /// * Up-down mode: Blanking from Cmp1 to Cmp2(only during up counting) + BlankingResetToCmp2OrCmp1ToCmp2InUdm = 0b0010, + + /// Blanking from reset/rollover to Cmp3 + BlankingResetToCmp3 = 0b0011, + + /// This depends on counter mode: + /// * Up-counting mode: Blanking from reset/rollover to Cmp4 + /// * Up-down mode: Blanking from Cmp3 to Cmp4(only during up counting) + BlankingResetToCmp4OrCmp3ToCmp4InUdm = 0b0100, + + BlankingSource1 = 0b0101, + BlankingSource2 = 0b0110, + BlankingSource3 = 0b0111, + BlankingSource4 = 0b1000, + BlankingSource5 = 0b1001, + BlankingSource6 = 0b1010, + BlankingSource7 = 0b1011, + BlankingSource8 = 0b1100, + + /// This depends on counter mode: + /// * Up-counting mode: Windowing from reset/rollover to Cmp2 + /// * Up-down mode: Windowing from Cmp2 to Cmp3(only during up counting) + WindowingResetToCmp2OrCmp2ToCmp3InUdm = 0b1101, + + /// This depends on counter mode: + /// * Up-counting mode: Windowing from reset/rollover to Cmp3 + /// * Up-down mode: Windowing from Cmp2 to Cmp3(only during down counting) + WindowingResetToCmp3OrCmp2ToCmp3InUdm = 0b1110, + + Windowing from another timing unit: TIMWIN source (see Table 227 for details) in upcounting mode (UDM bit reset) +In up-down counting mode (UDM bit set): windowing from compare 2 during the up-counting +phase to compare 3 during the down-counting phase. + Windowing +} \ No newline at end of file From 30d117f53f324a72c3a49ee049044d72a32d57bd Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 7 Nov 2023 17:32:43 +0100 Subject: [PATCH 41/88] more eev hrtim --- examples/hrtim_eev.rs | 78 +++++++++++--------- examples/hrtim_eev_comp.rs | 135 ++++++++++++++++++++++++++++++++++ src/hrtim/control.rs | 5 +- src/hrtim/event.rs | 7 +- src/hrtim/external_event.rs | 114 ++++++++++++++++++---------- src/hrtim/mod.rs | 58 ++++++++++----- src/hrtim/output.rs | 71 +++++++++--------- src/hrtim/timer_eev_cfg.rs | 143 +++++++++++++++++++++++++++++------- 8 files changed, 461 insertions(+), 150 deletions(-) create mode 100644 examples/hrtim_eev_comp.rs diff --git a/examples/hrtim_eev.rs b/examples/hrtim_eev.rs index c62e2f12..0ad29263 100644 --- a/examples/hrtim_eev.rs +++ b/examples/hrtim_eev.rs @@ -7,15 +7,17 @@ use fugit::ExtU32; use hal::gpio::gpioa::PA8; use hal::gpio::Alternate; use hal::gpio::AF13; +use hal::hrtim::compare_register::HrCompareRegister; +use hal::hrtim::event::EventSource; +use hal::hrtim::external_event::{self, ToExternalEventSource}; +use hal::hrtim::timer_eev_cfg::EevCfgs; +use hal::hrtim::timer::HrTimer; +use hal::hrtim::HrPwmAdvExt; +use hal::hrtim::Pscl4; +use hal::hrtim::{control::HrControltExt, output::HrOutput}; use hal::prelude::*; -use hal::pwm::hrtim::EventSource; -use hal::pwm::hrtim::FaultAction; -use hal::pwm::hrtim::HrCompareRegister; -use hal::pwm::hrtim::HrPwmAdvExt; -use hal::pwm::hrtim::HrTimer; -use hal::pwm::hrtim::Pscl4; -use hal::pwm::hrtim::{HrControltExt, HrOutput}; -use hal::pwm::FaultMonitor; +use hal::pwm; +use hal::pwr::{self, PwrExt}; use hal::rcc; use hal::stm32; use stm32g4xx_hal as hal; @@ -30,26 +32,42 @@ fn main() -> ! { let cp = stm32::CorePeripherals::take().expect("cannot take core"); // Set system frequency to 16MHz * 75/4/2 = 150MHz // This would lead to HrTim running at 150MHz * 32 = 4.8GHz... - let mut rcc = dp.RCC.freeze(rcc::Config::pll().pll_cfg(rcc::PllConfig { - mux: rcc::PLLSrc::HSI, - n: rcc::PllNMul::MUL_75, - m: rcc::PllMDiv::DIV_4, - r: Some(rcc::PllRDiv::DIV_2), - ..Default::default() - })); + let pwr = dp + .PWR + .constrain() + .vos(pwr::VoltageScale::Range1 { + enable_boost: false, + }) + .freeze(); + + let mut rcc = dp.RCC.freeze( + rcc::Config::pll().pll_cfg(rcc::PllConfig { + mux: rcc::PLLSrc::HSI, + n: rcc::PllNMul::MUL_75, + m: rcc::PllMDiv::DIV_4, + r: Some(rcc::PllRDiv::DIV_2), + ..Default::default() + }), + pwr, + ); let mut delay = cp.SYST.delay(&rcc.clocks); let gpioa = dp.GPIOA.split(&mut rcc); let gpiob = dp.GPIOB.split(&mut rcc); - let (mut fault_control, flt_inputs, eev_inputs) = + + let (mut hr_control, _flt_inputs, eev_inputs) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); let eev_input3 = eev_inputs .eev_input3 .bind_pin(gpiob.pb7.into_pull_down_input()) - .polarity(hal::pwm::Polarity::ActiveHigh) - .finalize(&mut fault_control); + .edge_or_polarity(external_event::EdgeOrPolarity::Polarity( + pwm::Polarity::ActiveHigh, + )) + .finalize(&mut hr_control); + + let mut hr_control = hr_control.constrain(); // ...with a prescaler of 4 this gives us a HrTimer with a tick rate of 1.2GHz // With max the max period set, this would be 1.2GHz/2^16 ~= 18kHz... @@ -71,31 +89,23 @@ fn main() -> ! { // ------------------------- ------------------------------------------ // . . * . . . // . . * . . . - let (timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp + let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp .HRTIM_TIMA .pwm_advanced(pin_a, &mut rcc) .prescaler(prescaler) + .eev_cfg(EevCfgs::default()) .period(0xFFFF) - .finalize(&mut fault_control); + .finalize(&mut hr_control); - out1.enable_rst_event(EventSource::Cr1); // Set low on compare match with cr1 - out1.enable_rst_event(&eev_input3); - out1.enable_set_event(EventSource::Period); // Set high at new period + out1.enable_rst_event(&cr1); // Set low on compare match with cr1 + out1.enable_rst_event(eev_input3); + out1.enable_set_event(&timer); // Set high at new period cr1.set_duty(timer.get_period() / 3); //unsafe {((HRTIM_COMMON::ptr() as *mut u8).offset(0x14) as *mut u32).write_volatile(1); } out1.enable(); + timer.start(&mut hr_control); defmt::info!("Started"); - loop { - for _ in 0..5 { - delay.delay(500_u32.millis()); - defmt::info!("State: {}", out1.get_state()); - } - if fault_control.fault_3.is_fault_active() { - fault_control.fault_3.clear_fault(); // Clear fault every 5s - out1.enable(); - defmt::info!("failt cleared, and output reenabled"); - } - } + loop {} } diff --git a/examples/hrtim_eev_comp.rs b/examples/hrtim_eev_comp.rs new file mode 100644 index 00000000..2776b897 --- /dev/null +++ b/examples/hrtim_eev_comp.rs @@ -0,0 +1,135 @@ +//This example puts the timer in PWM mode using the specified pin with a frequency of 100Hz and a duty cycle of 50%. +#![no_main] +#![no_std] + +use cortex_m_rt::entry; +use fugit::ExtU32; +use hal::comparator; +use hal::comparator::{Hysteresis, ComparatorSplit, ComparatorExt}; +use hal::dac::{self, DacExt, DacOut}; +use hal::gpio::gpioa::PA8; +use hal::gpio::Alternate; +use hal::gpio::AF13; +use hal::hrtim::compare_register::HrCompareRegister; +use hal::hrtim::event::EventSource; +use hal::hrtim::external_event::{self, ToExternalEventSource}; +use hal::hrtim::timer_eev_cfg::EevCfgs; +use hal::hrtim::timer::HrTimer; +use hal::hrtim::HrPwmAdvExt; +use hal::hrtim::Pscl4; +use hal::hrtim::{control::HrControltExt, output::HrOutput}; +use hal::prelude::*; +use hal::pwm; +use hal::pwr::{self, PwrExt}; +use hal::rcc; +use hal::stm32; +use stm32g4xx_hal as hal; + +use defmt_rtt as _; // global logger +use panic_probe as _; + +#[entry] +fn main() -> ! { + let dp = stm32::Peripherals::take().expect("cannot take peripherals"); + let cp = stm32::CorePeripherals::take().expect("cannot take core"); + // Set system frequency to 16MHz * 75/4/2 = 150MHz + // This would lead to HrTim running at 150MHz * 32 = 4.8GHz... + let pwr = dp + .PWR + .constrain() + .vos(pwr::VoltageScale::Range1 { + enable_boost: false, + }) + .freeze(); + + let mut rcc = dp.RCC.freeze( + rcc::Config::pll().pll_cfg(rcc::PllConfig { + mux: rcc::PLLSrc::HSI, + n: rcc::PllNMul::MUL_75, + m: rcc::PllMDiv::DIV_4, + r: Some(rcc::PllRDiv::DIV_2), + ..Default::default() + }), + pwr, + ); + + let mut delay = cp.SYST.delay(&rcc.clocks); + + let gpioa = dp.GPIOA.split(&mut rcc); + let gpiob = dp.GPIOB.split(&mut rcc); + + let input = gpioa.pa1.into_analog(); + let pin_a: PA8> = gpioa.pa8.into_alternate(); + + let dac3ch1 = dp.DAC3.constrain(dac::Dac3IntSig1, &mut rcc); + let mut dac = dac3ch1.enable(); + + // Use dac to define the fault threshold + // 2^12 / 2 = 2^11 for about half of VCC + let fault_limit = 60; + dac.set_value(fault_limit); + + let (comp1, ..) = dp.COMP.split(&mut rcc); + + let comp1 = comp1 + .comparator( + &input, + &dac, + comparator::Config::default() + .hysteresis(Hysteresis::None), + //.output_inverted(), + &rcc.clocks, + ) + .enable(); + + let (mut hr_control, _flt_inputs, eev_inputs) = + dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); + + let eev_input4 = eev_inputs + .eev_input4 + .bind(&comp1) + .edge_or_polarity(external_event::EdgeOrPolarity::Polarity( + pwm::Polarity::ActiveHigh, + )) + .finalize(&mut hr_control); + + let mut hr_control = hr_control.constrain(); + + // ...with a prescaler of 4 this gives us a HrTimer with a tick rate of 1.2GHz + // With max the max period set, this would be 1.2GHz/2^16 ~= 18kHz... + let prescaler = Pscl4; + + // . . * . + // . 33% . * . . . + // .-----. .--* . .-----. .----- + //out1 | | | | . | | | + // | | | * . | | | + // ------ ----------- ------------------------------ ----------- + // . . * . . . + // . . * . . . + // . . *-------------* . . + //eev . . | .| . . + // . . | .| . . + // ------------------------- .-------------------------------------- + // . . * . . . + // . . * . . . + let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp + .HRTIM_TIMA + .pwm_advanced(pin_a, &mut rcc) + .prescaler(prescaler) + .eev_cfg(EevCfgs::default()) + .period(0xFFFF) + .finalize(&mut hr_control); + + out1.enable_rst_event(&cr1); // Set low on compare match with cr1 + out1.enable_rst_event(eev_input4); + out1.enable_set_event(&timer); // Set high at new period + cr1.set_duty(timer.get_period() / 3); + //unsafe {((HRTIM_COMMON::ptr() as *mut u8).offset(0x14) as *mut u32).write_volatile(1); } + out1.enable(); + timer.start(&mut hr_control); + + defmt::info!("Started"); + + loop {} +} diff --git a/src/hrtim/control.rs b/src/hrtim/control.rs index bbd02f52..ecf7a6fb 100644 --- a/src/hrtim/control.rs +++ b/src/hrtim/control.rs @@ -2,14 +2,13 @@ use core::marker::PhantomData; use crate::{ hrtim::fault::{ - FaultInput1, FaultInput2, FaultInput3, FaultInput4, FaultInput5, FaultInput6, FltMonitor1, - FltMonitor2, FltMonitor3, FltMonitor4, FltMonitor5, FltMonitor6, FltMonitorSys, + FltMonitor1, FltMonitor2, FltMonitor3, FltMonitor4, FltMonitor5, FltMonitor6, FltMonitorSys, }, rcc::{Enable, Rcc, Reset}, stm32::{HRTIM_COMMON, RCC}, }; -use super::{fault::FaultInputs, external_event::EevInputs}; +use super::{external_event::EevInputs, fault::FaultInputs}; pub trait HrControltExt { fn hr_control(self, _rcc: &mut Rcc) -> HrTimOngoingCalibration; diff --git a/src/hrtim/event.rs b/src/hrtim/event.rs index 245cf255..f0028f5b 100644 --- a/src/hrtim/event.rs +++ b/src/hrtim/event.rs @@ -159,13 +159,18 @@ pub enum EventSource { /// On complete master period MasterPeriod { _x: PhantomData<(PSCL, DST)> }, - ExternalEvent(ExternalEventSource), // This is fine + ExternalEvent(EevFastOrNormal), // This is fine NeighborTimer { n: NeighborTimerEventSource, }, } +pub enum EevFastOrNormal { + Fast(ExternalEventSource), + Normal(ExternalEventSource), +} + /// Compare events from neighbor timers /// /// See RM0440 Table 218. 'Events mapping across timer A to F' diff --git a/src/hrtim/external_event.rs b/src/hrtim/external_event.rs index 9cc24b39..19e61dbf 100644 --- a/src/hrtim/external_event.rs +++ b/src/hrtim/external_event.rs @@ -1,15 +1,17 @@ use core::marker::PhantomData; -use crate::comparator::{self, Comparator, COMP1, COMP2, COMP3, COMP4, COMP5, COMP6, COMP7}; +use crate::comparator::{COMP1, COMP2, COMP3, COMP4, COMP5, COMP6, COMP7}; use crate::gpio::gpiob::{PB3, PB4, PB5, PB6, PB7, PB8, PB9}; use crate::gpio::gpioc::{PC11, PC12, PC5, PC6}; use crate::gpio::{self, AF13, AF3}; use crate::stm32::HRTIM_COMMON; +use crate::pwm::Polarity; +use super::event::EevFastOrNormal; use super::{control::HrTimCalibrated, event::EventSource}; #[derive(Copy, Clone, PartialEq)] -pub enum ExternalEventSource { +pub enum ExternalEventSource { Eevnt1 { _x: PhantomData<()> }, Eevnt2 { _x: PhantomData<()> }, Eevnt3 { _x: PhantomData<()> }, @@ -22,6 +24,18 @@ pub enum ExternalEventSource { Eevnt10 { _x: PhantomData<()> }, } +impl From> for EventSource { + fn from(e: ExternalEventSource) -> Self { + EventSource::ExternalEvent(EevFastOrNormal::Fast(e)) + } +} + +impl From> for EventSource { + fn from(e: ExternalEventSource) -> Self { + EventSource::ExternalEvent(EevFastOrNormal::Normal(e)) + } +} + pub struct EevInputs { pub eev_input1: EevInput<1>, pub eev_input2: EevInput<2>, @@ -56,39 +70,51 @@ pub struct EevInput { _x: PhantomData<()>, } +pub unsafe trait EevSrcBits: Sized { + const SRC_BITS: u8; + fn cfg(self) {} +} + macro_rules! impl_eev_input { - ($N:literal: $compX:ident, PINS=[($pin:ident, $af:ident) $(, ($pin_b:ident, $af_b:ident))*]) => { - impl EevInput<$N> { - pub fn bind_pin(self, pin: $pin>) -> SourceBuilder<$N, IS_FAST> { - pin.into_alternate::<$af>(); - unsafe { SourceBuilder::new(0b00) } + ($N:literal: COMP=[$compX:ident $(, ($compY:ident, $compY_src_bits:literal))*], PINS=[$(($pin:ident, $af:ident)),*]) => { + $(unsafe impl EevSrcBits<$N> for $pin>{ + const SRC_BITS: u8 = 0b00; + fn cfg(self) { + self.into_alternate::<$af>(); } + })* - $( - // TODO: Is there a nicer way to do this? - pub fn bind_pin_b(self, pin: $pin_b>) -> SourceBuilder<$N, IS_FAST> { - pin.into_alternate::<$af_b>(); - unsafe { SourceBuilder::new(0b00) } - } - )* - - pub fn bind_comp(self, _comp: &crate::comparator::Comparator<$compX, crate::comparator::Enabled>) -> SourceBuilder<$N, IS_FAST> { - unsafe { SourceBuilder::new(0b01) } + unsafe impl EevSrcBits<$N> for &crate::comparator::Comparator<$compX, crate::comparator::Enabled> { + const SRC_BITS: u8 = 0b01; + } + + $( + unsafe impl EevSrcBits<$N> for &crate::comparator::Comparator<$compY, crate::comparator::Enabled> { + const SRC_BITS: u8 = $compY_src_bits; + } + )* + + impl EevInput<$N> { + pub fn bind(self, src: SRC) -> SourceBuilder<$N, IS_FAST> + where SRC: EevSrcBits<$N> + { + src.cfg(); + unsafe { SourceBuilder::new(SRC::SRC_BITS) } } } }; } -impl_eev_input!(1: COMP2, PINS=[(PC12, AF3)]); -impl_eev_input!(2: COMP4, PINS=[(PC11, AF3)]); -impl_eev_input!(3: COMP6, PINS=[(PB7, AF13)]); -impl_eev_input!(4: COMP1, PINS=[(PB6, AF13)]); -impl_eev_input!(5: COMP3, PINS=[(PB9, AF13)]); -impl_eev_input!(6: COMP2, PINS=[(PB5, AF13)]); -impl_eev_input!(7: COMP4, PINS=[(PB4, AF13)]); -impl_eev_input!(8: COMP6, PINS=[(PB8, AF13)]); -impl_eev_input!(9: COMP5, PINS=[(PB3, AF13)]); -impl_eev_input!(10: COMP7, PINS=[(PC5, AF13), (PC6, AF3)]); +impl_eev_input!(1: COMP=[COMP2], PINS=[(PC12, AF3)]); +impl_eev_input!(2: COMP=[COMP4], PINS=[(PC11, AF3)]); +impl_eev_input!(3: COMP=[COMP6], PINS=[(PB7, AF13)]); +impl_eev_input!(4: COMP=[COMP1, (COMP5, 0b10)], PINS=[(PB6, AF13)]); +impl_eev_input!(5: COMP=[COMP3, (COMP7, 0b10)], PINS=[(PB9, AF13)]); +impl_eev_input!(6: COMP=[COMP2, (COMP1, 0b10)], PINS=[(PB5, AF13)]); +impl_eev_input!(7: COMP=[COMP4], PINS=[(PB4, AF13)]); +impl_eev_input!(8: COMP=[COMP6, (COMP3, 0b10)], PINS=[(PB8, AF13)]); +impl_eev_input!(9: COMP=[COMP5, (COMP4, 0b11)], PINS=[(PB3, AF13)]); +impl_eev_input!(10: COMP=[COMP7], PINS=[(PC5, AF13), (PC6, AF3)]); pub enum EdgeOrPolarity { Edge(Edge), @@ -101,10 +127,6 @@ pub enum Edge { Both = 0b11, } -pub enum Polarity { - ActiveHigh, - ActiveLow, -} pub enum EevSamplingFilter { /// No filtering, fault acts asynchronously @@ -227,8 +249,8 @@ where } } -pub trait ToExternalEventSource { - fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource; +pub trait ToExternalEventSource { + fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource; } #[derive(Copy, Clone)] @@ -240,8 +262,26 @@ macro_rules! impl_eev1_5_to_es { ($eev:ident, $N:literal, $eeXsrc:ident, $eeXpol:ident, $eeXsns:ident, $eeXfast:ident) => { impl ExternalEventBuilder1To5 for SourceBuilder<$N, IS_FAST> {} - impl ToExternalEventSource for SourceBuilder<$N, IS_FAST> { - fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource { + impl SourceBuilder<$N, false> { + pub fn fast(self) -> SourceBuilder<$N, true> { + let SourceBuilder { + src_bits, + edge_or_polarity_bits, + polarity_bit, + filter_bits, + } = self; + + SourceBuilder { + src_bits, + edge_or_polarity_bits, + polarity_bit, + filter_bits, + } + } + } + + impl ToExternalEventSource for SourceBuilder<$N, IS_FAST> { + fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource { let SourceBuilder { src_bits, edge_or_polarity_bits, @@ -276,8 +316,8 @@ macro_rules! impl_eev6_10_to_es { ($eev:ident, $N:literal, $eeXsrc:ident, $eeXpol:ident, $eeXsns:ident, $eeXf:ident) => { impl ExternalEventBuilder6To10 for SourceBuilder<$N, false> {} - impl ToExternalEventSource for SourceBuilder<$N, false> { - fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource { + impl ToExternalEventSource for SourceBuilder<$N, false> { + fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource { let SourceBuilder { src_bits, edge_or_polarity_bits, diff --git a/src/hrtim/mod.rs b/src/hrtim/mod.rs index 369d664f..fcf9c45a 100644 --- a/src/hrtim/mod.rs +++ b/src/hrtim/mod.rs @@ -24,6 +24,7 @@ use self::control::HrPwmControl; use self::deadtime::DeadtimeConfig; use self::output::{HrtimChannel, ToHrOut, CH1, CH2}; +use self::timer_eev_cfg::EevCfgs; use crate::pwm::{ self, Alignment, ComplementaryImpossible, Pins, Polarity, Pwm, PwmPinEnable, TimerType, @@ -196,7 +197,7 @@ pub struct HrPwmBuilder { repetition_counter: u8, deadtime: Option, enable_repetition_interrupt: bool, - eev_cfg: EevCfg, + eev_cfg: EevCfgs, out1_polarity: Polarity, out2_polarity: Polarity, } @@ -219,7 +220,8 @@ pub enum MasterPreloadSource { macro_rules! hrtim_finalize_body { ($this:expr, $PreloadSource:ident, $TIMX:ident: ( - $timXcr:ident, $ck_psc:ident, $perXr:ident, $perx:ident, $tXcen:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident $(, $timXcr2:ident, $fltXr:ident, $outXr:ident, $dtXr:ident)*), + $timXcr:ident, $ck_psc:ident, $perXr:ident, $perx:ident, $tXcen:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident + $(, $timXcr2:ident, $fltXr:ident, $eefXr1:ident, $eefXr2:ident, $Xeefr3:ident, $outXr:ident, $dtXr:ident)*), ) => {{ let tim = unsafe { &*$TIMX::ptr() }; let (period, prescaler_bits) = match $this.count { @@ -323,6 +325,31 @@ macro_rules! hrtim_finalize_body { ); tim.$outXr.modify(|_r, w| w.dten().set_bit()); } + + // External event configs + let eev_cfg = $this.eev_cfg.clone(); + tim.$eefXr1.write(|w| w + .ee1ltch().bit(eev_cfg.eev1.latch_bit).ee1fltr().bits(eev_cfg.eev1.filter_bits) + .ee2ltch().bit(eev_cfg.eev2.latch_bit).ee2fltr().bits(eev_cfg.eev2.filter_bits) + .ee3ltch().bit(eev_cfg.eev3.latch_bit).ee3fltr().bits(eev_cfg.eev3.filter_bits) + .ee4ltch().bit(eev_cfg.eev4.latch_bit).ee4fltr().bits(eev_cfg.eev4.filter_bits) + .ee5ltch().bit(eev_cfg.eev5.latch_bit).ee5fltr().bits(eev_cfg.eev5.filter_bits) + ); + tim.$eefXr2.write(|w| w + .ee6ltch().bit(eev_cfg.eev6.latch_bit).ee6fltr().bits(eev_cfg.eev6.filter_bits) + .ee7ltch().bit(eev_cfg.eev7.latch_bit).ee7fltr().bits(eev_cfg.eev7.filter_bits) + .ee8ltch().bit(eev_cfg.eev8.latch_bit).ee8fltr().bits(eev_cfg.eev8.filter_bits) + .ee9ltch().bit(eev_cfg.eev9.latch_bit).ee9fltr().bits(eev_cfg.eev9.filter_bits) + .ee10ltch().bit(eev_cfg.eev10.latch_bit).ee10fltr().bits(eev_cfg.eev10.filter_bits) + ); + tim.$Xeefr3.write(|w| w + .eevace().bit(eev_cfg.event_counter_enable_bit) + // External Event A Counter Reset"] + //.eevacres().bit() + .eevarstm().bit(eev_cfg.event_counter_reset_mode_bit) + .eevasel().bits(eev_cfg.event_counter_source_bits) + .eevacnt().bits(eev_cfg.event_counter_threshold_bits) + ); })* @@ -452,21 +479,18 @@ macro_rules! hrtim_common_methods { 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 } @@ -474,19 +498,16 @@ macro_rules! hrtim_common_methods { /// 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 } - pub fn eev_cfg(mut self, eev_cfg: Stuff) -> Self { + pub fn eev_cfg(mut self, eev_cfg: EevCfgs<$TIMX>) -> Self { self.eev_cfg = eev_cfg; - self } }; @@ -494,7 +515,8 @@ macro_rules! hrtim_common_methods { // Implement PWM configuration for timer macro_rules! hrtim_hal { - ($($TIMX:ident: ($timXcr:ident, $timXcr2:ident, $perXr:ident, $tXcen:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident, $fltXr:ident, $outXr:ident, $dtXr:ident),)+) => { + ($($TIMX:ident: ($timXcr:ident, $timXcr2:ident, $perXr:ident, $tXcen:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident, + $fltXr:ident, $eefXr1:ident, $eefXr2:ident, $Xeefr3:ident, $outXr:ident, $dtXr:ident),)+) => { $( // Implement HrPwmExt trait for hrtimer @@ -551,6 +573,7 @@ macro_rules! hrtim_hal { repetition_counter: 0, deadtime: None, enable_repetition_interrupt: false, + eev_cfg: EevCfgs::default(), out1_polarity: Polarity::ActiveHigh, out2_polarity: Polarity::ActiveHigh, } @@ -566,7 +589,7 @@ macro_rules! hrtim_hal { pub fn finalize(self, _control: &mut HrPwmControl) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX, PSCL>, HrCr2<$TIMX, PSCL>, HrCr3<$TIMX, PSCL>, HrCr4<$TIMX, PSCL>), OUT) { hrtim_finalize_body!( self, PreloadSource, - $TIMX: ($timXcr, ck_pscx, $perXr, perx, $tXcen, $rep, $repx, $dier, $repie, $timXcr2, $fltXr, $outXr, $dtXr), + $TIMX: ($timXcr, ck_pscx, $perXr, perx, $tXcen, $rep, $repx, $dier, $repie, $timXcr2, $fltXr, $eefXr1, $eefXr2, $Xeefr3, $outXr, $dtXr), ) } @@ -694,6 +717,7 @@ macro_rules! hrtim_hal_master { repetition_counter: 0, deadtime: None, enable_repetition_interrupt: false, + eev_cfg: EevCfgs::default(), out1_polarity: Polarity::ActiveHigh, out2_polarity: Polarity::ActiveHigh, } @@ -807,12 +831,12 @@ macro_rules! hrtim_pin_hal { } hrtim_hal! { - HRTIM_TIMA: (timacr, timacr2, perar, tacen, repar, repx, timadier, repie, fltar, outar, dtar), - HRTIM_TIMB: (timbcr, timbcr2, perbr, tbcen, repbr, repx, timbdier, repie, fltbr, outbr, dtbr), - HRTIM_TIMC: (timccr, timccr2, percr, tccen, repcr, repx, timcdier, repie, fltcr, outcr, dtcr), - HRTIM_TIMD: (timdcr, timdcr2, perdr, tdcen, repdr, repx, timddier, repie, fltdr, outdr, dtdr), - HRTIM_TIME: (timecr, timecr2, perer, tecen, reper, repx, timedier, repie, flter, outer, dter), - HRTIM_TIMF: (timfcr, timfcr2, perfr, tfcen, repfr, repx, timfdier, repie, fltfr, outfr, dtfr), + HRTIM_TIMA: (timacr, timacr2, perar, tacen, repar, repx, timadier, repie, fltar, eefar1, eefar2, aeefr3, outar, dtar), + HRTIM_TIMB: (timbcr, timbcr2, perbr, tbcen, repbr, repx, timbdier, repie, fltbr, eefbr1, eefbr2, beefr3, outbr, dtbr), + HRTIM_TIMC: (timccr, timccr2, percr, tccen, repcr, repx, timcdier, repie, fltcr, eefcr1, eefcr2, ceefr3, outcr, dtcr), + HRTIM_TIMD: (timdcr, timdcr2, perdr, tdcen, repdr, repx, timddier, repie, fltdr, eefdr1, eefdr2, deefr3, outdr, dtdr), + HRTIM_TIME: (timecr, timecr2, perer, tecen, reper, repx, timedier, repie, flter, eefer1, eefer2, eeefr3, outer, dter), + HRTIM_TIMF: (timfcr, timfcr2, perfr, tfcen, repfr, repx, timfdier, repie, fltfr, eeffr1, eeffr2, feefr3, outfr, dtfr), } hrtim_hal_master! { diff --git a/src/hrtim/output.rs b/src/hrtim/output.rs index d2e9854f..a459fd92 100644 --- a/src/hrtim/output.rs +++ b/src/hrtim/output.rs @@ -4,7 +4,7 @@ use stm32g4::stm32g474::{ }; use crate::hrtim::external_event::ExternalEventSource; -use super::event::{EventSource, NeighborTimerEventSource}; +use super::event::{EventSource, NeighborTimerEventSource, EevFastOrNormal}; use crate::{ gpio::{ gpioa::{PA10, PA11, PA8, PA9}, @@ -17,6 +17,41 @@ use crate::{ }; macro_rules! hrtim_out_common { + ($e:ident, $register:expr, $action:ident) => { + match $e { + ExternalEventSource::Eevnt1 { .. } => { + $register.modify(|_r, w| w.extevnt1().$action()) + }, + ExternalEventSource::Eevnt2 { .. } => { + $register.modify(|_r, w| w.extevnt2().$action()) + }, + ExternalEventSource::Eevnt3 { .. } => { + $register.modify(|_r, w| w.extevnt3().$action()) + }, + ExternalEventSource::Eevnt4 { .. } => { + $register.modify(|_r, w| w.extevnt4().$action()) + }, + ExternalEventSource::Eevnt5 { .. } => { + $register.modify(|_r, w| w.extevnt5().$action()) + }, + ExternalEventSource::Eevnt6 { .. } => { + $register.modify(|_r, w| w.extevnt6().$action()) + }, + ExternalEventSource::Eevnt7 { .. } => { + $register.modify(|_r, w| w.extevnt7().$action()) + }, + ExternalEventSource::Eevnt8 { .. } => { + $register.modify(|_r, w| w.extevnt8().$action()) + }, + ExternalEventSource::Eevnt9 { .. } => { + $register.modify(|_r, w| w.extevnt9().$action()) + }, + ExternalEventSource::Eevnt10 { .. } => { + $register.modify(|_r, w| w.extevnt10().$action()) + }, + } + }; + ($TIMX:ident, $set_event:expr, $register:ident, $action:ident) => {{ let tim = unsafe { &*$TIMX::ptr() }; @@ -33,38 +68,8 @@ macro_rules! hrtim_out_common { EventSource::MasterCr4 { .. } => tim.$register.modify(|_r, w| w.mstcmp4().$action()), EventSource::MasterPeriod { .. } => tim.$register.modify(|_r, w| w.mstper().$action()), - EventSource::ExternalEvent(e) => match e { - ExternalEventSource::Eevnt1 { .. } => { - tim.$register.modify(|_r, w| w.extevnt1().$action()) - }, - ExternalEventSource::Eevnt2 { .. } => { - tim.$register.modify(|_r, w| w.extevnt2().$action()) - }, - ExternalEventSource::Eevnt3 { .. } => { - tim.$register.modify(|_r, w| w.extevnt3().$action()) - }, - ExternalEventSource::Eevnt4 { .. } => { - tim.$register.modify(|_r, w| w.extevnt4().$action()) - }, - ExternalEventSource::Eevnt5 { .. } => { - tim.$register.modify(|_r, w| w.extevnt5().$action()) - }, - ExternalEventSource::Eevnt6 { .. } => { - tim.$register.modify(|_r, w| w.extevnt6().$action()) - }, - ExternalEventSource::Eevnt7 { .. } => { - tim.$register.modify(|_r, w| w.extevnt7().$action()) - }, - ExternalEventSource::Eevnt8 { .. } => { - tim.$register.modify(|_r, w| w.extevnt8().$action()) - }, - ExternalEventSource::Eevnt9 { .. } => { - tim.$register.modify(|_r, w| w.extevnt9().$action()) - }, - ExternalEventSource::Eevnt10 { .. } => { - tim.$register.modify(|_r, w| w.extevnt10().$action()) - }, - } + EventSource::ExternalEvent(EevFastOrNormal::Fast(e)) => hrtim_out_common!(e, tim.$register, $action), + EventSource::ExternalEvent(EevFastOrNormal::Normal(e)) => hrtim_out_common!(e, tim.$register, $action), EventSource::NeighborTimer { n } => match n { NeighborTimerEventSource::TimEvent1 { .. } => { diff --git a/src/hrtim/timer_eev_cfg.rs b/src/hrtim/timer_eev_cfg.rs index ffc9213c..9ed8f55b 100644 --- a/src/hrtim/timer_eev_cfg.rs +++ b/src/hrtim/timer_eev_cfg.rs @@ -1,32 +1,72 @@ use core::marker::PhantomData; -struct EevCfgs { - eev1: EevCfg, - eev2: EevCfg, - eev3: EevCfg, - eev4: EevCfg, - eev5: EevCfg, - eev6: EevCfg, - eev7: EevCfg, - eev8: EevCfg, - eev9: EevCfg, - eev10: EevCfg, +pub struct EevCfgs { + pub eev1: EevCfg, + pub eev2: EevCfg, + pub eev3: EevCfg, + pub eev4: EevCfg, + pub eev5: EevCfg, + pub eev6: EevCfg, + pub eev7: EevCfg, + pub eev8: EevCfg, + pub eev9: EevCfg, + pub eev10: EevCfg, + + // TODO: Expose these + // TODO: Note there are some peculiarities here with fast mode + // One way to prevent missuse would be to require a borrowed ExternalEventSource when setting + // filter/latching as well as the event_counter related settings below. + pub(crate) event_counter_enable_bit: bool, + pub(crate) event_counter_reset_mode_bit: bool, + pub(crate) event_counter_source_bits: u8, + pub(crate) event_counter_threshold_bits: u8, +} + +impl Clone for EevCfgs { + fn clone(&self) -> Self { + Self { + eev1: self.eev1.clone(), + eev2: self.eev2.clone(), + eev3: self.eev3.clone(), + eev4: self.eev4.clone(), + eev5: self.eev5.clone(), + eev6: self.eev6.clone(), + eev7: self.eev7.clone(), + eev8: self.eev8.clone(), + eev9: self.eev9.clone(), + eev10: self.eev10.clone(), + event_counter_enable_bit: self.event_counter_enable_bit.clone(), + event_counter_reset_mode_bit: self.event_counter_reset_mode_bit.clone(), + event_counter_source_bits: self.event_counter_source_bits.clone(), + event_counter_threshold_bits: self.event_counter_threshold_bits.clone(), + } + } } -#[derive(Default)] -struct EevCfg { +pub struct EevCfg { _x: PhantomData, - filter_bits: u8, - latch_bit: u8, + pub(crate) filter_bits: u8, + pub(crate) latch_bit: bool, +} + +impl Clone for EevCfg { + fn clone(&self) -> Self { + Self { + _x: PhantomData, + filter_bits: self.filter_bits.clone(), + latch_bit: self.latch_bit.clone(), + } + } } impl EevCfg { - pub fn filter(mut self, stuff: u8) { - self.filter_bits = stuff; + /// NOTE: This can not be set if eev is in fast mode AND using `EevCfg::latching` + pub fn filter(mut self, filter: EventFilter) -> Self { + self.filter_bits = filter as u8; self } - /// NOTE: This can not be set if eev is in fast mode AND using a + /// NOTE: This can not be set if eev is in fast mode AND using a `EevCfg::filter` pub fn latching(mut self) -> Self { self.latch_bit = true; self @@ -35,11 +75,12 @@ impl EevCfg { /// Note: Whenever a compare register is used for filtering, the value must be strictly above 0. pub enum EventFilter { + /// No filtering None = 0b0000, - + /// Blanking from reset/rollover to Cmp1 BlankingResetToCmp1 = 0b0001, - + /// This depends on counter mode: /// * Up-counting mode: Blanking from reset/rollover to Cmp2 /// * Up-down mode: Blanking from Cmp1 to Cmp2(only during up counting) @@ -53,13 +94,28 @@ pub enum EventFilter { /// * Up-down mode: Blanking from Cmp3 to Cmp4(only during up counting) BlankingResetToCmp4OrCmp3ToCmp4InUdm = 0b0100, + /// (RM 0440 table 226 'Filtering signals mapping per timer') BlankingSource1 = 0b0101, + + /// (RM 0440 table 226 'Filtering signals mapping per timer') BlankingSource2 = 0b0110, + + /// (RM 0440 table 226 'Filtering signals mapping per timer') BlankingSource3 = 0b0111, + + /// (RM 0440 table 226 'Filtering signals mapping per timer') BlankingSource4 = 0b1000, + + /// (RM 0440 table 226 'Filtering signals mapping per timer') BlankingSource5 = 0b1001, + + /// (RM 0440 table 226 'Filtering signals mapping per timer') BlankingSource6 = 0b1010, + + /// (RM 0440 table 226 'Filtering signals mapping per timer') BlankingSource7 = 0b1011, + + /// (RM 0440 table 226 'Filtering signals mapping per timer') BlankingSource8 = 0b1100, /// This depends on counter mode: @@ -72,8 +128,45 @@ pub enum EventFilter { /// * Up-down mode: Windowing from Cmp2 to Cmp3(only during down counting) WindowingResetToCmp3OrCmp2ToCmp3InUdm = 0b1110, - Windowing from another timing unit: TIMWIN source (see Table 227 for details) in upcounting mode (UDM bit reset) -In up-down counting mode (UDM bit set): windowing from compare 2 during the up-counting -phase to compare 3 during the down-counting phase. - Windowing -} \ No newline at end of file + /// This depends on counter mode: + /// * Up-counting mode: Windowing from reset/rollover to other timer `TIMWIN`'s Cmp2 event + /// * Up-down mode: Windowing from other timer `TIMWIN`'s Cmp2 during up counting to Cmp3 during down counting + /// + /// `TIMWIN` (RM 0440 table 227 'Windowing signals mapping per timer'): + /// + /// | Destination |`TIMA`|`TIMB`|`TIMC`|`TIMD`|`TIME`|`TIMF`| + /// |-------------|------|------|------|------|------|------| + /// | TIMWIN |`TIMB`|`TIMA`|`TIMD`|`TIMC`|`TIMF`|`TIME`| + WindowingResetToOtherCmp2OrCmp2UpToCmp3DownInUdm = 0b1111, +} + +impl Default for EevCfg { + fn default() -> Self { + Self { + _x: PhantomData, + filter_bits: EventFilter::None as u8, + latch_bit: false, + } + } +} + +impl Default for EevCfgs { + fn default() -> Self { + Self { + eev1: EevCfg::default(), + eev2: Default::default(), + eev3: Default::default(), + eev4: Default::default(), + eev5: Default::default(), + eev6: Default::default(), + eev7: Default::default(), + eev8: Default::default(), + eev9: Default::default(), + eev10: Default::default(), + event_counter_enable_bit: false, + event_counter_reset_mode_bit: false, + event_counter_source_bits: 0, + event_counter_threshold_bits: 0, + } + } +} From 2053ecdece8e4b807cd7fc62c215020476319f2f Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 8 Nov 2023 18:09:40 +0100 Subject: [PATCH 42/88] Update hrtim examples. TODO: Make sure timers are started --- .../adc-trigger.rs} | 70 +++++++++----- .../{hrtim_eev_comp.rs => hrtim/eev-comp.rs} | 59 ++++++------ examples/{hrtim_eev.rs => hrtim/eev.rs} | 24 ++--- .../{hrtim_flt_comp.rs => hrtim/flt-comp.rs} | 53 ++++++----- examples/{hrtim_flt.rs => hrtim/flt.rs} | 50 +++++----- examples/{ => hrtim}/hrtim.rs | 48 +++++----- examples/{hrtim-master.rs => hrtim/master.rs} | 93 +++++++++++-------- examples/{hrtim_simple.rs => hrtim/simple.rs} | 33 ++++--- src/hrtim/deadtime.rs | 2 +- src/hrtim/event.rs | 47 +++++++--- src/hrtim/external_event.rs | 19 ++-- src/hrtim/mod.rs | 2 +- src/hrtim/output.rs | 50 ++++------ src/hrtim/timer_eev_cfg.rs | 22 +++++ 14 files changed, 330 insertions(+), 242 deletions(-) rename examples/{hrtim-adc-trigger.rs => hrtim/adc-trigger.rs} (58%) rename examples/{hrtim_eev_comp.rs => hrtim/eev-comp.rs} (80%) rename examples/{hrtim_eev.rs => hrtim/eev.rs} (86%) rename examples/{hrtim_flt_comp.rs => hrtim/flt-comp.rs} (79%) rename examples/{hrtim_flt.rs => hrtim/flt.rs} (76%) rename examples/{ => hrtim}/hrtim.rs (75%) rename examples/{hrtim-master.rs => hrtim/master.rs} (60%) rename examples/{hrtim_simple.rs => hrtim/simple.rs} (74%) diff --git a/examples/hrtim-adc-trigger.rs b/examples/hrtim/adc-trigger.rs similarity index 58% rename from examples/hrtim-adc-trigger.rs rename to examples/hrtim/adc-trigger.rs index 9c9f0eb8..45134bc5 100644 --- a/examples/hrtim-adc-trigger.rs +++ b/examples/hrtim/adc-trigger.rs @@ -10,34 +10,51 @@ use crate::hal::{ AdcClaim, ClockSource, Temperature, Vref, }, delay::SYSTDelayExt, - dma::{config::DmaConfig, stream::DMAExt, TransferExt}, - gpio::GpioExt, - rcc::{Config, RccExt}, + dma::{self, config::DmaConfig, stream::DMAExt, TransferExt}, + gpio::{gpioa::PA8, gpioa::PA9, Alternate, GpioExt, AF13}, + hrtim::control::HrControltExt, + hrtim::output::HrOutput, + hrtim::HrPwmAdvExt, + hrtim::{control::Adc13Trigger, Pscl4}, + pwr::PwrExt, + rcc::{self, RccExt}, stm32::Peripherals, }; use stm32g4xx_hal as hal; -use log::info; +use defmt::info; -#[macro_use] -mod utils; +use defmt_rtt as _; // global logger +use panic_probe as _; #[entry] fn main() -> ! { - utils::logger::init(); - info!("start"); let dp = Peripherals::take().unwrap(); let cp = cortex_m::Peripherals::take().expect("cannot take core peripherals"); + // Set system frequency to 16MHz * 15/1/2 = 120MHz + // This would lead to HrTim running at 120MHz * 32 = 3.84... info!("rcc"); - let rcc = dp.RCC.constrain(); - let mut rcc = rcc.freeze(Config::hsi()); + let pwr = dp.PWR.constrain().freeze(); + let mut rcc = dp.RCC.freeze( + rcc::Config::pll().pll_cfg(rcc::PllConfig { + mux: rcc::PLLSrc::HSI, + n: rcc::PllNMul::MUL_15, + m: rcc::PllMDiv::DIV_1, + r: Some(rcc::PllRDiv::DIV_2), + + ..Default::default() + }), + pwr, + ); + + let mut delay = cp.SYST.delay(&rcc.clocks); - let streams = dp.DMA1.split(&rcc); + let dma::stream::StreamsTuple(dma1ch1, ..) = dp.DMA1.split(&rcc); let config = DmaConfig::default() - .transfer_complete_interrupt(false) + .transfer_complete_interrupt(true) .circular_buffer(true) .memory_increment(true); @@ -46,7 +63,6 @@ fn main() -> ! { let pa0 = gpioa.pa0.into_analog(); info!("Setup Adc1"); - let mut delay = cp.SYST.delay(&rcc.clocks); let mut adc = dp .ADC1 .claim(ClockSource::SystemClock, &rcc, &mut delay, true); @@ -63,7 +79,8 @@ fn main() -> ! { info!("Setup DMA"); let first_buffer = cortex_m::singleton!(: [u16; 10] = [0; 10]).unwrap(); - let mut transfer = streams.0.into_circ_peripheral_to_memory_transfer( + + let mut transfer = dma1ch1.into_circ_peripheral_to_memory_transfer( adc.enable_dma(AdcDma::Continuous), &mut first_buffer[..], config, @@ -71,18 +88,27 @@ fn main() -> ! { transfer.start(|adc| adc.start_conversion()); + let pin_a: PA8> = gpioa.pa8.into_alternate(); + let pin_b: PA9> = gpioa.pa9.into_alternate(); + + // ...with a prescaler of 4 this gives us a HrTimer with a tick rate of 960MHz + // With max the max period set, this would be 960MHz/2^16 ~= 15kHz... + let prescaler = Pscl4; + // . . // . 50% . // ------ ------ //out1 | | | | // | | | | // -------- ---------- -------- - let (mut fault_control, _) = dp + let (hr_control, ..) = dp .HRTIM_COMMON .hr_control(&mut rcc) - .set_adc_trigger1(Adc13Trigger::) + .enable_adc_trigger1_source(Adc13Trigger::TimACmp3) + .enable_adc_trigger1_source(Adc13Trigger::TimACmp4) .wait_for_calibration(); - let (mut timer, (mut cr1, _cr2, _cr3, _cr4), (mut out1, mut out2)) = dp + let mut hr_control = hr_control.constrain(); + let (timer, (cr1, _cr2, _cr3, _cr4), (mut out1, mut out2)) = dp .HRTIM_TIMA .pwm_advanced((pin_a, pin_b), &mut rcc) .prescaler(prescaler) @@ -90,13 +116,13 @@ fn main() -> ! { // alternated every period with one being // inactive and the other getting to output its wave form // as normal - .finalize(&mut fault_control); + .finalize(&mut hr_control); - out1.enable_rst_event(EventSource::Cr1); // Set low on compare match with cr1 - out2.enable_rst_event(EventSource::Cr1); + out1.enable_rst_event(&cr1); // Set low on compare match with cr1 + out2.enable_rst_event(&cr1); - out1.enable_set_event(EventSource::Period); // Set high at new period - out2.enable_set_event(EventSource::Period); + out1.enable_set_event(&timer); // Set high at new period + out2.enable_set_event(&timer); out1.enable(); out2.enable(); diff --git a/examples/hrtim_eev_comp.rs b/examples/hrtim/eev-comp.rs similarity index 80% rename from examples/hrtim_eev_comp.rs rename to examples/hrtim/eev-comp.rs index 2776b897..15f69f71 100644 --- a/examples/hrtim_eev_comp.rs +++ b/examples/hrtim/eev-comp.rs @@ -3,24 +3,23 @@ #![no_std] use cortex_m_rt::entry; -use fugit::ExtU32; use hal::comparator; -use hal::comparator::{Hysteresis, ComparatorSplit, ComparatorExt}; +use hal::comparator::{ComparatorExt, ComparatorSplit, Hysteresis}; use hal::dac::{self, DacExt, DacOut}; use hal::gpio::gpioa::PA8; use hal::gpio::Alternate; +use hal::gpio::SignalEdge; use hal::gpio::AF13; use hal::hrtim::compare_register::HrCompareRegister; -use hal::hrtim::event::EventSource; use hal::hrtim::external_event::{self, ToExternalEventSource}; -use hal::hrtim::timer_eev_cfg::EevCfgs; use hal::hrtim::timer::HrTimer; +use hal::hrtim::timer_eev_cfg::{EevCfg, EevCfgs}; use hal::hrtim::HrPwmAdvExt; use hal::hrtim::Pscl4; use hal::hrtim::{control::HrControltExt, output::HrOutput}; use hal::prelude::*; use hal::pwm; -use hal::pwr::{self, PwrExt}; +use hal::pwr::PwrExt; use hal::rcc; use hal::stm32; use stm32g4xx_hal as hal; @@ -34,13 +33,7 @@ fn main() -> ! { let cp = stm32::CorePeripherals::take().expect("cannot take core"); // Set system frequency to 16MHz * 75/4/2 = 150MHz // This would lead to HrTim running at 150MHz * 32 = 4.8GHz... - let pwr = dp - .PWR - .constrain() - .vos(pwr::VoltageScale::Range1 { - enable_boost: false, - }) - .freeze(); + let pwr = dp.PWR.constrain().freeze(); let mut rcc = dp.RCC.freeze( rcc::Config::pll().pll_cfg(rcc::PllConfig { @@ -53,34 +46,34 @@ fn main() -> ! { pwr, ); + let exti = dp.EXTI; + let mut delay = cp.SYST.delay(&rcc.clocks); let gpioa = dp.GPIOA.split(&mut rcc); - let gpiob = dp.GPIOB.split(&mut rcc); let input = gpioa.pa1.into_analog(); let pin_a: PA8> = gpioa.pa8.into_alternate(); - let dac3ch1 = dp.DAC3.constrain(dac::Dac3IntSig1, &mut rcc); - let mut dac = dac3ch1.enable(); + let dac1ch1 = dp.DAC1.constrain(dac::Dac1IntSig1, &mut rcc); + let mut dac = dac1ch1.calibrate_buffer(&mut delay).enable(); // Use dac to define the fault threshold // 2^12 / 2 = 2^11 for about half of VCC - let fault_limit = 60; - dac.set_value(fault_limit); + let limit = 1 << 11; + dac.set_value(limit); let (comp1, ..) = dp.COMP.split(&mut rcc); - let comp1 = comp1 - .comparator( - &input, - &dac, - comparator::Config::default() - .hysteresis(Hysteresis::None), - //.output_inverted(), - &rcc.clocks, - ) - .enable(); + let comp1 = comp1.comparator( + &input, + &dac, + comparator::Config::default().hysteresis(Hysteresis::None), + //.output_inverted(), + &rcc.clocks, + ); + comp1.listen(SignalEdge::Rising, &exti); + let comp1 = comp1.enable().lock(); let (mut hr_control, _flt_inputs, eev_inputs) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); @@ -117,7 +110,7 @@ fn main() -> ! { .HRTIM_TIMA .pwm_advanced(pin_a, &mut rcc) .prescaler(prescaler) - .eev_cfg(EevCfgs::default()) + .eev_cfg(EevCfgs::default().eev4(EevCfg::default())) .period(0xFFFF) .finalize(&mut hr_control); @@ -125,11 +118,17 @@ fn main() -> ! { out1.enable_rst_event(eev_input4); out1.enable_set_event(&timer); // Set high at new period cr1.set_duty(timer.get_period() / 3); - //unsafe {((HRTIM_COMMON::ptr() as *mut u8).offset(0x14) as *mut u32).write_volatile(1); } + out1.enable(); timer.start(&mut hr_control); defmt::info!("Started"); - loop {} + loop { + defmt::info!( + "Comp: {}, pending: {}", + comp1.output(), + comp1.is_pending(&exti) + ); + } } diff --git a/examples/hrtim_eev.rs b/examples/hrtim/eev.rs similarity index 86% rename from examples/hrtim_eev.rs rename to examples/hrtim/eev.rs index 0ad29263..281fa7c1 100644 --- a/examples/hrtim_eev.rs +++ b/examples/hrtim/eev.rs @@ -3,21 +3,20 @@ #![no_std] use cortex_m_rt::entry; -use fugit::ExtU32; use hal::gpio::gpioa::PA8; use hal::gpio::Alternate; use hal::gpio::AF13; use hal::hrtim::compare_register::HrCompareRegister; -use hal::hrtim::event::EventSource; -use hal::hrtim::external_event::{self, ToExternalEventSource}; -use hal::hrtim::timer_eev_cfg::EevCfgs; +use hal::hrtim::external_event; +use hal::hrtim::external_event::ToExternalEventSource; use hal::hrtim::timer::HrTimer; +use hal::hrtim::timer_eev_cfg::EevCfgs; use hal::hrtim::HrPwmAdvExt; use hal::hrtim::Pscl4; use hal::hrtim::{control::HrControltExt, output::HrOutput}; use hal::prelude::*; use hal::pwm; -use hal::pwr::{self, PwrExt}; +use hal::pwr::PwrExt; use hal::rcc; use hal::stm32; use stm32g4xx_hal as hal; @@ -29,16 +28,9 @@ use panic_probe as _; #[entry] fn main() -> ! { let dp = stm32::Peripherals::take().expect("cannot take peripherals"); - let cp = stm32::CorePeripherals::take().expect("cannot take core"); // Set system frequency to 16MHz * 75/4/2 = 150MHz // This would lead to HrTim running at 150MHz * 32 = 4.8GHz... - let pwr = dp - .PWR - .constrain() - .vos(pwr::VoltageScale::Range1 { - enable_boost: false, - }) - .freeze(); + let pwr = dp.PWR.constrain().freeze(); let mut rcc = dp.RCC.freeze( rcc::Config::pll().pll_cfg(rcc::PllConfig { @@ -51,8 +43,6 @@ fn main() -> ! { pwr, ); - let mut delay = cp.SYST.delay(&rcc.clocks); - let gpioa = dp.GPIOA.split(&mut rcc); let gpiob = dp.GPIOB.split(&mut rcc); @@ -61,7 +51,7 @@ fn main() -> ! { let eev_input3 = eev_inputs .eev_input3 - .bind_pin(gpiob.pb7.into_pull_down_input()) + .bind(gpiob.pb7.into_pull_down_input()) .edge_or_polarity(external_event::EdgeOrPolarity::Polarity( pwm::Polarity::ActiveHigh, )) @@ -101,7 +91,7 @@ fn main() -> ! { out1.enable_rst_event(eev_input3); out1.enable_set_event(&timer); // Set high at new period cr1.set_duty(timer.get_period() / 3); - //unsafe {((HRTIM_COMMON::ptr() as *mut u8).offset(0x14) as *mut u32).write_volatile(1); } + out1.enable(); timer.start(&mut hr_control); diff --git a/examples/hrtim_flt_comp.rs b/examples/hrtim/flt-comp.rs similarity index 79% rename from examples/hrtim_flt_comp.rs rename to examples/hrtim/flt-comp.rs index 2809639a..cea854af 100644 --- a/examples/hrtim_flt_comp.rs +++ b/examples/hrtim/flt-comp.rs @@ -3,24 +3,23 @@ #![no_std] use cortex_m_rt::entry; -use fugit::ExtU32; -use hal::comparator::{ComparatorExt, ComparatorSplit, Config, Hysteresis, RefintInput}; +use hal::comparator::{ComparatorExt, ComparatorSplit, Config, Hysteresis}; use hal::dac::{Dac3IntSig1, DacExt, DacOut}; use hal::gpio::gpioa::PA8; use hal::gpio::Alternate; use hal::gpio::AF13; +use hal::hrtim::compare_register::HrCompareRegister; +use hal::hrtim::fault::FaultAction; +use hal::hrtim::timer::HrTimer; +use hal::hrtim::HrPwmAdvExt; +use hal::hrtim::Pscl4; +use hal::hrtim::{control::HrControltExt, output::HrOutput}; use hal::prelude::*; -use hal::pwm::hrtim::EventSource; -use hal::pwm::hrtim::FaultAction; -use hal::pwm::hrtim::HrCompareRegister; -use hal::pwm::hrtim::HrPwmAdvExt; -use hal::pwm::hrtim::HrTimer; -use hal::pwm::hrtim::Pscl4; -use hal::pwm::hrtim::{HrControltExt, HrOutput}; use hal::pwm::FaultMonitor; use hal::rcc; use hal::stm32; use stm32g4xx_hal as hal; +use stm32g4xx_hal::pwr::PwrExt; //mod utils; use defmt_rtt as _; // global logger @@ -34,13 +33,17 @@ fn main() -> ! { let cp = stm32::CorePeripherals::take().expect("cannot take core"); // Set system frequency to 16MHz * 15/1/2 = 120MHz // This would lead to HrTim running at 120MHz * 32 = 3.84GHz... - let mut rcc = dp.RCC.freeze(rcc::Config::pll().pll_cfg(rcc::PllConfig { - mux: rcc::PLLSrc::HSI, - n: rcc::PllNMul::MUL_15, - m: rcc::PllMDiv::DIV_1, - r: Some(rcc::PllRDiv::DIV_2), - ..Default::default() - })); + let pwr = dp.PWR.constrain().freeze(); + let mut rcc = dp.RCC.freeze( + rcc::Config::pll().pll_cfg(rcc::PllConfig { + mux: rcc::PLLSrc::HSI, + n: rcc::PllNMul::MUL_15, + m: rcc::PllMDiv::DIV_1, + r: Some(rcc::PllRDiv::DIV_2), + ..Default::default() + }), + pwr, + ); let mut delay = cp.SYST.delay(&rcc.clocks); @@ -78,14 +81,14 @@ fn main() -> ! { ) .enable(); - let (mut fault_control, flt_inputs) = - dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); + let (hr_control, flt_inputs, _) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); + let mut hr_control = hr_control.constrain(); let fault_source5 = flt_inputs .fault_input5 .bind_comp(&comp3) .polarity(hal::pwm::Polarity::ActiveHigh) - .finalize(&mut fault_control); + .finalize(&mut hr_control); // ...with a prescaler of 4 this gives us a HrTimer with a tick rate of 1.2GHz // With max the max period set, this would be 1.2GHz/2^16 ~= 18kHz... @@ -115,10 +118,10 @@ fn main() -> ! { .with_fault_source(fault_source5) // Set fault source .fault_action1(FaultAction::ForceInactive) .fault_action2(FaultAction::ForceInactive) - .finalize(&mut fault_control); + .finalize(&mut hr_control); - out1.enable_rst_event(EventSource::Cr1); // Set low on compare match with cr1 - out1.enable_set_event(EventSource::Period); // Set high at new period + out1.enable_rst_event(&cr1); // Set low on compare match with cr1 + out1.enable_set_event(&timer); // Set high at new period cr1.set_duty(timer.get_period() / 3); //unsafe {((HRTIM_COMMON::ptr() as *mut u8).offset(0x14) as *mut u32).write_volatile(1); } out1.enable(); @@ -132,12 +135,12 @@ fn main() -> ! { "State: {}, comp: {}, is_fault_active: {}, pc1: {}", out1.get_state(), comp3.output(), - fault_control.fault_5.is_fault_active(), + hr_control.fault_5.is_fault_active(), adc1.convert(&pc1, hal::adc::config::SampleTime::Cycles_92_5) ); } - if fault_control.fault_5.is_fault_active() { - fault_control.fault_5.clear_fault(); // Clear fault every 5s + if hr_control.fault_5.is_fault_active() { + hr_control.fault_5.clear_fault(); // Clear fault every 5s out1.enable(); defmt::info!("failt cleared, and output reenabled"); } diff --git a/examples/hrtim_flt.rs b/examples/hrtim/flt.rs similarity index 76% rename from examples/hrtim_flt.rs rename to examples/hrtim/flt.rs index a9c1f4ee..7a408de9 100644 --- a/examples/hrtim_flt.rs +++ b/examples/hrtim/flt.rs @@ -3,21 +3,21 @@ #![no_std] use cortex_m_rt::entry; -use fugit::ExtU32; use hal::gpio::gpioa::PA8; use hal::gpio::Alternate; use hal::gpio::AF13; +use hal::hrtim::compare_register::HrCompareRegister; +use hal::hrtim::fault::FaultAction; +use hal::hrtim::timer::HrTimer; +use hal::hrtim::HrPwmAdvExt; +use hal::hrtim::Pscl4; +use hal::hrtim::{control::HrControltExt, output::HrOutput}; use hal::prelude::*; -use hal::pwm::hrtim::EventSource; -use hal::pwm::hrtim::FaultAction; -use hal::pwm::hrtim::HrCompareRegister; -use hal::pwm::hrtim::HrPwmAdvExt; -use hal::pwm::hrtim::HrTimer; -use hal::pwm::hrtim::Pscl4; -use hal::pwm::hrtim::{HrControltExt, HrOutput}; use hal::pwm::FaultMonitor; +use hal::pwr::PwrExt; use hal::rcc; use hal::stm32; +use hal::time::ExtU32; use stm32g4xx_hal as hal; //mod utils; @@ -30,26 +30,30 @@ fn main() -> ! { let cp = stm32::CorePeripherals::take().expect("cannot take core"); // Set system frequency to 16MHz * 75/4/2 = 150MHz // This would lead to HrTim running at 150MHz * 32 = 4.8GHz... - let mut rcc = dp.RCC.freeze(rcc::Config::pll().pll_cfg(rcc::PllConfig { - mux: rcc::PLLSrc::HSI, - n: rcc::PllNMul::MUL_75, - m: rcc::PllMDiv::DIV_4, - r: Some(rcc::PllRDiv::DIV_2), - ..Default::default() - })); + let pwr = dp.PWR.constrain().freeze(); + let mut rcc = dp.RCC.freeze( + rcc::Config::pll().pll_cfg(rcc::PllConfig { + mux: rcc::PLLSrc::HSI, + n: rcc::PllNMul::MUL_75, + m: rcc::PllMDiv::DIV_4, + r: Some(rcc::PllRDiv::DIV_2), + ..Default::default() + }), + pwr, + ); let mut delay = cp.SYST.delay(&rcc.clocks); let gpioa = dp.GPIOA.split(&mut rcc); let gpiob = dp.GPIOB.split(&mut rcc); - let (mut fault_control, flt_inputs) = - dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); + let (hr_control, flt_inputs, _) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); + let mut hr_control = hr_control.constrain(); let fault_source3 = flt_inputs .fault_input3 .bind_pin(gpiob.pb10.into_pull_down_input()) .polarity(hal::pwm::Polarity::ActiveHigh) - .finalize(&mut fault_control); + .finalize(&mut hr_control); // ...with a prescaler of 4 this gives us a HrTimer with a tick rate of 1.2GHz // With max the max period set, this would be 1.2GHz/2^16 ~= 18kHz... @@ -87,10 +91,10 @@ fn main() -> ! { // alternated every period with one being // inactive and the other getting to output its wave form // as normal - .finalize(&mut fault_control); + .finalize(&mut hr_control); - out1.enable_rst_event(EventSource::Cr1); // Set low on compare match with cr1 - out1.enable_set_event(EventSource::Period); // Set high at new period + out1.enable_rst_event(&cr1); // Set low on compare match with cr1 + out1.enable_set_event(&timer); // Set high at new period cr1.set_duty(timer.get_period() / 3); //unsafe {((HRTIM_COMMON::ptr() as *mut u8).offset(0x14) as *mut u32).write_volatile(1); } out1.enable(); @@ -102,8 +106,8 @@ fn main() -> ! { delay.delay(500_u32.millis()); defmt::info!("State: {}", out1.get_state()); } - if fault_control.fault_3.is_fault_active() { - fault_control.fault_3.clear_fault(); // Clear fault every 5s + if hr_control.fault_3.is_fault_active() { + hr_control.fault_3.clear_fault(); // Clear fault every 5s out1.enable(); defmt::info!("failt cleared, and output reenabled"); } diff --git a/examples/hrtim.rs b/examples/hrtim/hrtim.rs similarity index 75% rename from examples/hrtim.rs rename to examples/hrtim/hrtim.rs index 58cb0f8b..08b972a1 100644 --- a/examples/hrtim.rs +++ b/examples/hrtim/hrtim.rs @@ -22,14 +22,14 @@ fn main() -> ! { use hal::gpio::gpioa::PA9; use hal::gpio::Alternate; use hal::gpio::AF13; + use hal::hrtim::compare_register::HrCompareRegister; + use hal::hrtim::control::HrControltExt; + use hal::hrtim::output::HrOutput; + use hal::hrtim::timer::HrTimer; + use hal::hrtim::HrPwmAdvExt; + use hal::hrtim::Pscl4; use hal::prelude::*; - use hal::pwm::hrtim::EventSource; - use hal::pwm::hrtim::HrCompareRegister; - use hal::pwm::hrtim::HrControltExt; - use hal::pwm::hrtim::HrOutput; - use hal::pwm::hrtim::HrPwmAdvExt; - use hal::pwm::hrtim::HrTimer; - use hal::pwm::hrtim::Pscl4; + use hal::pwr::PwrExt; use hal::rcc; use hal::stm32; use stm32g4xx_hal as hal; @@ -39,14 +39,18 @@ fn main() -> ! { let cp = stm32::CorePeripherals::take().expect("cannot take core"); // Set system frequency to 16MHz * 15/1/2 = 120MHz // This would lead to HrTim running at 120MHz * 32 = 3.84... - let mut rcc = dp.RCC.freeze(rcc::Config::pll().pll_cfg(rcc::PllConfig { - mux: rcc::PLLSrc::HSI, - n: rcc::PllNMul::MUL_15, - m: rcc::PllMDiv::DIV_1, - r: Some(rcc::PllRDiv::DIV_2), - - ..Default::default() - })); + let pwr = dp.PWR.constrain().freeze(); + let mut rcc = dp.RCC.freeze( + rcc::Config::pll().pll_cfg(rcc::PllConfig { + mux: rcc::PLLSrc::HSI, + n: rcc::PllNMul::MUL_15, + m: rcc::PllMDiv::DIV_1, + r: Some(rcc::PllRDiv::DIV_2), + + ..Default::default() + }), + pwr, + ); let mut delay = cp.SYST.delay(&rcc.clocks); @@ -70,7 +74,9 @@ fn main() -> ! { // ------------------------ ---------------------------- ---- // . . . . // . . . . - let (mut fault_control, _) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); + let (hr_control, ..) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); + let mut hr_control = hr_control.constrain(); + let (mut timer, (mut cr1, _cr2, _cr3, _cr4), (mut out1, mut out2)) = dp .HRTIM_TIMA .pwm_advanced((pin_a, pin_b), &mut rcc) @@ -80,13 +86,13 @@ fn main() -> ! { // alternated every period with one being // inactive and the other getting to output its wave form // as normal - .finalize(&mut fault_control); + .finalize(&mut hr_control); - out1.enable_rst_event(EventSource::Cr1); // Set low on compare match with cr1 - out2.enable_rst_event(EventSource::Cr1); + out1.enable_rst_event(&cr1); // Set low on compare match with cr1 + out2.enable_rst_event(&cr1); - out1.enable_set_event(EventSource::Period); // Set high at new period - out2.enable_set_event(EventSource::Period); + out1.enable_set_event(&timer); // Set high at new period + out2.enable_set_event(&timer); out1.enable(); out2.enable(); diff --git a/examples/hrtim-master.rs b/examples/hrtim/master.rs similarity index 60% rename from examples/hrtim-master.rs rename to examples/hrtim/master.rs index 6a9b62cb..4f085c3a 100644 --- a/examples/hrtim-master.rs +++ b/examples/hrtim/master.rs @@ -11,29 +11,27 @@ fn main() -> ! { loop {} } -use utils::logger::info; - -#[macro_use] -mod utils; +use defmt_rtt as _; // global logger +use panic_probe as _; #[cfg(any(feature = "stm32g474", feature = "stm32g484"))] #[entry] fn main() -> ! { - utils::logger::init(); - use fugit::ExtU32; use hal::gpio::gpioa::PA8; use hal::gpio::gpioa::PA9; use hal::gpio::Alternate; use hal::gpio::AF13; + use hal::hrtim::compare_register::HrCompareRegister; + use hal::hrtim::control::HrControltExt; + use hal::hrtim::output::HrOutput; + use hal::hrtim::timer::HrTimer; + use hal::hrtim::HrPwmAdvExt; + use hal::hrtim::{ + event::TimerAResetEventSource, HrTimerMode, MasterPreloadSource, PreloadSource, Pscl4, + }; use hal::prelude::*; - use hal::pwm::hrtim::EventSource; - use hal::pwm::hrtim::HrCompareRegister; - use hal::pwm::hrtim::HrControltExt; - use hal::pwm::hrtim::HrOutput; - use hal::pwm::hrtim::HrPwmAdvExt; - use hal::pwm::hrtim::HrTimer; - use hal::pwm::hrtim::{Pscl4, MasterPreloadSource}; + use hal::pwr::PwrExt; use hal::rcc; use hal::stm32; use stm32g4xx_hal as hal; @@ -43,14 +41,18 @@ fn main() -> ! { let cp = stm32::CorePeripherals::take().expect("cannot take core"); // Set system frequency to 16MHz * 15/1/2 = 120MHz // This would lead to HrTim running at 120MHz * 32 = 3.84... - let mut rcc = dp.RCC.freeze(rcc::Config::pll().pll_cfg(rcc::PllConfig { - mux: rcc::PLLSrc::HSI, - n: rcc::PllNMul::MUL_15, - m: rcc::PllMDiv::DIV_1, - r: Some(rcc::PllRDiv::DIV_2), - - ..Default::default() - })); + let pwr = dp.PWR.constrain().freeze(); + let mut rcc = dp.RCC.freeze( + rcc::Config::pll().pll_cfg(rcc::PllConfig { + mux: rcc::PLLSrc::HSI, + n: rcc::PllNMul::MUL_15, + m: rcc::PllMDiv::DIV_1, + r: Some(rcc::PllRDiv::DIV_2), + + ..Default::default() + }), + pwr, + ); let mut delay = cp.SYST.delay(&rcc.clocks); @@ -74,42 +76,49 @@ fn main() -> ! { // ------------------------ ---------------------------- ---- // . . . . // . . . . - let (mut fault_control, _) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); + let (hr_control, ..) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); + let mut hr_control = hr_control.constrain(); + let (mut timer, (mut cr1, _cr2, _cr3, _cr4), (mut out1, mut out2)) = dp .HRTIM_TIMA .pwm_advanced((pin_a, pin_b), &mut rcc) .prescaler(prescaler) - //.push_pull_mode(true) // Set push pull mode, out1 and out2 are + .push_pull_mode(true) // Set push pull mode, out1 and out2 are // alternated every period with one being // inactive and the other getting to output its wave form // as normal - .finalize(&mut fault_control); + .preload(PreloadSource::OnMasterTimerUpdate) + .timer_mode(HrTimerMode::SingleShotRetriggerable) + .finalize(&mut hr_control); - let (mut mtimer, (mut mcr1, cr2, cr3, cr4)) = dp + let (mut mtimer, (mut mcr1, _mcr2, _mcr3, _mcr4)) = dp .HRTIM_MASTER .pwm_advanced((), &mut rcc) .prescaler(prescaler) .preload(MasterPreloadSource::OnMasterRepetitionUpdate) .period(0xFFFF) - .finalize(&mut fault_control); + .finalize(&mut hr_control); - out1.enable_rst_event(EventSource::MasterCr1); // Set low on compare match with cr1 - out2.enable_rst_event(EventSource::MasterCr1); + // Run in sync with master timer + timer.enable_reset_event(TimerAResetEventSource::MasterPeriod); - out1.enable_set_event(EventSource::MasterPeriod); // Set high at new period - out2.enable_set_event(EventSource::MasterPeriod); + out1.enable_rst_event(&mcr1); // Set low on compare match with cr1 + out2.enable_rst_event(&mcr1); + + out1.enable_set_event(&mtimer); // Set high at new period + out2.enable_set_event(&mtimer); out1.enable(); out2.enable(); let tima = unsafe { &*stm32g4xx_hal::stm32::HRTIM_TIMA::ptr() }; - info!("set1r: {}", tima.seta1r.read().bits()); - info!("rst1r: {}", tima.rsta1r.read().bits()); - - info!("set2r: {}", tima.seta2r.read().bits()); - info!("rst2r: {}", tima.rsta2r.read().bits()); + defmt::info!("set1r: {}", tima.seta1r.read().bits()); + defmt::info!("rst1r: {}", tima.rsta1r.read().bits()); + + defmt::info!("set2r: {}", tima.seta2r.read().bits()); + defmt::info!("rst2r: {}", tima.rsta2r.read().bits()); - info!("Running"); + defmt::info!("Running"); loop { // Step frequency from 18kHz to about 180kHz(half of that when only looking at one pin) @@ -120,10 +129,16 @@ fn main() -> ! { cr1.set_duty(new_period / 3 - 1000); mtimer.set_period(new_period); timer.set_period(new_period - 1000); - - info!("period: {}, duty: {}, get_duty: {}, get_period: {}", new_period, new_period / 3, mcr1.get_duty(), mtimer.get_period()); - delay.delay(5000_u32.millis()); + defmt::info!( + "period: {}, duty: {}, get_duty: {}, get_period: {}", + new_period, + new_period / 3, + mcr1.get_duty(), + mtimer.get_period() + ); + + delay.delay(500_u32.millis()); } } } diff --git a/examples/hrtim_simple.rs b/examples/hrtim/simple.rs similarity index 74% rename from examples/hrtim_simple.rs rename to examples/hrtim/simple.rs index df142cd2..79f1b621 100644 --- a/examples/hrtim_simple.rs +++ b/examples/hrtim/simple.rs @@ -23,8 +23,9 @@ fn main() -> ! { use hal::gpio::gpioa::PA9; use hal::gpio::Alternate; use hal::gpio::AF13; + use hal::hrtim::{control::HrControltExt, HrPwmExt}; use hal::prelude::*; - use hal::pwm::hrtim::{HrControltExt, HrPwmExt}; + use hal::pwr::PwrExt; use hal::rcc; use hal::stm32; use hal::time::RateExtU32; @@ -32,14 +33,21 @@ fn main() -> ! { extern crate cortex_m_rt as rt; let dp = stm32::Peripherals::take().expect("cannot take peripherals"); + defmt::info!("Initializing..."); + // Set system frequency to 16MHz * 75/4/2 = 150MHz // This would lead to HrTim running at 150MHz * 32 = 4.8GHz... - let mut rcc = dp.RCC.freeze(rcc::Config::pll().pll_cfg(rcc::PllConfig { - n: rcc::PllNMul::MUL_75, - m: rcc::PllMDiv::DIV_4, - r: Some(rcc::PllRDiv::DIV_2), - ..Default::default() - })); + let pwr = dp.PWR.constrain().freeze(); + let mut rcc = dp.RCC.freeze( + rcc::Config::pll().pll_cfg(rcc::PllConfig { + mux: rcc::PLLSrc::HSI, + n: rcc::PllNMul::MUL_75, + m: rcc::PllMDiv::DIV_4, + r: Some(rcc::PllRDiv::DIV_2), + ..Default::default() + }), + pwr, + ); let gpioa = dp.GPIOA.split(&mut rcc); let pin_a: PA8> = gpioa.pa8.into_alternate(); @@ -60,10 +68,11 @@ fn main() -> ! { // . . . // . . . - let (mut control, _) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); - let (mut p1, mut p2) = dp - .HRTIM_TIMA - .pwm((pin_a, pin_b), 20_u32.kHz(), &mut control, &mut rcc); + let (hr_control, ..) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); + let mut hr_control = hr_control.constrain(); + let (mut p1, mut p2) = + dp.HRTIM_TIMA + .pwm((pin_a, pin_b), 20_u32.kHz(), &mut hr_control, &mut rcc); let max_duty = p1.get_max_duty(); p1.set_duty(max_duty / 3); // Set output 1 to about 33% @@ -73,6 +82,8 @@ fn main() -> ! { p1.enable(); p2.enable(); + defmt::info!("Running"); + loop { cortex_m::asm::nop() } diff --git a/src/hrtim/deadtime.rs b/src/hrtim/deadtime.rs index dc3b3141..c59c0641 100644 --- a/src/hrtim/deadtime.rs +++ b/src/hrtim/deadtime.rs @@ -76,4 +76,4 @@ pub enum DeadtimePrescaler { ThrtimMul4 = 0b101, ThrtimMul8 = 0b110, ThrtimMul16 = 0b111, -} \ No newline at end of file +} diff --git a/src/hrtim/event.rs b/src/hrtim/event.rs index f0028f5b..c4604cca 100644 --- a/src/hrtim/event.rs +++ b/src/hrtim/event.rs @@ -4,7 +4,10 @@ use crate::stm32::{ HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF, }; -use super::{compare_register::{HrCr1, HrCr2, HrCr3, HrCr4}, external_event::ExternalEventSource}; +use super::{ + compare_register::{HrCr1, HrCr2, HrCr3, HrCr4}, + external_event::ExternalEventSource, +}; use crate::hrtim::timer::HrTim; macro_rules! impl_into_es { @@ -130,36 +133,56 @@ impl_into_neighbor_es! { pub enum EventSource { /// Compare match with compare register 1 of this timer - Cr1 { _x: PhantomData<(PSCL, DST)> }, + Cr1 { + _x: PhantomData<(PSCL, DST)>, + }, /// Compare match with compare register 2 of this timer - Cr2 { _x: PhantomData<(PSCL, DST)> }, + Cr2 { + _x: PhantomData<(PSCL, DST)>, + }, /// Compare match with compare register 3 of this timer - Cr3 { _x: PhantomData<(PSCL, DST)> }, + Cr3 { + _x: PhantomData<(PSCL, DST)>, + }, /// Compare match with compare register 4 of this timer - Cr4 { _x: PhantomData<(PSCL, DST)> }, + Cr4 { + _x: PhantomData<(PSCL, DST)>, + }, /// On complete period - Period { _x: PhantomData<(PSCL, DST)> }, + Period { + _x: PhantomData<(PSCL, DST)>, + }, /// Compare match with compare register 1 of master timer - MasterCr1 { _x: PhantomData<(PSCL, DST)> }, + MasterCr1 { + _x: PhantomData<(PSCL, DST)>, + }, /// Compare match with compare register 2 of master timer - MasterCr2 { _x: PhantomData<(PSCL, DST)> }, + MasterCr2 { + _x: PhantomData<(PSCL, DST)>, + }, /// Compare match with compare register 3 of master timer - MasterCr3 { _x: PhantomData<(PSCL, DST)> }, + MasterCr3 { + _x: PhantomData<(PSCL, DST)>, + }, /// Compare match with compare register 4 of master timer - MasterCr4 { _x: PhantomData<(PSCL, DST)> }, + MasterCr4 { + _x: PhantomData<(PSCL, DST)>, + }, /// On complete master period - MasterPeriod { _x: PhantomData<(PSCL, DST)> }, + MasterPeriod { + _x: PhantomData<(PSCL, DST)>, + }, - ExternalEvent(EevFastOrNormal), // This is fine + ExternalEvent(EevFastOrNormal), // This is fine NeighborTimer { n: NeighborTimerEventSource, diff --git a/src/hrtim/external_event.rs b/src/hrtim/external_event.rs index 19e61dbf..d56d35d3 100644 --- a/src/hrtim/external_event.rs +++ b/src/hrtim/external_event.rs @@ -4,8 +4,8 @@ use crate::comparator::{COMP1, COMP2, COMP3, COMP4, COMP5, COMP6, COMP7}; use crate::gpio::gpiob::{PB3, PB4, PB5, PB6, PB7, PB8, PB9}; use crate::gpio::gpioc::{PC11, PC12, PC5, PC6}; use crate::gpio::{self, AF13, AF3}; -use crate::stm32::HRTIM_COMMON; use crate::pwm::Polarity; +use crate::stm32::HRTIM_COMMON; use super::event::EevFastOrNormal; use super::{control::HrTimCalibrated, event::EventSource}; @@ -84,18 +84,22 @@ macro_rules! impl_eev_input { } })* - unsafe impl EevSrcBits<$N> for &crate::comparator::Comparator<$compX, crate::comparator::Enabled> { + unsafe impl EevSrcBits<$N> for &crate::comparator::Comparator<$compX, ED> + where ED: crate::comparator::EnabledState + { const SRC_BITS: u8 = 0b01; } - + $( - unsafe impl EevSrcBits<$N> for &crate::comparator::Comparator<$compY, crate::comparator::Enabled> { + unsafe impl EevSrcBits<$N> for &crate::comparator::Comparator<$compY, ED> + where ED: crate::comparator::EnabledState + { const SRC_BITS: u8 = $compY_src_bits; } )* - + impl EevInput<$N> { - pub fn bind(self, src: SRC) -> SourceBuilder<$N, IS_FAST> + pub fn bind(self, src: SRC) -> SourceBuilder<$N, IS_FAST> where SRC: EevSrcBits<$N> { src.cfg(); @@ -127,7 +131,6 @@ pub enum Edge { Both = 0b11, } - pub enum EevSamplingFilter { /// No filtering, fault acts asynchronously /// @@ -270,7 +273,7 @@ macro_rules! impl_eev1_5_to_es { polarity_bit, filter_bits, } = self; - + SourceBuilder { src_bits, edge_or_polarity_bits, diff --git a/src/hrtim/mod.rs b/src/hrtim/mod.rs index fcf9c45a..cc231c74 100644 --- a/src/hrtim/mod.rs +++ b/src/hrtim/mod.rs @@ -515,7 +515,7 @@ macro_rules! hrtim_common_methods { // Implement PWM configuration for timer macro_rules! hrtim_hal { - ($($TIMX:ident: ($timXcr:ident, $timXcr2:ident, $perXr:ident, $tXcen:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident, + ($($TIMX:ident: ($timXcr:ident, $timXcr2:ident, $perXr:ident, $tXcen:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident, $fltXr:ident, $eefXr1:ident, $eefXr2:ident, $Xeefr3:ident, $outXr:ident, $dtXr:ident),)+) => { $( diff --git a/src/hrtim/output.rs b/src/hrtim/output.rs index a459fd92..6633acc3 100644 --- a/src/hrtim/output.rs +++ b/src/hrtim/output.rs @@ -1,10 +1,10 @@ +use crate::hrtim::external_event::ExternalEventSource; use core::marker::PhantomData; use stm32g4::stm32g474::{ HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF, }; -use crate::hrtim::external_event::ExternalEventSource; -use super::event::{EventSource, NeighborTimerEventSource, EevFastOrNormal}; +use super::event::{EevFastOrNormal, EventSource, NeighborTimerEventSource}; use crate::{ gpio::{ gpioa::{PA10, PA11, PA8, PA9}, @@ -19,36 +19,18 @@ use crate::{ macro_rules! hrtim_out_common { ($e:ident, $register:expr, $action:ident) => { match $e { - ExternalEventSource::Eevnt1 { .. } => { - $register.modify(|_r, w| w.extevnt1().$action()) - }, - ExternalEventSource::Eevnt2 { .. } => { - $register.modify(|_r, w| w.extevnt2().$action()) - }, - ExternalEventSource::Eevnt3 { .. } => { - $register.modify(|_r, w| w.extevnt3().$action()) - }, - ExternalEventSource::Eevnt4 { .. } => { - $register.modify(|_r, w| w.extevnt4().$action()) - }, - ExternalEventSource::Eevnt5 { .. } => { - $register.modify(|_r, w| w.extevnt5().$action()) - }, - ExternalEventSource::Eevnt6 { .. } => { - $register.modify(|_r, w| w.extevnt6().$action()) - }, - ExternalEventSource::Eevnt7 { .. } => { - $register.modify(|_r, w| w.extevnt7().$action()) - }, - ExternalEventSource::Eevnt8 { .. } => { - $register.modify(|_r, w| w.extevnt8().$action()) - }, - ExternalEventSource::Eevnt9 { .. } => { - $register.modify(|_r, w| w.extevnt9().$action()) - }, + ExternalEventSource::Eevnt1 { .. } => $register.modify(|_r, w| w.extevnt1().$action()), + ExternalEventSource::Eevnt2 { .. } => $register.modify(|_r, w| w.extevnt2().$action()), + ExternalEventSource::Eevnt3 { .. } => $register.modify(|_r, w| w.extevnt3().$action()), + ExternalEventSource::Eevnt4 { .. } => $register.modify(|_r, w| w.extevnt4().$action()), + ExternalEventSource::Eevnt5 { .. } => $register.modify(|_r, w| w.extevnt5().$action()), + ExternalEventSource::Eevnt6 { .. } => $register.modify(|_r, w| w.extevnt6().$action()), + ExternalEventSource::Eevnt7 { .. } => $register.modify(|_r, w| w.extevnt7().$action()), + ExternalEventSource::Eevnt8 { .. } => $register.modify(|_r, w| w.extevnt8().$action()), + ExternalEventSource::Eevnt9 { .. } => $register.modify(|_r, w| w.extevnt9().$action()), ExternalEventSource::Eevnt10 { .. } => { $register.modify(|_r, w| w.extevnt10().$action()) - }, + } } }; @@ -68,8 +50,12 @@ macro_rules! hrtim_out_common { EventSource::MasterCr4 { .. } => tim.$register.modify(|_r, w| w.mstcmp4().$action()), EventSource::MasterPeriod { .. } => tim.$register.modify(|_r, w| w.mstper().$action()), - EventSource::ExternalEvent(EevFastOrNormal::Fast(e)) => hrtim_out_common!(e, tim.$register, $action), - EventSource::ExternalEvent(EevFastOrNormal::Normal(e)) => hrtim_out_common!(e, tim.$register, $action), + EventSource::ExternalEvent(EevFastOrNormal::Fast(e)) => { + hrtim_out_common!(e, tim.$register, $action) + } + EventSource::ExternalEvent(EevFastOrNormal::Normal(e)) => { + hrtim_out_common!(e, tim.$register, $action) + } EventSource::NeighborTimer { n } => match n { NeighborTimerEventSource::TimEvent1 { .. } => { diff --git a/src/hrtim/timer_eev_cfg.rs b/src/hrtim/timer_eev_cfg.rs index 9ed8f55b..cfaa7667 100644 --- a/src/hrtim/timer_eev_cfg.rs +++ b/src/hrtim/timer_eev_cfg.rs @@ -22,6 +22,28 @@ pub struct EevCfgs { pub(crate) event_counter_threshold_bits: u8, } +macro_rules! impl_setter { + ($eevX:ident) => { + pub fn $eevX(mut self, cfg: EevCfg) -> Self { + self.$eevX = cfg; + self + } + }; +} + +impl EevCfgs { + impl_setter!(eev1); + impl_setter!(eev2); + impl_setter!(eev3); + impl_setter!(eev4); + impl_setter!(eev5); + impl_setter!(eev6); + impl_setter!(eev7); + impl_setter!(eev8); + impl_setter!(eev9); + impl_setter!(eev10); +} + impl Clone for EevCfgs { fn clone(&self) -> Self { Self { From 3d078616f272643fb616a00456addb8ebacd3163 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 8 Nov 2023 18:23:19 +0100 Subject: [PATCH 43/88] HRTIM examples --- Cargo.toml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 8bac4fc7..2bc57b8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -120,3 +120,35 @@ required-features = ["usb"] [[example]] name = "cordic" required-features = ["cordic"] + +[[example]] +name = "hrtim-adc-trigger" +path = "examples/hrtim/adc-trigger.rs" + +[[example]] +name = "hrtim-eev-comp" +path = "examples/hrtim/eev-comp.rs" + +[[example]] +name = "hrtim-eev" +path = "examples/hrtim/eev.rs" + +[[example]] +name = "hrtim-flt-comp" +path = "examples/hrtim/flt-comp.rs" + +[[example]] +name = "hrtim-flt" +path = "examples/hrtim/flt.rs" + +[[example]] +name = "hrtim" +path = "examples/hrtim/hrtim.rs" + +[[example]] +name = "hrtim-master" +path = "examples/hrtim/master.rs" + +[[example]] +name = "hrtim-simple" +path = "examples/hrtim/simple.rs" From 89f0706a47af829fbfe73bf17bf1a5ba58c06a57 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 8 Nov 2023 22:42:31 +0100 Subject: [PATCH 44/88] Fix warnings for hrtim --- examples/hrtim/adc-trigger.rs | 50 ++++++++++++++++++++--------------- examples/hrtim/eev-comp.rs | 49 ++++++++++++++++++++-------------- examples/hrtim/eev.rs | 48 ++++++++++++++++++++------------- examples/hrtim/flt-comp.rs | 42 +++++++++++++++++------------ examples/hrtim/flt.rs | 41 +++++++++++++++++----------- src/hrtim/external_event.rs | 22 ++++++++------- src/hrtim/fault.rs | 2 ++ src/hrtim/mod.rs | 2 ++ src/hrtim/output.rs | 4 +-- src/hrtim/timer.rs | 4 +-- src/hrtim/timer_eev_cfg.rs | 12 ++++----- 11 files changed, 164 insertions(+), 112 deletions(-) diff --git a/examples/hrtim/adc-trigger.rs b/examples/hrtim/adc-trigger.rs index 45134bc5..04865cbe 100644 --- a/examples/hrtim/adc-trigger.rs +++ b/examples/hrtim/adc-trigger.rs @@ -2,33 +2,41 @@ #![no_main] use cortex_m_rt::entry; -use hal::adc::{self, config::ExternalTrigger12}; - -use crate::hal::{ - adc::{ - config::{Continuous, Dma as AdcDma, SampleTime, Sequence}, - AdcClaim, ClockSource, Temperature, Vref, - }, - delay::SYSTDelayExt, - dma::{self, config::DmaConfig, stream::DMAExt, TransferExt}, - gpio::{gpioa::PA8, gpioa::PA9, Alternate, GpioExt, AF13}, - hrtim::control::HrControltExt, - hrtim::output::HrOutput, - hrtim::HrPwmAdvExt, - hrtim::{control::Adc13Trigger, Pscl4}, - pwr::PwrExt, - rcc::{self, RccExt}, - stm32::Peripherals, -}; -use stm32g4xx_hal as hal; - -use defmt::info; use defmt_rtt as _; // global logger use panic_probe as _; +#[cfg(not(any(feature = "stm32g474", feature = "stm32g484")))] #[entry] fn main() -> ! { + #[allow(clippy::empty_loop)] + loop {} +} + +#[cfg(any(feature = "stm32g474", feature = "stm32g484"))] +#[entry] +fn main() -> ! { + use hal::adc::{self, config::ExternalTrigger12}; + use stm32g4xx_hal as hal; + + use defmt::info; + use hal::{ + adc::{ + config::{Continuous, Dma as AdcDma, SampleTime, Sequence}, + AdcClaim, ClockSource, Temperature, Vref, + }, + delay::SYSTDelayExt, + dma::{self, config::DmaConfig, stream::DMAExt, TransferExt}, + gpio::{gpioa::PA8, gpioa::PA9, Alternate, GpioExt, AF13}, + hrtim::control::HrControltExt, + hrtim::output::HrOutput, + hrtim::HrPwmAdvExt, + hrtim::{control::Adc13Trigger, Pscl4}, + pwr::PwrExt, + rcc::{self, RccExt}, + stm32::Peripherals, + }; + info!("start"); let dp = Peripherals::take().unwrap(); diff --git a/examples/hrtim/eev-comp.rs b/examples/hrtim/eev-comp.rs index 15f69f71..e2b51d17 100644 --- a/examples/hrtim/eev-comp.rs +++ b/examples/hrtim/eev-comp.rs @@ -3,32 +3,41 @@ #![no_std] use cortex_m_rt::entry; -use hal::comparator; -use hal::comparator::{ComparatorExt, ComparatorSplit, Hysteresis}; -use hal::dac::{self, DacExt, DacOut}; -use hal::gpio::gpioa::PA8; -use hal::gpio::Alternate; -use hal::gpio::SignalEdge; -use hal::gpio::AF13; -use hal::hrtim::compare_register::HrCompareRegister; -use hal::hrtim::external_event::{self, ToExternalEventSource}; -use hal::hrtim::timer::HrTimer; -use hal::hrtim::timer_eev_cfg::{EevCfg, EevCfgs}; -use hal::hrtim::HrPwmAdvExt; -use hal::hrtim::Pscl4; -use hal::hrtim::{control::HrControltExt, output::HrOutput}; -use hal::prelude::*; -use hal::pwm; -use hal::pwr::PwrExt; -use hal::rcc; -use hal::stm32; -use stm32g4xx_hal as hal; use defmt_rtt as _; // global logger use panic_probe as _; +#[cfg(not(any(feature = "stm32g474", feature = "stm32g484")))] #[entry] fn main() -> ! { + #[allow(clippy::empty_loop)] + loop {} +} + +#[cfg(any(feature = "stm32g474", feature = "stm32g484"))] +#[entry] +fn main() -> ! { + use hal::comparator; + use hal::comparator::{ComparatorExt, ComparatorSplit, Hysteresis}; + use hal::dac::{self, DacExt, DacOut}; + use hal::gpio::gpioa::PA8; + use hal::gpio::Alternate; + use hal::gpio::SignalEdge; + use hal::gpio::AF13; + use hal::hrtim::compare_register::HrCompareRegister; + use hal::hrtim::external_event::{self, ToExternalEventSource}; + use hal::hrtim::timer::HrTimer; + use hal::hrtim::timer_eev_cfg::{EevCfg, EevCfgs}; + use hal::hrtim::HrPwmAdvExt; + use hal::hrtim::Pscl4; + use hal::hrtim::{control::HrControltExt, output::HrOutput}; + use hal::prelude::*; + use hal::pwm; + use hal::pwr::PwrExt; + use hal::rcc; + use hal::stm32; + use stm32g4xx_hal as hal; + let dp = stm32::Peripherals::take().expect("cannot take peripherals"); let cp = stm32::CorePeripherals::take().expect("cannot take core"); // Set system frequency to 16MHz * 75/4/2 = 150MHz diff --git a/examples/hrtim/eev.rs b/examples/hrtim/eev.rs index 281fa7c1..1ed8f32e 100644 --- a/examples/hrtim/eev.rs +++ b/examples/hrtim/eev.rs @@ -3,30 +3,40 @@ #![no_std] use cortex_m_rt::entry; -use hal::gpio::gpioa::PA8; -use hal::gpio::Alternate; -use hal::gpio::AF13; -use hal::hrtim::compare_register::HrCompareRegister; -use hal::hrtim::external_event; -use hal::hrtim::external_event::ToExternalEventSource; -use hal::hrtim::timer::HrTimer; -use hal::hrtim::timer_eev_cfg::EevCfgs; -use hal::hrtim::HrPwmAdvExt; -use hal::hrtim::Pscl4; -use hal::hrtim::{control::HrControltExt, output::HrOutput}; -use hal::prelude::*; -use hal::pwm; -use hal::pwr::PwrExt; -use hal::rcc; -use hal::stm32; -use stm32g4xx_hal as hal; + //mod utils; use defmt_rtt as _; // global logger use panic_probe as _; +#[cfg(not(any(feature = "stm32g474", feature = "stm32g484")))] +#[entry] +fn main() -> ! { + #[allow(clippy::empty_loop)] + loop {} +} + +#[cfg(any(feature = "stm32g474", feature = "stm32g484"))] #[entry] fn main() -> ! { + use hal::gpio::gpioa::PA8; + use hal::gpio::Alternate; + use hal::gpio::AF13; + use hal::hrtim::compare_register::HrCompareRegister; + use hal::hrtim::external_event; + use hal::hrtim::external_event::ToExternalEventSource; + use hal::hrtim::timer::HrTimer; + use hal::hrtim::timer_eev_cfg::EevCfgs; + use hal::hrtim::HrPwmAdvExt; + use hal::hrtim::Pscl4; + use hal::hrtim::{control::HrControltExt, output::HrOutput}; + use hal::prelude::*; + use hal::pwm; + use hal::pwr::PwrExt; + use hal::rcc; + use hal::stm32; + use stm32g4xx_hal as hal; + let dp = stm32::Peripherals::take().expect("cannot take peripherals"); // Set system frequency to 16MHz * 75/4/2 = 150MHz // This would lead to HrTim running at 150MHz * 32 = 4.8GHz... @@ -97,5 +107,7 @@ fn main() -> ! { defmt::info!("Started"); - loop {} + loop { + cortex_m::asm::nop() + } } diff --git a/examples/hrtim/flt-comp.rs b/examples/hrtim/flt-comp.rs index cea854af..15fdf744 100644 --- a/examples/hrtim/flt-comp.rs +++ b/examples/hrtim/flt-comp.rs @@ -3,31 +3,39 @@ #![no_std] use cortex_m_rt::entry; -use hal::comparator::{ComparatorExt, ComparatorSplit, Config, Hysteresis}; -use hal::dac::{Dac3IntSig1, DacExt, DacOut}; -use hal::gpio::gpioa::PA8; -use hal::gpio::Alternate; -use hal::gpio::AF13; -use hal::hrtim::compare_register::HrCompareRegister; -use hal::hrtim::fault::FaultAction; -use hal::hrtim::timer::HrTimer; -use hal::hrtim::HrPwmAdvExt; -use hal::hrtim::Pscl4; -use hal::hrtim::{control::HrControltExt, output::HrOutput}; -use hal::prelude::*; -use hal::pwm::FaultMonitor; -use hal::rcc; -use hal::stm32; -use stm32g4xx_hal as hal; -use stm32g4xx_hal::pwr::PwrExt; //mod utils; use defmt_rtt as _; // global logger use panic_probe as _; +#[cfg(not(any(feature = "stm32g474", feature = "stm32g484")))] #[entry] fn main() -> ! { + #[allow(clippy::empty_loop)] + loop {} +} + +#[cfg(any(feature = "stm32g474", feature = "stm32g484"))] +#[entry] +fn main() -> ! { + use hal::comparator::{ComparatorExt, ComparatorSplit, Config, Hysteresis}; + use hal::dac::{Dac3IntSig1, DacExt, DacOut}; + use hal::gpio::gpioa::PA8; + use hal::gpio::Alternate; + use hal::gpio::AF13; + use hal::hrtim::compare_register::HrCompareRegister; + use hal::hrtim::fault::FaultAction; + use hal::hrtim::timer::HrTimer; + use hal::hrtim::HrPwmAdvExt; + use hal::hrtim::Pscl4; + use hal::hrtim::{control::HrControltExt, output::HrOutput}; + use hal::prelude::*; + use hal::pwm::FaultMonitor; + use hal::rcc; + use hal::stm32; + use stm32g4xx_hal as hal; use stm32g4xx_hal::adc::AdcClaim; + use stm32g4xx_hal::pwr::PwrExt; let dp = stm32::Peripherals::take().expect("cannot take peripherals"); let cp = stm32::CorePeripherals::take().expect("cannot take core"); diff --git a/examples/hrtim/flt.rs b/examples/hrtim/flt.rs index 7a408de9..a43a8ccc 100644 --- a/examples/hrtim/flt.rs +++ b/examples/hrtim/flt.rs @@ -3,29 +3,38 @@ #![no_std] use cortex_m_rt::entry; -use hal::gpio::gpioa::PA8; -use hal::gpio::Alternate; -use hal::gpio::AF13; -use hal::hrtim::compare_register::HrCompareRegister; -use hal::hrtim::fault::FaultAction; -use hal::hrtim::timer::HrTimer; -use hal::hrtim::HrPwmAdvExt; -use hal::hrtim::Pscl4; -use hal::hrtim::{control::HrControltExt, output::HrOutput}; -use hal::prelude::*; -use hal::pwm::FaultMonitor; -use hal::pwr::PwrExt; -use hal::rcc; -use hal::stm32; -use hal::time::ExtU32; -use stm32g4xx_hal as hal; //mod utils; use defmt_rtt as _; // global logger use panic_probe as _; +#[cfg(not(any(feature = "stm32g474", feature = "stm32g484")))] #[entry] fn main() -> ! { + #[allow(clippy::empty_loop)] + loop {} +} + +#[cfg(any(feature = "stm32g474", feature = "stm32g484"))] +#[entry] +fn main() -> ! { + use hal::gpio::gpioa::PA8; + use hal::gpio::Alternate; + use hal::gpio::AF13; + use hal::hrtim::compare_register::HrCompareRegister; + use hal::hrtim::fault::FaultAction; + use hal::hrtim::timer::HrTimer; + use hal::hrtim::HrPwmAdvExt; + use hal::hrtim::Pscl4; + use hal::hrtim::{control::HrControltExt, output::HrOutput}; + use hal::prelude::*; + use hal::pwm::FaultMonitor; + use hal::pwr::PwrExt; + use hal::rcc; + use hal::stm32; + use hal::time::ExtU32; + use stm32g4xx_hal as hal; + let dp = stm32::Peripherals::take().expect("cannot take peripherals"); let cp = stm32::CorePeripherals::take().expect("cannot take core"); // Set system frequency to 16MHz * 75/4/2 = 150MHz diff --git a/src/hrtim/external_event.rs b/src/hrtim/external_event.rs index d56d35d3..56e9f079 100644 --- a/src/hrtim/external_event.rs +++ b/src/hrtim/external_event.rs @@ -70,6 +70,8 @@ pub struct EevInput { _x: PhantomData<()>, } +/// # Safety +/// Only implement for types that can be used as sources to eev number `EEV_N` with src bits `SRC_BITS` pub unsafe trait EevSrcBits: Sized { const SRC_BITS: u8; fn cfg(self) {} @@ -109,16 +111,16 @@ macro_rules! impl_eev_input { }; } -impl_eev_input!(1: COMP=[COMP2], PINS=[(PC12, AF3)]); -impl_eev_input!(2: COMP=[COMP4], PINS=[(PC11, AF3)]); -impl_eev_input!(3: COMP=[COMP6], PINS=[(PB7, AF13)]); -impl_eev_input!(4: COMP=[COMP1, (COMP5, 0b10)], PINS=[(PB6, AF13)]); -impl_eev_input!(5: COMP=[COMP3, (COMP7, 0b10)], PINS=[(PB9, AF13)]); -impl_eev_input!(6: COMP=[COMP2, (COMP1, 0b10)], PINS=[(PB5, AF13)]); -impl_eev_input!(7: COMP=[COMP4], PINS=[(PB4, AF13)]); -impl_eev_input!(8: COMP=[COMP6, (COMP3, 0b10)], PINS=[(PB8, AF13)]); -impl_eev_input!(9: COMP=[COMP5, (COMP4, 0b11)], PINS=[(PB3, AF13)]); -impl_eev_input!(10: COMP=[COMP7], PINS=[(PC5, AF13), (PC6, AF3)]); +impl_eev_input!(1: COMP = [COMP2], PINS = [(PC12, AF3)]); +impl_eev_input!(2: COMP = [COMP4], PINS = [(PC11, AF3)]); +impl_eev_input!(3: COMP = [COMP6], PINS = [(PB7, AF13)]); +impl_eev_input!(4: COMP = [COMP1, (COMP5, 0b10)], PINS = [(PB6, AF13)]); +impl_eev_input!(5: COMP = [COMP3, (COMP7, 0b10)], PINS = [(PB9, AF13)]); +impl_eev_input!(6: COMP = [COMP2, (COMP1, 0b10)], PINS = [(PB5, AF13)]); +impl_eev_input!(7: COMP = [COMP4], PINS = [(PB4, AF13)]); +impl_eev_input!(8: COMP = [COMP6, (COMP3, 0b10)], PINS = [(PB8, AF13)]); +impl_eev_input!(9: COMP = [COMP5, (COMP4, 0b11)], PINS = [(PB3, AF13)]); +impl_eev_input!(10: COMP = [COMP7], PINS = [(PC5, AF13), (PC6, AF3)]); pub enum EdgeOrPolarity { Edge(Edge), diff --git a/src/hrtim/fault.rs b/src/hrtim/fault.rs index 8e8f5ae1..17fdd34d 100644 --- a/src/hrtim/fault.rs +++ b/src/hrtim/fault.rs @@ -23,6 +23,8 @@ pub enum FaultAction { Floating = 0b11, } +/// # Safety +/// Only implement for actual fault sources with correct `ENABLE_BITS` pub unsafe trait FaultSource: Copy { const ENABLE_BITS: u8; } diff --git a/src/hrtim/mod.rs b/src/hrtim/mod.rs index cc231c74..5062df19 100644 --- a/src/hrtim/mod.rs +++ b/src/hrtim/mod.rs @@ -863,6 +863,8 @@ hrtim_pin_hal! { HRTIM_TIMF: (CH2, perfr, cmp3fr, cmp3x, cmp3, tf2oen, tf2odis), } +/// # Safety +/// Only implement for valid prescalers with correct values pub unsafe trait HrtimPrescaler: Default { const BITS: u8; const VALUE: u8; diff --git a/src/hrtim/output.rs b/src/hrtim/output.rs index 6633acc3..45c97ca0 100644 --- a/src/hrtim/output.rs +++ b/src/hrtim/output.rs @@ -1,8 +1,8 @@ use crate::hrtim::external_event::ExternalEventSource; -use core::marker::PhantomData; -use stm32g4::stm32g474::{ +use crate::stm32::{ HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF, }; +use core::marker::PhantomData; use super::event::{EevFastOrNormal, EventSource, NeighborTimerEventSource}; use crate::{ diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs index fdaffd86..7291440b 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -1,7 +1,7 @@ -use core::marker::PhantomData; -use stm32g4::stm32g474::{ +use crate::stm32::{ HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF, }; +use core::marker::PhantomData; use super::{ control::HrPwmControl, diff --git a/src/hrtim/timer_eev_cfg.rs b/src/hrtim/timer_eev_cfg.rs index cfaa7667..96f79bde 100644 --- a/src/hrtim/timer_eev_cfg.rs +++ b/src/hrtim/timer_eev_cfg.rs @@ -57,10 +57,10 @@ impl Clone for EevCfgs { eev8: self.eev8.clone(), eev9: self.eev9.clone(), eev10: self.eev10.clone(), - event_counter_enable_bit: self.event_counter_enable_bit.clone(), - event_counter_reset_mode_bit: self.event_counter_reset_mode_bit.clone(), - event_counter_source_bits: self.event_counter_source_bits.clone(), - event_counter_threshold_bits: self.event_counter_threshold_bits.clone(), + event_counter_enable_bit: self.event_counter_enable_bit, + event_counter_reset_mode_bit: self.event_counter_reset_mode_bit, + event_counter_source_bits: self.event_counter_source_bits, + event_counter_threshold_bits: self.event_counter_threshold_bits, } } } @@ -75,8 +75,8 @@ impl Clone for EevCfg { fn clone(&self) -> Self { Self { _x: PhantomData, - filter_bits: self.filter_bits.clone(), - latch_bit: self.latch_bit.clone(), + filter_bits: self.filter_bits, + latch_bit: self.latch_bit, } } } From 7004ec6a21bf6f842c52906fb8bc3f526f881aaf Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 6 Jan 2024 02:01:31 +0100 Subject: [PATCH 45/88] HRTIM - Traitify adc_triggers --- src/hrtim/adc_trigger.rs | 21 + src/hrtim/compare_register.rs | 85 +++- src/hrtim/control.rs | 801 +++----------------------------- src/hrtim/external_event_new.rs | 243 ---------- src/hrtim/mod.rs | 1 + src/hrtim/timer.rs | 69 ++- 6 files changed, 224 insertions(+), 996 deletions(-) create mode 100644 src/hrtim/adc_trigger.rs delete mode 100644 src/hrtim/external_event_new.rs diff --git a/src/hrtim/adc_trigger.rs b/src/hrtim/adc_trigger.rs new file mode 100644 index 00000000..0fdd3fe4 --- /dev/null +++ b/src/hrtim/adc_trigger.rs @@ -0,0 +1,21 @@ + +use core::marker::PhantomData; + +pub trait Adc13Trigger { + const BITS: u32; +} + +pub trait Adc24Trigger { + const BITS: u32; +} + +pub trait Adc579Trigger { + const BITS: u32; +} + +pub trait Adc6810Trigger { + const BITS: u32; +} + +pub struct TimerReset(pub(crate)PhantomData); +pub struct TimerPeriod(pub(crate)PhantomData); \ No newline at end of file diff --git a/src/hrtim/compare_register.rs b/src/hrtim/compare_register.rs index 3c6b7ac9..32d52a84 100644 --- a/src/hrtim/compare_register.rs +++ b/src/hrtim/compare_register.rs @@ -14,8 +14,14 @@ pub struct HrCr2(PhantomData<(TIM, PSCL)>); pub struct HrCr3(PhantomData<(TIM, PSCL)>); pub struct HrCr4(PhantomData<(TIM, PSCL)>); + +use super::adc_trigger::Adc13Trigger as Adc13; +use super::adc_trigger::Adc24Trigger as Adc24; +use super::adc_trigger::Adc579Trigger as Adc579; +use super::adc_trigger::Adc6810Trigger as Adc6810; + macro_rules! hrtim_cr_helper { - ($TIMX:ident: $cr_type:ident: $cmpXYr:ident, $cmpYx:ident) => { + ($TIMX:ident: $cr_type:ident: $cmpXYr:ident, $cmpYx:ident, $(($Trigger:ty: $trigger_bits:expr)),*) => { impl HrCompareRegister for $cr_type<$TIMX, PSCL> { fn get_duty(&self) -> u16 { let tim = unsafe { &*$TIMX::ptr() }; @@ -28,28 +34,75 @@ macro_rules! hrtim_cr_helper { tim.$cmpXYr.write(|w| unsafe { w.$cmpYx().bits(duty) }); } } + + $(impl $Trigger for $cr_type<$TIMX, PSCL> { + const BITS: u32 = $trigger_bits; + })* }; } + macro_rules! hrtim_cr { ($($TIMX:ident: [ - $cmpX1r:ident, $cmpX2r:ident, $cmpX3r:ident, $cmpX4r:ident, - $cmp1x:ident, $cmp2x:ident, $cmp3x:ident, $cmp4x:ident - ],)+) => {$( - hrtim_cr_helper!($TIMX: HrCr1: $cmpX1r, $cmp1x); - hrtim_cr_helper!($TIMX: HrCr2: $cmpX2r, $cmp2x); - hrtim_cr_helper!($TIMX: HrCr3: $cmpX3r, $cmp3x); - hrtim_cr_helper!($TIMX: HrCr4: $cmpX4r, $cmp4x); + [$cmpX1r:ident, $cmp1x:ident, $(($cr1_trigger:ident: $cr1_trigger_bits:expr)),*], + [$cmpX2r:ident, $cmp2x:ident, $(($cr2_trigger:ident: $cr2_trigger_bits:expr)),*], + [$cmpX3r:ident, $cmp3x:ident, $(($cr3_trigger:ident: $cr3_trigger_bits:expr)),*], + [$cmpX4r:ident, $cmp4x:ident, $(($cr4_trigger:ident: $cr4_trigger_bits:expr)),*] + ]),+) => {$( + hrtim_cr_helper!($TIMX: HrCr1: $cmpX1r, $cmp1x, $(($cr1_trigger: $cr1_trigger_bits)),*); + hrtim_cr_helper!($TIMX: HrCr2: $cmpX2r, $cmp2x, $(($cr2_trigger: $cr2_trigger_bits)),*); + hrtim_cr_helper!($TIMX: HrCr3: $cmpX3r, $cmp3x, $(($cr3_trigger: $cr3_trigger_bits)),*); + hrtim_cr_helper!($TIMX: HrCr4: $cmpX4r, $cmp4x, $(($cr4_trigger: $cr4_trigger_bits)),*); )+}; } hrtim_cr! { - HRTIM_MASTER: [mcmp1r, mcmp2r, mcmp3r, mcmp4r, mcmp1, mcmp2, mcmp3, mcmp4], - - HRTIM_TIMA: [cmp1ar, cmp2ar, cmp3ar, cmp4ar, cmp1x, cmp2x, cmp3x, cmp4x], - HRTIM_TIMB: [cmp1br, cmp2br, cmp3br, cmp4br, cmp1x, cmp2x, cmp3x, cmp4x], - HRTIM_TIMC: [cmp1cr, cmp2cr, cmp3cr, cmp4cr, cmp1x, cmp2x, cmp3x, cmp4x], - HRTIM_TIMD: [cmp1dr, cmp2dr, cmp3dr, cmp4dr, cmp1x, cmp2x, cmp3x, cmp4x], - HRTIM_TIME: [cmp1er, cmp2er, cmp3er, cmp4er, cmp1x, cmp2x, cmp3x, cmp4x], - HRTIM_TIMF: [cmp1fr, cmp2fr, cmp3fr, cmp4fr, cmp1x, cmp2x, cmp3x, cmp4x], + HRTIM_MASTER: [ + [mcmp1r,mcmp1, (Adc13: 1 << 0), (Adc24: 1 << 0), (Adc579: 0), (Adc6810: 0) ], + [mcmp2r,mcmp2, (Adc13: 1 << 1), (Adc24: 1 << 1), (Adc579: 1), (Adc6810: 1) ], + [mcmp3r,mcmp3, (Adc13: 1 << 2), (Adc24: 1 << 2), (Adc579: 2), (Adc6810: 2) ], + [mcmp4r,mcmp4, (Adc13: 1 << 3), (Adc24: 1 << 3), (Adc579: 3), (Adc6810: 3) ] + ], + + HRTIM_TIMA: [ + [cmp1ar, cmp1x, ], + [cmp2ar, cmp2x, (Adc24: 1 << 10), (Adc6810: 10)], + [cmp3ar, cmp3x, (Adc13: 1 << 11), (Adc579: 10) ], + [cmp4ar, cmp4x, (Adc13: 1 << 12), (Adc24: 1 << 12), (Adc579: 11), (Adc6810: 11)] + ], + + HRTIM_TIMB: [ + [cmp1br, cmp1x, ], + [cmp2br, cmp2x, (Adc24: 1 << 14), (Adc6810: 13)], + [cmp3br, cmp3x, (Adc13: 1 << 16), (Adc579: 14) ], + [cmp4br, cmp4x, (Adc13: 1 << 17), (Adc24: 1 << 16), (Adc579: 15), (Adc6810: 14)] + ], + + HRTIM_TIMC: [ + [cmp1cr, cmp1x, ], + [cmp2cr, cmp2x, (Adc24: 1 << 18), (Adc6810: 16)], + [cmp3cr, cmp3x, (Adc13: 1 << 21), (Adc579: 18) ], + [cmp4cr, cmp4x, (Adc13: 1 << 22), (Adc24: 1 << 20), (Adc579: 19), (Adc6810: 17)] + ], + + HRTIM_TIMD: [ + [cmp1dr, cmp1x, ], + [cmp2dr, cmp2x, (Adc24: 1 << 23), (Adc6810: 20)], + [cmp3dr, cmp3x, (Adc13: 1 << 25), (Adc579: 21) ], + [cmp4dr, cmp4x, (Adc13: 1 << 26), (Adc24: 1 << 25), (Adc579: 22), (Adc6810: 21)] + ], + + HRTIM_TIME: [ + [cmp1er, cmp1x, ], + [cmp2er, cmp2x, (Adc24: 1 << 28), (Adc6810: 24)], + [cmp3er, cmp3x, (Adc13: 1 << 29), (Adc24: 1 << 29), (Adc579: 24), (Adc6810: 25)], + [cmp4er, cmp4x, (Adc13: 1 << 30), (Adc24: 1 << 30), (Adc579: 25), (Adc6810: 26)] + ], + + HRTIM_TIMF: [ + [cmp1fr, cmp1x, (Adc24: 1 << 15) ], + [cmp2fr, cmp2x, (Adc13: 1 << 10), (Adc24: 1 << 11), (Adc579: 27), (Adc6810: 28)], + [cmp3fr, cmp3x, (Adc13: 1 << 15), (Adc579: 28), (Adc6810: 29)], + [cmp4fr, cmp4x, (Adc13: 1 << 20), (Adc24: 1 << 19), (Adc579: 29), (Adc6810: 30)] + ] } diff --git a/src/hrtim/control.rs b/src/hrtim/control.rs index ecf7a6fb..cc466737 100644 --- a/src/hrtim/control.rs +++ b/src/hrtim/control.rs @@ -31,18 +31,6 @@ impl HrControltExt for HRTIM_COMMON { .write(|w| w.cal().set_bit().calen().clear_bit()); HrTimOngoingCalibration { - adc_trigger1_bits: 0, - adc_trigger2_bits: 0, - adc_trigger3_bits: 0, - adc_trigger4_bits: 0, - - adc_trigger5_bits: 0, - adc_trigger6_bits: 0, - adc_trigger7_bits: 0, - adc_trigger8_bits: 0, - adc_trigger9_bits: 0, - adc_trigger10_bits: 0, - adc_trigger1_postscaler: AdcTriggerPostscaler::None, adc_trigger2_postscaler: AdcTriggerPostscaler::None, adc_trigger3_postscaler: AdcTriggerPostscaler::None, @@ -62,18 +50,6 @@ impl HrControltExt for HRTIM_COMMON { } pub struct HrTimOngoingCalibration { - adc_trigger1_bits: u32, - adc_trigger2_bits: u32, - adc_trigger3_bits: u32, - adc_trigger4_bits: u32, - - adc_trigger5_bits: u8, - adc_trigger6_bits: u8, - adc_trigger7_bits: u8, - adc_trigger8_bits: u8, - adc_trigger9_bits: u8, - adc_trigger10_bits: u8, - adc_trigger1_postscaler: AdcTriggerPostscaler, adc_trigger2_postscaler: AdcTriggerPostscaler, adc_trigger3_postscaler: AdcTriggerPostscaler, @@ -93,24 +69,9 @@ pub struct HrTimOngoingCalibration { impl HrTimOngoingCalibration { /// SAFETY: Calibration needs to be done before calling this unsafe fn init(self) { - use Adc13Trigger as Ad13T; - use Adc24Trigger as Ad24T; - let common = unsafe { &*HRTIM_COMMON::ptr() }; let Self { - adc_trigger1_bits: ad1_bits, - adc_trigger2_bits: ad2_bits, - adc_trigger3_bits: ad3_bits, - adc_trigger4_bits: ad4_bits, - - adc_trigger5_bits: ad5_bits, - adc_trigger6_bits: ad6_bits, - adc_trigger7_bits: ad7_bits, - adc_trigger8_bits: ad8_bits, - adc_trigger9_bits: ad9_bits, - adc_trigger10_bits: ad10_bits, - adc_trigger1_postscaler, adc_trigger2_postscaler, adc_trigger3_postscaler, @@ -137,259 +98,6 @@ impl HrTimOngoingCalibration { common.fltinr2.write(|w| w.fltsd().bits(flt_divider as u8)); common.eecr3.write(|w| w.eevsd().bits(eev_divider as u8)); - common.adc1r.write(|w| { - w.eper() - .bit(ad1_bits | Ad13T::TimEPeriod as u32 != 0) - .ec4() - .bit(ad1_bits | Ad13T::TimECmp4 as u32 != 0) - .ec3() - .bit(ad1_bits | Ad13T::TimECmp3 as u32 != 0) - //.frst() - .dper() - .bit(ad1_bits | Ad13T::TimDPeriod as u32 != 0) - .dc4() - .bit(ad1_bits | Ad13T::TimDCmp4 as u32 != 0) - .dc3() - .bit(ad1_bits | Ad13T::TimDCmp3 as u32 != 0) - .fper() - .bit(ad1_bits | Ad13T::TimFPeriod as u32 != 0) - .cper() - .bit(ad1_bits | Ad13T::TimCPeriod as u32 != 0) - .cc4() - .bit(ad1_bits | Ad13T::TimCCmp4 as u32 != 0) - .cc3() - .bit(ad1_bits | Ad13T::TimCCmp3 as u32 != 0) - .fc4() - .bit(ad1_bits | Ad13T::TimFCmp4 as u32 != 0) - //.brst() - .bper() - .bit(ad1_bits | Ad13T::TimBPeriod as u32 != 0) - .bc4() - .bit(ad1_bits | Ad13T::TimBCmp4 as u32 != 0) - .bc3() - .bit(ad1_bits | Ad13T::TimBCmp3 as u32 != 0) - .fc3() - .bit(ad1_bits | Ad13T::TimFCmp3 as u32 != 0) - //.arst() - .aper() - .bit(ad1_bits | Ad13T::TimAPeriod as u32 != 0) - .ac4() - .bit(ad1_bits | Ad13T::TimACmp4 as u32 != 0) - .ac3() - .bit(ad1_bits | Ad13T::TimACmp3 as u32 != 0) - .fc2() - .bit(ad1_bits | Ad13T::TimFCmp2 as u32 != 0) - //.eev5().bit(ad1_bits | Ad13T::_ as u32) - //.eev4().bit(ad1_bits | Ad13T::_ as u32) - //.eev3().bit(ad1_bits | Ad13T::_ as u32) - //.eev2().bit(ad1_bits | Ad13T::_ as u32) - //.eev1().bit(ad1_bits | Ad13T::_ as u32) - .mper() - .bit(ad1_bits | Ad13T::MasterPeriod as u32 != 0) - .mc4() - .bit(ad1_bits | Ad13T::MasterCmp4 as u32 != 0) - .mc3() - .bit(ad1_bits | Ad13T::MasterCmp3 as u32 != 0) - .mc2() - .bit(ad1_bits | Ad13T::MasterCmp2 as u32 != 0) - .mc1() - .bit(ad1_bits | Ad13T::MasterCmp1 as u32 != 0) - }); - - common.adc3r.write(|w| { - w.eper() - .bit(ad3_bits | Ad13T::TimEPeriod as u32 != 0) - .ec4() - .bit(ad3_bits | Ad13T::TimECmp4 as u32 != 0) - .ec3() - .bit(ad3_bits | Ad13T::TimECmp3 as u32 != 0) - //.frst() - .dper() - .bit(ad3_bits | Ad13T::TimDPeriod as u32 != 0) - .dc4() - .bit(ad3_bits | Ad13T::TimDCmp4 as u32 != 0) - .dc3() - .bit(ad3_bits | Ad13T::TimDCmp3 as u32 != 0) - .fper() - .bit(ad3_bits | Ad13T::TimFPeriod as u32 != 0) - .cper() - .bit(ad3_bits | Ad13T::TimCPeriod as u32 != 0) - .cc4() - .bit(ad3_bits | Ad13T::TimCCmp4 as u32 != 0) - .cc3() - .bit(ad3_bits | Ad13T::TimCCmp3 as u32 != 0) - .fc4() - .bit(ad3_bits | Ad13T::TimFCmp4 as u32 != 0) - //.brst() - .bper() - .bit(ad3_bits | Ad13T::TimBPeriod as u32 != 0) - .bc4() - .bit(ad3_bits | Ad13T::TimBCmp4 as u32 != 0) - .bc3() - .bit(ad3_bits | Ad13T::TimBCmp3 as u32 != 0) - .fc3() - .bit(ad3_bits | Ad13T::TimFCmp3 as u32 != 0) - //.arst() - .aper() - .bit(ad3_bits | Ad13T::TimAPeriod as u32 != 0) - .ac4() - .bit(ad3_bits | Ad13T::TimACmp4 as u32 != 0) - .ac3() - .bit(ad3_bits | Ad13T::TimACmp3 as u32 != 0) - .fc2() - .bit(ad3_bits | Ad13T::TimFCmp2 as u32 != 0) - //.eev5().bit(ad3_bits | Ad13T::_ as u32) - //.eev4().bit(ad3_bits | Ad13T::_ as u32) - //.eev3().bit(ad3_bits | Ad13T::_ as u32) - //.eev2().bit(ad3_bits | Ad13T::_ as u32) - //.eev1().bit(ad3_bits | Ad13T::_ as u32) - .mper() - .bit(ad3_bits | Ad13T::MasterPeriod as u32 != 0) - .mc4() - .bit(ad3_bits | Ad13T::MasterCmp4 as u32 != 0) - .mc3() - .bit(ad3_bits | Ad13T::MasterCmp3 as u32 != 0) - .mc2() - .bit(ad3_bits | Ad13T::MasterCmp2 as u32 != 0) - .mc1() - .bit(ad3_bits | Ad13T::MasterCmp1 as u32 != 0) - }); - - common.adc2r.write(|w| { - w - //.erst() - .ec4() - .bit(ad2_bits | Ad24T::TimECmp4 as u32 != 0) - .ec3() - .bit(ad2_bits | Ad24T::TimECmp3 as u32 != 0) - .ec2() - .bit(ad2_bits | Ad24T::TimECmp2 as u32 != 0) - //.drst().bit(ad2_bits | Ad24T::_ as u32 != 0) - .dper() - .bit(ad2_bits | Ad24T::TimDPeriod as u32 != 0) - .dc4() - .bit(ad2_bits | Ad24T::TimDCmp4 as u32 != 0) - .fper() - .bit(ad2_bits | Ad24T::TimFPeriod as u32 != 0) - .dc2() - .bit(ad2_bits | Ad24T::TimDCmp2 as u32 != 0) - //.crst().bit(ad2_bits | Ad24T::_ as u32 != 0) - .cper() - .bit(ad2_bits | Ad24T::TimCPeriod as u32 != 0) - .cc4() - .bit(ad2_bits | Ad24T::TimCCmp4 as u32 != 0) - .fc4() - .bit(ad2_bits | Ad24T::TimFCmp4 as u32 != 0) - .cc2() - .bit(ad2_bits | Ad24T::TimCCmp2 as u32 != 0) - .bper() - .bit(ad2_bits | Ad24T::TimBPeriod as u32 != 0) - .bc4() - .bit(ad2_bits | Ad24T::TimBCmp4 as u32 != 0) - .fc3() - .bit(ad2_bits | Ad24T::TimFCmp3 as u32 != 0) - .bc2() - .bit(ad2_bits | Ad24T::TimBCmp2 as u32 != 0) - .aper() - .bit(ad2_bits | Ad24T::TimAPeriod as u32 != 0) - .ac4() - .bit(ad2_bits | Ad24T::TimACmp4 as u32 != 0) - .fc2() - .bit(ad2_bits | Ad24T::TimFCmp2 as u32 != 0) - .ac2() - .bit(ad2_bits | Ad24T::TimACmp2 as u32 != 0) - //.eev10() - //.eev9() - //.eev8() - //.eev7() - //.eev6() - .mper() - .bit(ad2_bits | Ad24T::MasterPeriod as u32 != 0) - .mc4() - .bit(ad2_bits | Ad24T::MasterCmp4 as u32 != 0) - .mc3() - .bit(ad2_bits | Ad24T::MasterCmp3 as u32 != 0) - .mc2() - .bit(ad2_bits | Ad24T::MasterCmp2 as u32 != 0) - .mc1() - .bit(ad2_bits | Ad24T::MasterCmp1 as u32 != 0) - }); - - common.adc4r.write(|w| { - w - //.erst() - .ec4() - .bit(ad4_bits | Ad24T::TimECmp4 as u32 != 0) - .ec3() - .bit(ad4_bits | Ad24T::TimECmp3 as u32 != 0) - .ec2() - .bit(ad4_bits | Ad24T::TimECmp2 as u32 != 0) - //.drst().bit(ad4_bits | Ad24T::_ as u32 != 0) - .dper() - .bit(ad4_bits | Ad24T::TimDPeriod as u32 != 0) - .dc4() - .bit(ad4_bits | Ad24T::TimDCmp4 as u32 != 0) - .fper() - .bit(ad4_bits | Ad24T::TimFPeriod as u32 != 0) - .dc2() - .bit(ad4_bits | Ad24T::TimDCmp2 as u32 != 0) - //.crst().bit(ad4_bits | Ad24T::_ as u32 != 0) - .cper() - .bit(ad4_bits | Ad24T::TimCPeriod as u32 != 0) - .cc4() - .bit(ad4_bits | Ad24T::TimCCmp4 as u32 != 0) - .fc4() - .bit(ad4_bits | Ad24T::TimFCmp4 as u32 != 0) - .cc2() - .bit(ad4_bits | Ad24T::TimCCmp2 as u32 != 0) - .bper() - .bit(ad4_bits | Ad24T::TimBPeriod as u32 != 0) - .bc4() - .bit(ad4_bits | Ad24T::TimBCmp4 as u32 != 0) - .fc3() - .bit(ad4_bits | Ad24T::TimFCmp3 as u32 != 0) - .bc2() - .bit(ad4_bits | Ad24T::TimBCmp2 as u32 != 0) - .aper() - .bit(ad4_bits | Ad24T::TimAPeriod as u32 != 0) - .ac4() - .bit(ad4_bits | Ad24T::TimACmp4 as u32 != 0) - .fc2() - .bit(ad4_bits | Ad24T::TimFCmp2 as u32 != 0) - .ac2() - .bit(ad4_bits | Ad24T::TimACmp2 as u32 != 0) - //.eev10() - //.eev9() - //.eev8() - //.eev7() - //.eev6() - .mper() - .bit(ad4_bits | Ad24T::MasterPeriod as u32 != 0) - .mc4() - .bit(ad4_bits | Ad24T::MasterCmp4 as u32 != 0) - .mc3() - .bit(ad4_bits | Ad24T::MasterCmp3 as u32 != 0) - .mc2() - .bit(ad4_bits | Ad24T::MasterCmp2 as u32 != 0) - .mc1() - .bit(ad4_bits | Ad24T::MasterCmp1 as u32 != 0) - }); - - common.adcer.write(|w| { - w.adc5trg() - .variant(ad5_bits) - .adc6trg() - .variant(ad6_bits) - .adc7trg() - .variant(ad7_bits) - .adc8trg() - .variant(ad8_bits) - .adc9trg() - .variant(ad9_bits) - .adc10trg() - .variant(ad10_bits) - }); - common.adcps1.write(|w| { w.adc1psc() .bits(adc_trigger1_postscaler as u8) @@ -436,56 +144,6 @@ impl HrTimOngoingCalibration { ) } - pub fn enable_adc_trigger1_source(mut self, trigger: Adc13Trigger) -> Self { - self.adc_trigger1_bits |= trigger as u32; - self - } - - pub fn enable_adc_trigger2_source(mut self, trigger: Adc24Trigger) -> Self { - self.adc_trigger2_bits |= trigger as u32; - self - } - - pub fn enable_adc_trigger3_source(mut self, trigger: Adc13Trigger) -> Self { - self.adc_trigger3_bits |= trigger as u32; - self - } - - pub fn enable_adc_trigger4_source(mut self, trigger: Adc24Trigger) -> Self { - self.adc_trigger4_bits |= trigger as u32; - self - } - - pub fn enable_adc_trigger5_source(mut self, trigger: Adc579Trigger) -> Self { - self.adc_trigger5_bits = trigger as u8; - self - } - - pub fn enable_adc_trigger6_source(mut self, trigger: Adc6810Trigger) -> Self { - self.adc_trigger6_bits = trigger as u8; - self - } - - pub fn enable_adc_trigger7_source(mut self, trigger: Adc579Trigger) -> Self { - self.adc_trigger7_bits = trigger as u8; - self - } - - pub fn enable_adc_trigger8_source(mut self, trigger: Adc6810Trigger) -> Self { - self.adc_trigger8_bits = trigger as u8; - self - } - - pub fn enable_adc_trigger9_source(mut self, trigger: Adc579Trigger) -> Self { - self.adc_trigger9_bits = trigger as u8; - self - } - - pub fn enable_adc_trigger10_source(mut self, trigger: Adc6810Trigger) -> Self { - self.adc_trigger10_bits = trigger as u8; - self - } - pub fn set_adc1_trigger_psc(mut self, post_scaler: AdcTriggerPostscaler) -> Self { self.adc_trigger1_postscaler = post_scaler; self @@ -515,8 +173,6 @@ impl HrTimOngoingCalibration { self.eev_divider = divider; self } - - // TODO: Adc trigger 5-10 } /// This object may be used for things that needs to be done before any timers have been started but after the calibration has been completed. Its existence is proof that no timers have started. @@ -552,6 +208,79 @@ pub struct HrPwmControl { pub fault_5: FltMonitor5, pub fault_6: FltMonitor6, } + +use super::adc_trigger::{Adc13Trigger, Adc24Trigger, Adc579Trigger, Adc6810Trigger}; + +impl HrPwmControl { + pub fn enable_adc_trigger1_source(&mut self, _trigger: T) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + unsafe { common.adc1r.modify(|r, w| w.bits(r.bits() | T::BITS)); } + } + + pub fn enable_adc_trigger2_source(&mut self, _trigger: T) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + unsafe { common.adc2r.modify(|r, w| w.bits(r.bits() | T::BITS)); } + } + + pub fn enable_adc_trigger3_source(&mut self, _trigger: T) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + unsafe { common.adc3r.modify(|r, w| w.bits(r.bits() | T::BITS)); } + } + + pub fn enable_adc_trigger4_source(&mut self, _trigger: T) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + unsafe { common.adc4r.modify(|r, w| w.bits(r.bits() | T::BITS)); } + } + + pub fn enable_adc_trigger5_source(&mut self, _trigger: T) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.adcer.modify(|_r, w| { + w.adc5trg() + .variant(T::BITS as u8) + }); + } + + pub fn enable_adc_trigger6_source(&mut self, _trigger: T) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.adcer.modify(|_r, w| { + w.adc6trg() + .variant(T::BITS as u8) + }); + } + + pub fn enable_adc_trigger7_source(&mut self, _trigger: T) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.adcer.modify(|_r, w| { + w.adc7trg() + .variant(T::BITS as u8) + }); + } + + pub fn enable_adc_trigger8_source(&mut self, _trigger: T) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.adcer.modify(|_r, w| { + w.adc8trg() + .variant(T::BITS as u8) + }); + } + + pub fn enable_adc_trigger9_source(&mut self, _trigger: T) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.adcer.modify(|_r, w| { + w.adc9trg() + .variant(T::BITS as u8) + }); + } + + pub fn enable_adc_trigger10_source(&mut self, _trigger: T) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.adcer.modify(|_r, w| { + w.adc10trg() + .variant(T::BITS as u8) + }); + } +} + pub enum AdcTriggerPostscaler { None = 0, Div2 = 1, @@ -608,386 +337,4 @@ pub enum SamplingClkDiv { /// /// fault signal sampling clock f_flts = f_hrtim / 8 Eight = 0b11, -} - -pub enum Adc13Trigger { - /// bit 31 ADCxTEPER - Trigger on HRTIM_TIME period - TimEPeriod = 1 << 31, - - /// bit 30 ADCxTEC4 - Trigger on HRTIM_TIME compare match for compare register 4 - TimECmp4 = 1 << 30, - - /// bit 29 ADCxTEC3 - Trigger on HRTIM_TIME compare match for compare register 3 - TimECmp3 = 1 << 29, - - /// bit 28 ADCxTFRST - Trigger on HRTIM_TIMF reset or counter roll-over - TimFRst = 1 << 28, - - /// bit 27 ADCxTDPER - Trigger on HRTIM_TIMD period - TimDPeriod = 1 << 27, - - /// bit 26 ADCxTDC4 - Trigger on HRTIM_TIMD compare match for compare register 4 - TimDCmp4 = 1 << 26, - - /// bit 25 ADCxTDC3 - Trigger on HRTIM_TIMD compare match for compare register 3 - TimDCmp3 = 1 << 25, - - /// bit 24 ADCxTFPER - Trigger on HRTIM_TIMF period - TimFPeriod = 1 << 24, - - /// bit 23 ADCxTCPER - Trigger on HRTIM_TIMC period - TimCPeriod = 1 << 23, - - /// bit 22 ADCxTCC4 - Trigger on HRTIM_TIMC compare match for compare register 4 - TimCCmp4 = 1 << 22, - - /// bit 21 ADCxTCC3 - Trigger on HRTIM_TIMC compare match for compare register 3 - TimCCmp3 = 1 << 21, - - /// bit 20 ADCxTFC4 - Trigger on HRTIM_TIMF compare match for compare register 4 - TimFCmp4 = 1 << 20, - - /// bit 19 ADCxTBRST - Trigger on HRTIM_TIMB reset or counter roll-over - TimBRst = 1 << 19, - - /// bit 18 ADCxTBPER - Trigger on HRTIM_TIMB period - TimBPeriod = 1 << 18, - - /// bit 17 ADCxTBC4 - Trigger on HRTIM_TIMB compare match for compare register 4 - TimBCmp4 = 1 << 17, - - /// bit 16 ADCxTBC3 - Trigger on HRTIM_TIMB compare match for compare register 3 - TimBCmp3 = 1 << 16, - - /// bit 15 ADCxTFC3 - Trigger on HRTIM_TIMF compare match for compare register 3 - TimFCmp3 = 1 << 15, - - /// bit 14 ADCxTARST - Trigger on HRTIM_TIMA reset or counter roll-over - TimARst = 1 << 14, - - /// bit 13 ADCxTAPER - Trigger on HRTIM_TIMA period - TimAPeriod = 1 << 13, - - /// bit 12 ADCxTAC4 - Trigger on HRTIM_TIMA compare match for compare register 4 - TimACmp4 = 1 << 12, - - /// bit 11 ADCxTAC3 - Trigger on HRTIM_TIMA compare match for compare register 3 - TimACmp3 = 1 << 11, - - /// bit 10 ADCxTFC2 - Trigger on HRTIM_TIMF compare match for compare register 2 - TimFCmp2 = 1 << 10, - - // /// bit 9 ADCxEEV5 - // _ = 1 << 9, - - // /// bit 8 ADCxEEV4 - // _ = 1 << 8, - - // /// bit 7 ADCxEEV3 - // _ = 1 << 7, - - // /// bit 6 ADCxEEV2 - // _ = 1 << 6, - /// bit 5 ADCxEEV1 - // _ = 1 << 5, - - /// bit 4 ADCxMPER - Trigger on HRTIM_MASTER period - MasterPeriod = 1 << 4, - - /// bit 3 ADCxMC4 - Trigger on HRTIM_MASTER compare match for compare register 4 - MasterCmp4 = 1 << 3, - - /// bit 2 ADCxMC3 - Trigger on HRTIM_MASTER compare match for compare register 3 - MasterCmp3 = 1 << 2, - - /// bit 1 ADCxMC2 - Trigger on HRTIM_MASTER compare match for compare register 2 - MasterCmp2 = 1 << 1, - - /// bit 0 ADCxMC1 - Trigger on HRTIM_MASTER compare match for compare register 1 - MasterCmp1 = 1 << 0, -} - -pub enum Adc24Trigger { - /// bit 31 ADCxTERST - Trigger on HRTIM_TIME reset or counter roll-over - TimERst = 1 << 31, - - /// bit 30 ADCxTEC4 - Trigger on HRTIM_TIME compare match for compare register 4 - TimECmp4 = 1 << 30, - - /// bit 29 ADCxTEC3 - Trigger on HRTIM_TIME compare match for compare register 3 - TimECmp3 = 1 << 29, - - /// bit 28 ADCxTEC2 - Trigger on HRTIM_TIME compare match for compare register 2 - TimECmp2 = 1 << 28, - - /// bit 27 ADCxTDRST - Trigger on HRTIM_TIMD reset or counter roll-over - TimDRst = 1 << 27, - - /// bit 26 ADCxTDPER - Trigger on HRTIM_TIMD period - TimDPeriod = 1 << 26, - - /// bit 25 ADCxTDC4 - Trigger on HRTIM_TIMD compare match for compare register 4 - TimDCmp4 = 1 << 25, - - /// bit 24 ADCxTFPER - Trigger on HRTIM_TIMF period - TimFPeriod = 1 << 24, - - /// bit 23 ADCxTDC2 - Trigger on HRTIM_TIMD compare match for compare register 2 - TimDCmp2 = 1 << 23, - - /// bit 22 ADCxTCRST - Trigger on HRTIM_TIMC reset or counter roll-over - TimCRst = 1 << 22, - - /// bit 21 ADCxTCPER - Trigger on HRTIM_TIMC period - TimCPeriod = 1 << 21, - - /// bit 20 ADCxTCC4 - Trigger on HRTIM_TIMC compare match for compare register 4 - TimCCmp4 = 1 << 20, - - /// bit 19 ADCxTFC4 - Trigger on HRTIM_TIMF compare match for compare register 4 - TimFCmp4 = 1 << 19, - - /// bit 18 ADCxTCC2 - Trigger on HRTIM_TIMC compare match for compare register 2 - TimCCmp2 = 1 << 18, - - /// bit 17 ADCxTBPER - Trigger on HRTIM_TIMB period - TimBPeriod = 1 << 17, - - /// bit 16 ADCxTBC4 - Trigger on HRTIM_TIMB compare match for compare register 4 - TimBCmp4 = 1 << 16, - - /// bit 15 ADCxTFC3 - Trigger on HRTIM_TIMF compare match for compare register 3 - TimFCmp3 = 1 << 15, - - /// bit 14 ADCxTBC2 - Trigger on HRTIM_TIMB compare match for compare register 2 - TimBCmp2 = 1 << 14, - - /// bit 13 ADCxTAPER - Trigger on HRTIM_TIMA period - TimAPeriod = 1 << 13, - - /// bit 12 ADCxTAC4 - Trigger on HRTIM_TIMA compare match for compare register 4 - TimACmp4 = 1 << 12, - - /// bit 11 ADCxTFC2 - Trigger on HRTIM_TIMF compare match for compare register 2 - TimFCmp2 = 1 << 11, - - /// bit 10 ADCxTAC2 - Trigger on HRTIM_TIMA compare match for compare register 2 - TimACmp2 = 1 << 10, - - // /// bit 9 ADCxEEV10 - // _ = 1 << 9, - - // /// bit 8 ADCxEEV9 - // _ = 1 << 8, - - // /// bit 7 ADCxEEV8 - // _ = 1 << 7, - - // /// bit 6 ADCxEEV7 - // _ = 1 << 6, - - // /// bit 5 ADCxEEV6 - // _ = 1 << 5, - /// bit 4 ADCxMPER - Trigger on HRTIM_MASTER period - MasterPeriod = 1 << 4, - - /// bit 3 ADCxMC4 - Trigger on HRTIM_MASTER compare match for compare register 4 - MasterCmp4 = 1 << 3, - - /// bit 2 ADCxMC3 - Trigger on HRTIM_MASTER compare match for compare register 3 - MasterCmp3 = 1 << 2, - - /// bit 1 ADCxMC2 - Trigger on HRTIM_MASTER compare match for compare register 2 - MasterCmp2 = 1 << 1, - - /// bit 0 ADCxMC1 - Trigger on HRTIM_MASTER compare match for compare register 1 - MasterCmp1 = 1 << 0, -} - -pub enum Adc579Trigger { - // /// Trigger on F reset and counter roll-over - // _ = 31 - /// Trigger on HRTIM_TIMF period - TimFPeriod = 30, - - /// Trigger on HRTIM_TIMF compare match for compare register 4 - TimFCmp4 = 29, - - /// Trigger on HRTIM_TIMF compare match for compare register 3 - TimFCmp3 = 28, - - /// Trigger on HRTIM_TIMF compare match for compare register 2 - TimFCmp2 = 27, - - /// Trigger on HRTIM_TIME period - TimEPeriod = 26, - - /// Trigger on HRTIM_TIME compare match for compare register 4 - TimECmp4 = 25, - - /// Trigger on HRTIM_TIME compare match for compare register 3 - TimECmp3 = 24, - - /// Trigger on HRTIM_TIMD period - TimDPeriod = 23, - - /// Trigger on HRTIM_TIMD compare match for compare register 4 - TimDCmp4 = 22, - - /// Trigger on HRTIM_TIMD compare match for compare register 3 - TimDCmp3 = 21, - - /// Trigger on HRTIM_TIMC period - TimCPeriod = 20, - - /// Trigger on HRTIM_TIMC compare match for compare register 4 - TimCCmp4 = 19, - - /// Trigger on HRTIM_TIMC compare match for compare register 3 - TimCCmp3 = 18, - - // /// Trigger on B reset and counter roll-over - // _ = 17 - /// Trigger on HRTIM_TIMB period - TimBPeriod = 16, - - /// Trigger on HRTIM_TIMB compare match for compare register 4 - TimBCmp4 = 15, - - /// Trigger on HRTIM_TIMB compare match for compare register 3 - TimBCmp3 = 14, - - // /// Trigger on A reset and counter roll-over - // _ = 13 - /// Trigger on HRTIM_TIMA period - TimAPeriod = 12, - - /// Trigger on HRTIM_TIMA compare match for compare register 4 - TimACmp4 = 11, - - /// Trigger on HRTIM_TIMA compare match for compare register 3 - TimACmp3 = 10, - - // /// Trigger on EEV5 - // _ = 9, - - // /// Trigger on EEV4 - // _ = 8, - - // /// Trigger on EEV3 - // _ = 7, - - // /// Trigger on EEV2 - // _ = 6, - - // /// Trigger on EEV1 - // _ = 5, - /// Trigger on HRTIM_MASTER period - MasterPeriod = 4, - - /// Trigger on HRTIM_MASTER compare match for compare register 4 - MasterCmp4 = 3, - - /// Trigger on HRTIM_MASTER compare match for compare register 3 - MasterCmp3 = 2, - - /// Trigger on HRTIM_MASTER compare match for compare register 2 - MasterCmp2 = 1, - - /// Trigger on HRTIM_MASTER compare match for compare register 1 - MasterCmp1 = 0, -} - -pub enum Adc6810Trigger { - /// Trigger on HRTIM_TIMF period - TimFPeriod = 31, - - /// Trigger on HRTIM_TIMF compare match for compare register 4 - TimFCmp4 = 30, - - /// Trigger on HRTIM_TIMF compare match for compare register 3 - TimFCmp3 = 29, - - /// Trigger on HRTIM_TIMF compare match for compare register 2 - TimFCmp2 = 28, - - // /// Trigger on E reset and counter roll-over - // _ = 27 - /// Trigger on HRTIM_TIME compare match for compare register 4 - TimECmp4 = 26, - - /// Trigger on HRTIM_TIME compare match for compare register 3 - TimECmp3 = 25, - - /// Trigger on HRTIM_TIME compare match for compare register 2 - TimECmp2 = 24, - - // /// Trigger on D reset and counter roll-over - // _ = 23 - /// Trigger on HRTIM_TIMD period - TimDPeriod = 22, - - /// Trigger on HRTIM_TIMD compare match for compare register 4 - TimDCmp4 = 21, - - /// Trigger on HRTIM_TIMD compare match for compare register 2 - TimDCmp2 = 20, - - // /// Trigger on D reset and counter roll-over - // _ = 19 - /// Trigger on HRTIM_TIMC period - TimCPeriod = 18, - - /// Trigger on HRTIM_TIMC compare match for compare register 4 - TimCCmp4 = 17, - - /// Trigger on HRTIM_TIMC compare match for compare register 2 - TimCCmp2 = 16, - - /// Trigger on HRTIM_TIMB period - TimBPeriod = 15, - - /// Trigger on HRTIM_TIMB compare match for compare register 4 - TimBCmp4 = 14, - - /// Trigger on HRTIM_TIMB compare match for compare register 2 - TimBCmp2 = 13, - - /// Trigger on HRTIM_TIMA period - TimAPeriod = 12, - - /// Trigger on HRTIM_TIMA compare match for compare register 4 - TimACmp4 = 11, - - /// Trigger on HRTIM_TIMA compare match for compare register 2 - TimACmp2 = 10, - - // /// Trigger on EEV10 - // _ = 9, - - // /// Trigger on EEV9 - // _ = 8, - - // /// Trigger on EEV8 - // _ = 7, - - // /// Trigger on EEV7 - // _ = 6, - - // /// Trigger on EEV6 - // _ = 5, - /// Trigger on HRTIM_MASTER period - MasterPeriod = 4, - - /// Trigger on HRTIM_MASTER compare match for compare register 4 - MasterCmp4 = 3, - - /// Trigger on HRTIM_MASTER compare match for compare register 3 - MasterCmp3 = 2, - - /// Trigger on HRTIM_MASTER compare match for compare register 2 - MasterCmp2 = 1, - - /// Trigger on HRTIM_MASTER compare match for compare register 1 - MasterCmp1 = 0, -} +} \ No newline at end of file diff --git a/src/hrtim/external_event_new.rs b/src/hrtim/external_event_new.rs deleted file mode 100644 index 2ffa5d74..00000000 --- a/src/hrtim/external_event_new.rs +++ /dev/null @@ -1,243 +0,0 @@ -use core::marker::PhantomData; - -use crate::comparator::{COMP1, COMP2, COMP3, COMP4, COMP5, COMP6}; -use crate::gpio::gpioa::{PA12, PA15}; -use crate::gpio::gpiob::{PB0, PB10, PB11}; -use crate::gpio::gpioc::{PC10, PC7}; -use crate::gpio::{self, AF13, AF3}; -use crate::hrtim::control::HrPwmControl; -use crate::pwm::FaultMonitor; -use crate::stm32::HRTIM_COMMON; - -pub struct SourceBuilder { - /// EExSRC - src_bits: u8, - - /// EExSNS - edge_or_polarity_bits: u8, - - /// EExPOL - polarity_bit: bool, - - /// EExF - filter_bits: u8, - - /// EExFAST - fast_bit: bool, -} - -impl SourceBuilder { - unsafe fn new(src_bits: u8) -> Self { - SourceBuilder { - src_bits, - edge_or_polarity_bits: 0, // Polarity sensitive - polarity_bit: false, // Active high - filter_bits: 0, // No filter - fast_bit: false, // Not fast - } - } -} - -// This should NOT be Copy/Clone -pub struct EevInput { - pub(crate) _x: PhantomData<()> -} - -#[derive(Copy, Clone)] -pub struct EevSource { - _x: PhantomData<()> -} - -macro_rules! impl_eev { - ($( - $input:ident => $source:ident: - PINS=[($pin:ident, $af:ident), $(($pin_b:ident, $af_b:ident),)*], - COMP=$compX:ident, $enable_bits:literal, - $fltinrZ:ident, $fltWsrc_0:ident, $fltWsrc_1:ident, $fltWp:ident, $fltWf:ident, $fltWe:ident, $fltWlck:ident, - )+) => {$( - - - impl $input { - pub fn bind_pin(self, pin: $pin>) -> SourceBuilder<$input> { - pin.into_alternate::<$af>(); - unsafe { SourceBuilder::new(self, 0b00) } - } - - $( - // TODO: Is there a nicer way to do this? - pub fn bind_pin_b(self, pin: $pin_b>) -> SourceBuilder<$input> { - pin.into_alternate::<$af_b>(); - unsafe { SourceBuilder::new(self, 0b00) } - } - )* - - pub fn bind_comp(self, _comp: &crate::comparator::Comparator<$compX, crate::comparator::Enabled>) -> SourceBuilder<$input> { - unsafe { SourceBuilder::new(self, 0b01) } - } - } - - impl SourceBuilder<$input> { - pub fn finalize(self, _control: &mut HrPwmControl) -> $source { - let SourceBuilder{ _input, src_bits, is_active_high, filter_bits } = self; - - // Setup fault source - unsafe { - let common = &*HRTIM_COMMON::ptr(); - - common.fltinr2.modify(|_r, w| w.$fltWsrc_1().bit(src_bits & 0b10 != 0)); - common.$fltinrZ.modify(|_r, w| w - .$fltWsrc_0().bit(src_bits & 0b01 != 0) - .$fltWp().bit(is_active_high) - .$fltWf().bits(filter_bits) - .$fltWe().set_bit() // Enable - ); - - // ... and lock configuration - common.$fltinrZ.modify(|_r, w| w.$fltWlck().set_bit()); - } - - $source { - _x: PhantomData - } - } - - pub fn polarity(mut self, polarity: super::Polarity) -> Self { - self.is_active_high = polarity == super::Polarity::ActiveHigh; - self - } - - // TODO: add more settings - /* pub fn blanking(?) -> Self */ - - pub fn filter(mut self, filter: FaultSamplingFilter) -> Self { - self.filter_bits = filter as u8; - self - } - } - - unsafe impl FaultSource for $source { - const ENABLE_BITS: u8 = $enable_bits; - } - )+} -} - -// TODO: Lookup to ensure the alternate function are the same for other devices than stm32g474 -#[cfg(feature = "stm32g474")] -impl_faults!( - FaultInput1 => FaultSource1: PINS=[(PA12, AF13),], COMP=COMP2, 0b000001, fltinr1, flt1src, flt1src_1, flt1p, flt1f, flt1e, flt1lck, - FaultInput2 => FaultSource2: PINS=[(PA15, AF13),], COMP=COMP4, 0b000010, fltinr1, flt2src, flt2src_1, flt2p, flt2f, flt2e, flt2lck, - FaultInput3 => FaultSource3: PINS=[(PB10, AF13),], COMP=COMP6, 0b000100, fltinr1, flt3src, flt3src_1, flt3p, flt3f, flt3e, flt3lck, - FaultInput4 => FaultSource4: PINS=[(PB11, AF13),], COMP=COMP1, 0b001000, fltinr1, flt4src, flt4src_1, flt4p, flt4f, flt4e, flt4lck, - FaultInput5 => FaultSource5: PINS=[(PB0, AF13), (PC7, AF3),], COMP=COMP3, 0b010000, fltinr2, flt5src, flt5src_1, flt5p, flt5f, flt5e, flt5lck, - FaultInput6 => FaultSource6: PINS=[(PC10, AF13),], COMP=COMP5, 0b100000, fltinr2, flt6src_0, flt6src_1, flt6p, flt6f, flt6e, flt6lck, -); - -pub struct EevInputs { - pub eev_input1: EevInput<1>, - pub eev_input2: EevInput<2>, - pub eev_input3: EevInput<3>, - pub eev_input4: EevInput<4>, - pub eev_input5: EevInput<5>, - pub eev_input6: EevInput<6>, - pub eev_input7: EevInput<7>, - pub eev_input8: EevInput<8>, - pub eev_input9: EevInput<9>, - pub eev_input10: EevInput<10>, -} - -impl EevInputs { - -} - -pub enum FaultSamplingFilter { - /// No filtering, fault acts asynchronously - /// - /// Note that this bypasses any f_flts (SamplingClkDiv) - None = 0b0000, - - /// Sample directly at rate f_hrtim, with a count of 2 - /// - /// Note that this bypasses: any f_flts (SamplingClkDiv) - HrtimN2 = 0b0001, - - /// Sample directly at rate f_hrtim, with a count of 4 - /// - /// Note that this bypasses any f_flts (SamplingClkDiv) - HrtimN4 = 0b0010, - - /// Sample directly at rate f_hrtim, with a count of 8 - /// - /// Note that this bypasses any f_flts (SamplingClkDiv) - HrtimN8 = 0b0011, - - /// Sample at rate f_flts / 2, with a count of 6 - FltsDiv2N6 = 0b0100, - - /// Sample at rate f_flts / 2, with a count of 8 - FltsDiv2N8 = 0b0101, - - /// Sample at rate f_flts / 4, with a count of 6 - FltsDiv4N6 = 0b0110, - - /// Sample at rate f_flts / 4, with a count of 8 - FltsDiv4N8 = 0b0111, - - /// Sample at rate f_flts / 8, with a count of 6 - FltsDiv8N6 = 0b1000, - - /// Sample at rate f_flts / 8, with a count of 8 - FltsDiv8N8 = 0b1001, - - /// Sample at rate f_flts / 16, with a count of 5 - FltsDiv16N5 = 0b1010, - - /// Sample at rate f_flts / 16, with a count of 6 - FltsDiv16N6 = 0b1011, - - /// Sample at rate f_flts / 16, with a count of 8 - FltsDiv16N8 = 0b1100, - - /// Sample at rate f_flts / 32, with a count of 5 - FltsDiv32N5 = 0b1101, - - /// Sample at rate f_flts / 32, with a count of 6 - FltsDiv32N6 = 0b1110, - - /// Sample at rate f_flts / 32, with a count of 8 - FltsDiv32N8 = 0b1111, -} - -macro_rules! impl_flt_monitor { - ($($t:ident: ($fltx:ident, $fltxc:ident),)+) => {$( - pub struct $t { - pub(crate) _x: PhantomData<()> - } - - impl FaultMonitor for $t { - fn is_fault_active(&self) -> bool { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.isr.read().$fltx().bit() - } - - fn clear_fault(&mut self) { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.icr.write(|w| w.$fltxc().set_bit()); - } - - // TODO: Should we have our own trait since it does not seem possible to implement this - fn set_fault(&mut self) { - todo!() - } - } - )+}; -} - -impl_flt_monitor!( - FltMonitorSys: (sysflt, sysfltc), - FltMonitor1: (flt1, flt1c), - FltMonitor2: (flt2, flt2c), - FltMonitor3: (flt3, flt3c), - FltMonitor4: (flt4, flt4c), - FltMonitor5: (flt5, flt5c), - FltMonitor6: (flt6, flt6c), -); diff --git a/src/hrtim/mod.rs b/src/hrtim/mod.rs index 5062df19..d846701f 100644 --- a/src/hrtim/mod.rs +++ b/src/hrtim/mod.rs @@ -1,3 +1,4 @@ +pub mod adc_trigger; pub mod compare_register; pub mod control; pub mod deadtime; diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs index 7291440b..c7ed6fd1 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -16,7 +16,7 @@ pub struct HrTim { _prescaler: PhantomData, } -pub trait HrTimer { +pub trait HrTimer: Sized { /// Get period of timer in number of ticks /// /// This is also the maximum duty usable for `HrCompareRegister::set_duty` @@ -35,10 +35,34 @@ pub trait HrTimer { /// Stop timer and reset counter fn stop_and_reset(&mut self, _hr_control: &mut HrPwmControl); + + /// Make a handle to this timers reset event to use as adc trigger + fn as_reset_adc_trigger(&self) -> super::adc_trigger::TimerReset; + + /// Make a handle to this timers period event to use as adc trigger + fn as_period_adc_trigger(&self) -> super::adc_trigger::TimerPeriod; } macro_rules! hrtim_timer { - ($($TIMX:ident: $cntXr:ident, $cntx:ident, $perXr:ident, $tXcen:ident, $perx:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident, $icr:ident, $repc:ident, $([$rstXr:ident, $TimerXResetEventSource:ident],)*)+) => {$( + ($( + $TIMX:ident: + $cntXr:ident, + $cntx:ident, + $perXr:ident, + $tXcen:ident, + $perx:ident, + $rep:ident, + $repx:ident, + $dier:ident, + $repie:ident, + $icr:ident, + $repc:ident, + $(($rstXr:ident, $TimerXResetEventSource:ident))* + ,[$(($AdcTrigger:ident: [ + $((PER: $adc_trigger_bits_period:expr),)* + $((RST: $adc_trigger_bits_reset:expr)),* + ])),*]),+ + ) => {$( impl HrTimer<$TIMX, PSCL> for HrTim<$TIMX, PSCL> { fn get_period(&self) -> u16 { let tim = unsafe { &*$TIMX::ptr() }; @@ -76,6 +100,16 @@ macro_rules! hrtim_timer { let tim = unsafe { &*$TIMX::ptr() }; unsafe { tim.$cntXr.write(|w| w.$cntx().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 period event to use as adc trigger + fn as_period_adc_trigger(&self) -> super::adc_trigger::TimerPeriod { + super::adc_trigger::TimerPeriod(PhantomData) + } } impl HrTim<$TIMX, PSCL> { @@ -126,16 +160,31 @@ macro_rules! hrtim_timer { tim.$icr.write(|w| w.$repc().set_bit()); } } + + $( + $(impl $AdcTrigger for super::adc_trigger::TimerReset> { + const BITS: u32 = $adc_trigger_bits_reset; + })* + + $(impl $AdcTrigger for super::adc_trigger::TimerPeriod> { + const BITS: u32 = $adc_trigger_bits_period; + })* + )* )+}; } +use super::adc_trigger::Adc13Trigger as Adc13; +use super::adc_trigger::Adc24Trigger as Adc24; +use super::adc_trigger::Adc579Trigger as Adc579; +use super::adc_trigger::Adc6810Trigger as Adc6810; + hrtim_timer! { - HRTIM_MASTER: mcntr, mcnt, mper, mcen, mper, mrep, mrep, mdier, mrepie, micr, mrepc, - - HRTIM_TIMA: cntar, cntx, perar, tacen, perx, repar, repx, timadier, repie, timaicr, repc, [rstar, TimerAResetEventSource], - HRTIM_TIMB: cntr, cntx, perbr, tbcen, perx, repbr, repx, timbdier, repie, timbicr, repc, [rstbr, TimerBResetEventSource], - HRTIM_TIMC: cntcr, cntx, percr, tccen, perx, repcr, repx, timcdier, repie, timcicr, repc, [rstcr, TimerCResetEventSource], - HRTIM_TIMD: cntdr, cntx, perdr, tdcen, perx, repdr, repx, timddier, repie, timdicr, repc, [rstdr, TimerDResetEventSource], - HRTIM_TIME: cnter, cntx, perer, tecen, perx, reper, repx, timedier, repie, timeicr, repc, [rster, TimerEResetEventSource], - HRTIM_TIMF: cntfr, cntx, perfr, tfcen, perx, repfr, repx, timfdier, repie, timficr, repc, [rstfr, TimerFResetEventSource], + HRTIM_MASTER: mcntr, mcnt, mper, mcen, mper, mrep, mrep, mdier, mrepie, micr, mrepc,, [(Adc13: [(PER: 1 << 4),]), (Adc24: [(PER: 1 << 4),]), (Adc579: [(PER: 4),]), (Adc6810: [(PER: 4),])], + + HRTIM_TIMA: cntar, cntx, perar, tacen, perx, repar, repx, timadier, repie, timaicr, repc, (rstar, TimerAResetEventSource), [(Adc13: [(PER: 1 << 13), (RST: 1 << 14)]), (Adc24: [(PER: 1 << 13), ]), (Adc579: [(PER: 12), (RST: 13)]), (Adc6810: [(PER: 12), ])], + HRTIM_TIMB: cntr, cntx, perbr, tbcen, perx, repbr, repx, timbdier, repie, timbicr, repc, (rstbr, TimerBResetEventSource), [(Adc13: [(PER: 1 << 18), (RST: 1 << 19)]), (Adc24: [(PER: 1 << 17), ]), (Adc579: [(PER: 16), (RST: 17)]), (Adc6810: [(PER: 15), ])], + HRTIM_TIMC: cntcr, cntx, percr, tccen, perx, repcr, repx, timcdier, repie, timcicr, repc, (rstcr, TimerCResetEventSource), [(Adc13: [(PER: 1 << 23), ]), (Adc24: [(PER: 1 << 21), (RST: 1 << 22)]), (Adc579: [(PER: 20), ]), (Adc6810: [(PER: 18), (RST: 19)])], + HRTIM_TIMD: cntdr, cntx, perdr, tdcen, perx, repdr, repx, timddier, repie, timdicr, repc, (rstdr, TimerDResetEventSource), [(Adc13: [(PER: 1 << 27), ]), (Adc24: [(PER: 1 << 26), (RST: 1 << 27)]), (Adc579: [(PER: 23), ]), (Adc6810: [(PER: 22), (RST: 23)])], + HRTIM_TIME: cnter, cntx, perer, tecen, perx, reper, repx, timedier, repie, timeicr, repc, (rster, TimerEResetEventSource), [(Adc13: [(PER: 1 << 31), ]), (Adc24: [ (RST: 1 << 31)]), (Adc579: [(PER: 26), ]), (Adc6810: [ ])], + HRTIM_TIMF: cntfr, cntx, perfr, tfcen, perx, repfr, repx, timfdier, repie, timficr, repc, (rstfr, TimerFResetEventSource), [(Adc13: [(PER: 1 << 24), (RST: 1 << 28)]), (Adc24: [(PER: 1 << 24), ]), (Adc579: [(PER: 30), (RST: 31)]), (Adc6810: [(PER: 31), ])] } From 72dd9c27aaf14af5ba545313fc9c19ffa80f0212 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 17 Jan 2024 15:40:02 +0100 Subject: [PATCH 46/88] HRTIM: Start work on capture support --- src/hrtim/mod.rs | 1 + src/hrtim/timer.rs | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/hrtim/mod.rs b/src/hrtim/mod.rs index d846701f..5c679511 100644 --- a/src/hrtim/mod.rs +++ b/src/hrtim/mod.rs @@ -1,4 +1,5 @@ pub mod adc_trigger; +pub mod capture; pub mod compare_register; pub mod control; pub mod deadtime; diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs index c7ed6fd1..86d4f682 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -8,12 +8,14 @@ use super::{ event::{ TimerAResetEventSource, TimerBResetEventSource, TimerCResetEventSource, TimerDResetEventSource, TimerEResetEventSource, TimerFResetEventSource, - }, + }, capture::{HrCapt, self}, }; pub struct HrTim { _timer: PhantomData, _prescaler: PhantomData, + capture_ch1: HrCapt, + capture_ch2: HrCapt, } pub trait HrTimer: Sized { @@ -159,6 +161,14 @@ macro_rules! hrtim_timer { tim.$icr.write(|w| w.$repc().set_bit()); } + + pub fn capture_ch1(&mut self) -> &mut HrCapt<$TIMX, PSCL, capture::Ch1> { + &mut self.capture_ch1 + } + + pub fn capture_ch2(&mut self) -> &mut HrCapt<$TIMX, PSCL, capture::Ch2> { + &mut self.capture_ch2 + } } $( From 189f1cdd1cca05e45cfd342e191354f9f5353616 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 18 Jan 2024 10:52:22 +0100 Subject: [PATCH 47/88] HRTIM: Add capture.rs --- src/hrtim/capture.rs | 120 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 src/hrtim/capture.rs diff --git a/src/hrtim/capture.rs b/src/hrtim/capture.rs new file mode 100644 index 00000000..3d62db22 --- /dev/null +++ b/src/hrtim/capture.rs @@ -0,0 +1,120 @@ +use core::marker::PhantomData; + +use stm32g4::stm32g474::{ + HRTIM_TIMA, + HRTIM_TIMB, + HRTIM_TIMC, + HRTIM_TIMD, + HRTIM_TIME, + HRTIM_TIMF, +}; + + +pub struct Ch1; +pub struct Ch2; + +pub struct HrCapt { + _x: PhantomData<(TIM, PSCL, CH)> +} + +pub enum CountingDirection { + Up = 0, + Down = 1, +} + +pub trait CaptureEvent { + const BITS: u32; +} + +trait HrCapture { + fn get(&self) -> (u16, CountingDirection); + + /// Get number of ticks relative to beginning of upcounting + /// + /// where captures during down counting count as negative (before the upcount) + fn get_signed(&self) -> i32 { + let (value, dir) = self.get(); + let dir_bit = dir as i32; + dir_bit << 31 | i32::from(value) + } + + /// Get number of ticks relative to beginning of upcounting + /// + /// where captures during down counting count as larger (after upcount) + fn get_unsigned(&self) -> u32 { + let (value, dir) = self.get(); + let dir_bit = dir as u32; + dir_bit << 16 | u32::from(value) + } +} + +macro_rules! impl_capture { + ($($TIMX:ident, $CH:ident, $cptXYr:ident, $cptXYcr:ident, $cptXx:ident),+) => { + $(impl HrCapt<$TIMX, PSCL, $CH> { + /// 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.$cptXYcr.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.$cptXYcr.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.$cptXYcr.modify(|_, w| w.swcpt().set_bit()); + } + } + + impl HrCapture for HrCapt<$TIMX, PSCL, $CH> { + fn get(&self) -> (u16, CountingDirection) { + let tim = unsafe { &*$TIMX::ptr() }; + let data = tim.$cptXYr.read(); + let dir = match data.dir().bit() { + true => CountingDirection::Down, + false => CountingDirection::Up, + }; + let value = data.$cptXx().bits(); + + (value, dir) + } + })+ + }; +} + +impl_capture!( + HRTIM_TIMA, Ch1, cpt1ar, cpt1acr, cpt1x, + HRTIM_TIMA, Ch2, cpt2ar, cpt2acr, cpt2x, + + HRTIM_TIMB, Ch1, cpt1br, cpt1bcr, cpt1x, + HRTIM_TIMB, Ch2, cpt2br, cpt2bcr, cpt2x, + + HRTIM_TIMC, Ch1, cpt1cr, cpt1ccr, cpt1x, + HRTIM_TIMC, Ch2, cpt2cr, cpt2ccr, cpt2x, + + HRTIM_TIMD, Ch1, cpt1dr, cpt1dcr, cpt1x, + HRTIM_TIMD, Ch2, cpt2dr, cpt2dcr, cpt2x, + + HRTIM_TIME, Ch1, cpt1er, cpt1ecr, cpt1x, + HRTIM_TIME, Ch2, cpt2er, cpt2ecr, cpt2x, + + HRTIM_TIMF, Ch1, cpt1fr, cpt1fcr, cpt1x, + HRTIM_TIMF, Ch2, cpt2fr, cpt2fcr, cpt2x +); \ No newline at end of file From d6a69965411d3c0ea2a6985738cc63e847899987 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 18 Jan 2024 13:43:50 +0100 Subject: [PATCH 48/88] HRTIM: Impl CompareEvent for more types --- src/hrtim/adc_trigger.rs | 5 +- src/hrtim/capture.rs | 60 ++++++++----------- src/hrtim/compare_register.rs | 12 ++-- src/hrtim/control.rs | 60 ++++++++++--------- src/hrtim/external_event.rs | 108 ++++++++++++++++++++++++++++------ src/hrtim/timer.rs | 69 +++++++++++++++------- 6 files changed, 199 insertions(+), 115 deletions(-) diff --git a/src/hrtim/adc_trigger.rs b/src/hrtim/adc_trigger.rs index 0fdd3fe4..2782c10e 100644 --- a/src/hrtim/adc_trigger.rs +++ b/src/hrtim/adc_trigger.rs @@ -1,4 +1,3 @@ - use core::marker::PhantomData; pub trait Adc13Trigger { @@ -17,5 +16,5 @@ pub trait Adc6810Trigger { const BITS: u32; } -pub struct TimerReset(pub(crate)PhantomData); -pub struct TimerPeriod(pub(crate)PhantomData); \ No newline at end of file +pub struct TimerReset(pub(crate) PhantomData); +pub struct TimerPeriod(pub(crate) PhantomData); diff --git a/src/hrtim/capture.rs b/src/hrtim/capture.rs index 3d62db22..26651c43 100644 --- a/src/hrtim/capture.rs +++ b/src/hrtim/capture.rs @@ -1,20 +1,12 @@ use core::marker::PhantomData; -use stm32g4::stm32g474::{ - HRTIM_TIMA, - HRTIM_TIMB, - HRTIM_TIMC, - HRTIM_TIMD, - HRTIM_TIME, - HRTIM_TIMF, -}; - +use stm32g4::stm32g474::{HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF}; pub struct Ch1; pub struct Ch2; pub struct HrCapt { - _x: PhantomData<(TIM, PSCL, CH)> + _x: PhantomData<(TIM, PSCL, CH)>, } pub enum CountingDirection { @@ -22,7 +14,12 @@ pub enum CountingDirection { Down = 1, } -pub trait CaptureEvent { +/// Implemented for +/// * TIM's update event +/// * EEVT1-10 +/// TODO: This sould be implemeted +/// * All neighbor timers CMP1, CPM2, OUTPUT($CH)_RST and OUTPUT($CH)_SET events +pub trait CaptureEvent { const BITS: u32; } @@ -30,7 +27,7 @@ trait HrCapture { fn get(&self) -> (u16, CountingDirection); /// Get number of ticks relative to beginning of upcounting - /// + /// /// where captures during down counting count as negative (before the upcount) fn get_signed(&self) -> i32 { let (value, dir) = self.get(); @@ -39,7 +36,7 @@ trait HrCapture { } /// Get number of ticks relative to beginning of upcounting - /// + /// /// where captures during down counting count as larger (after upcount) fn get_unsigned(&self) -> u32 { let (value, dir) = self.get(); @@ -52,12 +49,12 @@ macro_rules! impl_capture { ($($TIMX:ident, $CH:ident, $cptXYr:ident, $cptXYcr:ident, $cptXx:ident),+) => { $(impl HrCapt<$TIMX, PSCL, $CH> { /// 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) { + 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.$cptXYcr.modify(|r, w| w.bits(r.bits() | E::BITS)); @@ -65,9 +62,9 @@ macro_rules! impl_capture { } /// Remove event to capture - pub fn remove_event>(&mut self, _event: &E) { + 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.$cptXYcr.modify(|r, w| w.bits(r.bits() & !E::BITS)); @@ -78,7 +75,7 @@ macro_rules! impl_capture { pub fn trigger_now(&mut self) { // SAFETY: We are the only one with access to cptXYcr let tim = unsafe { &*$TIMX::ptr() }; - + tim.$cptXYcr.modify(|_, w| w.swcpt().set_bit()); } } @@ -100,21 +97,10 @@ macro_rules! impl_capture { } impl_capture!( - HRTIM_TIMA, Ch1, cpt1ar, cpt1acr, cpt1x, - HRTIM_TIMA, Ch2, cpt2ar, cpt2acr, cpt2x, - - HRTIM_TIMB, Ch1, cpt1br, cpt1bcr, cpt1x, - HRTIM_TIMB, Ch2, cpt2br, cpt2bcr, cpt2x, - - HRTIM_TIMC, Ch1, cpt1cr, cpt1ccr, cpt1x, - HRTIM_TIMC, Ch2, cpt2cr, cpt2ccr, cpt2x, - - HRTIM_TIMD, Ch1, cpt1dr, cpt1dcr, cpt1x, - HRTIM_TIMD, Ch2, cpt2dr, cpt2dcr, cpt2x, - - HRTIM_TIME, Ch1, cpt1er, cpt1ecr, cpt1x, - HRTIM_TIME, Ch2, cpt2er, cpt2ecr, cpt2x, - - HRTIM_TIMF, Ch1, cpt1fr, cpt1fcr, cpt1x, - HRTIM_TIMF, Ch2, cpt2fr, cpt2fcr, cpt2x -); \ No newline at end of file + HRTIM_TIMA, Ch1, cpt1ar, cpt1acr, cpt1x, HRTIM_TIMA, Ch2, cpt2ar, cpt2acr, cpt2x, HRTIM_TIMB, + Ch1, cpt1br, cpt1bcr, cpt1x, HRTIM_TIMB, Ch2, cpt2br, cpt2bcr, cpt2x, HRTIM_TIMC, Ch1, cpt1cr, + cpt1ccr, cpt1x, HRTIM_TIMC, Ch2, cpt2cr, cpt2ccr, cpt2x, HRTIM_TIMD, Ch1, cpt1dr, cpt1dcr, + cpt1x, HRTIM_TIMD, Ch2, cpt2dr, cpt2dcr, cpt2x, HRTIM_TIME, Ch1, cpt1er, cpt1ecr, cpt1x, + HRTIM_TIME, Ch2, cpt2er, cpt2ecr, cpt2x, HRTIM_TIMF, Ch1, cpt1fr, cpt1fcr, cpt1x, HRTIM_TIMF, + Ch2, cpt2fr, cpt2fcr, cpt2x +); diff --git a/src/hrtim/compare_register.rs b/src/hrtim/compare_register.rs index 32d52a84..5984ec05 100644 --- a/src/hrtim/compare_register.rs +++ b/src/hrtim/compare_register.rs @@ -14,7 +14,6 @@ pub struct HrCr2(PhantomData<(TIM, PSCL)>); pub struct HrCr3(PhantomData<(TIM, PSCL)>); pub struct HrCr4(PhantomData<(TIM, PSCL)>); - use super::adc_trigger::Adc13Trigger as Adc13; use super::adc_trigger::Adc24Trigger as Adc24; use super::adc_trigger::Adc579Trigger as Adc579; @@ -41,7 +40,6 @@ macro_rules! hrtim_cr_helper { }; } - macro_rules! hrtim_cr { ($($TIMX:ident: [ [$cmpX1r:ident, $cmp1x:ident, $(($cr1_trigger:ident: $cr1_trigger_bits:expr)),*], @@ -58,19 +56,19 @@ macro_rules! hrtim_cr { hrtim_cr! { HRTIM_MASTER: [ - [mcmp1r,mcmp1, (Adc13: 1 << 0), (Adc24: 1 << 0), (Adc579: 0), (Adc6810: 0) ], - [mcmp2r,mcmp2, (Adc13: 1 << 1), (Adc24: 1 << 1), (Adc579: 1), (Adc6810: 1) ], - [mcmp3r,mcmp3, (Adc13: 1 << 2), (Adc24: 1 << 2), (Adc579: 2), (Adc6810: 2) ], + [mcmp1r,mcmp1, (Adc13: 1 << 0), (Adc24: 1 << 0), (Adc579: 0), (Adc6810: 0) ], + [mcmp2r,mcmp2, (Adc13: 1 << 1), (Adc24: 1 << 1), (Adc579: 1), (Adc6810: 1) ], + [mcmp3r,mcmp3, (Adc13: 1 << 2), (Adc24: 1 << 2), (Adc579: 2), (Adc6810: 2) ], [mcmp4r,mcmp4, (Adc13: 1 << 3), (Adc24: 1 << 3), (Adc579: 3), (Adc6810: 3) ] ], - + HRTIM_TIMA: [ [cmp1ar, cmp1x, ], [cmp2ar, cmp2x, (Adc24: 1 << 10), (Adc6810: 10)], [cmp3ar, cmp3x, (Adc13: 1 << 11), (Adc579: 10) ], [cmp4ar, cmp4x, (Adc13: 1 << 12), (Adc24: 1 << 12), (Adc579: 11), (Adc6810: 11)] ], - + HRTIM_TIMB: [ [cmp1br, cmp1x, ], [cmp2br, cmp2x, (Adc24: 1 << 14), (Adc6810: 13)], diff --git a/src/hrtim/control.rs b/src/hrtim/control.rs index cc466737..42a80a5b 100644 --- a/src/hrtim/control.rs +++ b/src/hrtim/control.rs @@ -214,70 +214,72 @@ use super::adc_trigger::{Adc13Trigger, Adc24Trigger, Adc579Trigger, Adc6810Trigg impl HrPwmControl { pub fn enable_adc_trigger1_source(&mut self, _trigger: T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; - unsafe { common.adc1r.modify(|r, w| w.bits(r.bits() | T::BITS)); } + unsafe { + common.adc1r.modify(|r, w| w.bits(r.bits() | T::BITS)); + } } pub fn enable_adc_trigger2_source(&mut self, _trigger: T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; - unsafe { common.adc2r.modify(|r, w| w.bits(r.bits() | T::BITS)); } + unsafe { + common.adc2r.modify(|r, w| w.bits(r.bits() | T::BITS)); + } } pub fn enable_adc_trigger3_source(&mut self, _trigger: T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; - unsafe { common.adc3r.modify(|r, w| w.bits(r.bits() | T::BITS)); } + unsafe { + common.adc3r.modify(|r, w| w.bits(r.bits() | T::BITS)); + } } pub fn enable_adc_trigger4_source(&mut self, _trigger: T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; - unsafe { common.adc4r.modify(|r, w| w.bits(r.bits() | T::BITS)); } + unsafe { + common.adc4r.modify(|r, w| w.bits(r.bits() | T::BITS)); + } } pub fn enable_adc_trigger5_source(&mut self, _trigger: T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.adcer.modify(|_r, w| { - w.adc5trg() - .variant(T::BITS as u8) - }); + common + .adcer + .modify(|_r, w| w.adc5trg().variant(T::BITS as u8)); } pub fn enable_adc_trigger6_source(&mut self, _trigger: T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.adcer.modify(|_r, w| { - w.adc6trg() - .variant(T::BITS as u8) - }); + common + .adcer + .modify(|_r, w| w.adc6trg().variant(T::BITS as u8)); } pub fn enable_adc_trigger7_source(&mut self, _trigger: T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.adcer.modify(|_r, w| { - w.adc7trg() - .variant(T::BITS as u8) - }); + common + .adcer + .modify(|_r, w| w.adc7trg().variant(T::BITS as u8)); } pub fn enable_adc_trigger8_source(&mut self, _trigger: T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.adcer.modify(|_r, w| { - w.adc8trg() - .variant(T::BITS as u8) - }); + common + .adcer + .modify(|_r, w| w.adc8trg().variant(T::BITS as u8)); } pub fn enable_adc_trigger9_source(&mut self, _trigger: T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.adcer.modify(|_r, w| { - w.adc9trg() - .variant(T::BITS as u8) - }); + common + .adcer + .modify(|_r, w| w.adc9trg().variant(T::BITS as u8)); } pub fn enable_adc_trigger10_source(&mut self, _trigger: T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.adcer.modify(|_r, w| { - w.adc10trg() - .variant(T::BITS as u8) - }); + common + .adcer + .modify(|_r, w| w.adc10trg().variant(T::BITS as u8)); } } @@ -337,4 +339,4 @@ pub enum SamplingClkDiv { /// /// fault signal sampling clock f_flts = f_hrtim / 8 Eight = 0b11, -} \ No newline at end of file +} diff --git a/src/hrtim/external_event.rs b/src/hrtim/external_event.rs index 56e9f079..1e3fa69f 100644 --- a/src/hrtim/external_event.rs +++ b/src/hrtim/external_event.rs @@ -10,18 +10,43 @@ use crate::stm32::HRTIM_COMMON; use super::event::EevFastOrNormal; use super::{control::HrTimCalibrated, event::EventSource}; +#[derive(Copy, Clone, PartialEq)] +pub struct ExternalEventSourceInner { + _x: PhantomData<()>, +} + #[derive(Copy, Clone, PartialEq)] pub enum ExternalEventSource { - Eevnt1 { _x: PhantomData<()> }, - Eevnt2 { _x: PhantomData<()> }, - Eevnt3 { _x: PhantomData<()> }, - Eevnt4 { _x: PhantomData<()> }, - Eevnt5 { _x: PhantomData<()> }, - Eevnt6 { _x: PhantomData<()> }, - Eevnt7 { _x: PhantomData<()> }, - Eevnt8 { _x: PhantomData<()> }, - Eevnt9 { _x: PhantomData<()> }, - Eevnt10 { _x: PhantomData<()> }, + Eevnt1 { + x: ExternalEventSourceInner<1, IS_FAST>, + }, + Eevnt2 { + x: ExternalEventSourceInner<2, IS_FAST>, + }, + Eevnt3 { + x: ExternalEventSourceInner<3, IS_FAST>, + }, + Eevnt4 { + x: ExternalEventSourceInner<4, IS_FAST>, + }, + Eevnt5 { + x: ExternalEventSourceInner<5, IS_FAST>, + }, + Eevnt6 { + x: ExternalEventSourceInner<6, IS_FAST>, + }, + Eevnt7 { + x: ExternalEventSourceInner<7, IS_FAST>, + }, + Eevnt8 { + x: ExternalEventSourceInner<8, IS_FAST>, + }, + Eevnt9 { + x: ExternalEventSourceInner<9, IS_FAST>, + }, + Eevnt10 { + x: ExternalEventSourceInner<10, IS_FAST>, + }, } impl From> for EventSource { @@ -70,6 +95,7 @@ pub struct EevInput { _x: PhantomData<()>, } +/// This is implemented for types that can be used as inputs to the eev /// # Safety /// Only implement for types that can be used as sources to eev number `EEV_N` with src bits `SRC_BITS` pub unsafe trait EevSrcBits: Sized { @@ -254,8 +280,8 @@ where } } -pub trait ToExternalEventSource { - fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource; +pub trait ToExternalEventSource { + fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSourceInner; } #[derive(Copy, Clone)] @@ -285,8 +311,13 @@ macro_rules! impl_eev1_5_to_es { } } - impl ToExternalEventSource for SourceBuilder<$N, IS_FAST> { - fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource { + impl ToExternalEventSource<$N, IS_FAST> + for SourceBuilder<$N, IS_FAST> + { + fn finalize( + self, + _calibrated: &mut HrTimCalibrated, + ) -> ExternalEventSourceInner<$N, IS_FAST> { let SourceBuilder { src_bits, edge_or_polarity_bits, @@ -311,7 +342,7 @@ macro_rules! impl_eev1_5_to_es { }); } - ExternalEventSource::$eev { _x: PhantomData } + ExternalEventSourceInner { _x: PhantomData } } } }; @@ -321,8 +352,11 @@ macro_rules! impl_eev6_10_to_es { ($eev:ident, $N:literal, $eeXsrc:ident, $eeXpol:ident, $eeXsns:ident, $eeXf:ident) => { impl ExternalEventBuilder6To10 for SourceBuilder<$N, false> {} - impl ToExternalEventSource for SourceBuilder<$N, false> { - fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource { + impl ToExternalEventSource<$N, false> for SourceBuilder<$N, false> { + fn finalize( + self, + _calibrated: &mut HrTimCalibrated, + ) -> ExternalEventSourceInner<$N, false> { let SourceBuilder { src_bits, edge_or_polarity_bits, @@ -346,7 +380,7 @@ macro_rules! impl_eev6_10_to_es { common.eecr3.modify(|_r, w| w.$eeXf().bits(filter_bits)); } - ExternalEventSource::$eev { _x: PhantomData } + ExternalEventSourceInner { _x: PhantomData } } } }; @@ -363,3 +397,41 @@ impl_eev6_10_to_es!(Eevnt7, 7, ee7src, ee7pol, ee7sns, ee7f); impl_eev6_10_to_es!(Eevnt8, 8, ee8src, ee8pol, ee8sns, ee8f); impl_eev6_10_to_es!(Eevnt9, 9, ee9src, ee9pol, ee9sns, ee9f); impl_eev6_10_to_es!(Eevnt10, 10, ee10src, ee10pol, ee10sns, ee10f); + +impl + super::capture::CaptureEvent + for ExternalEventSourceInner +{ + const BITS: u32 = 1 << (N + 1); // EEV1 is at bit #2 etc +} + +impl + super::capture::CaptureEvent + for ExternalEventSourceInner +{ + const BITS: u32 = 1 << (N + 1); // EEV1 is at bit #2 etc +} + +// TODO: Get rid of ExternalEventSource completely in favour of using ExternalEventSourceInner directly +macro_rules! impl_into_ees { + ($($N:literal => $variant:ident),+) => {$( + impl Into> for ExternalEventSourceInner<$N, IS_FAST> { + fn into(self) -> ExternalEventSource { + ExternalEventSource::$variant { x: self } + } + } + )+} +} + +impl_into_ees! { + 1 => Eevnt1, + 2 => Eevnt2, + 3 => Eevnt3, + 4 => Eevnt4, + 5 => Eevnt5, + 6 => Eevnt6, + 7 => Eevnt7, + 8 => Eevnt8, + 9 => Eevnt9, + 10 => Eevnt10 +} diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs index 86d4f682..9870ad12 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -4,11 +4,12 @@ use crate::stm32::{ use core::marker::PhantomData; use super::{ + capture::{self, HrCapt}, control::HrPwmControl, event::{ TimerAResetEventSource, TimerBResetEventSource, TimerCResetEventSource, TimerDResetEventSource, TimerEResetEventSource, TimerFResetEventSource, - }, capture::{HrCapt, self}, + }, }; pub struct HrTim { @@ -54,17 +55,13 @@ macro_rules! hrtim_timer { $tXcen:ident, $perx:ident, $rep:ident, - $repx:ident, + $repx:ident, $dier:ident, $repie:ident, $icr:ident, $repc:ident, - $(($rstXr:ident, $TimerXResetEventSource:ident))* - ,[$(($AdcTrigger:ident: [ - $((PER: $adc_trigger_bits_period:expr),)* - $((RST: $adc_trigger_bits_reset:expr)),* - ])),*]),+ - ) => {$( + $(($rstXr:ident, $TimerXResetEventSource:ident))*, + )+) => {$( impl HrTimer<$TIMX, PSCL> for HrTim<$TIMX, PSCL> { fn get_period(&self) -> u16 { let tim = unsafe { &*$TIMX::ptr() }; @@ -161,7 +158,7 @@ macro_rules! hrtim_timer { tim.$icr.write(|w| w.$repc().set_bit()); } - + pub fn capture_ch1(&mut self) -> &mut HrCapt<$TIMX, PSCL, capture::Ch1> { &mut self.capture_ch1 } @@ -170,8 +167,27 @@ macro_rules! hrtim_timer { &mut self.capture_ch2 } } - - $( + + /// Timer Update event + impl super::capture::CaptureEvent<$TIMX, PSCL, super::capture::Ch1> for HrTim<$TIMX, PSCL> { + const BITS: u32 = 1 << 1; + } + + /// Timer Update event + impl super::capture::CaptureEvent<$TIMX, PSCL, super::capture::Ch2> for HrTim<$TIMX, PSCL> { + const BITS: u32 = 1 << 1; + } + )+} +} + +macro_rules! hrtim_timer_adc_trigger { + ($($TIMX:ident: + [$(($AdcTrigger:ident: [ + $((PER: $adc_trigger_bits_period:expr),)* + $((RST: $adc_trigger_bits_reset:expr)),* + ])),+] + ),+) => { + $($( $(impl $AdcTrigger for super::adc_trigger::TimerReset> { const BITS: u32 = $adc_trigger_bits_reset; })* @@ -179,8 +195,8 @@ macro_rules! hrtim_timer { $(impl $AdcTrigger for super::adc_trigger::TimerPeriod> { const BITS: u32 = $adc_trigger_bits_period; })* - )* - )+}; + )*)* + } } use super::adc_trigger::Adc13Trigger as Adc13; @@ -189,12 +205,23 @@ use super::adc_trigger::Adc579Trigger as Adc579; use super::adc_trigger::Adc6810Trigger as Adc6810; hrtim_timer! { - HRTIM_MASTER: mcntr, mcnt, mper, mcen, mper, mrep, mrep, mdier, mrepie, micr, mrepc,, [(Adc13: [(PER: 1 << 4),]), (Adc24: [(PER: 1 << 4),]), (Adc579: [(PER: 4),]), (Adc6810: [(PER: 4),])], - - HRTIM_TIMA: cntar, cntx, perar, tacen, perx, repar, repx, timadier, repie, timaicr, repc, (rstar, TimerAResetEventSource), [(Adc13: [(PER: 1 << 13), (RST: 1 << 14)]), (Adc24: [(PER: 1 << 13), ]), (Adc579: [(PER: 12), (RST: 13)]), (Adc6810: [(PER: 12), ])], - HRTIM_TIMB: cntr, cntx, perbr, tbcen, perx, repbr, repx, timbdier, repie, timbicr, repc, (rstbr, TimerBResetEventSource), [(Adc13: [(PER: 1 << 18), (RST: 1 << 19)]), (Adc24: [(PER: 1 << 17), ]), (Adc579: [(PER: 16), (RST: 17)]), (Adc6810: [(PER: 15), ])], - HRTIM_TIMC: cntcr, cntx, percr, tccen, perx, repcr, repx, timcdier, repie, timcicr, repc, (rstcr, TimerCResetEventSource), [(Adc13: [(PER: 1 << 23), ]), (Adc24: [(PER: 1 << 21), (RST: 1 << 22)]), (Adc579: [(PER: 20), ]), (Adc6810: [(PER: 18), (RST: 19)])], - HRTIM_TIMD: cntdr, cntx, perdr, tdcen, perx, repdr, repx, timddier, repie, timdicr, repc, (rstdr, TimerDResetEventSource), [(Adc13: [(PER: 1 << 27), ]), (Adc24: [(PER: 1 << 26), (RST: 1 << 27)]), (Adc579: [(PER: 23), ]), (Adc6810: [(PER: 22), (RST: 23)])], - HRTIM_TIME: cnter, cntx, perer, tecen, perx, reper, repx, timedier, repie, timeicr, repc, (rster, TimerEResetEventSource), [(Adc13: [(PER: 1 << 31), ]), (Adc24: [ (RST: 1 << 31)]), (Adc579: [(PER: 26), ]), (Adc6810: [ ])], - HRTIM_TIMF: cntfr, cntx, perfr, tfcen, perx, repfr, repx, timfdier, repie, timficr, repc, (rstfr, TimerFResetEventSource), [(Adc13: [(PER: 1 << 24), (RST: 1 << 28)]), (Adc24: [(PER: 1 << 24), ]), (Adc579: [(PER: 30), (RST: 31)]), (Adc6810: [(PER: 31), ])] + HRTIM_MASTER: mcntr, mcnt, mper, mcen, mper, mrep, mrep, mdier, mrepie, micr, mrepc,, + + HRTIM_TIMA: cntar, cntx, perar, tacen, perx, repar, repx, timadier, repie, timaicr, repc, (rstar, TimerAResetEventSource), + HRTIM_TIMB: cntr, cntx, perbr, tbcen, perx, repbr, repx, timbdier, repie, timbicr, repc, (rstbr, TimerBResetEventSource), + HRTIM_TIMC: cntcr, cntx, percr, tccen, perx, repcr, repx, timcdier, repie, timcicr, repc, (rstcr, TimerCResetEventSource), + HRTIM_TIMD: cntdr, cntx, perdr, tdcen, perx, repdr, repx, timddier, repie, timdicr, repc, (rstdr, TimerDResetEventSource), + HRTIM_TIME: cnter, cntx, perer, tecen, perx, reper, repx, timedier, repie, timeicr, repc, (rster, TimerEResetEventSource), + HRTIM_TIMF: cntfr, cntx, perfr, tfcen, perx, repfr, repx, timfdier, repie, timficr, repc, (rstfr, TimerFResetEventSource), +} + +hrtim_timer_adc_trigger! { + HRTIM_MASTER: [(Adc13: [(PER: 1 << 4),]), (Adc24: [(PER: 1 << 4),]), (Adc579: [(PER: 4),]), (Adc6810: [(PER: 4),])], + + HRTIM_TIMA: [(Adc13: [(PER: 1 << 13), (RST: 1 << 14)]), (Adc24: [(PER: 1 << 13), ]), (Adc579: [(PER: 12), (RST: 13)]), (Adc6810: [(PER: 12), ])], + HRTIM_TIMB: [(Adc13: [(PER: 1 << 18), (RST: 1 << 19)]), (Adc24: [(PER: 1 << 17), ]), (Adc579: [(PER: 16), (RST: 17)]), (Adc6810: [(PER: 15), ])], + HRTIM_TIMC: [(Adc13: [(PER: 1 << 23), ]), (Adc24: [(PER: 1 << 21), (RST: 1 << 22)]), (Adc579: [(PER: 20), ]), (Adc6810: [(PER: 18), (RST: 19)])], + HRTIM_TIMD: [(Adc13: [(PER: 1 << 27), ]), (Adc24: [(PER: 1 << 26), (RST: 1 << 27)]), (Adc579: [(PER: 23), ]), (Adc6810: [(PER: 22), (RST: 23)])], + HRTIM_TIME: [(Adc13: [(PER: 1 << 31), ]), (Adc24: [ (RST: 1 << 31)]), (Adc579: [(PER: 26), ]), (Adc6810: [ ])], + HRTIM_TIMF: [(Adc13: [(PER: 1 << 24), (RST: 1 << 28)]), (Adc24: [(PER: 1 << 24), ]), (Adc579: [(PER: 30), (RST: 31)]), (Adc6810: [(PER: 31), ])] } From dfb264291c32e23853827320c94d68c90e2b1b4e Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 18 Jan 2024 13:51:25 +0100 Subject: [PATCH 49/88] Fmt --- src/hrtim/capture.rs | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/hrtim/capture.rs b/src/hrtim/capture.rs index 26651c43..4adf8de7 100644 --- a/src/hrtim/capture.rs +++ b/src/hrtim/capture.rs @@ -46,7 +46,7 @@ trait HrCapture { } macro_rules! impl_capture { - ($($TIMX:ident, $CH:ident, $cptXYr:ident, $cptXYcr:ident, $cptXx:ident),+) => { + ($($TIMX:ident: $CH:ident, $cptXYr:ident, $cptXYcr:ident, $cptXx:ident),+) => { $(impl HrCapt<$TIMX, PSCL, $CH> { /// Add event to capture /// @@ -96,11 +96,22 @@ macro_rules! impl_capture { }; } -impl_capture!( - HRTIM_TIMA, Ch1, cpt1ar, cpt1acr, cpt1x, HRTIM_TIMA, Ch2, cpt2ar, cpt2acr, cpt2x, HRTIM_TIMB, - Ch1, cpt1br, cpt1bcr, cpt1x, HRTIM_TIMB, Ch2, cpt2br, cpt2bcr, cpt2x, HRTIM_TIMC, Ch1, cpt1cr, - cpt1ccr, cpt1x, HRTIM_TIMC, Ch2, cpt2cr, cpt2ccr, cpt2x, HRTIM_TIMD, Ch1, cpt1dr, cpt1dcr, - cpt1x, HRTIM_TIMD, Ch2, cpt2dr, cpt2dcr, cpt2x, HRTIM_TIME, Ch1, cpt1er, cpt1ecr, cpt1x, - HRTIM_TIME, Ch2, cpt2er, cpt2ecr, cpt2x, HRTIM_TIMF, Ch1, cpt1fr, cpt1fcr, cpt1x, HRTIM_TIMF, - Ch2, cpt2fr, cpt2fcr, cpt2x -); +impl_capture!{ + HRTIM_TIMA: Ch1, cpt1ar, cpt1acr, cpt1x, + HRTIM_TIMA: Ch2, cpt2ar, cpt2acr, cpt2x, + + HRTIM_TIMB: Ch1, cpt1br, cpt1bcr, cpt1x, + HRTIM_TIMB: Ch2, cpt2br, cpt2bcr, cpt2x, + + HRTIM_TIMC: Ch1, cpt1cr, cpt1ccr, cpt1x, + HRTIM_TIMC: Ch2, cpt2cr, cpt2ccr, cpt2x, + + HRTIM_TIMD: Ch1, cpt1dr, cpt1dcr, cpt1x, + HRTIM_TIMD: Ch2, cpt2dr, cpt2dcr, cpt2x, + + HRTIM_TIME: Ch1, cpt1er, cpt1ecr, cpt1x, + HRTIM_TIME: Ch2, cpt2er, cpt2ecr, cpt2x, + + HRTIM_TIMF: Ch1, cpt1fr, cpt1fcr, cpt1x, + HRTIM_TIMF: Ch2, cpt2fr, cpt2fcr, cpt2x +} From a214200e5f5ebc2352eba3f319e230ba688e1dbe Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 18 Jan 2024 17:38:50 +0100 Subject: [PATCH 50/88] HRTIM: Traitify events --- src/hrtim/capture.rs | 22 +- src/hrtim/compare_register.rs | 160 ++++++-- src/hrtim/event.rs | 661 +--------------------------------- src/hrtim/external_event.rs | 100 +---- src/hrtim/output.rs | 105 +----- src/hrtim/timer.rs | 102 +++--- 6 files changed, 229 insertions(+), 921 deletions(-) diff --git a/src/hrtim/capture.rs b/src/hrtim/capture.rs index 4adf8de7..1c71943a 100644 --- a/src/hrtim/capture.rs +++ b/src/hrtim/capture.rs @@ -18,8 +18,8 @@ pub enum CountingDirection { /// * TIM's update event /// * EEVT1-10 /// TODO: This sould be implemeted -/// * All neighbor timers CMP1, CPM2, OUTPUT($CH)_RST and OUTPUT($CH)_SET events -pub trait CaptureEvent { +/// * All neighbor timers CMP1, CPM2, OUT1_RST and OUT1_SET events +pub trait CaptureEvent { const BITS: u32; } @@ -52,7 +52,7 @@ macro_rules! impl_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) { + pub fn add_event>(&mut self, _event: &E) { let tim = unsafe { &*$TIMX::ptr() }; // SAFETY: We are the only one with access to cptXYcr @@ -62,7 +62,7 @@ macro_rules! impl_capture { } /// Remove event to capture - pub fn remove_event>(&mut self, _event: &E) { + pub fn remove_event>(&mut self, _event: &E) { let tim = unsafe { &*$TIMX::ptr() }; // SAFETY: We are the only one with access to cptXYcr @@ -96,22 +96,22 @@ macro_rules! impl_capture { }; } -impl_capture!{ - HRTIM_TIMA: Ch1, cpt1ar, cpt1acr, cpt1x, +impl_capture! { + HRTIM_TIMA: Ch1, cpt1ar, cpt1acr, cpt1x, HRTIM_TIMA: Ch2, cpt2ar, cpt2acr, cpt2x, - + HRTIM_TIMB: Ch1, cpt1br, cpt1bcr, cpt1x, HRTIM_TIMB: Ch2, cpt2br, cpt2bcr, cpt2x, - + HRTIM_TIMC: Ch1, cpt1cr, cpt1ccr, cpt1x, HRTIM_TIMC: Ch2, cpt2cr, cpt2ccr, cpt2x, - + HRTIM_TIMD: Ch1, cpt1dr, cpt1dcr, cpt1x, HRTIM_TIMD: Ch2, cpt2dr, cpt2dcr, cpt2x, - + HRTIM_TIME: Ch1, cpt1er, cpt1ecr, cpt1x, HRTIM_TIME: Ch2, cpt2er, cpt2ecr, cpt2x, - + HRTIM_TIMF: Ch1, cpt1fr, cpt1fcr, cpt1x, HRTIM_TIMF: Ch2, cpt2fr, cpt2fcr, cpt2x } diff --git a/src/hrtim/compare_register.rs b/src/hrtim/compare_register.rs index 5984ec05..8beb4103 100644 --- a/src/hrtim/compare_register.rs +++ b/src/hrtim/compare_register.rs @@ -20,7 +20,22 @@ use super::adc_trigger::Adc579Trigger as Adc579; use super::adc_trigger::Adc6810Trigger as Adc6810; macro_rules! hrtim_cr_helper { - ($TIMX:ident: $cr_type:ident: $cmpXYr:ident, $cmpYx:ident, $(($Trigger:ty: $trigger_bits:expr)),*) => { + (HRTIM_MASTER: $cr_type:ident: + $cmpXYr:ident, $cmpYx: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, $cmpYx, [$(($Trigger: $trigger_bits)),*], [$(($event_dst, $tim_event_index)),*]); + }; + + ($TIMX:ident: $cr_type:ident: + $cmpXYr:ident, $cmpYx: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() }; @@ -34,73 +49,138 @@ macro_rules! hrtim_cr_helper { } } - $(impl $Trigger for $cr_type<$TIMX, PSCL> { - const BITS: u32 = $trigger_bits; - })* + $( + /// 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> { + const BITS: u32 = 1 << ($tim_event_index + 11); // TIMEVNT1 is at bit 12, TIMEVNT2 at bit 13 etc + } + )* + + $( + impl $Trigger for $cr_type<$TIMX, PSCL> { + const BITS: u32 = $trigger_bits; + } + )* }; } macro_rules! hrtim_cr { ($($TIMX:ident: [ - [$cmpX1r:ident, $cmp1x:ident, $(($cr1_trigger:ident: $cr1_trigger_bits:expr)),*], - [$cmpX2r:ident, $cmp2x:ident, $(($cr2_trigger:ident: $cr2_trigger_bits:expr)),*], - [$cmpX3r:ident, $cmp3x:ident, $(($cr3_trigger:ident: $cr3_trigger_bits:expr)),*], - [$cmpX4r:ident, $cmp4x:ident, $(($cr4_trigger:ident: $cr4_trigger_bits:expr)),*] + [$cmpX1r:ident, $cmp1x:ident, [$(($cr1_trigger:ident: $cr1_trigger_bits:expr)),*], [$(($cr1_event_dst:ident, $cr1_tim_event_index:expr)),*]], + [$cmpX2r:ident, $cmp2x:ident, [$(($cr2_trigger:ident: $cr2_trigger_bits:expr)),*], [$(($cr2_event_dst:ident, $cr2_tim_event_index:expr)),*]], + [$cmpX3r:ident, $cmp3x:ident, [$(($cr3_trigger:ident: $cr3_trigger_bits:expr)),*], [$(($cr3_event_dst:ident, $cr3_tim_event_index:expr)),*]], + [$cmpX4r:ident, $cmp4x:ident, [$(($cr4_trigger:ident: $cr4_trigger_bits:expr)),*], [$(($cr4_event_dst:ident, $cr4_tim_event_index:expr)),*]] ]),+) => {$( - hrtim_cr_helper!($TIMX: HrCr1: $cmpX1r, $cmp1x, $(($cr1_trigger: $cr1_trigger_bits)),*); - hrtim_cr_helper!($TIMX: HrCr2: $cmpX2r, $cmp2x, $(($cr2_trigger: $cr2_trigger_bits)),*); - hrtim_cr_helper!($TIMX: HrCr3: $cmpX3r, $cmp3x, $(($cr3_trigger: $cr3_trigger_bits)),*); - hrtim_cr_helper!($TIMX: HrCr4: $cmpX4r, $cmp4x, $(($cr4_trigger: $cr4_trigger_bits)),*); + hrtim_cr_helper!($TIMX: HrCr1: $cmpX1r, $cmp1x, [$(($cr1_trigger: $cr1_trigger_bits)),*], [$(($cr1_event_dst, $cr1_tim_event_index)),*], 3); + hrtim_cr_helper!($TIMX: HrCr2: $cmpX2r, $cmp2x, [$(($cr2_trigger: $cr2_trigger_bits)),*], [$(($cr2_event_dst, $cr2_tim_event_index)),*], 4); + hrtim_cr_helper!($TIMX: HrCr3: $cmpX3r, $cmp3x, [$(($cr3_trigger: $cr3_trigger_bits)),*], [$(($cr3_event_dst, $cr3_tim_event_index)),*], 5); + hrtim_cr_helper!($TIMX: HrCr4: $cmpX4r, $cmp4x, [$(($cr4_trigger: $cr4_trigger_bits)),*], [$(($cr4_event_dst, $cr4_tim_event_index)),*], 6); )+}; } +// See RM0440 Table 218. 'Events mapping across timer A to F' hrtim_cr! { HRTIM_MASTER: [ - [mcmp1r,mcmp1, (Adc13: 1 << 0), (Adc24: 1 << 0), (Adc579: 0), (Adc6810: 0) ], - [mcmp2r,mcmp2, (Adc13: 1 << 1), (Adc24: 1 << 1), (Adc579: 1), (Adc6810: 1) ], - [mcmp3r,mcmp3, (Adc13: 1 << 2), (Adc24: 1 << 2), (Adc579: 2), (Adc6810: 2) ], - [mcmp4r,mcmp4, (Adc13: 1 << 3), (Adc24: 1 << 3), (Adc579: 3), (Adc6810: 3) ] + [mcmp1r, mcmp1, [(Adc13: 1 << 0), (Adc24: 1 << 0), (Adc579: 0), (Adc6810: 0) ], []], + [mcmp2r, mcmp2, [(Adc13: 1 << 1), (Adc24: 1 << 1), (Adc579: 1), (Adc6810: 1) ], []], + [mcmp3r, mcmp3, [(Adc13: 1 << 2), (Adc24: 1 << 2), (Adc579: 2), (Adc6810: 2) ], []], + [mcmp4r, mcmp4, [(Adc13: 1 << 3), (Adc24: 1 << 3), (Adc579: 3), (Adc6810: 3) ], []] ], HRTIM_TIMA: [ - [cmp1ar, cmp1x, ], - [cmp2ar, cmp2x, (Adc24: 1 << 10), (Adc6810: 10)], - [cmp3ar, cmp3x, (Adc13: 1 << 11), (Adc579: 10) ], - [cmp4ar, cmp4x, (Adc13: 1 << 12), (Adc24: 1 << 12), (Adc579: 11), (Adc6810: 11)] + [cmp1ar, cmp1x, [ ], [(HRTIM_TIMB, 1), (HRTIM_TIMD, 1) ]], + [cmp2ar, cmp2x, [ (Adc24: 1 << 10), (Adc6810: 10)], [(HRTIM_TIMB, 2), (HRTIM_TIMC, 1) ]], + [cmp3ar, cmp3x, [(Adc13: 1 << 11), (Adc579: 10) ], [(HRTIM_TIMC, 2), (HRTIM_TIMF, 1) ]], + [cmp4ar, cmp4x, [(Adc13: 1 << 12), (Adc24: 1 << 12), (Adc579: 11), (Adc6810: 11)], [(HRTIM_TIMD, 2), (HRTIM_TIME, 1) ]] ], HRTIM_TIMB: [ - [cmp1br, cmp1x, ], - [cmp2br, cmp2x, (Adc24: 1 << 14), (Adc6810: 13)], - [cmp3br, cmp3x, (Adc13: 1 << 16), (Adc579: 14) ], - [cmp4br, cmp4x, (Adc13: 1 << 17), (Adc24: 1 << 16), (Adc579: 15), (Adc6810: 14)] + [cmp1br, cmp1x, [ ], [(HRTIM_TIMA, 1), (HRTIM_TIMF, 2) ]], + [cmp2br, cmp2x, [ (Adc24: 1 << 14), (Adc6810: 13)], [(HRTIM_TIMA, 2), (HRTIM_TIMC, 3), (HRTIM_TIMD, 3)]], + [cmp3br, cmp3x, [(Adc13: 1 << 16), (Adc579: 14) ], [(HRTIM_TIMC, 4), (HRTIM_TIME, 2) ]], + [cmp4br, cmp4x, [(Adc13: 1 << 17), (Adc24: 1 << 16), (Adc579: 15), (Adc6810: 14)], [(HRTIM_TIMD, 4), (HRTIM_TIME, 3), (HRTIM_TIMF, 3)]] ], HRTIM_TIMC: [ - [cmp1cr, cmp1x, ], - [cmp2cr, cmp2x, (Adc24: 1 << 18), (Adc6810: 16)], - [cmp3cr, cmp3x, (Adc13: 1 << 21), (Adc579: 18) ], - [cmp4cr, cmp4x, (Adc13: 1 << 22), (Adc24: 1 << 20), (Adc579: 19), (Adc6810: 17)] + [cmp1cr, cmp1x, [ ], [(HRTIM_TIME, 4), (HRTIM_TIMF, 4) ]], + [cmp2cr, cmp2x, [ (Adc24: 1 << 18), (Adc6810: 16)], [(HRTIM_TIMA, 3), (HRTIM_TIME, 5) ]], + [cmp3cr, cmp3x, [(Adc13: 1 << 21), (Adc579: 18) ], [(HRTIM_TIMA, 4), (HRTIM_TIMB, 3) ]], + [cmp4cr, cmp4x, [(Adc13: 1 << 22), (Adc24: 1 << 20), (Adc579: 19), (Adc6810: 17)], [(HRTIM_TIMB, 4), (HRTIM_TIMD, 5), (HRTIM_TIMF, 5)]] ], HRTIM_TIMD: [ - [cmp1dr, cmp1x, ], - [cmp2dr, cmp2x, (Adc24: 1 << 23), (Adc6810: 20)], - [cmp3dr, cmp3x, (Adc13: 1 << 25), (Adc579: 21) ], - [cmp4dr, cmp4x, (Adc13: 1 << 26), (Adc24: 1 << 25), (Adc579: 22), (Adc6810: 21)] + [cmp1dr, cmp1x, [ ], [(HRTIM_TIMA, 5), (HRTIM_TIME, 6) ]], + [cmp2dr, cmp2x, [ (Adc24: 1 << 23), (Adc6810: 20)], [(HRTIM_TIMA, 6), (HRTIM_TIMC, 5), (HRTIM_TIME, 7)]], + [cmp3dr, cmp3x, [(Adc13: 1 << 25), (Adc579: 21) ], [(HRTIM_TIMB, 5), (HRTIM_TIMF, 6) ]], + [cmp4dr, cmp4x, [(Adc13: 1 << 26), (Adc24: 1 << 25), (Adc579: 22), (Adc6810: 21)], [(HRTIM_TIMB, 6), (HRTIM_TIMC, 6), (HRTIM_TIMF, 7)]] ], HRTIM_TIME: [ - [cmp1er, cmp1x, ], - [cmp2er, cmp2x, (Adc24: 1 << 28), (Adc6810: 24)], - [cmp3er, cmp3x, (Adc13: 1 << 29), (Adc24: 1 << 29), (Adc579: 24), (Adc6810: 25)], - [cmp4er, cmp4x, (Adc13: 1 << 30), (Adc24: 1 << 30), (Adc579: 25), (Adc6810: 26)] + [cmp1er, cmp1x, [ ], [(HRTIM_TIMB, 7), (HRTIM_TIMD, 6) ]], + [cmp2er, cmp2x, [ (Adc24: 1 << 28), (Adc6810: 24)], [(HRTIM_TIMB, 8), (HRTIM_TIMF, 8) ]], + [cmp3er, cmp3x, [(Adc13: 1 << 29), (Adc24: 1 << 29), (Adc579: 24), (Adc6810: 25)], [(HRTIM_TIMA, 7), (HRTIM_TIMC, 7), (HRTIM_TIMF, 9)]], + [cmp4er, cmp4x, [(Adc13: 1 << 30), (Adc24: 1 << 30), (Adc579: 25), (Adc6810: 26)], [(HRTIM_TIMA, 8), (HRTIM_TIMC, 8), (HRTIM_TIMD, 7)]] ], HRTIM_TIMF: [ - [cmp1fr, cmp1x, (Adc24: 1 << 15) ], - [cmp2fr, cmp2x, (Adc13: 1 << 10), (Adc24: 1 << 11), (Adc579: 27), (Adc6810: 28)], - [cmp3fr, cmp3x, (Adc13: 1 << 15), (Adc579: 28), (Adc6810: 29)], - [cmp4fr, cmp4x, (Adc13: 1 << 20), (Adc24: 1 << 19), (Adc579: 29), (Adc6810: 30)] + [cmp1fr, cmp1x, [ (Adc24: 1 << 15) ], [(HRTIM_TIMD, 8) ]], + [cmp2fr, cmp2x, [(Adc13: 1 << 10), (Adc24: 1 << 11), (Adc579: 27), (Adc6810: 28)], [(HRTIM_TIMC, 9) ]], + [cmp3fr, cmp3x, [(Adc13: 1 << 15), (Adc579: 28), (Adc6810: 29)], [(HRTIM_TIMB, 9), (HRTIM_TIMD, 9), (HRTIM_TIME, 8)]], + [cmp4fr, cmp4x, [(Adc13: 1 << 20), (Adc24: 1 << 19), (Adc579: 29), (Adc6810: 30)], [(HRTIM_TIMA, 9), (HRTIM_TIME, 9) ]] ] } + +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 + } + )*}; +} + +hrtim_master_cr! { + HrCr1: 1, + HrCr2: 2, + HrCr3: 3, + HrCr4: 4 +} + +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; + } + )*}; +} + +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, + + HRTIM_TIMF: HrCr2: 2, + HRTIM_TIMF: HrCr4: 3 +} diff --git a/src/hrtim/event.rs b/src/hrtim/event.rs index c4604cca..5c472809 100644 --- a/src/hrtim/event.rs +++ b/src/hrtim/event.rs @@ -1,647 +1,16 @@ -use core::marker::PhantomData; - -use crate::stm32::{ - HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF, -}; - -use super::{ - compare_register::{HrCr1, HrCr2, HrCr3, HrCr4}, - external_event::ExternalEventSource, -}; -use crate::hrtim::timer::HrTim; - -macro_rules! impl_into_es { - ($dst:ident: [$(($t:ty, $ES:ident),)*]) => {$( - impl_into_es!($dst, $t, $ES); - )*}; - - ($dst:ident, $t:ty, $ES:ident) => { - impl From<&$t> for EventSource { - fn from(_: &$t) -> Self { - EventSource::$ES{ _x: PhantomData } - } - } - }; - ($dst:ident) => { - impl_into_es! { - $dst: [ - (HrCr1<$dst, PSCL>, Cr1), - (HrCr2<$dst, PSCL>, Cr2), - (HrCr3<$dst, PSCL>, Cr3), - (HrCr4<$dst, PSCL>, Cr4), - (HrTim<$dst, PSCL>, Period), - - (HrCr1, MasterCr1), - (HrCr2, MasterCr2), - (HrCr3, MasterCr3), - (HrCr4, MasterCr4), - (HrTim, MasterPeriod), - ] - } - }; -} - -impl_into_es!(HRTIM_TIMA); -impl_into_es!(HRTIM_TIMB); -impl_into_es!(HRTIM_TIMC); -impl_into_es!(HRTIM_TIMD); -impl_into_es!(HRTIM_TIME); -impl_into_es!(HRTIM_TIMF); - -macro_rules! impl_into_neighbor_es { - ( - DST: $dst:ident: [ - ($src1:ident, $cr1:ident), - ($src2:ident, $cr2:ident), - ($src3:ident, $cr3:ident), - ($src4:ident, $cr4:ident), - ($src5:ident, $cr5:ident), - ($src6:ident, $cr6:ident), - ($src7:ident, $cr7:ident), - ($src8:ident, $cr8:ident), - ($src9:ident, $cr9:ident), - ] - ) => { - impl_into_neighbor_es!($dst, $src1, $cr1, TimEvent1); - impl_into_neighbor_es!($dst, $src2, $cr2, TimEvent2); - impl_into_neighbor_es!($dst, $src3, $cr3, TimEvent3); - impl_into_neighbor_es!($dst, $src4, $cr4, TimEvent4); - impl_into_neighbor_es!($dst, $src5, $cr5, TimEvent5); - impl_into_neighbor_es!($dst, $src6, $cr6, TimEvent6); - impl_into_neighbor_es!($dst, $src7, $cr7, TimEvent7); - impl_into_neighbor_es!($dst, $src8, $cr8, TimEvent8); - impl_into_neighbor_es!($dst, $src9, $cr9, TimEvent9); - }; - - ($dst:ident, $src:ident, $cr:ident, $TimEventX:ident) => { - impl From<&$cr<$src, PSCL>> for EventSource { - fn from(_: &$cr<$src, PSCL>) -> Self { - EventSource::NeighborTimer { - n: NeighborTimerEventSource::$TimEventX { _x: PhantomData }, - } - } - } - }; -} - -impl_into_neighbor_es! { - DST: HRTIM_TIMA: [ - // src - (HRTIM_TIMB, HrCr1), - (HRTIM_TIMB, HrCr2), - (HRTIM_TIMC, HrCr2), - (HRTIM_TIMC, HrCr3), - (HRTIM_TIMD, HrCr1), - (HRTIM_TIMD, HrCr2), - (HRTIM_TIME, HrCr3), - (HRTIM_TIME, HrCr4), - (HRTIM_TIMF, HrCr4), - ] -} - -impl_into_neighbor_es! { - DST: HRTIM_TIMB: [ - // src - (HRTIM_TIMA, HrCr1), - (HRTIM_TIMA, HrCr2), - (HRTIM_TIMC, HrCr3), - (HRTIM_TIMC, HrCr4), - (HRTIM_TIMD, HrCr3), - (HRTIM_TIMD, HrCr4), - (HRTIM_TIME, HrCr1), - (HRTIM_TIME, HrCr2), - (HRTIM_TIMF, HrCr3), - ] -} - -impl_into_neighbor_es! { - DST: HRTIM_TIMC: [ - // src - (HRTIM_TIMA, HrCr2), - (HRTIM_TIMA, HrCr3), - (HRTIM_TIMB, HrCr2), - (HRTIM_TIMB, HrCr3), - (HRTIM_TIMD, HrCr2), - (HRTIM_TIMD, HrCr4), - (HRTIM_TIME, HrCr3), - (HRTIM_TIME, HrCr4), - (HRTIM_TIMF, HrCr2), - ] -} - -// TODO: Continue for TIMD, TIME and TIMF, see RM0440 Table 218. 'Events mapping across timer A to F' - -pub enum EventSource { - /// Compare match with compare register 1 of this timer - Cr1 { - _x: PhantomData<(PSCL, DST)>, - }, - - /// Compare match with compare register 2 of this timer - Cr2 { - _x: PhantomData<(PSCL, DST)>, - }, - - /// Compare match with compare register 3 of this timer - Cr3 { - _x: PhantomData<(PSCL, DST)>, - }, - - /// Compare match with compare register 4 of this timer - Cr4 { - _x: PhantomData<(PSCL, DST)>, - }, - - /// On complete period - Period { - _x: PhantomData<(PSCL, DST)>, - }, - - /// Compare match with compare register 1 of master timer - MasterCr1 { - _x: PhantomData<(PSCL, DST)>, - }, - - /// Compare match with compare register 2 of master timer - MasterCr2 { - _x: PhantomData<(PSCL, DST)>, - }, - - /// Compare match with compare register 3 of master timer - MasterCr3 { - _x: PhantomData<(PSCL, DST)>, - }, - - /// Compare match with compare register 4 of master timer - MasterCr4 { - _x: PhantomData<(PSCL, DST)>, - }, - - /// On complete master period - MasterPeriod { - _x: PhantomData<(PSCL, DST)>, - }, - - ExternalEvent(EevFastOrNormal), // This is fine - - NeighborTimer { - n: NeighborTimerEventSource, - }, -} - -pub enum EevFastOrNormal { - Fast(ExternalEventSource), - Normal(ExternalEventSource), -} - -/// Compare events from neighbor timers -/// -/// See RM0440 Table 218. 'Events mapping across timer A to F' -pub enum NeighborTimerEventSource { - /// Timer event 1 - /// - /// This is different depending on destination timer: - /// |dest | source | - /// |-----|--------| - /// |TimA | B CR1 | - /// |TimB | A CR1 | - /// |TimC | A CR2 | - /// |TimD | A CR1 | - /// |TimE | A CR4 | - /// |TimF | A CR3 | - TimEvent1 { - _x: PhantomData<(PSCL, DST)>, - }, - - /// Timer event x - /// - /// This is different depending on destination timer: - /// |dest | source | - /// |-----|--------| - /// |TimA | x CRy | - /// |TimB | x CRy | - /// |TimC | x CRy | - /// |TimD | x CRy | - /// |TimE | x CRy | - /// |TimF | x CRy | - //TimEventx, - - /// Timer event 2 - /// - /// This is different depending on destination timer: - /// |dest | source | - /// |-----|--------| - /// |TimA | B CR2 | - /// |TimB | A CR2 | - /// |TimC | A CR3 | - /// |TimD | A CR4 | - /// |TimE | B CR3 | - /// |TimF | B CR1 | - TimEvent2 { - _x: PhantomData<(PSCL, DST)>, - }, - - /// Timer event 3 - /// - /// This is different depending on destination timer: - /// |dest | source | - /// |-----|--------| - /// |TimA | C CR2 | - /// |TimB | C CR3 | - /// |TimC | B CR2 | - /// |TimD | B CR2 | - /// |TimE | B CR4 | - /// |TimF | B CR4 | - TimEvent3 { - _x: PhantomData<(PSCL, DST)>, - }, - - /// Timer event 4 - /// - /// This is different depending on destination timer: - /// |dest | source | - /// |-----|--------| - /// |TimA | C CR3 | - /// |TimB | C CR4 | - /// |TimC | B CR3 | - /// |TimD | B CR4 | - /// |TimE | C CR1 | - /// |TimF | C CR1 | - TimEvent4 { - _x: PhantomData<(PSCL, DST)>, - }, - // TODO: Document those - TimEvent5 { - _x: PhantomData<(PSCL, DST)>, - }, - TimEvent6 { - _x: PhantomData<(PSCL, DST)>, - }, - TimEvent7 { - _x: PhantomData<(PSCL, DST)>, - }, - TimEvent8 { - _x: PhantomData<(PSCL, DST)>, - }, - TimEvent9 { - _x: PhantomData<(PSCL, DST)>, - }, +/// Event that can be used to set/reset an output +pub trait EventSource { + const BITS: u32; +} + +/// Done: +/// * [x] Eev1-10 +/// * [x] Master period +/// * [x] Master CMP1-4 +/// * [x] Cmp2, Cmp4 +/// * [x] Timer Update +/// * [ ] Neighbor timers compare events +/// Event that can be used reset the timer counter +pub trait TimerResetEventSource { + const BITS: u32; } - -macro_rules! hr_timer_reset_event_source_common { - ($(#[$($attrss:tt)*])* pub enum $t:ident { [COMMON], $(#[$($attrss2:tt)*] $vals:tt = 1 << $x:literal,)*}) => { - $(#[$($attrss)*])* - pub enum $t { - $(#[$($attrss2)*] $vals = 1 << $x,)* - - /// The timer counter is reset upon external event 10. - Eevnt10 = 1 << 18, - - /// The timer counter is reset upon external event 9. - Eevnt9 = 1 << 17, - - /// The timer counter is reset upon external event 8. - Eevnt8 = 1 << 16, - - /// The timer counter is reset upon external event 7. - Eevnt7 = 1 << 15, - - /// The timer counter is reset upon external event 6. - Eevnt6 = 1 << 14, - - /// The timer counter is reset upon external event 5. - Eevnt5 = 1 << 13, - - /// The timer counter is reset upon external event 4. - Eevnt4 = 1 << 12, - - /// The timer counter is reset upon external event 3. - Eevnt3 = 1 << 11, - - /// The timer counter is reset upon external event 2. - Eevnt2 = 1 << 10, - - /// The timer counter is reset upon external event 1. - Eevnt1 = 1 << 9, - - /// The timer counter is reset upon master timer compare 4 event. - MasterCmp4 = 1 << 8, - - /// The timer counter is reset upon master timer compare 3 event. - MasterCmp3 = 1 << 7, - - /// The timer counter is reset upon master timer compare 2 event. - MasterCmp2 = 1 << 6, - - /// The timer counter is reset upon master timer compare 1 event. - MasterCmp1 = 1 << 5, - - /// The timer counter is reset upon master timer period event. - MasterPeriod = 1 << 4, - - /// The timer counter is reset upon timer its own compare 4 event - Cmp4 = 1 << 3, - - /// The timer counter is reset upon timer its own compare 2 event - Cmp2 = 1 << 2, - - /// The timer counter is reset upon update event. - Update = 1 << 1, - } - }; -} - -hr_timer_reset_event_source_common!( - /// A - pub enum TimerAResetEventSource { - [COMMON], - /// The timer counter is reset upon timer F compare 2 event. - TimFCmp2 = 1 << 31, - - /// The timer counter is reset upon timer E compare 4 event. - TimECmp4 = 1 << 30, - - /// The timer counter is reset upon timer E compare 2 event. - TimECmp2 = 1 << 29, - - /// The timer counter is reset upon timer E compare 1 event. - TimECmp1 = 1 << 28, - - /// The timer counter is reset upon timer D compare 4 event. - TimDCmp4 = 1 << 27, - - /// The timer counter is reset upon timer D compare 2 event. - TimDCmp2 = 1 << 26, - - /// The timer counter is reset upon timer D compare 1 event. - TimDCmp1 = 1 << 25, - - /// The timer counter is reset upon timer C compare 4 event. - TimCCmp4 = 1 << 24, - - /// The timer counter is reset upon timer C compare 2 event. - TimCCmp2 = 1 << 23, - - /// The timer counter is reset upon timer C compare 1 event. - TimCCmp1 = 1 << 22, - - /// The timer counter is reset upon timer B compare 4 event. - TimBCmp4 = 1 << 21, - - /// The timer counter is reset upon timer B compare 2 event. - TimBCmp2 = 1 << 20, - - /// The timer counter is reset upon timer B compare 1 event. - TimBCmp1 = 1 << 19, - - /// The timer counter is reset upon timer F compare 1 event. - TimFCmp1 = 1 << 0, - } -); - -hr_timer_reset_event_source_common!( - /// B - pub enum TimerBResetEventSource { - [COMMON], - - /// The timer counter is reset upon timer F compare 2 event. - TimFCmp2 = 1 << 31, - - /// The timer counter is reset upon timer E compare 4 event. - TimECmp4 = 1 << 30, - - /// The timer counter is reset upon timer E compare 2 event. - TimECmp2 = 1 << 29, - - /// The timer counter is reset upon timer E compare 1 event. - TimECmp1 = 1 << 28, - - /// The timer counter is reset upon timer D compare 4 event. - TimDCmp4 = 1 << 27, - - /// The timer counter is reset upon timer D compare 2 event. - TimDCmp2 = 1 << 26, - - /// The timer counter is reset upon timer D compare 1 event. - TimDCmp1 = 1 << 25, - - /// The timer counter is reset upon timer C compare 4 event. - TimCCmp4 = 1 << 24, - - /// The timer counter is reset upon timer C compare 2 event. - TimCCmp2 = 1 << 23, - - /// The timer counter is reset upon timer C compare 1 event. - TimCCmp1 = 1 << 22, - - /// The timer counter is reset upon timer A compare 4 event. - TimACmp4 = 1 << 21, - - /// The timer counter is reset upon timer A compare 2 event. - TimACmp2 = 1 << 20, - - /// The timer counter is reset upon timer A compare 1 event. - TimACmp1 = 1 << 19, - - /// The timer counter is reset upon timer F compare 1 event. - TimFCmp1 = 1 << 0, - } -); - -hr_timer_reset_event_source_common!( - /// C - pub enum TimerCResetEventSource { - [COMMON], - - /// The timer counter is reset upon timer F compare 2 event. - TimFCmp2 = 1 << 31, - - /// The timer counter is reset upon timer E compare 4 event. - TimECmp4 = 1 << 30, - - /// The timer counter is reset upon timer E compare 2 event. - TimECmp2 = 1 << 29, - - /// The timer counter is reset upon timer E compare 1 event. - TimECmp1 = 1 << 28, - - /// The timer counter is reset upon timer D compare 4 event. - TimDCmp4 = 1 << 27, - - /// The timer counter is reset upon timer D compare 2 event. - TimDCmp2 = 1 << 26, - - /// The timer counter is reset upon timer D compare 1 event. - TimDCmp1 = 1 << 25, - - /// The timer counter is reset upon timer B compare 4 event. - TimBCmp4 = 1 << 24, - - /// The timer counter is reset upon timer B compare 2 event. - TimBCmp2 = 1 << 23, - - /// The timer counter is reset upon timer B compare 1 event. - TimBCmp1 = 1 << 22, - - /// The timer counter is reset upon timer A compare 4 event. - TimACmp4 = 1 << 21, - - /// The timer counter is reset upon timer A compare 2 event. - TimACmp2 = 1 << 20, - - /// The timer counter is reset upon timer A compare 1 event. - TimACmp1 = 1 << 19, - - - /// The timer counter is reset upon timer F compare 1 event. - TimFCmp1 = 1 << 0, - } -); - -hr_timer_reset_event_source_common!( - /// D - pub enum TimerDResetEventSource { - [COMMON], - - /// The timer counter is reset upon timer F compare 2 event. - TimFCmp2 = 1 << 31, - - /// The timer counter is reset upon timer E compare 4 event. - TimECmp4 = 1 << 30, - - /// The timer counter is reset upon timer E compare 2 event. - TimECmp2 = 1 << 29, - - /// The timer counter is reset upon timer E compare 1 event. - TimECmp1 = 1 << 28, - - /// The timer counter is reset upon timer C compare 4 event. - TimCCmp4 = 1 << 27, - - /// The timer counter is reset upon timer C compare 2 event. - TimCCmp2 = 1 << 26, - - /// The timer counter is reset upon timer C compare 1 event. - TimCCmp1 = 1 << 25, - - /// The timer counter is reset upon timer B compare 4 event. - TimBCmp4 = 1 << 24, - - /// The timer counter is reset upon timer B compare 2 event. - TimBCmp2 = 1 << 23, - - /// The timer counter is reset upon timer B compare 1 event. - TimBCmp1 = 1 << 22, - - /// The timer counter is reset upon timer A compare 4 event. - TimACmp4 = 1 << 21, - - /// The timer counter is reset upon timer A compare 2 event. - TimACmp2 = 1 << 20, - - /// The timer counter is reset upon timer A compare 1 event. - TimACmp1 = 1 << 19, - - /// The timer counter is reset upon timer F compare 1 event. - TimFCmp1 = 1 << 0, - } -); - -hr_timer_reset_event_source_common!( - /// E - pub enum TimerEResetEventSource { - [COMMON], - - /// The timer counter is reset upon timer F compare 2 event. - TimFCmp2 = 1 << 31, - - /// The timer counter is reset upon timer D compare 4 event. - TimDCmp4 = 1 << 30, - - /// The timer counter is reset upon timer D compare 2 event. - TimDCmp2 = 1 << 29, - - /// The timer counter is reset upon timer D compare 1 event. - TimDCmp1 = 1 << 28, - - /// The timer counter is reset upon timer C compare 4 event. - TimCCmp4 = 1 << 27, - - /// The timer counter is reset upon timer C compare 2 event. - TimCCmp2 = 1 << 26, - - /// The timer counter is reset upon timer C compare 1 event. - TimCCmp1 = 1 << 25, - - /// The timer counter is reset upon timer B compare 4 event. - TimBCmp4 = 1 << 24, - - /// The timer counter is reset upon timer B compare 2 event. - TimBCmp2 = 1 << 23, - - /// The timer counter is reset upon timer B compare 1 event. - TimBCmp1 = 1 << 22, - - /// The timer counter is reset upon timer A compare 4 event. - TimACmp4 = 1 << 21, - - /// The timer counter is reset upon timer A compare 2 event. - TimACmp2 = 1 << 20, - - /// The timer counter is reset upon timer A compare 1 event. - TimACmp1 = 1 << 19, - - - /// The timer counter is reset upon timer F compare 1 event. - TimFCmp1 = 1 << 0, - } -); - -hr_timer_reset_event_source_common!( - /// F - pub enum TimerFResetEventSource { - [COMMON], - - /// The timer counter is reset upon timer E compare 2 event. - TimECmp2 = 1 << 31, - - /// The timer counter is reset upon timer D compare 4 event. - TimDCmp4 = 1 << 30, - - /// The timer counter is reset upon timer D compare 2 event. - TimDCmp2 = 1 << 29, - - /// The timer counter is reset upon timer D compare 1 event. - TimDCmp1 = 1 << 28, - - /// The timer counter is reset upon timer C compare 4 event. - TimCCmp4 = 1 << 27, - - /// The timer counter is reset upon timer C compare 2 event. - TimCCmp2 = 1 << 26, - - /// The timer counter is reset upon timer C compare 1 event. - TimCCmp1 = 1 << 25, - - /// The timer counter is reset upon timer B compare 4 event. - TimBCmp4 = 1 << 24, - - /// The timer counter is reset upon timer B compare 2 event. - TimBCmp2 = 1 << 23, - - /// The timer counter is reset upon timer B compare 1 event. - TimBCmp1 = 1 << 22, - - /// The timer counter is reset upon timer A compare 4 event. - TimACmp4 = 1 << 21, - - /// The timer counter is reset upon timer A compare 2 event. - TimACmp2 = 1 << 20, - - /// The timer counter is reset upon timer A compare 1 event. - TimACmp1 = 1 << 19, - - /// The timer counter is reset upon timer E compare 1 event. - TimECmp1 = 1 << 0, - } -); diff --git a/src/hrtim/external_event.rs b/src/hrtim/external_event.rs index 1e3fa69f..d658e0f6 100644 --- a/src/hrtim/external_event.rs +++ b/src/hrtim/external_event.rs @@ -7,60 +7,13 @@ use crate::gpio::{self, AF13, AF3}; use crate::pwm::Polarity; use crate::stm32::HRTIM_COMMON; -use super::event::EevFastOrNormal; -use super::{control::HrTimCalibrated, event::EventSource}; +use super::control::HrTimCalibrated; #[derive(Copy, Clone, PartialEq)] -pub struct ExternalEventSourceInner { +pub struct ExternalEventSource { _x: PhantomData<()>, } -#[derive(Copy, Clone, PartialEq)] -pub enum ExternalEventSource { - Eevnt1 { - x: ExternalEventSourceInner<1, IS_FAST>, - }, - Eevnt2 { - x: ExternalEventSourceInner<2, IS_FAST>, - }, - Eevnt3 { - x: ExternalEventSourceInner<3, IS_FAST>, - }, - Eevnt4 { - x: ExternalEventSourceInner<4, IS_FAST>, - }, - Eevnt5 { - x: ExternalEventSourceInner<5, IS_FAST>, - }, - Eevnt6 { - x: ExternalEventSourceInner<6, IS_FAST>, - }, - Eevnt7 { - x: ExternalEventSourceInner<7, IS_FAST>, - }, - Eevnt8 { - x: ExternalEventSourceInner<8, IS_FAST>, - }, - Eevnt9 { - x: ExternalEventSourceInner<9, IS_FAST>, - }, - Eevnt10 { - x: ExternalEventSourceInner<10, IS_FAST>, - }, -} - -impl From> for EventSource { - fn from(e: ExternalEventSource) -> Self { - EventSource::ExternalEvent(EevFastOrNormal::Fast(e)) - } -} - -impl From> for EventSource { - fn from(e: ExternalEventSource) -> Self { - EventSource::ExternalEvent(EevFastOrNormal::Normal(e)) - } -} - pub struct EevInputs { pub eev_input1: EevInput<1>, pub eev_input2: EevInput<2>, @@ -281,7 +234,7 @@ where } pub trait ToExternalEventSource { - fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSourceInner; + fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource; } #[derive(Copy, Clone)] @@ -317,7 +270,7 @@ macro_rules! impl_eev1_5_to_es { fn finalize( self, _calibrated: &mut HrTimCalibrated, - ) -> ExternalEventSourceInner<$N, IS_FAST> { + ) -> ExternalEventSource<$N, IS_FAST> { let SourceBuilder { src_bits, edge_or_polarity_bits, @@ -342,7 +295,7 @@ macro_rules! impl_eev1_5_to_es { }); } - ExternalEventSourceInner { _x: PhantomData } + ExternalEventSource { _x: PhantomData } } } }; @@ -353,10 +306,7 @@ macro_rules! impl_eev6_10_to_es { impl ExternalEventBuilder6To10 for SourceBuilder<$N, false> {} impl ToExternalEventSource<$N, false> for SourceBuilder<$N, false> { - fn finalize( - self, - _calibrated: &mut HrTimCalibrated, - ) -> ExternalEventSourceInner<$N, false> { + fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource<$N, false> { let SourceBuilder { src_bits, edge_or_polarity_bits, @@ -380,7 +330,7 @@ macro_rules! impl_eev6_10_to_es { common.eecr3.modify(|_r, w| w.$eeXf().bits(filter_bits)); } - ExternalEventSourceInner { _x: PhantomData } + ExternalEventSource { _x: PhantomData } } } }; @@ -398,40 +348,14 @@ impl_eev6_10_to_es!(Eevnt8, 8, ee8src, ee8pol, ee8sns, ee8f); impl_eev6_10_to_es!(Eevnt9, 9, ee9src, ee9pol, ee9sns, ee9f); impl_eev6_10_to_es!(Eevnt10, 10, ee10src, ee10pol, ee10sns, ee10f); -impl - super::capture::CaptureEvent - for ExternalEventSourceInner +impl super::capture::CaptureEvent + for ExternalEventSource { const BITS: u32 = 1 << (N + 1); // EEV1 is at bit #2 etc } -impl - super::capture::CaptureEvent - for ExternalEventSourceInner +impl super::event::TimerResetEventSource + for ExternalEventSource { - const BITS: u32 = 1 << (N + 1); // EEV1 is at bit #2 etc -} - -// TODO: Get rid of ExternalEventSource completely in favour of using ExternalEventSourceInner directly -macro_rules! impl_into_ees { - ($($N:literal => $variant:ident),+) => {$( - impl Into> for ExternalEventSourceInner<$N, IS_FAST> { - fn into(self) -> ExternalEventSource { - ExternalEventSource::$variant { x: self } - } - } - )+} -} - -impl_into_ees! { - 1 => Eevnt1, - 2 => Eevnt2, - 3 => Eevnt3, - 4 => Eevnt4, - 5 => Eevnt5, - 6 => Eevnt6, - 7 => Eevnt7, - 8 => Eevnt8, - 9 => Eevnt9, - 10 => Eevnt10 + const BITS: u32 = 1 << (N + 8); // EEV1 is at bit 9 } diff --git a/src/hrtim/output.rs b/src/hrtim/output.rs index 45c97ca0..05d6003e 100644 --- a/src/hrtim/output.rs +++ b/src/hrtim/output.rs @@ -1,10 +1,9 @@ -use crate::hrtim::external_event::ExternalEventSource; use crate::stm32::{ HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF, }; use core::marker::PhantomData; -use super::event::{EevFastOrNormal, EventSource, NeighborTimerEventSource}; +use super::event::EventSource; use crate::{ gpio::{ gpioa::{PA10, PA11, PA8, PA9}, @@ -16,80 +15,6 @@ use crate::{ stm32::HRTIM_COMMON, }; -macro_rules! hrtim_out_common { - ($e:ident, $register:expr, $action:ident) => { - match $e { - ExternalEventSource::Eevnt1 { .. } => $register.modify(|_r, w| w.extevnt1().$action()), - ExternalEventSource::Eevnt2 { .. } => $register.modify(|_r, w| w.extevnt2().$action()), - ExternalEventSource::Eevnt3 { .. } => $register.modify(|_r, w| w.extevnt3().$action()), - ExternalEventSource::Eevnt4 { .. } => $register.modify(|_r, w| w.extevnt4().$action()), - ExternalEventSource::Eevnt5 { .. } => $register.modify(|_r, w| w.extevnt5().$action()), - ExternalEventSource::Eevnt6 { .. } => $register.modify(|_r, w| w.extevnt6().$action()), - ExternalEventSource::Eevnt7 { .. } => $register.modify(|_r, w| w.extevnt7().$action()), - ExternalEventSource::Eevnt8 { .. } => $register.modify(|_r, w| w.extevnt8().$action()), - ExternalEventSource::Eevnt9 { .. } => $register.modify(|_r, w| w.extevnt9().$action()), - ExternalEventSource::Eevnt10 { .. } => { - $register.modify(|_r, w| w.extevnt10().$action()) - } - } - }; - - ($TIMX:ident, $set_event:expr, $register:ident, $action:ident) => {{ - let tim = unsafe { &*$TIMX::ptr() }; - - match $set_event { - EventSource::Cr1 { .. } => tim.$register.modify(|_r, w| w.cmp1().$action()), - EventSource::Cr2 { .. } => tim.$register.modify(|_r, w| w.cmp2().$action()), - EventSource::Cr3 { .. } => tim.$register.modify(|_r, w| w.cmp3().$action()), - EventSource::Cr4 { .. } => tim.$register.modify(|_r, w| w.cmp4().$action()), - EventSource::Period { .. } => tim.$register.modify(|_r, w| w.per().$action()), - - EventSource::MasterCr1 { .. } => tim.$register.modify(|_r, w| w.mstcmp1().$action()), - EventSource::MasterCr2 { .. } => tim.$register.modify(|_r, w| w.mstcmp2().$action()), - EventSource::MasterCr3 { .. } => tim.$register.modify(|_r, w| w.mstcmp3().$action()), - EventSource::MasterCr4 { .. } => tim.$register.modify(|_r, w| w.mstcmp4().$action()), - EventSource::MasterPeriod { .. } => tim.$register.modify(|_r, w| w.mstper().$action()), - - EventSource::ExternalEvent(EevFastOrNormal::Fast(e)) => { - hrtim_out_common!(e, tim.$register, $action) - } - EventSource::ExternalEvent(EevFastOrNormal::Normal(e)) => { - hrtim_out_common!(e, tim.$register, $action) - } - - EventSource::NeighborTimer { n } => match n { - NeighborTimerEventSource::TimEvent1 { .. } => { - tim.$register.modify(|_r, w| w.timevnt1().$action()) - } - NeighborTimerEventSource::TimEvent2 { .. } => { - tim.$register.modify(|_r, w| w.timevnt2().$action()) - } - NeighborTimerEventSource::TimEvent3 { .. } => { - tim.$register.modify(|_r, w| w.timevnt3().$action()) - } - NeighborTimerEventSource::TimEvent4 { .. } => { - tim.$register.modify(|_r, w| w.timevnt4().$action()) - } - NeighborTimerEventSource::TimEvent5 { .. } => { - tim.$register.modify(|_r, w| w.timevnt5().$action()) - } - NeighborTimerEventSource::TimEvent6 { .. } => { - tim.$register.modify(|_r, w| w.timevnt6().$action()) - } - NeighborTimerEventSource::TimEvent7 { .. } => { - tim.$register.modify(|_r, w| w.timevnt7().$action()) - } - NeighborTimerEventSource::TimEvent8 { .. } => { - tim.$register.modify(|_r, w| w.timevnt8().$action()) - } - NeighborTimerEventSource::TimEvent9 { .. } => { - tim.$register.modify(|_r, w| w.timevnt9().$action()) - } - }, - } - }}; -} - macro_rules! hrtim_out { ($($TIMX:ident: $out_type:ident: $tXYoen:ident, $tXYodis:ident, $tXYods:ident, $setXYr:ident, $rstXYr:ident,)+) => {$( impl HrOutput for $out_type<$TIMX, PSCL> { @@ -103,18 +28,22 @@ macro_rules! hrtim_out { common.odisr.write(|w| { w.$tXYodis().set_bit() }); } - fn enable_set_event(&mut self, set_event: impl Into>) { - hrtim_out_common!($TIMX, set_event.into(), $setXYr, 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: impl Into>) { - hrtim_out_common!($TIMX, set_event.into(), $setXYr, clear_bit) + 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_rst_event(&mut self, reset_event: impl Into>) { - hrtim_out_common!($TIMX, reset_event.into(), $rstXYr, set_bit) + 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: impl Into>) { - hrtim_out_common!($TIMX, reset_event.into(), $rstXYr, clear_bit) + 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 get_state(&self) -> State { @@ -168,19 +97,19 @@ pub trait HrOutput { /// /// NOTE: Enabling the same event for both SET and RESET /// will make that event TOGGLE the output - fn enable_set_event(&mut self, set_event: impl Into>); + fn enable_set_event>(&mut self, set_event: &ES); /// Stop listening to the specified event - fn disable_set_event(&mut self, set_event: impl Into>); + fn disable_set_event>(&mut self, set_event: &ES); /// Set this output to *not* active every time the specified event occurs /// /// NOTE: Enabling the same event for both SET and RESET /// will make that event TOGGLE the output - fn enable_rst_event(&mut self, reset_event: impl Into>); + fn enable_rst_event>(&mut self, reset_event: &ES); /// Stop listening to the specified event - fn disable_rst_event(&mut self, reset_event: impl Into>); + fn disable_rst_event>(&mut self, reset_event: &ES); /// Get current state of the output fn get_state(&self) -> State; diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs index 9870ad12..1f3fa77e 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -6,10 +6,6 @@ use core::marker::PhantomData; use super::{ capture::{self, HrCapt}, control::HrPwmControl, - event::{ - TimerAResetEventSource, TimerBResetEventSource, TimerCResetEventSource, - TimerDResetEventSource, TimerEResetEventSource, TimerFResetEventSource, - }, }; pub struct HrTim { @@ -60,7 +56,7 @@ macro_rules! hrtim_timer { $repie:ident, $icr:ident, $repc:ident, - $(($rstXr:ident, $TimerXResetEventSource:ident))*, + $(($rstXr:ident))*, )+) => {$( impl HrTimer<$TIMX, PSCL> for HrTim<$TIMX, PSCL> { fn get_period(&self) -> u16 { @@ -112,35 +108,6 @@ macro_rules! hrtim_timer { } impl HrTim<$TIMX, PSCL> { - $( - /// 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 - pub fn enable_reset_event(&mut self, set_event: $TimerXResetEventSource) { - let tim = unsafe { &*$TIMX::ptr() }; - - unsafe { tim.$rstXr.modify(|r, w| w.bits(r.bits() | set_event as u32)); } - } - - /// Stop listening to the specified event - pub fn disable_reset_event(&mut self, set_event: $TimerXResetEventSource) { - let tim = unsafe { &*$TIMX::ptr() }; - - unsafe { tim.$rstXr.modify(|r, w| w.bits(r.bits() & !(set_event as u32))); } - })* - pub fn set_repetition_counter(&mut self, repetition_counter: u8) { let tim = unsafe { &*$TIMX::ptr() }; @@ -168,15 +135,50 @@ macro_rules! hrtim_timer { } } - /// Timer Update event - impl super::capture::CaptureEvent<$TIMX, PSCL, super::capture::Ch1> for HrTim<$TIMX, PSCL> { - const BITS: u32 = 1 << 1; - } + $(// Only for Non-Master timers + impl HrTim<$TIMX, PSCL> { + /// 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 + pub 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 + pub 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)); } + } + } - /// Timer Update event - impl super::capture::CaptureEvent<$TIMX, PSCL, super::capture::Ch2> for HrTim<$TIMX, PSCL> { - const BITS: u32 = 1 << 1; - } + /// Timer Period event + impl super::event::EventSource for HrTim<$TIMX, PSCL> { + // $rstXr + const BITS: u32 = 1 << 2; + } + + /// Timer Update event + /// + /// TODO: What dows this mean? + impl super::capture::CaptureEvent<$TIMX, PSCL> for HrTim<$TIMX, PSCL> { + const BITS: u32 = 1 << 1; + } + )* )+} } @@ -207,12 +209,12 @@ use super::adc_trigger::Adc6810Trigger as Adc6810; hrtim_timer! { HRTIM_MASTER: mcntr, mcnt, mper, mcen, mper, mrep, mrep, mdier, mrepie, micr, mrepc,, - HRTIM_TIMA: cntar, cntx, perar, tacen, perx, repar, repx, timadier, repie, timaicr, repc, (rstar, TimerAResetEventSource), - HRTIM_TIMB: cntr, cntx, perbr, tbcen, perx, repbr, repx, timbdier, repie, timbicr, repc, (rstbr, TimerBResetEventSource), - HRTIM_TIMC: cntcr, cntx, percr, tccen, perx, repcr, repx, timcdier, repie, timcicr, repc, (rstcr, TimerCResetEventSource), - HRTIM_TIMD: cntdr, cntx, perdr, tdcen, perx, repdr, repx, timddier, repie, timdicr, repc, (rstdr, TimerDResetEventSource), - HRTIM_TIME: cnter, cntx, perer, tecen, perx, reper, repx, timedier, repie, timeicr, repc, (rster, TimerEResetEventSource), - HRTIM_TIMF: cntfr, cntx, perfr, tfcen, perx, repfr, repx, timfdier, repie, timficr, repc, (rstfr, TimerFResetEventSource), + HRTIM_TIMA: cntar, cntx, perar, tacen, perx, repar, repx, timadier, repie, timaicr, repc, (rstar), + HRTIM_TIMB: cntr, cntx, perbr, tbcen, perx, repbr, repx, timbdier, repie, timbicr, repc, (rstbr), + HRTIM_TIMC: cntcr, cntx, percr, tccen, perx, repcr, repx, timcdier, repie, timcicr, repc, (rstcr), + HRTIM_TIMD: cntdr, cntx, perdr, tdcen, perx, repdr, repx, timddier, repie, timdicr, repc, (rstdr), + HRTIM_TIME: cnter, cntx, perer, tecen, perx, reper, repx, timedier, repie, timeicr, repc, (rster), + HRTIM_TIMF: cntfr, cntx, perfr, tfcen, perx, repfr, repx, timfdier, repie, timficr, repc, (rstfr), } hrtim_timer_adc_trigger! { @@ -225,3 +227,7 @@ hrtim_timer_adc_trigger! { HRTIM_TIME: [(Adc13: [(PER: 1 << 31), ]), (Adc24: [ (RST: 1 << 31)]), (Adc579: [(PER: 26), ]), (Adc6810: [ ])], HRTIM_TIMF: [(Adc13: [(PER: 1 << 24), (RST: 1 << 28)]), (Adc24: [(PER: 1 << 24), ]), (Adc579: [(PER: 30), (RST: 31)]), (Adc6810: [(PER: 31), ])] } + +impl super::event::TimerResetEventSource for HrTim { + const BITS: u32 = 1 << 4; // MSTPER +} From 27aa85e35644a3cf74add07ab483863f668cc45f Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Jan 2024 10:08:57 +0100 Subject: [PATCH 51/88] HRTIM: Fix bugs caused by traitification --- src/hrtim/control.rs | 20 ++++++++++---------- src/hrtim/output.rs | 18 +++++++++--------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/hrtim/control.rs b/src/hrtim/control.rs index 42a80a5b..7a634210 100644 --- a/src/hrtim/control.rs +++ b/src/hrtim/control.rs @@ -212,70 +212,70 @@ pub struct HrPwmControl { use super::adc_trigger::{Adc13Trigger, Adc24Trigger, Adc579Trigger, Adc6810Trigger}; impl HrPwmControl { - pub fn enable_adc_trigger1_source(&mut self, _trigger: T) { + pub fn enable_adc_trigger1_source(&mut self, _trigger: &T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; unsafe { common.adc1r.modify(|r, w| w.bits(r.bits() | T::BITS)); } } - pub fn enable_adc_trigger2_source(&mut self, _trigger: T) { + pub fn enable_adc_trigger2_source(&mut self, _trigger: &T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; unsafe { common.adc2r.modify(|r, w| w.bits(r.bits() | T::BITS)); } } - pub fn enable_adc_trigger3_source(&mut self, _trigger: T) { + pub fn enable_adc_trigger3_source(&mut self, _trigger: &T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; unsafe { common.adc3r.modify(|r, w| w.bits(r.bits() | T::BITS)); } } - pub fn enable_adc_trigger4_source(&mut self, _trigger: T) { + pub fn enable_adc_trigger4_source(&mut self, _trigger: &T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; unsafe { common.adc4r.modify(|r, w| w.bits(r.bits() | T::BITS)); } } - pub fn enable_adc_trigger5_source(&mut self, _trigger: T) { + pub fn enable_adc_trigger5_source(&mut self, _trigger: &T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; common .adcer .modify(|_r, w| w.adc5trg().variant(T::BITS as u8)); } - pub fn enable_adc_trigger6_source(&mut self, _trigger: T) { + pub fn enable_adc_trigger6_source(&mut self, _trigger: &T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; common .adcer .modify(|_r, w| w.adc6trg().variant(T::BITS as u8)); } - pub fn enable_adc_trigger7_source(&mut self, _trigger: T) { + pub fn enable_adc_trigger7_source(&mut self, _trigger: &T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; common .adcer .modify(|_r, w| w.adc7trg().variant(T::BITS as u8)); } - pub fn enable_adc_trigger8_source(&mut self, _trigger: T) { + pub fn enable_adc_trigger8_source(&mut self, _trigger: &T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; common .adcer .modify(|_r, w| w.adc8trg().variant(T::BITS as u8)); } - pub fn enable_adc_trigger9_source(&mut self, _trigger: T) { + pub fn enable_adc_trigger9_source(&mut self, _trigger: &T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; common .adcer .modify(|_r, w| w.adc9trg().variant(T::BITS as u8)); } - pub fn enable_adc_trigger10_source(&mut self, _trigger: T) { + pub fn enable_adc_trigger10_source(&mut self, _trigger: &T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; common .adcer diff --git a/src/hrtim/output.rs b/src/hrtim/output.rs index 05d6003e..997ce4c7 100644 --- a/src/hrtim/output.rs +++ b/src/hrtim/output.rs @@ -28,20 +28,20 @@ macro_rules! hrtim_out { common.odisr.write(|w| { w.$tXYodis().set_bit() }); } - fn enable_set_event>(&mut self, _set_event: &ES) { + 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) { + 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_rst_event>(&mut self, _reset_event: &ES) { + 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) { + 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)); } } @@ -97,25 +97,25 @@ pub trait HrOutput { /// /// NOTE: Enabling the same event for both SET and RESET /// will make that event TOGGLE the output - fn enable_set_event>(&mut self, set_event: &ES); + fn enable_set_event>(&mut self, set_event: &ES); /// Stop listening to the specified event - fn disable_set_event>(&mut self, set_event: &ES); + fn disable_set_event>(&mut self, set_event: &ES); /// Set this output to *not* active every time the specified event occurs /// /// NOTE: Enabling the same event for both SET and RESET /// will make that event TOGGLE the output - fn enable_rst_event>(&mut self, reset_event: &ES); + fn enable_rst_event>(&mut self, reset_event: &ES); /// Stop listening to the specified event - fn disable_rst_event>(&mut self, reset_event: &ES); + fn disable_rst_event>(&mut self, reset_event: &ES); /// Get current state of the output fn get_state(&self) -> State; } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Copy, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum State { Idle, From 6beb611cc7a8b19172f7100454374eed9d7f2701 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Jan 2024 10:09:41 +0100 Subject: [PATCH 52/88] HRTIM: Update adc-trigger example for traitification changes --- examples/hrtim/adc-trigger.rs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/examples/hrtim/adc-trigger.rs b/examples/hrtim/adc-trigger.rs index 04865cbe..7df80a4f 100644 --- a/examples/hrtim/adc-trigger.rs +++ b/examples/hrtim/adc-trigger.rs @@ -31,12 +31,14 @@ fn main() -> ! { hrtim::control::HrControltExt, hrtim::output::HrOutput, hrtim::HrPwmAdvExt, - hrtim::{control::Adc13Trigger, Pscl4}, + hrtim::Pscl4, pwr::PwrExt, rcc::{self, RccExt}, stm32::Peripherals, }; + const VREF: f32 = 3.3; + info!("start"); let dp = Peripherals::take().unwrap(); @@ -109,14 +111,9 @@ fn main() -> ! { //out1 | | | | // | | | | // -------- ---------- -------- - let (hr_control, ..) = dp - .HRTIM_COMMON - .hr_control(&mut rcc) - .enable_adc_trigger1_source(Adc13Trigger::TimACmp3) - .enable_adc_trigger1_source(Adc13Trigger::TimACmp4) - .wait_for_calibration(); + let (hr_control, ..) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); let mut hr_control = hr_control.constrain(); - let (timer, (cr1, _cr2, _cr3, _cr4), (mut out1, mut out2)) = dp + let (timer, (cr1, _cr2, cr3, cr4), (mut out1, mut out2)) = dp .HRTIM_TIMA .pwm_advanced((pin_a, pin_b), &mut rcc) .prescaler(prescaler) @@ -126,6 +123,9 @@ fn main() -> ! { // as normal .finalize(&mut hr_control); + hr_control.enable_adc_trigger1_source(&cr3); + hr_control.enable_adc_trigger1_source(&cr4); + out1.enable_rst_event(&cr1); // Set low on compare match with cr1 out2.enable_rst_event(&cr1); @@ -144,7 +144,11 @@ fn main() -> ! { let millivolts = Vref::sample_to_millivolts((b[0] + b[2]) / 2); info!("pa3: {}mV", millivolts); - let temp = Temperature::temperature_to_degrees_centigrade((b[1] + b[3]) / 2); + let temp = Temperature::temperature_to_degrees_centigrade( + (b[1] + b[3]) / 2, + VREF, + adc::config::Resolution::Twelve, + ); info!("temp: {}℃C", temp); // Note: Temperature seems quite low... } } From 24d1bf1e8c765d73c52f0276fb2a2ee220a21d77 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Jan 2024 10:19:44 +0100 Subject: [PATCH 53/88] HRTIM: Start timer and set trigger points in adc-trigger example --- examples/hrtim/adc-trigger.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/examples/hrtim/adc-trigger.rs b/examples/hrtim/adc-trigger.rs index 7df80a4f..ad31dfc9 100644 --- a/examples/hrtim/adc-trigger.rs +++ b/examples/hrtim/adc-trigger.rs @@ -28,8 +28,10 @@ fn main() -> ! { delay::SYSTDelayExt, dma::{self, config::DmaConfig, stream::DMAExt, TransferExt}, gpio::{gpioa::PA8, gpioa::PA9, Alternate, GpioExt, AF13}, + hrtim::compare_register::HrCompareRegister, hrtim::control::HrControltExt, hrtim::output::HrOutput, + hrtim::timer::HrTimer, hrtim::HrPwmAdvExt, hrtim::Pscl4, pwr::PwrExt, @@ -111,18 +113,22 @@ fn main() -> ! { //out1 | | | | // | | | | // -------- ---------- -------- + let period = 0xFFFF; let (hr_control, ..) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); let mut hr_control = hr_control.constrain(); - let (timer, (cr1, _cr2, cr3, cr4), (mut out1, mut out2)) = dp + let (mut timer, (cr1, _cr2, mut cr3, mut cr4), (mut out1, mut out2)) = dp .HRTIM_TIMA .pwm_advanced((pin_a, pin_b), &mut rcc) .prescaler(prescaler) - .period(0xFFFF) + .period(period) // alternated every period with one being // inactive and the other getting to output its wave form // as normal .finalize(&mut hr_control); + cr3.set_duty(period / 3); + cr4.set_duty((2 * u32::from(period) / 3) as u16); + hr_control.enable_adc_trigger1_source(&cr3); hr_control.enable_adc_trigger1_source(&cr4); @@ -135,6 +141,8 @@ fn main() -> ! { out1.enable(); out2.enable(); + timer.start(&mut hr_control); + loop { let mut b = [0_u16; 4]; let r = transfer.read_exact(&mut b); @@ -149,6 +157,6 @@ fn main() -> ! { VREF, adc::config::Resolution::Twelve, ); - info!("temp: {}℃C", temp); // Note: Temperature seems quite low... + info!("temp: {}℃C", temp); } } From 7f54235bf08b4da398d336e8a1a97ffdb43c431f Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Jan 2024 11:35:53 +0100 Subject: [PATCH 54/88] HRTIM: Refactor adc trigger --- src/hrtim/control.rs | 145 ++++++++++++++++++++++++------------------- 1 file changed, 82 insertions(+), 63 deletions(-) diff --git a/src/hrtim/control.rs b/src/hrtim/control.rs index 7a634210..e86243a1 100644 --- a/src/hrtim/control.rs +++ b/src/hrtim/control.rs @@ -193,6 +193,17 @@ impl HrTimCalibrated { fault_4: FltMonitor4 { _x: PhantomData }, fault_5: FltMonitor5 { _x: PhantomData }, fault_6: FltMonitor6 { _x: PhantomData }, + + adc_trigger1: Adc1Trigger { _x: PhantomData }, + adc_trigger2: Adc2Trigger { _x: PhantomData }, + adc_trigger3: Adc3Trigger { _x: PhantomData }, + adc_trigger4: Adc4Trigger { _x: PhantomData }, + adc_trigger5: Adc5Trigger { _x: PhantomData }, + adc_trigger6: Adc6Trigger { _x: PhantomData }, + adc_trigger7: Adc7Trigger { _x: PhantomData }, + adc_trigger8: Adc8Trigger { _x: PhantomData }, + adc_trigger9: Adc9Trigger { _x: PhantomData }, + adc_trigger10: Adc10Trigger { _x: PhantomData }, } } } @@ -207,82 +218,90 @@ pub struct HrPwmControl { pub fault_4: FltMonitor4, pub fault_5: FltMonitor5, pub fault_6: FltMonitor6, -} -use super::adc_trigger::{Adc13Trigger, Adc24Trigger, Adc579Trigger, Adc6810Trigger}; + pub adc_trigger1: Adc1Trigger, + pub adc_trigger2: Adc2Trigger, + pub adc_trigger3: Adc3Trigger, + pub adc_trigger4: Adc4Trigger, + + pub adc_trigger5: Adc5Trigger, + pub adc_trigger6: Adc6Trigger, + pub adc_trigger7: Adc7Trigger, + pub adc_trigger8: Adc8Trigger, + pub adc_trigger9: Adc9Trigger, + pub adc_trigger10: Adc10Trigger, +} -impl HrPwmControl { - pub fn enable_adc_trigger1_source(&mut self, _trigger: &T) { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - unsafe { - common.adc1r.modify(|r, w| w.bits(r.bits() | T::BITS)); +macro_rules! impl_adc1234_trigger { + ($($t:ident: [$trait_:ident, $adcXr:ident, $variant345:ident $(, $variant12:ident)*]),*) => {$( + pub struct $t { + _x: PhantomData<()>, } - } - pub fn enable_adc_trigger2_source(&mut self, _trigger: &T) { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - unsafe { - common.adc2r.modify(|r, w| w.bits(r.bits() | T::BITS)); + impl $t { + pub fn enable_source(&mut self, _trigger: &T) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + unsafe { + common.$adcXr.modify(|r, w| w.bits(r.bits() | T::BITS)); + } + } + + $( + pub fn as_adc12_trigger(&self) -> crate::adc::config::ExternalTrigger12 { + crate::adc::config::ExternalTrigger12::$variant12 + } + )* + + pub fn as_adc345_trigger(&self) -> crate::adc::config::ExternalTrigger345 { + crate::adc::config::ExternalTrigger345::$variant345 + } } - } + )*} +} - pub fn enable_adc_trigger3_source(&mut self, _trigger: &T) { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - unsafe { - common.adc3r.modify(|r, w| w.bits(r.bits() | T::BITS)); +macro_rules! impl_adc5678910_trigger { + ($($t:ident: [$trait_:ident, $adcXtrg:ident, $variant345:ident, $variant12:ident]),*) => {$( + pub struct $t { + _x: PhantomData<()>, } - } - pub fn enable_adc_trigger4_source(&mut self, _trigger: &T) { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - unsafe { - common.adc4r.modify(|r, w| w.bits(r.bits() | T::BITS)); + impl $t { + pub fn enable_source(&mut self, _trigger: &T) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common + .adcer + .modify(|_r, w| w.$adcXtrg().variant(T::BITS as u8)); + } + + pub fn as_adc12_trigger(&self) -> crate::adc::config::ExternalTrigger12 { + crate::adc::config::ExternalTrigger12::$variant12 + } + + pub fn as_adc345_trigger(&self) -> crate::adc::config::ExternalTrigger345 { + crate::adc::config::ExternalTrigger345::$variant345 + } } - } - - pub fn enable_adc_trigger5_source(&mut self, _trigger: &T) { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common - .adcer - .modify(|_r, w| w.adc5trg().variant(T::BITS as u8)); - } - - pub fn enable_adc_trigger6_source(&mut self, _trigger: &T) { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common - .adcer - .modify(|_r, w| w.adc6trg().variant(T::BITS as u8)); - } - - pub fn enable_adc_trigger7_source(&mut self, _trigger: &T) { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common - .adcer - .modify(|_r, w| w.adc7trg().variant(T::BITS as u8)); - } - - pub fn enable_adc_trigger8_source(&mut self, _trigger: &T) { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common - .adcer - .modify(|_r, w| w.adc8trg().variant(T::BITS as u8)); - } + )*} +} - pub fn enable_adc_trigger9_source(&mut self, _trigger: &T) { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common - .adcer - .modify(|_r, w| w.adc9trg().variant(T::BITS as u8)); - } +impl_adc1234_trigger! {// reg adc345, adc12 + Adc1Trigger: [Adc13Trigger, adc1r, Hrtim_adc_trg_1, Hrtim_adc_trg_1], + Adc2Trigger: [Adc24Trigger, adc2r, Hrtim_adc_trg_2], + Adc3Trigger: [Adc13Trigger, adc3r, Hrtim_adc_trg_3, Hrtim_adc_trg_3], + Adc4Trigger: [Adc24Trigger, adc4r, Hrtim_adc_trg_4] +} - pub fn enable_adc_trigger10_source(&mut self, _trigger: &T) { - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common - .adcer - .modify(|_r, w| w.adc10trg().variant(T::BITS as u8)); - } +impl_adc5678910_trigger! { + Adc5Trigger: [Adc579Trigger, adc5trg, Hrtim_adc_trg_5, Hrtim_adc_trg_5], + Adc6Trigger: [Adc6810Trigger, adc6trg, Hrtim_adc_trg_6, Hrtim_adc_trg_6], + Adc7Trigger: [Adc579Trigger, adc7trg, Hrtim_adc_trg_7, Hrtim_adc_trg_7], + Adc8Trigger: [Adc6810Trigger, adc8trg, Hrtim_adc_trg_8, Hrtim_adc_trg_8], + Adc9Trigger: [Adc579Trigger, adc9trg, Hrtim_adc_trg_9, Hrtim_adc_trg_9], + Adc10Trigger: [Adc6810Trigger, adc10trg, Hrtim_adc_trg_10, Hrtim_adc_trg_10] } +use super::adc_trigger::{Adc13Trigger, Adc24Trigger, Adc579Trigger, Adc6810Trigger}; + pub enum AdcTriggerPostscaler { None = 0, Div2 = 1, From 8051ee41aa39a81a67c934ba1233e594f8c6c520 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Jan 2024 11:36:25 +0100 Subject: [PATCH 55/88] HRTIM: Refactor adc trigger - example hrtim-adc-trigger --- examples/hrtim/adc-trigger.rs | 61 +++++++++++++++++------------------ 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/examples/hrtim/adc-trigger.rs b/examples/hrtim/adc-trigger.rs index ad31dfc9..04366060 100644 --- a/examples/hrtim/adc-trigger.rs +++ b/examples/hrtim/adc-trigger.rs @@ -16,7 +16,7 @@ fn main() -> ! { #[cfg(any(feature = "stm32g474", feature = "stm32g484"))] #[entry] fn main() -> ! { - use hal::adc::{self, config::ExternalTrigger12}; + use hal::adc; use stm32g4xx_hal as hal; use defmt::info; @@ -74,32 +74,6 @@ fn main() -> ! { let gpioa = dp.GPIOA.split(&mut rcc); let pa0 = gpioa.pa0.into_analog(); - info!("Setup Adc1"); - let mut adc = dp - .ADC1 - .claim(ClockSource::SystemClock, &rcc, &mut delay, true); - - adc.set_external_trigger(( - adc::config::TriggerMode::RisingEdge, - ExternalTrigger12::Hrtim_adc_trg_1, - )); - adc.enable_temperature(&dp.ADC12_COMMON); - adc.set_continuous(Continuous::Discontinuous); - adc.reset_sequence(); - adc.configure_channel(&pa0, Sequence::One, SampleTime::Cycles_640_5); - adc.configure_channel(&Temperature, Sequence::Two, SampleTime::Cycles_640_5); - - info!("Setup DMA"); - let first_buffer = cortex_m::singleton!(: [u16; 10] = [0; 10]).unwrap(); - - let mut transfer = dma1ch1.into_circ_peripheral_to_memory_transfer( - adc.enable_dma(AdcDma::Continuous), - &mut first_buffer[..], - config, - ); - - transfer.start(|adc| adc.start_conversion()); - let pin_a: PA8> = gpioa.pa8.into_alternate(); let pin_b: PA9> = gpioa.pa9.into_alternate(); @@ -121,16 +95,13 @@ fn main() -> ! { .pwm_advanced((pin_a, pin_b), &mut rcc) .prescaler(prescaler) .period(period) - // alternated every period with one being - // inactive and the other getting to output its wave form - // as normal .finalize(&mut hr_control); cr3.set_duty(period / 3); cr4.set_duty((2 * u32::from(period) / 3) as u16); - hr_control.enable_adc_trigger1_source(&cr3); - hr_control.enable_adc_trigger1_source(&cr4); + hr_control.adc_trigger1.enable_source(&cr3); + hr_control.adc_trigger1.enable_source(&cr4); out1.enable_rst_event(&cr1); // Set low on compare match with cr1 out2.enable_rst_event(&cr1); @@ -138,6 +109,32 @@ fn main() -> ! { out1.enable_set_event(&timer); // Set high at new period out2.enable_set_event(&timer); + info!("Setup Adc1"); + let mut adc = dp + .ADC1 + .claim(ClockSource::SystemClock, &rcc, &mut delay, true); + + adc.set_external_trigger(( + adc::config::TriggerMode::RisingEdge, + hr_control.adc_trigger1.as_adc12_trigger(), + )); + adc.enable_temperature(&dp.ADC12_COMMON); + adc.set_continuous(Continuous::Discontinuous); + adc.reset_sequence(); + adc.configure_channel(&pa0, Sequence::One, SampleTime::Cycles_640_5); + adc.configure_channel(&Temperature, Sequence::Two, SampleTime::Cycles_640_5); + + info!("Setup DMA"); + let first_buffer = cortex_m::singleton!(: [u16; 10] = [0; 10]).unwrap(); + + let mut transfer = dma1ch1.into_circ_peripheral_to_memory_transfer( + adc.enable_dma(AdcDma::Continuous), + &mut first_buffer[..], + config, + ); + + transfer.start(|adc| adc.start_conversion()); + out1.enable(); out2.enable(); From 60118060cb7860fa7f68b26482c2cea1ab214bbd Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Jan 2024 13:51:05 +0100 Subject: [PATCH 56/88] HRTIM: adc trigger impl into --- examples/hrtim/adc-trigger.rs | 2 +- src/adc.rs | 4 ++-- src/hrtim/control.rs | 23 +++++++++++++++-------- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/examples/hrtim/adc-trigger.rs b/examples/hrtim/adc-trigger.rs index 04366060..08cf4348 100644 --- a/examples/hrtim/adc-trigger.rs +++ b/examples/hrtim/adc-trigger.rs @@ -116,7 +116,7 @@ fn main() -> ! { adc.set_external_trigger(( adc::config::TriggerMode::RisingEdge, - hr_control.adc_trigger1.as_adc12_trigger(), + &hr_control.adc_trigger1, )); adc.enable_temperature(&dp.ADC12_COMMON); adc.set_continuous(Continuous::Discontinuous); diff --git a/src/adc.rs b/src/adc.rs index 08a9a73a..45f775bf 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -2341,8 +2341,8 @@ macro_rules! adc { /// Sets which external trigger to use and if it is disabled, rising, falling or both #[inline(always)] - pub fn set_external_trigger(&mut self, (edge, extsel): (config::TriggerMode, $trigger_type)) { - self.adc.set_external_trigger( (edge, extsel) ) + pub fn set_external_trigger>(&mut self, (edge, extsel): (config::TriggerMode, T)) { + self.adc.set_external_trigger( (edge, extsel.into()) ) } /// Sets auto delay to true or false diff --git a/src/hrtim/control.rs b/src/hrtim/control.rs index e86243a1..9dc694ea 100644 --- a/src/hrtim/control.rs +++ b/src/hrtim/control.rs @@ -245,14 +245,16 @@ macro_rules! impl_adc1234_trigger { common.$adcXr.modify(|r, w| w.bits(r.bits() | T::BITS)); } } + } - $( - pub fn as_adc12_trigger(&self) -> crate::adc::config::ExternalTrigger12 { - crate::adc::config::ExternalTrigger12::$variant12 - } - )* + $(impl Into for &$t { + fn into(self) -> crate::adc::config::ExternalTrigger12 { + crate::adc::config::ExternalTrigger12::$variant12 + } + })* - pub fn as_adc345_trigger(&self) -> crate::adc::config::ExternalTrigger345 { + impl Into for &$t { + fn into(self) -> crate::adc::config::ExternalTrigger345 { crate::adc::config::ExternalTrigger345::$variant345 } } @@ -272,15 +274,20 @@ macro_rules! impl_adc5678910_trigger { .adcer .modify(|_r, w| w.$adcXtrg().variant(T::BITS as u8)); } + } - pub fn as_adc12_trigger(&self) -> crate::adc::config::ExternalTrigger12 { + impl Into for &$t { + fn into(self) -> crate::adc::config::ExternalTrigger12 { crate::adc::config::ExternalTrigger12::$variant12 } + } - pub fn as_adc345_trigger(&self) -> crate::adc::config::ExternalTrigger345 { + impl Into for &$t { + fn into(self) -> crate::adc::config::ExternalTrigger345 { crate::adc::config::ExternalTrigger345::$variant345 } } + )*} } From 47f09700eae1c39040c05953a99238df7b9a1f72 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Jan 2024 13:57:42 +0100 Subject: [PATCH 57/88] HRTIM: adc-trigger example set duty --- examples/hrtim/adc-trigger.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/hrtim/adc-trigger.rs b/examples/hrtim/adc-trigger.rs index 08cf4348..314813a9 100644 --- a/examples/hrtim/adc-trigger.rs +++ b/examples/hrtim/adc-trigger.rs @@ -87,16 +87,20 @@ fn main() -> ! { //out1 | | | | // | | | | // -------- ---------- -------- + // . ^ ^ + // . | | + //AD samlp pa0 temp let period = 0xFFFF; let (hr_control, ..) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); let mut hr_control = hr_control.constrain(); - let (mut timer, (cr1, _cr2, mut cr3, mut cr4), (mut out1, mut out2)) = dp + let (mut timer, (mut cr1, _cr2, mut cr3, mut cr4), (mut out1, mut out2)) = dp .HRTIM_TIMA .pwm_advanced((pin_a, pin_b), &mut rcc) .prescaler(prescaler) .period(period) .finalize(&mut hr_control); + cr1.set_duty(period / 2); cr3.set_duty(period / 3); cr4.set_duty((2 * u32::from(period) / 3) as u16); From df47539c4afb7d9312fa8b6a44675467c1398f1e Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Jan 2024 17:23:55 +0100 Subject: [PATCH 58/88] HRTIM: Move clear_repetition_interrupt to trait --- src/hrtim/timer.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs index 1f3fa77e..142b92de 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -35,6 +35,8 @@ pub trait HrTimer: Sized { /// Stop timer and reset counter fn stop_and_reset(&mut self, _hr_control: &mut HrPwmControl); + fn clear_repetition_interrupt(&mut self); + /// Make a handle to this timers reset event to use as adc trigger fn as_reset_adc_trigger(&self) -> super::adc_trigger::TimerReset; @@ -105,6 +107,12 @@ macro_rules! hrtim_timer { fn as_period_adc_trigger(&self) -> super::adc_trigger::TimerPeriod { super::adc_trigger::TimerPeriod(PhantomData) } + + fn clear_repetition_interrupt(&mut self) { + let tim = unsafe { &*$TIMX::ptr() }; + + tim.$icr.write(|w| w.$repc().set_bit()); + } } impl HrTim<$TIMX, PSCL> { @@ -120,12 +128,6 @@ macro_rules! hrtim_timer { tim.$dier.modify(|_r, w| w.$repie().bit(enable)); } - pub fn clear_repetition_interrupt(&mut self) { - let tim = unsafe { &*$TIMX::ptr() }; - - tim.$icr.write(|w| w.$repc().set_bit()); - } - pub fn capture_ch1(&mut self) -> &mut HrCapt<$TIMX, PSCL, capture::Ch1> { &mut self.capture_ch1 } From 7f93d53a3dd7e3d6a2a2b081373e51c7fad4cd29 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 22 Jan 2024 11:31:22 +0100 Subject: [PATCH 59/88] HRTIM: Capture interrupts and clippy --- src/hrtim/capture.rs | 57 +++++++++++++++++++++++++++++++++----------- src/hrtim/control.rs | 16 ++++++------- src/hrtim/output.rs | 4 ++-- 3 files changed, 53 insertions(+), 24 deletions(-) diff --git a/src/hrtim/capture.rs b/src/hrtim/capture.rs index 1c71943a..e0019022 100644 --- a/src/hrtim/capture.rs +++ b/src/hrtim/capture.rs @@ -9,6 +9,8 @@ pub struct HrCapt { _x: PhantomData<(TIM, PSCL, CH)>, } +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug)] pub enum CountingDirection { Up = 0, Down = 1, @@ -23,7 +25,7 @@ pub trait CaptureEvent { const BITS: u32; } -trait HrCapture { +pub trait HrCapture { fn get(&self) -> (u16, CountingDirection); /// Get number of ticks relative to beginning of upcounting @@ -43,10 +45,14 @@ trait HrCapture { let dir_bit = dir as u32; dir_bit << 16 | u32::from(value) } + + fn clear_interrupt(&mut self); + + fn is_pending(&self) -> bool; } macro_rules! impl_capture { - ($($TIMX:ident: $CH:ident, $cptXYr:ident, $cptXYcr:ident, $cptXx:ident),+) => { + ($($TIMX:ident: $CH:ident, $cptXYr:ident, $cptXYcr:ident, $cptXx:ident, $dier:ident, $icr:ident, $isr:ident, $cptXie:ident, $cptXc:ident, $cptX:ident),+) => { $(impl HrCapt<$TIMX, PSCL, $CH> { /// Add event to capture /// @@ -78,6 +84,15 @@ macro_rules! impl_capture { tim.$cptXYcr.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)); + } } impl HrCapture for HrCapt<$TIMX, PSCL, $CH> { @@ -92,26 +107,40 @@ macro_rules! impl_capture { (value, dir) } + + fn clear_interrupt(&mut self) { + let tim = unsafe { &*$TIMX::ptr() }; + + // No need for exclusive access since this is a write only register + tim.$icr.write(|w| w.$cptXc().set_bit()); + } + + fn is_pending(&self) -> bool { + let tim = unsafe { &*$TIMX::ptr() }; + + // No need for exclusive access since this is a read only register + tim.$isr.read().$cptX().bit() + } })+ }; } impl_capture! { - HRTIM_TIMA: Ch1, cpt1ar, cpt1acr, cpt1x, - HRTIM_TIMA: Ch2, cpt2ar, cpt2acr, cpt2x, + HRTIM_TIMA: Ch1, cpt1ar, cpt1acr, cpt1x, timadier, timaicr, timaisr, cpt1ie, cpt1c, cpt1, + HRTIM_TIMA: Ch2, cpt2ar, cpt2acr, cpt2x, timadier, timaicr, timaisr, cpt2ie, cpt2c, cpt2, - HRTIM_TIMB: Ch1, cpt1br, cpt1bcr, cpt1x, - HRTIM_TIMB: Ch2, cpt2br, cpt2bcr, cpt2x, + HRTIM_TIMB: Ch1, cpt1br, cpt1bcr, cpt1x, timbdier, timbicr, timbisr, cpt1ie, cpt1c, cpt1, + HRTIM_TIMB: Ch2, cpt2br, cpt2bcr, cpt2x, timbdier, timbicr, timbisr, cpt2ie, cpt2c, cpt2, - HRTIM_TIMC: Ch1, cpt1cr, cpt1ccr, cpt1x, - HRTIM_TIMC: Ch2, cpt2cr, cpt2ccr, cpt2x, + HRTIM_TIMC: Ch1, cpt1cr, cpt1ccr, cpt1x, timcdier, timcicr, timcisr, cpt1ie, cpt1c, cpt1, + HRTIM_TIMC: Ch2, cpt2cr, cpt2ccr, cpt2x, timcdier, timcicr, timcisr, cpt2ie, cpt2c, cpt2, - HRTIM_TIMD: Ch1, cpt1dr, cpt1dcr, cpt1x, - HRTIM_TIMD: Ch2, cpt2dr, cpt2dcr, cpt2x, + HRTIM_TIMD: Ch1, cpt1dr, cpt1dcr, cpt1x, timddier, timdicr, timdisr, cpt1ie, cpt1c, cpt1, + HRTIM_TIMD: Ch2, cpt2dr, cpt2dcr, cpt2x, timddier, timdicr, timdisr, cpt2ie, cpt2c, cpt2, - HRTIM_TIME: Ch1, cpt1er, cpt1ecr, cpt1x, - HRTIM_TIME: Ch2, cpt2er, cpt2ecr, cpt2x, + HRTIM_TIME: Ch1, cpt1er, cpt1ecr, cpt1x, timedier, timeicr, timeisr, cpt1ie, cpt1c, cpt1, + HRTIM_TIME: Ch2, cpt2er, cpt2ecr, cpt2x, timedier, timeicr, timeisr, cpt2ie, cpt2c, cpt2, - HRTIM_TIMF: Ch1, cpt1fr, cpt1fcr, cpt1x, - HRTIM_TIMF: Ch2, cpt2fr, cpt2fcr, cpt2x + HRTIM_TIMF: Ch1, cpt1fr, cpt1fcr, cpt1x, timfdier, timficr, timfisr, cpt1ie, cpt1c, cpt1, + HRTIM_TIMF: Ch2, cpt2fr, cpt2fcr, cpt2x, timfdier, timficr, timfisr, cpt2ie, cpt2c, cpt2 } diff --git a/src/hrtim/control.rs b/src/hrtim/control.rs index 9dc694ea..bcb1414b 100644 --- a/src/hrtim/control.rs +++ b/src/hrtim/control.rs @@ -247,14 +247,14 @@ macro_rules! impl_adc1234_trigger { } } - $(impl Into for &$t { - fn into(self) -> crate::adc::config::ExternalTrigger12 { + $(impl From<&$t> for crate::adc::config::ExternalTrigger12 { + fn from(_val: &$t) -> Self { crate::adc::config::ExternalTrigger12::$variant12 } })* - impl Into for &$t { - fn into(self) -> crate::adc::config::ExternalTrigger345 { + impl From<&$t> for crate::adc::config::ExternalTrigger345 { + fn from(_val: &$t) -> Self { crate::adc::config::ExternalTrigger345::$variant345 } } @@ -276,14 +276,14 @@ macro_rules! impl_adc5678910_trigger { } } - impl Into for &$t { - fn into(self) -> crate::adc::config::ExternalTrigger12 { + impl From<&$t> for crate::adc::config::ExternalTrigger12 { + fn from(_val: &$t) -> Self { crate::adc::config::ExternalTrigger12::$variant12 } } - impl Into for &$t { - fn into(self) -> crate::adc::config::ExternalTrigger345 { + impl From<&$t> for crate::adc::config::ExternalTrigger345 { + fn from(_val: &$t) -> Self { crate::adc::config::ExternalTrigger345::$variant345 } } diff --git a/src/hrtim/output.rs b/src/hrtim/output.rs index 997ce4c7..ef16f23c 100644 --- a/src/hrtim/output.rs +++ b/src/hrtim/output.rs @@ -1,5 +1,5 @@ use crate::stm32::{ - HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF, + HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF, }; use core::marker::PhantomData; @@ -179,7 +179,7 @@ pins! { HRTIM_TIMF: CH1: PC6>, CH2: PC7> } -impl Pins for () { +impl Pins for () { type Channel = (); } From ae1a3719a884971e617e770d3ca62d27406cd17b Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 22 Jan 2024 11:31:42 +0100 Subject: [PATCH 60/88] HRTIM: Capture example --- examples/hrtim/capture.rs | 103 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 examples/hrtim/capture.rs diff --git a/examples/hrtim/capture.rs b/examples/hrtim/capture.rs new file mode 100644 index 00000000..59471b94 --- /dev/null +++ b/examples/hrtim/capture.rs @@ -0,0 +1,103 @@ +#![no_std] +#![no_main] + +use cortex_m_rt::entry; + +use defmt_rtt as _; // global logger +use panic_probe as _; + +#[entry] +fn main() -> ! { + use stm32g4xx_hal as hal; + + use defmt::info; + use hal::{ + gpio::{gpioa::PA8, Alternate, GpioExt, AF13}, + hrtim::{ + capture::HrCapture, compare_register::HrCompareRegister, control::HrControltExt, + external_event, external_event::ToExternalEventSource, output::HrOutput, + timer::HrTimer, HrPwmAdvExt, Pscl4, + }, + pwm, + pwr::PwrExt, + rcc::{self, RccExt}, + stm32::Peripherals, + }; + + info!("start"); + + let dp = Peripherals::take().unwrap(); + + // Set system frequency to 16MHz * 15/1/2 = 120MHz + // This would lead to HrTim running at 120MHz * 32 = 3.84... + info!("rcc"); + let pwr = dp.PWR.constrain().freeze(); + let mut rcc = dp.RCC.freeze( + rcc::Config::pll().pll_cfg(rcc::PllConfig { + mux: rcc::PLLSrc::HSI, + n: rcc::PllNMul::MUL_15, + m: rcc::PllMDiv::DIV_1, + r: Some(rcc::PllRDiv::DIV_2), + + ..Default::default() + }), + pwr, + ); + + info!("Setup Gpio"); + let gpioa = dp.GPIOA.split(&mut rcc); + let gpiob = dp.GPIOB.split(&mut rcc); + let pin_a: PA8> = gpioa.pa8.into_alternate(); + + // ...with a prescaler of 4 this gives us a HrTimer with a tick rate of 960MHz + // With max the max period set, this would be 960MHz/2^16 ~= 15kHz... + let prescaler = Pscl4; + + // . . + // . 50% . + // ------ ------ + //out1 | | | | + // | | | | + // -------- ---------- -------- + // . ^ ^ + // . | | + //AD samlp pa0 temp + let period = 0xFFFF; + let (mut hr_control, _flt_inputs, eev_inputs) = + dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); + + let eev_input3 = eev_inputs + .eev_input3 + .bind(gpiob.pb7.into_pull_down_input()) + .edge_or_polarity(external_event::EdgeOrPolarity::Polarity( + pwm::Polarity::ActiveHigh, + )) + .finalize(&mut hr_control); + + let mut hr_control = hr_control.constrain(); + let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp + .HRTIM_TIMA + .pwm_advanced(pin_a, &mut rcc) + .prescaler(prescaler) + .period(period) + .finalize(&mut hr_control); + + out1.enable_rst_event(&cr1); // Set low on compare match with cr1 + out1.enable_set_event(&timer); // Set high at new period + + cr1.set_duty(period / 2); + timer.start(&mut hr_control); + + let capture = timer.capture_ch1(); + capture.enable_interrupt(true, &mut hr_control); + capture.add_event(&eev_input3); + + loop { + if !capture.is_pending() { + continue; + } + capture.clear_interrupt(); + + info!("Capture: {:?}", capture.get()); + } +} From cc84bce0bb7d91e15df95824d655ab980611eefc Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 22 Jan 2024 11:33:09 +0100 Subject: [PATCH 61/88] HRTIM: Create feature for all devices supporting hrtim --- Cargo.toml | 18 ++++++++++++++++-- examples/hrtim/adc-trigger.rs | 8 -------- examples/hrtim/eev-comp.rs | 8 -------- examples/hrtim/eev.rs | 8 -------- examples/hrtim/flt-comp.rs | 8 -------- examples/hrtim/flt.rs | 8 -------- examples/hrtim/hrtim.rs | 8 -------- examples/hrtim/master.rs | 11 ----------- examples/hrtim/simple.rs | 8 -------- src/lib.rs | 3 +-- 10 files changed, 17 insertions(+), 71 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2bc57b8f..37b9cb36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -86,11 +86,12 @@ stm32g431 = ["stm32g4/stm32g431"] stm32g441 = ["stm32g4/stm32g441"] stm32g471 = ["stm32g4/stm32g471"] stm32g473 = ["stm32g4/stm32g473"] -stm32g474 = ["stm32g4/stm32g474"] +stm32g474 = ["stm32g4/stm32g474", "hrtim"] stm32g483 = ["stm32g4/stm32g483"] -stm32g484 = ["stm32g4/stm32g484"] +stm32g484 = ["stm32g4/stm32g484", "hrtim"] stm32g491 = ["stm32g4/stm32g491"] stm32g4a1 = ["stm32g4/stm32g4a1"] +hrtim = [] log-itm = ["cortex-m-log/itm"] log-rtt = [] log-semihost = ["cortex-m-log/semihosting"] @@ -123,32 +124,45 @@ required-features = ["cordic"] [[example]] name = "hrtim-adc-trigger" +required-features = ["hrtim"] path = "examples/hrtim/adc-trigger.rs" +[[example]] +name = "hrtim-capture" +required-features = ["hrtim"] +path = "examples/hrtim/capture.rs" + [[example]] name = "hrtim-eev-comp" +required-features = ["hrtim"] path = "examples/hrtim/eev-comp.rs" [[example]] name = "hrtim-eev" +required-features = ["hrtim"] path = "examples/hrtim/eev.rs" [[example]] name = "hrtim-flt-comp" +required-features = ["hrtim"] path = "examples/hrtim/flt-comp.rs" [[example]] name = "hrtim-flt" +required-features = ["hrtim"] path = "examples/hrtim/flt.rs" [[example]] name = "hrtim" +required-features = ["hrtim"] path = "examples/hrtim/hrtim.rs" [[example]] name = "hrtim-master" +required-features = ["hrtim"] path = "examples/hrtim/master.rs" [[example]] name = "hrtim-simple" +required-features = ["hrtim"] path = "examples/hrtim/simple.rs" diff --git a/examples/hrtim/adc-trigger.rs b/examples/hrtim/adc-trigger.rs index 314813a9..3a76580b 100644 --- a/examples/hrtim/adc-trigger.rs +++ b/examples/hrtim/adc-trigger.rs @@ -6,14 +6,6 @@ use cortex_m_rt::entry; use defmt_rtt as _; // global logger use panic_probe as _; -#[cfg(not(any(feature = "stm32g474", feature = "stm32g484")))] -#[entry] -fn main() -> ! { - #[allow(clippy::empty_loop)] - loop {} -} - -#[cfg(any(feature = "stm32g474", feature = "stm32g484"))] #[entry] fn main() -> ! { use hal::adc; diff --git a/examples/hrtim/eev-comp.rs b/examples/hrtim/eev-comp.rs index e2b51d17..b2b5b95b 100644 --- a/examples/hrtim/eev-comp.rs +++ b/examples/hrtim/eev-comp.rs @@ -7,14 +7,6 @@ use cortex_m_rt::entry; use defmt_rtt as _; // global logger use panic_probe as _; -#[cfg(not(any(feature = "stm32g474", feature = "stm32g484")))] -#[entry] -fn main() -> ! { - #[allow(clippy::empty_loop)] - loop {} -} - -#[cfg(any(feature = "stm32g474", feature = "stm32g484"))] #[entry] fn main() -> ! { use hal::comparator; diff --git a/examples/hrtim/eev.rs b/examples/hrtim/eev.rs index 1ed8f32e..50e218c7 100644 --- a/examples/hrtim/eev.rs +++ b/examples/hrtim/eev.rs @@ -9,14 +9,6 @@ use cortex_m_rt::entry; use defmt_rtt as _; // global logger use panic_probe as _; -#[cfg(not(any(feature = "stm32g474", feature = "stm32g484")))] -#[entry] -fn main() -> ! { - #[allow(clippy::empty_loop)] - loop {} -} - -#[cfg(any(feature = "stm32g474", feature = "stm32g484"))] #[entry] fn main() -> ! { use hal::gpio::gpioa::PA8; diff --git a/examples/hrtim/flt-comp.rs b/examples/hrtim/flt-comp.rs index 15fdf744..5549ea6c 100644 --- a/examples/hrtim/flt-comp.rs +++ b/examples/hrtim/flt-comp.rs @@ -8,14 +8,6 @@ use cortex_m_rt::entry; use defmt_rtt as _; // global logger use panic_probe as _; -#[cfg(not(any(feature = "stm32g474", feature = "stm32g484")))] -#[entry] -fn main() -> ! { - #[allow(clippy::empty_loop)] - loop {} -} - -#[cfg(any(feature = "stm32g474", feature = "stm32g484"))] #[entry] fn main() -> ! { use hal::comparator::{ComparatorExt, ComparatorSplit, Config, Hysteresis}; diff --git a/examples/hrtim/flt.rs b/examples/hrtim/flt.rs index a43a8ccc..2bc20d04 100644 --- a/examples/hrtim/flt.rs +++ b/examples/hrtim/flt.rs @@ -8,14 +8,6 @@ use cortex_m_rt::entry; use defmt_rtt as _; // global logger use panic_probe as _; -#[cfg(not(any(feature = "stm32g474", feature = "stm32g484")))] -#[entry] -fn main() -> ! { - #[allow(clippy::empty_loop)] - loop {} -} - -#[cfg(any(feature = "stm32g474", feature = "stm32g484"))] #[entry] fn main() -> ! { use hal::gpio::gpioa::PA8; diff --git a/examples/hrtim/hrtim.rs b/examples/hrtim/hrtim.rs index 08b972a1..2dbec016 100644 --- a/examples/hrtim/hrtim.rs +++ b/examples/hrtim/hrtim.rs @@ -7,14 +7,6 @@ use cortex_m_rt::entry; use defmt_rtt as _; // global logger use panic_probe as _; -#[cfg(not(any(feature = "stm32g474", feature = "stm32g484")))] -#[entry] -fn main() -> ! { - #[allow(clippy::empty_loop)] - loop {} -} - -#[cfg(any(feature = "stm32g474", feature = "stm32g484"))] #[entry] fn main() -> ! { use fugit::ExtU32; diff --git a/examples/hrtim/master.rs b/examples/hrtim/master.rs index 4f085c3a..521c7ef8 100644 --- a/examples/hrtim/master.rs +++ b/examples/hrtim/master.rs @@ -4,17 +4,6 @@ use cortex_m_rt::entry; -#[cfg(not(any(feature = "stm32g474", feature = "stm32g484")))] -#[entry] -fn main() -> ! { - #[allow(clippy::empty_loop)] - loop {} -} - -use defmt_rtt as _; // global logger -use panic_probe as _; - -#[cfg(any(feature = "stm32g474", feature = "stm32g484"))] #[entry] fn main() -> ! { use fugit::ExtU32; diff --git a/examples/hrtim/simple.rs b/examples/hrtim/simple.rs index 79f1b621..dd7180a5 100644 --- a/examples/hrtim/simple.rs +++ b/examples/hrtim/simple.rs @@ -9,14 +9,6 @@ use cortex_m_rt::entry; use defmt_rtt as _; // global logger use panic_probe as _; -#[cfg(not(any(feature = "stm32g474", feature = "stm32g484")))] -#[entry] -fn main() -> ! { - #[allow(clippy::empty_loop)] - loop {} -} - -#[cfg(any(feature = "stm32g474", feature = "stm32g484"))] #[entry] fn main() -> ! { use hal::gpio::gpioa::PA8; diff --git a/src/lib.rs b/src/lib.rs index a18b3c38..3e2382e3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,7 +12,6 @@ feature = "stm32g491", feature = "stm32g4a1" )))] - compile_error!( "This crate requires one of the following features enabled: stm32g431 @@ -84,7 +83,7 @@ pub mod exti; pub mod flash; pub mod gpio; -#[cfg(any(feature = "stm32g474", feature = "stm32g484"))] +#[cfg(feature = "hrtim")] pub mod hrtim; pub mod i2c; pub mod opamp; From 00fd46c78de75e607462f8a63349e05a3ddeea3d Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 22 Jan 2024 15:24:19 +0100 Subject: [PATCH 62/88] HRTIM: Some fixes for capture example --- examples/hrtim/capture.rs | 42 ++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/examples/hrtim/capture.rs b/examples/hrtim/capture.rs index 59471b94..095ca887 100644 --- a/examples/hrtim/capture.rs +++ b/examples/hrtim/capture.rs @@ -16,7 +16,7 @@ fn main() -> ! { hrtim::{ capture::HrCapture, compare_register::HrCompareRegister, control::HrControltExt, external_event, external_event::ToExternalEventSource, output::HrOutput, - timer::HrTimer, HrPwmAdvExt, Pscl4, + timer::HrTimer, HrPwmAdvExt, Pscl128, }, pwm, pwr::PwrExt, @@ -47,11 +47,13 @@ fn main() -> ! { info!("Setup Gpio"); let gpioa = dp.GPIOA.split(&mut rcc); let gpiob = dp.GPIOB.split(&mut rcc); + + // PA8 (D7 on Nucleo G474RE) let pin_a: PA8> = gpioa.pa8.into_alternate(); - // ...with a prescaler of 4 this gives us a HrTimer with a tick rate of 960MHz - // With max the max period set, this would be 960MHz/2^16 ~= 15kHz... - let prescaler = Pscl4; + // ...with a prescaler of 128 this gives us a HrTimer with a tick rate of 30MHz + // With max the max period set, this would be 30MHz/2^16 ~= 458Hz... + let prescaler = Pscl128; // . . // . 50% . @@ -59,18 +61,16 @@ fn main() -> ! { //out1 | | | | // | | | | // -------- ---------- -------- - // . ^ ^ - // . | | - //AD samlp pa0 temp let period = 0xFFFF; let (mut hr_control, _flt_inputs, eev_inputs) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); - let eev_input3 = eev_inputs - .eev_input3 - .bind(gpiob.pb7.into_pull_down_input()) - .edge_or_polarity(external_event::EdgeOrPolarity::Polarity( - pwm::Polarity::ActiveHigh, + // PB5 (D4 on Nucleo G474RE) + let eev_input6 = eev_inputs + .eev_input6 + .bind(gpiob.pb5.into_pull_down_input()) + .edge_or_polarity(external_event::EdgeOrPolarity::Edge( + external_event::Edge::Falling, )) .finalize(&mut hr_control); @@ -87,17 +87,23 @@ fn main() -> ! { cr1.set_duty(period / 2); timer.start(&mut hr_control); + out1.enable(); let capture = timer.capture_ch1(); capture.enable_interrupt(true, &mut hr_control); - capture.add_event(&eev_input3); + capture.add_event(&eev_input6); + let mut old_duty = 0; loop { - if !capture.is_pending() { - continue; + for duty in (u32::from(period) / 10)..(9 * u32::from(period) / 10) { + if !capture.is_pending() { + continue; + } + let value = capture.get_signed(); + cr1.set_duty(duty as u16); + capture.clear_interrupt(); + info!("Capture: {:?}, duty: {}, diff: {}", value, old_duty, value - old_duty as i32); + old_duty = duty; } - capture.clear_interrupt(); - - info!("Capture: {:?}", capture.get()); } } From b2da099c3bdfc7ad1b22f71b280a9b335461c28c Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 22 Jan 2024 15:55:39 +0100 Subject: [PATCH 63/88] HRTIM: Fix warning in capture example --- examples/hrtim/capture.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/hrtim/capture.rs b/examples/hrtim/capture.rs index 095ca887..f6e6a010 100644 --- a/examples/hrtim/capture.rs +++ b/examples/hrtim/capture.rs @@ -18,7 +18,6 @@ fn main() -> ! { external_event, external_event::ToExternalEventSource, output::HrOutput, timer::HrTimer, HrPwmAdvExt, Pscl128, }, - pwm, pwr::PwrExt, rcc::{self, RccExt}, stm32::Peripherals, From 88545c158568d1bf7ed99c8b2606d79eec71cc17 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 22 Jan 2024 16:54:50 +0100 Subject: [PATCH 64/88] HRTIM: Add forgotten traitification impls --- src/hrtim/external_event.rs | 12 ++++++++++++ src/hrtim/output.rs | 4 +--- src/hrtim/timer.rs | 10 ++++++++-- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/hrtim/external_event.rs b/src/hrtim/external_event.rs index d658e0f6..3c5e0c38 100644 --- a/src/hrtim/external_event.rs +++ b/src/hrtim/external_event.rs @@ -298,6 +298,13 @@ macro_rules! impl_eev1_5_to_es { ExternalEventSource { _x: PhantomData } } } + + /// EEV$1 event + impl super::event::EventSource + for ExternalEventSource<$N, IS_FAST> + { + const BITS: u32 = 1 << ($N + 20); // EEV1 is at bit 21 + } }; } @@ -333,6 +340,11 @@ macro_rules! impl_eev6_10_to_es { ExternalEventSource { _x: PhantomData } } } + + /// EEV$1 event + impl super::event::EventSource for ExternalEventSource<$N, false> { + const BITS: u32 = 1 << ($N + 20); // EEV1 is at bit 21 + } }; } diff --git a/src/hrtim/output.rs b/src/hrtim/output.rs index ef16f23c..31d28914 100644 --- a/src/hrtim/output.rs +++ b/src/hrtim/output.rs @@ -1,6 +1,4 @@ -use crate::stm32::{ - HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF, -}; +use crate::stm32::{HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF}; use core::marker::PhantomData; use super::event::EventSource; diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs index 142b92de..e981b8bf 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -154,14 +154,14 @@ macro_rules! hrtim_timer { /// * `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 - pub fn enable_reset_event>(&mut self, _event: E) { + pub 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 - pub fn disable_reset_event>(&mut self, _event: E) { + pub 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)); } @@ -230,6 +230,12 @@ hrtim_timer_adc_trigger! { HRTIM_TIMF: [(Adc13: [(PER: 1 << 24), (RST: 1 << 28)]), (Adc24: [(PER: 1 << 24), ]), (Adc579: [(PER: 30), (RST: 31)]), (Adc6810: [(PER: 31), ])] } +/// Master Timer Period event impl super::event::TimerResetEventSource for HrTim { const BITS: u32 = 1 << 4; // MSTPER } + +/// Master Timer Period event +impl super::event::EventSource for HrTim { + const BITS: u32 = 1 << 7; // MSTPER +} From cdea5a539e1f08f6c1cc56b8ecbc0173f10af3ed Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 22 Jan 2024 16:55:13 +0100 Subject: [PATCH 65/88] HRTIM: Update examples --- examples/hrtim/adc-trigger.rs | 8 +++++++- examples/hrtim/capture.rs | 16 ++++++++++++++-- examples/hrtim/eev-comp.rs | 17 ++++++++++++----- examples/hrtim/eev.rs | 17 +++++++++++------ examples/hrtim/flt-comp.rs | 21 ++++++++++++++------- examples/hrtim/flt.rs | 21 ++++++++++++++------- examples/hrtim/hrtim.rs | 12 ++++++++++-- examples/hrtim/master.rs | 31 +++++++++++++++++++------------ examples/hrtim/simple.rs | 18 +++++++++++------- 9 files changed, 112 insertions(+), 49 deletions(-) diff --git a/examples/hrtim/adc-trigger.rs b/examples/hrtim/adc-trigger.rs index 3a76580b..c80f17f9 100644 --- a/examples/hrtim/adc-trigger.rs +++ b/examples/hrtim/adc-trigger.rs @@ -1,17 +1,23 @@ #![no_std] #![no_main] +/// Example showcasing the use of the HRTIM peripheral to trigger the ADC at various points of the switch cycle off HRTIM_TIMA + +#[path = "../utils/mod.rs"] +mod utils; + use cortex_m_rt::entry; use defmt_rtt as _; // global logger use panic_probe as _; +use utils::logger::info; + #[entry] fn main() -> ! { use hal::adc; use stm32g4xx_hal as hal; - use defmt::info; use hal::{ adc::{ config::{Continuous, Dma as AdcDma, SampleTime, Sequence}, diff --git a/examples/hrtim/capture.rs b/examples/hrtim/capture.rs index f6e6a010..c6ceb8c6 100644 --- a/examples/hrtim/capture.rs +++ b/examples/hrtim/capture.rs @@ -1,16 +1,22 @@ #![no_std] #![no_main] +/// Example showcasing the use of the HRTIM peripheral's capture function to detect phase shift between a digital event and the output of HRTIM_TIMA + +#[path = "../utils/mod.rs"] +mod utils; + use cortex_m_rt::entry; use defmt_rtt as _; // global logger use panic_probe as _; +use utils::logger::info; + #[entry] fn main() -> ! { use stm32g4xx_hal as hal; - use defmt::info; use hal::{ gpio::{gpioa::PA8, Alternate, GpioExt, AF13}, hrtim::{ @@ -22,6 +28,7 @@ fn main() -> ! { rcc::{self, RccExt}, stm32::Peripherals, }; + use info; info!("start"); @@ -101,7 +108,12 @@ fn main() -> ! { let value = capture.get_signed(); cr1.set_duty(duty as u16); capture.clear_interrupt(); - info!("Capture: {:?}, duty: {}, diff: {}", value, old_duty, value - old_duty as i32); + info!( + "Capture: {:?}, duty: {}, diff: {}", + value, + old_duty, + value - old_duty as i32 + ); old_duty = duty; } } diff --git a/examples/hrtim/eev-comp.rs b/examples/hrtim/eev-comp.rs index b2b5b95b..2c1e802f 100644 --- a/examples/hrtim/eev-comp.rs +++ b/examples/hrtim/eev-comp.rs @@ -1,12 +1,19 @@ -//This example puts the timer in PWM mode using the specified pin with a frequency of 100Hz and a duty cycle of 50%. -#![no_main] #![no_std] +#![no_main] + +/// Example showcasing the use of the HRTIM peripheral together with a comparator to implement a cycle by cycle current limit. +/// Once the comparator input exceeds the reference set by the DAC, the output is set low thus limiting the pulse width and in turn the current. + +#[path = "../utils/mod.rs"] +mod utils; use cortex_m_rt::entry; use defmt_rtt as _; // global logger use panic_probe as _; +use utils::logger::info; + #[entry] fn main() -> ! { use hal::comparator; @@ -116,17 +123,17 @@ fn main() -> ! { .finalize(&mut hr_control); out1.enable_rst_event(&cr1); // Set low on compare match with cr1 - out1.enable_rst_event(eev_input4); + out1.enable_rst_event(&eev_input4); out1.enable_set_event(&timer); // Set high at new period cr1.set_duty(timer.get_period() / 3); out1.enable(); timer.start(&mut hr_control); - defmt::info!("Started"); + info!("Started"); loop { - defmt::info!( + info!( "Comp: {}, pending: {}", comp1.output(), comp1.is_pending(&exti) diff --git a/examples/hrtim/eev.rs b/examples/hrtim/eev.rs index 50e218c7..846fd1ac 100644 --- a/examples/hrtim/eev.rs +++ b/examples/hrtim/eev.rs @@ -1,14 +1,19 @@ -//This example puts the timer in PWM mode using the specified pin with a frequency of 100Hz and a duty cycle of 50%. -#![no_main] #![no_std] +#![no_main] -use cortex_m_rt::entry; +/// Example showcasing the use of the HRTIM peripheral together with a digital input to implement a cycle by cycle current limit. +/// Once the digital input goes high, the output is set low thus limiting the pulse width and in turn the current. -//mod utils; +#[path = "../utils/mod.rs"] +mod utils; + +use cortex_m_rt::entry; use defmt_rtt as _; // global logger use panic_probe as _; +use utils::logger::info; + #[entry] fn main() -> ! { use hal::gpio::gpioa::PA8; @@ -90,14 +95,14 @@ fn main() -> ! { .finalize(&mut hr_control); out1.enable_rst_event(&cr1); // Set low on compare match with cr1 - out1.enable_rst_event(eev_input3); + out1.enable_rst_event(&eev_input3); out1.enable_set_event(&timer); // Set high at new period cr1.set_duty(timer.get_period() / 3); out1.enable(); timer.start(&mut hr_control); - defmt::info!("Started"); + info!("Started"); loop { cortex_m::asm::nop() diff --git a/examples/hrtim/flt-comp.rs b/examples/hrtim/flt-comp.rs index 5549ea6c..d9923515 100644 --- a/examples/hrtim/flt-comp.rs +++ b/examples/hrtim/flt-comp.rs @@ -1,13 +1,19 @@ -//This example puts the timer in PWM mode using the specified pin with a frequency of 100Hz and a duty cycle of 50%. -#![no_main] #![no_std] +#![no_main] + +/// Example showcasing the use of the HRTIM peripheral together with a comparator to implement a current fault. +/// Once the comparator input exceeds the reference set by the DAC, the output is forced low and put into a fault state. + +#[path = "../utils/mod.rs"] +mod utils; use cortex_m_rt::entry; -//mod utils; use defmt_rtt as _; // global logger use panic_probe as _; +use utils::logger::info; + #[entry] fn main() -> ! { use hal::comparator::{ComparatorExt, ComparatorSplit, Config, Hysteresis}; @@ -110,7 +116,7 @@ fn main() -> ! { // ----------------------------------------- -------------------------- // . . . * . . // . . . * . . - let (timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp + let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp .HRTIM_TIMA .pwm_advanced(pin_a, &mut rcc) .prescaler(prescaler) @@ -125,13 +131,14 @@ fn main() -> ! { cr1.set_duty(timer.get_period() / 3); //unsafe {((HRTIM_COMMON::ptr() as *mut u8).offset(0x14) as *mut u32).write_volatile(1); } out1.enable(); + timer.start(&mut hr_control); - defmt::info!("Started"); + info!("Started"); loop { for _ in 0..5 { //delay.delay(500_u32.millis()); - defmt::info!( + info!( "State: {}, comp: {}, is_fault_active: {}, pc1: {}", out1.get_state(), comp3.output(), @@ -142,7 +149,7 @@ fn main() -> ! { if hr_control.fault_5.is_fault_active() { hr_control.fault_5.clear_fault(); // Clear fault every 5s out1.enable(); - defmt::info!("failt cleared, and output reenabled"); + info!("failt cleared, and output reenabled"); } } } diff --git a/examples/hrtim/flt.rs b/examples/hrtim/flt.rs index 2bc20d04..d95ca8b4 100644 --- a/examples/hrtim/flt.rs +++ b/examples/hrtim/flt.rs @@ -1,13 +1,19 @@ -//This example puts the timer in PWM mode using the specified pin with a frequency of 100Hz and a duty cycle of 50%. -#![no_main] #![no_std] +#![no_main] + +/// Example showcasing the use of the HRTIM peripheral together with a comparator to implement a current fault. +/// Once the digital input goes high, the output is forced low and put into a fault state. + +#[path = "../utils/mod.rs"] +mod utils; use cortex_m_rt::entry; -//mod utils; use defmt_rtt as _; // global logger use panic_probe as _; +use utils::logger::info; + #[entry] fn main() -> ! { use hal::gpio::gpioa::PA8; @@ -76,7 +82,7 @@ fn main() -> ! { // ----------------------------------------- -------------------------- // . . . * . . // . . . * . . - let (timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp + let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp .HRTIM_TIMA .pwm_advanced(pin_a, &mut rcc) .prescaler(prescaler) @@ -99,18 +105,19 @@ fn main() -> ! { cr1.set_duty(timer.get_period() / 3); //unsafe {((HRTIM_COMMON::ptr() as *mut u8).offset(0x14) as *mut u32).write_volatile(1); } out1.enable(); + timer.start(&mut hr_control); - defmt::info!("Started"); + info!("Started"); loop { for _ in 0..5 { delay.delay(500_u32.millis()); - defmt::info!("State: {}", out1.get_state()); + info!("State: {}", out1.get_state()); } if hr_control.fault_3.is_fault_active() { hr_control.fault_3.clear_fault(); // Clear fault every 5s out1.enable(); - defmt::info!("failt cleared, and output reenabled"); + info!("failt cleared, and output reenabled"); } } } diff --git a/examples/hrtim/hrtim.rs b/examples/hrtim/hrtim.rs index 2dbec016..c81555da 100644 --- a/examples/hrtim/hrtim.rs +++ b/examples/hrtim/hrtim.rs @@ -1,12 +1,18 @@ -//This example puts the timer in PWM mode using the specified pin with a frequency of 100Hz and a duty cycle of 50%. -#![no_main] #![no_std] +#![no_main] + +/// Add description + +#[path = "../utils/mod.rs"] +mod utils; use cortex_m_rt::entry; use defmt_rtt as _; // global logger use panic_probe as _; +use utils::logger::info; + #[entry] fn main() -> ! { use fugit::ExtU32; @@ -27,6 +33,8 @@ fn main() -> ! { use stm32g4xx_hal as hal; extern crate cortex_m_rt as rt; + info!("Initializing..."); + let dp = stm32::Peripherals::take().expect("cannot take peripherals"); let cp = stm32::CorePeripherals::take().expect("cannot take core"); // Set system frequency to 16MHz * 15/1/2 = 120MHz diff --git a/examples/hrtim/master.rs b/examples/hrtim/master.rs index 521c7ef8..fca32d9e 100644 --- a/examples/hrtim/master.rs +++ b/examples/hrtim/master.rs @@ -1,9 +1,18 @@ -//This example puts the timer in PWM mode using the specified pin with a frequency of 100Hz and a duty cycle of 50%. -#![no_main] #![no_std] +#![no_main] + +/// Add description + +#[path = "../utils/mod.rs"] +mod utils; use cortex_m_rt::entry; +use defmt_rtt as _; // global logger +use panic_probe as _; + +use utils::logger::info; + #[entry] fn main() -> ! { use fugit::ExtU32; @@ -16,9 +25,7 @@ fn main() -> ! { use hal::hrtim::output::HrOutput; use hal::hrtim::timer::HrTimer; use hal::hrtim::HrPwmAdvExt; - use hal::hrtim::{ - event::TimerAResetEventSource, HrTimerMode, MasterPreloadSource, PreloadSource, Pscl4, - }; + use hal::hrtim::{HrTimerMode, MasterPreloadSource, PreloadSource, Pscl4}; use hal::prelude::*; use hal::pwr::PwrExt; use hal::rcc; @@ -89,7 +96,7 @@ fn main() -> ! { .finalize(&mut hr_control); // Run in sync with master timer - timer.enable_reset_event(TimerAResetEventSource::MasterPeriod); + timer.enable_reset_event(&mtimer); out1.enable_rst_event(&mcr1); // Set low on compare match with cr1 out2.enable_rst_event(&mcr1); @@ -101,13 +108,13 @@ fn main() -> ! { out2.enable(); let tima = unsafe { &*stm32g4xx_hal::stm32::HRTIM_TIMA::ptr() }; - defmt::info!("set1r: {}", tima.seta1r.read().bits()); - defmt::info!("rst1r: {}", tima.rsta1r.read().bits()); + info!("set1r: {}", tima.seta1r.read().bits()); + info!("rst1r: {}", tima.rsta1r.read().bits()); - defmt::info!("set2r: {}", tima.seta2r.read().bits()); - defmt::info!("rst2r: {}", tima.rsta2r.read().bits()); + info!("set2r: {}", tima.seta2r.read().bits()); + info!("rst2r: {}", tima.rsta2r.read().bits()); - defmt::info!("Running"); + info!("Running"); loop { // Step frequency from 18kHz to about 180kHz(half of that when only looking at one pin) @@ -119,7 +126,7 @@ fn main() -> ! { mtimer.set_period(new_period); timer.set_period(new_period - 1000); - defmt::info!( + info!( "period: {}, duty: {}, get_duty: {}, get_period: {}", new_period, new_period / 3, diff --git a/examples/hrtim/simple.rs b/examples/hrtim/simple.rs index dd7180a5..e493adac 100644 --- a/examples/hrtim/simple.rs +++ b/examples/hrtim/simple.rs @@ -1,14 +1,18 @@ -//This example puts the timer in PWM mode using the specified pin with a frequency of 100Hz and a duty cycle of 50%. -#![no_main] #![no_std] +#![no_main] -use cortex_m_rt::entry; +/// Example showcasing the use of the HRTIM peripheral generating two 20kHz pwm signals. One with 33% duty and the other with 50% + +#[path = "../utils/mod.rs"] +mod utils; -//mod utils; +use cortex_m_rt::entry; use defmt_rtt as _; // global logger use panic_probe as _; +use utils::logger::info; + #[entry] fn main() -> ! { use hal::gpio::gpioa::PA8; @@ -23,10 +27,10 @@ fn main() -> ! { use hal::time::RateExtU32; use stm32g4xx_hal as hal; extern crate cortex_m_rt as rt; - let dp = stm32::Peripherals::take().expect("cannot take peripherals"); - defmt::info!("Initializing..."); + info!("Initializing..."); + let dp = stm32::Peripherals::take().expect("cannot take peripherals"); // Set system frequency to 16MHz * 75/4/2 = 150MHz // This would lead to HrTim running at 150MHz * 32 = 4.8GHz... let pwr = dp.PWR.constrain().freeze(); @@ -74,7 +78,7 @@ fn main() -> ! { p1.enable(); p2.enable(); - defmt::info!("Running"); + info!("Running"); loop { cortex_m::asm::nop() From c9408ac951f0b8a8d7f51c110f451912242e5619 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 23 Jan 2024 17:02:13 +0100 Subject: [PATCH 66/88] HRTIM: Capture cleanup --- examples/hrtim/capture.rs | 6 ++++-- src/hrtim/capture.rs | 27 +++++++++++++++++---------- src/hrtim/timer.rs | 18 ++++++++++-------- 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/examples/hrtim/capture.rs b/examples/hrtim/capture.rs index c6ceb8c6..a90c84f5 100644 --- a/examples/hrtim/capture.rs +++ b/examples/hrtim/capture.rs @@ -57,6 +57,9 @@ fn main() -> ! { // PA8 (D7 on Nucleo G474RE) let pin_a: PA8> = gpioa.pa8.into_alternate(); + // PB5 (D4 on Nucleo G474RE) + let input = gpiob.pb5.into_pull_down_input(); + // ...with a prescaler of 128 this gives us a HrTimer with a tick rate of 30MHz // With max the max period set, this would be 30MHz/2^16 ~= 458Hz... let prescaler = Pscl128; @@ -71,10 +74,9 @@ fn main() -> ! { let (mut hr_control, _flt_inputs, eev_inputs) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); - // PB5 (D4 on Nucleo G474RE) let eev_input6 = eev_inputs .eev_input6 - .bind(gpiob.pb5.into_pull_down_input()) + .bind(input) .edge_or_polarity(external_event::EdgeOrPolarity::Edge( external_event::Edge::Falling, )) diff --git a/src/hrtim/capture.rs b/src/hrtim/capture.rs index e0019022..b93e7642 100644 --- a/src/hrtim/capture.rs +++ b/src/hrtim/capture.rs @@ -31,19 +31,26 @@ pub trait HrCapture { /// Get number of ticks relative to beginning of upcounting /// /// where captures during down counting count as negative (before the upcount) + /// + /// ```` + /// Counter + /// ---------------------------------- <--- period + /// \ ^ / + /// \ | / + /// \ | / + /// \ | / + /// Down count \ | / Up count + /// \|/ + /// <-------------- 0 --------------> t + /// Negative result | positive result + /// ```` fn get_signed(&self) -> i32 { let (value, dir) = self.get(); - let dir_bit = dir as i32; - dir_bit << 31 | i32::from(value) - } - /// Get number of ticks relative to beginning of upcounting - /// - /// where captures during down counting count as larger (after upcount) - fn get_unsigned(&self) -> u32 { - let (value, dir) = self.get(); - let dir_bit = dir as u32; - dir_bit << 16 | u32::from(value) + match dir { + CountingDirection::Up => i32::from(value), + CountingDirection::Down => -i32::from(value), + } } fn clear_interrupt(&mut self); diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs index e981b8bf..b7989a06 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -127,14 +127,6 @@ macro_rules! hrtim_timer { tim.$dier.modify(|_r, w| w.$repie().bit(enable)); } - - pub fn capture_ch1(&mut self) -> &mut HrCapt<$TIMX, PSCL, capture::Ch1> { - &mut self.capture_ch1 - } - - pub fn capture_ch2(&mut self) -> &mut HrCapt<$TIMX, PSCL, capture::Ch2> { - &mut self.capture_ch2 - } } $(// Only for Non-Master timers @@ -230,6 +222,16 @@ hrtim_timer_adc_trigger! { HRTIM_TIMF: [(Adc13: [(PER: 1 << 24), (RST: 1 << 28)]), (Adc24: [(PER: 1 << 24), ]), (Adc579: [(PER: 30), (RST: 31)]), (Adc6810: [(PER: 31), ])] } +impl HrTim { + pub fn capture_ch1(&mut self) -> &mut HrCapt { + &mut self.capture_ch1 + } + + pub fn capture_ch2(&mut self) -> &mut HrCapt { + &mut self.capture_ch2 + } +} + /// Master Timer Period event impl super::event::TimerResetEventSource for HrTim { const BITS: u32 = 1 << 4; // MSTPER From 5527508ba07552deb663c88ebc9c26f68afe7857 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 24 Jan 2024 15:56:04 +0100 Subject: [PATCH 67/88] HRTIM: Avoid unneeded type parameters on HrTimer trait --- src/hrtim/timer.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs index b7989a06..b09f0c01 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -15,7 +15,10 @@ pub struct HrTim { capture_ch2: HrCapt, } -pub trait HrTimer: Sized { +pub trait HrTimer { + type Timer; + type Prescaler; + /// Get period of timer in number of ticks /// /// This is also the maximum duty usable for `HrCompareRegister::set_duty` @@ -38,10 +41,10 @@ pub trait HrTimer: Sized { fn clear_repetition_interrupt(&mut self); /// Make a handle to this timers reset event to use as adc trigger - fn as_reset_adc_trigger(&self) -> super::adc_trigger::TimerReset; + fn as_reset_adc_trigger(&self) -> super::adc_trigger::TimerReset; /// Make a handle to this timers period event to use as adc trigger - fn as_period_adc_trigger(&self) -> super::adc_trigger::TimerPeriod; + fn as_period_adc_trigger(&self) -> super::adc_trigger::TimerPeriod; } macro_rules! hrtim_timer { @@ -60,7 +63,10 @@ macro_rules! hrtim_timer { $repc:ident, $(($rstXr:ident))*, )+) => {$( - impl HrTimer<$TIMX, PSCL> for HrTim<$TIMX, PSCL> { + impl HrTimer for HrTim<$TIMX, PSCL> { + type Prescaler = PSCL; + type Timer = $TIMX; + fn get_period(&self) -> u16 { let tim = unsafe { &*$TIMX::ptr() }; @@ -99,12 +105,12 @@ macro_rules! hrtim_timer { } /// Make a handle to this timers reset event to use as adc trigger - fn as_reset_adc_trigger(&self) -> super::adc_trigger::TimerReset { + 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 { + fn as_period_adc_trigger(&self) -> super::adc_trigger::TimerPeriod { super::adc_trigger::TimerPeriod(PhantomData) } From 6cd1ff8c33421b64567da80dc934293e8bc700ee Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 24 Jan 2024 16:23:15 +0100 Subject: [PATCH 68/88] HRTIM: Move some inherent methods to traits on HrTim --- src/hrtim/timer.rs | 53 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs index b09f0c01..c6f52369 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -47,6 +47,27 @@ pub trait HrTimer { fn as_period_adc_trigger(&self) -> super::adc_trigger::TimerPeriod; } +pub trait HrSlaveTimer: HrTimer +{ + type CaptureCh1: super::capture::HrCapture; + type CaptureCh2: super::capture::HrCapture; + + /// Start listening to the specified event + fn enable_reset_event>( + &mut self, + _event: &E, + ); + + /// Stop listening to the specified event + fn disable_reset_event>( + &mut self, + _event: &E, + ); + + fn capture_ch1(&mut self) -> &mut Self::CaptureCh1; + fn capture_ch2(&mut self) -> &mut Self::CaptureCh2; +} + macro_rules! hrtim_timer { ($( $TIMX:ident: @@ -135,8 +156,11 @@ macro_rules! hrtim_timer { } } - $(// Only for Non-Master timers - impl HrTim<$TIMX, PSCL> { + $( + impl HrSlaveTimer for HrTim<$TIMX, PSCL> { + type CaptureCh1 = HrCapt; + type CaptureCh2 = HrCapt; + /// Reset this timer every time the specified event occurs /// /// Behaviour depends on `timer_mode`: @@ -152,20 +176,31 @@ macro_rules! hrtim_timer { /// * `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 - pub fn enable_reset_event>(&mut self, _event: &E) { + 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 - pub fn disable_reset_event>(&mut self, _event: &E) { + 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)); } } + + /// 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 + } } + /// Timer Period event impl super::event::EventSource for HrTim<$TIMX, PSCL> { // $rstXr @@ -228,16 +263,6 @@ hrtim_timer_adc_trigger! { HRTIM_TIMF: [(Adc13: [(PER: 1 << 24), (RST: 1 << 28)]), (Adc24: [(PER: 1 << 24), ]), (Adc579: [(PER: 30), (RST: 31)]), (Adc6810: [(PER: 31), ])] } -impl HrTim { - pub fn capture_ch1(&mut self) -> &mut HrCapt { - &mut self.capture_ch1 - } - - pub fn capture_ch2(&mut self) -> &mut HrCapt { - &mut self.capture_ch2 - } -} - /// Master Timer Period event impl super::event::TimerResetEventSource for HrTim { const BITS: u32 = 1 << 4; // MSTPER From 0e471e9cfac42acf9a74c5f64b663a784e3cd78e Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 7 Sep 2023 11:47:23 +0200 Subject: [PATCH 69/88] Fix incorrect mapping of DMA channel to DMAMUX channel This is quite an ugly hack but it does try to keep the API as unchanged as possible. This fix only fixes the problem on cat 3 and 4 devices for now. According to RM0440 under "DMAMUX mapping": For category 3 and category 4 devices: * DMAMUX channels 0 to 7 are connected to DMA1 channels 1 to 8 * DMAMUX channels 8 to 15 are connected to DMA2 channels 1 to 8 For category 2 devices: * DMAMUX channels 0 to 5 are connected to DMA1 channels 1 to 6 * DMAMUX channels 6 to 11 are connected to DMA2 channels 1 to 6 --- Cargo.toml | 1 + src/dma/config.rs | 7 -- src/dma/transfer.rs | 2 +- src/rcc/config.rs | 8 +-- src/serial/usart.rs | 151 ++++++++++++++++++++++++++++++++++++-------- 5 files changed, 131 insertions(+), 38 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 37b9cb36..845e2d9e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ static_assertions = "1.1" fugit = "0.3.5" stm32-usbd = { version = "0.7.0", optional = true } fixed = { version = "1.28.0", optional = true } +embedded-io = "0.6.1" [dependencies.cortex-m] version = "0.7.7" diff --git a/src/dma/config.rs b/src/dma/config.rs index 21b3bd02..6c854c58 100644 --- a/src/dma/config.rs +++ b/src/dma/config.rs @@ -38,7 +38,6 @@ pub struct DmaConfig { pub(crate) transfer_complete_interrupt: bool, pub(crate) half_transfer_interrupt: bool, pub(crate) transfer_error_interrupt: bool, - pub(crate) double_buffer: bool, } impl DmaConfig { @@ -84,10 +83,4 @@ impl DmaConfig { self.transfer_error_interrupt = transfer_error_interrupt; self } - /// Set the double_buffer. - #[inline(always)] - pub fn double_buffer(mut self, double_buffer: bool) -> Self { - self.double_buffer = double_buffer; - self - } } diff --git a/src/dma/transfer.rs b/src/dma/transfer.rs index 2c0d2f3d..c7599f07 100644 --- a/src/dma/transfer.rs +++ b/src/dma/transfer.rs @@ -512,7 +512,7 @@ impl_adc_overrun!(ADC4, ADC5,); macro_rules! impl_serial_timeout { ($($uart:ident, )*) => {$( - impl CircTransfer, BUF> + impl CircTransfer, BUF> where STREAM: Stream, /*BUF: StaticWriteBuffer + Deref*/ { diff --git a/src/rcc/config.rs b/src/rcc/config.rs index 4af1dcb1..5e1c4393 100644 --- a/src/rcc/config.rs +++ b/src/rcc/config.rs @@ -46,12 +46,12 @@ pub enum PllSrc { HSE_BYPASS(Hertz), } -impl PLLSrc { +impl PllSrc { pub const fn frequency(self) -> Hertz { match self { - PLLSrc::HSI => Hertz::MHz(16), - PLLSrc::HSE(f) => f, - PLLSrc::HSE_BYPASS(f) => f, + PllSrc::HSI => Hertz::MHz(16), + PllSrc::HSE(f) => f, + PllSrc::HSE_BYPASS(f) => f, } } } diff --git a/src/serial/usart.rs b/src/serial/usart.rs index 893b735d..bd9ccc92 100644 --- a/src/serial/usart.rs +++ b/src/serial/usart.rs @@ -1,9 +1,9 @@ +use core::convert::Infallible; use core::fmt; use core::marker::PhantomData; -use crate::dma::{ - mux::DmaMuxResources, traits::TargetAddress, MemoryToPeripheral, PeripheralToMemory, -}; +use crate::dma::traits::Stream; +use crate::dma::{mux::DmaMuxResources, traits::TargetAddress, PeripheralToMemory, MemoryToPeripheral}; use crate::gpio::{gpioa::*, gpiob::*, gpioc::*, gpiod::*, gpioe::*, gpiog::*}; use crate::gpio::{Alternate, AlternateOD, AF12, AF5, AF7, AF8}; use crate::prelude::*; @@ -84,7 +84,7 @@ pub struct Rx { pub struct Tx { pin: Pin, usart: USART, - _dma: PhantomData, + dma: Dma, } /// Serial abstraction @@ -108,7 +108,12 @@ impl TxPin for NoTx {} pub struct NoDMA; /// Type state for Tx/Rx, indicating configuration for DMA #[derive(Debug)] -pub struct DMA; +pub struct DMA { + stream: T, + memory: M, +} + +pub struct DMAOld; pub trait SerialExt { fn usart( @@ -133,9 +138,9 @@ where } } -impl fmt::Write for Tx +impl fmt::Write for Tx where - Tx: hal::serial::Write, + Tx: hal::serial::Write, { fn write_str(&mut self, s: &str) -> fmt::Result { let _ = s.as_bytes().iter().map(|c| block!(self.write(*c))).last(); @@ -143,6 +148,10 @@ where } } +impl embedded_io::ErrorType for Tx> { + type Error = Infallible; +} + macro_rules! uart_shared { ($USARTX:ident, $dmamux_rx:ident, $dmamux_tx:ident, tx: [ $($( #[ $pmeta1:meta ] )* ($PTX:ident, $TAF:expr),)+ ], @@ -189,7 +198,7 @@ macro_rules! uart_shared { } impl Rx<$USARTX, Pin, NoDMA> { - pub fn enable_dma(self) -> Rx<$USARTX, Pin, DMA> { + pub fn enable_dma(self) -> Rx<$USARTX, Pin, DMAOld> { // NOTE(unsafe) critical section prevents races cortex_m::interrupt::free(|_| unsafe { let cr3 = &(*$USARTX::ptr()).cr3(); @@ -204,7 +213,7 @@ macro_rules! uart_shared { } } - impl Rx<$USARTX, Pin, DMA> { + impl Rx<$USARTX, Pin, DMAOld> { pub fn disable_dma(self) -> Rx<$USARTX, Pin, NoDMA> { // NOTE(unsafe) critical section prevents races interrupt::free(|_| unsafe { @@ -280,37 +289,127 @@ macro_rules! uart_shared { let usart = unsafe { &(*$USARTX::ptr()) }; usart.isr().read().txft().bit_is_set() } + + pub fn clear_transmission_complete(&mut self) { + let usart = unsafe { &(*$USARTX::ptr()) }; + usart.icr().write(|w| w.tccf().set_bit()); + } } impl Tx<$USARTX, Pin, NoDMA> { - pub fn enable_dma(self) -> Tx<$USARTX, Pin, DMA> { + pub fn enable_dma(self, mut stream: STREAM, memory: BUF) -> Tx<$USARTX, Pin, DMA> + where + STREAM: crate::dma::traits::Stream, + BUF: embedded_dma::StaticReadBuffer + { // NOTE(unsafe) critical section prevents races interrupt::free(|_| unsafe { let cr3 = &(*$USARTX::ptr()).cr3(); cr3.modify(|_, w| w.dmat().set_bit()); }); + stream.disable(); + + core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst); + + // Set peripheral to memory mode + stream.set_direction(crate::dma::DmaDirection::MemoryToPeripheral); + + // NOTE(unsafe) We now own this buffer and we won't call any &mut + // methods on it until the end of the DMA transfer + let (buf_ptr, buf_len) = unsafe { memory.read_buffer() }; + + // Set the memory address + // + // # Safety + // + // Must be a valid memory address + unsafe { + stream.set_memory_address( + buf_ptr as u32, + ); + } + + // Set the peripheral address or the source address in memory-to-memory mode + // + // # Safety + // + // Must be a valid peripheral address or source address + let write_register_address = &unsafe { &*<$USARTX>::ptr() }.tdr() as *const _ as u32; + unsafe { stream.set_peripheral_address(write_register_address); } + + assert!( + buf_len <= 65535, + "Hardware does not support more than 65535 transfers" + ); + + // Set the DMAMUX request line + stream.set_request_line(DmaMuxResources::$dmamux_tx as u8); + + let msize = core::mem::size_of::() / 2; + + stream.clear_interrupts(); + + // NOTE(unsafe) These values are correct because of the + // invariants of TargetAddress + unsafe { + stream.set_memory_size(msize as u8); + stream.set_peripheral_size(msize as u8); + } + + let config = crate::dma::config::DmaConfig::default() + .transfer_complete_interrupt(false) + .circular_buffer(false) + .memory_increment(true); + stream.apply_config(config); + Tx { pin: self.pin, usart: self.usart, - _dma: PhantomData, + dma: DMA{ stream, memory }, } } } - impl Tx<$USARTX, Pin, DMA> { - pub fn disable_dma(self) -> Tx<$USARTX, Pin, NoDMA> { - // NOTE(unsafe) critical section prevents races - interrupt::free(|_| unsafe { - let cr3 = &(*$USARTX::ptr()).cr3(); - cr3.modify(|_, w| w.dmat().clear_bit()); - }); + impl embedded_io::Write for Tx<$USARTX, Pin, DMA> + where + T: Stream, + M: embedded_dma::StaticReadBuffer + core::ops::DerefMut, + ::Target: core::ops::IndexMut, Output = [u8]>, + { + fn write(&mut self, buf: &[u8]) -> Result { + use core::sync::atomic::fence; - Tx { - pin: self.pin, - usart: self.usart, - _dma: PhantomData, + let (_p, buffer_capacity) = unsafe { self.dma.memory.read_buffer() }; + let count = buf.len().min(buffer_capacity); + + embedded_io::Write::flush(self)?; + + fence(core::sync::atomic::Ordering::SeqCst); + self.dma.stream.disable(); + + fence(core::sync::atomic::Ordering::SeqCst); + + self.dma.memory[0..count].copy_from_slice(&buf[0..count]); + self.dma.stream.set_number_of_transfers(count as u16); + + fence(core::sync::atomic::Ordering::SeqCst); + + unsafe { + self.clear_transmission_complete(); + self.dma.stream.enable(); } + + Ok(count) + } + + fn flush(&mut self) -> Result<(), Self::Error> { + while T::get_number_of_transfers() > 0 { + assert!(!T::get_transfer_error_flag()); + } + self.dma.stream.clear_transfer_complete_interrupt(); + assert!(!T::get_transfer_error_flag()); + Ok(()) } } @@ -388,7 +487,7 @@ macro_rules! uart_shared { } } - unsafe impl TargetAddress for Tx<$USARTX, Pin, DMA> { + unsafe impl TargetAddress for Tx<$USARTX, Pin, DMAOld> { #[inline(always)] fn address(&self) -> u32 { // unsafe: only the Tx part accesses the Tx register @@ -400,7 +499,7 @@ macro_rules! uart_shared { const REQUEST_LINE: Option = Some(DmaMuxResources::$dmamux_tx as u8); } - unsafe impl TargetAddress for Rx<$USARTX, Pin, DMA> { + unsafe impl TargetAddress for Rx<$USARTX, Pin, DMAOld> { #[inline(always)] fn address(&self) -> u32 { // unsafe: only the Rx part accesses the Rx register @@ -513,7 +612,7 @@ macro_rules! uart_lp { tx: Tx { pin: tx, usart, - _dma: PhantomData, + dma: NoDMA, }, rx: Rx { pin: rx, @@ -667,7 +766,7 @@ macro_rules! uart_full { tx: Tx { pin: tx, usart, - _dma: PhantomData, + dma: NoDMA, }, rx: Rx { pin: rx, From d3fc23da46638b8e7077bb8a574719ef4bb019b3 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 3 Apr 2024 16:06:41 +0200 Subject: [PATCH 70/88] OPAMP - Add more adc pin impls for opamp follower --- src/adc.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/adc.rs b/src/adc.rs index 45f775bf..ee4e6f72 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -2863,6 +2863,21 @@ adc_opamp!( opamp::Opamp6 => (ADC4, 17), ); +#[cfg(any( + feature = "stm32g473", + feature = "stm32g474", + feature = "stm32g483", + feature = "stm32g484", + feature = "stm32g491", + feature = "stm32g4a1", +))] +adc_op_follower!( + opamp::opamp3::Follower => (ADC3, 13), + opamp::opamp4::Follower => (ADC5, 5), + opamp::opamp5::Follower => (ADC5, 3), + opamp::opamp6::Follower => (ADC4, 17), +); + #[cfg(any(feature = "stm32g491", feature = "stm32g4a1",))] adc_opamp!( opamp::Opamp6 => (ADC3, 17), From e8ef32231e3d1e173dfd56babe997e4f799b2a63 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 18 Apr 2024 11:53:29 +0200 Subject: [PATCH 71/88] HRTIM - Add derives for some types --- src/hrtim/external_event.rs | 3 +++ src/pwm.rs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/hrtim/external_event.rs b/src/hrtim/external_event.rs index 3c5e0c38..2389dc3a 100644 --- a/src/hrtim/external_event.rs +++ b/src/hrtim/external_event.rs @@ -101,17 +101,20 @@ impl_eev_input!(8: COMP = [COMP6, (COMP3, 0b10)], PINS = [(PB8, AF13)]); impl_eev_input!(9: COMP = [COMP5, (COMP4, 0b11)], PINS = [(PB3, AF13)]); impl_eev_input!(10: COMP = [COMP7], PINS = [(PC5, AF13), (PC6, AF3)]); +#[derive(Copy, Clone, Debug, PartialEq)] pub enum EdgeOrPolarity { Edge(Edge), Polarity(Polarity), } +#[derive(Copy, Clone, Debug, PartialEq)] pub enum Edge { Rising = 0b01, Falling = 0b10, Both = 0b11, } +#[derive(Copy, Clone, Debug, PartialEq)] pub enum EevSamplingFilter { /// No filtering, fault acts asynchronously /// diff --git a/src/pwm.rs b/src/pwm.rs index 25338b60..e88748e3 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -255,7 +255,7 @@ pub struct ComplementaryDisabled; pub struct ComplementaryEnabled; /// Enum for IO polarity -#[derive(Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub enum Polarity { ActiveHigh, ActiveLow, From d3d17fd5ce4630ca3de87e31eb56b0fa3ff6f41f Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Apr 2024 10:10:10 +0200 Subject: [PATCH 72/88] HRTIM - Allow using capture module with DMA --- examples/hrtim/capture-dma.rs | 134 ++++++++++++++++++++++++++++++++++ examples/hrtim/capture.rs | 2 +- src/dma/transfer.rs | 30 +++++++- src/hrtim/capture.rs | 85 +++++++++++++++------ src/hrtim/mod.rs | 27 ++++++- src/hrtim/output.rs | 4 +- src/hrtim/timer.rs | 79 ++++++++++++++------ 7 files changed, 310 insertions(+), 51 deletions(-) create mode 100644 examples/hrtim/capture-dma.rs diff --git a/examples/hrtim/capture-dma.rs b/examples/hrtim/capture-dma.rs new file mode 100644 index 00000000..d6069206 --- /dev/null +++ b/examples/hrtim/capture-dma.rs @@ -0,0 +1,134 @@ +#![no_std] +#![no_main] + +/// Example showcasing the use of the HRTIM peripheral's capture function to detect phase shift between a digital event and the output of HRTIM_TIMA + +#[path = "../utils/mod.rs"] +mod utils; + +use cortex_m_rt::entry; + +use defmt_rtt as _; // global logger +use panic_probe as _; + +use utils::logger::info; + +#[entry] +fn main() -> ! { + use stm32g4xx_hal as hal; + + use hal::{ + dma::{config::DmaConfig, stream::DMAExt, TransferExt}, + gpio::{gpioa::PA8, Alternate, GpioExt, AF13}, + hrtim::{ + capture, compare_register::HrCompareRegister, control::HrControltExt, external_event, + external_event::ToExternalEventSource, output::HrOutput, timer::HrSlaveTimerCpt, + timer::HrTimer, HrPwmAdvExt, Pscl128, + }, + pwr::PwrExt, + rcc::{self, RccExt}, + stm32::Peripherals, + }; + use info; + + info!("start"); + + let dp = Peripherals::take().unwrap(); + + // Set system frequency to 16MHz * 15/1/2 = 120MHz + // This would lead to HrTim running at 120MHz * 32 = 3.84... + info!("rcc"); + let pwr = dp.PWR.constrain().freeze(); + let mut rcc = dp.RCC.freeze( + rcc::Config::pll().pll_cfg(rcc::PllConfig { + mux: rcc::PLLSrc::HSI, + n: rcc::PllNMul::MUL_15, + m: rcc::PllMDiv::DIV_1, + r: Some(rcc::PllRDiv::DIV_2), + + ..Default::default() + }), + pwr, + ); + + info!("Setup Gpio"); + let gpioa = dp.GPIOA.split(&mut rcc); + let gpiob = dp.GPIOB.split(&mut rcc); + + // PA8 (D7 on Nucleo G474RE) + let pin_a: PA8> = gpioa.pa8.into_alternate(); + + // PB5 (D4 on Nucleo G474RE) + let input = gpiob.pb5.into_pull_down_input(); + + // ...with a prescaler of 128 this gives us a HrTimer with a tick rate of 30MHz + // With max the max period set, this would be 30MHz/2^16 ~= 458Hz... + let prescaler = Pscl128; + + // t1 t2 . + // | | . + // v v . + // . . + // . 50% . + // ------ ------ + //out1 | | | | + // | | | | + // -------- ---------- -------- + let period = 0xFFFF; + let (mut hr_control, _flt_inputs, eev_inputs) = + dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); + + let eev_input6 = eev_inputs + .eev_input6 + .bind(input) + .edge_or_polarity(external_event::EdgeOrPolarity::Edge( + external_event::Edge::Both, + )) + .finalize(&mut hr_control); + + let mut hr_control = hr_control.constrain(); + let (timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp + .HRTIM_TIMA + .pwm_advanced(pin_a, &mut rcc) + .prescaler(prescaler) + .period(period) + .finalize(&mut hr_control); + out1.enable_rst_event(&cr1); // Set low on compare match with cr1 + out1.enable_set_event(&timer); // Set high at new period + cr1.set_duty(period / 2); + + let (mut timer, mut capture, _capture_ch2) = timer.split_capture(); + timer.start(&mut hr_control); + out1.enable(); + + capture.enable_interrupt(true, &mut hr_control); + capture.add_event(&eev_input6); + + info!("Setup DMA"); + let streams = dp.DMA1.split(&rcc); + let config = DmaConfig::default() + .transfer_complete_interrupt(false) + .circular_buffer(true) + .memory_increment(true); + + let first_buffer = cortex_m::singleton!(: [u32; 16] = [0; 16]).unwrap(); + let mut transfer = streams.0.into_circ_peripheral_to_memory_transfer( + capture.enable_dma(), + &mut first_buffer[..], + config, + ); + + transfer.start(|_| ()); + + let mut old_duty = 0; + loop { + for duty in (u32::from(period) / 10)..(9 * u32::from(period) / 10) { + let mut data = [0; 2]; + transfer.read_exact(&mut data); + let [t1, t2] = data.map(capture::dma_value_to_signed); + cr1.set_duty(duty as u16); + info!("Capture: t1: {}, t2: {}, duty: {}, ", t1, t2, old_duty); + old_duty = duty; + } + } +} diff --git a/examples/hrtim/capture.rs b/examples/hrtim/capture.rs index a90c84f5..75b7f4e1 100644 --- a/examples/hrtim/capture.rs +++ b/examples/hrtim/capture.rs @@ -22,7 +22,7 @@ fn main() -> ! { hrtim::{ capture::HrCapture, compare_register::HrCompareRegister, control::HrControltExt, external_event, external_event::ToExternalEventSource, output::HrOutput, - timer::HrTimer, HrPwmAdvExt, Pscl128, + timer::HrSlaveTimerCpt, timer::HrTimer, HrPwmAdvExt, Pscl128, }, pwr::PwrExt, rcc::{self, RccExt}, diff --git a/src/dma/transfer.rs b/src/dma/transfer.rs index c7599f07..399abe87 100644 --- a/src/dma/transfer.rs +++ b/src/dma/transfer.rs @@ -383,14 +383,38 @@ where read } + /// Read all immediately available values without blocking pub fn read_available<'a>( &mut self, - data: &'a mut [>::MemSize], + dst: &'a mut [>::MemSize], + ) -> &'a mut [>::MemSize] { + self.read_available_multiple(1, dst) + } + + /// Same as [`CircTransfer::read_available`] but only read a whole multiple number of elements + /// + /// Example: + /// ``` + /// ... + /// // There are 7 values in the buffer + /// assert_eq!(transfer.read_available_multiple(3, &mut dst).len(), 6); + /// + /// // There are 3 values in the buffer + /// assert_eq!(transfer.read_available_multiple(2, &mut dst).len(), 2); + /// + /// // There are 1 values in the buffer + /// assert_eq!(transfer.read_available_multiple(2, &mut dst).len(), 0); + /// ``` + pub fn read_available_multiple<'a>( + &mut self, + multiple: u8, + dst: &'a mut [>::MemSize], ) -> &'a mut [>::MemSize] { let blen = unsafe { self.transfer.buf.static_write_buffer().1 }; let available = self.elements_available(); - let len = data.len().min(available).min(blen - 1); - let result = &mut data[0..len]; + let len = dst.len().min(available).min(blen - 1); + let len = len - (len % usize::from(multiple)); + let result = &mut dst[0..len]; self.read_exact(result); result diff --git a/src/hrtim/capture.rs b/src/hrtim/capture.rs index b93e7642..b3df231b 100644 --- a/src/hrtim/capture.rs +++ b/src/hrtim/capture.rs @@ -1,12 +1,17 @@ +use crate::dma::mux::DmaMuxResources; +use crate::dma::traits::TargetAddress; +use crate::dma::PeripheralToMemory; +use crate::stm32::{HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF}; use core::marker::PhantomData; -use stm32g4::stm32g474::{HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF}; - pub struct Ch1; pub struct Ch2; -pub struct HrCapt { - _x: PhantomData<(TIM, PSCL, CH)>, +pub struct Dma; +pub struct NoDma; + +pub struct HrCapt { + _x: PhantomData<(TIM, PSCL, CH, DMA)>, } #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -58,9 +63,26 @@ pub trait HrCapture { fn is_pending(&self) -> bool; } +pub fn dma_value_to_dir_and_value(x: u32) -> (u16, CountingDirection) { + let value = (x & 0xFFFF) as u16; + match x & 1 << 16 != 0 { + true => (value, CountingDirection::Down), + false => (value, CountingDirection::Up), + } +} + +pub fn dma_value_to_signed(x: u32) -> i32 { + let (value, dir) = dma_value_to_dir_and_value(x); + + match dir { + CountingDirection::Up => i32::from(value), + CountingDirection::Down => -i32::from(value), + } +} + macro_rules! impl_capture { - ($($TIMX:ident: $CH:ident, $cptXYr:ident, $cptXYcr:ident, $cptXx:ident, $dier:ident, $icr:ident, $isr:ident, $cptXie:ident, $cptXc:ident, $cptX:ident),+) => { - $(impl HrCapt<$TIMX, PSCL, $CH> { + ($($TIMX:ident: $CH:ident, $cptXYr:ident, $cptXYcr:ident, $cptXx:ident, $dier:ident, $icr:ident, $isr:ident, $cptXie:ident, $cptXde:ident, $cptXc:ident, $cptX:ident, $mux:expr),+) => {$( + impl HrCapt<$TIMX, PSCL, $CH, NoDma> { /// Add event to capture /// /// If multiple events are added, they will be ORed together meaning @@ -100,12 +122,21 @@ macro_rules! impl_capture { tim.$dier.modify(|_r, w| w.$cptXie().bit(enable)); } + + pub fn enable_dma(self) -> HrCapt<$TIMX, PSCL, $CH, Dma> { + let tim = unsafe { &*$TIMX::ptr() }; + tim.$dier.modify(|_r, w| w.$cptXde().set_bit()); + HrCapt { + _x: PhantomData + } + } } - impl HrCapture for HrCapt<$TIMX, PSCL, $CH> { + impl HrCapture for HrCapt<$TIMX, PSCL, $CH, DMA> { fn get(&self) -> (u16, CountingDirection) { let tim = unsafe { &*$TIMX::ptr() }; let data = tim.$cptXYr.read(); + let dir = match data.dir().bit() { true => CountingDirection::Down, false => CountingDirection::Up, @@ -128,26 +159,38 @@ macro_rules! impl_capture { // No need for exclusive access since this is a read only register tim.$isr.read().$cptX().bit() } - })+ - }; + } + + unsafe impl TargetAddress for HrCapt<$TIMX, PSCL, $CH, Dma> { + #[inline(always)] + fn address(&self) -> u32 { + let tim = unsafe { &*$TIMX::ptr() }; + &tim.$cptXYr as *const _ as u32 + } + + type MemSize = u32; + + const REQUEST_LINE: Option = Some($mux as u8); + } + )+}; } impl_capture! { - HRTIM_TIMA: Ch1, cpt1ar, cpt1acr, cpt1x, timadier, timaicr, timaisr, cpt1ie, cpt1c, cpt1, - HRTIM_TIMA: Ch2, cpt2ar, cpt2acr, cpt2x, timadier, timaicr, timaisr, cpt2ie, cpt2c, cpt2, + HRTIM_TIMA: Ch1, cpt1ar, cpt1acr, cpt1x, timadier, timaicr, timaisr, cpt1ie, cpt1de, cpt1c, cpt1, DmaMuxResources::HRTIM_TIMA, + HRTIM_TIMA: Ch2, cpt2ar, cpt2acr, cpt2x, timadier, timaicr, timaisr, cpt2ie, cpt2de, cpt2c, cpt2, DmaMuxResources::HRTIM_TIMA, - HRTIM_TIMB: Ch1, cpt1br, cpt1bcr, cpt1x, timbdier, timbicr, timbisr, cpt1ie, cpt1c, cpt1, - HRTIM_TIMB: Ch2, cpt2br, cpt2bcr, cpt2x, timbdier, timbicr, timbisr, cpt2ie, cpt2c, cpt2, + HRTIM_TIMB: Ch1, cpt1br, cpt1bcr, cpt1x, timbdier, timbicr, timbisr, cpt1ie, cpt1de, cpt1c, cpt1, DmaMuxResources::HRTIM_TIMB, + HRTIM_TIMB: Ch2, cpt2br, cpt2bcr, cpt2x, timbdier, timbicr, timbisr, cpt2ie, cpt2de, cpt2c, cpt2, DmaMuxResources::HRTIM_TIMB, - HRTIM_TIMC: Ch1, cpt1cr, cpt1ccr, cpt1x, timcdier, timcicr, timcisr, cpt1ie, cpt1c, cpt1, - HRTIM_TIMC: Ch2, cpt2cr, cpt2ccr, cpt2x, timcdier, timcicr, timcisr, cpt2ie, cpt2c, cpt2, + HRTIM_TIMC: Ch1, cpt1cr, cpt1ccr, cpt1x, timcdier, timcicr, timcisr, cpt1ie, cpt1de, cpt1c, cpt1, DmaMuxResources::HRTIM_TIMC, + HRTIM_TIMC: Ch2, cpt2cr, cpt2ccr, cpt2x, timcdier, timcicr, timcisr, cpt2ie, cpt2de, cpt2c, cpt2, DmaMuxResources::HRTIM_TIMC, - HRTIM_TIMD: Ch1, cpt1dr, cpt1dcr, cpt1x, timddier, timdicr, timdisr, cpt1ie, cpt1c, cpt1, - HRTIM_TIMD: Ch2, cpt2dr, cpt2dcr, cpt2x, timddier, timdicr, timdisr, cpt2ie, cpt2c, cpt2, + HRTIM_TIMD: Ch1, cpt1dr, cpt1dcr, cpt1x, timddier, timdicr, timdisr, cpt1ie, cpt1de, cpt1c, cpt1, DmaMuxResources::HRTIM_TIMD, + HRTIM_TIMD: Ch2, cpt2dr, cpt2dcr, cpt2x, timddier, timdicr, timdisr, cpt2ie, cpt2de, cpt2c, cpt2, DmaMuxResources::HRTIM_TIMD, - HRTIM_TIME: Ch1, cpt1er, cpt1ecr, cpt1x, timedier, timeicr, timeisr, cpt1ie, cpt1c, cpt1, - HRTIM_TIME: Ch2, cpt2er, cpt2ecr, cpt2x, timedier, timeicr, timeisr, cpt2ie, cpt2c, cpt2, + HRTIM_TIME: Ch1, cpt1er, cpt1ecr, cpt1x, timedier, timeicr, timeisr, cpt1ie, cpt1de, cpt1c, cpt1, DmaMuxResources::HRTIM_TIME, + HRTIM_TIME: Ch2, cpt2er, cpt2ecr, cpt2x, timedier, timeicr, timeisr, cpt2ie, cpt2de, cpt2c, cpt2, DmaMuxResources::HRTIM_TIME, - HRTIM_TIMF: Ch1, cpt1fr, cpt1fcr, cpt1x, timfdier, timficr, timfisr, cpt1ie, cpt1c, cpt1, - HRTIM_TIMF: Ch2, cpt2fr, cpt2fcr, cpt2x, timfdier, timficr, timfisr, cpt2ie, cpt2c, cpt2 + HRTIM_TIMF: Ch1, cpt1fr, cpt1fcr, cpt1x, timfdier, timficr, timfisr, cpt1ie, cpt1de, cpt1c, cpt1, DmaMuxResources::HRTIM_TIMF, + HRTIM_TIMF: Ch2, cpt2fr, cpt2fcr, cpt2x, timfdier, timficr, timfisr, cpt2ie, cpt2de, cpt2c, cpt2, DmaMuxResources::HRTIM_TIMF } diff --git a/src/hrtim/mod.rs b/src/hrtim/mod.rs index 5c679511..c337269c 100644 --- a/src/hrtim/mod.rs +++ b/src/hrtim/mod.rs @@ -13,6 +13,7 @@ pub mod timer_eev_cfg; use core::marker::PhantomData; use core::mem::MaybeUninit; +use crate::hrtim::capture::HrCapt; use crate::hrtim::compare_register::{HrCr1, HrCr2, HrCr3, HrCr4}; use crate::hrtim::fault::{FaultAction, FaultSource}; use crate::hrtim::timer::HrTim; @@ -588,7 +589,19 @@ macro_rules! hrtim_hal { PSCL: HrtimPrescaler, OUT: ToHrOut, { - pub fn finalize(self, _control: &mut HrPwmControl) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX, PSCL>, HrCr2<$TIMX, PSCL>, HrCr3<$TIMX, PSCL>, HrCr4<$TIMX, PSCL>), OUT) { + pub fn finalize(self, _control: &mut HrPwmControl) -> ( + HrTim<$TIMX, PSCL, + HrCapt<$TIMX, PSCL, capture::Ch1, capture::NoDma>, + HrCapt<$TIMX, PSCL, capture::Ch2, capture::NoDma>>, + ( + HrCr1<$TIMX, PSCL>, + HrCr2<$TIMX, PSCL>, + HrCr3<$TIMX, PSCL>, + HrCr4<$TIMX, PSCL> + ), + OUT + ) { + hrtim_finalize_body!( self, PreloadSource, $TIMX: ($timXcr, ck_pscx, $perXr, perx, $tXcen, $rep, $repx, $dier, $repie, $timXcr2, $fltXr, $eefXr1, $eefXr2, $Xeefr3, $outXr, $dtXr), @@ -732,7 +745,17 @@ macro_rules! hrtim_hal_master { PSCL: HrtimPrescaler, OUT: ToHrOut, { - pub fn finalize(self, _control: &mut HrPwmControl) -> (HrTim<$TIMX, PSCL>, (HrCr1<$TIMX, PSCL>, HrCr2<$TIMX, PSCL>, HrCr3<$TIMX, PSCL>, HrCr4<$TIMX, PSCL>)) { + pub fn finalize(self, _control: &mut HrPwmControl) -> ( + HrTim<$TIMX, PSCL, + HrCapt<$TIMX, PSCL, capture::Ch1, capture::NoDma>, + HrCapt<$TIMX, PSCL, capture::Ch2, capture::NoDma>, + >, ( + HrCr1<$TIMX, PSCL>, + HrCr2<$TIMX, PSCL>, + HrCr3<$TIMX, PSCL>, + HrCr4<$TIMX, PSCL> + )) { + hrtim_finalize_body!(self, MasterPreloadSource, $TIMX: ($timXcr, $ck_psc, $perXr, $perx, $tXcen, $rep, $rep, $dier, $repie),) } diff --git a/src/hrtim/output.rs b/src/hrtim/output.rs index 31d28914..b74d6d72 100644 --- a/src/hrtim/output.rs +++ b/src/hrtim/output.rs @@ -15,7 +15,7 @@ use crate::{ macro_rules! hrtim_out { ($($TIMX:ident: $out_type:ident: $tXYoen:ident, $tXYodis:ident, $tXYods:ident, $setXYr:ident, $rstXYr:ident,)+) => {$( - impl HrOutput for $out_type<$TIMX, PSCL> { + 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() }); @@ -84,7 +84,7 @@ hrtim_out! { HRTIM_TIMF: HrOut2: tf2oen, tf2odis, tf2ods, setf2r, rstf2r, } -pub trait HrOutput { +pub trait HrOutput { /// Enable this output fn enable(&mut self); diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs index c6f52369..1adb5301 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -6,18 +6,19 @@ use core::marker::PhantomData; use super::{ capture::{self, HrCapt}, control::HrPwmControl, + HrtimPrescaler, }; -pub struct HrTim { +pub struct HrTim { _timer: PhantomData, _prescaler: PhantomData, - capture_ch1: HrCapt, - capture_ch2: HrCapt, + capture_ch1: CPT1, + capture_ch2: CPT2, } pub trait HrTimer { type Timer; - type Prescaler; + type Prescaler: HrtimPrescaler; /// Get period of timer in number of ticks /// @@ -47,10 +48,9 @@ pub trait HrTimer { fn as_period_adc_trigger(&self) -> super::adc_trigger::TimerPeriod; } -pub trait HrSlaveTimer: HrTimer -{ - type CaptureCh1: super::capture::HrCapture; - type CaptureCh2: super::capture::HrCapture; +pub trait HrSlaveTimer: HrTimer { + type CaptureCh1; + type CaptureCh2; /// Start listening to the specified event fn enable_reset_event>( @@ -63,9 +63,19 @@ pub trait HrSlaveTimer: HrTimer &mut self, _event: &E, ); +} - fn capture_ch1(&mut self) -> &mut Self::CaptureCh1; - fn capture_ch2(&mut self) -> &mut Self::CaptureCh2; +/// Trait for unsplit slave timer which still contains its capture modules +pub trait HrSlaveTimerCpt: HrSlaveTimer { + fn capture_ch1(&mut self) -> &mut ::CaptureCh1; + fn capture_ch2(&mut self) -> &mut ::CaptureCh2; + fn split_capture( + self, + ) -> ( + HrTim, + HrCapt, + HrCapt, + ); } macro_rules! hrtim_timer { @@ -84,7 +94,7 @@ macro_rules! hrtim_timer { $repc:ident, $(($rstXr:ident))*, )+) => {$( - impl HrTimer for HrTim<$TIMX, PSCL> { + impl HrTimer for HrTim<$TIMX, PSCL, CPT1, CPT2> { type Prescaler = PSCL; type Timer = $TIMX; @@ -142,7 +152,7 @@ macro_rules! hrtim_timer { } } - impl HrTim<$TIMX, PSCL> { + impl HrTim<$TIMX, PSCL, CPT1, CPT2> { pub fn set_repetition_counter(&mut self, repetition_counter: u8) { let tim = unsafe { &*$TIMX::ptr() }; @@ -157,9 +167,9 @@ macro_rules! hrtim_timer { } $( - impl HrSlaveTimer for HrTim<$TIMX, PSCL> { - type CaptureCh1 = HrCapt; - type CaptureCh2 = HrCapt; + impl HrSlaveTimer for HrTim<$TIMX, PSCL, CPT1, CPT2> { + type CaptureCh1 = HrCapt; + type CaptureCh2 = HrCapt; /// Reset this timer every time the specified event occurs /// @@ -188,7 +198,9 @@ macro_rules! hrtim_timer { unsafe { tim.$rstXr.modify(|r, w| w.bits(r.bits() & !E::BITS)); } } + } + impl HrSlaveTimerCpt for HrTim<$TIMX, PSCL, HrCapt<$TIMX, PSCL, capture::Ch1, capture::NoDma>, HrCapt<$TIMX, PSCL, capture::Ch2, capture::NoDma>> { /// Access the timers first capture channel fn capture_ch1(&mut self) -> &mut Self::CaptureCh1 { &mut self.capture_ch1 @@ -198,11 +210,30 @@ macro_rules! hrtim_timer { fn capture_ch2(&mut self) -> &mut Self::CaptureCh2 { &mut self.capture_ch2 } - } + fn split_capture(self) -> (HrTim<$TIMX, PSCL, (), ()>, HrCapt<$TIMX, PSCL, capture::Ch1, capture::NoDma>, HrCapt<$TIMX, PSCL, capture::Ch2, capture::NoDma>) { + let HrTim{ + _timer, + _prescaler, + capture_ch1, + capture_ch2, + } = self; + + ( + HrTim{ + _timer, + _prescaler, + capture_ch1: (), + capture_ch2: (), + }, + capture_ch1, + capture_ch2, + ) + } + } /// Timer Period event - impl super::event::EventSource for HrTim<$TIMX, PSCL> { + impl super::event::EventSource for HrTim<$TIMX, PSCL, CPT1, CPT2> { // $rstXr const BITS: u32 = 1 << 2; } @@ -210,7 +241,7 @@ macro_rules! hrtim_timer { /// Timer Update event /// /// TODO: What dows this mean? - impl super::capture::CaptureEvent<$TIMX, PSCL> for HrTim<$TIMX, PSCL> { + impl super::capture::CaptureEvent<$TIMX, PSCL> for HrTim<$TIMX, PSCL, CPT1, CPT2> { const BITS: u32 = 1 << 1; } )* @@ -225,11 +256,11 @@ macro_rules! hrtim_timer_adc_trigger { ])),+] ),+) => { $($( - $(impl $AdcTrigger for super::adc_trigger::TimerReset> { + $(impl $AdcTrigger for super::adc_trigger::TimerReset> { const BITS: u32 = $adc_trigger_bits_reset; })* - $(impl $AdcTrigger for super::adc_trigger::TimerPeriod> { + $(impl $AdcTrigger for super::adc_trigger::TimerPeriod> { const BITS: u32 = $adc_trigger_bits_period; })* )*)* @@ -264,11 +295,15 @@ hrtim_timer_adc_trigger! { } /// Master Timer Period event -impl super::event::TimerResetEventSource for HrTim { +impl super::event::TimerResetEventSource + for HrTim +{ const BITS: u32 = 1 << 4; // MSTPER } /// Master Timer Period event -impl super::event::EventSource for HrTim { +impl super::event::EventSource + for HrTim +{ const BITS: u32 = 1 << 7; // MSTPER } From 6e9a34e76170d7c2fc6077b34e2c2e5020ea4785 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Apr 2024 10:10:36 +0200 Subject: [PATCH 73/88] HRTIM - Fix example --- examples/hrtim/master.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/hrtim/master.rs b/examples/hrtim/master.rs index fca32d9e..2037a9b6 100644 --- a/examples/hrtim/master.rs +++ b/examples/hrtim/master.rs @@ -23,6 +23,7 @@ fn main() -> ! { use hal::hrtim::compare_register::HrCompareRegister; use hal::hrtim::control::HrControltExt; use hal::hrtim::output::HrOutput; + use hal::hrtim::timer::HrSlaveTimer; use hal::hrtim::timer::HrTimer; use hal::hrtim::HrPwmAdvExt; use hal::hrtim::{HrTimerMode, MasterPreloadSource, PreloadSource, Pscl4}; From 3ea35f6e401e7101435c4bca79edb6651e43341b Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Apr 2024 10:11:24 +0200 Subject: [PATCH 74/88] UART - Fix example --- examples/uart-dma-tx.rs | 50 +++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/examples/uart-dma-tx.rs b/examples/uart-dma-tx.rs index 78abeb4f..2f56eea0 100644 --- a/examples/uart-dma-tx.rs +++ b/examples/uart-dma-tx.rs @@ -5,9 +5,9 @@ extern crate cortex_m_rt as rt; -use core::fmt::Write; - -use hal::dma::{config::DmaConfig, stream::DMAExt, TransferExt}; +use core::fmt::Write as _; +use embedded_io::Write as _; +use hal::dma::stream::DMAExt; use hal::prelude::*; use hal::pwr::PwrExt; use hal::serial::*; @@ -33,10 +33,6 @@ fn main() -> ! { let mut rcc = rcc.freeze(rcc::Config::hsi(), pwr); let streams = dp.DMA1.split(&rcc); - let config = DmaConfig::default() - .transfer_complete_interrupt(false) - .circular_buffer(false) - .memory_increment(true); info!("Init UART"); let gpioa = dp.GPIOA.split(&mut rcc); @@ -53,28 +49,44 @@ fn main() -> ! { .unwrap(); let mut delay_syst = cp.SYST.delay(&rcc.clocks); - let mut led = gpioa.pa5.into_push_pull_output(); + let mut led1 = gpioa.pa5.into_push_pull_output(); + let mut led2 = gpioa.pa6.into_push_pull_output(); info!("Start writing"); writeln!(usart, "Hello without DMA\r").unwrap(); - let tx_buffer = cortex_m::singleton!(: [u8; 17] = *b"Hello with DMA!\r\n").unwrap(); + let tx_buffer = cortex_m::singleton!(: [u8; 64] = [0; 64]).unwrap(); let (tx, _rx) = usart.split(); // Setup DMA for USART2 TX with dma channel 1. - let mut transfer = - streams - .0 - .into_memory_to_peripheral_transfer(tx.enable_dma(), &mut tx_buffer[..], config); + let mut tx = tx.enable_dma(streams.0, &mut tx_buffer[..]); - transfer.start(|_tx| {}); loop { - while !transfer.get_transfer_complete_flag() {} - - delay_syst.delay(1000.millis()); - led.toggle().unwrap(); - transfer.restart(|_tx| {}); + for i in 0.. { + // This will write to the DMA buffer and return directly, proveded the buffer is empty + // and there is enough room in the buffer for the entire message. Otherwise it will block. + led1.set_high().unwrap(); + writeln!(&mut tx, "Hello with DMA").unwrap(); + led1.set_low().unwrap(); + + delay_syst.delay(100.millis()); + + // This will not block due the message above since we have a delay. However do watch out for the + // `{i}` since this will invoke another DMA transfer. This will block until the first part of + // the message before the `{i}` has been flushed. Same thing for the part after the `{i}`. + led2.set_high().unwrap(); + writeln!(&mut tx, "Partially blocking DMA write: {i}!").unwrap(); + led2.set_low().unwrap(); + + // Something like this ensures there is only one DMA transfer. This, assuming the DMA buffer is empty and + // the data fits, guarantees a non blocking write: + //let mut bytes = heapless::Vec::<_, 64>::new(); + //writeln!(&mut bytes, "Non blocking write of complex message: {i} % 10 = {}!", i % 10); + //tx.write(bytes.as_slice()).unwrap(); + + delay_syst.delay(1000.millis()); + } } } From 07eb18d4d77e3ebb906911ed057159ed9d1f188b Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Apr 2024 10:32:09 +0200 Subject: [PATCH 75/88] HRTIM - Prevent future dataraces for DMA --- examples/hrtim/adc-trigger.rs | 2 +- examples/hrtim/capture-dma.rs | 4 ++-- examples/hrtim/capture.rs | 2 +- examples/hrtim/eev-comp.rs | 2 +- examples/hrtim/eev.rs | 2 +- examples/hrtim/flt-comp.rs | 2 +- examples/hrtim/flt.rs | 2 +- examples/hrtim/hrtim.rs | 2 +- examples/hrtim/master.rs | 4 ++-- src/hrtim/capture.rs | 4 +++- src/hrtim/mod.rs | 11 +++++++---- src/hrtim/timer.rs | 7 +++++++ 12 files changed, 28 insertions(+), 16 deletions(-) diff --git a/examples/hrtim/adc-trigger.rs b/examples/hrtim/adc-trigger.rs index c80f17f9..7c6facb9 100644 --- a/examples/hrtim/adc-trigger.rs +++ b/examples/hrtim/adc-trigger.rs @@ -91,7 +91,7 @@ fn main() -> ! { let period = 0xFFFF; let (hr_control, ..) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); let mut hr_control = hr_control.constrain(); - let (mut timer, (mut cr1, _cr2, mut cr3, mut cr4), (mut out1, mut out2)) = dp + let (mut timer, (mut cr1, _cr2, mut cr3, mut cr4), (mut out1, mut out2), ..) = dp .HRTIM_TIMA .pwm_advanced((pin_a, pin_b), &mut rcc) .prescaler(prescaler) diff --git a/examples/hrtim/capture-dma.rs b/examples/hrtim/capture-dma.rs index d6069206..3e513ebf 100644 --- a/examples/hrtim/capture-dma.rs +++ b/examples/hrtim/capture-dma.rs @@ -87,7 +87,7 @@ fn main() -> ! { .finalize(&mut hr_control); let mut hr_control = hr_control.constrain(); - let (timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp + let (timer, (mut cr1, _cr2, _cr3, _cr4), mut out1, dma_ch) = dp .HRTIM_TIMA .pwm_advanced(pin_a, &mut rcc) .prescaler(prescaler) @@ -113,7 +113,7 @@ fn main() -> ! { let first_buffer = cortex_m::singleton!(: [u32; 16] = [0; 16]).unwrap(); let mut transfer = streams.0.into_circ_peripheral_to_memory_transfer( - capture.enable_dma(), + capture.enable_dma(dma_ch), &mut first_buffer[..], config, ); diff --git a/examples/hrtim/capture.rs b/examples/hrtim/capture.rs index 75b7f4e1..c62e84c5 100644 --- a/examples/hrtim/capture.rs +++ b/examples/hrtim/capture.rs @@ -83,7 +83,7 @@ fn main() -> ! { .finalize(&mut hr_control); let mut hr_control = hr_control.constrain(); - let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp + let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1, ..) = dp .HRTIM_TIMA .pwm_advanced(pin_a, &mut rcc) .prescaler(prescaler) diff --git a/examples/hrtim/eev-comp.rs b/examples/hrtim/eev-comp.rs index 2c1e802f..c4a7ee06 100644 --- a/examples/hrtim/eev-comp.rs +++ b/examples/hrtim/eev-comp.rs @@ -114,7 +114,7 @@ fn main() -> ! { // ------------------------- .-------------------------------------- // . . * . . . // . . * . . . - let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp + let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1, ..) = dp .HRTIM_TIMA .pwm_advanced(pin_a, &mut rcc) .prescaler(prescaler) diff --git a/examples/hrtim/eev.rs b/examples/hrtim/eev.rs index 846fd1ac..636564bc 100644 --- a/examples/hrtim/eev.rs +++ b/examples/hrtim/eev.rs @@ -86,7 +86,7 @@ fn main() -> ! { // ------------------------- ------------------------------------------ // . . * . . . // . . * . . . - let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp + let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1, ..) = dp .HRTIM_TIMA .pwm_advanced(pin_a, &mut rcc) .prescaler(prescaler) diff --git a/examples/hrtim/flt-comp.rs b/examples/hrtim/flt-comp.rs index d9923515..9131f42f 100644 --- a/examples/hrtim/flt-comp.rs +++ b/examples/hrtim/flt-comp.rs @@ -116,7 +116,7 @@ fn main() -> ! { // ----------------------------------------- -------------------------- // . . . * . . // . . . * . . - let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp + let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1, ..) = dp .HRTIM_TIMA .pwm_advanced(pin_a, &mut rcc) .prescaler(prescaler) diff --git a/examples/hrtim/flt.rs b/examples/hrtim/flt.rs index d95ca8b4..a1a6879e 100644 --- a/examples/hrtim/flt.rs +++ b/examples/hrtim/flt.rs @@ -82,7 +82,7 @@ fn main() -> ! { // ----------------------------------------- -------------------------- // . . . * . . // . . . * . . - let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1) = dp + let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1, ..) = dp .HRTIM_TIMA .pwm_advanced(pin_a, &mut rcc) .prescaler(prescaler) diff --git a/examples/hrtim/hrtim.rs b/examples/hrtim/hrtim.rs index c81555da..b29ceffe 100644 --- a/examples/hrtim/hrtim.rs +++ b/examples/hrtim/hrtim.rs @@ -77,7 +77,7 @@ fn main() -> ! { let (hr_control, ..) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); let mut hr_control = hr_control.constrain(); - let (mut timer, (mut cr1, _cr2, _cr3, _cr4), (mut out1, mut out2)) = dp + let (mut timer, (mut cr1, _cr2, _cr3, _cr4), (mut out1, mut out2), ..) = dp .HRTIM_TIMA .pwm_advanced((pin_a, pin_b), &mut rcc) .prescaler(prescaler) diff --git a/examples/hrtim/master.rs b/examples/hrtim/master.rs index 2037a9b6..a74dafff 100644 --- a/examples/hrtim/master.rs +++ b/examples/hrtim/master.rs @@ -76,7 +76,7 @@ fn main() -> ! { let (hr_control, ..) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration(); let mut hr_control = hr_control.constrain(); - let (mut timer, (mut cr1, _cr2, _cr3, _cr4), (mut out1, mut out2)) = dp + let (mut timer, (mut cr1, _cr2, _cr3, _cr4), (mut out1, mut out2), ..) = dp .HRTIM_TIMA .pwm_advanced((pin_a, pin_b), &mut rcc) .prescaler(prescaler) @@ -88,7 +88,7 @@ fn main() -> ! { .timer_mode(HrTimerMode::SingleShotRetriggerable) .finalize(&mut hr_control); - let (mut mtimer, (mut mcr1, _mcr2, _mcr3, _mcr4)) = dp + let (mut mtimer, (mut mcr1, _mcr2, _mcr3, _mcr4), ..) = dp .HRTIM_MASTER .pwm_advanced((), &mut rcc) .prescaler(prescaler) diff --git a/src/hrtim/capture.rs b/src/hrtim/capture.rs index b3df231b..35b505c4 100644 --- a/src/hrtim/capture.rs +++ b/src/hrtim/capture.rs @@ -1,3 +1,4 @@ +use super::timer; use crate::dma::mux::DmaMuxResources; use crate::dma::traits::TargetAddress; use crate::dma::PeripheralToMemory; @@ -123,7 +124,8 @@ macro_rules! impl_capture { tim.$dier.modify(|_r, w| w.$cptXie().bit(enable)); } - pub fn enable_dma(self) -> HrCapt<$TIMX, PSCL, $CH, Dma> { + 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 { diff --git a/src/hrtim/mod.rs b/src/hrtim/mod.rs index c337269c..92fbc73f 100644 --- a/src/hrtim/mod.rs +++ b/src/hrtim/mod.rs @@ -592,14 +592,15 @@ macro_rules! hrtim_hal { pub fn finalize(self, _control: &mut HrPwmControl) -> ( HrTim<$TIMX, PSCL, HrCapt<$TIMX, PSCL, capture::Ch1, capture::NoDma>, - HrCapt<$TIMX, PSCL, capture::Ch2, capture::NoDma>>, - ( + HrCapt<$TIMX, PSCL, capture::Ch2, capture::NoDma> + >, ( HrCr1<$TIMX, PSCL>, HrCr2<$TIMX, PSCL>, HrCr3<$TIMX, PSCL>, HrCr4<$TIMX, PSCL> ), - OUT + OUT, + timer::DmaChannel<$TIMX>, ) { hrtim_finalize_body!( @@ -754,7 +755,9 @@ macro_rules! hrtim_hal_master { HrCr2<$TIMX, PSCL>, HrCr3<$TIMX, PSCL>, HrCr4<$TIMX, PSCL> - )) { + ), + timer::DmaChannel<$TIMX>, + ) { hrtim_finalize_body!(self, MasterPreloadSource, $TIMX: ($timXcr, $ck_psc, $perXr, $perx, $tXcen, $rep, $rep, $dier, $repie),) } diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs index 1adb5301..9eee991d 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -16,6 +16,13 @@ pub struct HrTim { capture_ch2: CPT2, } +/// This is the DMA channel of a HRTIM timer +/// +/// Every HRTIM timer including the master timer has a DMA channel +pub struct DmaChannel { + _x: PhantomData, +} + pub trait HrTimer { type Timer; type Prescaler: HrtimPrescaler; From 352cada1012ccab31a1bdfd00f1ccf8a04622336 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Apr 2024 18:24:34 +0200 Subject: [PATCH 76/88] HRTIM - Fix error in --- src/hrtim/capture.rs | 10 +++++----- src/hrtim/timer.rs | 4 ++++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/hrtim/capture.rs b/src/hrtim/capture.rs index 35b505c4..f54dfd42 100644 --- a/src/hrtim/capture.rs +++ b/src/hrtim/capture.rs @@ -50,12 +50,12 @@ pub trait HrCapture { /// <-------------- 0 --------------> t /// Negative result | positive result /// ```` - fn get_signed(&self) -> i32 { + fn get_signed(&self, period: u16) -> i32 { let (value, dir) = self.get(); match dir { CountingDirection::Up => i32::from(value), - CountingDirection::Down => -i32::from(value), + CountingDirection::Down => i32::from(period) - i32::from(value), } } @@ -66,18 +66,18 @@ pub trait HrCapture { pub fn dma_value_to_dir_and_value(x: u32) -> (u16, CountingDirection) { let value = (x & 0xFFFF) as u16; - match x & 1 << 16 != 0 { + match x & (1 << 16) != 0 { true => (value, CountingDirection::Down), false => (value, CountingDirection::Up), } } -pub fn dma_value_to_signed(x: u32) -> i32 { +pub fn dma_value_to_signed(x: u32, period: u16) -> i32 { let (value, dir) = dma_value_to_dir_and_value(x); match dir { CountingDirection::Up => i32::from(value), - CountingDirection::Down => -i32::from(value), + CountingDirection::Down => i32::from(period) - i32::from(value), } } diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs index 9eee991d..1afd7232 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -30,6 +30,10 @@ pub trait HrTimer { /// Get period of timer in number of ticks /// /// This is also the maximum duty usable for `HrCompareRegister::set_duty` + /// + /// NOTE: The effective period in number of ticks will be twice as large as + /// returned by this function when running in UpDown mode or PushPull mode. + /// 4 times as large when having both modes active fn get_period(&self) -> u16; /// Set period of timer in number of ticks From da19e8f253a5d8a4d5edabfd80aaa2ac75b8a4c4 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 7 May 2024 18:45:48 +0200 Subject: [PATCH 77/88] HRTIM - Fix bugs in capture module with get_signed and some restructurings --- src/hrtim/adc_trigger.rs | 3 ++ src/hrtim/capture.rs | 78 ++++++++++++++++++++++++++++++++++++---- src/hrtim/timer.rs | 22 +++++++----- 3 files changed, 89 insertions(+), 14 deletions(-) diff --git a/src/hrtim/adc_trigger.rs b/src/hrtim/adc_trigger.rs index 2782c10e..6238501f 100644 --- a/src/hrtim/adc_trigger.rs +++ b/src/hrtim/adc_trigger.rs @@ -16,5 +16,8 @@ pub trait Adc6810Trigger { const BITS: u32; } +/// Handle to timers reset/roll-over event pub struct TimerReset(pub(crate) PhantomData); + +/// Handle to timers period event pub struct TimerPeriod(pub(crate) PhantomData); diff --git a/src/hrtim/capture.rs b/src/hrtim/capture.rs index f54dfd42..5b08dcda 100644 --- a/src/hrtim/capture.rs +++ b/src/hrtim/capture.rs @@ -31,8 +31,72 @@ pub trait CaptureEvent { const BITS: u32; } +/// Trait for capture channels used for capturing edges +/// +/// ``` +/// let capture: HrCapt<_, _, _> = todo!(); +/// if capture.is_pending() { +/// let (value, dir) = capture.get_last(); +/// capture.clear_interrupt(); +/// defmt::info!("Edge captured at counter value: {}, with: {}", value, dir); +/// } +/// ``` +/// +/// or alternatively +/// +/// ``` +/// let capture: HrCapt<_, _, _> = todo!(); +/// if let Some((value, dir)) = capture.get() { +/// defmt::info!("Edge captured at counter value: {}, with: {}", value, dir); +/// } +/// ``` pub trait HrCapture { - fn get(&self) -> (u16, CountingDirection); + /// Try to get the capture value + /// + /// Returns none if edge has been captured since last time + /// + /// NOTE: This function will use [`Self::is_pending`] to chech if there is a value available and + /// [`Self::clear_interrupt`] to clear it. + fn get(&mut self) -> Option<(u16, CountingDirection)> { + if self.is_pending() { + let value = self.get_last(); + self.clear_interrupt(); + Some(value) + } else { + None + } + } + + /// Get number of ticks relative to beginning of upcounting + /// + /// where captures during down counting count as negative (before the upcount) + /// + /// ```txt + /// Counter + /// ---------------------------------- <--- period + /// \ ^ / + /// \ | / + /// \ | / + /// \ | / + /// Down count \ | / Up count + /// \|/ + /// <-------------- 0 --------------> t + /// Negative result | positive result + /// ``` + /// + /// NOTE: This function will use [`Self::is_pending`] to chech if there is a value available and + /// [`Self::clear_interrupt`] to clear it. + fn get_signed(&mut self, period: u16) -> Option { + if self.is_pending() { + let value = self.get_last_signed(period); + self.clear_interrupt(); + Some(value) + } else { + None + } + } + + fn get_last(&self) -> (u16, CountingDirection); /// Get number of ticks relative to beginning of upcounting /// @@ -50,12 +114,13 @@ pub trait HrCapture { /// <-------------- 0 --------------> t /// Negative result | positive result /// ```` - fn get_signed(&self, period: u16) -> i32 { - let (value, dir) = self.get(); + fn get_last_signed(&self, period: u16) -> i32 { + let (value, dir) = self.get_last(); + // The capture counter always counts up and restarts at period match dir { CountingDirection::Up => i32::from(value), - CountingDirection::Down => i32::from(period) - i32::from(value), + CountingDirection::Down => i32::from(value) - i32::from(period), } } @@ -75,9 +140,10 @@ pub fn dma_value_to_dir_and_value(x: u32) -> (u16, CountingDirection) { pub fn dma_value_to_signed(x: u32, period: u16) -> i32 { let (value, dir) = dma_value_to_dir_and_value(x); + // The capture counter always counts up and restarts at period match dir { CountingDirection::Up => i32::from(value), - CountingDirection::Down => i32::from(period) - i32::from(value), + CountingDirection::Down => i32::from(value) - i32::from(period), } } @@ -135,7 +201,7 @@ macro_rules! impl_capture { } impl HrCapture for HrCapt<$TIMX, PSCL, $CH, DMA> { - fn get(&self) -> (u16, CountingDirection) { + fn get_last(&self) -> (u16, CountingDirection) { let tim = unsafe { &*$TIMX::ptr() }; let data = tim.$cptXYr.read(); diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs index 1afd7232..fabc6887 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -4,7 +4,7 @@ use crate::stm32::{ use core::marker::PhantomData; use super::{ - capture::{self, HrCapt}, + capture::{self, HrCapt, HrCapture}, control::HrPwmControl, HrtimPrescaler, }; @@ -52,7 +52,7 @@ pub trait HrTimer { fn clear_repetition_interrupt(&mut self); - /// Make a handle to this timers reset event to use as adc trigger + /// Make a handle to this timers reset/roll-over event to use as adc trigger fn as_reset_adc_trigger(&self) -> super::adc_trigger::TimerReset; /// Make a handle to this timers period event to use as adc trigger @@ -60,8 +60,8 @@ pub trait HrTimer { } pub trait HrSlaveTimer: HrTimer { - type CaptureCh1; - type CaptureCh2; + type CptCh1; + type CptCh2; /// Start listening to the specified event fn enable_reset_event>( @@ -78,8 +78,11 @@ pub trait HrSlaveTimer: HrTimer { /// Trait for unsplit slave timer which still contains its capture modules pub trait HrSlaveTimerCpt: HrSlaveTimer { - fn capture_ch1(&mut self) -> &mut ::CaptureCh1; - fn capture_ch2(&mut self) -> &mut ::CaptureCh2; + type CaptureCh1: HrCapture; + type CaptureCh2: HrCapture; + + fn capture_ch1(&mut self) -> &mut ::CaptureCh1; + fn capture_ch2(&mut self) -> &mut ::CaptureCh2; fn split_capture( self, ) -> ( @@ -179,8 +182,8 @@ macro_rules! hrtim_timer { $( impl HrSlaveTimer for HrTim<$TIMX, PSCL, CPT1, CPT2> { - type CaptureCh1 = HrCapt; - type CaptureCh2 = HrCapt; + type CptCh1 = HrCapt; + type CptCh2 = HrCapt; /// Reset this timer every time the specified event occurs /// @@ -212,6 +215,9 @@ macro_rules! hrtim_timer { } 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 From f0507de63075997a718cdc999b89392077fdd01a Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 7 May 2024 18:46:26 +0200 Subject: [PATCH 78/88] HRTIM - Wrong type in AdcTrigger impl for TimerPeriod and TimerReset --- src/hrtim/timer.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs index fabc6887..42d27123 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -273,11 +273,11 @@ macro_rules! hrtim_timer_adc_trigger { ])),+] ),+) => { $($( - $(impl $AdcTrigger for super::adc_trigger::TimerReset> { + $(impl $AdcTrigger for super::adc_trigger::TimerReset<$TIMX> { const BITS: u32 = $adc_trigger_bits_reset; })* - $(impl $AdcTrigger for super::adc_trigger::TimerPeriod> { + $(impl $AdcTrigger for super::adc_trigger::TimerPeriod<$TIMX> { const BITS: u32 = $adc_trigger_bits_period; })* )*)* From 516b246529bd09791f318a8bede7ae32e8687af7 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 19 Jun 2024 17:17:28 +0200 Subject: [PATCH 79/88] HRTIM - Multiple changes * Allow disabling update of shadow registers * Add `control` member to HrPwmControl * HRTIM now has its own `FaultMonitor` trait --- src/hrtim/control.rs | 17 +++++++++++ src/hrtim/fault.rs | 43 ++++++++++++++++++--------- src/hrtim/output.rs | 14 +++++++++ src/hrtim/timer.rs | 69 ++++++++++++++++++++++++++++++++++---------- src/serial/usart.rs | 3 +- 5 files changed, 116 insertions(+), 30 deletions(-) diff --git a/src/hrtim/control.rs b/src/hrtim/control.rs index bcb1414b..16b022b9 100644 --- a/src/hrtim/control.rs +++ b/src/hrtim/control.rs @@ -186,6 +186,7 @@ impl HrTimCalibrated { pub fn constrain(self) -> HrPwmControl { HrPwmControl { _x: PhantomData, + control: HrPwmCtrl { _x: PhantomData }, fault_sys: FltMonitorSys { _x: PhantomData }, fault_1: FltMonitor1 { _x: PhantomData }, fault_2: FltMonitor2 { _x: PhantomData }, @@ -208,9 +209,25 @@ impl HrTimCalibrated { } } +impl<'a> Into<&'a mut HrPwmCtrl> for &'a mut HrPwmControl { + fn into(self) -> &'a mut HrPwmCtrl { + &mut self.control + } +} + +/// Used as a token to guarantee unique access to resources common to multiple timers +/// +/// An instance of this object can be obtained from [`HrPwmControl`].control +pub struct HrPwmCtrl { + _x: PhantomData<()>, +} + +/// Used as a token to guarantee unique access to resources common to multiple timers pub struct HrPwmControl { _x: PhantomData<()>, + pub control: HrPwmCtrl, + pub fault_sys: FltMonitorSys, pub fault_1: FltMonitor1, pub fault_2: FltMonitor2, diff --git a/src/hrtim/fault.rs b/src/hrtim/fault.rs index 17fdd34d..ecea174c 100644 --- a/src/hrtim/fault.rs +++ b/src/hrtim/fault.rs @@ -6,9 +6,24 @@ use crate::gpio::gpiob::{PB0, PB10, PB11}; use crate::gpio::gpioc::{PC10, PC7}; use crate::gpio::{self, AF13, AF3}; use crate::hrtim::control::HrPwmControl; -use crate::pwm::FaultMonitor; use crate::stm32::HRTIM_COMMON; +use super::control::HrPwmCtrl; + +/// Allows a FaultMonitor to monitor faults +pub trait FaultMonitor { + fn enable_interrupt(&mut self, hr_control: &mut HrPwmCtrl); + + /// Returns true if a fault is preventing PWM output + fn is_fault_active(&self) -> bool; + + /// Clear the fault interrupt flag + /// + /// This will *NOT* resume normal PWM operation. The affected outputs need to be re-enabled to resume operation; + /// This will do nothing if the fault is still active. + fn clear_fault(&mut self); +} + pub enum FaultAction { /// Output never enters fault mode None = 0b00, @@ -227,12 +242,17 @@ pub enum FaultSamplingFilter { } macro_rules! impl_flt_monitor { - ($($t:ident: ($fltx:ident, $fltxc:ident),)+) => {$( + ($($t:ident: ($fltx:ident, $fltxc:ident, $fltxie:ident),)+) => {$( pub struct $t { pub(crate) _x: PhantomData<()> } impl FaultMonitor for $t { + fn enable_interrupt(&mut self, _hr_control: &mut HrPwmCtrl) { + let common = unsafe { &*HRTIM_COMMON::ptr() }; + common.ier.modify(|_r, w| w.$fltxie().set_bit()); + } + fn is_fault_active(&self) -> bool { let common = unsafe { &*HRTIM_COMMON::ptr() }; common.isr.read().$fltx().bit() @@ -242,21 +262,16 @@ macro_rules! impl_flt_monitor { let common = unsafe { &*HRTIM_COMMON::ptr() }; common.icr.write(|w| w.$fltxc().set_bit()); } - - // TODO: Should we have our own trait since it does not seem possible to implement this - fn set_fault(&mut self) { - todo!() - } } )+}; } impl_flt_monitor!( - FltMonitorSys: (sysflt, sysfltc), - FltMonitor1: (flt1, flt1c), - FltMonitor2: (flt2, flt2c), - FltMonitor3: (flt3, flt3c), - FltMonitor4: (flt4, flt4c), - FltMonitor5: (flt5, flt5c), - FltMonitor6: (flt6, flt6c), + FltMonitorSys: (sysflt, sysfltc, sysflte), + FltMonitor1: (flt1, flt1c, flt1ie), + FltMonitor2: (flt2, flt2c, flt2ie), + FltMonitor3: (flt3, flt3c, flt3ie), + FltMonitor4: (flt4, flt4c, flt4ie), + FltMonitor5: (flt5, flt5c, flt5ie), + FltMonitor6: (flt6, flt6c, flt6ie), ); diff --git a/src/hrtim/output.rs b/src/hrtim/output.rs index b74d6d72..7b60cb00 100644 --- a/src/hrtim/output.rs +++ b/src/hrtim/output.rs @@ -121,6 +121,20 @@ pub enum State { Fault, } +impl State { + pub fn is_idle(self) -> bool { + matches!(self, State::Idle) + } + + pub fn is_running(self) -> bool { + matches!(self, State::Running) + } + + pub fn is_fault(self) -> bool { + matches!(self, State::Fault) + } +} + pub unsafe trait ToHrOut { type Out: ToHrOut; } diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs index 42d27123..4e162b3d 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -5,7 +5,7 @@ use core::marker::PhantomData; use super::{ capture::{self, HrCapt, HrCapture}, - control::HrPwmControl, + control::HrPwmCtrl, HrtimPrescaler, }; @@ -42,13 +42,13 @@ pub trait HrTimer { fn set_period(&mut self, period: u16); /// Start timer - fn start(&mut self, _hr_control: &mut HrPwmControl); + fn start(&mut self, _hr_control: &mut HrPwmCtrl); /// Stop timer - fn stop(&mut self, _hr_control: &mut HrPwmControl); + fn stop(&mut self, _hr_control: &mut HrPwmCtrl); /// Stop timer and reset counter - fn stop_and_reset(&mut self, _hr_control: &mut HrPwmControl); + fn stop_and_reset(&mut self, _hr_control: &mut HrPwmCtrl); fn clear_repetition_interrupt(&mut self); @@ -57,6 +57,21 @@ pub trait HrTimer { /// Make a handle to this timers period event to use as adc trigger fn as_period_adc_trigger(&self) -> super::adc_trigger::TimerPeriod; + + /// 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); + + /// 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(&mut self, _hr_control: &mut HrPwmCtrl); } pub trait HrSlaveTimer: HrTimer { @@ -106,6 +121,7 @@ macro_rules! hrtim_timer { $repie:ident, $icr:ident, $repc:ident, + $tXudis:ident, $(($rstXr:ident))*, )+) => {$( impl HrTimer for HrTim<$TIMX, PSCL, CPT1, CPT2> { @@ -124,7 +140,7 @@ macro_rules! hrtim_timer { } /// Start timer - fn start(&mut self, _hr_control: &mut HrPwmControl) { + fn start(&mut self, _hr_control: &mut HrPwmCtrl) { // Start timer // SAFETY: Since we hold _hr_control there is no risk for a race condition @@ -133,7 +149,7 @@ macro_rules! hrtim_timer { } /// Stop timer - fn stop(&mut self, _hr_control: &mut HrPwmControl) { + 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() }; @@ -141,7 +157,7 @@ macro_rules! hrtim_timer { } /// Stop timer and reset counter - fn stop_and_reset(&mut self, _hr_control: &mut HrPwmControl) { + fn stop_and_reset(&mut self, _hr_control: &mut HrPwmCtrl) { self.stop(_hr_control); // Reset counter @@ -164,6 +180,29 @@ macro_rules! hrtim_timer { tim.$icr.write(|w| w.$repc().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(|_r, w| w.$tXudis().clear_bit()); + } } impl HrTim<$TIMX, PSCL, CPT1, CPT2> { @@ -290,14 +329,14 @@ use super::adc_trigger::Adc579Trigger as Adc579; use super::adc_trigger::Adc6810Trigger as Adc6810; hrtim_timer! { - HRTIM_MASTER: mcntr, mcnt, mper, mcen, mper, mrep, mrep, mdier, mrepie, micr, mrepc,, - - HRTIM_TIMA: cntar, cntx, perar, tacen, perx, repar, repx, timadier, repie, timaicr, repc, (rstar), - HRTIM_TIMB: cntr, cntx, perbr, tbcen, perx, repbr, repx, timbdier, repie, timbicr, repc, (rstbr), - HRTIM_TIMC: cntcr, cntx, percr, tccen, perx, repcr, repx, timcdier, repie, timcicr, repc, (rstcr), - HRTIM_TIMD: cntdr, cntx, perdr, tdcen, perx, repdr, repx, timddier, repie, timdicr, repc, (rstdr), - HRTIM_TIME: cnter, cntx, perer, tecen, perx, reper, repx, timedier, repie, timeicr, repc, (rster), - HRTIM_TIMF: cntfr, cntx, perfr, tfcen, perx, repfr, repx, timfdier, repie, timficr, repc, (rstfr), + HRTIM_MASTER: mcntr, mcnt, mper, mcen, mper, mrep, mrep, mdier, mrepie, micr, mrepc, mudis,, + + HRTIM_TIMA: cntar, cntx, perar, tacen, perx, repar, repx, timadier, repie, timaicr, repc, taudis, (rstar), + HRTIM_TIMB: cntr, cntx, perbr, tbcen, perx, repbr, repx, timbdier, repie, timbicr, repc, tbudis, (rstbr), + HRTIM_TIMC: cntcr, cntx, percr, tccen, perx, repcr, repx, timcdier, repie, timcicr, repc, tcudis, (rstcr), + HRTIM_TIMD: cntdr, cntx, perdr, tdcen, perx, repdr, repx, timddier, repie, timdicr, repc, tdudis, (rstdr), + HRTIM_TIME: cnter, cntx, perer, tecen, perx, reper, repx, timedier, repie, timeicr, repc, teudis, (rster), + HRTIM_TIMF: cntfr, cntx, perfr, tfcen, perx, repfr, repx, timfdier, repie, timficr, repc, tfudis, (rstfr), } hrtim_timer_adc_trigger! { diff --git a/src/serial/usart.rs b/src/serial/usart.rs index bd9ccc92..139ddfbe 100644 --- a/src/serial/usart.rs +++ b/src/serial/usart.rs @@ -360,7 +360,8 @@ macro_rules! uart_shared { let config = crate::dma::config::DmaConfig::default() .transfer_complete_interrupt(false) .circular_buffer(false) - .memory_increment(true); + .memory_increment(true) + .priority(crate::dma::config::Priority::Low); stream.apply_config(config); Tx { From 4f6ac37c081af0cdbda6473429964cab52202f7d Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 19 Jun 2024 17:23:38 +0200 Subject: [PATCH 80/88] Use stm32g4 from gitea registry --- Cargo.toml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 845e2d9e..92265ae0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT/Apache-2.0" name = "stm32g4xx-hal" readme = "README.md" repository = "https://github.com/stm32-rs/stm32g4xx-hal" -version = "0.0.2" +version = "0.0.3-alpha.0" [dependencies] nb = "0.1.1" @@ -128,6 +128,16 @@ name = "hrtim-adc-trigger" required-features = ["hrtim"] path = "examples/hrtim/adc-trigger.rs" +[[example]] +name = "hrtim-capture-dma" +required-features = ["hrtim"] +path = "examples/hrtim/capture-dma.rs" + +[[example]] +name = "hrtim-capture-dma-up-down" +required-features = ["hrtim"] +path = "examples/hrtim/capture-dma-up-down.rs" + [[example]] name = "hrtim-capture" required-features = ["hrtim"] @@ -153,6 +163,11 @@ name = "hrtim-flt" required-features = ["hrtim"] path = "examples/hrtim/flt.rs" +[[example]] +name = "hrtim-flt-up-down-push-pull" +required-features = ["hrtim"] +path = "examples/hrtim/flt-up-down-push-pull.rs" + [[example]] name = "hrtim" required-features = ["hrtim"] From 8b9c0c9b7ddd9286040aa9f7b1f09bf57a68b026 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 26 Jun 2024 11:09:47 +0200 Subject: [PATCH 81/88] HRTIM - Make sure output pins are not set to alternate mode intil end of init This ensures there is no sporadic output at the pins. This is a breaking change and does change and clean up quite a lot of things. Examples will need to be updated. --- Cargo.toml | 7 +- src/hrtim/external_event.rs | 5 - src/hrtim/mod.rs | 214 +++++------------------------------- src/hrtim/output.rs | 84 +++++++------- 4 files changed, 68 insertions(+), 242 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 92265ae0..aef214e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -176,9 +176,4 @@ path = "examples/hrtim/hrtim.rs" [[example]] name = "hrtim-master" required-features = ["hrtim"] -path = "examples/hrtim/master.rs" - -[[example]] -name = "hrtim-simple" -required-features = ["hrtim"] -path = "examples/hrtim/simple.rs" +path = "examples/hrtim/master.rs" \ No newline at end of file diff --git a/src/hrtim/external_event.rs b/src/hrtim/external_event.rs index 2389dc3a..c97cb806 100644 --- a/src/hrtim/external_event.rs +++ b/src/hrtim/external_event.rs @@ -240,11 +240,6 @@ pub trait ToExternalEventSource { fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource; } -#[derive(Copy, Clone)] -struct ExternalEventMuxOut { - _x: PhantomData<()>, -} - macro_rules! impl_eev1_5_to_es { ($eev:ident, $N:literal, $eeXsrc:ident, $eeXpol:ident, $eeXsns:ident, $eeXfast:ident) => { impl ExternalEventBuilder1To5 for SourceBuilder<$N, IS_FAST> {} diff --git a/src/hrtim/mod.rs b/src/hrtim/mod.rs index 92fbc73f..ba3df712 100644 --- a/src/hrtim/mod.rs +++ b/src/hrtim/mod.rs @@ -26,12 +26,10 @@ use fugit::HertzU64; use self::control::HrPwmControl; use self::deadtime::DeadtimeConfig; -use self::output::{HrtimChannel, ToHrOut, CH1, CH2}; +use self::output::ToHrOut; use self::timer_eev_cfg::EevCfgs; -use crate::pwm::{ - self, Alignment, ComplementaryImpossible, Pins, Polarity, Pwm, PwmPinEnable, TimerType, -}; +use crate::pwm::{self, Alignment, Polarity, TimerType}; use crate::rcc::{GetBusFreq, Rcc}; use crate::time::Hertz; @@ -152,41 +150,23 @@ pub enum InterleavedMode { Quad, } -// HrPwmExt trait -/// Allows the pwm() method to be added to the peripheral register structs from the device crate -pub trait HrPwmExt: Sized { - /// The requested frequency will be rounded to the nearest achievable frequency; the actual frequency may be higher or lower than requested. - fn pwm( - self, - _pins: PINS, - frequency: T, - control: &mut HrPwmControl, - rcc: &mut Rcc, - ) -> PINS::Channel - where - PINS: Pins + ToHrOut, - T: Into, - U: HrtimChannel; -} - pub trait HrPwmAdvExt: Sized { type PreloadSource; - fn pwm_advanced( + fn pwm_advanced( self, _pins: PINS, rcc: &mut Rcc, - ) -> HrPwmBuilder> + ) -> HrPwmBuilder where - PINS: Pins + ToHrOut, - CHANNEL: HrtimChannel; + PINS: ToHrOut; } /// HrPwmBuilder is used to configure advanced HrTim PWM features -pub struct HrPwmBuilder { +pub struct HrPwmBuilder { _tim: PhantomData, _prescaler: PhantomData, - _out: PhantomData, + pins: PINS, timer_mode: HrTimerMode, counting_direction: HrCountingDirection, base_freq: HertzU64, @@ -368,6 +348,9 @@ macro_rules! hrtim_finalize_body { //let master = unsafe { &*HRTIM_MASTER::ptr() }; //master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); + // Connect pins and let HRTIM take over control over them + $this.pins.connect_to_hrtim(); + unsafe { MaybeUninit::uninit().assume_init() } @@ -421,17 +404,14 @@ macro_rules! hrtim_common_methods { } /// Set the prescaler; PWM count runs at base_frequency/(prescaler+1) - pub fn prescaler

( - self, - _prescaler: P, - ) -> HrPwmBuilder<$TIMX, P, $PS, ::Out

> + pub fn prescaler

(self, _prescaler: P) -> HrPwmBuilder<$TIMX, P, $PS, PINS> where P: HrtimPrescaler, { let HrPwmBuilder { _tim, _prescaler: _, - _out, + pins, timer_mode, fault_enable_bits, fault1_bits, @@ -460,7 +440,7 @@ macro_rules! hrtim_common_methods { HrPwmBuilder { _tim, _prescaler: PhantomData, - _out: PhantomData, + pins, timer_mode, fault_enable_bits, fault1_bits, @@ -521,38 +501,16 @@ macro_rules! hrtim_hal { ($($TIMX:ident: ($timXcr:ident, $timXcr2:ident, $perXr:ident, $tXcen:ident, $rep:ident, $repx:ident, $dier:ident, $repie:ident, $fltXr:ident, $eefXr1:ident, $eefXr2:ident, $Xeefr3:ident, $outXr:ident, $dtXr:ident),)+) => { $( - - // Implement HrPwmExt trait for hrtimer - impl HrPwmExt for $TIMX { - fn pwm( - self, - pins: PINS, - frequency: T, - control: &mut HrPwmControl, - rcc: &mut Rcc, - ) -> PINS::Channel - where - PINS: Pins + ToHrOut, - T: Into, - U: HrtimChannel, - { - let _= self.pwm_advanced(pins, rcc).frequency(frequency).finalize(control); - - unsafe { MaybeUninit::::uninit().assume_init() } - } - } - impl HrPwmAdvExt for $TIMX { type PreloadSource = PreloadSource; - fn pwm_advanced( + fn pwm_advanced( self, - _pins: PINS, + pins: PINS, rcc: &mut Rcc, - ) -> HrPwmBuilder> + ) -> HrPwmBuilder where - PINS: Pins + ToHrOut, - CHANNEL: HrtimChannel + PINS: ToHrOut<$TIMX>, { // TODO: That 32x factor... Is that included below, or should we // do that? Also that will likely risk overflowing u32 since @@ -562,7 +520,7 @@ macro_rules! hrtim_hal { HrPwmBuilder { _tim: PhantomData, _prescaler: PhantomData, - _out: PhantomData, + pins, timer_mode: HrTimerMode::Continuous, fault_enable_bits: 0b000000, fault1_bits: 0b00, @@ -583,11 +541,11 @@ macro_rules! hrtim_hal { } } - impl - HrPwmBuilder<$TIMX, PSCL, PreloadSource, OUT> + impl + HrPwmBuilder<$TIMX, PSCL, PreloadSource, PINS> where PSCL: HrtimPrescaler, - OUT: ToHrOut, + PINS: ToHrOut<$TIMX>, { pub fn finalize(self, _control: &mut HrPwmControl) -> ( HrTim<$TIMX, PSCL, @@ -599,7 +557,7 @@ macro_rules! hrtim_hal { HrCr3<$TIMX, PSCL>, HrCr4<$TIMX, PSCL> ), - OUT, + PINS::Out, timer::DmaChannel<$TIMX>, ) { @@ -702,14 +660,13 @@ macro_rules! hrtim_hal_master { impl HrPwmAdvExt for $TIMX { type PreloadSource = MasterPreloadSource; - fn pwm_advanced( + fn pwm_advanced( self, - _pins: PINS, + pins: PINS, rcc: &mut Rcc, - ) -> HrPwmBuilder> + ) -> HrPwmBuilder where - PINS: Pins + ToHrOut, // TODO: figure out - CHANNEL: HrtimChannel + PINS: ToHrOut<$TIMX>, { // TODO: That 32x factor... Is that included below, or should we // do that? Also that will likely risk overflowing u32 since @@ -719,7 +676,7 @@ macro_rules! hrtim_hal_master { HrPwmBuilder { _tim: PhantomData, _prescaler: PhantomData, - _out: PhantomData, + pins, timer_mode: HrTimerMode::Continuous, fault_enable_bits: 0b000000, fault1_bits: 0b00, @@ -740,11 +697,11 @@ macro_rules! hrtim_hal_master { } } - impl - HrPwmBuilder<$TIMX, PSCL, MasterPreloadSource, OUT> + impl + HrPwmBuilder<$TIMX, PSCL, MasterPreloadSource, PINS> where PSCL: HrtimPrescaler, - OUT: ToHrOut, + PINS: ToHrOut<$TIMX>, { pub fn finalize(self, _control: &mut HrPwmControl) -> ( HrTim<$TIMX, PSCL, @@ -767,97 +724,6 @@ macro_rules! hrtim_hal_master { )*} } -macro_rules! hrtim_pin_hal { - ($($TIMX:ident: - ($CH:ident, $perXr:ident, $cmpXYr:ident, $cmpYx:ident, $cmpY:ident, $tXYoen:ident, $tXYodis:ident),)+ - ) => { - $( - impl hal::PwmPin for Pwm<$TIMX, $CH, COMP, POL, NPOL> - where Pwm<$TIMX, $CH, COMP, POL, NPOL>: PwmPinEnable { - type Duty = u16; - - // You may not access self in the following methods! - // See unsafe above - - fn disable(&mut self) { - self.ccer_disable(); - } - - fn enable(&mut self) { - self.ccer_enable(); - } - - fn get_duty(&self) -> Self::Duty { - let tim = unsafe { &*$TIMX::ptr() }; - - tim.$cmpXYr.read().$cmpYx().bits() - } - - fn get_max_duty(&self) -> Self::Duty { - let tim = unsafe { &*$TIMX::ptr() }; - - let arr = tim.$perXr.read().perx().bits(); - - // One PWM cycle is ARR+1 counts long - // Valid PWM duty cycles are 0 to ARR+1 - // However, if ARR is 65535 on a 16-bit timer, we can't add 1 - // In that case, 100% duty cycle is not possible, only 65535/65536 - if arr == Self::Duty::MAX { - arr - } - else { - arr + 1 - } - } - - /// Set duty cycle - /// - /// NOTE: Please observe limits(RM0440 "Period and compare registers min and max values"): - /// | Prescaler | Min duty | Max duty | - /// |-----------|----------|----------| - /// | 1 | 0x0060 | 0xFFDF | - /// | 2 | 0x0030 | 0xFFEF | - /// | 4 | 0x0018 | 0xFFF7 | - /// | 8 | 0x000C | 0xFFFB | - /// | 16 | 0x0006 | 0xFFFD | - /// | 32 | 0x0003 | 0xFFFD | - /// | 64 | 0x0003 | 0xFFFD | - /// | 128 | 0x0003 | 0xFFFD | - /// - /// Also, writing 0 as duty is only valid for CR1 and CR3 during a set of - /// specific conditions(see RM0440 "Null duty cycle exception case"): - /// – the output SET event is generated by the PERIOD event - /// – the output RESET if generated by the compare 1 (respectively compare 3) event - /// – the compare 1 (compare 3) event is active within the timer unit itself, and not used - /// for other timing units - fn set_duty(&mut self, duty: Self::Duty) { - let tim = unsafe { &*$TIMX::ptr() }; - - tim.$cmpXYr.write(|w| unsafe { w.$cmpYx().bits(duty) }); - } - } - - // Enable implementation for ComplementaryImpossible - impl PwmPinEnable for Pwm<$TIMX, $CH, ComplementaryImpossible, POL, NPOL> { - fn ccer_enable(&mut self) { - // TODO: Should this part only be in Pwm::enable? - // Enable output Y on channel X - // This is a set-only register, no risk for data race - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.oenr.write(|w| { w.$tXYoen().set_bit() }); - } - fn ccer_disable(&mut self) { - // TODO: Should this part only be in Pwm::disable - // Disable output Y on channel X - // This is a write only register, no risk for data race - let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.odisr.write(|w| { w.$tXYodis().set_bit() }); - } - } - )+ - } -} - hrtim_hal! { HRTIM_TIMA: (timacr, timacr2, perar, tacen, repar, repx, timadier, repie, fltar, eefar1, eefar2, aeefr3, outar, dtar), HRTIM_TIMB: (timbcr, timbcr2, perbr, tbcen, repbr, repx, timbdier, repie, fltbr, eefbr1, eefbr2, beefr3, outbr, dtbr), @@ -871,26 +737,6 @@ hrtim_hal_master! { HRTIM_MASTER: (mcr, ck_psc, mper, mper, mrep, mcen, mdier, mrepie), } -hrtim_pin_hal! { - HRTIM_TIMA: (CH1, perar, cmp1ar, cmp1x, cmp1, ta1oen, ta1odis), - HRTIM_TIMA: (CH2, perar, cmp3ar, cmp3x, cmp3, ta2oen, ta2odis), - - HRTIM_TIMB: (CH1, perbr, cmp1br, cmp1x, cmp1, tb1oen, tb1odis), - HRTIM_TIMB: (CH2, perbr, cmp3br, cmp3x, cmp3, tb2oen, tb2odis), - - HRTIM_TIMC: (CH1, percr, cmp1cr, cmp1x, cmp1, tc1oen, tc1odis), - HRTIM_TIMC: (CH2, percr, cmp3cr, cmp3x, cmp3, tc2oen, tc2odis), - - HRTIM_TIMD: (CH1, perdr, cmp1dr, cmp1x, cmp1, td1oen, td1odis), - HRTIM_TIMD: (CH2, perdr, cmp3dr, cmp3x, cmp3, td2oen, td2odis), - - HRTIM_TIME: (CH1, perer, cmp1er, cmp1x, cmp1, te1oen, te1odis), - HRTIM_TIME: (CH2, perer, cmp3er, cmp3x, cmp3, te2oen, te2odis), - - HRTIM_TIMF: (CH1, perfr, cmp1fr, cmp1x, cmp1, tf1oen, tf1odis), - HRTIM_TIMF: (CH2, perfr, cmp3fr, cmp3x, cmp3, tf2oen, tf2odis), -} - /// # Safety /// Only implement for valid prescalers with correct values pub unsafe trait HrtimPrescaler: Default { diff --git a/src/hrtim/output.rs b/src/hrtim/output.rs index 7b60cb00..5e1e815f 100644 --- a/src/hrtim/output.rs +++ b/src/hrtim/output.rs @@ -4,12 +4,13 @@ use core::marker::PhantomData; use super::event::EventSource; use crate::{ gpio::{ + self, gpioa::{PA10, PA11, PA8, PA9}, gpiob::{PB12, PB13, PB14, PB15}, gpioc::{PC6, PC7, PC8, PC9}, Alternate, AF13, AF3, }, - pwm::{ActiveHigh, ComplementaryImpossible, Pins, Pwm}, + pwm::{ComplementaryImpossible, Pins}, stm32::HRTIM_COMMON, }; @@ -135,25 +136,32 @@ impl State { } } -pub unsafe trait ToHrOut { - type Out: ToHrOut; +pub unsafe trait ToHrOut { + type Out; + + fn connect_to_hrtim(self); } -unsafe impl ToHrOut for (PA, PB) +unsafe impl ToHrOut for (PA, PB) where - PA: ToHrOut, - PB: ToHrOut, + PA: ToHrOut, + PB: ToHrOut, { type Out = (PA::Out, PB::Out); + + fn connect_to_hrtim(self) { + self.0.connect_to_hrtim(); + self.1.connect_to_hrtim(); + } } pub struct HrOut1(PhantomData<(TIM, PSCL)>); pub struct HrOut2(PhantomData<(TIM, PSCL)>); macro_rules! pins { - ($($TIMX:ty: CH1: $CH1:ty, CH2: $CH2:ty)+) => { + ($($TIMX:ty: CH1: $CH1:ident<$CH1_AF:ident>, CH2: $CH2:ident<$CH2_AF:ident>)+) => { $( - impl Pins<$TIMX, CH1, ComplementaryImpossible> for $CH1 { + /*impl Pins<$TIMX, CH1, ComplementaryImpossible> for $CH1 { type Channel = Pwm<$TIMX, CH1, ComplementaryImpossible, ActiveHigh, ActiveHigh>; } @@ -161,72 +169,54 @@ macro_rules! pins { type Channel = Pwm<$TIMX, CH2, ComplementaryImpossible, ActiveHigh, ActiveHigh>; } - unsafe impl ToHrOut for $CH1 { + */ + unsafe impl ToHrOut<$TIMX> for $CH1> { type Out = HrOut1<$TIMX, PSCL>; + + fn connect_to_hrtim(self) { + let _: $CH1> = self.into_alternate(); + } } - unsafe impl ToHrOut for $CH2 { + unsafe impl ToHrOut<$TIMX> for $CH2> { type Out = HrOut2<$TIMX, PSCL>; + + fn connect_to_hrtim(self) { + let _: $CH2> = self.into_alternate(); + } } - unsafe impl ToHrOut for HrOut1<$TIMX, PSCL> { + /*unsafe impl ToHrOut for HrOut1<$TIMX, PSCL> { type Out

= HrOut1<$TIMX, P>; } unsafe impl ToHrOut for HrOut2<$TIMX, PSCL> { type Out

= HrOut2<$TIMX, P>; - } + }*/ )+ } } pins! { - HRTIM_TIMA: CH1: PA8>, CH2: PA9> + HRTIM_TIMA: CH1: PA8, CH2: PA9 - HRTIM_TIMB: CH1: PA10>, CH2: PA11> - HRTIM_TIMC: CH1: PB12>, CH2: PB13> - HRTIM_TIMD: CH1: PB14>, CH2: PB15> + HRTIM_TIMB: CH1: PA10, CH2: PA11 + HRTIM_TIMC: CH1: PB12, CH2: PB13 + HRTIM_TIMD: CH1: PB14, CH2: PB15 - HRTIM_TIME: CH1: PC8>, CH2: PC9> - HRTIM_TIMF: CH1: PC6>, CH2: PC7> + HRTIM_TIME: CH1: PC8, CH2: PC9 + HRTIM_TIMF: CH1: PC6, CH2: PC7 } impl Pins for () { type Channel = (); } -unsafe impl ToHrOut for () { +unsafe impl ToHrOut for () { type Out = (); -} - -// automatically implement Pins trait for tuples of individual pins -macro_rules! pins_tuples { - // Tuple of two pins - ($(($CHA:ident, $CHB:ident)),*) => { - $( - impl Pins, $CHB), (TA, TB)> for (CHA, CHB) - where - CHA: Pins, TA>, - CHB: Pins, TB>, - { - type Channel = (Pwm, TA, ActiveHigh, ActiveHigh>, Pwm, TB, ActiveHigh, ActiveHigh>); - } - impl HrtimChannel for ($CHA, $CHB) {} - )* - }; -} - -pins_tuples! { - (CH1, CH2), - (CH2, CH1) + fn connect_to_hrtim(self) {} } pub struct CH1(PhantomData); pub struct CH2(PhantomData); - -impl HrtimChannel for () {} -pub trait HrtimChannel {} - -impl HrtimChannel for CH1 {} -impl HrtimChannel for CH2 {} From a9947737e0855435ad93cc268a2700228f400f35 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 17 Aug 2024 20:50:00 +0200 Subject: [PATCH 82/88] Revert "Use stm32g4 from gitea registry" This reverts commit 298e6d95ae99e86da64b7e4971d44b44d2b88244. --- Cargo.toml | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index aef214e1..6ceb5c27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT/Apache-2.0" name = "stm32g4xx-hal" readme = "README.md" repository = "https://github.com/stm32-rs/stm32g4xx-hal" -version = "0.0.3-alpha.0" +version = "0.0.2" [dependencies] nb = "0.1.1" @@ -128,16 +128,6 @@ name = "hrtim-adc-trigger" required-features = ["hrtim"] path = "examples/hrtim/adc-trigger.rs" -[[example]] -name = "hrtim-capture-dma" -required-features = ["hrtim"] -path = "examples/hrtim/capture-dma.rs" - -[[example]] -name = "hrtim-capture-dma-up-down" -required-features = ["hrtim"] -path = "examples/hrtim/capture-dma-up-down.rs" - [[example]] name = "hrtim-capture" required-features = ["hrtim"] @@ -163,11 +153,6 @@ name = "hrtim-flt" required-features = ["hrtim"] path = "examples/hrtim/flt.rs" -[[example]] -name = "hrtim-flt-up-down-push-pull" -required-features = ["hrtim"] -path = "examples/hrtim/flt-up-down-push-pull.rs" - [[example]] name = "hrtim" required-features = ["hrtim"] From a42558f0b49e87a2c46f9aa60a04b0084846e2b8 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 17 Aug 2024 22:30:54 +0200 Subject: [PATCH 83/88] Update for new pac --- src/hrtim/capture.rs | 22 ++++++++++---------- src/hrtim/compare_register.rs | 4 ++-- src/hrtim/control.rs | 20 +++++++++--------- src/hrtim/external_event.rs | 6 +++--- src/hrtim/fault.rs | 12 +++++------ src/hrtim/mod.rs | 38 +++++++++++++++++------------------ src/hrtim/output.rs | 16 +++++++-------- src/hrtim/timer.rs | 24 +++++++++++----------- 8 files changed, 71 insertions(+), 71 deletions(-) diff --git a/src/hrtim/capture.rs b/src/hrtim/capture.rs index 5b08dcda..f2081344 100644 --- a/src/hrtim/capture.rs +++ b/src/hrtim/capture.rs @@ -102,7 +102,7 @@ pub trait HrCapture { /// /// where captures during down counting count as negative (before the upcount) /// - /// ```` + /// ``` /// Counter /// ---------------------------------- <--- period /// \ ^ / @@ -113,7 +113,7 @@ pub trait HrCapture { /// \|/ /// <-------------- 0 --------------> t /// Negative result | positive result - /// ```` + /// ``` fn get_last_signed(&self, period: u16) -> i32 { let (value, dir) = self.get_last(); @@ -159,7 +159,7 @@ macro_rules! impl_capture { // SAFETY: We are the only one with access to cptXYcr unsafe { - tim.$cptXYcr.modify(|r, w| w.bits(r.bits() | E::BITS)); + tim.$cptXYcr().modify(|r, w| w.bits(r.bits() | E::BITS)); } } @@ -169,7 +169,7 @@ macro_rules! impl_capture { // SAFETY: We are the only one with access to cptXYcr unsafe { - tim.$cptXYcr.modify(|r, w| w.bits(r.bits() & !E::BITS)); + tim.$cptXYcr().modify(|r, w| w.bits(r.bits() & !E::BITS)); } } @@ -178,7 +178,7 @@ macro_rules! impl_capture { // SAFETY: We are the only one with access to cptXYcr let tim = unsafe { &*$TIMX::ptr() }; - tim.$cptXYcr.modify(|_, w| w.swcpt().set_bit()); + tim.$cptXYcr().modify(|_, w| w.swcpt().set_bit()); } // TODO: It would be sufficient to instead of hr_control only require exclusive access to the owning timer @@ -187,13 +187,13 @@ macro_rules! impl_capture { 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)); + 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()); + tim.$dier().modify(|_r, w| w.$cptXde().set_bit()); HrCapt { _x: PhantomData } @@ -203,7 +203,7 @@ macro_rules! impl_capture { impl HrCapture for HrCapt<$TIMX, PSCL, $CH, DMA> { fn get_last(&self) -> (u16, CountingDirection) { let tim = unsafe { &*$TIMX::ptr() }; - let data = tim.$cptXYr.read(); + let data = tim.$cptXYr().read(); let dir = match data.dir().bit() { true => CountingDirection::Down, @@ -218,14 +218,14 @@ macro_rules! impl_capture { let tim = unsafe { &*$TIMX::ptr() }; // No need for exclusive access since this is a write only register - tim.$icr.write(|w| w.$cptXc().set_bit()); + tim.$icr().write(|w| w.$cptXc().set_bit()); } fn is_pending(&self) -> bool { let tim = unsafe { &*$TIMX::ptr() }; // No need for exclusive access since this is a read only register - tim.$isr.read().$cptX().bit() + tim.$isr().read().$cptX().bit() } } @@ -233,7 +233,7 @@ macro_rules! impl_capture { #[inline(always)] fn address(&self) -> u32 { let tim = unsafe { &*$TIMX::ptr() }; - &tim.$cptXYr as *const _ as u32 + &tim.$cptXYr() as *const _ as u32 } type MemSize = u32; diff --git a/src/hrtim/compare_register.rs b/src/hrtim/compare_register.rs index 8beb4103..1cdaf69c 100644 --- a/src/hrtim/compare_register.rs +++ b/src/hrtim/compare_register.rs @@ -40,12 +40,12 @@ macro_rules! hrtim_cr_helper { fn get_duty(&self) -> u16 { let tim = unsafe { &*$TIMX::ptr() }; - tim.$cmpXYr.read().$cmpYx().bits() + tim.$cmpXYr().read().$cmpYx().bits() } fn set_duty(&mut self, duty: u16) { let tim = unsafe { &*$TIMX::ptr() }; - tim.$cmpXYr.write(|w| unsafe { w.$cmpYx().bits(duty) }); + tim.$cmpXYr().write(|w| unsafe { w.$cmpYx().bits(duty) }); } } diff --git a/src/hrtim/control.rs b/src/hrtim/control.rs index 16b022b9..ccbf7606 100644 --- a/src/hrtim/control.rs +++ b/src/hrtim/control.rs @@ -27,7 +27,7 @@ impl HrControltExt for HRTIM_COMMON { // Start calibration procedure common - .dllcr + .dllcr() .write(|w| w.cal().set_bit().calen().clear_bit()); HrTimOngoingCalibration { @@ -93,12 +93,12 @@ impl HrTimOngoingCalibration { // with f_hrtim at 170MHz, these settings leads to // a period of about 6.2ms common - .dllcr + .dllcr() .modify(|_r, w| w.calrte().bits(0b00).cal().set_bit().calen().clear_bit()); - common.fltinr2.write(|w| w.fltsd().bits(flt_divider as u8)); - common.eecr3.write(|w| w.eevsd().bits(eev_divider as u8)); + common.fltinr2().write(|w| w.fltsd().bits(flt_divider as u8)); + common.eecr3().write(|w| w.eevsd().bits(eev_divider as u8)); - common.adcps1.write(|w| { + common.adcps1().write(|w| { w.adc1psc() .bits(adc_trigger1_postscaler as u8) .adc2psc() @@ -111,7 +111,7 @@ impl HrTimOngoingCalibration { .bits(adc_trigger5_postscaler as u8) }); - common.adcps2.write(|w| { + common.adcps2().write(|w| { w.adc6psc() .bits(adc_trigger6_postscaler as u8) .adc7psc() @@ -130,7 +130,7 @@ impl HrTimOngoingCalibration { pub fn wait_for_calibration(self) -> (HrTimCalibrated, FaultInputs, EevInputs) { let common = unsafe { &*HRTIM_COMMON::ptr() }; - while common.isr.read().dllrdy().bit_is_clear() { + while common.isr().read().dllrdy().bit_is_clear() { // Wait until ready } @@ -259,7 +259,7 @@ macro_rules! impl_adc1234_trigger { pub fn enable_source(&mut self, _trigger: &T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; unsafe { - common.$adcXr.modify(|r, w| w.bits(r.bits() | T::BITS)); + common.$adcXr().modify(|r, w| w.bits(r.bits() | T::BITS)); } } } @@ -288,8 +288,8 @@ macro_rules! impl_adc5678910_trigger { pub fn enable_source(&mut self, _trigger: &T) { let common = unsafe { &*HRTIM_COMMON::ptr() }; common - .adcer - .modify(|_r, w| w.$adcXtrg().variant(T::BITS as u8)); + .adcer() + .modify(|_r, w| unsafe { w.$adcXtrg().bits(T::BITS as u8) }); } } diff --git a/src/hrtim/external_event.rs b/src/hrtim/external_event.rs index c97cb806..ee88262e 100644 --- a/src/hrtim/external_event.rs +++ b/src/hrtim/external_event.rs @@ -281,7 +281,7 @@ macro_rules! impl_eev1_5_to_es { // SAFETY: Thanks to, `HrTimCalibrated`, we know we have exclusive access to the register, // we also know no timers are started. unsafe { - common.eecr1.modify(|_r, w| { + common.eecr1().modify(|_r, w| { w.$eeXsrc() .bits(src_bits) .$eeXpol() @@ -324,7 +324,7 @@ macro_rules! impl_eev6_10_to_es { // SAFETY: Thanks to, `HrTimCalibrated`, we know we have exclusive access to the register, // we also know no timers are started. unsafe { - common.eecr2.modify(|_r, w| { + common.eecr2().modify(|_r, w| { w.$eeXsrc() .bits(src_bits) .$eeXpol() @@ -332,7 +332,7 @@ macro_rules! impl_eev6_10_to_es { .$eeXsns() .bits(edge_or_polarity_bits) }); - common.eecr3.modify(|_r, w| w.$eeXf().bits(filter_bits)); + common.eecr3().modify(|_r, w| w.$eeXf().bits(filter_bits)); } ExternalEventSource { _x: PhantomData } diff --git a/src/hrtim/fault.rs b/src/hrtim/fault.rs index ecea174c..2447c793 100644 --- a/src/hrtim/fault.rs +++ b/src/hrtim/fault.rs @@ -115,8 +115,8 @@ macro_rules! impl_faults { unsafe { let common = &*HRTIM_COMMON::ptr(); - common.fltinr2.modify(|_r, w| w.$fltWsrc_1().bit(src_bits & 0b10 != 0)); - common.$fltinrZ.modify(|_r, w| w + common.fltinr2().modify(|_r, w| w.$fltWsrc_1().bit(src_bits & 0b10 != 0)); + common.$fltinrZ().modify(|_r, w| w .$fltWsrc_0().bit(src_bits & 0b01 != 0) .$fltWp().bit(is_active_high) .$fltWf().bits(filter_bits) @@ -124,7 +124,7 @@ macro_rules! impl_faults { ); // ... and lock configuration - common.$fltinrZ.modify(|_r, w| w.$fltWlck().set_bit()); + common.$fltinrZ().modify(|_r, w| w.$fltWlck().set_bit()); } $source { @@ -250,17 +250,17 @@ macro_rules! impl_flt_monitor { impl FaultMonitor for $t { fn enable_interrupt(&mut self, _hr_control: &mut HrPwmCtrl) { let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.ier.modify(|_r, w| w.$fltxie().set_bit()); + common.ier().modify(|_r, w| w.$fltxie().set_bit()); } fn is_fault_active(&self) -> bool { let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.isr.read().$fltx().bit() + common.isr().read().$fltx().bit() } fn clear_fault(&mut self) { let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.icr.write(|w| w.$fltxc().set_bit()); + common.icr().write(|w| w.$fltxc().set_bit()); } } )+}; diff --git a/src/hrtim/mod.rs b/src/hrtim/mod.rs index ba3df712..351387bd 100644 --- a/src/hrtim/mod.rs +++ b/src/hrtim/mod.rs @@ -222,7 +222,7 @@ macro_rules! hrtim_finalize_body { }; // Write prescaler and any special modes - tim.$timXcr.modify(|_r, w| unsafe { + tim.$timXcr().modify(|_r, w| unsafe { w // Enable Continuous mode .cont().bit($this.timer_mode == HrTimerMode::Continuous) @@ -241,27 +241,27 @@ macro_rules! hrtim_finalize_body { }); $( - tim.$timXcr2.modify(|_r, w| + tim.$timXcr2().modify(|_r, w| // Set counting direction w.udm().bit($this.counting_direction == HrCountingDirection::UpDown) ); // Only available for timers with outputs(not HRTIM_MASTER) - let _ = tim.$outXr; - tim.$timXcr.modify(|_r, w| + let _ = tim.$outXr(); + tim.$timXcr().modify(|_r, w| // Push-Pull mode w.pshpll().bit($this.enable_push_pull) ); )* // Write period - tim.$perXr.write(|w| unsafe { w.$perx().bits(period as u16) }); + tim.$perXr().write(|w| unsafe { w.$perx().bits(period as u16) }); // Enable fault sources and lock configuration $(unsafe { // Enable fault sources let fault_enable_bits = $this.fault_enable_bits as u32; - tim.$fltXr.write(|w| w + tim.$fltXr().write(|w| w .flt1en().bit(fault_enable_bits & (1 << 0) != 0) .flt2en().bit(fault_enable_bits & (1 << 1) != 0) .flt3en().bit(fault_enable_bits & (1 << 2) != 0) @@ -271,9 +271,9 @@ macro_rules! hrtim_finalize_body { ); // ... and lock configuration - tim.$fltXr.modify(|_r, w| w.fltlck().set_bit()); + tim.$fltXr().modify(|_r, w| w.fltlck().set_bit()); - tim.$outXr.modify(|_r, w| w + tim.$outXr().modify(|_r, w| w // Set actions on fault for both outputs .fault1().bits($this.fault1_bits) .fault2().bits($this.fault2_bits) @@ -293,7 +293,7 @@ macro_rules! hrtim_finalize_body { // SAFETY: DeadtimeConfig makes sure rising and falling values are valid // and DeadtimePrescaler has its own garantuee - tim.$dtXr.modify(|_r, w| w + tim.$dtXr().modify(|_r, w| w .dtprsc().bits(prescaler as u8) .dtrx().bits(deadtime_rising_value) .sdtrx().bit(deadtime_rising_sign) @@ -306,26 +306,26 @@ macro_rules! hrtim_finalize_body { .dtrlkx().set_bit() .dtrslkx().set_bit() ); - tim.$outXr.modify(|_r, w| w.dten().set_bit()); + tim.$outXr().modify(|_r, w| w.dten().set_bit()); } // External event configs let eev_cfg = $this.eev_cfg.clone(); - tim.$eefXr1.write(|w| w + tim.$eefXr1().write(|w| w .ee1ltch().bit(eev_cfg.eev1.latch_bit).ee1fltr().bits(eev_cfg.eev1.filter_bits) .ee2ltch().bit(eev_cfg.eev2.latch_bit).ee2fltr().bits(eev_cfg.eev2.filter_bits) .ee3ltch().bit(eev_cfg.eev3.latch_bit).ee3fltr().bits(eev_cfg.eev3.filter_bits) .ee4ltch().bit(eev_cfg.eev4.latch_bit).ee4fltr().bits(eev_cfg.eev4.filter_bits) .ee5ltch().bit(eev_cfg.eev5.latch_bit).ee5fltr().bits(eev_cfg.eev5.filter_bits) ); - tim.$eefXr2.write(|w| w + tim.$eefXr2().write(|w| w .ee6ltch().bit(eev_cfg.eev6.latch_bit).ee6fltr().bits(eev_cfg.eev6.filter_bits) .ee7ltch().bit(eev_cfg.eev7.latch_bit).ee7fltr().bits(eev_cfg.eev7.filter_bits) .ee8ltch().bit(eev_cfg.eev8.latch_bit).ee8fltr().bits(eev_cfg.eev8.filter_bits) .ee9ltch().bit(eev_cfg.eev9.latch_bit).ee9fltr().bits(eev_cfg.eev9.filter_bits) .ee10ltch().bit(eev_cfg.eev10.latch_bit).ee10fltr().bits(eev_cfg.eev10.filter_bits) ); - tim.$Xeefr3.write(|w| w + tim.$Xeefr3().write(|w| w .eevace().bit(eev_cfg.event_counter_enable_bit) // External Event A Counter Reset"] //.eevacres().bit() @@ -339,10 +339,10 @@ macro_rules! hrtim_finalize_body { hrtim_finalize_body!($PreloadSource, $this, tim, $timXcr); // Set repetition counter - unsafe { tim.$rep.write(|w| w.$repx().bits($this.repetition_counter)); } + unsafe { tim.$rep().write(|w| w.$repx().bits($this.repetition_counter)); } // Enable interrupts - tim.$dier.modify(|_r, w| w.$repie().bit($this.enable_repetition_interrupt)); + tim.$dier().modify(|_r, w| w.$repie().bit($this.enable_repetition_interrupt)); // Start timer //let master = unsafe { &*HRTIM_MASTER::ptr() }; @@ -359,19 +359,19 @@ macro_rules! hrtim_finalize_body { (PreloadSource, $this:expr, $tim:expr, $timXcr:ident) => {{ match $this.preload_source { Some(PreloadSource::OnCounterReset) => { - $tim.$timXcr.modify(|_r, w| w + $tim.$timXcr().modify(|_r, w| w .tx_rstu().set_bit() .preen().set_bit() ) }, Some(PreloadSource::OnMasterTimerUpdate) => { - $tim.$timXcr.modify(|_r, w| w + $tim.$timXcr().modify(|_r, w| w .mstu().set_bit() .preen().set_bit() ) } Some(PreloadSource::OnRepetitionUpdate) => { - $tim.$timXcr.modify(|_r, w| w + $tim.$timXcr().modify(|_r, w| w .tx_repu().set_bit() .preen().set_bit() ) @@ -383,7 +383,7 @@ macro_rules! hrtim_finalize_body { (MasterPreloadSource, $this:expr, $tim:expr, $timXcr:ident) => {{ match $this.preload_source { Some(MasterPreloadSource::OnMasterRepetitionUpdate) => { - $tim.$timXcr.modify(|_r, w| w + $tim.$timXcr().modify(|_r, w| w .mrepu().set_bit() .preen().set_bit() ) diff --git a/src/hrtim/output.rs b/src/hrtim/output.rs index 5e1e815f..f0d140d2 100644 --- a/src/hrtim/output.rs +++ b/src/hrtim/output.rs @@ -19,30 +19,30 @@ macro_rules! hrtim_out { 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() }); + common.oenr().write(|w| { w.$tXYoen().set_bit() }); } fn disable(&mut self) { let common = unsafe { &*HRTIM_COMMON::ptr() }; - common.odisr.write(|w| { w.$tXYodis().set_bit() }); + common.odisr().write(|w| { w.$tXYodis().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)); } + 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)); } + unsafe { tim.$setXYr().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)); } + 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)); } + unsafe { tim.$rstXYr().modify(|r, w| w.bits(r.bits() & !ES::BITS)); } } fn get_state(&self) -> State { @@ -51,8 +51,8 @@ macro_rules! hrtim_out { unsafe { let common = &*HRTIM_COMMON::ptr(); - ods = common.odsr.read().$tXYods().bit_is_set(); - oen = common.oenr.read().$tXYoen().bit_is_set(); + ods = common.odsr().read().$tXYods().bit_is_set(); + oen = common.oenr().read().$tXYoen().bit_is_set(); } match (oen, ods) { diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs index 4e162b3d..689d7bd7 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -131,12 +131,12 @@ macro_rules! hrtim_timer { fn get_period(&self) -> u16 { let tim = unsafe { &*$TIMX::ptr() }; - tim.$perXr.read().$perx().bits() + tim.$perXr().read().$perx().bits() } fn set_period(&mut self, period: u16) { let tim = unsafe { &*$TIMX::ptr() }; - tim.$perXr.write(|w| unsafe { w.$perx().bits(period as u16) }); + tim.$perXr().write(|w| unsafe { w.$perx().bits(period as u16) }); } /// Start timer @@ -145,7 +145,7 @@ macro_rules! hrtim_timer { // SAFETY: Since we hold _hr_control there is no risk for a race condition let master = unsafe { &*HRTIM_MASTER::ptr() }; - master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); + master.mcr().modify(|_r, w| { w.$tXcen().set_bit() }); } /// Stop timer @@ -153,7 +153,7 @@ macro_rules! hrtim_timer { // Stop counter // SAFETY: Since we hold _hr_control there is no risk for a race condition let master = unsafe { &*HRTIM_MASTER::ptr() }; - master.mcr.modify(|_r, w| { w.$tXcen().set_bit() }); + master.mcr().modify(|_r, w| { w.$tXcen().set_bit() }); } /// Stop timer and reset counter @@ -162,7 +162,7 @@ macro_rules! hrtim_timer { // Reset counter let tim = unsafe { &*$TIMX::ptr() }; - unsafe { tim.$cntXr.write(|w| w.$cntx().bits(0)); } + unsafe { tim.$cntXr().write(|w| w.$cntx().bits(0)); } } /// Make a handle to this timers reset event to use as adc trigger @@ -178,7 +178,7 @@ macro_rules! hrtim_timer { fn clear_repetition_interrupt(&mut self) { let tim = unsafe { &*$TIMX::ptr() }; - tim.$icr.write(|w| w.$repc().set_bit()); + tim.$icr().write(|w| w.$repc().set_bit()); } /// Disable register updates @@ -189,7 +189,7 @@ macro_rules! hrtim_timer { 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()); + common.cr1().modify(|_r, w| w.$tXudis().set_bit()); } /// Enable register updates @@ -201,7 +201,7 @@ macro_rules! hrtim_timer { 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()); + common.cr1().modify(|_r, w| w.$tXudis().clear_bit()); } } @@ -209,13 +209,13 @@ macro_rules! hrtim_timer { pub fn set_repetition_counter(&mut self, repetition_counter: u8) { let tim = unsafe { &*$TIMX::ptr() }; - unsafe { tim.$rep.write(|w| w.$repx().bits(repetition_counter)); } + unsafe { tim.$rep().write(|w| w.$repx().bits(repetition_counter)); } } pub fn enable_repetition_interrupt(&mut self, enable: bool) { let tim = unsafe { &*$TIMX::ptr() }; - tim.$dier.modify(|_r, w| w.$repie().bit(enable)); + tim.$dier().modify(|_r, w| w.$repie().bit(enable)); } } @@ -242,14 +242,14 @@ macro_rules! hrtim_timer { 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)); } + 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)); } + unsafe { tim.$rstXr().modify(|r, w| w.bits(r.bits() & !E::BITS)); } } } From 849e484f49803bc9d14a69eae8e1ca676607bc56 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 7 Nov 2024 23:32:22 +0100 Subject: [PATCH 84/88] Revert "OPAMP - Add more adc pin impls for opamp follower" This reverts commit d3fc23da46638b8e7077bb8a574719ef4bb019b3. --- src/adc.rs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/adc.rs b/src/adc.rs index ee4e6f72..45f775bf 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -2863,21 +2863,6 @@ adc_opamp!( opamp::Opamp6 => (ADC4, 17), ); -#[cfg(any( - feature = "stm32g473", - feature = "stm32g474", - feature = "stm32g483", - feature = "stm32g484", - feature = "stm32g491", - feature = "stm32g4a1", -))] -adc_op_follower!( - opamp::opamp3::Follower => (ADC3, 13), - opamp::opamp4::Follower => (ADC5, 5), - opamp::opamp5::Follower => (ADC5, 3), - opamp::opamp6::Follower => (ADC4, 17), -); - #[cfg(any(feature = "stm32g491", feature = "stm32g4a1",))] adc_opamp!( opamp::Opamp6 => (ADC3, 17), From ad146a00632beb74afbdbecac9f10df1f93641ab Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 7 Nov 2024 23:36:13 +0100 Subject: [PATCH 85/88] HRTIM - Fix some errors due to new pac --- src/hrtim/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hrtim/mod.rs b/src/hrtim/mod.rs index 351387bd..d0666197 100644 --- a/src/hrtim/mod.rs +++ b/src/hrtim/mod.rs @@ -362,19 +362,19 @@ macro_rules! hrtim_finalize_body { $tim.$timXcr().modify(|_r, w| w .tx_rstu().set_bit() .preen().set_bit() - ) + ); }, Some(PreloadSource::OnMasterTimerUpdate) => { $tim.$timXcr().modify(|_r, w| w .mstu().set_bit() .preen().set_bit() - ) + ); } Some(PreloadSource::OnRepetitionUpdate) => { $tim.$timXcr().modify(|_r, w| w .tx_repu().set_bit() .preen().set_bit() - ) + ); } None => () } @@ -386,7 +386,7 @@ macro_rules! hrtim_finalize_body { $tim.$timXcr().modify(|_r, w| w .mrepu().set_bit() .preen().set_bit() - ) + ); } None => () } From dd918b4a59b56be6f9be43da2b741b9b9e2c2148 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 7 Nov 2024 23:37:50 +0100 Subject: [PATCH 86/88] fmt --- src/hrtim/control.rs | 4 +++- src/serial/usart.rs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/hrtim/control.rs b/src/hrtim/control.rs index ccbf7606..234d25d1 100644 --- a/src/hrtim/control.rs +++ b/src/hrtim/control.rs @@ -95,7 +95,9 @@ impl HrTimOngoingCalibration { common .dllcr() .modify(|_r, w| w.calrte().bits(0b00).cal().set_bit().calen().clear_bit()); - common.fltinr2().write(|w| w.fltsd().bits(flt_divider as u8)); + common + .fltinr2() + .write(|w| w.fltsd().bits(flt_divider as u8)); common.eecr3().write(|w| w.eevsd().bits(eev_divider as u8)); common.adcps1().write(|w| { diff --git a/src/serial/usart.rs b/src/serial/usart.rs index 139ddfbe..e89a3451 100644 --- a/src/serial/usart.rs +++ b/src/serial/usart.rs @@ -3,7 +3,9 @@ use core::fmt; use core::marker::PhantomData; use crate::dma::traits::Stream; -use crate::dma::{mux::DmaMuxResources, traits::TargetAddress, PeripheralToMemory, MemoryToPeripheral}; +use crate::dma::{ + mux::DmaMuxResources, traits::TargetAddress, MemoryToPeripheral, PeripheralToMemory, +}; use crate::gpio::{gpioa::*, gpiob::*, gpioc::*, gpiod::*, gpioe::*, gpiog::*}; use crate::gpio::{Alternate, AlternateOD, AF12, AF5, AF7, AF8}; use crate::prelude::*; From f9099f8a0e59cd93ba5a8e674828c11fee00dc8e Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 7 Nov 2024 23:59:37 +0100 Subject: [PATCH 87/88] HRTIM - Update examples --- examples/hrtim/adc-trigger.rs | 10 +++++----- examples/hrtim/capture-dma.rs | 6 +++--- examples/hrtim/capture.rs | 29 +++++++++++++---------------- examples/hrtim/eev-comp.rs | 9 +++------ examples/hrtim/eev.rs | 9 +++------ examples/hrtim/flt-comp.rs | 12 ++++-------- examples/hrtim/flt.rs | 12 ++++-------- examples/hrtim/hrtim.rs | 10 +++------- examples/hrtim/master.rs | 17 +++-------------- examples/hrtim/simple.rs | 5 ++--- 10 files changed, 43 insertions(+), 76 deletions(-) diff --git a/examples/hrtim/adc-trigger.rs b/examples/hrtim/adc-trigger.rs index 7c6facb9..e2e4d5e3 100644 --- a/examples/hrtim/adc-trigger.rs +++ b/examples/hrtim/adc-trigger.rs @@ -25,7 +25,7 @@ fn main() -> ! { }, delay::SYSTDelayExt, dma::{self, config::DmaConfig, stream::DMAExt, TransferExt}, - gpio::{gpioa::PA8, gpioa::PA9, Alternate, GpioExt, AF13}, + gpio::GpioExt, hrtim::compare_register::HrCompareRegister, hrtim::control::HrControltExt, hrtim::output::HrOutput, @@ -50,7 +50,7 @@ fn main() -> ! { let pwr = dp.PWR.constrain().freeze(); let mut rcc = dp.RCC.freeze( rcc::Config::pll().pll_cfg(rcc::PllConfig { - mux: rcc::PLLSrc::HSI, + mux: rcc::PllSrc::HSI, n: rcc::PllNMul::MUL_15, m: rcc::PllMDiv::DIV_1, r: Some(rcc::PllRDiv::DIV_2), @@ -72,8 +72,8 @@ fn main() -> ! { let gpioa = dp.GPIOA.split(&mut rcc); let pa0 = gpioa.pa0.into_analog(); - let pin_a: PA8> = gpioa.pa8.into_alternate(); - let pin_b: PA9> = gpioa.pa9.into_alternate(); + let pin_a = gpioa.pa8; + let pin_b = gpioa.pa9; // ...with a prescaler of 4 this gives us a HrTimer with a tick rate of 960MHz // With max the max period set, this would be 960MHz/2^16 ~= 15kHz... @@ -140,7 +140,7 @@ fn main() -> ! { out1.enable(); out2.enable(); - timer.start(&mut hr_control); + timer.start(&mut hr_control.control); loop { let mut b = [0_u16; 4]; diff --git a/examples/hrtim/capture-dma.rs b/examples/hrtim/capture-dma.rs index 3e513ebf..ade47443 100644 --- a/examples/hrtim/capture-dma.rs +++ b/examples/hrtim/capture-dma.rs @@ -19,7 +19,7 @@ fn main() -> ! { use hal::{ dma::{config::DmaConfig, stream::DMAExt, TransferExt}, - gpio::{gpioa::PA8, Alternate, GpioExt, AF13}, + gpio::{GpioExt, AF13}, hrtim::{ capture, compare_register::HrCompareRegister, control::HrControltExt, external_event, external_event::ToExternalEventSource, output::HrOutput, timer::HrSlaveTimerCpt, @@ -56,7 +56,7 @@ fn main() -> ! { let gpiob = dp.GPIOB.split(&mut rcc); // PA8 (D7 on Nucleo G474RE) - let pin_a: PA8> = gpioa.pa8.into_alternate(); + let pin_a = gpioa.pa8; // PB5 (D4 on Nucleo G474RE) let input = gpiob.pb5.into_pull_down_input(); @@ -98,7 +98,7 @@ fn main() -> ! { cr1.set_duty(period / 2); let (mut timer, mut capture, _capture_ch2) = timer.split_capture(); - timer.start(&mut hr_control); + timer.start(&mut hr_control.control); out1.enable(); capture.enable_interrupt(true, &mut hr_control); diff --git a/examples/hrtim/capture.rs b/examples/hrtim/capture.rs index c62e84c5..1e0c2c46 100644 --- a/examples/hrtim/capture.rs +++ b/examples/hrtim/capture.rs @@ -18,7 +18,7 @@ fn main() -> ! { use stm32g4xx_hal as hal; use hal::{ - gpio::{gpioa::PA8, Alternate, GpioExt, AF13}, + gpio::GpioExt, hrtim::{ capture::HrCapture, compare_register::HrCompareRegister, control::HrControltExt, external_event, external_event::ToExternalEventSource, output::HrOutput, @@ -40,7 +40,7 @@ fn main() -> ! { let pwr = dp.PWR.constrain().freeze(); let mut rcc = dp.RCC.freeze( rcc::Config::pll().pll_cfg(rcc::PllConfig { - mux: rcc::PLLSrc::HSI, + mux: rcc::PllSrc::HSI, n: rcc::PllNMul::MUL_15, m: rcc::PllMDiv::DIV_1, r: Some(rcc::PllRDiv::DIV_2), @@ -55,7 +55,7 @@ fn main() -> ! { let gpiob = dp.GPIOB.split(&mut rcc); // PA8 (D7 on Nucleo G474RE) - let pin_a: PA8> = gpioa.pa8.into_alternate(); + let pin_a = gpioa.pa8; // PB5 (D4 on Nucleo G474RE) let input = gpiob.pb5.into_pull_down_input(); @@ -94,7 +94,7 @@ fn main() -> ! { out1.enable_set_event(&timer); // Set high at new period cr1.set_duty(period / 2); - timer.start(&mut hr_control); + timer.start(&mut hr_control.control); out1.enable(); let capture = timer.capture_ch1(); @@ -104,19 +104,16 @@ fn main() -> ! { let mut old_duty = 0; loop { for duty in (u32::from(period) / 10)..(9 * u32::from(period) / 10) { - if !capture.is_pending() { - continue; + if let Some(value) = capture.get_signed(period) { + info!( + "Capture: {:?}, duty: {}, diff: {}", + value, + old_duty, + value - old_duty as i32 + ); + cr1.set_duty(duty as u16); + old_duty = duty; } - let value = capture.get_signed(); - cr1.set_duty(duty as u16); - capture.clear_interrupt(); - info!( - "Capture: {:?}, duty: {}, diff: {}", - value, - old_duty, - value - old_duty as i32 - ); - old_duty = duty; } } } diff --git a/examples/hrtim/eev-comp.rs b/examples/hrtim/eev-comp.rs index c4a7ee06..329779de 100644 --- a/examples/hrtim/eev-comp.rs +++ b/examples/hrtim/eev-comp.rs @@ -19,10 +19,7 @@ fn main() -> ! { use hal::comparator; use hal::comparator::{ComparatorExt, ComparatorSplit, Hysteresis}; use hal::dac::{self, DacExt, DacOut}; - use hal::gpio::gpioa::PA8; - use hal::gpio::Alternate; use hal::gpio::SignalEdge; - use hal::gpio::AF13; use hal::hrtim::compare_register::HrCompareRegister; use hal::hrtim::external_event::{self, ToExternalEventSource}; use hal::hrtim::timer::HrTimer; @@ -45,7 +42,7 @@ fn main() -> ! { let mut rcc = dp.RCC.freeze( rcc::Config::pll().pll_cfg(rcc::PllConfig { - mux: rcc::PLLSrc::HSI, + mux: rcc::PllSrc::HSI, n: rcc::PllNMul::MUL_75, m: rcc::PllMDiv::DIV_4, r: Some(rcc::PllRDiv::DIV_2), @@ -61,7 +58,7 @@ fn main() -> ! { let gpioa = dp.GPIOA.split(&mut rcc); let input = gpioa.pa1.into_analog(); - let pin_a: PA8> = gpioa.pa8.into_alternate(); + let pin_a = gpioa.pa8; let dac1ch1 = dp.DAC1.constrain(dac::Dac1IntSig1, &mut rcc); let mut dac = dac1ch1.calibrate_buffer(&mut delay).enable(); @@ -128,7 +125,7 @@ fn main() -> ! { cr1.set_duty(timer.get_period() / 3); out1.enable(); - timer.start(&mut hr_control); + timer.start(&mut hr_control.control); info!("Started"); diff --git a/examples/hrtim/eev.rs b/examples/hrtim/eev.rs index 636564bc..a8a3e662 100644 --- a/examples/hrtim/eev.rs +++ b/examples/hrtim/eev.rs @@ -16,9 +16,6 @@ use utils::logger::info; #[entry] fn main() -> ! { - use hal::gpio::gpioa::PA8; - use hal::gpio::Alternate; - use hal::gpio::AF13; use hal::hrtim::compare_register::HrCompareRegister; use hal::hrtim::external_event; use hal::hrtim::external_event::ToExternalEventSource; @@ -41,7 +38,7 @@ fn main() -> ! { let mut rcc = dp.RCC.freeze( rcc::Config::pll().pll_cfg(rcc::PllConfig { - mux: rcc::PLLSrc::HSI, + mux: rcc::PllSrc::HSI, n: rcc::PllNMul::MUL_75, m: rcc::PllMDiv::DIV_4, r: Some(rcc::PllRDiv::DIV_2), @@ -70,7 +67,7 @@ fn main() -> ! { // With max the max period set, this would be 1.2GHz/2^16 ~= 18kHz... let prescaler = Pscl4; - let pin_a: PA8> = gpioa.pa8.into_alternate(); + let pin_a = gpioa.pa8; // . . * . // . 33% . * . . . @@ -100,7 +97,7 @@ fn main() -> ! { cr1.set_duty(timer.get_period() / 3); out1.enable(); - timer.start(&mut hr_control); + timer.start(&mut hr_control.control); info!("Started"); diff --git a/examples/hrtim/flt-comp.rs b/examples/hrtim/flt-comp.rs index 9131f42f..235bceb2 100644 --- a/examples/hrtim/flt-comp.rs +++ b/examples/hrtim/flt-comp.rs @@ -18,17 +18,13 @@ use utils::logger::info; fn main() -> ! { use hal::comparator::{ComparatorExt, ComparatorSplit, Config, Hysteresis}; use hal::dac::{Dac3IntSig1, DacExt, DacOut}; - use hal::gpio::gpioa::PA8; - use hal::gpio::Alternate; - use hal::gpio::AF13; use hal::hrtim::compare_register::HrCompareRegister; - use hal::hrtim::fault::FaultAction; + use hal::hrtim::fault::{FaultAction, FaultMonitor}; use hal::hrtim::timer::HrTimer; use hal::hrtim::HrPwmAdvExt; use hal::hrtim::Pscl4; use hal::hrtim::{control::HrControltExt, output::HrOutput}; use hal::prelude::*; - use hal::pwm::FaultMonitor; use hal::rcc; use hal::stm32; use stm32g4xx_hal as hal; @@ -42,7 +38,7 @@ fn main() -> ! { let pwr = dp.PWR.constrain().freeze(); let mut rcc = dp.RCC.freeze( rcc::Config::pll().pll_cfg(rcc::PllConfig { - mux: rcc::PLLSrc::HSI, + mux: rcc::PllSrc::HSI, n: rcc::PllNMul::MUL_15, m: rcc::PllMDiv::DIV_1, r: Some(rcc::PllRDiv::DIV_2), @@ -100,7 +96,7 @@ fn main() -> ! { // With max the max period set, this would be 1.2GHz/2^16 ~= 18kHz... let prescaler = Pscl4; - let pin_a: PA8> = gpioa.pa8.into_alternate(); + let pin_a = gpioa.pa8; // . . . * // . 33% . . * . . @@ -131,7 +127,7 @@ fn main() -> ! { cr1.set_duty(timer.get_period() / 3); //unsafe {((HRTIM_COMMON::ptr() as *mut u8).offset(0x14) as *mut u32).write_volatile(1); } out1.enable(); - timer.start(&mut hr_control); + timer.start(&mut hr_control.control); info!("Started"); diff --git a/examples/hrtim/flt.rs b/examples/hrtim/flt.rs index a1a6879e..990c7e79 100644 --- a/examples/hrtim/flt.rs +++ b/examples/hrtim/flt.rs @@ -16,17 +16,13 @@ use utils::logger::info; #[entry] fn main() -> ! { - use hal::gpio::gpioa::PA8; - use hal::gpio::Alternate; - use hal::gpio::AF13; use hal::hrtim::compare_register::HrCompareRegister; - use hal::hrtim::fault::FaultAction; + use hal::hrtim::fault::{FaultAction, FaultMonitor}; use hal::hrtim::timer::HrTimer; use hal::hrtim::HrPwmAdvExt; use hal::hrtim::Pscl4; use hal::hrtim::{control::HrControltExt, output::HrOutput}; use hal::prelude::*; - use hal::pwm::FaultMonitor; use hal::pwr::PwrExt; use hal::rcc; use hal::stm32; @@ -40,7 +36,7 @@ fn main() -> ! { let pwr = dp.PWR.constrain().freeze(); let mut rcc = dp.RCC.freeze( rcc::Config::pll().pll_cfg(rcc::PllConfig { - mux: rcc::PLLSrc::HSI, + mux: rcc::PllSrc::HSI, n: rcc::PllNMul::MUL_75, m: rcc::PllMDiv::DIV_4, r: Some(rcc::PllRDiv::DIV_2), @@ -66,7 +62,7 @@ fn main() -> ! { // With max the max period set, this would be 1.2GHz/2^16 ~= 18kHz... let prescaler = Pscl4; - let pin_a: PA8> = gpioa.pa8.into_alternate(); + let pin_a = gpioa.pa8; // . . . * // . 33% . . * . . @@ -105,7 +101,7 @@ fn main() -> ! { cr1.set_duty(timer.get_period() / 3); //unsafe {((HRTIM_COMMON::ptr() as *mut u8).offset(0x14) as *mut u32).write_volatile(1); } out1.enable(); - timer.start(&mut hr_control); + timer.start(&mut hr_control.control); info!("Started"); diff --git a/examples/hrtim/hrtim.rs b/examples/hrtim/hrtim.rs index b29ceffe..845b0f34 100644 --- a/examples/hrtim/hrtim.rs +++ b/examples/hrtim/hrtim.rs @@ -16,10 +16,6 @@ use utils::logger::info; #[entry] fn main() -> ! { use fugit::ExtU32; - use hal::gpio::gpioa::PA8; - use hal::gpio::gpioa::PA9; - use hal::gpio::Alternate; - use hal::gpio::AF13; use hal::hrtim::compare_register::HrCompareRegister; use hal::hrtim::control::HrControltExt; use hal::hrtim::output::HrOutput; @@ -42,7 +38,7 @@ fn main() -> ! { let pwr = dp.PWR.constrain().freeze(); let mut rcc = dp.RCC.freeze( rcc::Config::pll().pll_cfg(rcc::PllConfig { - mux: rcc::PLLSrc::HSI, + mux: rcc::PllSrc::HSI, n: rcc::PllNMul::MUL_15, m: rcc::PllMDiv::DIV_1, r: Some(rcc::PllRDiv::DIV_2), @@ -59,8 +55,8 @@ fn main() -> ! { let prescaler = Pscl4; let gpioa = dp.GPIOA.split(&mut rcc); - let pin_a: PA8> = gpioa.pa8.into_alternate(); - let pin_b: PA9> = gpioa.pa9.into_alternate(); + let pin_a = gpioa.pa8; + let pin_b = gpioa.pa9; // . . . . // . 30% . . . diff --git a/examples/hrtim/master.rs b/examples/hrtim/master.rs index a74dafff..b707de08 100644 --- a/examples/hrtim/master.rs +++ b/examples/hrtim/master.rs @@ -16,10 +16,6 @@ use utils::logger::info; #[entry] fn main() -> ! { use fugit::ExtU32; - use hal::gpio::gpioa::PA8; - use hal::gpio::gpioa::PA9; - use hal::gpio::Alternate; - use hal::gpio::AF13; use hal::hrtim::compare_register::HrCompareRegister; use hal::hrtim::control::HrControltExt; use hal::hrtim::output::HrOutput; @@ -41,7 +37,7 @@ fn main() -> ! { let pwr = dp.PWR.constrain().freeze(); let mut rcc = dp.RCC.freeze( rcc::Config::pll().pll_cfg(rcc::PllConfig { - mux: rcc::PLLSrc::HSI, + mux: rcc::PllSrc::HSI, n: rcc::PllNMul::MUL_15, m: rcc::PllMDiv::DIV_1, r: Some(rcc::PllRDiv::DIV_2), @@ -58,8 +54,8 @@ fn main() -> ! { let prescaler = Pscl4; let gpioa = dp.GPIOA.split(&mut rcc); - let pin_a: PA8> = gpioa.pa8.into_alternate(); - let pin_b: PA9> = gpioa.pa9.into_alternate(); + let pin_a = gpioa.pa8; + let pin_b = gpioa.pa9; // . . . . // . 30% . . . @@ -108,13 +104,6 @@ fn main() -> ! { out1.enable(); out2.enable(); - let tima = unsafe { &*stm32g4xx_hal::stm32::HRTIM_TIMA::ptr() }; - info!("set1r: {}", tima.seta1r.read().bits()); - info!("rst1r: {}", tima.rsta1r.read().bits()); - - info!("set2r: {}", tima.seta2r.read().bits()); - info!("rst2r: {}", tima.rsta2r.read().bits()); - info!("Running"); loop { diff --git a/examples/hrtim/simple.rs b/examples/hrtim/simple.rs index e493adac..d89c8774 100644 --- a/examples/hrtim/simple.rs +++ b/examples/hrtim/simple.rs @@ -17,7 +17,6 @@ use utils::logger::info; fn main() -> ! { use hal::gpio::gpioa::PA8; use hal::gpio::gpioa::PA9; - use hal::gpio::Alternate; use hal::gpio::AF13; use hal::hrtim::{control::HrControltExt, HrPwmExt}; use hal::prelude::*; @@ -46,8 +45,8 @@ fn main() -> ! { ); let gpioa = dp.GPIOA.split(&mut rcc); - let pin_a: PA8> = gpioa.pa8.into_alternate(); - let pin_b: PA9> = gpioa.pa9.into_alternate(); + let pin_a = gpioa.pa8; + let pin_b = gpioa.pa9; // . . . // . 33% . . From 34537954faf760115c0368d04099caf283573917 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 8 Nov 2024 00:10:06 +0100 Subject: [PATCH 88/88] HRTIM - Update examples --- examples/hrtim/adc-trigger.rs | 4 ---- examples/hrtim/capture-dma.rs | 4 ---- examples/hrtim/capture.rs | 4 ---- examples/hrtim/eev-comp.rs | 4 ---- examples/hrtim/eev.rs | 4 ---- examples/hrtim/flt-comp.rs | 6 +----- examples/hrtim/flt.rs | 6 +----- examples/hrtim/hrtim.rs | 4 ---- examples/hrtim/master.rs | 4 ---- examples/hrtim/simple.rs | 4 ---- 10 files changed, 2 insertions(+), 42 deletions(-) diff --git a/examples/hrtim/adc-trigger.rs b/examples/hrtim/adc-trigger.rs index e2e4d5e3..f2b7fc83 100644 --- a/examples/hrtim/adc-trigger.rs +++ b/examples/hrtim/adc-trigger.rs @@ -7,10 +7,6 @@ mod utils; use cortex_m_rt::entry; - -use defmt_rtt as _; // global logger -use panic_probe as _; - use utils::logger::info; #[entry] diff --git a/examples/hrtim/capture-dma.rs b/examples/hrtim/capture-dma.rs index ade47443..175a670e 100644 --- a/examples/hrtim/capture-dma.rs +++ b/examples/hrtim/capture-dma.rs @@ -7,10 +7,6 @@ mod utils; use cortex_m_rt::entry; - -use defmt_rtt as _; // global logger -use panic_probe as _; - use utils::logger::info; #[entry] diff --git a/examples/hrtim/capture.rs b/examples/hrtim/capture.rs index 1e0c2c46..90d3bc05 100644 --- a/examples/hrtim/capture.rs +++ b/examples/hrtim/capture.rs @@ -7,10 +7,6 @@ mod utils; use cortex_m_rt::entry; - -use defmt_rtt as _; // global logger -use panic_probe as _; - use utils::logger::info; #[entry] diff --git a/examples/hrtim/eev-comp.rs b/examples/hrtim/eev-comp.rs index 329779de..ee1d44fb 100644 --- a/examples/hrtim/eev-comp.rs +++ b/examples/hrtim/eev-comp.rs @@ -8,10 +8,6 @@ mod utils; use cortex_m_rt::entry; - -use defmt_rtt as _; // global logger -use panic_probe as _; - use utils::logger::info; #[entry] diff --git a/examples/hrtim/eev.rs b/examples/hrtim/eev.rs index a8a3e662..3dd4a1e7 100644 --- a/examples/hrtim/eev.rs +++ b/examples/hrtim/eev.rs @@ -8,10 +8,6 @@ mod utils; use cortex_m_rt::entry; - -use defmt_rtt as _; // global logger -use panic_probe as _; - use utils::logger::info; #[entry] diff --git a/examples/hrtim/flt-comp.rs b/examples/hrtim/flt-comp.rs index 235bceb2..4a83a476 100644 --- a/examples/hrtim/flt-comp.rs +++ b/examples/hrtim/flt-comp.rs @@ -8,10 +8,6 @@ mod utils; use cortex_m_rt::entry; - -use defmt_rtt as _; // global logger -use panic_probe as _; - use utils::logger::info; #[entry] @@ -135,7 +131,7 @@ fn main() -> ! { for _ in 0..5 { //delay.delay(500_u32.millis()); info!( - "State: {}, comp: {}, is_fault_active: {}, pc1: {}", + "State: {:?}, comp: {}, is_fault_active: {}, pc1: {}", out1.get_state(), comp3.output(), hr_control.fault_5.is_fault_active(), diff --git a/examples/hrtim/flt.rs b/examples/hrtim/flt.rs index 990c7e79..cad59c53 100644 --- a/examples/hrtim/flt.rs +++ b/examples/hrtim/flt.rs @@ -8,10 +8,6 @@ mod utils; use cortex_m_rt::entry; - -use defmt_rtt as _; // global logger -use panic_probe as _; - use utils::logger::info; #[entry] @@ -108,7 +104,7 @@ fn main() -> ! { loop { for _ in 0..5 { delay.delay(500_u32.millis()); - info!("State: {}", out1.get_state()); + info!("State: {:?}", out1.get_state()); } if hr_control.fault_3.is_fault_active() { hr_control.fault_3.clear_fault(); // Clear fault every 5s diff --git a/examples/hrtim/hrtim.rs b/examples/hrtim/hrtim.rs index 845b0f34..f55caa94 100644 --- a/examples/hrtim/hrtim.rs +++ b/examples/hrtim/hrtim.rs @@ -7,10 +7,6 @@ mod utils; use cortex_m_rt::entry; - -use defmt_rtt as _; // global logger -use panic_probe as _; - use utils::logger::info; #[entry] diff --git a/examples/hrtim/master.rs b/examples/hrtim/master.rs index b707de08..cf432a6e 100644 --- a/examples/hrtim/master.rs +++ b/examples/hrtim/master.rs @@ -7,10 +7,6 @@ mod utils; use cortex_m_rt::entry; - -use defmt_rtt as _; // global logger -use panic_probe as _; - use utils::logger::info; #[entry] diff --git a/examples/hrtim/simple.rs b/examples/hrtim/simple.rs index d89c8774..14d60812 100644 --- a/examples/hrtim/simple.rs +++ b/examples/hrtim/simple.rs @@ -7,10 +7,6 @@ mod utils; use cortex_m_rt::entry; - -use defmt_rtt as _; // global logger -use panic_probe as _; - use utils::logger::info; #[entry]