From e3c068e8b79febc899dc9933f432e29f60e82822 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 9 May 2023 23:55:39 +0200 Subject: [PATCH 01/85] 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 e078a63e09c5b7721dbb60d96eb1bcd19b334222 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 20 May 2023 11:25:42 +0200 Subject: [PATCH 02/85] 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 c50ba201587308ae7b107ebf342ba9364c842a4e Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 20 May 2023 13:13:36 +0200 Subject: [PATCH 03/85] 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 c83eb2a95562807ea2fc3e9aa0615c3a380b2129 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 20 May 2023 22:01:03 +0200 Subject: [PATCH 04/85] 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 a74e315e24f60a89eeccae604320a6c0425cc89c Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 20 May 2023 23:14:28 +0200 Subject: [PATCH 05/85] 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 aac01f6f39b08bf5ae0cab236f81456feb4f8546 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 20 May 2023 23:37:02 +0200 Subject: [PATCH 06/85] 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 2e570cd4ce5b102d4b8938912be490d16277a0bb Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 20 May 2023 23:39:25 +0200 Subject: [PATCH 07/85] 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 9b3f820bc5fb4f46af6496ba5bfc28e5ed9e1018 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 20 May 2023 23:52:18 +0200 Subject: [PATCH 08/85] 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 10f5edf93eee212357e6032d55a1b04625017e8e Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 7 Jun 2023 15:50:35 +0200 Subject: [PATCH 09/85] 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 182e84a1975555fcefcd9ec21634290cf01f03be Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 7 Jun 2023 15:55:26 +0200 Subject: [PATCH 10/85] 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 26f795bb6f32642da5fee4ecbb7ebd136a99fbee Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 9 Jun 2023 17:34:57 +0200 Subject: [PATCH 11/85] 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 bb70f527f4a3571816bd1767bcedc0130115eb59 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 20 Jun 2023 14:37:07 +0200 Subject: [PATCH 12/85] 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 d9f1b3fdeb422da37db916f2ce3c31039c33ff4d Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 12 Jun 2023 22:23:09 +0200 Subject: [PATCH 13/85] 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 2832f9e067b0a68188178bb81fedf319f159ff6a Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 20 Jun 2023 15:20:37 +0200 Subject: [PATCH 14/85] 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 0e4367f4f787cbe49e98831814ee5183dede7b60 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 28 Jun 2023 17:58:47 +0200 Subject: [PATCH 15/85] 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 1e5786d0b548c86080591a954b64bdde90b8f450 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 25 Aug 2023 17:08:00 +0200 Subject: [PATCH 16/85] 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 0814706b4a873b0d6e689459081ef48be0ec5a80 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 25 Aug 2023 17:26:01 +0200 Subject: [PATCH 17/85] 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 832a087cac07333c28b24df090c9838135bd5fda Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 4 Sep 2023 18:55:59 +0200 Subject: [PATCH 18/85] 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 62ec4c78726fb3c3b18deab846f432a4079261a1 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 24 Oct 2023 10:32:19 +0200 Subject: [PATCH 19/85] 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 7a17a5476e882bfffebf5fb3cca49d1acb8700b7 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 24 Oct 2023 17:36:54 +0200 Subject: [PATCH 20/85] 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 16302ca7b5446cc01284fc4714fc7ff38a6d6f0a Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 24 Oct 2023 17:46:47 +0200 Subject: [PATCH 21/85] 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 2baed51f1bb146a47426caa08e77f40c2d2f23c4 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 3 Nov 2023 16:03:51 +0100 Subject: [PATCH 22/85] 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 95cd969e849d2c2bed70635ed3f9f8b73e8c2f66 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 4 Nov 2023 01:33:45 +0100 Subject: [PATCH 23/85] 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 b3e3e346863854728d65e87b5156f90fb72e8035 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sun, 5 Nov 2023 21:35:48 +0100 Subject: [PATCH 24/85] 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 4fbea36b0139ac313d85e618a9ec05ac74381e39 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 6 Nov 2023 15:41:26 +0100 Subject: [PATCH 25/85] 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 01583465d92eb10bfa6bc053e7148683d973866e Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 6 Nov 2023 19:11:08 +0100 Subject: [PATCH 26/85] 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 c1250875b8d37f857e0bc7075a6a8739fb0654bb Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 7 Nov 2023 17:32:43 +0100 Subject: [PATCH 27/85] 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 7ddc5da18c8e1c87402cecf70b08d6f3043a07d3 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 8 Nov 2023 18:09:40 +0100 Subject: [PATCH 28/85] 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 8e947de4d9335e587b03690b3d933ea41638c107 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 8 Nov 2023 18:23:19 +0100 Subject: [PATCH 29/85] 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 a53ebbaed86cf2c6fc4f05b09206281ae1210d8a Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 8 Nov 2023 22:42:31 +0100 Subject: [PATCH 30/85] 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 6d4631379a2c07a228b53a16abc1030ae74f31ff Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 6 Jan 2024 02:01:31 +0100 Subject: [PATCH 31/85] 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 167cc79f5b4ba3fd74425fe94c0c5502219233c9 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 17 Jan 2024 15:40:02 +0100 Subject: [PATCH 32/85] 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 3554c5c8db974bb7ef9b01ce8712ea005d7f6a5f Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 18 Jan 2024 10:52:22 +0100 Subject: [PATCH 33/85] 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 c0adecb360c9abac8c0eedfcd44f588946cad265 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 18 Jan 2024 13:43:50 +0100 Subject: [PATCH 34/85] 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 237cc866cbeed73e6a093937536dde5823691a1d Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 18 Jan 2024 13:51:25 +0100 Subject: [PATCH 35/85] 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 c86ae8989d20ee9ddf302ece0f353e085d049af2 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 18 Jan 2024 17:38:50 +0100 Subject: [PATCH 36/85] 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 d1a02b9b55a4bea804476f5c54c055f97773b757 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Jan 2024 10:08:57 +0100 Subject: [PATCH 37/85] 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 e086e651c6a2953ab76f72e126cd7a2c179276fb Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Jan 2024 10:09:41 +0100 Subject: [PATCH 38/85] 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 355b4c7ce6c848c8e77bed9d6164009d351614c4 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Jan 2024 10:19:44 +0100 Subject: [PATCH 39/85] 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 1cd72e248ce6cec95795f09a0fcca0539d2ad62e Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Jan 2024 11:35:53 +0100 Subject: [PATCH 40/85] 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 8886a7895347d4dc4deb1a30c1babdc226b3537f Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Jan 2024 11:36:25 +0100 Subject: [PATCH 41/85] 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 8fb088df5b9be789061fecbf40e57ab4645de8e7 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Jan 2024 13:51:05 +0100 Subject: [PATCH 42/85] 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 7a03587df4e48ce5feb938a8b631b2a6a062ef39 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Jan 2024 13:57:42 +0100 Subject: [PATCH 43/85] 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 8a229b1ad7e20074c81de366b0b8218754405cb5 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Jan 2024 17:23:55 +0100 Subject: [PATCH 44/85] 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 10251b79f1a170188f39b7d987e3c87ffc0592ca Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 22 Jan 2024 11:31:22 +0100 Subject: [PATCH 45/85] 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 bcbe0fefd3d14530e10ed8ed2f02244ca6ac7ef7 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 22 Jan 2024 11:31:42 +0100 Subject: [PATCH 46/85] 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 322cb608abc02cc315db52000ea784f5a106c1c1 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 22 Jan 2024 11:33:09 +0100 Subject: [PATCH 47/85] 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 765715b74bf5970d1cf86f62303c34b0ebd53cb0 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 22 Jan 2024 15:24:19 +0100 Subject: [PATCH 48/85] 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 21cf9f8b4f773c82c73132519d64cb3caa24c365 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 22 Jan 2024 15:55:39 +0100 Subject: [PATCH 49/85] 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 8667e71d654534ba92d07f3c403ae67870ed9947 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 22 Jan 2024 16:54:50 +0100 Subject: [PATCH 50/85] 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 97d8c5256836c507c2f1eb2ab22ba871c9fec25e Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 22 Jan 2024 16:55:13 +0100 Subject: [PATCH 51/85] 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 bf15715f169576163b8bac5331ba5adce59e417c Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 23 Jan 2024 17:02:13 +0100 Subject: [PATCH 52/85] 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 822ee3db3d30bbe0c7fd481dc8f81c4e5c078d8e Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 24 Jan 2024 15:56:04 +0100 Subject: [PATCH 53/85] 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 a59386b9386c2ec27fb6edfc189832ae76e4245c Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 24 Jan 2024 16:23:15 +0100 Subject: [PATCH 54/85] 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 32cdce47026af94878d9ce2e630c4b2ad1c92779 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 7 Sep 2023 11:47:23 +0200 Subject: [PATCH 55/85] 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 dfc555b7c9add375ae95bab09c9072d4047c5c31 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 3 Apr 2024 16:06:41 +0200 Subject: [PATCH 56/85] 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 098a8032bed46c3d700fa1cfdeb1c8cef4e77729 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 18 Apr 2024 11:53:29 +0200 Subject: [PATCH 57/85] 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 81760bd8389fc5055776c09421fef07f04b9372d Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Apr 2024 10:10:10 +0200 Subject: [PATCH 58/85] 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 de53acf9c05ee05742f362df8e2171897a8d4fcb Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Apr 2024 10:10:36 +0200 Subject: [PATCH 59/85] 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 b6da7279b42ca8ea5649359bc2bb9383640b20af Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Apr 2024 10:11:24 +0200 Subject: [PATCH 60/85] 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 96c2528421f111f3a483f53ecafd462edf2ab914 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Apr 2024 10:32:09 +0200 Subject: [PATCH 61/85] 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 8c7c49021bdccdf0e6451fc3b57e76867644cec2 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 19 Apr 2024 18:24:34 +0200 Subject: [PATCH 62/85] 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 146b8d06afb15c4e0cf2ecc5d77916f196fd1fe4 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 7 May 2024 18:45:48 +0200 Subject: [PATCH 63/85] 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 642ad5b2ac1b1893de7ed26644648e81db5e2a3b Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 7 May 2024 18:46:26 +0200 Subject: [PATCH 64/85] 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 4f5d1195319ad2b80eaf9799d08dce0a86e9e0a8 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 19 Jun 2024 17:17:28 +0200 Subject: [PATCH 65/85] 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 681cf2fa6829d21c6e043c418cdd728999c809db Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 19 Jun 2024 17:23:38 +0200 Subject: [PATCH 66/85] 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 b773b366b3af053bc3c0cefe11e28f9ca5d7dd75 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 26 Jun 2024 11:09:47 +0200 Subject: [PATCH 67/85] 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 6aa974fae85e3ee79c40cfa029427bdd8eb926aa Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 17 Aug 2024 20:50:00 +0200 Subject: [PATCH 68/85] 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 e45b57c412011910ad0e4fecea42b51f50159ead Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 17 Aug 2024 22:30:54 +0200 Subject: [PATCH 69/85] 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 231808b1c58c2f60584b8134983f7c2d86849ffb Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 7 Nov 2024 23:32:22 +0100 Subject: [PATCH 70/85] 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 cf956bf40bfe82b297314fb931572c1cd8c79174 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 7 Nov 2024 23:36:13 +0100 Subject: [PATCH 71/85] 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 b988a2ee518bbad6c1c4e603df7863cb1bd2b980 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 7 Nov 2024 23:37:50 +0100 Subject: [PATCH 72/85] 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 bb961cb369357fb29201355780fecb859bea5609 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 7 Nov 2024 23:59:37 +0100 Subject: [PATCH 73/85] 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 2ff3d07c89407163ec35ccca5f37c950409c3585 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Fri, 8 Nov 2024 00:10:06 +0100 Subject: [PATCH 74/85] 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] From 0a893cc6558f8f9a9f3d56f127434eb868800c42 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 9 Nov 2024 11:58:23 +0100 Subject: [PATCH 75/85] HRTIM - Fix some warnings --- src/hrtim/capture.rs | 3 +- src/hrtim/control.rs | 6 +- src/hrtim/event.rs | 3 +- src/hrtim/event.rs_old | 619 ++++++++++++++++++++++++++++++++++++++++ src/hrtim/mod.rs | 3 + src/hrtim/output.rs | 40 ++- src/hrtim/output.rs_old | 300 +++++++++++++++++++ src/hrtim/timer.rs | 26 +- 8 files changed, 961 insertions(+), 39 deletions(-) create mode 100644 src/hrtim/event.rs_old create mode 100644 src/hrtim/output.rs_old diff --git a/src/hrtim/capture.rs b/src/hrtim/capture.rs index f2081344..831ac7ae 100644 --- a/src/hrtim/capture.rs +++ b/src/hrtim/capture.rs @@ -25,7 +25,8 @@ pub enum CountingDirection { /// Implemented for /// * TIM's update event /// * EEVT1-10 -/// TODO: This sould be implemeted +/// +/// TODO: /// * All neighbor timers CMP1, CPM2, OUT1_RST and OUT1_SET events pub trait CaptureEvent { const BITS: u32; diff --git a/src/hrtim/control.rs b/src/hrtim/control.rs index 234d25d1..6173d887 100644 --- a/src/hrtim/control.rs +++ b/src/hrtim/control.rs @@ -211,9 +211,9 @@ impl HrTimCalibrated { } } -impl<'a> Into<&'a mut HrPwmCtrl> for &'a mut HrPwmControl { - fn into(self) -> &'a mut HrPwmCtrl { - &mut self.control +impl<'a> From<&'a mut HrPwmControl> for &'a mut HrPwmCtrl { + fn from(val: &'a mut HrPwmControl) -> Self { + &mut val.control } } diff --git a/src/hrtim/event.rs b/src/hrtim/event.rs index 5c472809..29a1f7b9 100644 --- a/src/hrtim/event.rs +++ b/src/hrtim/event.rs @@ -3,6 +3,8 @@ pub trait EventSource { const BITS: u32; } +/// Event that can be used reset the timer counter +/// /// Done: /// * [x] Eev1-10 /// * [x] Master period @@ -10,7 +12,6 @@ pub trait EventSource { /// * [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; } diff --git a/src/hrtim/event.rs_old b/src/hrtim/event.rs_old new file mode 100644 index 00000000..65258c1c --- /dev/null +++ b/src/hrtim/event.rs_old @@ -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_old::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/mod.rs b/src/hrtim/mod.rs index d0666197..ae6d522d 100644 --- a/src/hrtim/mod.rs +++ b/src/hrtim/mod.rs @@ -121,6 +121,7 @@ pub enum InterleavedMode { /// /// Automatically force /// * Cr1 to PERIOD / 2 (not visable through `get_duty`). + /// /// Automatically updates when changing period /// /// NOTE: Affects Cr1 @@ -131,6 +132,7 @@ pub enum InterleavedMode { /// 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 @@ -143,6 +145,7 @@ pub enum InterleavedMode { /// * 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 diff --git a/src/hrtim/output.rs b/src/hrtim/output.rs index f0d140d2..e3ba34bb 100644 --- a/src/hrtim/output.rs +++ b/src/hrtim/output.rs @@ -14,6 +14,10 @@ use crate::{ stm32::HRTIM_COMMON, }; +mod sealed { + pub trait Sealed {} +} + macro_rules! hrtim_out { ($($TIMX:ident: $out_type:ident: $tXYoen:ident, $tXYodis:ident, $tXYods:ident, $setXYr:ident, $rstXYr:ident,)+) => {$( impl HrOutput<$TIMX, PSCL> for $out_type<$TIMX, PSCL> { @@ -136,13 +140,20 @@ impl State { } } -pub unsafe trait ToHrOut { +pub trait ToHrOut: sealed::Sealed { type Out; fn connect_to_hrtim(self); } -unsafe impl ToHrOut for (PA, PB) +impl sealed::Sealed for (PA, PB) +where + PA: ToHrOut, + PB: ToHrOut, +{ +} + +impl ToHrOut for (PA, PB) where PA: ToHrOut, PB: ToHrOut, @@ -161,16 +172,10 @@ pub struct HrOut2(PhantomData<(TIM, PSCL)>); macro_rules! pins { ($($TIMX:ty: CH1: $CH1:ident<$CH1_AF:ident>, CH2: $CH2:ident<$CH2_AF:ident>)+) => { $( - /*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 sealed::Sealed<$TIMX> for $CH1> {} + impl sealed::Sealed<$TIMX> for $CH2> {} - */ - unsafe impl ToHrOut<$TIMX> for $CH1> { + impl ToHrOut<$TIMX> for $CH1> { type Out = HrOut1<$TIMX, PSCL>; fn connect_to_hrtim(self) { @@ -178,21 +183,13 @@ macro_rules! pins { } } - unsafe impl ToHrOut<$TIMX> for $CH2> { + 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> { - type Out

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

= HrOut2<$TIMX, P>; - }*/ )+ } } @@ -212,7 +209,8 @@ impl Pins for () { type Channel = (); } -unsafe impl ToHrOut for () { +impl sealed::Sealed for () {} +impl ToHrOut for () { type Out = (); fn connect_to_hrtim(self) {} diff --git a/src/hrtim/output.rs_old b/src/hrtim/output.rs_old new file mode 100644 index 00000000..0ab07d6d --- /dev/null +++ b/src/hrtim/output.rs_old @@ -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_old::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 index 689d7bd7..344234e9 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -91,6 +91,12 @@ pub trait HrSlaveTimer: HrTimer { ); } +pub struct TimerSplitCapture { + pub timer: HrTim, + pub ch1: HrCapt, + pub ch2: HrCapt, +} + /// Trait for unsplit slave timer which still contains its capture modules pub trait HrSlaveTimerCpt: HrSlaveTimer { type CaptureCh1: HrCapture; @@ -100,11 +106,7 @@ pub trait HrSlaveTimerCpt: HrSlaveTimer { fn capture_ch2(&mut self) -> &mut ::CaptureCh2; fn split_capture( self, - ) -> ( - HrTim, - HrCapt, - HrCapt, - ); + ) -> TimerSplitCapture; } macro_rules! hrtim_timer { @@ -267,7 +269,7 @@ macro_rules! hrtim_timer { &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>) { + fn split_capture(self) -> TimerSplitCapture<$TIMX, PSCL, capture::Ch1, capture::Ch2> { let HrTim{ _timer, _prescaler, @@ -275,16 +277,16 @@ macro_rules! hrtim_timer { capture_ch2, } = self; - ( - HrTim{ + TimerSplitCapture { + timer: HrTim{ _timer, _prescaler, capture_ch1: (), capture_ch2: (), }, - capture_ch1, - capture_ch2, - ) + ch1: capture_ch1, + ch2: capture_ch2, + } } } @@ -295,8 +297,6 @@ macro_rules! hrtim_timer { } /// Timer Update event - /// - /// TODO: What dows this mean? impl super::capture::CaptureEvent<$TIMX, PSCL> for HrTim<$TIMX, PSCL, CPT1, CPT2> { const BITS: u32 = 1 << 1; } From 469b9931dcedc64c9d1c870482289aaf99bfa608 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 16 Nov 2024 22:10:54 +0100 Subject: [PATCH 76/85] Update for new pac changes --- Cargo.toml | 3 +- src/hrtim/capture.rs | 52 ++++---- src/hrtim/compare_register.rs | 82 ++++++------- src/hrtim/fault.rs | 2 +- src/hrtim/mod.rs | 225 +++++++++++++++++----------------- src/hrtim/output.rs | 24 ++-- src/hrtim/timer.rs | 42 +++---- 7 files changed, 205 insertions(+), 225 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6ceb5c27..5c8dd760 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,8 @@ version = "0.0.2" [dependencies] nb = "0.1.1" #stm32g4 = { git = "https://github.com/stm32-rs/stm32-rs-nightlies" } #"0.15.1" -stm32g4 = { version = "0.17.0", package = "stm32g4-staging" } +#stm32g4 = { version = "0.18.0", package = "stm32g4-staging" } +stm32g4 = { path = "../stm32-rs/stm32g4" } paste = "1.0" bitflags = "1.2" vcell = "0.1" diff --git a/src/hrtim/capture.rs b/src/hrtim/capture.rs index 831ac7ae..b1908012 100644 --- a/src/hrtim/capture.rs +++ b/src/hrtim/capture.rs @@ -149,7 +149,12 @@ pub fn dma_value_to_signed(x: u32, period: u16) -> i32 { } macro_rules! impl_capture { - ($($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),+) => {$( + ($($TIMX:ident: $mux:expr),+) => {$( + impl_capture!($TIMX: Ch1, cpt1r, cpt1cr, cpt1, cpt1ie, cpt1de, cpt1c, $mux); + impl_capture!($TIMX: Ch2, cpt2r, cpt2cr, cpt2, cpt2ie, cpt2de, cpt2c, $mux); + )+}; + + ($TIMX:ident: $CH:ident, $cptXr:ident, $cptXcr:ident, $cptX:ident, $cptXie:ident, $cptXde:ident, $cptXc:ident, $mux:expr) => { impl HrCapt<$TIMX, PSCL, $CH, NoDma> { /// Add event to capture /// @@ -160,7 +165,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.$cptXcr().modify(|r, w| w.bits(r.bits() | E::BITS)); } } @@ -170,7 +175,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.$cptXcr().modify(|r, w| w.bits(r.bits() & !E::BITS)); } } @@ -179,7 +184,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.$cptXcr().modify(|_, w| w.swcpt().set_bit()); } // TODO: It would be sufficient to instead of hr_control only require exclusive access to the owning timer @@ -188,13 +193,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 } @@ -204,13 +209,13 @@ 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.$cptXr().read(); let dir = match data.dir().bit() { true => CountingDirection::Down, false => CountingDirection::Up, }; - let value = data.$cptXx().bits(); + let value = data.cpt().bits(); (value, dir) } @@ -219,14 +224,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().bit(true)); } 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() } } @@ -234,32 +239,21 @@ macro_rules! impl_capture { #[inline(always)] fn address(&self) -> u32 { let tim = unsafe { &*$TIMX::ptr() }; - &tim.$cptXYr() as *const _ as u32 + &tim.$cptXr() 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, 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, 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, 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, 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, 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, cpt1de, cpt1c, cpt1, DmaMuxResources::HRTIM_TIMF, - HRTIM_TIMF: Ch2, cpt2fr, cpt2fcr, cpt2x, timfdier, timficr, timfisr, cpt2ie, cpt2de, cpt2c, cpt2, DmaMuxResources::HRTIM_TIMF + HRTIM_TIMA: DmaMuxResources::HRTIM_TIMA, + HRTIM_TIMB: DmaMuxResources::HRTIM_TIMB, + HRTIM_TIMC: DmaMuxResources::HRTIM_TIMC, + HRTIM_TIMD: DmaMuxResources::HRTIM_TIMD, + HRTIM_TIME: DmaMuxResources::HRTIM_TIME, + HRTIM_TIMF: DmaMuxResources::HRTIM_TIMF } diff --git a/src/hrtim/compare_register.rs b/src/hrtim/compare_register.rs index 1cdaf69c..0b54c741 100644 --- a/src/hrtim/compare_register.rs +++ b/src/hrtim/compare_register.rs @@ -21,17 +21,17 @@ use super::adc_trigger::Adc6810Trigger as Adc6810; macro_rules! hrtim_cr_helper { (HRTIM_MASTER: $cr_type:ident: - $cmpXYr:ident, $cmpYx:ident, + $cmpXYr:ident, [$(($Trigger:ty: $trigger_bits:expr)),*], [$(($event_dst:ident, $tim_event_index:expr)),*], $bit_index:literal ) => { // Strip bit_index since master timer has other bits that are common across all destinations - hrtim_cr_helper!(HRTIM_MASTER: $cr_type: $cmpXYr, $cmpYx, [$(($Trigger: $trigger_bits)),*], [$(($event_dst, $tim_event_index)),*]); + hrtim_cr_helper!(HRTIM_MASTER: $cr_type: $cmpXYr, [$(($Trigger: $trigger_bits)),*], [$(($event_dst, $tim_event_index)),*]); }; ($TIMX:ident: $cr_type:ident: - $cmpXYr:ident, $cmpYx:ident, + $cmpXYr:ident, [$(($Trigger:ty: $trigger_bits:expr)),*], [$(($event_dst:ident, $tim_event_index:expr)),*] $(, $bit_index:literal)* @@ -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().cmp().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.cmp().bits(duty) }); } } @@ -73,67 +73,67 @@ macro_rules! hrtim_cr_helper { macro_rules! hrtim_cr { ($($TIMX:ident: [ - [$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)),*]] + [$(($cr1_trigger:ident: $cr1_trigger_bits:expr)),*], [$(($cr1_event_dst:ident, $cr1_tim_event_index:expr)),*], + [$(($cr2_trigger:ident: $cr2_trigger_bits:expr)),*], [$(($cr2_event_dst:ident, $cr2_tim_event_index:expr)),*], + [$(($cr3_trigger:ident: $cr3_trigger_bits:expr)),*], [$(($cr3_event_dst:ident, $cr3_tim_event_index:expr)),*], + [$(($cr4_trigger:ident: $cr4_trigger_bits:expr)),*], [$(($cr4_event_dst:ident, $cr4_tim_event_index:expr)),*] ]),+) => {$( - hrtim_cr_helper!($TIMX: HrCr1: $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); + hrtim_cr_helper!($TIMX: HrCr1: cmp1r, [$(($cr1_trigger: $cr1_trigger_bits)),*], [$(($cr1_event_dst, $cr1_tim_event_index)),*], 3); + hrtim_cr_helper!($TIMX: HrCr2: cmp2r, [$(($cr2_trigger: $cr2_trigger_bits)),*], [$(($cr2_event_dst, $cr2_tim_event_index)),*], 4); + hrtim_cr_helper!($TIMX: HrCr3: cmp3r, [$(($cr3_trigger: $cr3_trigger_bits)),*], [$(($cr3_event_dst, $cr3_tim_event_index)),*], 5); + hrtim_cr_helper!($TIMX: HrCr4: cmp4r, [$(($cr4_trigger: $cr4_trigger_bits)),*], [$(($cr4_event_dst, $cr4_tim_event_index)),*], 6); )+}; } // 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) ], []] + [(Adc13: 1 << 0), (Adc24: 1 << 0), (Adc579: 0), (Adc6810: 0) ], [], + [(Adc13: 1 << 1), (Adc24: 1 << 1), (Adc579: 1), (Adc6810: 1) ], [], + [(Adc13: 1 << 2), (Adc24: 1 << 2), (Adc579: 2), (Adc6810: 2) ], [], + [(Adc13: 1 << 3), (Adc24: 1 << 3), (Adc579: 3), (Adc6810: 3) ], [] ], HRTIM_TIMA: [ - [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, 1), (HRTIM_TIMD, 1) ], + [ (Adc24: 1 << 10), (Adc6810: 10)], [(HRTIM_TIMB, 2), (HRTIM_TIMC, 1) ], + [(Adc13: 1 << 11), (Adc579: 10) ], [(HRTIM_TIMC, 2), (HRTIM_TIMF, 1) ], + [(Adc13: 1 << 12), (Adc24: 1 << 12), (Adc579: 11), (Adc6810: 11)], [(HRTIM_TIMD, 2), (HRTIM_TIME, 1) ] ], HRTIM_TIMB: [ - [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_TIMA, 1), (HRTIM_TIMF, 2) ], + [ (Adc24: 1 << 14), (Adc6810: 13)], [(HRTIM_TIMA, 2), (HRTIM_TIMC, 3), (HRTIM_TIMD, 3)], + [(Adc13: 1 << 16), (Adc579: 14) ], [(HRTIM_TIMC, 4), (HRTIM_TIME, 2) ], + [(Adc13: 1 << 17), (Adc24: 1 << 16), (Adc579: 15), (Adc6810: 14)], [(HRTIM_TIMD, 4), (HRTIM_TIME, 3), (HRTIM_TIMF, 3)] ], HRTIM_TIMC: [ - [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_TIME, 4), (HRTIM_TIMF, 4) ], + [ (Adc24: 1 << 18), (Adc6810: 16)], [(HRTIM_TIMA, 3), (HRTIM_TIME, 5) ], + [(Adc13: 1 << 21), (Adc579: 18) ], [(HRTIM_TIMA, 4), (HRTIM_TIMB, 3) ], + [(Adc13: 1 << 22), (Adc24: 1 << 20), (Adc579: 19), (Adc6810: 17)], [(HRTIM_TIMB, 4), (HRTIM_TIMD, 5), (HRTIM_TIMF, 5)] ], HRTIM_TIMD: [ - [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_TIMA, 5), (HRTIM_TIME, 6) ], + [ (Adc24: 1 << 23), (Adc6810: 20)], [(HRTIM_TIMA, 6), (HRTIM_TIMC, 5), (HRTIM_TIME, 7)], + [(Adc13: 1 << 25), (Adc579: 21) ], [(HRTIM_TIMB, 5), (HRTIM_TIMF, 6) ], + [(Adc13: 1 << 26), (Adc24: 1 << 25), (Adc579: 22), (Adc6810: 21)], [(HRTIM_TIMB, 6), (HRTIM_TIMC, 6), (HRTIM_TIMF, 7)] ], HRTIM_TIME: [ - [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_TIMB, 7), (HRTIM_TIMD, 6) ], + [ (Adc24: 1 << 28), (Adc6810: 24)], [(HRTIM_TIMB, 8), (HRTIM_TIMF, 8) ], + [(Adc13: 1 << 29), (Adc24: 1 << 29), (Adc579: 24), (Adc6810: 25)], [(HRTIM_TIMA, 7), (HRTIM_TIMC, 7), (HRTIM_TIMF, 9)], + [(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) ], [(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) ]] + [ (Adc24: 1 << 15) ], [(HRTIM_TIMD, 8) ], + [(Adc13: 1 << 10), (Adc24: 1 << 11), (Adc579: 27), (Adc6810: 28)], [(HRTIM_TIMC, 9) ], + [(Adc13: 1 << 15), (Adc579: 28), (Adc6810: 29)], [(HRTIM_TIMB, 9), (HRTIM_TIMD, 9), (HRTIM_TIME, 8)], + [(Adc13: 1 << 20), (Adc24: 1 << 19), (Adc579: 29), (Adc6810: 30)], [(HRTIM_TIMA, 9), (HRTIM_TIME, 9) ] ] } diff --git a/src/hrtim/fault.rs b/src/hrtim/fault.rs index 2447c793..7e390014 100644 --- a/src/hrtim/fault.rs +++ b/src/hrtim/fault.rs @@ -267,7 +267,7 @@ macro_rules! impl_flt_monitor { } impl_flt_monitor!( - FltMonitorSys: (sysflt, sysfltc, sysflte), + FltMonitorSys: (sysflt, sysfltc, sysfltie), FltMonitor1: (flt1, flt1c, flt1ie), FltMonitor2: (flt2, flt2c, flt2ie), FltMonitor3: (flt3, flt3c, flt3ie), diff --git a/src/hrtim/mod.rs b/src/hrtim/mod.rs index ae6d522d..0609a872 100644 --- a/src/hrtim/mod.rs +++ b/src/hrtim/mod.rs @@ -205,10 +205,7 @@ 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, $eefXr1:ident, $eefXr2:ident, $Xeefr3:ident, $outXr:ident, $dtXr:ident)*), - ) => {{ + ($this:expr, $PreloadSource:ident, $TIMX:ident, $($out:ident)*) => {{ let tim = unsafe { &*$TIMX::ptr() }; let (period, prescaler_bits) = match $this.count { CountSettings::Period(period) => (period as u32, PSCL::BITS as u16), @@ -225,7 +222,7 @@ macro_rules! hrtim_finalize_body { }; // Write prescaler and any special modes - tim.$timXcr().modify(|_r, w| unsafe { + tim.cr().modify(|_r, w| unsafe { w // Enable Continuous mode .cont().bit($this.timer_mode == HrTimerMode::Continuous) @@ -240,31 +237,37 @@ macro_rules! hrtim_finalize_body { .half().bit(half) // Set prescaler - .$ck_psc().bits(prescaler_bits as u8) + .ckpsc().bits(prescaler_bits as u8) }); $( - tim.$timXcr2().modify(|_r, w| + // Only available for timers with outputs(not HRTIM_MASTER) + #[allow(unused)] + let $out = (); + + tim.cr2().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| + + tim.cr().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.perr().write(|w| unsafe { w.per().bits(period as u16) }); // Enable fault sources and lock configuration $(unsafe { + // Only available for timers with outputs(not HRTIM_MASTER) + #[allow(unused)] + let $out = (); + // Enable fault sources let fault_enable_bits = $this.fault_enable_bits as u32; - tim.$fltXr().write(|w| w + tim.fltr().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) @@ -274,9 +277,9 @@ macro_rules! hrtim_finalize_body { ); // ... and lock configuration - tim.$fltXr().modify(|_r, w| w.fltlck().set_bit()); + tim.fltr().modify(|_r, w| w.fltlck().set_bit()); - tim.$outXr().modify(|_r, w| w + tim.outr().modify(|_r, w| w // Set actions on fault for both outputs .fault1().bits($this.fault1_bits) .fault2().bits($this.fault2_bits) @@ -296,39 +299,39 @@ 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.dtr().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) + .dtr().bits(deadtime_rising_value) + .sdtr().bit(deadtime_rising_sign) + .dtf().bits(deadtime_falling_value) + .sdtf().bit(deadtime_falling_sign) // Lock configuration - .dtflkx().set_bit() - .dtfslkx().set_bit() - .dtrlkx().set_bit() - .dtrslkx().set_bit() + .dtflk().set_bit() + .dtfslk().set_bit() + .dtrlk().set_bit() + .dtrslk().set_bit() ); - tim.$outXr().modify(|_r, w| w.dten().set_bit()); + tim.outr().modify(|_r, w| w.dten().set_bit()); } // External event configs let eev_cfg = $this.eev_cfg.clone(); - tim.$eefXr1().write(|w| w + tim.eefr1().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.eefr2().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.eefr3().write(|w| w .eevace().bit(eev_cfg.event_counter_enable_bit) // External Event A Counter Reset"] //.eevacres().bit() @@ -339,13 +342,13 @@ macro_rules! hrtim_finalize_body { })* - hrtim_finalize_body!($PreloadSource, $this, tim, $timXcr); + hrtim_finalize_body!($PreloadSource, $this, tim); // Set repetition counter - unsafe { tim.$rep().write(|w| w.$repx().bits($this.repetition_counter)); } + unsafe { tim.repr().write(|w| w.rep().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,23 +362,23 @@ macro_rules! hrtim_finalize_body { } }}; - (PreloadSource, $this:expr, $tim:expr, $timXcr:ident) => {{ + (PreloadSource, $this:expr, $tim:expr) => {{ match $this.preload_source { Some(PreloadSource::OnCounterReset) => { - $tim.$timXcr().modify(|_r, w| w - .tx_rstu().set_bit() + $tim.cr().modify(|_r, w| w + .trstu().set_bit() .preen().set_bit() ); }, Some(PreloadSource::OnMasterTimerUpdate) => { - $tim.$timXcr().modify(|_r, w| w + $tim.cr().modify(|_r, w| w .mstu().set_bit() .preen().set_bit() ); } Some(PreloadSource::OnRepetitionUpdate) => { - $tim.$timXcr().modify(|_r, w| w - .tx_repu().set_bit() + $tim.cr().modify(|_r, w| w + .trepu().set_bit() .preen().set_bit() ); } @@ -383,10 +386,10 @@ macro_rules! hrtim_finalize_body { } }}; - (MasterPreloadSource, $this:expr, $tim:expr, $timXcr:ident) => {{ + (MasterPreloadSource, $this:expr, $tim:expr) => {{ match $this.preload_source { Some(MasterPreloadSource::OnMasterRepetitionUpdate) => { - $tim.$timXcr().modify(|_r, w| w + $tim.cr().modify(|_r, w| w .mrepu().set_bit() .preen().set_bit() ); @@ -501,8 +504,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, $eefXr1:ident, $eefXr2:ident, $Xeefr3:ident, $outXr:ident, $dtXr:ident),)+) => { + ($($TIMX:ident: $($out:ident)*,)+) => { $( impl HrPwmAdvExt for $TIMX { type PreloadSource = PreloadSource; @@ -566,7 +568,7 @@ macro_rules! hrtim_hal { hrtim_finalize_body!( self, PreloadSource, - $TIMX: ($timXcr, ck_pscx, $perXr, perx, $tXcen, $rep, $repx, $dier, $repie, $timXcr2, $fltXr, $eefXr1, $eefXr2, $Xeefr3, $outXr, $dtXr), + $TIMX, $($out)* ) } @@ -658,86 +660,79 @@ macro_rules! hrtim_hal { }; } -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: ToHrOut<$TIMX>, - { - // TODO: That 32x factor... Is that included below, or should we - // do that? Also that will likely risk overflowing u32 since - // 170MHz * 32 = 5.44GHz > u32::MAX.Hz() - let clk = HertzU64::from(HRTIM_COMMON::get_timer_frequency(&rcc.clocks)) * 32; - - HrPwmBuilder { - _tim: PhantomData, - _prescaler: PhantomData, - pins, - timer_mode: HrTimerMode::Continuous, - fault_enable_bits: 0b000000, - fault1_bits: 0b00, - fault2_bits: 0b00, - counting_direction: HrCountingDirection::Up, - base_freq: clk, - count: CountSettings::Period(u16::MAX), - preload_source: None, - enable_push_pull: false, - interleaved_mode: InterleavedMode::Disabled, - repetition_counter: 0, - deadtime: None, - enable_repetition_interrupt: false, - eev_cfg: EevCfgs::default(), - out1_polarity: Polarity::ActiveHigh, - out2_polarity: Polarity::ActiveHigh, - } - } - } - impl - HrPwmBuilder<$TIMX, PSCL, MasterPreloadSource, PINS> - where - PSCL: HrtimPrescaler, - PINS: ToHrOut<$TIMX>, - { - 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> - ), - timer::DmaChannel<$TIMX>, - ) { - - hrtim_finalize_body!(self, MasterPreloadSource, $TIMX: ($timXcr, $ck_psc, $perXr, $perx, $tXcen, $rep, $rep, $dier, $repie),) - } +impl HrPwmAdvExt for HRTIM_MASTER { + type PreloadSource = MasterPreloadSource; - hrtim_common_methods!($TIMX, MasterPreloadSource); + fn pwm_advanced( + self, + pins: PINS, + rcc: &mut Rcc, + ) -> HrPwmBuilder + where + PINS: ToHrOut, + { + // TODO: That 32x factor... Is that included below, or should we + // do that? Also that will likely risk overflowing u32 since + // 170MHz * 32 = 5.44GHz > u32::MAX.Hz() + let clk = HertzU64::from(HRTIM_COMMON::get_timer_frequency(&rcc.clocks)) * 32; + + HrPwmBuilder { + _tim: PhantomData, + _prescaler: PhantomData, + pins, + timer_mode: HrTimerMode::Continuous, + fault_enable_bits: 0b000000, + fault1_bits: 0b00, + fault2_bits: 0b00, + counting_direction: HrCountingDirection::Up, + base_freq: clk, + count: CountSettings::Period(u16::MAX), + preload_source: None, + enable_push_pull: false, + interleaved_mode: InterleavedMode::Disabled, + repetition_counter: 0, + deadtime: None, + enable_repetition_interrupt: false, + eev_cfg: EevCfgs::default(), + out1_polarity: Polarity::ActiveHigh, + out2_polarity: Polarity::ActiveHigh, } - )*} + } } -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), - 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), +impl + HrPwmBuilder +where + PSCL: HrtimPrescaler, + PINS: ToHrOut, +{ + pub fn finalize(self, _control: &mut HrPwmControl) -> ( + HrTim, + HrCapt, + >, ( + HrCr1, + HrCr2, + HrCr3, + HrCr4 + ), + timer::DmaChannel, + ) { + + hrtim_finalize_body!(self, MasterPreloadSource, HRTIM_MASTER,) + } + + hrtim_common_methods!(HRTIM_MASTER, MasterPreloadSource); } -hrtim_hal_master! { - HRTIM_MASTER: (mcr, ck_psc, mper, mper, mrep, mcen, mdier, mrepie), +hrtim_hal! { + HRTIM_TIMA: out, + HRTIM_TIMB: out, + HRTIM_TIMC: out, + HRTIM_TIMD: out, + HRTIM_TIME: out, + HRTIM_TIMF: out, } /// # Safety diff --git a/src/hrtim/output.rs b/src/hrtim/output.rs index e3ba34bb..6d80b78d 100644 --- a/src/hrtim/output.rs +++ b/src/hrtim/output.rs @@ -70,23 +70,23 @@ macro_rules! hrtim_out { } hrtim_out! { - HRTIM_TIMA: HrOut1: ta1oen, ta1odis, ta1ods, seta1r, rsta1r, - HRTIM_TIMA: HrOut2: ta2oen, ta2odis, ta2ods, seta2r, rsta2r, + HRTIM_TIMA: HrOut1: ta1oen, ta1odis, ta1ods, set1r, rst1r, + HRTIM_TIMA: HrOut2: ta2oen, ta2odis, ta2ods, set2r, rst2r, - HRTIM_TIMB: HrOut1: tb1oen, tb1odis, tb1ods, setb1r, rstb1r, - HRTIM_TIMB: HrOut2: tb2oen, tb2odis, tb2ods, setb2r, rstb2r, + HRTIM_TIMB: HrOut1: tb1oen, tb1odis, tb1ods, set1r, rst1r, + HRTIM_TIMB: HrOut2: tb2oen, tb2odis, tb2ods, set2r, rst2r, - HRTIM_TIMC: HrOut1: tc1oen, tc1odis, tc1ods, setc1r, rstc1r, - HRTIM_TIMC: HrOut2: tc2oen, tc2odis, tc2ods, setc2r, rstc2r, + HRTIM_TIMC: HrOut1: tc1oen, tc1odis, tc1ods, set1r, rst1r, + HRTIM_TIMC: HrOut2: tc2oen, tc2odis, tc2ods, set2r, rst2r, - HRTIM_TIMD: HrOut1: td1oen, td1odis, td1ods, setd1r, rstd1r, - HRTIM_TIMD: HrOut2: td2oen, td2odis, td2ods, setd2r, rstd2r, + HRTIM_TIMD: HrOut1: td1oen, td1odis, td1ods, set1r, rst1r, + HRTIM_TIMD: HrOut2: td2oen, td2odis, td2ods, set2r, rst2r, - HRTIM_TIME: HrOut1: te1oen, te1odis, te1ods, sete1r, rste1r, - HRTIM_TIME: HrOut2: te2oen, te2odis, te2ods, sete2r, rste2r, + HRTIM_TIME: HrOut1: te1oen, te1odis, te1ods, set1r, rst1r, + HRTIM_TIME: HrOut2: te2oen, te2odis, te2ods, set2r, rst2r, - HRTIM_TIMF: HrOut1: tf1oen, tf1odis, tf1ods, setf1r, rstf1r, - HRTIM_TIMF: HrOut2: tf2oen, tf2odis, tf2ods, setf2r, rstf2r, + HRTIM_TIMF: HrOut1: tf1oen, tf1odis, tf1ods, set1r, rst1r, + HRTIM_TIMF: HrOut2: tf2oen, tf2odis, tf2ods, set2r, rst2r, } pub trait HrOutput { diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs index 344234e9..2b51fa2f 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -112,17 +112,7 @@ pub trait HrSlaveTimerCpt: HrSlaveTimer { 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, $tXudis:ident, $(($rstXr:ident))*, )+) => {$( @@ -133,12 +123,12 @@ macro_rules! hrtim_timer { fn get_period(&self) -> u16 { let tim = unsafe { &*$TIMX::ptr() }; - tim.$perXr().read().$perx().bits() + tim.perr().read().per().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.perr().write(|w| unsafe { w.per().bits(period as u16) }); } /// Start timer @@ -147,7 +137,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.cr().modify(|_r, w| { w.$tXcen().set_bit() }); } /// Stop timer @@ -155,7 +145,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.cr().modify(|_r, w| { w.$tXcen().set_bit() }); } /// Stop timer and reset counter @@ -164,7 +154,7 @@ macro_rules! hrtim_timer { // Reset counter let tim = unsafe { &*$TIMX::ptr() }; - unsafe { tim.$cntXr().write(|w| w.$cntx().bits(0)); } + unsafe { tim.cntr().write(|w| w.cnt().bits(0)); } } /// Make a handle to this timers reset event to use as adc trigger @@ -180,7 +170,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().bit(true)); } /// Disable register updates @@ -211,13 +201,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.repr().write(|w| w.rep().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)); } } @@ -329,14 +319,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, 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_MASTER: mcen, mudis,, + + HRTIM_TIMA: tacen, taudis, (rstr), + HRTIM_TIMB: tbcen, tbudis, (rstr), + HRTIM_TIMC: tccen, tcudis, (rstr), + HRTIM_TIMD: tdcen, tdudis, (rstr), + HRTIM_TIME: tecen, teudis, (rstr), + HRTIM_TIMF: tfcen, tfudis, (rstr), } hrtim_timer_adc_trigger! { From 6af8dccab49acb6d977aa29ee987f6ca15d98520 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sun, 17 Nov 2024 00:06:05 +0100 Subject: [PATCH 77/85] HRTIM - Use non_exhaustive on EevInput to make its constructor private Co-authored-by: Zgarbul Andrey --- src/hrtim/external_event.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/hrtim/external_event.rs b/src/hrtim/external_event.rs index ee88262e..3a7b9e1b 100644 --- a/src/hrtim/external_event.rs +++ b/src/hrtim/external_event.rs @@ -30,23 +30,22 @@ pub struct EevInputs { 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 }, + eev_input1: EevInput, + eev_input2: EevInput, + eev_input3: EevInput, + eev_input4: EevInput, + eev_input5: EevInput, + eev_input6: EevInput, + eev_input7: EevInput, + eev_input8: EevInput, + eev_input9: EevInput, + eev_input10: EevInput, } } } -pub struct EevInput { - _x: PhantomData<()>, -} +#[non_exhaustive] +pub struct EevInput; /// This is implemented for types that can be used as inputs to the eev /// # Safety From b524806a2eed36c23d75ef60f193de1b43fbaa99 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sun, 17 Nov 2024 21:02:10 +0100 Subject: [PATCH 78/85] Avoid using PhantomData<()> to make constructor private --- src/comparator.rs | 19 +++++------ src/hrtim/control.rs | 66 ++++++++++++++++--------------------- src/hrtim/external_event.rs | 11 +++---- src/hrtim/fault.rs | 33 ++++++++----------- 4 files changed, 55 insertions(+), 74 deletions(-) diff --git a/src/comparator.rs b/src/comparator.rs index b5e80fc4..8b5f2851 100644 --- a/src/comparator.rs +++ b/src/comparator.rs @@ -56,9 +56,8 @@ impl EnabledState for Locked {} macro_rules! impl_comp { ($($t:ident: $reg:ident,)+) => {$( - pub struct $t { - _rb: PhantomData<()>, - } + #[non_exhaustive] + pub struct $t; impl $t { pub fn csr(&self) -> &$crate::stm32::comp::CCSR { @@ -548,31 +547,31 @@ pub fn split(_comp: COMP, rcc: &mut Rcc) -> Comparators { rcc.rb.apb2rstr().modify(|_, w| w.syscfgrst().clear_bit()); ( - COMP1 { _rb: PhantomData }, - COMP2 { _rb: PhantomData }, - COMP3 { _rb: PhantomData }, - COMP4 { _rb: PhantomData }, + COMP1, + COMP2, + COMP3, + COMP4, #[cfg(any( feature = "stm32g473", feature = "stm32g483", feature = "stm32g474", feature = "stm32g484" ))] - COMP5 { _rb: PhantomData }, + COMP5, #[cfg(any( feature = "stm32g473", feature = "stm32g483", feature = "stm32g474", feature = "stm32g484" ))] - COMP6 { _rb: PhantomData }, + COMP6, #[cfg(any( feature = "stm32g473", feature = "stm32g483", feature = "stm32g474", feature = "stm32g484" ))] - COMP7 { _rb: PhantomData }, + COMP7, ) } diff --git a/src/hrtim/control.rs b/src/hrtim/control.rs index 6173d887..045abcb1 100644 --- a/src/hrtim/control.rs +++ b/src/hrtim/control.rs @@ -1,5 +1,3 @@ -use core::marker::PhantomData; - use crate::{ hrtim::fault::{ FltMonitor1, FltMonitor2, FltMonitor3, FltMonitor4, FltMonitor5, FltMonitor6, FltMonitorSys, @@ -140,7 +138,7 @@ impl HrTimOngoingCalibration { unsafe { self.init() }; ( - HrTimCalibrated { _x: PhantomData }, + HrTimCalibrated, unsafe { FaultInputs::new() }, unsafe { EevInputs::new() }, ) @@ -180,33 +178,31 @@ impl HrTimOngoingCalibration { /// 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<()>, -} +#[non_exhaustive] +pub struct HrTimCalibrated; 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 }, - fault_3: FltMonitor3 { _x: PhantomData }, - 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 }, + control: HrPwmCtrl, + fault_sys: FltMonitorSys, + fault_1: FltMonitor1, + fault_2: FltMonitor2, + fault_3: FltMonitor3, + fault_4: FltMonitor4, + fault_5: FltMonitor5, + fault_6: FltMonitor6, + + adc_trigger1: Adc1Trigger, + adc_trigger2: Adc2Trigger, + adc_trigger3: Adc3Trigger, + adc_trigger4: Adc4Trigger, + adc_trigger5: Adc5Trigger, + adc_trigger6: Adc6Trigger, + adc_trigger7: Adc7Trigger, + adc_trigger8: Adc8Trigger, + adc_trigger9: Adc9Trigger, + adc_trigger10: Adc10Trigger, } } } @@ -220,14 +216,12 @@ impl<'a> From<&'a mut HrPwmControl> for &'a mut HrPwmCtrl { /// 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<()>, -} +#[non_exhaustive] +pub struct HrPwmCtrl; /// Used as a token to guarantee unique access to resources common to multiple timers +#[non_exhaustive] pub struct HrPwmControl { - _x: PhantomData<()>, - pub control: HrPwmCtrl, pub fault_sys: FltMonitorSys, @@ -253,9 +247,8 @@ pub struct HrPwmControl { macro_rules! impl_adc1234_trigger { ($($t:ident: [$trait_:ident, $adcXr:ident, $variant345:ident $(, $variant12:ident)*]),*) => {$( - pub struct $t { - _x: PhantomData<()>, - } + #[non_exhaustive] + pub struct $t; impl $t { pub fn enable_source(&mut self, _trigger: &T) { @@ -282,9 +275,8 @@ macro_rules! impl_adc1234_trigger { macro_rules! impl_adc5678910_trigger { ($($t:ident: [$trait_:ident, $adcXtrg:ident, $variant345:ident, $variant12:ident]),*) => {$( - pub struct $t { - _x: PhantomData<()>, - } + #[non_exhaustive] + pub struct $t; impl $t { pub fn enable_source(&mut self, _trigger: &T) { diff --git a/src/hrtim/external_event.rs b/src/hrtim/external_event.rs index 3a7b9e1b..74b6a539 100644 --- a/src/hrtim/external_event.rs +++ b/src/hrtim/external_event.rs @@ -1,5 +1,3 @@ -use core::marker::PhantomData; - 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}; @@ -9,10 +7,9 @@ use crate::stm32::HRTIM_COMMON; use super::control::HrTimCalibrated; +#[non_exhaustive] #[derive(Copy, Clone, PartialEq)] -pub struct ExternalEventSource { - _x: PhantomData<()>, -} +pub struct ExternalEventSource; pub struct EevInputs { pub eev_input1: EevInput<1>, @@ -292,7 +289,7 @@ macro_rules! impl_eev1_5_to_es { }); } - ExternalEventSource { _x: PhantomData } + ExternalEventSource } } @@ -334,7 +331,7 @@ macro_rules! impl_eev6_10_to_es { common.eecr3().modify(|_r, w| w.$eeXf().bits(filter_bits)); } - ExternalEventSource { _x: PhantomData } + ExternalEventSource } } diff --git a/src/hrtim/fault.rs b/src/hrtim/fault.rs index 7e390014..a4d0213e 100644 --- a/src/hrtim/fault.rs +++ b/src/hrtim/fault.rs @@ -1,5 +1,3 @@ -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}; @@ -75,14 +73,12 @@ macro_rules! impl_faults { )+) => {$( // This should NOT be Copy/Clone - pub struct $input { - pub(crate) _x: PhantomData<()> - } + #[non_exhaustive] + pub struct $input; + #[non_exhaustive] #[derive(Copy, Clone)] - pub struct $source { - _x: PhantomData<()> - } + pub struct $source; impl $input { pub fn bind_pin(self, pin: $pin>) -> SourceBuilder<$input> { @@ -127,9 +123,7 @@ macro_rules! impl_faults { common.$fltinrZ().modify(|_r, w| w.$fltWlck().set_bit()); } - $source { - _x: PhantomData - } + $source } pub fn polarity(mut self, polarity: super::Polarity) -> Self { @@ -173,12 +167,12 @@ pub struct FaultInputs { 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 }, + fault_input1: FaultInput1, + fault_input2: FaultInput2, + fault_input3: FaultInput3, + fault_input4: FaultInput4, + fault_input5: FaultInput5, + fault_input6: FaultInput6, } } } @@ -243,9 +237,8 @@ pub enum FaultSamplingFilter { macro_rules! impl_flt_monitor { ($($t:ident: ($fltx:ident, $fltxc:ident, $fltxie:ident),)+) => {$( - pub struct $t { - pub(crate) _x: PhantomData<()> - } + #[non_exhaustive] + pub struct $t; impl FaultMonitor for $t { fn enable_interrupt(&mut self, _hr_control: &mut HrPwmCtrl) { From fd92940065a5e9267e9355341b738e466bdb55e2 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 18 Nov 2024 20:06:49 +0100 Subject: [PATCH 79/85] Update to pac changes --- src/hrtim/capture.rs | 2 +- src/hrtim/fault.rs | 6 +++--- src/hrtim/timer.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/hrtim/capture.rs b/src/hrtim/capture.rs index b1908012..e08a2fbd 100644 --- a/src/hrtim/capture.rs +++ b/src/hrtim/capture.rs @@ -224,7 +224,7 @@ 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().bit(true)); + tim.icr().write(|w| w.$cptXc().clear()); } fn is_pending(&self) -> bool { diff --git a/src/hrtim/fault.rs b/src/hrtim/fault.rs index a4d0213e..c54cf9fb 100644 --- a/src/hrtim/fault.rs +++ b/src/hrtim/fault.rs @@ -152,7 +152,7 @@ impl_faults!( 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, + FaultInput6 => FaultSource6: PINS=[(PC10, AF13)], COMP=COMP5, 0b100000, fltinr2, flt6src, flt6src_1, flt6p, flt6f, flt6e, flt6lck, ); pub struct FaultInputs { @@ -253,7 +253,7 @@ macro_rules! impl_flt_monitor { 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().clear()); } } )+}; @@ -267,4 +267,4 @@ impl_flt_monitor!( FltMonitor4: (flt4, flt4c, flt4ie), FltMonitor5: (flt5, flt5c, flt5ie), FltMonitor6: (flt6, flt6c, flt6ie), -); +); \ No newline at end of file diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs index 2b51fa2f..958ffbce 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -170,7 +170,7 @@ macro_rules! hrtim_timer { fn clear_repetition_interrupt(&mut self) { let tim = unsafe { &*$TIMX::ptr() }; - tim.icr().write(|w| w.repc().bit(true)); + tim.icr().write(|w| w.repc().clear()); } /// Disable register updates @@ -352,4 +352,4 @@ impl super::event::EventSource for HrTim { const BITS: u32 = 1 << 7; // MSTPER -} +} \ No newline at end of file From 5795c713c6b2a04287f42e4dec62803a26991567 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 18 Nov 2024 20:47:01 +0100 Subject: [PATCH 80/85] Use latest pac --- Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 5c8dd760..6489ebd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,8 @@ version = "0.0.2" nb = "0.1.1" #stm32g4 = { git = "https://github.com/stm32-rs/stm32-rs-nightlies" } #"0.15.1" #stm32g4 = { version = "0.18.0", package = "stm32g4-staging" } -stm32g4 = { path = "../stm32-rs/stm32g4" } +stm32g4 = { git = "https://github.com/stm32-rs/stm32-rs-nightlies", rev = "74b26b7" } +#stm32g4 = { path = "../stm32-rs/stm32g4" } paste = "1.0" bitflags = "1.2" vcell = "0.1" From 657f52bec44ccee65a9a8b97886c800c410aca91 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 20 Nov 2024 16:09:31 +0100 Subject: [PATCH 81/85] Use latest pac --- Cargo.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6489ebd0..501b9b46 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,8 +15,7 @@ version = "0.0.2" nb = "0.1.1" #stm32g4 = { git = "https://github.com/stm32-rs/stm32-rs-nightlies" } #"0.15.1" #stm32g4 = { version = "0.18.0", package = "stm32g4-staging" } -stm32g4 = { git = "https://github.com/stm32-rs/stm32-rs-nightlies", rev = "74b26b7" } -#stm32g4 = { path = "../stm32-rs/stm32g4" } +stm32g4 = { git = "https://github.com/stm32-rs/stm32-rs-nightlies", rev = "4c4f246" } paste = "1.0" bitflags = "1.2" vcell = "0.1" From 87bb961758887378844f330546f0a0c88e466b72 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 25 Nov 2024 19:59:37 +0100 Subject: [PATCH 82/85] HRTIM - Clean up macro --- src/hrtim/capture.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/hrtim/capture.rs b/src/hrtim/capture.rs index e08a2fbd..8d5f94da 100644 --- a/src/hrtim/capture.rs +++ b/src/hrtim/capture.rs @@ -149,12 +149,12 @@ pub fn dma_value_to_signed(x: u32, period: u16) -> i32 { } macro_rules! impl_capture { - ($($TIMX:ident: $mux:expr),+) => {$( - impl_capture!($TIMX: Ch1, cpt1r, cpt1cr, cpt1, cpt1ie, cpt1de, cpt1c, $mux); - impl_capture!($TIMX: Ch2, cpt2r, cpt2cr, cpt2, cpt2ie, cpt2de, cpt2c, $mux); + ($($TIMX:ident),+) => {$( + impl_capture!($TIMX: Ch1, cpt1r, cpt1cr, cpt1, cpt1ie, cpt1de, cpt1c); + impl_capture!($TIMX: Ch2, cpt2r, cpt2cr, cpt2, cpt2ie, cpt2de, cpt2c); )+}; - ($TIMX:ident: $CH:ident, $cptXr:ident, $cptXcr:ident, $cptX:ident, $cptXie:ident, $cptXde:ident, $cptXc:ident, $mux:expr) => { + ($TIMX:ident: $CH:ident, $cptXr:ident, $cptXcr:ident, $cptX:ident, $cptXie:ident, $cptXde:ident, $cptXc:ident) => { impl HrCapt<$TIMX, PSCL, $CH, NoDma> { /// Add event to capture /// @@ -244,16 +244,16 @@ macro_rules! impl_capture { type MemSize = u32; - const REQUEST_LINE: Option = Some($mux as u8); + const REQUEST_LINE: Option = Some(DmaMuxResources::$TIMX as u8); } }; } impl_capture! { - HRTIM_TIMA: DmaMuxResources::HRTIM_TIMA, - HRTIM_TIMB: DmaMuxResources::HRTIM_TIMB, - HRTIM_TIMC: DmaMuxResources::HRTIM_TIMC, - HRTIM_TIMD: DmaMuxResources::HRTIM_TIMD, - HRTIM_TIME: DmaMuxResources::HRTIM_TIME, - HRTIM_TIMF: DmaMuxResources::HRTIM_TIMF + HRTIM_TIMA, + HRTIM_TIMB, + HRTIM_TIMC, + HRTIM_TIMD, + HRTIM_TIME, + HRTIM_TIMF } From a79d4b44aee7e73b8c7506fa58c71685d9650845 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 25 Nov 2024 20:48:35 +0100 Subject: [PATCH 83/85] HRTIM - Fix some clippy warnings and fmt --- src/hrtim/capture.rs | 6 ++++++ src/hrtim/control.rs | 8 +++----- src/hrtim/fault.rs | 2 +- src/hrtim/mod.rs | 49 +++++++++++++++----------------------------- src/hrtim/timer.rs | 2 +- 5 files changed, 28 insertions(+), 39 deletions(-) diff --git a/src/hrtim/capture.rs b/src/hrtim/capture.rs index 8d5f94da..eb1d0475 100644 --- a/src/hrtim/capture.rs +++ b/src/hrtim/capture.rs @@ -11,6 +11,12 @@ pub struct Ch2; pub struct Dma; pub struct NoDma; +/// Type alias for the default capture for channel 1 +pub type HrCaptCh1 = HrCapt; + +/// Type alias for the default capture for channel 2 +pub type HrCaptCh2 = HrCapt; + pub struct HrCapt { _x: PhantomData<(TIM, PSCL, CH, DMA)>, } diff --git a/src/hrtim/control.rs b/src/hrtim/control.rs index 045abcb1..57974d69 100644 --- a/src/hrtim/control.rs +++ b/src/hrtim/control.rs @@ -137,11 +137,9 @@ impl HrTimOngoingCalibration { // Calibration is now done, it is safe to continue unsafe { self.init() }; - ( - HrTimCalibrated, - unsafe { FaultInputs::new() }, - unsafe { EevInputs::new() }, - ) + (HrTimCalibrated, unsafe { FaultInputs::new() }, unsafe { + EevInputs::new() + }) } pub fn set_adc1_trigger_psc(mut self, post_scaler: AdcTriggerPostscaler) -> Self { diff --git a/src/hrtim/fault.rs b/src/hrtim/fault.rs index c54cf9fb..c425077f 100644 --- a/src/hrtim/fault.rs +++ b/src/hrtim/fault.rs @@ -267,4 +267,4 @@ impl_flt_monitor!( FltMonitor4: (flt4, flt4c, flt4ie), FltMonitor5: (flt5, flt5c, flt5ie), FltMonitor6: (flt6, flt6c, flt6ie), -); \ No newline at end of file +); diff --git a/src/hrtim/mod.rs b/src/hrtim/mod.rs index 0609a872..d07ef3c2 100644 --- a/src/hrtim/mod.rs +++ b/src/hrtim/mod.rs @@ -13,7 +13,6 @@ 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; @@ -21,6 +20,7 @@ use crate::stm32::{ HRTIM_COMMON, HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF, }; +use capture::{HrCaptCh1, HrCaptCh2}; use fugit::HertzU64; use self::control::HrPwmControl; @@ -188,6 +188,18 @@ pub struct HrPwmBuilder { out2_polarity: Polarity, } +pub struct HrParts { + pub timer: HrTim, HrCaptCh2>, + + pub cr1: HrCr1, + pub cr2: HrCr2, + pub cr3: HrCr3, + pub cr4: HrCr4, + + pub out: OUT, + pub dma_channel: timer::DmaChannel, +} + pub enum PreloadSource { /// Preloaded registers are updated on counter roll over or counter reset OnCounterReset, @@ -249,7 +261,7 @@ macro_rules! hrtim_finalize_body { // Set counting direction w.udm().bit($this.counting_direction == HrCountingDirection::UpDown) ); - + tim.cr().modify(|_r, w| // Push-Pull mode w.pshpll().bit($this.enable_push_pull) @@ -552,20 +564,7 @@ macro_rules! hrtim_hal { PSCL: HrtimPrescaler, PINS: ToHrOut<$TIMX>, { - 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> - ), - PINS::Out, - timer::DmaChannel<$TIMX>, - ) { - + pub fn finalize(self, _control: &mut HrPwmControl) -> HrParts<$TIMX, PSCL, PINS::Out> { hrtim_finalize_body!( self, PreloadSource, $TIMX, $($out)* @@ -660,7 +659,6 @@ macro_rules! hrtim_hal { }; } - impl HrPwmAdvExt for HRTIM_MASTER { type PreloadSource = MasterPreloadSource; @@ -701,25 +699,12 @@ impl HrPwmAdvExt for HRTIM_MASTER { } } -impl - HrPwmBuilder +impl HrPwmBuilder where PSCL: HrtimPrescaler, PINS: ToHrOut, { - pub fn finalize(self, _control: &mut HrPwmControl) -> ( - HrTim, - HrCapt, - >, ( - HrCr1, - HrCr2, - HrCr3, - HrCr4 - ), - timer::DmaChannel, - ) { - + pub fn finalize(self, _control: &mut HrPwmControl) -> HrParts { hrtim_finalize_body!(self, MasterPreloadSource, HRTIM_MASTER,) } diff --git a/src/hrtim/timer.rs b/src/hrtim/timer.rs index 958ffbce..bbc5dc86 100644 --- a/src/hrtim/timer.rs +++ b/src/hrtim/timer.rs @@ -352,4 +352,4 @@ impl super::event::EventSource for HrTim { const BITS: u32 = 1 << 7; // MSTPER -} \ No newline at end of file +} From 1ea1347e8c15a2c472d5f7ff0ed4dcc3d2ed75fd Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 25 Nov 2024 20:49:07 +0100 Subject: [PATCH 84/85] HRTIM - Fix some clippy warnings and fmt - examples --- Cargo.toml | 5 +++ examples/hrtim/adc-trigger.rs | 10 ++++- examples/hrtim/capture-dma.rs | 23 +++++++--- examples/hrtim/capture.rs | 14 ++++-- examples/hrtim/eev-comp.rs | 16 ++++--- examples/hrtim/eev.rs | 16 ++++--- examples/hrtim/flt-comp.rs | 8 +++- examples/hrtim/flt.rs | 18 +++++--- examples/hrtim/hrtim.rs | 8 +++- examples/hrtim/master.rs | 14 +++++- examples/hrtim/simple.rs | 81 ----------------------------------- 11 files changed, 101 insertions(+), 112 deletions(-) delete mode 100644 examples/hrtim/simple.rs diff --git a/Cargo.toml b/Cargo.toml index 501b9b46..4517b5e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -134,6 +134,11 @@ name = "hrtim-capture" required-features = ["hrtim"] path = "examples/hrtim/capture.rs" +[[example]] +name = "hrtim-capture-dma" +required-features = ["hrtim"] +path = "examples/hrtim/capture-dma.rs" + [[example]] name = "hrtim-eev-comp" required-features = ["hrtim"] diff --git a/examples/hrtim/adc-trigger.rs b/examples/hrtim/adc-trigger.rs index f2b7fc83..e03c8f7a 100644 --- a/examples/hrtim/adc-trigger.rs +++ b/examples/hrtim/adc-trigger.rs @@ -7,6 +7,7 @@ mod utils; use cortex_m_rt::entry; +use stm32g4xx_hal::hrtim::HrParts; use utils::logger::info; #[entry] @@ -87,7 +88,14 @@ 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 HrParts { + mut timer, + mut cr1, + mut cr3, + mut cr4, + out: (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 175a670e..a1ce1ffc 100644 --- a/examples/hrtim/capture-dma.rs +++ b/examples/hrtim/capture-dma.rs @@ -7,6 +7,7 @@ mod utils; use cortex_m_rt::entry; +use stm32g4xx_hal::hrtim::{timer::TimerSplitCapture, HrParts}; use utils::logger::info; #[entry] @@ -15,7 +16,7 @@ fn main() -> ! { use hal::{ dma::{config::DmaConfig, stream::DMAExt, TransferExt}, - gpio::{GpioExt, AF13}, + gpio::GpioExt, hrtim::{ capture, compare_register::HrCompareRegister, control::HrControltExt, external_event, external_event::ToExternalEventSource, output::HrOutput, timer::HrSlaveTimerCpt, @@ -37,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), @@ -83,7 +84,13 @@ fn main() -> ! { .finalize(&mut hr_control); let mut hr_control = hr_control.constrain(); - let (timer, (mut cr1, _cr2, _cr3, _cr4), mut out1, dma_ch) = dp + let HrParts { + timer, + mut cr1, + out: mut out1, + dma_channel, + .. + } = dp .HRTIM_TIMA .pwm_advanced(pin_a, &mut rcc) .prescaler(prescaler) @@ -93,7 +100,11 @@ fn main() -> ! { 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(); + let TimerSplitCapture { + mut timer, + ch1: mut capture, + .. + } = timer.split_capture(); timer.start(&mut hr_control.control); out1.enable(); @@ -109,7 +120,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(dma_ch), + capture.enable_dma(dma_channel), &mut first_buffer[..], config, ); @@ -121,7 +132,7 @@ fn main() -> ! { 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); + let [t1, t2] = data.map(|x| capture::dma_value_to_signed(x, period)); 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 90d3bc05..e2416396 100644 --- a/examples/hrtim/capture.rs +++ b/examples/hrtim/capture.rs @@ -7,6 +7,7 @@ mod utils; use cortex_m_rt::entry; +use stm32g4xx_hal::hrtim::HrParts; use utils::logger::info; #[entry] @@ -79,19 +80,24 @@ 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 HrParts { + mut timer, + mut cr1, + mut out, + .. + } = 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 + out.enable_rst_event(&cr1); // Set low on compare match with cr1 + out.enable_set_event(&timer); // Set high at new period cr1.set_duty(period / 2); timer.start(&mut hr_control.control); - out1.enable(); + out.enable(); let capture = timer.capture_ch1(); capture.enable_interrupt(true, &mut hr_control); diff --git a/examples/hrtim/eev-comp.rs b/examples/hrtim/eev-comp.rs index ee1d44fb..b405840a 100644 --- a/examples/hrtim/eev-comp.rs +++ b/examples/hrtim/eev-comp.rs @@ -8,6 +8,7 @@ mod utils; use cortex_m_rt::entry; +use stm32g4xx_hal::hrtim::HrParts; use utils::logger::info; #[entry] @@ -107,7 +108,12 @@ fn main() -> ! { // ------------------------- .-------------------------------------- // . . * . . . // . . * . . . - let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1, ..) = dp + let HrParts { + mut timer, + mut cr1, + mut out, + .. + } = dp .HRTIM_TIMA .pwm_advanced(pin_a, &mut rcc) .prescaler(prescaler) @@ -115,12 +121,12 @@ fn main() -> ! { .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 + out.enable_rst_event(&cr1); // Set low on compare match with cr1 + out.enable_rst_event(&eev_input4); + out.enable_set_event(&timer); // Set high at new period cr1.set_duty(timer.get_period() / 3); - out1.enable(); + out.enable(); timer.start(&mut hr_control.control); info!("Started"); diff --git a/examples/hrtim/eev.rs b/examples/hrtim/eev.rs index 3dd4a1e7..390461f0 100644 --- a/examples/hrtim/eev.rs +++ b/examples/hrtim/eev.rs @@ -8,6 +8,7 @@ mod utils; use cortex_m_rt::entry; +use stm32g4xx_hal::hrtim::HrParts; use utils::logger::info; #[entry] @@ -79,7 +80,12 @@ fn main() -> ! { // ------------------------- ------------------------------------------ // . . * . . . // . . * . . . - let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1, ..) = dp + let HrParts { + mut timer, + mut cr1, + mut out, + .. + } = dp .HRTIM_TIMA .pwm_advanced(pin_a, &mut rcc) .prescaler(prescaler) @@ -87,12 +93,12 @@ fn main() -> ! { .period(0xFFFF) .finalize(&mut hr_control); - 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 + out.enable_rst_event(&cr1); // Set low on compare match with cr1 + out.enable_rst_event(&eev_input3); + out.enable_set_event(&timer); // Set high at new period cr1.set_duty(timer.get_period() / 3); - out1.enable(); + out.enable(); timer.start(&mut hr_control.control); info!("Started"); diff --git a/examples/hrtim/flt-comp.rs b/examples/hrtim/flt-comp.rs index 4a83a476..e99448dd 100644 --- a/examples/hrtim/flt-comp.rs +++ b/examples/hrtim/flt-comp.rs @@ -8,6 +8,7 @@ mod utils; use cortex_m_rt::entry; +use stm32g4xx_hal::hrtim::HrParts; use utils::logger::info; #[entry] @@ -108,7 +109,12 @@ fn main() -> ! { // ----------------------------------------- -------------------------- // . . . * . . // . . . * . . - let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1, ..) = dp + let HrParts { + mut timer, + mut cr1, + out: 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 cad59c53..2408aa54 100644 --- a/examples/hrtim/flt.rs +++ b/examples/hrtim/flt.rs @@ -8,6 +8,7 @@ mod utils; use cortex_m_rt::entry; +use stm32g4xx_hal::hrtim::HrParts; use utils::logger::info; #[entry] @@ -74,7 +75,12 @@ fn main() -> ! { // ----------------------------------------- -------------------------- // . . . * . . // . . . * . . - let (mut timer, (mut cr1, _cr2, _cr3, _cr4), mut out1, ..) = dp + let HrParts { + mut timer, + mut cr1, + mut out, + .. + } = dp .HRTIM_TIMA .pwm_advanced(pin_a, &mut rcc) .prescaler(prescaler) @@ -92,11 +98,11 @@ fn main() -> ! { // as normal .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 + out.enable_rst_event(&cr1); // Set low on compare match with cr1 + out.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(); + out.enable(); timer.start(&mut hr_control.control); info!("Started"); @@ -104,11 +110,11 @@ fn main() -> ! { loop { for _ in 0..5 { delay.delay(500_u32.millis()); - info!("State: {:?}", out1.get_state()); + info!("State: {:?}", out.get_state()); } if hr_control.fault_3.is_fault_active() { hr_control.fault_3.clear_fault(); // Clear fault every 5s - out1.enable(); + out.enable(); info!("failt cleared, and output reenabled"); } } diff --git a/examples/hrtim/hrtim.rs b/examples/hrtim/hrtim.rs index f55caa94..bac0ff7a 100644 --- a/examples/hrtim/hrtim.rs +++ b/examples/hrtim/hrtim.rs @@ -7,6 +7,7 @@ mod utils; use cortex_m_rt::entry; +use stm32g4xx_hal::hrtim::HrParts; use utils::logger::info; #[entry] @@ -69,7 +70,12 @@ 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 HrParts { + mut timer, + mut cr1, + out: (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 cf432a6e..5e5793b7 100644 --- a/examples/hrtim/master.rs +++ b/examples/hrtim/master.rs @@ -7,6 +7,7 @@ mod utils; use cortex_m_rt::entry; +use stm32g4xx_hal::hrtim::HrParts; use utils::logger::info; #[entry] @@ -68,7 +69,12 @@ 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 HrParts { + mut timer, + mut cr1, + out: (mut out1, mut out2), + .. + } = dp .HRTIM_TIMA .pwm_advanced((pin_a, pin_b), &mut rcc) .prescaler(prescaler) @@ -80,7 +86,11 @@ fn main() -> ! { .timer_mode(HrTimerMode::SingleShotRetriggerable) .finalize(&mut hr_control); - let (mut mtimer, (mut mcr1, _mcr2, _mcr3, _mcr4), ..) = dp + let HrParts { + timer: mut mtimer, + cr1: mut mcr1, + .. + } = dp .HRTIM_MASTER .pwm_advanced((), &mut rcc) .prescaler(prescaler) diff --git a/examples/hrtim/simple.rs b/examples/hrtim/simple.rs deleted file mode 100644 index 14d60812..00000000 --- a/examples/hrtim/simple.rs +++ /dev/null @@ -1,81 +0,0 @@ -#![no_std] -#![no_main] - -/// 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; - -use cortex_m_rt::entry; -use utils::logger::info; - -#[entry] -fn main() -> ! { - use hal::gpio::gpioa::PA8; - use hal::gpio::gpioa::PA9; - use hal::gpio::AF13; - use hal::hrtim::{control::HrControltExt, HrPwmExt}; - use hal::prelude::*; - use hal::pwr::PwrExt; - use hal::rcc; - use hal::stm32; - use hal::time::RateExtU32; - use stm32g4xx_hal as hal; - extern crate cortex_m_rt as rt; - - 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(); - 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 = gpioa.pa8; - let pin_b = gpioa.pa9; - - // . . . - // . 33% . . - // ---- .---- .---- - //out1 | | | | | | - // | | | | | | - // ------ ------------ ------------ --------- - // . . - // 50% . . - // -------- .-------- .-------- - //out2 | | | | | | - // | | | | | | - // ------ -------- -------- ----- - // . . . - // . . . - - 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% - p2.set_duty(max_duty / 2); // Set output 2 to 50% - - // Enable the outputs - p1.enable(); - p2.enable(); - - info!("Running"); - - loop { - cortex_m::asm::nop() - } -} From 558969fe27daaa9fcab514394d966d5401c30bd2 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Tue, 26 Nov 2024 18:26:47 +0100 Subject: [PATCH 85/85] Bump pac --- Cargo.toml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4517b5e9..dfaa025a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,9 +13,7 @@ version = "0.0.2" [dependencies] nb = "0.1.1" -#stm32g4 = { git = "https://github.com/stm32-rs/stm32-rs-nightlies" } #"0.15.1" -#stm32g4 = { version = "0.18.0", package = "stm32g4-staging" } -stm32g4 = { git = "https://github.com/stm32-rs/stm32-rs-nightlies", rev = "4c4f246" } +stm32g4 = { version = "0.19.0", package = "stm32g4-staging" } paste = "1.0" bitflags = "1.2" vcell = "0.1"