diff --git a/ci.sh b/ci.sh index cd82af2f1..d17f4e13e 100755 --- a/ci.sh +++ b/ci.sh @@ -124,6 +124,7 @@ cargo batch \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h725re,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7b3ai,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7b3ai,defmt,exti,time-driver-tim1,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l431cb,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l422cb,defmt,exti,time-driver-any,time \ diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index ee224da67..15bb8ea62 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -584,7 +584,7 @@ fn main() { }; g.extend(quote! { - impl crate::rcc::sealed::RccPeripheral for peripherals::#pname { + impl crate::rcc::SealedRccPeripheral for peripherals::#pname { fn frequency() -> crate::time::Hertz { #clock_frequency } @@ -1486,7 +1486,7 @@ fn main() { #[crate::interrupt] unsafe fn #irq () { #( - ::on_irq(); + ::on_irq(); )* } } diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs index b27b99827..cecf67947 100644 --- a/embassy-stm32/src/adc/f1.rs +++ b/embassy-stm32/src/adc/f1.rs @@ -33,7 +33,7 @@ impl interrupt::typelevel::Handler for InterruptHandl pub struct Vref; impl AdcPin for Vref {} -impl super::sealed::AdcPin for Vref { +impl super::SealedAdcPin for Vref { fn channel(&self) -> u8 { 17 } @@ -41,7 +41,7 @@ impl super::sealed::AdcPin for Vref { pub struct Temperature; impl AdcPin for Temperature {} -impl super::sealed::AdcPin for Temperature { +impl super::SealedAdcPin for Temperature { fn channel(&self) -> u8 { 16 } diff --git a/embassy-stm32/src/adc/f3.rs b/embassy-stm32/src/adc/f3.rs index efade1f64..c5581dba1 100644 --- a/embassy-stm32/src/adc/f3.rs +++ b/embassy-stm32/src/adc/f3.rs @@ -33,7 +33,7 @@ impl interrupt::typelevel::Handler for InterruptHandl pub struct Vref; impl AdcPin for Vref {} -impl super::sealed::AdcPin for Vref { +impl super::SealedAdcPin for Vref { fn channel(&self) -> u8 { 18 } @@ -48,7 +48,7 @@ impl Vref { pub struct Temperature; impl AdcPin for Temperature {} -impl super::sealed::AdcPin for Temperature { +impl super::SealedAdcPin for Temperature { fn channel(&self) -> u8 { 16 } @@ -102,7 +102,7 @@ impl<'d, T: Instance> Adc<'d, T> { } fn freq() -> Hertz { - ::frequency() + ::frequency() } pub fn sample_time_for_us(&self, us: u32) -> SampleTime { diff --git a/embassy-stm32/src/adc/f3_v1_1.rs b/embassy-stm32/src/adc/f3_v1_1.rs index f842893fa..672ace04f 100644 --- a/embassy-stm32/src/adc/f3_v1_1.rs +++ b/embassy-stm32/src/adc/f3_v1_1.rs @@ -65,7 +65,7 @@ fn update_vref(op: i8) { pub struct Vref(core::marker::PhantomData); impl AdcPin for Vref {} -impl super::sealed::AdcPin for Vref { +impl super::SealedAdcPin for Vref { fn channel(&self) -> u8 { 17 } @@ -124,7 +124,7 @@ impl Drop for Vref { pub struct Temperature(core::marker::PhantomData); impl AdcPin for Temperature {} -impl super::sealed::AdcPin for Temperature { +impl super::SealedAdcPin for Temperature { fn channel(&self) -> u8 { 16 } diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index 0d0d40549..ead2357ce 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs @@ -17,6 +17,8 @@ mod _version; #[allow(unused)] #[cfg(not(adc_f3_v2))] pub use _version::*; +#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] +use embassy_sync::waitqueue::AtomicWaker; #[cfg(not(any(adc_f1, adc_f3_v2)))] pub use crate::pac::adc::vals::Res as Resolution; @@ -31,63 +33,65 @@ pub struct Adc<'d, T: Instance> { sample_time: SampleTime, } -pub(crate) mod sealed { - #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] - use embassy_sync::waitqueue::AtomicWaker; +#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] +pub struct State { + pub waker: AtomicWaker, +} - #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] - pub struct State { - pub waker: AtomicWaker, - } - - #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] - impl State { - pub const fn new() -> Self { - Self { - waker: AtomicWaker::new(), - } +#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] +impl State { + pub const fn new() -> Self { + Self { + waker: AtomicWaker::new(), } } +} - pub trait InterruptableInstance { - type Interrupt: crate::interrupt::typelevel::Interrupt; - } +trait SealedInstance { + #[allow(unused)] + fn regs() -> crate::pac::adc::Adc; + #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))] + fn common_regs() -> crate::pac::adccommon::AdcCommon; + #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] + fn state() -> &'static State; +} - pub trait Instance: InterruptableInstance { - fn regs() -> crate::pac::adc::Adc; - #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))] - fn common_regs() -> crate::pac::adccommon::AdcCommon; - #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] - fn state() -> &'static State; - } +pub(crate) trait SealedAdcPin { + #[cfg(any(adc_v1, adc_l0, adc_v2))] + fn set_as_analog(&mut self) {} - pub trait AdcPin { - #[cfg(any(adc_v1, adc_l0, adc_v2))] - fn set_as_analog(&mut self) {} + #[allow(unused)] + fn channel(&self) -> u8; +} - fn channel(&self) -> u8; - } - - pub trait InternalChannel { - fn channel(&self) -> u8; - } +trait SealedInternalChannel { + #[allow(unused)] + fn channel(&self) -> u8; } /// ADC instance. #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0, adc_h5)))] -pub trait Instance: sealed::Instance + crate::Peripheral

{} +#[allow(private_bounds)] +pub trait Instance: SealedInstance + crate::Peripheral

{ + type Interrupt: crate::interrupt::typelevel::Interrupt; +} /// ADC instance. #[cfg(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0, adc_h5))] -pub trait Instance: sealed::Instance + crate::Peripheral

+ crate::rcc::RccPeripheral {} +#[allow(private_bounds)] +pub trait Instance: SealedInstance + crate::Peripheral

+ crate::rcc::RccPeripheral { + type Interrupt: crate::interrupt::typelevel::Interrupt; +} /// ADC pin. -pub trait AdcPin: sealed::AdcPin {} +#[allow(private_bounds)] +pub trait AdcPin: SealedAdcPin {} /// ADC internal channel. -pub trait InternalChannel: sealed::InternalChannel {} +#[allow(private_bounds)] +pub trait InternalChannel: SealedInternalChannel {} foreach_adc!( ($inst:ident, $common_inst:ident, $clock:ident) => { - impl crate::adc::sealed::Instance for peripherals::$inst { + impl crate::adc::SealedInstance for peripherals::$inst { fn regs() -> crate::pac::adc::Adc { crate::pac::$inst } @@ -98,21 +102,15 @@ foreach_adc!( } #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] - fn state() -> &'static sealed::State { - static STATE: sealed::State = sealed::State::new(); + fn state() -> &'static State { + static STATE: State = State::new(); &STATE } } - foreach_interrupt!( - ($inst,adc,ADC,GLOBAL,$irq:ident) => { - impl sealed::InterruptableInstance for peripherals::$inst { - type Interrupt = crate::interrupt::typelevel::$irq; - } - }; - ); - - impl crate::adc::Instance for peripherals::$inst {} + impl crate::adc::Instance for peripherals::$inst { + type Interrupt = crate::_generated::peripheral_interrupts::$inst::GLOBAL; + } }; ); @@ -120,10 +118,10 @@ macro_rules! impl_adc_pin { ($inst:ident, $pin:ident, $ch:expr) => { impl crate::adc::AdcPin for crate::peripherals::$pin {} - impl crate::adc::sealed::AdcPin for crate::peripherals::$pin { + impl crate::adc::SealedAdcPin for crate::peripherals::$pin { #[cfg(any(adc_v1, adc_l0, adc_v2))] fn set_as_analog(&mut self) { - ::set_as_analog(self); + ::set_as_analog(self); } fn channel(&self) -> u8 { diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs index a8dc6ce98..e9b46be80 100644 --- a/embassy-stm32/src/adc/v1.rs +++ b/embassy-stm32/src/adc/v1.rs @@ -39,7 +39,7 @@ pub struct Vbat; impl AdcPin for Vbat {} #[cfg(not(adc_l0))] -impl super::sealed::AdcPin for Vbat { +impl super::SealedAdcPin for Vbat { fn channel(&self) -> u8 { 18 } @@ -47,7 +47,7 @@ impl super::sealed::AdcPin for Vbat { pub struct Vref; impl AdcPin for Vref {} -impl super::sealed::AdcPin for Vref { +impl super::SealedAdcPin for Vref { fn channel(&self) -> u8 { 17 } @@ -55,7 +55,7 @@ impl super::sealed::AdcPin for Vref { pub struct Temperature; impl AdcPin for Temperature {} -impl super::sealed::AdcPin for Temperature { +impl super::SealedAdcPin for Temperature { fn channel(&self) -> u8 { 16 } diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs index f6f7dbfcc..a43eb72db 100644 --- a/embassy-stm32/src/adc/v2.rs +++ b/embassy-stm32/src/adc/v2.rs @@ -16,7 +16,7 @@ pub const ADC_POWERUP_TIME_US: u32 = 3; pub struct VrefInt; impl AdcPin for VrefInt {} -impl super::sealed::AdcPin for VrefInt { +impl super::SealedAdcPin for VrefInt { fn channel(&self) -> u8 { 17 } @@ -31,7 +31,7 @@ impl VrefInt { pub struct Temperature; impl AdcPin for Temperature {} -impl super::sealed::AdcPin for Temperature { +impl super::SealedAdcPin for Temperature { fn channel(&self) -> u8 { cfg_if::cfg_if! { if #[cfg(any(stm32f2, stm32f40, stm32f41))] { @@ -52,7 +52,7 @@ impl Temperature { pub struct Vbat; impl AdcPin for Vbat {} -impl super::sealed::AdcPin for Vbat { +impl super::SealedAdcPin for Vbat { fn channel(&self) -> u8 { 18 } diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index 5f3512cad..8c9b47197 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs @@ -12,7 +12,7 @@ pub const VREF_CALIB_MV: u32 = 3000; pub struct VrefInt; impl AdcPin for VrefInt {} -impl super::sealed::AdcPin for VrefInt { +impl super::SealedAdcPin for VrefInt { fn channel(&self) -> u8 { cfg_if! { if #[cfg(adc_g0)] { @@ -29,7 +29,7 @@ impl super::sealed::AdcPin for VrefInt { pub struct Temperature; impl AdcPin for Temperature {} -impl super::sealed::AdcPin for Temperature { +impl super::SealedAdcPin for Temperature { fn channel(&self) -> u8 { cfg_if! { if #[cfg(adc_g0)] { @@ -46,7 +46,7 @@ impl super::sealed::AdcPin for Temperature { pub struct Vbat; impl AdcPin for Vbat {} -impl super::sealed::AdcPin for Vbat { +impl super::SealedAdcPin for Vbat { fn channel(&self) -> u8 { cfg_if! { if #[cfg(adc_g0)] { @@ -65,7 +65,7 @@ cfg_if! { if #[cfg(adc_h5)] { pub struct VddCore; impl AdcPin for VddCore {} - impl super::sealed::AdcPin for VddCore { + impl super::SealedAdcPin for VddCore { fn channel(&self) -> u8 { 6 } diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs index 3fd047375..1ae25bea2 100644 --- a/embassy-stm32/src/adc/v4.rs +++ b/embassy-stm32/src/adc/v4.rs @@ -35,7 +35,7 @@ const VBAT_CHANNEL: u8 = 17; /// Internal voltage reference channel. pub struct VrefInt; impl InternalChannel for VrefInt {} -impl super::sealed::InternalChannel for VrefInt { +impl super::SealedInternalChannel for VrefInt { fn channel(&self) -> u8 { VREF_CHANNEL } @@ -44,7 +44,7 @@ impl super::sealed::InternalChannel for VrefInt { /// Internal temperature channel. pub struct Temperature; impl InternalChannel for Temperature {} -impl super::sealed::InternalChannel for Temperature { +impl super::SealedInternalChannel for Temperature { fn channel(&self) -> u8 { TEMP_CHANNEL } @@ -53,7 +53,7 @@ impl super::sealed::InternalChannel for Temperature { /// Internal battery voltage channel. pub struct Vbat; impl InternalChannel for Vbat {} -impl super::sealed::InternalChannel for Vbat { +impl super::SealedInternalChannel for Vbat { fn channel(&self) -> u8 { VBAT_CHANNEL } @@ -276,7 +276,7 @@ impl<'d, T: Instance> Adc<'d, T> { pub fn read

(&mut self, pin: &mut P) -> u16 where P: AdcPin, - P: crate::gpio::sealed::Pin, + P: crate::gpio::Pin, { pin.set_as_analog(); diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs index 1a625bdc4..017c5110d 100644 --- a/embassy-stm32/src/can/bxcan.rs +++ b/embassy-stm32/src/can/bxcan.rs @@ -7,9 +7,12 @@ pub mod bx; pub use bx::{filter, Data, ExtendedId, Fifo, Frame, Header, Id, StandardId}; use embassy_hal_internal::{into_ref, PeripheralRef}; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::channel::Channel; +use embassy_sync::waitqueue::AtomicWaker; use futures::FutureExt; -use crate::gpio::sealed::AFType; +use crate::gpio::AFType; use crate::interrupt::typelevel::Interrupt; use crate::pac::can::vals::{Ide, Lec}; use crate::rcc::RccPeripheral; @@ -485,37 +488,30 @@ impl<'d, T: Instance> DerefMut for Can<'d, T> { } } -pub(crate) mod sealed { - use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; - use embassy_sync::channel::Channel; - use embassy_sync::waitqueue::AtomicWaker; +struct State { + pub tx_waker: AtomicWaker, + pub err_waker: AtomicWaker, + pub rx_queue: Channel, +} - use super::Envelope; - - pub struct State { - pub tx_waker: AtomicWaker, - pub err_waker: AtomicWaker, - pub rx_queue: Channel, - } - - impl State { - pub const fn new() -> Self { - Self { - tx_waker: AtomicWaker::new(), - err_waker: AtomicWaker::new(), - rx_queue: Channel::new(), - } +impl State { + pub const fn new() -> Self { + Self { + tx_waker: AtomicWaker::new(), + err_waker: AtomicWaker::new(), + rx_queue: Channel::new(), } } - - pub trait Instance { - fn regs() -> crate::pac::can::Can; - fn state() -> &'static State; - } +} + +trait SealedInstance { + fn regs() -> crate::pac::can::Can; + fn state() -> &'static State; } /// CAN instance trait. -pub trait Instance: sealed::Instance + RccPeripheral + 'static { +#[allow(private_bounds)] +pub trait Instance: SealedInstance + RccPeripheral + 'static { /// TX interrupt for this instance. type TXInterrupt: crate::interrupt::typelevel::Interrupt; /// RX0 interrupt for this instance. @@ -533,14 +529,14 @@ unsafe impl<'d, T: Instance> crate::can::bx::Instance for BxcanInstance<'d, T> { foreach_peripheral!( (can, $inst:ident) => { - impl sealed::Instance for peripherals::$inst { + impl SealedInstance for peripherals::$inst { fn regs() -> crate::pac::can::Can { crate::pac::$inst } - fn state() -> &'static sealed::State { - static STATE: sealed::State = sealed::State::new(); + fn state() -> &'static State { + static STATE: State = State::new(); &STATE } } diff --git a/embassy-stm32/src/can/fd/peripheral.rs b/embassy-stm32/src/can/fd/peripheral.rs index 682e13f4b..76b76afe1 100644 --- a/embassy-stm32/src/can/fd/peripheral.rs +++ b/embassy-stm32/src/can/fd/peripheral.rs @@ -325,17 +325,6 @@ impl Registers { */ } - /// Disables the CAN interface and returns back the raw peripheral it was created from. - #[inline] - pub fn free(mut self) { - //self.disable_interrupts(Interrupts::all()); - - //TODO check this! - self.enter_init_mode(); - self.set_power_down_mode(true); - //self.control.instance - } - /// Applies the settings of a new FdCanConfig See [`FdCanConfig`] #[inline] pub fn apply_config(&mut self, config: FdCanConfig) { @@ -419,55 +408,6 @@ impl Registers { self.leave_init_mode(config); } - /// Moves out of ConfigMode and into InternalLoopbackMode - #[inline] - pub fn into_internal_loopback(mut self, config: FdCanConfig) { - self.set_loopback_mode(LoopbackMode::Internal); - self.leave_init_mode(config); - } - - /// Moves out of ConfigMode and into ExternalLoopbackMode - #[inline] - pub fn into_external_loopback(mut self, config: FdCanConfig) { - self.set_loopback_mode(LoopbackMode::External); - self.leave_init_mode(config); - } - - /// Moves out of ConfigMode and into RestrictedOperationMode - #[inline] - pub fn into_restricted(mut self, config: FdCanConfig) { - self.set_restricted_operations(true); - self.leave_init_mode(config); - } - - /// Moves out of ConfigMode and into NormalOperationMode - #[inline] - pub fn into_normal(mut self, config: FdCanConfig) { - self.set_normal_operations(true); - self.leave_init_mode(config); - } - - /// Moves out of ConfigMode and into BusMonitoringMode - #[inline] - pub fn into_bus_monitoring(mut self, config: FdCanConfig) { - self.set_bus_monitoring_mode(true); - self.leave_init_mode(config); - } - - /// Moves out of ConfigMode and into Testmode - #[inline] - pub fn into_test_mode(mut self, config: FdCanConfig) { - self.set_test_mode(true); - self.leave_init_mode(config); - } - - /// Moves out of ConfigMode and into PoweredDownmode - #[inline] - pub fn into_powered_down(mut self, config: FdCanConfig) { - self.set_power_down_mode(true); - self.leave_init_mode(config); - } - /// Configures the bit timings. /// /// You can use to calculate the `btr` parameter. Enter @@ -565,6 +505,7 @@ impl Registers { /// Configures and resets the timestamp counter #[inline] + #[allow(unused)] pub fn set_timestamp_counter_source(&mut self, select: TimestampSource) { #[cfg(stm32h7)] let (tcp, tss) = match select { diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs index 4c40f10e3..4ea036ab4 100644 --- a/embassy-stm32/src/can/fdcan.rs +++ b/embassy-stm32/src/can/fdcan.rs @@ -5,10 +5,11 @@ use core::task::Poll; use embassy_hal_internal::{into_ref, PeripheralRef}; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; -use embassy_sync::channel::Channel; +use embassy_sync::channel::{Channel, DynamicReceiver, DynamicSender}; +use embassy_sync::waitqueue::AtomicWaker; use crate::can::fd::peripheral::Registers; -use crate::gpio::sealed::AFType; +use crate::gpio::AFType; use crate::interrupt::typelevel::Interrupt; use crate::rcc::RccPeripheral; use crate::{interrupt, peripherals, Peripheral}; @@ -53,8 +54,8 @@ impl interrupt::typelevel::Handler for IT0Interrup } match &T::state().tx_mode { - sealed::TxMode::NonBuffered(waker) => waker.wake(), - sealed::TxMode::ClassicBuffered(buf) => { + TxMode::NonBuffered(waker) => waker.wake(), + TxMode::ClassicBuffered(buf) => { if !T::registers().tx_queue_is_full() { match buf.tx_receiver.try_receive() { Ok(frame) => { @@ -64,7 +65,7 @@ impl interrupt::typelevel::Handler for IT0Interrup } } } - sealed::TxMode::FdBuffered(buf) => { + TxMode::FdBuffered(buf) => { if !T::registers().tx_queue_is_full() { match buf.tx_receiver.try_receive() { Ok(frame) => { @@ -467,14 +468,14 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> fn setup(self) -> Self { // We don't want interrupts being processed while we change modes. critical_section::with(|_| unsafe { - let rx_inner = sealed::ClassicBufferedRxInner { + let rx_inner = ClassicBufferedRxInner { rx_sender: self.rx_buf.sender().into(), }; - let tx_inner = sealed::ClassicBufferedTxInner { + let tx_inner = ClassicBufferedTxInner { tx_receiver: self.tx_buf.receiver().into(), }; - T::mut_state().rx_mode = sealed::RxMode::ClassicBuffered(rx_inner); - T::mut_state().tx_mode = sealed::TxMode::ClassicBuffered(tx_inner); + T::mut_state().rx_mode = RxMode::ClassicBuffered(rx_inner); + T::mut_state().tx_mode = TxMode::ClassicBuffered(tx_inner); }); self } @@ -509,8 +510,8 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Dr { fn drop(&mut self) { critical_section::with(|_| unsafe { - T::mut_state().rx_mode = sealed::RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); - T::mut_state().tx_mode = sealed::TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); + T::mut_state().rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); + T::mut_state().tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); }); } } @@ -585,14 +586,14 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> fn setup(self) -> Self { // We don't want interrupts being processed while we change modes. critical_section::with(|_| unsafe { - let rx_inner = sealed::FdBufferedRxInner { + let rx_inner = FdBufferedRxInner { rx_sender: self.rx_buf.sender().into(), }; - let tx_inner = sealed::FdBufferedTxInner { + let tx_inner = FdBufferedTxInner { tx_receiver: self.tx_buf.receiver().into(), }; - T::mut_state().rx_mode = sealed::RxMode::FdBuffered(rx_inner); - T::mut_state().tx_mode = sealed::TxMode::FdBuffered(tx_inner); + T::mut_state().rx_mode = RxMode::FdBuffered(rx_inner); + T::mut_state().tx_mode = TxMode::FdBuffered(tx_inner); }); self } @@ -627,8 +628,8 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Dr { fn drop(&mut self) { critical_section::with(|_| unsafe { - T::mut_state().rx_mode = sealed::RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); - T::mut_state().tx_mode = sealed::TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); + T::mut_state().rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); + T::mut_state().tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); }); } } @@ -677,192 +678,180 @@ impl<'c, 'd, T: Instance> FdcanRx<'d, T> { } } -pub(crate) mod sealed { - use core::future::poll_fn; - use core::task::Poll; +struct ClassicBufferedRxInner { + rx_sender: DynamicSender<'static, Result<(ClassicFrame, Timestamp), BusError>>, +} +struct ClassicBufferedTxInner { + tx_receiver: DynamicReceiver<'static, ClassicFrame>, +} - use embassy_sync::channel::{DynamicReceiver, DynamicSender}; - use embassy_sync::waitqueue::AtomicWaker; +struct FdBufferedRxInner { + rx_sender: DynamicSender<'static, Result<(FdFrame, Timestamp), BusError>>, +} +struct FdBufferedTxInner { + tx_receiver: DynamicReceiver<'static, FdFrame>, +} - use super::CanHeader; - use crate::can::_version::{BusError, Timestamp}; - use crate::can::frame::{ClassicFrame, FdFrame}; +enum RxMode { + NonBuffered(AtomicWaker), + ClassicBuffered(ClassicBufferedRxInner), + FdBuffered(FdBufferedRxInner), +} - pub struct ClassicBufferedRxInner { - pub rx_sender: DynamicSender<'static, Result<(ClassicFrame, Timestamp), BusError>>, - } - pub struct ClassicBufferedTxInner { - pub tx_receiver: DynamicReceiver<'static, ClassicFrame>, - } - - pub struct FdBufferedRxInner { - pub rx_sender: DynamicSender<'static, Result<(FdFrame, Timestamp), BusError>>, - } - pub struct FdBufferedTxInner { - pub tx_receiver: DynamicReceiver<'static, FdFrame>, - } - - pub enum RxMode { - NonBuffered(AtomicWaker), - ClassicBuffered(ClassicBufferedRxInner), - FdBuffered(FdBufferedRxInner), - } - - impl RxMode { - pub fn register(&self, arg: &core::task::Waker) { - match self { - RxMode::NonBuffered(waker) => waker.register(arg), - _ => { - panic!("Bad Mode") - } - } - } - - pub fn on_interrupt(&self, fifonr: usize) { - T::regs().ir().write(|w| w.set_rfn(fifonr, true)); - match self { - RxMode::NonBuffered(waker) => { - waker.wake(); - } - RxMode::ClassicBuffered(buf) => { - if let Some(result) = self.read::() { - let _ = buf.rx_sender.try_send(result); - } - } - RxMode::FdBuffered(buf) => { - if let Some(result) = self.read::() { - let _ = buf.rx_sender.try_send(result); - } - } - } - } - - fn read(&self) -> Option> { - if let Some((msg, ts)) = T::registers().read(0) { - let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); - Some(Ok((msg, ts))) - } else if let Some((msg, ts)) = T::registers().read(1) { - let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); - Some(Ok((msg, ts))) - } else if let Some(err) = T::registers().curr_error() { - // TODO: this is probably wrong - Some(Err(err)) - } else { - None - } - } - - async fn read_async(&self) -> Result<(F, Timestamp), BusError> { - poll_fn(|cx| { - T::state().err_waker.register(cx.waker()); - self.register(cx.waker()); - match self.read::() { - Some(result) => Poll::Ready(result), - None => Poll::Pending, - } - }) - .await - } - - pub async fn read_classic(&self) -> Result<(ClassicFrame, Timestamp), BusError> { - self.read_async::().await - } - - pub async fn read_fd(&self) -> Result<(FdFrame, Timestamp), BusError> { - self.read_async::().await - } - } - - pub enum TxMode { - NonBuffered(AtomicWaker), - ClassicBuffered(ClassicBufferedTxInner), - FdBuffered(FdBufferedTxInner), - } - - impl TxMode { - pub fn register(&self, arg: &core::task::Waker) { - match self { - TxMode::NonBuffered(waker) => { - waker.register(arg); - } - _ => { - panic!("Bad mode"); - } - } - } - - /// Queues the message to be sent but exerts backpressure. If a lower-priority - /// frame is dropped from the mailbox, it is returned. If no lower-priority frames - /// can be replaced, this call asynchronously waits for a frame to be successfully - /// transmitted, then tries again. - async fn write_generic(&self, frame: &F) -> Option { - poll_fn(|cx| { - self.register(cx.waker()); - - if let Ok(dropped) = T::registers().write(frame) { - return Poll::Ready(dropped); - } - - // Couldn't replace any lower priority frames. Need to wait for some mailboxes - // to clear. - Poll::Pending - }) - .await - } - - /// Queues the message to be sent but exerts backpressure. If a lower-priority - /// frame is dropped from the mailbox, it is returned. If no lower-priority frames - /// can be replaced, this call asynchronously waits for a frame to be successfully - /// transmitted, then tries again. - pub async fn write(&self, frame: &ClassicFrame) -> Option { - self.write_generic::(frame).await - } - - /// Queues the message to be sent but exerts backpressure. If a lower-priority - /// frame is dropped from the mailbox, it is returned. If no lower-priority frames - /// can be replaced, this call asynchronously waits for a frame to be successfully - /// transmitted, then tries again. - pub async fn write_fd(&self, frame: &FdFrame) -> Option { - self.write_generic::(frame).await - } - } - - pub struct State { - pub rx_mode: RxMode, - pub tx_mode: TxMode, - pub ns_per_timer_tick: u64, - - pub err_waker: AtomicWaker, - } - - impl State { - pub const fn new() -> Self { - Self { - rx_mode: RxMode::NonBuffered(AtomicWaker::new()), - tx_mode: TxMode::NonBuffered(AtomicWaker::new()), - ns_per_timer_tick: 0, - err_waker: AtomicWaker::new(), +impl RxMode { + fn register(&self, arg: &core::task::Waker) { + match self { + RxMode::NonBuffered(waker) => waker.register(arg), + _ => { + panic!("Bad Mode") } } } - pub trait Instance { - const MSG_RAM_OFFSET: usize; + fn on_interrupt(&self, fifonr: usize) { + T::regs().ir().write(|w| w.set_rfn(fifonr, true)); + match self { + RxMode::NonBuffered(waker) => { + waker.wake(); + } + RxMode::ClassicBuffered(buf) => { + if let Some(result) = self.read::() { + let _ = buf.rx_sender.try_send(result); + } + } + RxMode::FdBuffered(buf) => { + if let Some(result) = self.read::() { + let _ = buf.rx_sender.try_send(result); + } + } + } + } - fn regs() -> &'static crate::pac::can::Fdcan; - fn registers() -> crate::can::fd::peripheral::Registers; - fn ram() -> &'static crate::pac::fdcanram::Fdcanram; - fn state() -> &'static State; - unsafe fn mut_state() -> &'static mut State; - fn calc_timestamp(ns_per_timer_tick: u64, ts_val: u16) -> Timestamp; + fn read(&self) -> Option> { + if let Some((msg, ts)) = T::registers().read(0) { + let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); + Some(Ok((msg, ts))) + } else if let Some((msg, ts)) = T::registers().read(1) { + let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); + Some(Ok((msg, ts))) + } else if let Some(err) = T::registers().curr_error() { + // TODO: this is probably wrong + Some(Err(err)) + } else { + None + } + } + + async fn read_async(&self) -> Result<(F, Timestamp), BusError> { + poll_fn(|cx| { + T::state().err_waker.register(cx.waker()); + self.register(cx.waker()); + match self.read::() { + Some(result) => Poll::Ready(result), + None => Poll::Pending, + } + }) + .await + } + + async fn read_classic(&self) -> Result<(ClassicFrame, Timestamp), BusError> { + self.read_async::().await + } + + async fn read_fd(&self) -> Result<(FdFrame, Timestamp), BusError> { + self.read_async::().await } } +enum TxMode { + NonBuffered(AtomicWaker), + ClassicBuffered(ClassicBufferedTxInner), + FdBuffered(FdBufferedTxInner), +} + +impl TxMode { + fn register(&self, arg: &core::task::Waker) { + match self { + TxMode::NonBuffered(waker) => { + waker.register(arg); + } + _ => { + panic!("Bad mode"); + } + } + } + + /// Queues the message to be sent but exerts backpressure. If a lower-priority + /// frame is dropped from the mailbox, it is returned. If no lower-priority frames + /// can be replaced, this call asynchronously waits for a frame to be successfully + /// transmitted, then tries again. + async fn write_generic(&self, frame: &F) -> Option { + poll_fn(|cx| { + self.register(cx.waker()); + + if let Ok(dropped) = T::registers().write(frame) { + return Poll::Ready(dropped); + } + + // Couldn't replace any lower priority frames. Need to wait for some mailboxes + // to clear. + Poll::Pending + }) + .await + } + + /// Queues the message to be sent but exerts backpressure. If a lower-priority + /// frame is dropped from the mailbox, it is returned. If no lower-priority frames + /// can be replaced, this call asynchronously waits for a frame to be successfully + /// transmitted, then tries again. + async fn write(&self, frame: &ClassicFrame) -> Option { + self.write_generic::(frame).await + } + + /// Queues the message to be sent but exerts backpressure. If a lower-priority + /// frame is dropped from the mailbox, it is returned. If no lower-priority frames + /// can be replaced, this call asynchronously waits for a frame to be successfully + /// transmitted, then tries again. + async fn write_fd(&self, frame: &FdFrame) -> Option { + self.write_generic::(frame).await + } +} + +struct State { + pub rx_mode: RxMode, + pub tx_mode: TxMode, + pub ns_per_timer_tick: u64, + + pub err_waker: AtomicWaker, +} + +impl State { + const fn new() -> Self { + Self { + rx_mode: RxMode::NonBuffered(AtomicWaker::new()), + tx_mode: TxMode::NonBuffered(AtomicWaker::new()), + ns_per_timer_tick: 0, + err_waker: AtomicWaker::new(), + } + } +} + +trait SealedInstance { + const MSG_RAM_OFFSET: usize; + + fn regs() -> &'static crate::pac::can::Fdcan; + fn registers() -> crate::can::fd::peripheral::Registers; + fn state() -> &'static State; + unsafe fn mut_state() -> &'static mut State; + fn calc_timestamp(ns_per_timer_tick: u64, ts_val: u16) -> Timestamp; +} + /// Instance trait -pub trait Instance: sealed::Instance + RccPeripheral + 'static { +#[allow(private_bounds)] +pub trait Instance: SealedInstance + RccPeripheral + 'static { /// Interrupt 0 type IT0Interrupt: crate::interrupt::typelevel::Interrupt; - /// Interrupt 0 + /// Interrupt 1 type IT1Interrupt: crate::interrupt::typelevel::Interrupt; } @@ -871,7 +860,7 @@ pub struct FdcanInstance<'a, T>(PeripheralRef<'a, T>); macro_rules! impl_fdcan { ($inst:ident, $msg_ram_inst:ident, $msg_ram_offset:literal) => { - impl sealed::Instance for peripherals::$inst { + impl SealedInstance for peripherals::$inst { const MSG_RAM_OFFSET: usize = $msg_ram_offset; fn regs() -> &'static crate::pac::can::Fdcan { @@ -880,14 +869,11 @@ macro_rules! impl_fdcan { fn registers() -> Registers { Registers{regs: &crate::pac::$inst, msgram: &crate::pac::$msg_ram_inst, msg_ram_offset: Self::MSG_RAM_OFFSET} } - fn ram() -> &'static crate::pac::fdcanram::Fdcanram { - &crate::pac::$msg_ram_inst - } - unsafe fn mut_state() -> &'static mut sealed::State { - static mut STATE: sealed::State = sealed::State::new(); + unsafe fn mut_state() -> &'static mut State { + static mut STATE: State = State::new(); &mut *core::ptr::addr_of_mut!(STATE) } - fn state() -> &'static sealed::State { + fn state() -> &'static State { unsafe { peripherals::$inst::mut_state() } } diff --git a/embassy-stm32/src/crc/v1.rs b/embassy-stm32/src/crc/v1.rs index 0166ab819..f8909d438 100644 --- a/embassy-stm32/src/crc/v1.rs +++ b/embassy-stm32/src/crc/v1.rs @@ -2,7 +2,7 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; use crate::pac::CRC as PAC_CRC; use crate::peripherals::CRC; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::SealedRccPeripheral; use crate::Peripheral; /// CRC driver. diff --git a/embassy-stm32/src/crc/v2v3.rs b/embassy-stm32/src/crc/v2v3.rs index 0c4ae55ce..46f5ea1be 100644 --- a/embassy-stm32/src/crc/v2v3.rs +++ b/embassy-stm32/src/crc/v2v3.rs @@ -3,7 +3,7 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; use crate::pac::crc::vals; use crate::pac::CRC as PAC_CRC; use crate::peripherals::CRC; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::SealedRccPeripheral; use crate::Peripheral; /// CRC driver. diff --git a/embassy-stm32/src/cryp/mod.rs b/embassy-stm32/src/cryp/mod.rs index 74b095b6f..18b5ec918 100644 --- a/embassy-stm32/src/cryp/mod.rs +++ b/embassy-stm32/src/cryp/mod.rs @@ -1885,16 +1885,13 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> { } } -pub(crate) mod sealed { - use super::*; - - pub trait Instance { - fn regs() -> pac::cryp::Cryp; - } +trait SealedInstance { + fn regs() -> pac::cryp::Cryp; } /// CRYP instance trait. -pub trait Instance: sealed::Instance + Peripheral

+ crate::rcc::RccPeripheral + 'static + Send { +#[allow(private_bounds)] +pub trait Instance: SealedInstance + Peripheral

+ crate::rcc::RccPeripheral + 'static + Send { /// Interrupt for this CRYP instance. type Interrupt: interrupt::typelevel::Interrupt; } @@ -1905,7 +1902,7 @@ foreach_interrupt!( type Interrupt = crate::interrupt::typelevel::$irq; } - impl sealed::Instance for peripherals::$inst { + impl SealedInstance for peripherals::$inst { fn regs() -> crate::pac::cryp::Cryp { crate::pac::$inst } diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs index 60f9404c2..acfed8356 100644 --- a/embassy-stm32/src/dac/mod.rs +++ b/embassy-stm32/src/dac/mod.rs @@ -127,7 +127,7 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { pub fn new( _peri: impl Peripheral

+ 'd, dma: impl Peripheral

+ 'd, - pin: impl Peripheral

+ crate::gpio::sealed::Pin> + 'd, + pin: impl Peripheral

+ crate::gpio::Pin> + 'd, ) -> Self { into_ref!(dma, pin); pin.set_as_analog(); @@ -392,8 +392,8 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { _peri: impl Peripheral

+ 'd, dma_ch1: impl Peripheral

+ 'd, dma_ch2: impl Peripheral

+ 'd, - pin_ch1: impl Peripheral

+ crate::gpio::sealed::Pin> + 'd, - pin_ch2: impl Peripheral

+ crate::gpio::sealed::Pin> + 'd, + pin_ch1: impl Peripheral

+ crate::gpio::Pin> + 'd, + pin_ch2: impl Peripheral

+ crate::gpio::Pin> + 'd, ) -> Self { into_ref!(dma_ch1, dma_ch2, pin_ch1, pin_ch2); pin_ch1.set_as_analog(); @@ -488,14 +488,13 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { } } -pub(crate) mod sealed { - pub trait Instance { - fn regs() -> &'static crate::pac::dac::Dac; - } +trait SealedInstance { + fn regs() -> &'static crate::pac::dac::Dac; } /// DAC instance. -pub trait Instance: sealed::Instance + RccPeripheral + 'static {} +#[allow(private_bounds)] +pub trait Instance: SealedInstance + RccPeripheral + 'static {} dma_trait!(DacDma1, Instance); dma_trait!(DacDma2, Instance); @@ -504,7 +503,7 @@ pub trait DacPin: crate::gpio::Pin + 'static {} foreach_peripheral!( (dac, $inst:ident) => { - impl crate::dac::sealed::Instance for peripherals::$inst { + impl crate::dac::SealedInstance for peripherals::$inst { fn regs() -> &'static crate::pac::dac::Dac { &crate::pac::$inst } diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs index 826b04a4b..646ee2ce2 100644 --- a/embassy-stm32/src/dcmi.rs +++ b/embassy-stm32/src/dcmi.rs @@ -7,8 +7,7 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use crate::dma::Transfer; -use crate::gpio::sealed::AFType; -use crate::gpio::Speed; +use crate::gpio::{AFType, Speed}; use crate::interrupt::typelevel::Interrupt; use crate::{interrupt, Peripheral}; @@ -431,14 +430,13 @@ where } } -mod sealed { - pub trait Instance: crate::rcc::RccPeripheral { - fn regs(&self) -> crate::pac::dcmi::Dcmi; - } +trait SealedInstance: crate::rcc::RccPeripheral { + fn regs(&self) -> crate::pac::dcmi::Dcmi; } /// DCMI instance. -pub trait Instance: sealed::Instance + 'static { +#[allow(private_bounds)] +pub trait Instance: SealedInstance + 'static { /// Interrupt for this instance. type Interrupt: interrupt::typelevel::Interrupt; } @@ -465,7 +463,7 @@ pin_trait!(PixClkPin, Instance); #[allow(unused)] macro_rules! impl_peripheral { ($inst:ident, $irq:ident) => { - impl sealed::Instance for crate::peripherals::$inst { + impl SealedInstance for crate::peripherals::$inst { fn regs(&self) -> crate::pac::dcmi::Dcmi { crate::pac::$inst } diff --git a/embassy-stm32/src/dma/dmamux.rs b/embassy-stm32/src/dma/dmamux.rs index 1e9ab5944..dc7cd3a66 100644 --- a/embassy-stm32/src/dma/dmamux.rs +++ b/embassy-stm32/src/dma/dmamux.rs @@ -19,9 +19,7 @@ pub(crate) fn configure_dmamux(info: &DmamuxInfo, request: u8) { }); } -pub(crate) mod dmamux_sealed { - pub trait MuxChannel {} -} +pub(crate) trait SealedMuxChannel {} /// DMAMUX1 instance. pub struct DMAMUX1; @@ -30,14 +28,15 @@ pub struct DMAMUX1; pub struct DMAMUX2; /// DMAMUX channel trait. -pub trait MuxChannel: dmamux_sealed::MuxChannel { +#[allow(private_bounds)] +pub trait MuxChannel: SealedMuxChannel { /// DMAMUX instance this channel is on. type Mux; } macro_rules! dmamux_channel_impl { ($channel_peri:ident, $dmamux:ident) => { - impl crate::dma::dmamux_sealed::MuxChannel for crate::peripherals::$channel_peri {} + impl crate::dma::SealedMuxChannel for crate::peripherals::$channel_peri {} impl crate::dma::MuxChannel for crate::peripherals::$channel_peri { type Mux = crate::dma::$dmamux; } diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index 2f98b9857..7e3681469 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs @@ -39,18 +39,18 @@ pub type Request = u8; #[cfg(not(any(dma_v2, bdma_v2, gpdma, dmamux)))] pub type Request = (); -pub(crate) mod sealed { - pub trait Channel { - fn id(&self) -> u8; - } - pub trait ChannelInterrupt { - #[cfg_attr(not(feature = "rt"), allow(unused))] - unsafe fn on_irq(); - } +pub(crate) trait SealedChannel { + fn id(&self) -> u8; +} + +pub(crate) trait ChannelInterrupt { + #[cfg_attr(not(feature = "rt"), allow(unused))] + unsafe fn on_irq(); } /// DMA channel. -pub trait Channel: sealed::Channel + Peripheral

+ Into + 'static { +#[allow(private_bounds)] +pub trait Channel: SealedChannel + Peripheral

+ Into + 'static { /// Type-erase (degrade) this pin into an `AnyChannel`. /// /// This converts DMA channel singletons (`DMA1_CH3`, `DMA2_CH1`, ...), which @@ -64,12 +64,12 @@ pub trait Channel: sealed::Channel + Peripheral

+ Into + ' macro_rules! dma_channel_impl { ($channel_peri:ident, $index:expr) => { - impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri { + impl crate::dma::SealedChannel for crate::peripherals::$channel_peri { fn id(&self) -> u8 { $index } } - impl crate::dma::sealed::ChannelInterrupt for crate::peripherals::$channel_peri { + impl crate::dma::ChannelInterrupt for crate::peripherals::$channel_peri { unsafe fn on_irq() { crate::dma::AnyChannel { id: $index }.on_irq(); } @@ -97,7 +97,7 @@ impl AnyChannel { } } -impl sealed::Channel for AnyChannel { +impl SealedChannel for AnyChannel { fn id(&self) -> u8 { self.id } diff --git a/embassy-stm32/src/dma/word.rs b/embassy-stm32/src/dma/word.rs index a72c4b7d9..fb1bde860 100644 --- a/embassy-stm32/src/dma/word.rs +++ b/embassy-stm32/src/dma/word.rs @@ -20,14 +20,13 @@ impl WordSize { } } -mod sealed { - pub trait Word {} -} +trait SealedWord {} /// DMA word trait. /// /// This is implemented for u8, u16, u32, etc. -pub trait Word: sealed::Word + Default + Copy + 'static { +#[allow(private_bounds)] +pub trait Word: SealedWord + Default + Copy + 'static { /// Word size fn size() -> WordSize; /// Amount of bits of this word size. @@ -36,7 +35,7 @@ pub trait Word: sealed::Word + Default + Copy + 'static { macro_rules! impl_word { (_, $T:ident, $bits:literal, $size:ident) => { - impl sealed::Word for $T {} + impl SealedWord for $T {} impl Word for $T { fn bits() -> usize { $bits diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs index 71fe09c3f..bfe8a60d6 100644 --- a/embassy-stm32/src/eth/mod.rs +++ b/embassy-stm32/src/eth/mod.rs @@ -177,16 +177,15 @@ pub unsafe trait PHY { fn poll_link(&mut self, sm: &mut S, cx: &mut Context) -> bool; } -pub(crate) mod sealed { - pub trait Instance { - fn regs() -> crate::pac::eth::Eth; - } +trait SealedInstance { + fn regs() -> crate::pac::eth::Eth; } /// Ethernet instance. -pub trait Instance: sealed::Instance + RccPeripheral + Send + 'static {} +#[allow(private_bounds)] +pub trait Instance: SealedInstance + RccPeripheral + Send + 'static {} -impl sealed::Instance for crate::peripherals::ETH { +impl SealedInstance for crate::peripherals::ETH { fn regs() -> crate::pac::eth::Eth { crate::pac::ETH } diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs index e5b7b0452..6f0174def 100644 --- a/embassy-stm32/src/eth/v1/mod.rs +++ b/embassy-stm32/src/eth/v1/mod.rs @@ -12,15 +12,14 @@ use stm32_metapac::eth::vals::{Apcs, Cr, Dm, DmaomrSr, Fes, Ftf, Ifg, MbProgress pub(crate) use self::rx_desc::{RDes, RDesRing}; pub(crate) use self::tx_desc::{TDes, TDesRing}; use super::*; -use crate::gpio::sealed::{AFType, Pin as __GpioPin}; -use crate::gpio::AnyPin; +use crate::gpio::{AFType, AnyPin, SealedPin}; use crate::interrupt::InterruptExt; #[cfg(eth_v1a)] use crate::pac::AFIO; #[cfg(any(eth_v1b, eth_v1c))] use crate::pac::SYSCFG; use crate::pac::{ETH, RCC}; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::SealedRccPeripheral; use crate::{interrupt, Peripheral}; /// Interrupt handler. @@ -149,8 +148,8 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { #[cfg(any(eth_v1b, eth_v1c))] config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); - let dma = ETH.ethernet_dma(); - let mac = ETH.ethernet_mac(); + let dma = T::regs().ethernet_dma(); + let mac = T::regs().ethernet_mac(); // Reset and wait dma.dmabmr().modify(|w| w.set_sr(true)); @@ -192,7 +191,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { // TODO MTU size setting not found for v1 ethernet, check if correct - let hclk = ::frequency(); + let hclk = ::frequency(); let hclk_mhz = hclk.0 / 1_000_000; // Set the MDC clock frequency in the range 1MHz - 2.5MHz @@ -235,8 +234,8 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { fence(Ordering::SeqCst); - let mac = ETH.ethernet_mac(); - let dma = ETH.ethernet_dma(); + let mac = T::regs().ethernet_mac(); + let dma = T::regs().ethernet_dma(); mac.maccr().modify(|w| { w.set_re(true); @@ -275,7 +274,7 @@ pub struct EthernetStationManagement { unsafe impl StationManagement for EthernetStationManagement { fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 { - let mac = ETH.ethernet_mac(); + let mac = T::regs().ethernet_mac(); mac.macmiiar().modify(|w| { w.set_pa(phy_addr); @@ -289,7 +288,7 @@ unsafe impl StationManagement for EthernetStationManagement { } fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) { - let mac = ETH.ethernet_mac(); + let mac = T::regs().ethernet_mac(); mac.macmiidr().write(|w| w.set_md(val)); mac.macmiiar().modify(|w| { @@ -305,8 +304,8 @@ unsafe impl StationManagement for EthernetStationManagement { impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { fn drop(&mut self) { - let dma = ETH.ethernet_dma(); - let mac = ETH.ethernet_mac(); + let dma = T::regs().ethernet_dma(); + let mac = T::regs().ethernet_mac(); // Disable the TX DMA and wait for any previous transmissions to be completed dma.dmaomr().modify(|w| w.set_st(St::STOPPED)); diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index 8d69561d4..c6e015022 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs @@ -7,11 +7,10 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing}; use super::*; -use crate::gpio::sealed::{AFType, Pin as _}; -use crate::gpio::{AnyPin, Speed}; +use crate::gpio::{AFType, AnyPin, SealedPin as _, Speed}; use crate::interrupt::InterruptExt; use crate::pac::ETH; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::SealedRccPeripheral; use crate::{interrupt, Peripheral}; /// Interrupt handler. @@ -207,9 +206,9 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { phy: P, mac_addr: [u8; 6], ) -> Self { - let dma = ETH.ethernet_dma(); - let mac = ETH.ethernet_mac(); - let mtl = ETH.ethernet_mtl(); + let dma = T::regs().ethernet_dma(); + let mac = T::regs().ethernet_mac(); + let mtl = T::regs().ethernet_mtl(); // Reset and wait dma.dmamr().modify(|w| w.set_swr(true)); @@ -265,7 +264,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { w.set_rbsz(RX_BUFFER_SIZE as u16); }); - let hclk = ::frequency(); + let hclk = ::frequency(); let hclk_mhz = hclk.0 / 1_000_000; // Set the MDC clock frequency in the range 1MHz - 2.5MHz @@ -296,9 +295,9 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { fence(Ordering::SeqCst); - let mac = ETH.ethernet_mac(); - let mtl = ETH.ethernet_mtl(); - let dma = ETH.ethernet_dma(); + let mac = T::regs().ethernet_mac(); + let mtl = T::regs().ethernet_mtl(); + let dma = T::regs().ethernet_dma(); mac.maccr().modify(|w| { w.set_re(true); @@ -334,7 +333,7 @@ pub struct EthernetStationManagement { unsafe impl StationManagement for EthernetStationManagement { fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 { - let mac = ETH.ethernet_mac(); + let mac = T::regs().ethernet_mac(); mac.macmdioar().modify(|w| { w.set_pa(phy_addr); @@ -348,7 +347,7 @@ unsafe impl StationManagement for EthernetStationManagement { } fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) { - let mac = ETH.ethernet_mac(); + let mac = T::regs().ethernet_mac(); mac.macmdiodr().write(|w| w.set_md(val)); mac.macmdioar().modify(|w| { @@ -364,9 +363,9 @@ unsafe impl StationManagement for EthernetStationManagement { impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { fn drop(&mut self) { - let dma = ETH.ethernet_dma(); - let mac = ETH.ethernet_mac(); - let mtl = ETH.ethernet_mtl(); + let dma = T::regs().ethernet_dma(); + let mac = T::regs().ethernet_mac(); + let mtl = T::regs().ethernet_mtl(); // Disable the TX DMA and wait for any previous transmissions to be completed dma.dmactx_cr().modify(|w| w.set_st(false)); diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs index bd10ba158..8d5dae436 100644 --- a/embassy-stm32/src/exti.rs +++ b/embassy-stm32/src/exti.rs @@ -330,12 +330,11 @@ macro_rules! impl_irq { foreach_exti_irq!(impl_irq); -pub(crate) mod sealed { - pub trait Channel {} -} +trait SealedChannel {} /// EXTI channel trait. -pub trait Channel: sealed::Channel + Sized { +#[allow(private_bounds)] +pub trait Channel: SealedChannel + Sized { /// Get the EXTI channel number. fn number(&self) -> u8; @@ -359,7 +358,7 @@ pub struct AnyChannel { } impl_peripheral!(AnyChannel); -impl sealed::Channel for AnyChannel {} +impl SealedChannel for AnyChannel {} impl Channel for AnyChannel { fn number(&self) -> u8 { self.number @@ -368,7 +367,7 @@ impl Channel for AnyChannel { macro_rules! impl_exti { ($type:ident, $number:expr) => { - impl sealed::Channel for peripherals::$type {} + impl SealedChannel for peripherals::$type {} impl Channel for peripherals::$type { fn number(&self) -> u8 { $number diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs index 9d731a512..aced69878 100644 --- a/embassy-stm32/src/fmc.rs +++ b/embassy-stm32/src/fmc.rs @@ -3,8 +3,7 @@ use core::marker::PhantomData; use embassy_hal_internal::into_ref; -use crate::gpio::sealed::AFType; -use crate::gpio::{Pull, Speed}; +use crate::gpio::{AFType, Pull, Speed}; use crate::Peripheral; /// FMC driver @@ -44,7 +43,7 @@ where /// Get the kernel clock currently in use for this FMC instance. pub fn source_clock_hz(&self) -> u32 { - ::frequency().0 + ::frequency().0 } } @@ -69,7 +68,7 @@ where } fn source_clock_hz(&self) -> u32 { - ::frequency().0 + ::frequency().0 } } @@ -201,18 +200,17 @@ impl<'d, T: Instance> Fmc<'d, T> { )); } -pub(crate) mod sealed { - pub trait Instance: crate::rcc::sealed::RccPeripheral { - const REGS: crate::pac::fmc::Fmc; - } +trait SealedInstance: crate::rcc::SealedRccPeripheral { + const REGS: crate::pac::fmc::Fmc; } /// FMC instance trait. -pub trait Instance: sealed::Instance + 'static {} +#[allow(private_bounds)] +pub trait Instance: SealedInstance + 'static {} foreach_peripheral!( (fmc, $inst:ident) => { - impl crate::fmc::sealed::Instance for crate::peripherals::$inst { + impl crate::fmc::SealedInstance for crate::peripherals::$inst { const REGS: crate::pac::fmc::Fmc = crate::pac::$inst; } impl crate::fmc::Instance for crate::peripherals::$inst {} diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index 7cc28ff56..33f22f676 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs @@ -6,7 +6,6 @@ use core::convert::Infallible; use critical_section::CriticalSection; use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef}; -use self::sealed::Pin as _; use crate::pac::gpio::{self, vals}; use crate::{pac, peripherals, Peripheral}; @@ -129,6 +128,18 @@ impl<'d> Flex<'d> { }); } + /// Put the pin into AF mode, unchecked. + /// + /// This puts the pin into the AF mode, with the requested number, pull and speed. This is + /// completely unchecked, it can attach the pin to literally any peripheral, so use with care. + #[inline] + pub fn set_as_af_unchecked(&mut self, af_num: u8, af_type: AFType, pull: Pull, speed: Speed) { + critical_section::with(|_| { + self.pin.set_as_af_pull(af_num, af_type, pull); + self.pin.set_speed(speed); + }); + } + /// Get whether the pin input level is high. #[inline] pub fn is_high(&self) -> bool { @@ -508,172 +519,168 @@ pub enum OutputType { OpenDrain, } -impl From for sealed::AFType { +impl From for AFType { fn from(value: OutputType) -> Self { match value { - OutputType::OpenDrain => sealed::AFType::OutputOpenDrain, - OutputType::PushPull => sealed::AFType::OutputPushPull, + OutputType::OpenDrain => AFType::OutputOpenDrain, + OutputType::PushPull => AFType::OutputPushPull, } } } -#[allow(missing_docs)] -pub(crate) mod sealed { - use super::*; +/// Alternate function type settings +#[derive(Debug, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum AFType { + /// Input + Input, + /// Output, drive the pin both high or low. + OutputPushPull, + /// Output, drive the pin low, or don't drive it at all if the output level is high. + OutputOpenDrain, +} - /// Alternate function type settings - #[derive(Debug, Copy, Clone)] - #[cfg_attr(feature = "defmt", derive(defmt::Format))] - pub enum AFType { - /// Input - Input, - /// Output, drive the pin both high or low. - OutputPushPull, - /// Output, drive the pin low, or don't drive it at all if the output level is high. - OutputOpenDrain, +pub(crate) trait SealedPin { + fn pin_port(&self) -> u8; + + #[inline] + fn _pin(&self) -> u8 { + self.pin_port() % 16 + } + #[inline] + fn _port(&self) -> u8 { + self.pin_port() / 16 } - pub trait Pin { - fn pin_port(&self) -> u8; + #[inline] + fn block(&self) -> gpio::Gpio { + pac::GPIO(self._port() as _) + } - #[inline] - fn _pin(&self) -> u8 { - self.pin_port() % 16 - } - #[inline] - fn _port(&self) -> u8 { - self.pin_port() / 16 - } + /// Set the output as high. + #[inline] + fn set_high(&self) { + let n = self._pin() as _; + self.block().bsrr().write(|w| w.set_bs(n, true)); + } - #[inline] - fn block(&self) -> gpio::Gpio { - pac::GPIO(self._port() as _) - } + /// Set the output as low. + #[inline] + fn set_low(&self) { + let n = self._pin() as _; + self.block().bsrr().write(|w| w.set_br(n, true)); + } - /// Set the output as high. - #[inline] - fn set_high(&self) { - let n = self._pin() as _; - self.block().bsrr().write(|w| w.set_bs(n, true)); - } + #[inline] + fn set_as_af(&self, af_num: u8, af_type: AFType) { + self.set_as_af_pull(af_num, af_type, Pull::None); + } - /// Set the output as low. - #[inline] - fn set_low(&self) { - let n = self._pin() as _; - self.block().bsrr().write(|w| w.set_br(n, true)); - } + #[cfg(gpio_v1)] + #[inline] + fn set_as_af_pull(&self, _af_num: u8, af_type: AFType, pull: Pull) { + // F1 uses the AFIO register for remapping. + // For now, this is not implemented, so af_num is ignored + // _af_num should be zero here, since it is not set by stm32-data + let r = self.block(); + let n = self._pin() as usize; + let crlh = if n < 8 { 0 } else { 1 }; + match af_type { + AFType::Input => { + let cnf = match pull { + Pull::Up => { + r.bsrr().write(|w| w.set_bs(n, true)); + vals::CnfIn::PULL + } + Pull::Down => { + r.bsrr().write(|w| w.set_br(n, true)); + vals::CnfIn::PULL + } + Pull::None => vals::CnfIn::FLOATING, + }; - #[inline] - fn set_as_af(&self, af_num: u8, af_type: AFType) { - self.set_as_af_pull(af_num, af_type, Pull::None); + r.cr(crlh).modify(|w| { + w.set_mode(n % 8, vals::Mode::INPUT); + w.set_cnf_in(n % 8, cnf); + }); + } + AFType::OutputPushPull => { + r.cr(crlh).modify(|w| { + w.set_mode(n % 8, vals::Mode::OUTPUT50MHZ); + w.set_cnf_out(n % 8, vals::CnfOut::ALTPUSHPULL); + }); + } + AFType::OutputOpenDrain => { + r.cr(crlh).modify(|w| { + w.set_mode(n % 8, vals::Mode::OUTPUT50MHZ); + w.set_cnf_out(n % 8, vals::CnfOut::ALTOPENDRAIN); + }); + } } + } + + #[cfg(gpio_v2)] + #[inline] + fn set_as_af_pull(&self, af_num: u8, af_type: AFType, pull: Pull) { + let pin = self._pin() as usize; + let block = self.block(); + block.afr(pin / 8).modify(|w| w.set_afr(pin % 8, af_num)); + match af_type { + AFType::Input => {} + AFType::OutputPushPull => block.otyper().modify(|w| w.set_ot(pin, vals::Ot::PUSHPULL)), + AFType::OutputOpenDrain => block.otyper().modify(|w| w.set_ot(pin, vals::Ot::OPENDRAIN)), + } + block.pupdr().modify(|w| w.set_pupdr(pin, pull.into())); + + block.moder().modify(|w| w.set_moder(pin, vals::Moder::ALTERNATE)); + } + + #[inline] + fn set_as_analog(&self) { + let pin = self._pin() as usize; + let block = self.block(); + #[cfg(gpio_v1)] + { + let crlh = if pin < 8 { 0 } else { 1 }; + block.cr(crlh).modify(|w| { + w.set_mode(pin % 8, vals::Mode::INPUT); + w.set_cnf_in(pin % 8, vals::CnfIn::ANALOG); + }); + } + #[cfg(gpio_v2)] + block.moder().modify(|w| w.set_moder(pin, vals::Moder::ANALOG)); + } + + /// Set the pin as "disconnected", ie doing nothing and consuming the lowest + /// amount of power possible. + /// + /// This is currently the same as set_as_analog but is semantically different really. + /// Drivers should set_as_disconnected pins when dropped. + #[inline] + fn set_as_disconnected(&self) { + self.set_as_analog(); + } + + #[inline] + fn set_speed(&self, speed: Speed) { + let pin = self._pin() as usize; #[cfg(gpio_v1)] - #[inline] - fn set_as_af_pull(&self, _af_num: u8, af_type: AFType, pull: Pull) { - // F1 uses the AFIO register for remapping. - // For now, this is not implemented, so af_num is ignored - // _af_num should be zero here, since it is not set by stm32-data - let r = self.block(); - let n = self._pin() as usize; - let crlh = if n < 8 { 0 } else { 1 }; - match af_type { - AFType::Input => { - let cnf = match pull { - Pull::Up => { - r.bsrr().write(|w| w.set_bs(n, true)); - vals::CnfIn::PULL - } - Pull::Down => { - r.bsrr().write(|w| w.set_br(n, true)); - vals::CnfIn::PULL - } - Pull::None => vals::CnfIn::FLOATING, - }; - - r.cr(crlh).modify(|w| { - w.set_mode(n % 8, vals::Mode::INPUT); - w.set_cnf_in(n % 8, cnf); - }); - } - AFType::OutputPushPull => { - r.cr(crlh).modify(|w| { - w.set_mode(n % 8, vals::Mode::OUTPUT50MHZ); - w.set_cnf_out(n % 8, vals::CnfOut::ALTPUSHPULL); - }); - } - AFType::OutputOpenDrain => { - r.cr(crlh).modify(|w| { - w.set_mode(n % 8, vals::Mode::OUTPUT50MHZ); - w.set_cnf_out(n % 8, vals::CnfOut::ALTOPENDRAIN); - }); - } - } + { + let crlh = if pin < 8 { 0 } else { 1 }; + self.block().cr(crlh).modify(|w| { + w.set_mode(pin % 8, speed.into()); + }); } #[cfg(gpio_v2)] - #[inline] - fn set_as_af_pull(&self, af_num: u8, af_type: AFType, pull: Pull) { - let pin = self._pin() as usize; - let block = self.block(); - block.afr(pin / 8).modify(|w| w.set_afr(pin % 8, af_num)); - match af_type { - AFType::Input => {} - AFType::OutputPushPull => block.otyper().modify(|w| w.set_ot(pin, vals::Ot::PUSHPULL)), - AFType::OutputOpenDrain => block.otyper().modify(|w| w.set_ot(pin, vals::Ot::OPENDRAIN)), - } - block.pupdr().modify(|w| w.set_pupdr(pin, pull.into())); - - block.moder().modify(|w| w.set_moder(pin, vals::Moder::ALTERNATE)); - } - - #[inline] - fn set_as_analog(&self) { - let pin = self._pin() as usize; - let block = self.block(); - #[cfg(gpio_v1)] - { - let crlh = if pin < 8 { 0 } else { 1 }; - block.cr(crlh).modify(|w| { - w.set_mode(pin % 8, vals::Mode::INPUT); - w.set_cnf_in(pin % 8, vals::CnfIn::ANALOG); - }); - } - #[cfg(gpio_v2)] - block.moder().modify(|w| w.set_moder(pin, vals::Moder::ANALOG)); - } - - /// Set the pin as "disconnected", ie doing nothing and consuming the lowest - /// amount of power possible. - /// - /// This is currently the same as set_as_analog but is semantically different really. - /// Drivers should set_as_disconnected pins when dropped. - #[inline] - fn set_as_disconnected(&self) { - self.set_as_analog(); - } - - #[inline] - fn set_speed(&self, speed: Speed) { - let pin = self._pin() as usize; - - #[cfg(gpio_v1)] - { - let crlh = if pin < 8 { 0 } else { 1 }; - self.block().cr(crlh).modify(|w| { - w.set_mode(pin % 8, speed.into()); - }); - } - - #[cfg(gpio_v2)] - self.block().ospeedr().modify(|w| w.set_ospeedr(pin, speed.into())); - } + self.block().ospeedr().modify(|w| w.set_ospeedr(pin, speed.into())); } } /// GPIO pin trait. -pub trait Pin: Peripheral

+ Into + sealed::Pin + Sized + 'static { +#[allow(private_bounds)] +pub trait Pin: Peripheral

+ Into + SealedPin + Sized + 'static { /// EXTI channel assigned to this pin. /// /// For example, PC4 uses EXTI4. @@ -737,7 +744,7 @@ impl Pin for AnyPin { #[cfg(feature = "exti")] type ExtiChannel = crate::exti::AnyChannel; } -impl sealed::Pin for AnyPin { +impl SealedPin for AnyPin { #[inline] fn pin_port(&self) -> u8 { self.pin_port @@ -752,7 +759,7 @@ foreach_pin!( #[cfg(feature = "exti")] type ExtiChannel = peripherals::$exti_ch; } - impl sealed::Pin for peripherals::$pin_name { + impl SealedPin for peripherals::$pin_name { #[inline] fn pin_port(&self) -> u8 { $port_num * 16 + $pin_num @@ -769,7 +776,7 @@ foreach_pin!( pub(crate) unsafe fn init(_cs: CriticalSection) { #[cfg(afio)] - ::enable_and_reset_with_cs(_cs); + ::enable_and_reset_with_cs(_cs); crate::_generated::init_gpio(); @@ -1061,9 +1068,3 @@ impl<'d> embedded_hal_1::digital::StatefulOutputPin for Flex<'d> { Ok((*self).is_set_low()) } } - -/// Low-level GPIO manipulation. -#[cfg(feature = "unstable-pac")] -pub mod low_level { - pub use super::sealed::*; -} diff --git a/embassy-stm32/src/hash/mod.rs b/embassy-stm32/src/hash/mod.rs index b47814f8b..787d5b1c9 100644 --- a/embassy-stm32/src/hash/mod.rs +++ b/embassy-stm32/src/hash/mod.rs @@ -17,7 +17,7 @@ use crate::dma::NoDma; use crate::dma::Transfer; use crate::interrupt::typelevel::Interrupt; use crate::peripherals::HASH; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::SealedRccPeripheral; use crate::{interrupt, pac, peripherals, Peripheral}; #[cfg(hash_v1)] @@ -561,16 +561,13 @@ impl<'d, T: Instance, D> Hash<'d, T, D> { } } -pub(crate) mod sealed { - use super::*; - - pub trait Instance { - fn regs() -> pac::hash::Hash; - } +trait SealedInstance { + fn regs() -> pac::hash::Hash; } /// HASH instance trait. -pub trait Instance: sealed::Instance + Peripheral

+ crate::rcc::RccPeripheral + 'static + Send { +#[allow(private_bounds)] +pub trait Instance: SealedInstance + Peripheral

+ crate::rcc::RccPeripheral + 'static + Send { /// Interrupt for this HASH instance. type Interrupt: interrupt::typelevel::Interrupt; } @@ -581,7 +578,7 @@ foreach_interrupt!( type Interrupt = crate::interrupt::typelevel::$irq; } - impl sealed::Instance for peripherals::$inst { + impl SealedInstance for peripherals::$inst { fn regs() -> crate::pac::hash::Hash { crate::pac::$inst } diff --git a/embassy-stm32/src/hrtim/mod.rs b/embassy-stm32/src/hrtim/mod.rs index 3ec646fc3..02e45819c 100644 --- a/embassy-stm32/src/hrtim/mod.rs +++ b/embassy-stm32/src/hrtim/mod.rs @@ -7,9 +7,7 @@ use core::marker::PhantomData; use embassy_hal_internal::{into_ref, PeripheralRef}; pub use traits::Instance; -#[allow(unused_imports)] -use crate::gpio::sealed::{AFType, Pin}; -use crate::gpio::AnyPin; +use crate::gpio::{AFType, AnyPin}; use crate::time::Hertz; use crate::Peripheral; @@ -54,16 +52,13 @@ pub struct ChF { phantom: PhantomData, } -mod sealed { - use super::Instance; - - pub trait AdvancedChannel { - fn raw() -> usize; - } +trait SealedAdvancedChannel { + fn raw() -> usize; } /// Advanced channel instance trait. -pub trait AdvancedChannel: sealed::AdvancedChannel {} +#[allow(private_bounds)] +pub trait AdvancedChannel: SealedAdvancedChannel {} /// HRTIM PWM pin. pub struct PwmPin<'d, T, C> { @@ -113,7 +108,7 @@ macro_rules! advanced_channel_impl { } } - impl sealed::AdvancedChannel for $channel { + impl SealedAdvancedChannel for $channel { fn raw() -> usize { $ch_num } diff --git a/embassy-stm32/src/hrtim/traits.rs b/embassy-stm32/src/hrtim/traits.rs index dcc2b9ef4..75f9971e2 100644 --- a/embassy-stm32/src/hrtim/traits.rs +++ b/embassy-stm32/src/hrtim/traits.rs @@ -1,4 +1,4 @@ -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::RccPeripheral; use crate::time::Hertz; #[repr(u8)] @@ -72,94 +72,92 @@ impl Prescaler { } } -pub(crate) mod sealed { - use super::*; +pub(crate) trait SealedInstance: RccPeripheral { + fn regs() -> crate::pac::hrtim::Hrtim; - pub trait Instance: RccPeripheral { - fn regs() -> crate::pac::hrtim::Hrtim; + #[allow(unused)] + fn set_master_frequency(frequency: Hertz) { + let f = frequency.0; - fn set_master_frequency(frequency: Hertz) { - let f = frequency.0; + // TODO: wire up HRTIM to the RCC mux infra. + //#[cfg(stm32f334)] + //let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0; + //#[cfg(not(stm32f334))] + let timer_f = Self::frequency().0; - // TODO: wire up HRTIM to the RCC mux infra. - //#[cfg(stm32f334)] - //let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0; - //#[cfg(not(stm32f334))] - let timer_f = Self::frequency().0; + let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); + let psc = if Self::regs().isr().read().dllrdy() { + Prescaler::compute_min_high_res(psc_min) + } else { + Prescaler::compute_min_low_res(psc_min) + }; - let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); - let psc = if Self::regs().isr().read().dllrdy() { - Prescaler::compute_min_high_res(psc_min) - } else { - Prescaler::compute_min_low_res(psc_min) - }; + let timer_f = 32 * (timer_f / psc as u32); + let per: u16 = (timer_f / f) as u16; - let timer_f = 32 * (timer_f / psc as u32); - let per: u16 = (timer_f / f) as u16; + let regs = Self::regs(); - let regs = Self::regs(); + regs.mcr().modify(|w| w.set_ckpsc(psc.into())); + regs.mper().modify(|w| w.set_mper(per)); + } - regs.mcr().modify(|w| w.set_ckpsc(psc.into())); - regs.mper().modify(|w| w.set_mper(per)); - } + fn set_channel_frequency(channel: usize, frequency: Hertz) { + let f = frequency.0; - fn set_channel_frequency(channel: usize, frequency: Hertz) { - let f = frequency.0; + // TODO: wire up HRTIM to the RCC mux infra. + //#[cfg(stm32f334)] + //let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0; + //#[cfg(not(stm32f334))] + let timer_f = Self::frequency().0; - // TODO: wire up HRTIM to the RCC mux infra. - //#[cfg(stm32f334)] - //let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0; - //#[cfg(not(stm32f334))] - let timer_f = Self::frequency().0; + let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); + let psc = if Self::regs().isr().read().dllrdy() { + Prescaler::compute_min_high_res(psc_min) + } else { + Prescaler::compute_min_low_res(psc_min) + }; - let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); - let psc = if Self::regs().isr().read().dllrdy() { - Prescaler::compute_min_high_res(psc_min) - } else { - Prescaler::compute_min_low_res(psc_min) - }; + let timer_f = 32 * (timer_f / psc as u32); + let per: u16 = (timer_f / f) as u16; - let timer_f = 32 * (timer_f / psc as u32); - let per: u16 = (timer_f / f) as u16; + let regs = Self::regs(); - let regs = Self::regs(); + regs.tim(channel).cr().modify(|w| w.set_ckpsc(psc.into())); + regs.tim(channel).per().modify(|w| w.set_per(per)); + } - regs.tim(channel).cr().modify(|w| w.set_ckpsc(psc.into())); - regs.tim(channel).per().modify(|w| w.set_per(per)); - } + /// Set the dead time as a proportion of max_duty + fn set_channel_dead_time(channel: usize, dead_time: u16) { + let regs = Self::regs(); - /// Set the dead time as a proportion of max_duty - fn set_channel_dead_time(channel: usize, dead_time: u16) { - let regs = Self::regs(); + let channel_psc: Prescaler = regs.tim(channel).cr().read().ckpsc().into(); - let channel_psc: Prescaler = regs.tim(channel).cr().read().ckpsc().into(); + // The dead-time base clock runs 4 times slower than the hrtim base clock + // u9::MAX = 511 + let psc_min = (channel_psc as u32 * dead_time as u32) / (4 * 511); + let psc = if Self::regs().isr().read().dllrdy() { + Prescaler::compute_min_high_res(psc_min) + } else { + Prescaler::compute_min_low_res(psc_min) + }; - // The dead-time base clock runs 4 times slower than the hrtim base clock - // u9::MAX = 511 - let psc_min = (channel_psc as u32 * dead_time as u32) / (4 * 511); - let psc = if Self::regs().isr().read().dllrdy() { - Prescaler::compute_min_high_res(psc_min) - } else { - Prescaler::compute_min_low_res(psc_min) - }; + let dt_val = (psc as u32 * dead_time as u32) / (4 * channel_psc as u32); - let dt_val = (psc as u32 * dead_time as u32) / (4 * channel_psc as u32); - - regs.tim(channel).dt().modify(|w| { - w.set_dtprsc(psc.into()); - w.set_dtf(dt_val as u16); - w.set_dtr(dt_val as u16); - }); - } + regs.tim(channel).dt().modify(|w| { + w.set_dtprsc(psc.into()); + w.set_dtf(dt_val as u16); + w.set_dtr(dt_val as u16); + }); } } /// HRTIM instance trait. -pub trait Instance: sealed::Instance + 'static {} +#[allow(private_bounds)] +pub trait Instance: SealedInstance + 'static {} foreach_interrupt! { ($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => { - impl sealed::Instance for crate::peripherals::$inst { + impl SealedInstance for crate::peripherals::$inst { fn regs() -> crate::pac::hrtim::Hrtim { crate::pac::$inst } diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 2c606c3c9..f1b11cc44 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -14,8 +14,7 @@ use embassy_sync::waitqueue::AtomicWaker; use embassy_time::{Duration, Instant}; use crate::dma::NoDma; -use crate::gpio::sealed::AFType; -use crate::gpio::Pull; +use crate::gpio::{AFType, Pull}; use crate::interrupt::typelevel::Interrupt; use crate::time::Hertz; use crate::{interrupt, peripherals}; @@ -175,30 +174,27 @@ impl Timeout { } } -pub(crate) mod sealed { - use super::*; +struct State { + #[allow(unused)] + waker: AtomicWaker, +} - pub struct State { - #[allow(unused)] - pub waker: AtomicWaker, - } - - impl State { - pub const fn new() -> Self { - Self { - waker: AtomicWaker::new(), - } +impl State { + const fn new() -> Self { + Self { + waker: AtomicWaker::new(), } } - - pub trait Instance: crate::rcc::RccPeripheral { - fn regs() -> crate::pac::i2c::I2c; - fn state() -> &'static State; - } +} + +trait SealedInstance: crate::rcc::RccPeripheral { + fn regs() -> crate::pac::i2c::I2c; + fn state() -> &'static State; } /// I2C peripheral instance -pub trait Instance: sealed::Instance + 'static { +#[allow(private_bounds)] +pub trait Instance: SealedInstance + 'static { /// Event interrupt for this instance type EventInterrupt: interrupt::typelevel::Interrupt; /// Error interrupt for this instance @@ -234,13 +230,13 @@ impl interrupt::typelevel::Handler for ErrorInte foreach_peripheral!( (i2c, $inst:ident) => { - impl sealed::Instance for peripherals::$inst { + impl SealedInstance for peripherals::$inst { fn regs() -> crate::pac::i2c::I2c { crate::pac::$inst } - fn state() -> &'static sealed::State { - static STATE: sealed::State = sealed::State::new(); + fn state() -> &'static State { + static STATE: State = State::new(); &STATE } } diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs index fa9ec0532..c5a606b21 100644 --- a/embassy-stm32/src/i2s.rs +++ b/embassy-stm32/src/i2s.rs @@ -1,8 +1,7 @@ //! Inter-IC Sound (I2S) use embassy_hal_internal::into_ref; -use crate::gpio::sealed::{AFType, Pin as _}; -use crate::gpio::AnyPin; +use crate::gpio::{AFType, AnyPin, SealedPin}; use crate::pac::spi::vals; use crate::spi::{Config as SpiConfig, *}; use crate::time::Hertz; diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs index 523719bb9..4d535cce2 100644 --- a/embassy-stm32/src/ipcc.rs +++ b/embassy-stm32/src/ipcc.rs @@ -4,11 +4,12 @@ use core::future::poll_fn; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; -use self::sealed::Instance; +use embassy_sync::waitqueue::AtomicWaker; + use crate::interrupt; use crate::interrupt::typelevel::Interrupt; use crate::peripherals::IPCC; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::SealedRccPeripheral; /// Interrupt handler. pub struct ReceiveInterruptHandler {} @@ -207,7 +208,7 @@ impl Ipcc { } } -impl sealed::Instance for crate::peripherals::IPCC { +impl SealedInstance for crate::peripherals::IPCC { fn regs() -> crate::pac::ipcc::Ipcc { crate::pac::IPCC } @@ -216,58 +217,52 @@ impl sealed::Instance for crate::peripherals::IPCC { crate::pac::PWR.cr4().modify(|w| w.set_c2boot(enabled)); } - fn state() -> &'static self::sealed::State { - static STATE: self::sealed::State = self::sealed::State::new(); + fn state() -> &'static State { + static STATE: State = State::new(); &STATE } } -pub(crate) mod sealed { - use embassy_sync::waitqueue::AtomicWaker; +struct State { + rx_wakers: [AtomicWaker; 6], + tx_wakers: [AtomicWaker; 6], +} - use super::*; +impl State { + const fn new() -> Self { + const WAKER: AtomicWaker = AtomicWaker::new(); - pub struct State { - rx_wakers: [AtomicWaker; 6], - tx_wakers: [AtomicWaker; 6], - } - - impl State { - pub const fn new() -> Self { - const WAKER: AtomicWaker = AtomicWaker::new(); - - Self { - rx_wakers: [WAKER; 6], - tx_wakers: [WAKER; 6], - } - } - - pub const fn rx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker { - match channel { - IpccChannel::Channel1 => &self.rx_wakers[0], - IpccChannel::Channel2 => &self.rx_wakers[1], - IpccChannel::Channel3 => &self.rx_wakers[2], - IpccChannel::Channel4 => &self.rx_wakers[3], - IpccChannel::Channel5 => &self.rx_wakers[4], - IpccChannel::Channel6 => &self.rx_wakers[5], - } - } - - pub const fn tx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker { - match channel { - IpccChannel::Channel1 => &self.tx_wakers[0], - IpccChannel::Channel2 => &self.tx_wakers[1], - IpccChannel::Channel3 => &self.tx_wakers[2], - IpccChannel::Channel4 => &self.tx_wakers[3], - IpccChannel::Channel5 => &self.tx_wakers[4], - IpccChannel::Channel6 => &self.tx_wakers[5], - } + Self { + rx_wakers: [WAKER; 6], + tx_wakers: [WAKER; 6], } } - pub trait Instance: crate::rcc::RccPeripheral { - fn regs() -> crate::pac::ipcc::Ipcc; - fn set_cpu2(enabled: bool); - fn state() -> &'static State; + const fn rx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker { + match channel { + IpccChannel::Channel1 => &self.rx_wakers[0], + IpccChannel::Channel2 => &self.rx_wakers[1], + IpccChannel::Channel3 => &self.rx_wakers[2], + IpccChannel::Channel4 => &self.rx_wakers[3], + IpccChannel::Channel5 => &self.rx_wakers[4], + IpccChannel::Channel6 => &self.rx_wakers[5], + } + } + + const fn tx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker { + match channel { + IpccChannel::Channel1 => &self.tx_wakers[0], + IpccChannel::Channel2 => &self.tx_wakers[1], + IpccChannel::Channel3 => &self.tx_wakers[2], + IpccChannel::Channel4 => &self.tx_wakers[3], + IpccChannel::Channel5 => &self.tx_wakers[4], + IpccChannel::Channel6 => &self.tx_wakers[5], + } } } + +trait SealedInstance: crate::rcc::RccPeripheral { + fn regs() -> crate::pac::ipcc::Ipcc; + fn set_cpu2(enabled: bool); + fn state() -> &'static State; +} diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 9e26a3513..6a3d1c463 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -158,7 +158,7 @@ pub(crate) use stm32_metapac as pac; use crate::interrupt::Priority; #[cfg(feature = "rt")] pub use crate::pac::NVIC_PRIO_BITS; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::SealedRccPeripheral; /// `embassy-stm32` global configuration. #[non_exhaustive] diff --git a/embassy-stm32/src/opamp.rs b/embassy-stm32/src/opamp.rs index cf531e266..a3b4352c0 100644 --- a/embassy-stm32/src/opamp.rs +++ b/embassy-stm32/src/opamp.rs @@ -81,8 +81,8 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// [`OpAmpOutput`] is dropped. pub fn buffer_ext( &'d mut self, - in_pin: impl Peripheral

+ crate::gpio::sealed::Pin>, - out_pin: impl Peripheral

+ crate::gpio::sealed::Pin> + 'd, + in_pin: impl Peripheral

+ crate::gpio::Pin>, + out_pin: impl Peripheral

+ crate::gpio::Pin> + 'd, gain: OpAmpGain, ) -> OpAmpOutput<'d, T> { into_ref!(in_pin); @@ -122,7 +122,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { #[cfg(opamp_g4)] pub fn buffer_int( &'d mut self, - pin: impl Peripheral

+ crate::gpio::sealed::Pin>, + pin: impl Peripheral

+ crate::gpio::Pin>, gain: OpAmpGain, ) -> OpAmpInternalOutput<'d, T> { into_ref!(pin); @@ -166,37 +166,39 @@ impl<'d, T: Instance> Drop for OpAmpInternalOutput<'d, T> { } } -/// Opamp instance trait. -pub trait Instance: sealed::Instance + 'static {} - -pub(crate) mod sealed { - pub trait Instance { - fn regs() -> crate::pac::opamp::Opamp; - } - - pub trait NonInvertingPin { - fn channel(&self) -> u8; - } - - pub trait InvertingPin { - fn channel(&self) -> u8; - } - - pub trait OutputPin {} +pub(crate) trait SealedInstance { + fn regs() -> crate::pac::opamp::Opamp; } +pub(crate) trait SealedNonInvertingPin { + fn channel(&self) -> u8; +} + +pub(crate) trait SealedInvertingPin { + #[allow(unused)] + fn channel(&self) -> u8; +} + +pub(crate) trait SealedOutputPin {} + +/// Opamp instance trait. +#[allow(private_bounds)] +pub trait Instance: SealedInstance + 'static {} /// Non-inverting pin trait. -pub trait NonInvertingPin: sealed::NonInvertingPin {} +#[allow(private_bounds)] +pub trait NonInvertingPin: SealedNonInvertingPin {} /// Inverting pin trait. -pub trait InvertingPin: sealed::InvertingPin {} +#[allow(private_bounds)] +pub trait InvertingPin: SealedInvertingPin {} /// Output pin trait. -pub trait OutputPin: sealed::OutputPin {} +#[allow(private_bounds)] +pub trait OutputPin: SealedOutputPin {} macro_rules! impl_opamp_external_output { ($inst:ident, $adc:ident, $ch:expr) => { foreach_adc!( ($adc, $common_inst:ident, $adc_clock:ident) => { - impl<'d> crate::adc::sealed::AdcPin + impl<'d> crate::adc::SealedAdcPin for OpAmpOutput<'d, crate::peripherals::$inst> { fn channel(&self) -> u8 { @@ -242,7 +244,7 @@ macro_rules! impl_opamp_internal_output { ($inst:ident, $adc:ident, $ch:expr) => { foreach_adc!( ($adc, $common_inst:ident, $adc_clock:ident) => { - impl<'d> crate::adc::sealed::AdcPin + impl<'d> crate::adc::SealedAdcPin for OpAmpInternalOutput<'d, crate::peripherals::$inst> { fn channel(&self) -> u8 { @@ -291,7 +293,7 @@ foreach_peripheral!( foreach_peripheral! { (opamp, $inst:ident) => { - impl sealed::Instance for crate::peripherals::$inst { + impl SealedInstance for crate::peripherals::$inst { fn regs() -> crate::pac::opamp::Opamp { crate::pac::$inst } @@ -306,7 +308,7 @@ foreach_peripheral! { macro_rules! impl_opamp_vp_pin { ($inst:ident, $pin:ident, $ch:expr) => { impl crate::opamp::NonInvertingPin for crate::peripherals::$pin {} - impl crate::opamp::sealed::NonInvertingPin for crate::peripherals::$pin { + impl crate::opamp::SealedNonInvertingPin for crate::peripherals::$pin { fn channel(&self) -> u8 { $ch } @@ -318,6 +320,6 @@ macro_rules! impl_opamp_vp_pin { macro_rules! impl_opamp_vout_pin { ($inst:ident, $pin:ident) => { impl crate::opamp::OutputPin for crate::peripherals::$pin {} - impl crate::opamp::sealed::OutputPin for crate::peripherals::$pin {} + impl crate::opamp::SealedOutputPin for crate::peripherals::$pin {} }; } diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index 8a709a89e..3c054e666 100644 --- a/embassy-stm32/src/qspi/mod.rs +++ b/embassy-stm32/src/qspi/mod.rs @@ -8,8 +8,7 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; use enums::*; use crate::dma::Transfer; -use crate::gpio::sealed::AFType; -use crate::gpio::{AnyPin, Pull}; +use crate::gpio::{AFType, AnyPin, Pull}; use crate::pac::quadspi::Quadspi as Regs; use crate::rcc::RccPeripheral; use crate::{peripherals, Peripheral}; @@ -381,16 +380,13 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { } } -pub(crate) mod sealed { - use super::*; - - pub trait Instance { - const REGS: Regs; - } +trait SealedInstance { + const REGS: Regs; } /// QSPI instance trait. -pub trait Instance: Peripheral

+ sealed::Instance + RccPeripheral {} +#[allow(private_bounds)] +pub trait Instance: Peripheral

+ SealedInstance + RccPeripheral {} pin_trait!(SckPin, Instance); pin_trait!(BK1D0Pin, Instance); @@ -409,7 +405,7 @@ dma_trait!(QuadDma, Instance); foreach_peripheral!( (quadspi, $inst:ident) => { - impl sealed::Instance for peripherals::$inst { + impl SealedInstance for peripherals::$inst { const REGS: Regs = crate::pac::$inst; } diff --git a/embassy-stm32/src/rcc/hsi48.rs b/embassy-stm32/src/rcc/hsi48.rs index 19a8c8cb9..6f0d7b379 100644 --- a/embassy-stm32/src/rcc/hsi48.rs +++ b/embassy-stm32/src/rcc/hsi48.rs @@ -2,7 +2,7 @@ use crate::pac::crs::vals::Syncsrc; use crate::pac::{CRS, RCC}; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::SealedRccPeripheral; use crate::time::Hertz; /// HSI48 speed diff --git a/embassy-stm32/src/rcc/mco.rs b/embassy-stm32/src/rcc/mco.rs index 654943bc1..d8604e07e 100644 --- a/embassy-stm32/src/rcc/mco.rs +++ b/embassy-stm32/src/rcc/mco.rs @@ -2,8 +2,7 @@ use core::marker::PhantomData; use embassy_hal_internal::into_ref; -use crate::gpio::sealed::AFType; -use crate::gpio::Speed; +use crate::gpio::{AFType, Speed}; #[cfg(not(any(stm32f1, rcc_f0v1, rcc_f3v1, rcc_f37)))] pub use crate::pac::rcc::vals::Mcopre as McoPrescaler; #[cfg(not(any(rcc_f2, rcc_f410, rcc_f4, rcc_f7, rcc_h50, rcc_h5, rcc_h7ab, rcc_h7rm0433, rcc_h7)))] @@ -19,23 +18,25 @@ pub enum McoPrescaler { DIV1, } -pub(crate) mod sealed { - pub trait McoInstance { - type Source; - unsafe fn apply_clock_settings(source: Self::Source, prescaler: super::McoPrescaler); - } -} +pub(crate) trait SealedMcoInstance {} -pub trait McoInstance: sealed::McoInstance + 'static {} +#[allow(private_bounds)] +pub trait McoInstance: SealedMcoInstance + 'static { + type Source; + + #[doc(hidden)] + unsafe fn _apply_clock_settings(source: Self::Source, prescaler: super::McoPrescaler); +} pin_trait!(McoPin, McoInstance); macro_rules! impl_peri { ($peri:ident, $source:ident, $set_source:ident, $set_prescaler:ident) => { - impl sealed::McoInstance for peripherals::$peri { + impl SealedMcoInstance for peripherals::$peri {} + impl McoInstance for peripherals::$peri { type Source = $source; - unsafe fn apply_clock_settings(source: Self::Source, _prescaler: McoPrescaler) { + unsafe fn _apply_clock_settings(source: Self::Source, _prescaler: McoPrescaler) { #[cfg(not(any(stm32u5, stm32wba)))] let r = RCC.cfgr(); #[cfg(any(stm32u5, stm32wba))] @@ -48,8 +49,6 @@ macro_rules! impl_peri { }); } } - - impl McoInstance for peripherals::$peri {} }; } @@ -79,7 +78,7 @@ impl<'d, T: McoInstance> Mco<'d, T> { into_ref!(pin); critical_section::with(|_| unsafe { - T::apply_clock_settings(source, prescaler); + T::_apply_clock_settings(source, prescaler); pin.set_as_af(pin.af_num(), AFType::OutputPushPull); pin.set_speed(Speed::VeryHigh); }); diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 910ebe205..d53d02203 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -10,6 +10,7 @@ pub use bd::*; #[cfg(any(mco, mco1, mco2))] mod mco; +use critical_section::CriticalSection; #[cfg(any(mco, mco1, mco2))] pub use mco::*; @@ -32,6 +33,7 @@ mod _version; pub use _version::*; pub use crate::_generated::{mux, Clocks}; +use crate::time::Hertz; #[cfg(feature = "low-power")] /// Must be written within a critical section @@ -63,29 +65,21 @@ pub(crate) unsafe fn get_freqs() -> &'static Clocks { CLOCK_FREQS.assume_init_ref() } -#[cfg(feature = "unstable-pac")] -pub mod low_level { - pub use super::sealed::*; -} +pub(crate) trait SealedRccPeripheral { + fn frequency() -> crate::time::Hertz; + fn enable_and_reset_with_cs(cs: CriticalSection); + fn disable_with_cs(cs: CriticalSection); -pub(crate) mod sealed { - use critical_section::CriticalSection; - - pub trait RccPeripheral { - fn frequency() -> crate::time::Hertz; - fn enable_and_reset_with_cs(cs: CriticalSection); - fn disable_with_cs(cs: CriticalSection); - - fn enable_and_reset() { - critical_section::with(|cs| Self::enable_and_reset_with_cs(cs)) - } - fn disable() { - critical_section::with(|cs| Self::disable_with_cs(cs)) - } + fn enable_and_reset() { + critical_section::with(|cs| Self::enable_and_reset_with_cs(cs)) + } + fn disable() { + critical_section::with(|cs| Self::disable_with_cs(cs)) } } -pub trait RccPeripheral: sealed::RccPeripheral + 'static {} +#[allow(private_bounds)] +pub trait RccPeripheral: SealedRccPeripheral + 'static {} #[allow(unused)] mod util { @@ -116,3 +110,12 @@ mod util { Ok(Some(x)) } } + +/// Get the kernel clocok frequency of the peripheral `T`. +/// +/// # Panics +/// +/// Panics if the clock is not active. +pub fn frequency() -> Hertz { + T::frequency() +} diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs index ca641f352..7a228e4a4 100644 --- a/embassy-stm32/src/rng.rs +++ b/embassy-stm32/src/rng.rs @@ -222,16 +222,13 @@ impl<'d, T: Instance> RngCore for Rng<'d, T> { impl<'d, T: Instance> CryptoRng for Rng<'d, T> {} -pub(crate) mod sealed { - use super::*; - - pub trait Instance { - fn regs() -> pac::rng::Rng; - } +trait SealedInstance { + fn regs() -> pac::rng::Rng; } /// RNG instance trait. -pub trait Instance: sealed::Instance + Peripheral

+ crate::rcc::RccPeripheral + 'static + Send { +#[allow(private_bounds)] +pub trait Instance: SealedInstance + Peripheral

+ crate::rcc::RccPeripheral + 'static + Send { /// Interrupt for this RNG instance. type Interrupt: interrupt::typelevel::Interrupt; } @@ -242,7 +239,7 @@ foreach_interrupt!( type Interrupt = crate::interrupt::typelevel::$irq; } - impl sealed::Instance for peripherals::$inst { + impl SealedInstance for peripherals::$inst { fn regs() -> crate::pac::rng::Rng { crate::pac::$inst } diff --git a/embassy-stm32/src/rtc/datetime.rs b/embassy-stm32/src/rtc/datetime.rs index 2bad79923..bab8cf4a3 100644 --- a/embassy-stm32/src/rtc/datetime.rs +++ b/embassy-stm32/src/rtc/datetime.rs @@ -4,7 +4,7 @@ use chrono::{Datelike, NaiveDate, Timelike, Weekday}; #[cfg(any(feature = "defmt", feature = "time"))] use crate::peripherals::RTC; #[cfg(any(feature = "defmt", feature = "time"))] -use crate::rtc::sealed::Instance; +use crate::rtc::SealedInstance; /// Represents an instant in time that can be substracted to compute a duration pub struct RtcInstant { diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 169505501..00abe9356 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -31,7 +31,6 @@ pub use _version::*; use embassy_hal_internal::Peripheral; use crate::peripherals::RTC; -use crate::rtc::sealed::Instance; #[allow(dead_code)] #[repr(u8)] @@ -212,7 +211,7 @@ impl Rtc { /// Create a new RTC instance. pub fn new(_rtc: impl Peripheral

, rtc_config: RtcConfig) -> Self { #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))] - ::enable_and_reset(); + ::enable_and_reset(); let mut this = Self { #[cfg(feature = "low-power")] @@ -437,7 +436,7 @@ impl Rtc { .fpr(0) .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); - ::WakeupInterrupt::unpend(); + ::WakeupInterrupt::unpend(); }); } @@ -449,8 +448,8 @@ impl Rtc { use crate::interrupt::typelevel::Interrupt; use crate::pac::EXTI; - ::WakeupInterrupt::unpend(); - unsafe { ::WakeupInterrupt::enable() }; + ::WakeupInterrupt::unpend(); + unsafe { ::WakeupInterrupt::enable() }; EXTI.rtsr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); EXTI.imr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); @@ -477,34 +476,30 @@ pub(crate) fn bcd2_to_byte(bcd: (u8, u8)) -> u8 { tmp + (value & 0x0F) } -pub(crate) mod sealed { - use crate::pac::rtc::Rtc; +trait SealedInstance { + const BACKUP_REGISTER_COUNT: usize; - pub trait Instance { - const BACKUP_REGISTER_COUNT: usize; + #[cfg(feature = "low-power")] + const EXTI_WAKEUP_LINE: usize; - #[cfg(feature = "low-power")] - const EXTI_WAKEUP_LINE: usize; + #[cfg(feature = "low-power")] + type WakeupInterrupt: crate::interrupt::typelevel::Interrupt; - #[cfg(feature = "low-power")] - type WakeupInterrupt: crate::interrupt::typelevel::Interrupt; - - fn regs() -> Rtc { - crate::pac::RTC - } - - /// Read content of the backup register. - /// - /// The registers retain their values during wakes from standby mode or system resets. They also - /// retain their value when Vdd is switched off as long as V_BAT is powered. - fn read_backup_register(rtc: &Rtc, register: usize) -> Option; - - /// Set content of the backup register. - /// - /// The registers retain their values during wakes from standby mode or system resets. They also - /// retain their value when Vdd is switched off as long as V_BAT is powered. - fn write_backup_register(rtc: &Rtc, register: usize, value: u32); - - // fn apply_config(&mut self, rtc_config: RtcConfig); + fn regs() -> crate::pac::rtc::Rtc { + crate::pac::RTC } + + /// Read content of the backup register. + /// + /// The registers retain their values during wakes from standby mode or system resets. They also + /// retain their value when Vdd is switched off as long as V_BAT is powered. + fn read_backup_register(rtc: &crate::pac::rtc::Rtc, register: usize) -> Option; + + /// Set content of the backup register. + /// + /// The registers retain their values during wakes from standby mode or system resets. They also + /// retain their value when Vdd is switched off as long as V_BAT is powered. + fn write_backup_register(rtc: &crate::pac::rtc::Rtc, register: usize, value: u32); + + // fn apply_config(&mut self, rtc_config: RtcConfig); } diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 1eda097a7..92f9de846 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -1,9 +1,8 @@ use stm32_metapac::rtc::vals::{Osel, Pol}; -use super::sealed; +use super::SealedInstance; use crate::pac::rtc::Rtc; use crate::peripherals::RTC; -use crate::rtc::sealed::Instance; #[allow(dead_code)] impl super::Rtc { @@ -126,7 +125,7 @@ impl super::Rtc { } } -impl sealed::Instance for crate::peripherals::RTC { +impl SealedInstance for crate::peripherals::RTC { const BACKUP_REGISTER_COUNT: usize = 20; #[cfg(all(feature = "low-power", stm32f4))] diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 3d44a52ff..8a78d16e1 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs @@ -1,9 +1,9 @@ use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Key, Osel, Pol, TampalrmType}; -use super::{sealed, RtcCalibrationCyclePeriod}; +use super::RtcCalibrationCyclePeriod; use crate::pac::rtc::Rtc; use crate::peripherals::RTC; -use crate::rtc::sealed::Instance; +use crate::rtc::SealedInstance; impl super::Rtc { /// Applies the RTC config @@ -126,7 +126,7 @@ impl super::Rtc { } } -impl sealed::Instance for crate::peripherals::RTC { +impl SealedInstance for crate::peripherals::RTC { const BACKUP_REGISTER_COUNT: usize = 32; #[cfg(all(feature = "low-power", stm32g4))] diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index 294620031..54dd81524 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs @@ -6,12 +6,10 @@ use core::marker::PhantomData; use embassy_hal_internal::{into_ref, PeripheralRef}; -use self::sealed::WhichSubBlock; pub use crate::dma::word; #[cfg(not(gpdma))] use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer}; -use crate::gpio::sealed::{AFType, Pin as _}; -use crate::gpio::AnyPin; +use crate::gpio::{AFType, AnyPin, SealedPin as _}; use crate::pac::sai::{vals, Sai as Regs}; use crate::rcc::RccPeripheral; use crate::{peripherals, Peripheral}; @@ -1041,43 +1039,42 @@ impl<'d, T: Instance, W: word::Word> Drop for Sai<'d, T, W> { } } -pub(crate) mod sealed { - use super::*; +trait SealedInstance { + const REGS: Regs; +} - pub trait Instance { - const REGS: Regs; - } +#[derive(Copy, Clone)] +enum WhichSubBlock { + A = 0, + B = 1, +} - #[derive(Copy, Clone)] - pub enum WhichSubBlock { - A = 0, - B = 1, - } - - pub trait SubBlock { - const WHICH: WhichSubBlock; - } +trait SealedSubBlock { + const WHICH: WhichSubBlock; } /// Sub-block instance trait. -pub trait SubBlockInstance: sealed::SubBlock {} +#[allow(private_bounds)] +pub trait SubBlockInstance: SealedSubBlock {} /// Sub-block A. pub enum A {} -impl sealed::SubBlock for A { +impl SealedSubBlock for A { const WHICH: WhichSubBlock = WhichSubBlock::A; } impl SubBlockInstance for A {} /// Sub-block B. pub enum B {} -impl sealed::SubBlock for B { +impl SealedSubBlock for B { const WHICH: WhichSubBlock = WhichSubBlock::B; } impl SubBlockInstance for B {} /// SAI instance trait. -pub trait Instance: Peripheral

+ sealed::Instance + RccPeripheral {} +#[allow(private_bounds)] +pub trait Instance: Peripheral

+ SealedInstance + RccPeripheral {} + pin_trait!(SckPin, Instance, SubBlockInstance); pin_trait!(FsPin, Instance, SubBlockInstance); pin_trait!(SdPin, Instance, SubBlockInstance); @@ -1087,7 +1084,7 @@ dma_trait!(Dma, Instance, SubBlockInstance); foreach_peripheral!( (sai, $inst:ident) => { - impl sealed::Instance for peripherals::$inst { + impl SealedInstance for peripherals::$inst { const REGS: Regs = crate::pac::$inst; } diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index c0b3a2183..f79a11606 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs @@ -13,8 +13,7 @@ use embassy_sync::waitqueue::AtomicWaker; use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; use crate::dma::NoDma; -use crate::gpio::sealed::{AFType, Pin}; -use crate::gpio::{AnyPin, Pull, Speed}; +use crate::gpio::{AFType, AnyPin, Pull, SealedPin, Speed}; use crate::interrupt::typelevel::Interrupt; use crate::pac::sdmmc::Sdmmc as RegBlock; use crate::rcc::RccPeripheral; @@ -1418,19 +1417,17 @@ impl Cmd { ////////////////////////////////////////////////////// -pub(crate) mod sealed { - use super::*; - - pub trait Instance { - type Interrupt: interrupt::typelevel::Interrupt; - - fn regs() -> RegBlock; - fn state() -> &'static AtomicWaker; - } +trait SealedInstance { + fn regs() -> RegBlock; + fn state() -> &'static AtomicWaker; } /// SDMMC instance trait. -pub trait Instance: sealed::Instance + RccPeripheral + 'static {} +#[allow(private_bounds)] +pub trait Instance: SealedInstance + RccPeripheral + 'static { + /// Interrupt for this instance. + type Interrupt: interrupt::typelevel::Interrupt; +} pin_trait!(CkPin, Instance); pin_trait!(CmdPin, Instance); @@ -1457,9 +1454,7 @@ impl SdmmcDma for NoDma {} foreach_peripheral!( (sdmmc, $inst:ident) => { - impl sealed::Instance for peripherals::$inst { - type Interrupt = crate::interrupt::typelevel::$inst; - + impl SealedInstance for peripherals::$inst { fn regs() -> RegBlock { crate::pac::$inst } @@ -1470,6 +1465,8 @@ foreach_peripheral!( } } - impl Instance for peripherals::$inst {} + impl Instance for peripherals::$inst { + type Interrupt = crate::interrupt::typelevel::$inst; + } }; ); diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index b517f640a..0b38c4288 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -9,8 +9,7 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; use crate::dma::{slice_ptr_parts, word, Transfer}; -use crate::gpio::sealed::{AFType, Pin as _}; -use crate::gpio::{AnyPin, Pull}; +use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _}; use crate::pac::spi::{regs, vals, Spi as Regs}; use crate::rcc::RccPeripheral; use crate::time::Hertz; @@ -210,7 +209,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { // see RM0453 rev 1 section 7.2.13 page 291 // The SUBGHZSPI_SCK frequency is obtained by PCLK3 divided by two. // The SUBGHZSPI_SCK clock maximum speed must not exceed 16 MHz. - let pclk3_freq = ::frequency().0; + let pclk3_freq = ::frequency().0; let freq = Hertz(core::cmp::min(pclk3_freq / 2, 16_000_000)); let mut config = Config::default(); config.mode = MODE_0; @@ -271,13 +270,13 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { if mosi.is_none() { w.set_rxonly(vals::Rxonly::OUTPUTDISABLED); } - w.set_dff(::CONFIG) + w.set_dff(::CONFIG) }); } #[cfg(spi_v2)] { T::REGS.cr2().modify(|w| { - let (ds, frxth) = ::CONFIG; + let (ds, frxth) = ::CONFIG; w.set_frxth(frxth); w.set_ds(ds); w.set_ssoe(false); @@ -317,7 +316,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { T::REGS.cfg1().modify(|w| { w.set_crcen(false); w.set_mbr(br); - w.set_dsize(::CONFIG); + w.set_dsize(::CONFIG); w.set_fthlv(vals::Fthlv::ONEFRAME); }); T::REGS.cr2().modify(|w| { @@ -336,7 +335,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { miso, txdma, rxdma, - current_word_size: ::CONFIG, + current_word_size: ::CONFIG, } } @@ -975,24 +974,21 @@ impl<'d, T: Instance, Tx: TxDma, Rx: RxDma, W: Word> embedded_hal_async::s } } -pub(crate) mod sealed { - use super::*; +pub(crate) trait SealedInstance { + const REGS: Regs; +} - pub trait Instance { - const REGS: Regs; - } - - pub trait Word { - const CONFIG: word_impl::Config; - } +trait SealedWord { + const CONFIG: word_impl::Config; } /// Word sizes usable for SPI. -pub trait Word: word::Word + sealed::Word {} +#[allow(private_bounds)] +pub trait Word: word::Word + SealedWord {} macro_rules! impl_word { ($T:ty, $config:expr) => { - impl sealed::Word for $T { + impl SealedWord for $T { const CONFIG: Config = $config; } impl Word for $T {} @@ -1068,7 +1064,8 @@ mod word_impl { } /// SPI instance trait. -pub trait Instance: Peripheral

+ sealed::Instance + RccPeripheral {} +#[allow(private_bounds)] +pub trait Instance: Peripheral

+ SealedInstance + RccPeripheral {} pin_trait!(SckPin, Instance); pin_trait!(MosiPin, Instance); @@ -1082,7 +1079,7 @@ dma_trait!(TxDma, Instance); foreach_peripheral!( (spi, $inst:ident) => { - impl sealed::Instance for peripherals::$inst { + impl SealedInstance for peripherals::$inst { const REGS: Regs = crate::pac::$inst; } diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index e78f81dca..cc8161276 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs @@ -8,16 +8,16 @@ use critical_section::CriticalSection; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::Mutex; use embassy_time_driver::{AlarmHandle, Driver, TICK_HZ}; -use stm32_metapac::timer::regs; +use stm32_metapac::timer::{regs, TimGp16}; use crate::interrupt::typelevel::Interrupt; use crate::pac::timer::vals; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::SealedRccPeripheral; #[cfg(feature = "low-power")] use crate::rtc::Rtc; #[cfg(any(time_driver_tim1, time_driver_tim8, time_driver_tim20))] -use crate::timer::sealed::AdvancedControlInstance; -use crate::timer::sealed::{CoreInstance, GeneralPurpose16bitInstance as Instance}; +use crate::timer::AdvancedInstance1Channel; +use crate::timer::CoreInstance; use crate::{interrupt, peripherals}; // NOTE regarding ALARM_COUNT: @@ -207,6 +207,10 @@ foreach_interrupt! { }; } +fn regs_gp16() -> TimGp16 { + unsafe { TimGp16::from_ptr(T::regs()) } +} + // Clock timekeeping works with something we call "periods", which are time intervals // of 2^15 ticks. The Clock counter value is 16 bits, so one "overflow cycle" is 2 periods. // @@ -271,9 +275,9 @@ embassy_time_driver::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver { impl RtcDriver { fn init(&'static self, cs: critical_section::CriticalSection) { - let r = T::regs_gp16(); + let r = regs_gp16(); - ::enable_and_reset_with_cs(cs); + ::enable_and_reset_with_cs(cs); let timer_freq = T::frequency(); @@ -308,9 +312,9 @@ impl RtcDriver { #[cfg(any(time_driver_tim1, time_driver_tim8, time_driver_tim20))] { - ::CaptureCompareInterrupt::unpend(); + ::CaptureCompareInterrupt::unpend(); unsafe { - ::CaptureCompareInterrupt::enable(); + ::CaptureCompareInterrupt::enable(); } } @@ -318,7 +322,7 @@ impl RtcDriver { } fn on_interrupt(&self) { - let r = T::regs_gp16(); + let r = regs_gp16(); // XXX: reduce the size of this critical section ? critical_section::with(|cs| { @@ -349,7 +353,7 @@ impl RtcDriver { } fn next_period(&self) { - let r = T::regs_gp16(); + let r = regs_gp16(); // We only modify the period from the timer interrupt, so we know this can't race. let period = self.period.load(Ordering::Relaxed) + 1; @@ -413,7 +417,7 @@ impl RtcDriver { /// Add the given offset to the current time fn add_time(&self, offset: embassy_time::Duration, cs: CriticalSection) { let offset = offset.as_ticks(); - let cnt = T::regs_gp16().cnt().read().cnt() as u32; + let cnt = regs_gp16().cnt().read().cnt() as u32; let period = self.period.load(Ordering::SeqCst); // Correct the race, if it exists @@ -439,7 +443,7 @@ impl RtcDriver { let period = if cnt > u16::MAX as u32 / 2 { period + 1 } else { period }; self.period.store(period, Ordering::SeqCst); - T::regs_gp16().cnt().write(|w| w.set_cnt(cnt as u16)); + regs_gp16().cnt().write(|w| w.set_cnt(cnt as u16)); // Now, recompute all alarms for i in 0..ALARM_COUNT { @@ -496,7 +500,7 @@ impl RtcDriver { .unwrap() .start_wakeup_alarm(time_until_next_alarm, cs); - T::regs_gp16().cr1().modify(|w| w.set_cen(false)); + regs_gp16().cr1().modify(|w| w.set_cen(false)); Ok(()) } @@ -506,7 +510,7 @@ impl RtcDriver { #[cfg(feature = "low-power")] /// Resume the timer with the given offset pub(crate) fn resume_time(&self) { - if T::regs_gp16().cr1().read().cen() { + if regs_gp16().cr1().read().cen() { // Time isn't currently stopped return; @@ -515,14 +519,14 @@ impl RtcDriver { critical_section::with(|cs| { self.stop_wakeup_alarm(cs); - T::regs_gp16().cr1().modify(|w| w.set_cen(true)); + regs_gp16().cr1().modify(|w| w.set_cen(true)); }) } } impl Driver for RtcDriver { fn now(&self) -> u64 { - let r = T::regs_gp16(); + let r = regs_gp16(); let period = self.period.load(Ordering::Relaxed); compiler_fence(Ordering::Acquire); @@ -553,7 +557,7 @@ impl Driver for RtcDriver { fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) -> bool { critical_section::with(|cs| { - let r = T::regs_gp16(); + let r = regs_gp16(); let n = alarm.id() as usize; let alarm = self.get_alarm(cs, alarm); diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index 723e8506b..a892646cf 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -5,11 +5,15 @@ use core::marker::PhantomData; use embassy_hal_internal::{into_ref, PeripheralRef}; use stm32_metapac::timer::vals::Ckd; -use super::simple_pwm::*; -use super::*; -#[allow(unused_imports)] -use crate::gpio::sealed::{AFType, Pin}; +use super::low_level::{CountingMode, OutputPolarity, Timer}; +use super::simple_pwm::{Ch1, Ch2, Ch3, Ch4, PwmPin}; +use super::{ + AdvancedInstance4Channel, Channel, Channel1ComplementaryPin, Channel2ComplementaryPin, Channel3ComplementaryPin, + Channel4ComplementaryPin, +}; use crate::gpio::{AnyPin, OutputType}; +use crate::time::Hertz; +use crate::timer::low_level::OutputCompareMode; use crate::Peripheral; /// Complementary PWM pin wrapper. @@ -22,7 +26,7 @@ pub struct ComplementaryPwmPin<'d, T, C> { macro_rules! complementary_channel_impl { ($new_chx:ident, $channel:ident, $pin_trait:ident) => { - impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwmPin<'d, T, $channel> { + impl<'d, T: AdvancedInstance4Channel> ComplementaryPwmPin<'d, T, $channel> { #[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")] pub fn $new_chx(pin: impl Peripheral

> + 'd, output_type: OutputType) -> Self { into_ref!(pin); @@ -47,11 +51,11 @@ complementary_channel_impl!(new_ch3, Ch3, Channel3ComplementaryPin); complementary_channel_impl!(new_ch4, Ch4, Channel4ComplementaryPin); /// PWM driver with support for standard and complementary outputs. -pub struct ComplementaryPwm<'d, T> { - inner: PeripheralRef<'d, T>, +pub struct ComplementaryPwm<'d, T: AdvancedInstance4Channel> { + inner: Timer<'d, T>, } -impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { +impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { /// Create a new complementary PWM driver. #[allow(clippy::too_many_arguments)] pub fn new( @@ -71,11 +75,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { } fn new_inner(tim: impl Peripheral

+ 'd, freq: Hertz, counting_mode: CountingMode) -> Self { - into_ref!(tim); - - T::enable_and_reset(); - - let mut this = Self { inner: tim }; + let mut this = Self { inner: Timer::new(tim) }; this.inner.set_counting_mode(counting_mode); this.set_frequency(freq); @@ -122,7 +122,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { /// /// This value depends on the configured frequency and the timer's clock rate from RCC. pub fn get_max_duty(&self) -> u16 { - self.inner.get_max_compare_value() + 1 + self.inner.get_max_compare_value() as u16 + 1 } /// Set the duty for a given channel. @@ -130,7 +130,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. pub fn set_duty(&mut self, channel: Channel, duty: u16) { assert!(duty <= self.get_max_duty()); - self.inner.set_compare_value(channel, duty) + self.inner.set_compare_value(channel, duty as _) } /// Set the output polarity for a given channel. @@ -148,7 +148,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { } } -impl<'d, T: ComplementaryCaptureCompare16bitInstance> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> { +impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> { type Channel = Channel; type Time = Hertz; type Duty = u16; @@ -168,16 +168,16 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> embedded_hal_02::Pwm for C } fn get_duty(&self, channel: Self::Channel) -> Self::Duty { - self.inner.get_compare_value(channel) + self.inner.get_compare_value(channel) as u16 } fn get_max_duty(&self) -> Self::Duty { - self.inner.get_max_compare_value() + 1 + self.inner.get_max_compare_value() as u16 + 1 } fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) { assert!(duty <= self.get_max_duty()); - self.inner.set_compare_value(channel, duty) + self.inner.set_compare_value(channel, duty as u32) } fn set_period

(&mut self, period: P) diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs new file mode 100644 index 000000000..a5d942314 --- /dev/null +++ b/embassy-stm32/src/timer/low_level.rs @@ -0,0 +1,638 @@ +//! Low-level timer driver. +//! +//! This is an unopinionated, very low-level driver for all STM32 timers. It allows direct register +//! manipulation with the `regs_*()` methods, and has utility functions that are thin wrappers +//! over the registers. +//! +//! The available functionality depends on the timer type. + +use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; + +use super::*; +use crate::pac::timer::vals; +use crate::time::Hertz; + +/// Input capture mode. +#[derive(Clone, Copy)] +pub enum InputCaptureMode { + /// Rising edge only. + Rising, + /// Falling edge only. + Falling, + /// Both rising or falling edges. + BothEdges, +} + +/// Input TI selection. +#[derive(Clone, Copy)] +pub enum InputTISelection { + /// Normal + Normal, + /// Alternate + Alternate, + /// TRC + TRC, +} + +impl From for stm32_metapac::timer::vals::CcmrInputCcs { + fn from(tisel: InputTISelection) -> Self { + match tisel { + InputTISelection::Normal => stm32_metapac::timer::vals::CcmrInputCcs::TI4, + InputTISelection::Alternate => stm32_metapac::timer::vals::CcmrInputCcs::TI3, + InputTISelection::TRC => stm32_metapac::timer::vals::CcmrInputCcs::TRC, + } + } +} + +/// Timer counting mode. +#[repr(u8)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +pub enum CountingMode { + #[default] + /// The timer counts up to the reload value and then resets back to 0. + EdgeAlignedUp, + /// The timer counts down to 0 and then resets back to the reload value. + EdgeAlignedDown, + /// The timer counts up to the reload value and then counts back to 0. + /// + /// The output compare interrupt flags of channels configured in output are + /// set when the counter is counting down. + CenterAlignedDownInterrupts, + /// The timer counts up to the reload value and then counts back to 0. + /// + /// The output compare interrupt flags of channels configured in output are + /// set when the counter is counting up. + CenterAlignedUpInterrupts, + /// The timer counts up to the reload value and then counts back to 0. + /// + /// The output compare interrupt flags of channels configured in output are + /// set when the counter is counting both up or down. + CenterAlignedBothInterrupts, +} + +impl CountingMode { + /// Return whether this mode is edge-aligned (up or down). + pub fn is_edge_aligned(&self) -> bool { + matches!(self, CountingMode::EdgeAlignedUp | CountingMode::EdgeAlignedDown) + } + + /// Return whether this mode is center-aligned. + pub fn is_center_aligned(&self) -> bool { + matches!( + self, + CountingMode::CenterAlignedDownInterrupts + | CountingMode::CenterAlignedUpInterrupts + | CountingMode::CenterAlignedBothInterrupts + ) + } +} + +impl From for (vals::Cms, vals::Dir) { + fn from(value: CountingMode) -> Self { + match value { + CountingMode::EdgeAlignedUp => (vals::Cms::EDGEALIGNED, vals::Dir::UP), + CountingMode::EdgeAlignedDown => (vals::Cms::EDGEALIGNED, vals::Dir::DOWN), + CountingMode::CenterAlignedDownInterrupts => (vals::Cms::CENTERALIGNED1, vals::Dir::UP), + CountingMode::CenterAlignedUpInterrupts => (vals::Cms::CENTERALIGNED2, vals::Dir::UP), + CountingMode::CenterAlignedBothInterrupts => (vals::Cms::CENTERALIGNED3, vals::Dir::UP), + } + } +} + +impl From<(vals::Cms, vals::Dir)> for CountingMode { + fn from(value: (vals::Cms, vals::Dir)) -> Self { + match value { + (vals::Cms::EDGEALIGNED, vals::Dir::UP) => CountingMode::EdgeAlignedUp, + (vals::Cms::EDGEALIGNED, vals::Dir::DOWN) => CountingMode::EdgeAlignedDown, + (vals::Cms::CENTERALIGNED1, _) => CountingMode::CenterAlignedDownInterrupts, + (vals::Cms::CENTERALIGNED2, _) => CountingMode::CenterAlignedUpInterrupts, + (vals::Cms::CENTERALIGNED3, _) => CountingMode::CenterAlignedBothInterrupts, + } + } +} + +/// Output compare mode. +#[derive(Clone, Copy)] +pub enum OutputCompareMode { + /// The comparison between the output compare register TIMx_CCRx and + /// the counter TIMx_CNT has no effect on the outputs. + /// (this mode is used to generate a timing base). + Frozen, + /// Set channel to active level on match. OCxREF signal is forced high when the + /// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx). + ActiveOnMatch, + /// Set channel to inactive level on match. OCxREF signal is forced low when the + /// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx). + InactiveOnMatch, + /// Toggle - OCxREF toggles when TIMx_CNT=TIMx_CCRx. + Toggle, + /// Force inactive level - OCxREF is forced low. + ForceInactive, + /// Force active level - OCxREF is forced high. + ForceActive, + /// PWM mode 1 - In upcounting, channel is active as long as TIMx_CNTTIMx_CCRx else active (OCxREF=1). + PwmMode1, + /// PWM mode 2 - In upcounting, channel is inactive as long as + /// TIMx_CNTTIMx_CCRx else inactive. + PwmMode2, + // TODO: there's more modes here depending on the chip family. +} + +impl From for stm32_metapac::timer::vals::Ocm { + fn from(mode: OutputCompareMode) -> Self { + match mode { + OutputCompareMode::Frozen => stm32_metapac::timer::vals::Ocm::FROZEN, + OutputCompareMode::ActiveOnMatch => stm32_metapac::timer::vals::Ocm::ACTIVEONMATCH, + OutputCompareMode::InactiveOnMatch => stm32_metapac::timer::vals::Ocm::INACTIVEONMATCH, + OutputCompareMode::Toggle => stm32_metapac::timer::vals::Ocm::TOGGLE, + OutputCompareMode::ForceInactive => stm32_metapac::timer::vals::Ocm::FORCEINACTIVE, + OutputCompareMode::ForceActive => stm32_metapac::timer::vals::Ocm::FORCEACTIVE, + OutputCompareMode::PwmMode1 => stm32_metapac::timer::vals::Ocm::PWMMODE1, + OutputCompareMode::PwmMode2 => stm32_metapac::timer::vals::Ocm::PWMMODE2, + } + } +} + +/// Timer output pin polarity. +#[derive(Clone, Copy)] +pub enum OutputPolarity { + /// Active high (higher duty value makes the pin spend more time high). + ActiveHigh, + /// Active low (higher duty value makes the pin spend more time low). + ActiveLow, +} + +impl From for bool { + fn from(mode: OutputPolarity) -> Self { + match mode { + OutputPolarity::ActiveHigh => false, + OutputPolarity::ActiveLow => true, + } + } +} + +/// Low-level timer driver. +pub struct Timer<'d, T: CoreInstance> { + tim: PeripheralRef<'d, T>, +} + +impl<'d, T: CoreInstance> Drop for Timer<'d, T> { + fn drop(&mut self) { + T::disable() + } +} + +impl<'d, T: CoreInstance> Timer<'d, T> { + /// Create a new timer driver. + pub fn new(tim: impl Peripheral

+ 'd) -> Self { + into_ref!(tim); + + T::enable_and_reset(); + + Self { tim } + } + + /// Get access to the virutal core 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + pub fn regs_core(&self) -> crate::pac::timer::TimCore { + unsafe { crate::pac::timer::TimCore::from_ptr(T::regs()) } + } + + #[cfg(not(stm32l0))] + fn regs_gp32_unchecked(&self) -> crate::pac::timer::TimGp32 { + unsafe { crate::pac::timer::TimGp32::from_ptr(T::regs()) } + } + + /// Start the timer. + pub fn start(&self) { + self.regs_core().cr1().modify(|r| r.set_cen(true)); + } + + /// Stop the timer. + pub fn stop(&self) { + self.regs_core().cr1().modify(|r| r.set_cen(false)); + } + + /// Reset the counter value to 0 + pub fn reset(&self) { + self.regs_core().cnt().write(|r| r.set_cnt(0)); + } + + /// Set the frequency of how many times per second the timer counts up to the max value or down to 0. + /// + /// This means that in the default edge-aligned mode, + /// the timer counter will wrap around at the same frequency as is being set. + /// In center-aligned mode (which not all timers support), the wrap-around frequency is effectively halved + /// because it needs to count up and down. + pub fn set_frequency(&self, frequency: Hertz) { + let f = frequency.0; + assert!(f > 0); + let timer_f = T::frequency().0; + + match T::BITS { + TimerBits::Bits16 => { + let pclk_ticks_per_timer_period = timer_f / f; + let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 16)).try_into()); + let divide_by = pclk_ticks_per_timer_period / (u32::from(psc) + 1); + + // the timer counts `0..=arr`, we want it to count `0..divide_by` + let arr = unwrap!(u16::try_from(divide_by - 1)); + + let regs = self.regs_core(); + regs.psc().write_value(psc); + regs.arr().write(|r| r.set_arr(arr)); + + regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); + regs.egr().write(|r| r.set_ug(true)); + regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); + } + #[cfg(not(stm32l0))] + TimerBits::Bits32 => { + let pclk_ticks_per_timer_period = (timer_f / f) as u64; + let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into()); + let arr: u32 = unwrap!((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into()); + + let regs = self.regs_gp32_unchecked(); + regs.psc().write_value(psc); + regs.arr().write_value(arr); + + regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); + regs.egr().write(|r| r.set_ug(true)); + regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); + } + } + } + + /// Clear update interrupt. + /// + /// Returns whether the update interrupt flag was set. + pub fn clear_update_interrupt(&self) -> bool { + let regs = self.regs_core(); + let sr = regs.sr().read(); + if sr.uif() { + regs.sr().modify(|r| { + r.set_uif(false); + }); + true + } else { + false + } + } + + /// Enable/disable the update interrupt. + pub fn enable_update_interrupt(&self, enable: bool) { + self.regs_core().dier().modify(|r| r.set_uie(enable)); + } + + /// Enable/disable autoreload preload. + pub fn set_autoreload_preload(&self, enable: bool) { + self.regs_core().cr1().modify(|r| r.set_arpe(enable)); + } + + /// Get the timer frequency. + pub fn get_frequency(&self) -> Hertz { + let timer_f = T::frequency(); + + match T::BITS { + TimerBits::Bits16 => { + let regs = self.regs_core(); + let arr = regs.arr().read().arr(); + let psc = regs.psc().read(); + + timer_f / arr / (psc + 1) + } + #[cfg(not(stm32l0))] + TimerBits::Bits32 => { + let regs = self.regs_gp32_unchecked(); + let arr = regs.arr().read(); + let psc = regs.psc().read(); + + timer_f / arr / (psc + 1) + } + } + } +} + +impl<'d, T: BasicNoCr2Instance> Timer<'d, T> { + /// Get access to the Baisc 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + pub fn regs_basic_no_cr2(&self) -> crate::pac::timer::TimBasicNoCr2 { + unsafe { crate::pac::timer::TimBasicNoCr2::from_ptr(T::regs()) } + } + + /// Enable/disable the update dma. + pub fn enable_update_dma(&self, enable: bool) { + self.regs_basic_no_cr2().dier().modify(|r| r.set_ude(enable)); + } + + /// Get the update dma enable/disable state. + pub fn get_update_dma_state(&self) -> bool { + self.regs_basic_no_cr2().dier().read().ude() + } +} + +impl<'d, T: BasicInstance> Timer<'d, T> { + /// Get access to the Baisc 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + pub fn regs_basic(&self) -> crate::pac::timer::TimBasic { + unsafe { crate::pac::timer::TimBasic::from_ptr(T::regs()) } + } +} + +impl<'d, T: GeneralInstance1Channel> Timer<'d, T> { + /// Get access to the general purpose 1 channel 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + pub fn regs_1ch(&self) -> crate::pac::timer::Tim1ch { + unsafe { crate::pac::timer::Tim1ch::from_ptr(T::regs()) } + } + + /// Set clock divider. + pub fn set_clock_division(&self, ckd: vals::Ckd) { + self.regs_1ch().cr1().modify(|r| r.set_ckd(ckd)); + } + + /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC. + pub fn get_max_compare_value(&self) -> u32 { + match T::BITS { + TimerBits::Bits16 => self.regs_1ch().arr().read().arr() as u32, + #[cfg(not(stm32l0))] + TimerBits::Bits32 => self.regs_gp32_unchecked().arr().read(), + } + } +} + +impl<'d, T: GeneralInstance2Channel> Timer<'d, T> { + /// Get access to the general purpose 2 channel 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + pub fn regs_2ch(&self) -> crate::pac::timer::Tim2ch { + unsafe { crate::pac::timer::Tim2ch::from_ptr(T::regs()) } + } +} + +impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { + /// Get access to the general purpose 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + pub fn regs_gp16(&self) -> crate::pac::timer::TimGp16 { + unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) } + } + + /// Enable timer outputs. + pub fn enable_outputs(&self) { + self.tim.enable_outputs() + } + + /// Set counting mode. + pub fn set_counting_mode(&self, mode: CountingMode) { + let (cms, dir) = mode.into(); + + let timer_enabled = self.regs_core().cr1().read().cen(); + // Changing from edge aligned to center aligned (and vice versa) is not allowed while the timer is running. + // Changing direction is discouraged while the timer is running. + assert!(!timer_enabled); + + self.regs_gp16().cr1().modify(|r| r.set_dir(dir)); + self.regs_gp16().cr1().modify(|r| r.set_cms(cms)) + } + + /// Get counting mode. + pub fn get_counting_mode(&self) -> CountingMode { + let cr1 = self.regs_gp16().cr1().read(); + (cr1.cms(), cr1.dir()).into() + } + + /// Set input capture filter. + pub fn set_input_capture_filter(&self, channel: Channel, icf: vals::FilterValue) { + let raw_channel = channel.index(); + self.regs_gp16() + .ccmr_input(raw_channel / 2) + .modify(|r| r.set_icf(raw_channel % 2, icf)); + } + + /// Clear input interrupt. + pub fn clear_input_interrupt(&self, channel: Channel) { + self.regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false)); + } + + /// Enable input interrupt. + pub fn enable_input_interrupt(&self, channel: Channel, enable: bool) { + self.regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable)); + } + + /// Set input capture prescaler. + pub fn set_input_capture_prescaler(&self, channel: Channel, factor: u8) { + let raw_channel = channel.index(); + self.regs_gp16() + .ccmr_input(raw_channel / 2) + .modify(|r| r.set_icpsc(raw_channel % 2, factor)); + } + + /// Set input TI selection. + pub fn set_input_ti_selection(&self, channel: Channel, tisel: InputTISelection) { + let raw_channel = channel.index(); + self.regs_gp16() + .ccmr_input(raw_channel / 2) + .modify(|r| r.set_ccs(raw_channel % 2, tisel.into())); + } + + /// Set input capture mode. + pub fn set_input_capture_mode(&self, channel: Channel, mode: InputCaptureMode) { + self.regs_gp16().ccer().modify(|r| match mode { + InputCaptureMode::Rising => { + r.set_ccnp(channel.index(), false); + r.set_ccp(channel.index(), false); + } + InputCaptureMode::Falling => { + r.set_ccnp(channel.index(), false); + r.set_ccp(channel.index(), true); + } + InputCaptureMode::BothEdges => { + r.set_ccnp(channel.index(), true); + r.set_ccp(channel.index(), true); + } + }); + } + + /// Set output compare mode. + pub fn set_output_compare_mode(&self, channel: Channel, mode: OutputCompareMode) { + let raw_channel: usize = channel.index(); + self.regs_gp16() + .ccmr_output(raw_channel / 2) + .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); + } + + /// Set output polarity. + pub fn set_output_polarity(&self, channel: Channel, polarity: OutputPolarity) { + self.regs_gp16() + .ccer() + .modify(|w| w.set_ccp(channel.index(), polarity.into())); + } + + /// Enable/disable a channel. + pub fn enable_channel(&self, channel: Channel, enable: bool) { + self.regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable)); + } + + /// Get enable/disable state of a channel + pub fn get_channel_enable_state(&self, channel: Channel) -> bool { + self.regs_gp16().ccer().read().cce(channel.index()) + } + + /// Set compare value for a channel. + pub fn set_compare_value(&self, channel: Channel, value: u32) { + match T::BITS { + TimerBits::Bits16 => { + let value = unwrap!(u16::try_from(value)); + self.regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value)); + } + #[cfg(not(stm32l0))] + TimerBits::Bits32 => { + self.regs_gp32_unchecked().ccr(channel.index()).write_value(value); + } + } + } + + /// Get compare value for a channel. + pub fn get_compare_value(&self, channel: Channel) -> u32 { + match T::BITS { + TimerBits::Bits16 => self.regs_gp16().ccr(channel.index()).read().ccr() as u32, + #[cfg(not(stm32l0))] + TimerBits::Bits32 => self.regs_gp32_unchecked().ccr(channel.index()).read(), + } + } + + /// Get capture value for a channel. + pub fn get_capture_value(&self, channel: Channel) -> u32 { + self.get_compare_value(channel) + } + + /// Set output compare preload. + pub fn set_output_compare_preload(&self, channel: Channel, preload: bool) { + let channel_index = channel.index(); + self.regs_gp16() + .ccmr_output(channel_index / 2) + .modify(|w| w.set_ocpe(channel_index % 2, preload)); + } + + /// Get capture compare DMA selection + pub fn get_cc_dma_selection(&self) -> vals::Ccds { + self.regs_gp16().cr2().read().ccds() + } + + /// Set capture compare DMA selection + pub fn set_cc_dma_selection(&self, ccds: vals::Ccds) { + self.regs_gp16().cr2().modify(|w| w.set_ccds(ccds)) + } + + /// Get capture compare DMA enable state + pub fn get_cc_dma_enable_state(&self, channel: Channel) -> bool { + self.regs_gp16().dier().read().ccde(channel.index()) + } + + /// Set capture compare DMA enable state + pub fn set_cc_dma_enable_state(&self, channel: Channel, ccde: bool) { + self.regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde)) + } +} + +#[cfg(not(stm32l0))] +impl<'d, T: GeneralInstance32bit4Channel> Timer<'d, T> { + /// Get access to the general purpose 32bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + pub fn regs_gp32(&self) -> crate::pac::timer::TimGp32 { + unsafe { crate::pac::timer::TimGp32::from_ptr(T::regs()) } + } +} + +#[cfg(not(stm32l0))] +impl<'d, T: AdvancedInstance1Channel> Timer<'d, T> { + /// Get access to the general purpose 1 channel with one complementary 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + pub fn regs_1ch_cmp(&self) -> crate::pac::timer::Tim1chCmp { + unsafe { crate::pac::timer::Tim1chCmp::from_ptr(T::regs()) } + } + + /// Set clock divider for the dead time. + pub fn set_dead_time_clock_division(&self, value: vals::Ckd) { + self.regs_1ch_cmp().cr1().modify(|w| w.set_ckd(value)); + } + + /// Set dead time, as a fraction of the max duty value. + pub fn set_dead_time_value(&self, value: u8) { + self.regs_1ch_cmp().bdtr().modify(|w| w.set_dtg(value)); + } + + /// Set state of MOE-bit in BDTR register to en-/disable output + pub fn set_moe(&self, enable: bool) { + self.regs_1ch_cmp().bdtr().modify(|w| w.set_moe(enable)); + } +} + +#[cfg(not(stm32l0))] +impl<'d, T: AdvancedInstance2Channel> Timer<'d, T> { + /// Get access to the general purpose 2 channel with one complementary 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + pub fn regs_2ch_cmp(&self) -> crate::pac::timer::Tim2chCmp { + unsafe { crate::pac::timer::Tim2chCmp::from_ptr(T::regs()) } + } +} + +#[cfg(not(stm32l0))] +impl<'d, T: AdvancedInstance4Channel> Timer<'d, T> { + /// Get access to the advanced timer registers. + pub fn regs_advanced(&self) -> crate::pac::timer::TimAdv { + unsafe { crate::pac::timer::TimAdv::from_ptr(T::regs()) } + } + + /// Set complementary output polarity. + pub fn set_complementary_output_polarity(&self, channel: Channel, polarity: OutputPolarity) { + self.regs_advanced() + .ccer() + .modify(|w| w.set_ccnp(channel.index(), polarity.into())); + } + + /// Enable/disable a complementary channel. + pub fn enable_complementary_channel(&self, channel: Channel, enable: bool) { + self.regs_advanced() + .ccer() + .modify(|w| w.set_ccne(channel.index(), enable)); + } +} diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index e5e84c255..2ba6b3f11 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -1,490 +1,13 @@ //! Timers, PWM, quadrature decoder. -//! - -//! Timer inheritance -//! - -// sealed: -// -// Core -------------------------> 1CH -------------------------> 1CH_CMP -// | | ^ | -// +--> Basic_NoCr2 --> Basic +--> 2CH --> GP16 --> GP32 | +--> 2CH_CMP --> ADV -// | | | ^ | | ^ ^ -// | | +------|--|--------------|-----------+ | -// | +--------------------+ +--------------|-----------|---------+ -// | | | | -// | +--------------------------------------|-----------+ -// +----------------------------------------------------+ - -//! ```text -//! BasicInstance --> CaptureCompare16bitInstance --+--> ComplementaryCaptureCompare16bitInstance -//! | -//! +--> CaptureCompare32bitInstance -//! ``` -//! -//! Mapping: -//! -//! | trait | timer | -//! | :----------------------------------------: | ------------------------------------------------------------------------------------------------- | -//! | [BasicInstance] | Basic Timer | -//! | [CaptureCompare16bitInstance] | 1-channel Timer, 2-channel Timer, General Purpose 16-bit Timer | -//! | [CaptureCompare32bitInstance] | General Purpose 32-bit Timer | -//! | [ComplementaryCaptureCompare16bitInstance] | 1-channel with one complentary Timer, 2-channel with one complentary Timer, Advance Control Timer | #[cfg(not(stm32l0))] pub mod complementary_pwm; +pub mod low_level; pub mod qei; pub mod simple_pwm; -use stm32_metapac::timer::vals; - use crate::interrupt; use crate::rcc::RccPeripheral; -use crate::time::Hertz; - -/// Low-level timer access. -#[cfg(feature = "unstable-pac")] -pub mod low_level { - pub use super::sealed::*; -} - -pub(crate) mod sealed { - use super::*; - - /// Virtual Core 16-bit timer instance. - pub trait CoreInstance: RccPeripheral { - /// Interrupt for this timer. - type Interrupt: interrupt::typelevel::Interrupt; - - /// Get access to the virutal core 16bit timer registers. - /// - /// Note: This works even if the timer is more capable, because registers - /// for the less capable timers are a subset. This allows writing a driver - /// for a given set of capabilities, and having it transparently work with - /// more capable timers. - fn regs_core() -> crate::pac::timer::TimCore; - - /// Start the timer. - fn start(&self) { - Self::regs_core().cr1().modify(|r| r.set_cen(true)); - } - - /// Stop the timer. - fn stop(&self) { - Self::regs_core().cr1().modify(|r| r.set_cen(false)); - } - - /// Reset the counter value to 0 - fn reset(&self) { - Self::regs_core().cnt().write(|r| r.set_cnt(0)); - } - - /// Set the frequency of how many times per second the timer counts up to the max value or down to 0. - /// - /// This means that in the default edge-aligned mode, - /// the timer counter will wrap around at the same frequency as is being set. - /// In center-aligned mode (which not all timers support), the wrap-around frequency is effectively halved - /// because it needs to count up and down. - fn set_frequency(&self, frequency: Hertz) { - let f = frequency.0; - let timer_f = Self::frequency().0; - assert!(f > 0); - let pclk_ticks_per_timer_period = timer_f / f; - let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 16)).try_into()); - let divide_by = pclk_ticks_per_timer_period / (u32::from(psc) + 1); - - // the timer counts `0..=arr`, we want it to count `0..divide_by` - let arr = unwrap!(u16::try_from(divide_by - 1)); - - let regs = Self::regs_core(); - regs.psc().write_value(psc); - regs.arr().write(|r| r.set_arr(arr)); - - regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); - regs.egr().write(|r| r.set_ug(true)); - regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); - } - - /// Clear update interrupt. - /// - /// Returns whether the update interrupt flag was set. - fn clear_update_interrupt(&self) -> bool { - let regs = Self::regs_core(); - let sr = regs.sr().read(); - if sr.uif() { - regs.sr().modify(|r| { - r.set_uif(false); - }); - true - } else { - false - } - } - - /// Enable/disable the update interrupt. - fn enable_update_interrupt(&self, enable: bool) { - Self::regs_core().dier().modify(|r| r.set_uie(enable)); - } - - /// Enable/disable autoreload preload. - fn set_autoreload_preload(&self, enable: bool) { - Self::regs_core().cr1().modify(|r| r.set_arpe(enable)); - } - - /// Get the timer frequency. - fn get_frequency(&self) -> Hertz { - let timer_f = Self::frequency(); - - let regs = Self::regs_core(); - let arr = regs.arr().read().arr(); - let psc = regs.psc().read(); - - timer_f / arr / (psc + 1) - } - } - - /// Virtual Basic without CR2 16-bit timer instance. - pub trait BasicNoCr2Instance: CoreInstance { - /// Get access to the Baisc 16bit timer registers. - /// - /// Note: This works even if the timer is more capable, because registers - /// for the less capable timers are a subset. This allows writing a driver - /// for a given set of capabilities, and having it transparently work with - /// more capable timers. - fn regs_basic_no_cr2() -> crate::pac::timer::TimBasicNoCr2; - - /// Enable/disable the update dma. - fn enable_update_dma(&self, enable: bool) { - Self::regs_basic_no_cr2().dier().modify(|r| r.set_ude(enable)); - } - - /// Get the update dma enable/disable state. - fn get_update_dma_state(&self) -> bool { - Self::regs_basic_no_cr2().dier().read().ude() - } - } - - /// Basic 16-bit timer instance. - pub trait BasicInstance: BasicNoCr2Instance { - /// Get access to the Baisc 16bit timer registers. - /// - /// Note: This works even if the timer is more capable, because registers - /// for the less capable timers are a subset. This allows writing a driver - /// for a given set of capabilities, and having it transparently work with - /// more capable timers. - fn regs_basic() -> crate::pac::timer::TimBasic; - } - - /// Gneral-purpose 1 channel 16-bit timer instance. - pub trait GeneralPurpose1ChannelInstance: CoreInstance { - /// Get access to the general purpose 1 channel 16bit timer registers. - /// - /// Note: This works even if the timer is more capable, because registers - /// for the less capable timers are a subset. This allows writing a driver - /// for a given set of capabilities, and having it transparently work with - /// more capable timers. - fn regs_1ch() -> crate::pac::timer::Tim1ch; - - /// Set clock divider. - fn set_clock_division(&self, ckd: vals::Ckd) { - Self::regs_1ch().cr1().modify(|r| r.set_ckd(ckd)); - } - - /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC. - fn get_max_compare_value(&self) -> u16 { - Self::regs_1ch().arr().read().arr() - } - } - - /// Gneral-purpose 1 channel 16-bit timer instance. - pub trait GeneralPurpose2ChannelInstance: GeneralPurpose1ChannelInstance { - /// Get access to the general purpose 2 channel 16bit timer registers. - /// - /// Note: This works even if the timer is more capable, because registers - /// for the less capable timers are a subset. This allows writing a driver - /// for a given set of capabilities, and having it transparently work with - /// more capable timers. - fn regs_2ch() -> crate::pac::timer::Tim2ch; - } - - /// Gneral-purpose 16-bit timer instance. - pub trait GeneralPurpose16bitInstance: BasicInstance + GeneralPurpose2ChannelInstance { - /// Get access to the general purpose 16bit timer registers. - /// - /// Note: This works even if the timer is more capable, because registers - /// for the less capable timers are a subset. This allows writing a driver - /// for a given set of capabilities, and having it transparently work with - /// more capable timers. - fn regs_gp16() -> crate::pac::timer::TimGp16; - - /// Set counting mode. - fn set_counting_mode(&self, mode: CountingMode) { - let (cms, dir) = mode.into(); - - let timer_enabled = Self::regs_core().cr1().read().cen(); - // Changing from edge aligned to center aligned (and vice versa) is not allowed while the timer is running. - // Changing direction is discouraged while the timer is running. - assert!(!timer_enabled); - - Self::regs_gp16().cr1().modify(|r| r.set_dir(dir)); - Self::regs_gp16().cr1().modify(|r| r.set_cms(cms)) - } - - /// Get counting mode. - fn get_counting_mode(&self) -> CountingMode { - let cr1 = Self::regs_gp16().cr1().read(); - (cr1.cms(), cr1.dir()).into() - } - - /// Set input capture filter. - fn set_input_capture_filter(&self, channel: Channel, icf: vals::FilterValue) { - let raw_channel = channel.index(); - Self::regs_gp16() - .ccmr_input(raw_channel / 2) - .modify(|r| r.set_icf(raw_channel % 2, icf)); - } - - /// Clear input interrupt. - fn clear_input_interrupt(&self, channel: Channel) { - Self::regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false)); - } - - /// Enable input interrupt. - fn enable_input_interrupt(&self, channel: Channel, enable: bool) { - Self::regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable)); - } - - /// Set input capture prescaler. - fn set_input_capture_prescaler(&self, channel: Channel, factor: u8) { - let raw_channel = channel.index(); - Self::regs_gp16() - .ccmr_input(raw_channel / 2) - .modify(|r| r.set_icpsc(raw_channel % 2, factor)); - } - - /// Set input TI selection. - fn set_input_ti_selection(&self, channel: Channel, tisel: InputTISelection) { - let raw_channel = channel.index(); - Self::regs_gp16() - .ccmr_input(raw_channel / 2) - .modify(|r| r.set_ccs(raw_channel % 2, tisel.into())); - } - - /// Set input capture mode. - fn set_input_capture_mode(&self, channel: Channel, mode: InputCaptureMode) { - Self::regs_gp16().ccer().modify(|r| match mode { - InputCaptureMode::Rising => { - r.set_ccnp(channel.index(), false); - r.set_ccp(channel.index(), false); - } - InputCaptureMode::Falling => { - r.set_ccnp(channel.index(), false); - r.set_ccp(channel.index(), true); - } - InputCaptureMode::BothEdges => { - r.set_ccnp(channel.index(), true); - r.set_ccp(channel.index(), true); - } - }); - } - - /// Set output compare mode. - fn set_output_compare_mode(&self, channel: Channel, mode: OutputCompareMode) { - let raw_channel: usize = channel.index(); - Self::regs_gp16() - .ccmr_output(raw_channel / 2) - .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); - } - - /// Set output polarity. - fn set_output_polarity(&self, channel: Channel, polarity: OutputPolarity) { - Self::regs_gp16() - .ccer() - .modify(|w| w.set_ccp(channel.index(), polarity.into())); - } - - /// Enable/disable a channel. - fn enable_channel(&self, channel: Channel, enable: bool) { - Self::regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable)); - } - - /// Get enable/disable state of a channel - fn get_channel_enable_state(&self, channel: Channel) -> bool { - Self::regs_gp16().ccer().read().cce(channel.index()) - } - - /// Set compare value for a channel. - fn set_compare_value(&self, channel: Channel, value: u16) { - Self::regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value)); - } - - /// Get capture value for a channel. - fn get_capture_value(&self, channel: Channel) -> u16 { - Self::regs_gp16().ccr(channel.index()).read().ccr() - } - - /// Get compare value for a channel. - fn get_compare_value(&self, channel: Channel) -> u16 { - Self::regs_gp16().ccr(channel.index()).read().ccr() - } - - /// Set output compare preload. - fn set_output_compare_preload(&self, channel: Channel, preload: bool) { - let channel_index = channel.index(); - Self::regs_gp16() - .ccmr_output(channel_index / 2) - .modify(|w| w.set_ocpe(channel_index % 2, preload)); - } - - /// Get capture compare DMA selection - fn get_cc_dma_selection(&self) -> super::vals::Ccds { - Self::regs_gp16().cr2().read().ccds() - } - - /// Set capture compare DMA selection - fn set_cc_dma_selection(&self, ccds: super::vals::Ccds) { - Self::regs_gp16().cr2().modify(|w| w.set_ccds(ccds)) - } - - /// Get capture compare DMA enable state - fn get_cc_dma_enable_state(&self, channel: Channel) -> bool { - Self::regs_gp16().dier().read().ccde(channel.index()) - } - - /// Set capture compare DMA enable state - fn set_cc_dma_enable_state(&self, channel: Channel, ccde: bool) { - Self::regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde)) - } - } - - #[cfg(not(stm32l0))] - /// Gneral-purpose 32-bit timer instance. - pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance { - /// Get access to the general purpose 32bit timer registers. - /// - /// Note: This works even if the timer is more capable, because registers - /// for the less capable timers are a subset. This allows writing a driver - /// for a given set of capabilities, and having it transparently work with - /// more capable timers. - fn regs_gp32() -> crate::pac::timer::TimGp32; - - /// Set timer frequency. - fn set_frequency(&self, frequency: Hertz) { - let f = frequency.0; - assert!(f > 0); - let timer_f = Self::frequency().0; - let pclk_ticks_per_timer_period = (timer_f / f) as u64; - let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into()); - let arr: u32 = unwrap!((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into()); - - let regs = Self::regs_gp32(); - regs.psc().write_value(psc); - regs.arr().write_value(arr); - - regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); - regs.egr().write(|r| r.set_ug(true)); - regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); - } - - /// Get timer frequency. - fn get_frequency(&self) -> Hertz { - let timer_f = Self::frequency(); - - let regs = Self::regs_gp32(); - let arr = regs.arr().read(); - let psc = regs.psc().read(); - - timer_f / arr / (psc + 1) - } - - /// Set comapre value for a channel. - fn set_compare_value(&self, channel: Channel, value: u32) { - Self::regs_gp32().ccr(channel.index()).write_value(value); - } - - /// Get capture value for a channel. - fn get_capture_value(&self, channel: Channel) -> u32 { - Self::regs_gp32().ccr(channel.index()).read() - } - - /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC. - fn get_max_compare_value(&self) -> u32 { - Self::regs_gp32().arr().read() - } - - /// Get compare value for a channel. - fn get_compare_value(&self, channel: Channel) -> u32 { - Self::regs_gp32().ccr(channel.index()).read() - } - } - - #[cfg(not(stm32l0))] - /// Gneral-purpose 1 channel with one complementary 16-bit timer instance. - pub trait GeneralPurpose1ChannelComplementaryInstance: BasicNoCr2Instance + GeneralPurpose1ChannelInstance { - /// Get access to the general purpose 1 channel with one complementary 16bit timer registers. - /// - /// Note: This works even if the timer is more capable, because registers - /// for the less capable timers are a subset. This allows writing a driver - /// for a given set of capabilities, and having it transparently work with - /// more capable timers. - fn regs_1ch_cmp() -> crate::pac::timer::Tim1chCmp; - - /// Set clock divider for the dead time. - fn set_dead_time_clock_division(&self, value: vals::Ckd) { - Self::regs_1ch_cmp().cr1().modify(|w| w.set_ckd(value)); - } - - /// Set dead time, as a fraction of the max duty value. - fn set_dead_time_value(&self, value: u8) { - Self::regs_1ch_cmp().bdtr().modify(|w| w.set_dtg(value)); - } - - /// Set state of MOE-bit in BDTR register to en-/disable output - fn set_moe(&self, enable: bool) { - Self::regs_1ch_cmp().bdtr().modify(|w| w.set_moe(enable)); - } - } - - #[cfg(not(stm32l0))] - /// Gneral-purpose 2 channel with one complementary 16-bit timer instance. - pub trait GeneralPurpose2ChannelComplementaryInstance: - BasicInstance + GeneralPurpose2ChannelInstance + GeneralPurpose1ChannelComplementaryInstance - { - /// Get access to the general purpose 2 channel with one complementary 16bit timer registers. - /// - /// Note: This works even if the timer is more capable, because registers - /// for the less capable timers are a subset. This allows writing a driver - /// for a given set of capabilities, and having it transparently work with - /// more capable timers. - fn regs_2ch_cmp() -> crate::pac::timer::Tim2chCmp; - } - - #[cfg(not(stm32l0))] - /// Advanced control timer instance. - pub trait AdvancedControlInstance: - GeneralPurpose2ChannelComplementaryInstance + GeneralPurpose16bitInstance - { - /// Capture compare interrupt for this timer. - type CaptureCompareInterrupt: interrupt::typelevel::Interrupt; - - /// Get access to the advanced timer registers. - fn regs_advanced() -> crate::pac::timer::TimAdv; - - /// Set complementary output polarity. - fn set_complementary_output_polarity(&self, channel: Channel, polarity: OutputPolarity) { - Self::regs_advanced() - .ccer() - .modify(|w| w.set_ccnp(channel.index(), polarity.into())); - } - - /// Enable/disable a complementary channel. - fn enable_complementary_channel(&self, channel: Channel, enable: bool) { - Self::regs_advanced() - .ccer() - .modify(|w| w.set_ccne(channel.index(), enable)); - } - } -} /// Timer channel. #[derive(Clone, Copy)] @@ -511,181 +34,44 @@ impl Channel { } } -/// Input capture mode. -#[derive(Clone, Copy)] -pub enum InputCaptureMode { - /// Rising edge only. - Rising, - /// Falling edge only. - Falling, - /// Both rising or falling edges. - BothEdges, +/// Amount of bits of a timer. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum TimerBits { + /// 16 bits. + Bits16, + /// 32 bits. + #[cfg(not(stm32l0))] + Bits32, } -/// Input TI selection. -#[derive(Clone, Copy)] -pub enum InputTISelection { - /// Normal - Normal, - /// Alternate - Alternate, - /// TRC - TRC, -} +/// Core timer instance. +pub trait CoreInstance: RccPeripheral + 'static { + /// Interrupt for this timer. + type Interrupt: interrupt::typelevel::Interrupt; -impl From for stm32_metapac::timer::vals::CcmrInputCcs { - fn from(tisel: InputTISelection) -> Self { - match tisel { - InputTISelection::Normal => stm32_metapac::timer::vals::CcmrInputCcs::TI4, - InputTISelection::Alternate => stm32_metapac::timer::vals::CcmrInputCcs::TI3, - InputTISelection::TRC => stm32_metapac::timer::vals::CcmrInputCcs::TRC, - } - } -} + /// Amount of bits this timer has. + const BITS: TimerBits; -/// Timer counting mode. -#[repr(u8)] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] -pub enum CountingMode { - #[default] - /// The timer counts up to the reload value and then resets back to 0. - EdgeAlignedUp, - /// The timer counts down to 0 and then resets back to the reload value. - EdgeAlignedDown, - /// The timer counts up to the reload value and then counts back to 0. + /// Registers for this timer. /// - /// The output compare interrupt flags of channels configured in output are - /// set when the counter is counting down. - CenterAlignedDownInterrupts, - /// The timer counts up to the reload value and then counts back to 0. - /// - /// The output compare interrupt flags of channels configured in output are - /// set when the counter is counting up. - CenterAlignedUpInterrupts, - /// The timer counts up to the reload value and then counts back to 0. - /// - /// The output compare interrupt flags of channels configured in output are - /// set when the counter is counting both up or down. - CenterAlignedBothInterrupts, + /// This is a raw pointer to the register block. The actual register block layout varies depending on the timer type. + fn regs() -> *mut (); } +/// Cut-down basic timer instance. +pub trait BasicNoCr2Instance: CoreInstance {} +/// Basic timer instance. +pub trait BasicInstance: BasicNoCr2Instance {} -impl CountingMode { - /// Return whether this mode is edge-aligned (up or down). - pub fn is_edge_aligned(&self) -> bool { - matches!(self, CountingMode::EdgeAlignedUp | CountingMode::EdgeAlignedDown) - } +/// General-purpose 16-bit timer with 1 channel instance. +pub trait GeneralInstance1Channel: CoreInstance {} - /// Return whether this mode is center-aligned. - pub fn is_center_aligned(&self) -> bool { - matches!( - self, - CountingMode::CenterAlignedDownInterrupts - | CountingMode::CenterAlignedUpInterrupts - | CountingMode::CenterAlignedBothInterrupts - ) - } -} +/// General-purpose 16-bit timer with 2 channels instance. +pub trait GeneralInstance2Channel: GeneralInstance1Channel {} -impl From for (vals::Cms, vals::Dir) { - fn from(value: CountingMode) -> Self { - match value { - CountingMode::EdgeAlignedUp => (vals::Cms::EDGEALIGNED, vals::Dir::UP), - CountingMode::EdgeAlignedDown => (vals::Cms::EDGEALIGNED, vals::Dir::DOWN), - CountingMode::CenterAlignedDownInterrupts => (vals::Cms::CENTERALIGNED1, vals::Dir::UP), - CountingMode::CenterAlignedUpInterrupts => (vals::Cms::CENTERALIGNED2, vals::Dir::UP), - CountingMode::CenterAlignedBothInterrupts => (vals::Cms::CENTERALIGNED3, vals::Dir::UP), - } - } -} - -impl From<(vals::Cms, vals::Dir)> for CountingMode { - fn from(value: (vals::Cms, vals::Dir)) -> Self { - match value { - (vals::Cms::EDGEALIGNED, vals::Dir::UP) => CountingMode::EdgeAlignedUp, - (vals::Cms::EDGEALIGNED, vals::Dir::DOWN) => CountingMode::EdgeAlignedDown, - (vals::Cms::CENTERALIGNED1, _) => CountingMode::CenterAlignedDownInterrupts, - (vals::Cms::CENTERALIGNED2, _) => CountingMode::CenterAlignedUpInterrupts, - (vals::Cms::CENTERALIGNED3, _) => CountingMode::CenterAlignedBothInterrupts, - } - } -} - -/// Output compare mode. -#[derive(Clone, Copy)] -pub enum OutputCompareMode { - /// The comparison between the output compare register TIMx_CCRx and - /// the counter TIMx_CNT has no effect on the outputs. - /// (this mode is used to generate a timing base). - Frozen, - /// Set channel to active level on match. OCxREF signal is forced high when the - /// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx). - ActiveOnMatch, - /// Set channel to inactive level on match. OCxREF signal is forced low when the - /// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx). - InactiveOnMatch, - /// Toggle - OCxREF toggles when TIMx_CNT=TIMx_CCRx. - Toggle, - /// Force inactive level - OCxREF is forced low. - ForceInactive, - /// Force active level - OCxREF is forced high. - ForceActive, - /// PWM mode 1 - In upcounting, channel is active as long as TIMx_CNTTIMx_CCRx else active (OCxREF=1). - PwmMode1, - /// PWM mode 2 - In upcounting, channel is inactive as long as - /// TIMx_CNTTIMx_CCRx else inactive. - PwmMode2, - // TODO: there's more modes here depending on the chip family. -} - -impl From for stm32_metapac::timer::vals::Ocm { - fn from(mode: OutputCompareMode) -> Self { - match mode { - OutputCompareMode::Frozen => stm32_metapac::timer::vals::Ocm::FROZEN, - OutputCompareMode::ActiveOnMatch => stm32_metapac::timer::vals::Ocm::ACTIVEONMATCH, - OutputCompareMode::InactiveOnMatch => stm32_metapac::timer::vals::Ocm::INACTIVEONMATCH, - OutputCompareMode::Toggle => stm32_metapac::timer::vals::Ocm::TOGGLE, - OutputCompareMode::ForceInactive => stm32_metapac::timer::vals::Ocm::FORCEINACTIVE, - OutputCompareMode::ForceActive => stm32_metapac::timer::vals::Ocm::FORCEACTIVE, - OutputCompareMode::PwmMode1 => stm32_metapac::timer::vals::Ocm::PWMMODE1, - OutputCompareMode::PwmMode2 => stm32_metapac::timer::vals::Ocm::PWMMODE2, - } - } -} - -/// Timer output pin polarity. -#[derive(Clone, Copy)] -pub enum OutputPolarity { - /// Active high (higher duty value makes the pin spend more time high). - ActiveHigh, - /// Active low (higher duty value makes the pin spend more time low). - ActiveLow, -} - -impl From for bool { - fn from(mode: OutputPolarity) -> Self { - match mode { - OutputPolarity::ActiveHigh => false, - OutputPolarity::ActiveLow => true, - } - } -} - -/// Basic 16-bit timer instance. -pub trait BasicInstance: sealed::BasicInstance + sealed::BasicNoCr2Instance + sealed::CoreInstance + 'static {} - -// It's just a General-purpose 16-bit timer instance. -/// Capture Compare timer instance. -pub trait CaptureCompare16bitInstance: - BasicInstance - + sealed::GeneralPurpose2ChannelInstance - + sealed::GeneralPurpose1ChannelInstance - + sealed::GeneralPurpose16bitInstance - + 'static -{ - // SimplePwm<'d, T> is implemented for T: CaptureCompare16bitInstance +/// General-purpose 16-bit timer with 4 channels instance. +pub trait GeneralInstance4Channel: BasicInstance + GeneralInstance2Channel { + // SimplePwm<'d, T> is implemented for T: GeneralInstance4Channel // Advanced timers implement this trait, but the output needs to be // enabled explicitly. // To support general-purpose and advanced timers, this function is added @@ -694,296 +80,149 @@ pub trait CaptureCompare16bitInstance: fn enable_outputs(&self) {} } -#[cfg(not(stm32l0))] -// It's just a General-purpose 32-bit timer instance. -/// Capture Compare 32-bit timer instance. -pub trait CaptureCompare32bitInstance: - CaptureCompare16bitInstance + sealed::GeneralPurpose32bitInstance + 'static -{ +/// General-purpose 32-bit timer with 4 channels instance. +pub trait GeneralInstance32bit4Channel: GeneralInstance4Channel {} + +/// Advanced 16-bit timer with 1 channel instance. +pub trait AdvancedInstance1Channel: BasicNoCr2Instance + GeneralInstance1Channel { + /// Capture compare interrupt for this timer. + type CaptureCompareInterrupt: interrupt::typelevel::Interrupt; } +/// Advanced 16-bit timer with 2 channels instance. -#[cfg(not(stm32l0))] -// It's just a Advanced Control timer instance. -/// Complementary Capture Compare 32-bit timer instance. -pub trait ComplementaryCaptureCompare16bitInstance: - CaptureCompare16bitInstance - + sealed::GeneralPurpose1ChannelComplementaryInstance - + sealed::GeneralPurpose2ChannelComplementaryInstance - + sealed::AdvancedControlInstance - + 'static -{ -} +pub trait AdvancedInstance2Channel: BasicInstance + GeneralInstance2Channel + AdvancedInstance1Channel {} -pin_trait!(Channel1Pin, CaptureCompare16bitInstance); -pin_trait!(Channel2Pin, CaptureCompare16bitInstance); -pin_trait!(Channel3Pin, CaptureCompare16bitInstance); -pin_trait!(Channel4Pin, CaptureCompare16bitInstance); -pin_trait!(ExternalTriggerPin, CaptureCompare16bitInstance); +/// Advanced 16-bit timer with 4 channels instance. +pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {} -cfg_if::cfg_if! { - if #[cfg(not(stm32l0))] { - pin_trait!(Channel1ComplementaryPin, ComplementaryCaptureCompare16bitInstance); - pin_trait!(Channel2ComplementaryPin, ComplementaryCaptureCompare16bitInstance); - pin_trait!(Channel3ComplementaryPin, ComplementaryCaptureCompare16bitInstance); - pin_trait!(Channel4ComplementaryPin, ComplementaryCaptureCompare16bitInstance); +pin_trait!(Channel1Pin, GeneralInstance4Channel); +pin_trait!(Channel2Pin, GeneralInstance4Channel); +pin_trait!(Channel3Pin, GeneralInstance4Channel); +pin_trait!(Channel4Pin, GeneralInstance4Channel); +pin_trait!(ExternalTriggerPin, GeneralInstance4Channel); - pin_trait!(BreakInputPin, ComplementaryCaptureCompare16bitInstance); - pin_trait!(BreakInput2Pin, ComplementaryCaptureCompare16bitInstance); +pin_trait!(Channel1ComplementaryPin, AdvancedInstance4Channel); +pin_trait!(Channel2ComplementaryPin, AdvancedInstance4Channel); +pin_trait!(Channel3ComplementaryPin, AdvancedInstance4Channel); +pin_trait!(Channel4ComplementaryPin, AdvancedInstance4Channel); - pin_trait!(BreakInputComparator1Pin, ComplementaryCaptureCompare16bitInstance); - pin_trait!(BreakInputComparator2Pin, ComplementaryCaptureCompare16bitInstance); +pin_trait!(BreakInputPin, AdvancedInstance4Channel); +pin_trait!(BreakInput2Pin, AdvancedInstance4Channel); - pin_trait!(BreakInput2Comparator1Pin, ComplementaryCaptureCompare16bitInstance); - pin_trait!(BreakInput2Comparator2Pin, ComplementaryCaptureCompare16bitInstance); - } -} +pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel); +pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel); + +pin_trait!(BreakInput2Comparator1Pin, AdvancedInstance4Channel); +pin_trait!(BreakInput2Comparator2Pin, AdvancedInstance4Channel); + +// Update Event trigger DMA for every timer +dma_trait!(UpDma, BasicInstance); + +dma_trait!(Ch1Dma, GeneralInstance4Channel); +dma_trait!(Ch2Dma, GeneralInstance4Channel); +dma_trait!(Ch3Dma, GeneralInstance4Channel); +dma_trait!(Ch4Dma, GeneralInstance4Channel); #[allow(unused)] macro_rules! impl_core_timer { - ($inst:ident, $irq:ident) => { - impl sealed::CoreInstance for crate::peripherals::$inst { - type Interrupt = crate::interrupt::typelevel::$irq; + ($inst:ident, $bits:expr) => { + impl CoreInstance for crate::peripherals::$inst { + type Interrupt = crate::_generated::peripheral_interrupts::$inst::UP; - fn regs_core() -> crate::pac::timer::TimCore { - unsafe { crate::pac::timer::TimCore::from_ptr(crate::pac::$inst.as_ptr()) } - } - } - }; -} + const BITS: TimerBits = $bits; -#[allow(unused)] -macro_rules! impl_basic_no_cr2_timer { - ($inst:ident) => { - impl sealed::BasicNoCr2Instance for crate::peripherals::$inst { - fn regs_basic_no_cr2() -> crate::pac::timer::TimBasicNoCr2 { - unsafe { crate::pac::timer::TimBasicNoCr2::from_ptr(crate::pac::$inst.as_ptr()) } - } - } - }; -} - -#[allow(unused)] -macro_rules! impl_basic_timer { - ($inst:ident) => { - impl sealed::BasicInstance for crate::peripherals::$inst { - fn regs_basic() -> crate::pac::timer::TimBasic { - unsafe { crate::pac::timer::TimBasic::from_ptr(crate::pac::$inst.as_ptr()) } - } - } - }; -} - -#[allow(unused)] -macro_rules! impl_1ch_timer { - ($inst:ident) => { - impl sealed::GeneralPurpose1ChannelInstance for crate::peripherals::$inst { - fn regs_1ch() -> crate::pac::timer::Tim1ch { - unsafe { crate::pac::timer::Tim1ch::from_ptr(crate::pac::$inst.as_ptr()) } - } - } - }; -} - -#[allow(unused)] -macro_rules! impl_2ch_timer { - ($inst:ident) => { - impl sealed::GeneralPurpose2ChannelInstance for crate::peripherals::$inst { - fn regs_2ch() -> crate::pac::timer::Tim2ch { - unsafe { crate::pac::timer::Tim2ch::from_ptr(crate::pac::$inst.as_ptr()) } - } - } - }; -} - -#[allow(unused)] -macro_rules! impl_gp16_timer { - ($inst:ident) => { - impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { - fn regs_gp16() -> crate::pac::timer::TimGp16 { - unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } - } - } - }; -} - -#[allow(unused)] -macro_rules! impl_gp32_timer { - ($inst:ident) => { - impl sealed::GeneralPurpose32bitInstance for crate::peripherals::$inst { - fn regs_gp32() -> crate::pac::timer::TimGp32 { - crate::pac::$inst - } - } - }; -} - -#[allow(unused)] -macro_rules! impl_1ch_cmp_timer { - ($inst:ident) => { - impl sealed::GeneralPurpose1ChannelComplementaryInstance for crate::peripherals::$inst { - fn regs_1ch_cmp() -> crate::pac::timer::Tim1chCmp { - unsafe { crate::pac::timer::Tim1chCmp::from_ptr(crate::pac::$inst.as_ptr()) } - } - } - }; -} - -#[allow(unused)] -macro_rules! impl_2ch_cmp_timer { - ($inst:ident) => { - impl sealed::GeneralPurpose2ChannelComplementaryInstance for crate::peripherals::$inst { - fn regs_2ch_cmp() -> crate::pac::timer::Tim2chCmp { - unsafe { crate::pac::timer::Tim2chCmp::from_ptr(crate::pac::$inst.as_ptr()) } - } - } - }; -} - -#[allow(unused)] -macro_rules! impl_adv_timer { - ($inst:ident, $irq:ident) => { - impl sealed::AdvancedControlInstance for crate::peripherals::$inst { - type CaptureCompareInterrupt = crate::interrupt::typelevel::$irq; - - fn regs_advanced() -> crate::pac::timer::TimAdv { - unsafe { crate::pac::timer::TimAdv::from_ptr(crate::pac::$inst.as_ptr()) } + fn regs() -> *mut () { + crate::pac::$inst.as_ptr() } } }; } foreach_interrupt! { - ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => { - impl_core_timer!($inst, $irq); - impl_basic_no_cr2_timer!($inst); - impl_basic_timer!($inst); + impl_core_timer!($inst, TimerBits::Bits16); + impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} }; ($inst:ident, timer, TIM_1CH, UP, $irq:ident) => { - impl_core_timer!($inst, $irq); - impl_basic_no_cr2_timer!($inst); - impl_basic_timer!($inst); - impl_1ch_timer!($inst); - impl_2ch_timer!($inst); - impl_gp16_timer!($inst); + impl_core_timer!($inst, TimerBits::Bits16); + impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} - impl CaptureCompare16bitInstance for crate::peripherals::$inst {} + impl GeneralInstance1Channel for crate::peripherals::$inst {} + impl GeneralInstance2Channel for crate::peripherals::$inst {} + impl GeneralInstance4Channel for crate::peripherals::$inst {} }; - ($inst:ident, timer, TIM_2CH, UP, $irq:ident) => { - impl_core_timer!($inst, $irq); - impl_basic_no_cr2_timer!($inst); - impl_basic_timer!($inst); - impl_1ch_timer!($inst); - impl_2ch_timer!($inst); - impl_gp16_timer!($inst); + impl_core_timer!($inst, TimerBits::Bits16); + impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} - impl CaptureCompare16bitInstance for crate::peripherals::$inst {} + impl GeneralInstance1Channel for crate::peripherals::$inst {} + impl GeneralInstance2Channel for crate::peripherals::$inst {} + impl GeneralInstance4Channel for crate::peripherals::$inst {} }; ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => { - impl_core_timer!($inst, $irq); - impl_basic_no_cr2_timer!($inst); - impl_basic_timer!($inst); - impl_1ch_timer!($inst); - impl_2ch_timer!($inst); - impl_gp16_timer!($inst); + impl_core_timer!($inst, TimerBits::Bits16); + impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} - impl CaptureCompare16bitInstance for crate::peripherals::$inst {} + impl GeneralInstance1Channel for crate::peripherals::$inst {} + impl GeneralInstance2Channel for crate::peripherals::$inst {} + impl GeneralInstance4Channel for crate::peripherals::$inst {} }; ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => { - impl_core_timer!($inst, $irq); - impl_basic_no_cr2_timer!($inst); - impl_basic_timer!($inst); - impl_1ch_timer!($inst); - impl_2ch_timer!($inst); - impl_gp16_timer!($inst); - impl_gp32_timer!($inst); + impl_core_timer!($inst, TimerBits::Bits32); + impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} - impl CaptureCompare16bitInstance for crate::peripherals::$inst {} - impl CaptureCompare32bitInstance for crate::peripherals::$inst {} + impl GeneralInstance1Channel for crate::peripherals::$inst {} + impl GeneralInstance2Channel for crate::peripherals::$inst {} + impl GeneralInstance4Channel for crate::peripherals::$inst {} + impl GeneralInstance32bit4Channel for crate::peripherals::$inst {} }; ($inst:ident, timer, TIM_1CH_CMP, UP, $irq:ident) => { - impl_core_timer!($inst, $irq); - impl_basic_no_cr2_timer!($inst); - impl_basic_timer!($inst); - impl_1ch_timer!($inst); - impl_2ch_timer!($inst); - impl_gp16_timer!($inst); - impl_1ch_cmp_timer!($inst); - impl_2ch_cmp_timer!($inst); + impl_core_timer!($inst, TimerBits::Bits16); + impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} - impl CaptureCompare16bitInstance for crate::peripherals::$inst { - /// Enable timer outputs. - fn enable_outputs(&self) { - use crate::timer::sealed::GeneralPurpose1ChannelComplementaryInstance; - self.set_moe(true); - } - } - impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} + impl GeneralInstance1Channel for crate::peripherals::$inst {} + impl GeneralInstance2Channel for crate::peripherals::$inst {} + impl GeneralInstance4Channel for crate::peripherals::$inst { fn enable_outputs(&self) { set_moe::() }} + impl AdvancedInstance1Channel for crate::peripherals::$inst { type CaptureCompareInterrupt = crate::_generated::peripheral_interrupts::$inst::CC; } + impl AdvancedInstance2Channel for crate::peripherals::$inst {} + impl AdvancedInstance4Channel for crate::peripherals::$inst {} }; - ($inst:ident, timer, TIM_1CH_CMP, CC, $irq:ident) => { - impl_adv_timer!($inst, $irq); - }; - ($inst:ident, timer, TIM_2CH_CMP, UP, $irq:ident) => { - impl_core_timer!($inst, $irq); - impl_basic_no_cr2_timer!($inst); - impl_basic_timer!($inst); - impl_1ch_timer!($inst); - impl_2ch_timer!($inst); - impl_gp16_timer!($inst); - impl_1ch_cmp_timer!($inst); - impl_2ch_cmp_timer!($inst); + impl_core_timer!($inst, TimerBits::Bits16); + impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} - impl CaptureCompare16bitInstance for crate::peripherals::$inst { - /// Enable timer outputs. - fn enable_outputs(&self) { - use crate::timer::sealed::GeneralPurpose1ChannelComplementaryInstance; - self.set_moe(true); - } - } - impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} + impl GeneralInstance1Channel for crate::peripherals::$inst {} + impl GeneralInstance2Channel for crate::peripherals::$inst {} + impl GeneralInstance4Channel for crate::peripherals::$inst { fn enable_outputs(&self) { set_moe::() }} + impl AdvancedInstance1Channel for crate::peripherals::$inst { type CaptureCompareInterrupt = crate::_generated::peripheral_interrupts::$inst::CC; } + impl AdvancedInstance2Channel for crate::peripherals::$inst {} + impl AdvancedInstance4Channel for crate::peripherals::$inst {} }; - ($inst:ident, timer, TIM_2CH_CMP, CC, $irq:ident) => { - impl_adv_timer!($inst, $irq); - }; - ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { - impl_core_timer!($inst, $irq); - impl_basic_no_cr2_timer!($inst); - impl_basic_timer!($inst); - impl_1ch_timer!($inst); - impl_2ch_timer!($inst); - impl_gp16_timer!($inst); - impl_1ch_cmp_timer!($inst); - impl_2ch_cmp_timer!($inst); + impl_core_timer!($inst, TimerBits::Bits16); + impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} - impl CaptureCompare16bitInstance for crate::peripherals::$inst { - /// Enable timer outputs. - fn enable_outputs(&self) { - use crate::timer::sealed::GeneralPurpose1ChannelComplementaryInstance; - self.set_moe(true); - } - } - impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} - }; - ($inst:ident, timer, TIM_ADV, CC, $irq:ident) => { - impl_adv_timer!($inst, $irq); + impl GeneralInstance1Channel for crate::peripherals::$inst {} + impl GeneralInstance2Channel for crate::peripherals::$inst {} + impl GeneralInstance4Channel for crate::peripherals::$inst { fn enable_outputs(&self) { set_moe::() }} + impl AdvancedInstance1Channel for crate::peripherals::$inst { type CaptureCompareInterrupt = crate::_generated::peripheral_interrupts::$inst::CC; } + impl AdvancedInstance2Channel for crate::peripherals::$inst {} + impl AdvancedInstance4Channel for crate::peripherals::$inst {} }; } -// Update Event trigger DMA for every timer -dma_trait!(UpDma, BasicInstance); - -dma_trait!(Ch1Dma, CaptureCompare16bitInstance); -dma_trait!(Ch2Dma, CaptureCompare16bitInstance); -dma_trait!(Ch3Dma, CaptureCompare16bitInstance); -dma_trait!(Ch4Dma, CaptureCompare16bitInstance); +#[cfg(not(stm32l0))] +#[allow(unused)] +fn set_moe() { + unsafe { crate::pac::timer::Tim1chCmp::from_ptr(T::regs()) } + .bdtr() + .modify(|w| w.set_moe(true)); +} diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs index 59efb72ba..ab9879be6 100644 --- a/embassy-stm32/src/timer/qei.rs +++ b/embassy-stm32/src/timer/qei.rs @@ -3,10 +3,11 @@ use core::marker::PhantomData; use embassy_hal_internal::{into_ref, PeripheralRef}; +use stm32_metapac::timer::vals; -use super::*; -use crate::gpio::sealed::AFType; -use crate::gpio::AnyPin; +use super::low_level::Timer; +use super::{Channel1Pin, Channel2Pin, GeneralInstance4Channel}; +use crate::gpio::{AFType, AnyPin}; use crate::Peripheral; /// Counting direction @@ -30,7 +31,7 @@ pub struct QeiPin<'d, T, Channel> { macro_rules! channel_impl { ($new_chx:ident, $channel:ident, $pin_trait:ident) => { - impl<'d, T: CaptureCompare16bitInstance> QeiPin<'d, T, $channel> { + impl<'d, T: GeneralInstance4Channel> QeiPin<'d, T, $channel> { #[doc = concat!("Create a new ", stringify!($channel), " QEI pin instance.")] pub fn $new_chx(pin: impl Peripheral

> + 'd) -> Self { into_ref!(pin); @@ -53,29 +54,28 @@ channel_impl!(new_ch1, Ch1, Channel1Pin); channel_impl!(new_ch2, Ch2, Channel2Pin); /// Quadrature decoder driver. -pub struct Qei<'d, T> { - _inner: PeripheralRef<'d, T>, +pub struct Qei<'d, T: GeneralInstance4Channel> { + inner: Timer<'d, T>, } -impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> { +impl<'d, T: GeneralInstance4Channel> Qei<'d, T> { /// Create a new quadrature decoder driver. pub fn new(tim: impl Peripheral

+ 'd, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self { Self::new_inner(tim) } fn new_inner(tim: impl Peripheral

+ 'd) -> Self { - into_ref!(tim); - - T::enable_and_reset(); + let inner = Timer::new(tim); + let r = inner.regs_gp16(); // Configure TxC1 and TxC2 as captures - T::regs_gp16().ccmr_input(0).modify(|w| { + r.ccmr_input(0).modify(|w| { w.set_ccs(0, vals::CcmrInputCcs::TI4); w.set_ccs(1, vals::CcmrInputCcs::TI4); }); // enable and configure to capture on rising edge - T::regs_gp16().ccer().modify(|w| { + r.ccer().modify(|w| { w.set_cce(0, true); w.set_cce(1, true); @@ -83,19 +83,19 @@ impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> { w.set_ccp(1, false); }); - T::regs_gp16().smcr().modify(|w| { + r.smcr().modify(|w| { w.set_sms(vals::Sms::ENCODER_MODE_3); }); - T::regs_gp16().arr().modify(|w| w.set_arr(u16::MAX)); - T::regs_gp16().cr1().modify(|w| w.set_cen(true)); + r.arr().modify(|w| w.set_arr(u16::MAX)); + r.cr1().modify(|w| w.set_cen(true)); - Self { _inner: tim } + Self { inner } } /// Get direction. pub fn read_direction(&self) -> Direction { - match T::regs_gp16().cr1().read().dir() { + match self.inner.regs_gp16().cr1().read().dir() { vals::Dir::DOWN => Direction::Downcounting, vals::Dir::UP => Direction::Upcounting, } @@ -103,6 +103,6 @@ impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> { /// Get count. pub fn count(&self) -> u16 { - T::regs_gp16().cnt().read().cnt() + self.inner.regs_gp16().cnt().read().cnt() } } diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index 4669fc6cc..b54e9a0d6 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -4,10 +4,10 @@ use core::marker::PhantomData; use embassy_hal_internal::{into_ref, PeripheralRef}; -use super::*; -#[allow(unused_imports)] -use crate::gpio::sealed::{AFType, Pin}; +use super::low_level::{CountingMode, OutputCompareMode, OutputPolarity, Timer}; +use super::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance4Channel}; use crate::gpio::{AnyPin, OutputType}; +use crate::time::Hertz; use crate::Peripheral; /// Channel 1 marker type. @@ -29,7 +29,7 @@ pub struct PwmPin<'d, T, C> { macro_rules! channel_impl { ($new_chx:ident, $channel:ident, $pin_trait:ident) => { - impl<'d, T: CaptureCompare16bitInstance> PwmPin<'d, T, $channel> { + impl<'d, T: GeneralInstance4Channel> PwmPin<'d, T, $channel> { #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")] pub fn $new_chx(pin: impl Peripheral

> + 'd, output_type: OutputType) -> Self { into_ref!(pin); @@ -54,11 +54,11 @@ channel_impl!(new_ch3, Ch3, Channel3Pin); channel_impl!(new_ch4, Ch4, Channel4Pin); /// Simple PWM driver. -pub struct SimplePwm<'d, T> { - inner: PeripheralRef<'d, T>, +pub struct SimplePwm<'d, T: GeneralInstance4Channel> { + inner: Timer<'d, T>, } -impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { +impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// Create a new simple PWM driver. pub fn new( tim: impl Peripheral

+ 'd, @@ -73,15 +73,11 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { } fn new_inner(tim: impl Peripheral

+ 'd, freq: Hertz, counting_mode: CountingMode) -> Self { - into_ref!(tim); - - T::enable_and_reset(); - - let mut this = Self { inner: tim }; + let mut this = Self { inner: Timer::new(tim) }; this.inner.set_counting_mode(counting_mode); this.set_frequency(freq); - this.inner.enable_outputs(); // Required for advanced timers, see CaptureCompare16bitInstance for details + this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details this.inner.start(); [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4] @@ -126,14 +122,14 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { /// Get max duty value. /// /// This value depends on the configured frequency and the timer's clock rate from RCC. - pub fn get_max_duty(&self) -> u16 { + pub fn get_max_duty(&self) -> u32 { self.inner.get_max_compare_value() + 1 } /// Set the duty for a given channel. /// /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. - pub fn set_duty(&mut self, channel: Channel, duty: u16) { + pub fn set_duty(&mut self, channel: Channel, duty: u32) { assert!(duty <= self.get_max_duty()); self.inner.set_compare_value(channel, duty) } @@ -141,7 +137,7 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { /// Get the duty for a given channel. /// /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. - pub fn get_duty(&self, channel: Channel) -> u16 { + pub fn get_duty(&self, channel: Channel) -> u32 { self.inner.get_compare_value(channel) } @@ -165,8 +161,6 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { channel: Channel, duty: &[u16], ) { - assert!(duty.iter().all(|v| *v <= self.get_max_duty())); - into_ref!(dma); #[allow(clippy::let_unit_value)] // eg. stm32f334 @@ -201,7 +195,7 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { &mut dma, req, duty, - T::regs_1ch().ccr(channel.index()).as_ptr() as *mut _, + self.inner.regs_1ch().ccr(channel.index()).as_ptr() as *mut _, dma_transfer_option, ) .await @@ -227,22 +221,20 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { macro_rules! impl_waveform_chx { ($fn_name:ident, $dma_ch:ident, $cc_ch:ident) => { - impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { + impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// Generate a sequence of PWM waveform /// /// Note: /// you will need to provide corresponding TIMx_CHy DMA channel to use this method. pub async fn $fn_name(&mut self, dma: impl Peripheral

>, duty: &[u16]) { - use super::vals::Ccds; - - assert!(duty.iter().all(|v| *v <= self.get_max_duty())); + use crate::pac::timer::vals::Ccds; into_ref!(dma); #[allow(clippy::let_unit_value)] // eg. stm32f334 let req = dma.request(); - let cc_channel = super::Channel::$cc_ch; + let cc_channel = Channel::$cc_ch; let original_duty_state = self.get_duty(cc_channel); let original_enable_state = self.is_enabled(cc_channel); @@ -279,7 +271,7 @@ macro_rules! impl_waveform_chx { &mut dma, req, duty, - T::regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut _, + self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut _, dma_transfer_option, ) .await @@ -314,10 +306,10 @@ impl_waveform_chx!(waveform_ch2, Ch2Dma, Ch2); impl_waveform_chx!(waveform_ch3, Ch3Dma, Ch3); impl_waveform_chx!(waveform_ch4, Ch4Dma, Ch4); -impl<'d, T: CaptureCompare16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d, T> { +impl<'d, T: GeneralInstance4Channel> embedded_hal_02::Pwm for SimplePwm<'d, T> { type Channel = Channel; type Time = Hertz; - type Duty = u16; + type Duty = u32; fn disable(&mut self, channel: Self::Channel) { self.inner.enable_channel(channel, false); diff --git a/embassy-stm32/src/ucpd.rs b/embassy-stm32/src/ucpd.rs index 9c37d2c04..fe614b811 100644 --- a/embassy-stm32/src/ucpd.rs +++ b/embassy-stm32/src/ucpd.rs @@ -16,11 +16,12 @@ use core::future::poll_fn; use core::marker::PhantomData; -use core::sync::atomic::Ordering; +use core::sync::atomic::{AtomicBool, Ordering}; use core::task::Poll; use embassy_hal_internal::drop::OnDrop; use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; +use embassy_sync::waitqueue::AtomicWaker; use crate::dma::{AnyChannel, Request, Transfer, TransferOptions}; use crate::interrupt; @@ -555,50 +556,47 @@ impl interrupt::typelevel::Handler for InterruptHandl } } -/// UCPD instance trait. -pub trait Instance: sealed::Instance + RccPeripheral {} +struct State { + waker: AtomicWaker, + // Inverted logic for a default state of 0 so that the data goes into the .bss section. + drop_not_ready: AtomicBool, +} -mod sealed { - use core::sync::atomic::AtomicBool; - - use embassy_sync::waitqueue::AtomicWaker; - - pub struct State { - pub waker: AtomicWaker, - // Inverted logic for a default state of 0 so that the data goes into the .bss section. - pub drop_not_ready: AtomicBool, - } - - impl State { - pub const fn new() -> Self { - Self { - waker: AtomicWaker::new(), - drop_not_ready: AtomicBool::new(false), - } +impl State { + pub const fn new() -> Self { + Self { + waker: AtomicWaker::new(), + drop_not_ready: AtomicBool::new(false), } } +} - pub trait Instance { - type Interrupt: crate::interrupt::typelevel::Interrupt; - const REGS: crate::pac::ucpd::Ucpd; - fn state() -> &'static crate::ucpd::sealed::State; - } +trait SealedInstance { + const REGS: crate::pac::ucpd::Ucpd; + fn state() -> &'static State; +} + +/// UCPD instance trait. +#[allow(private_bounds)] +pub trait Instance: SealedInstance + RccPeripheral { + /// Interrupt for this instance. + type Interrupt: crate::interrupt::typelevel::Interrupt; } foreach_interrupt!( ($inst:ident, ucpd, UCPD, GLOBAL, $irq:ident) => { - impl sealed::Instance for crate::peripherals::$inst { - type Interrupt = crate::interrupt::typelevel::$irq; - + impl SealedInstance for crate::peripherals::$inst { const REGS: crate::pac::ucpd::Ucpd = crate::pac::$inst; - fn state() -> &'static crate::ucpd::sealed::State { - static STATE: crate::ucpd::sealed::State = crate::ucpd::sealed::State::new(); + fn state() -> &'static State { + static STATE: State = State::new(); &STATE } } - impl Instance for crate::peripherals::$inst {} + impl Instance for crate::peripherals::$inst { + type Interrupt = crate::interrupt::typelevel::$irq; + } }; ); diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index ea727b010..7ab33043a 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -10,10 +10,11 @@ use core::task::Poll; use embassy_embedded_hal::SetConfig; use embassy_hal_internal::drop::OnDrop; use embassy_hal_internal::{into_ref, PeripheralRef}; +use embassy_sync::waitqueue::AtomicWaker; use futures::future::{select, Either}; use crate::dma::{NoDma, Transfer}; -use crate::gpio::sealed::AFType; +use crate::gpio::AFType; use crate::interrupt::typelevel::Interrupt; #[allow(unused_imports)] #[cfg(not(any(usart_v1, usart_v2)))] @@ -1326,8 +1327,6 @@ mod ringbuffered; #[cfg(not(gpdma))] pub use ringbuffered::RingBufferedUartRx; -use self::sealed::Kind; - #[cfg(any(usart_v1, usart_v2))] fn tdr(r: crate::pac::usart::Usart) -> *mut u8 { r.dr().as_ptr() as _ @@ -1370,52 +1369,50 @@ fn clear_interrupt_flags(r: Regs, sr: regs::Isr) { r.icr().write(|w| *w = regs::Icr(sr.0)); } -pub(crate) mod sealed { - use embassy_sync::waitqueue::AtomicWaker; +#[derive(Clone, Copy, PartialEq, Eq)] +enum Kind { + Uart, + #[cfg(any(usart_v3, usart_v4))] + #[allow(unused)] + Lpuart, +} - use super::*; +struct State { + rx_waker: AtomicWaker, +} - #[derive(Clone, Copy, PartialEq, Eq)] - pub enum Kind { - Uart, - #[cfg(any(usart_v3, usart_v4))] - Lpuart, - } - - pub struct State { - pub rx_waker: AtomicWaker, - pub tx_waker: AtomicWaker, - } - - impl State { - pub const fn new() -> Self { - Self { - rx_waker: AtomicWaker::new(), - tx_waker: AtomicWaker::new(), - } +impl State { + const fn new() -> Self { + Self { + rx_waker: AtomicWaker::new(), } } - - pub trait BasicInstance: crate::rcc::RccPeripheral { - const KIND: Kind; - type Interrupt: interrupt::typelevel::Interrupt; - - fn regs() -> Regs; - fn state() -> &'static State; - - fn buffered_state() -> &'static buffered::State; - } - - pub trait FullInstance: BasicInstance { - fn regs_uart() -> crate::pac::usart::Usart; - } +} + +trait SealedBasicInstance: crate::rcc::RccPeripheral { + const KIND: Kind; + + fn regs() -> Regs; + fn state() -> &'static State; + + fn buffered_state() -> &'static buffered::State; +} + +trait SealedFullInstance: SealedBasicInstance { + #[allow(unused)] + fn regs_uart() -> crate::pac::usart::Usart; } /// Basic UART driver instance -pub trait BasicInstance: Peripheral

+ sealed::BasicInstance + 'static + Send {} +#[allow(private_bounds)] +pub trait BasicInstance: Peripheral

+ SealedBasicInstance + 'static + Send { + /// Interrupt for this instance. + type Interrupt: interrupt::typelevel::Interrupt; +} /// Full UART driver instance -pub trait FullInstance: sealed::FullInstance {} +#[allow(private_bounds)] +pub trait FullInstance: SealedFullInstance {} pin_trait!(RxPin, BasicInstance); pin_trait!(TxPin, BasicInstance); @@ -1429,16 +1426,15 @@ dma_trait!(RxDma, BasicInstance); macro_rules! impl_usart { ($inst:ident, $irq:ident, $kind:expr) => { - impl sealed::BasicInstance for crate::peripherals::$inst { + impl SealedBasicInstance for crate::peripherals::$inst { const KIND: Kind = $kind; - type Interrupt = crate::interrupt::typelevel::$irq; fn regs() -> Regs { unsafe { Regs::from_ptr(crate::pac::$inst.as_ptr()) } } - fn state() -> &'static crate::usart::sealed::State { - static STATE: crate::usart::sealed::State = crate::usart::sealed::State::new(); + fn state() -> &'static crate::usart::State { + static STATE: crate::usart::State = crate::usart::State::new(); &STATE } @@ -1448,7 +1444,9 @@ macro_rules! impl_usart { } } - impl BasicInstance for peripherals::$inst {} + impl BasicInstance for peripherals::$inst { + type Interrupt = crate::interrupt::typelevel::$irq; + } }; } @@ -1460,7 +1458,7 @@ foreach_interrupt!( ($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => { impl_usart!($inst, $irq, Kind::Uart); - impl sealed::FullInstance for peripherals::$inst { + impl SealedFullInstance for peripherals::$inst { fn regs_uart() -> crate::pac::usart::Usart { crate::pac::$inst } diff --git a/embassy-stm32/src/usb/mod.rs b/embassy-stm32/src/usb/mod.rs index 788f61f16..1e3c44167 100644 --- a/embassy-stm32/src/usb/mod.rs +++ b/embassy-stm32/src/usb/mod.rs @@ -6,7 +6,7 @@ mod _version; pub use _version::*; use crate::interrupt::typelevel::Interrupt; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::SealedRccPeripheral; /// clock, power initialization stuff that's common for USB and OTG. fn common_init() { @@ -65,5 +65,5 @@ fn common_init() { T::Interrupt::unpend(); unsafe { T::Interrupt::enable() }; - ::enable_and_reset(); + ::enable_and_reset(); } diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs index d4095b466..b0e7067bd 100644 --- a/embassy-stm32/src/usb/otg.rs +++ b/embassy-stm32/src/usb/otg.rs @@ -11,11 +11,11 @@ use embassy_usb_driver::{ }; use futures::future::poll_fn; -use crate::gpio::sealed::AFType; +use crate::gpio::AFType; use crate::interrupt; use crate::interrupt::typelevel::Interrupt; use crate::pac::otg::{regs, vals}; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::{RccPeripheral, SealedRccPeripheral}; use crate::time::Hertz; /// Interrupt handler. @@ -809,7 +809,7 @@ impl<'d, T: Instance> Bus<'d, T> { fn disable(&mut self) { T::Interrupt::disable(); - ::disable(); + ::disable(); #[cfg(stm32l4)] crate::pac::PWR.cr2().modify(|w| w.set_usv(false)); @@ -1436,19 +1436,18 @@ fn quirk_setup_late_cnak(r: crate::pac::otg::Otg) -> bool { // Using Instance::ENDPOINT_COUNT requires feature(const_generic_expr) so just define maximum eps const MAX_EP_COUNT: usize = 9; -pub(crate) mod sealed { - pub trait Instance { - const HIGH_SPEED: bool; - const FIFO_DEPTH_WORDS: u16; - const ENDPOINT_COUNT: usize; +trait SealedInstance { + const HIGH_SPEED: bool; + const FIFO_DEPTH_WORDS: u16; + const ENDPOINT_COUNT: usize; - fn regs() -> crate::pac::otg::Otg; - fn state() -> &'static super::State<{ super::MAX_EP_COUNT }>; - } + fn regs() -> crate::pac::otg::Otg; + fn state() -> &'static super::State<{ MAX_EP_COUNT }>; } /// USB instance trait. -pub trait Instance: sealed::Instance + RccPeripheral + 'static { +#[allow(private_bounds)] +pub trait Instance: SealedInstance + RccPeripheral + 'static { /// Interrupt for this USB instance. type Interrupt: interrupt::typelevel::Interrupt; } @@ -1473,7 +1472,7 @@ pin_trait!(UlpiD7Pin, Instance); foreach_interrupt!( (USB_OTG_FS, otg, $block:ident, GLOBAL, $irq:ident) => { - impl sealed::Instance for crate::peripherals::USB_OTG_FS { + impl SealedInstance for crate::peripherals::USB_OTG_FS { const HIGH_SPEED: bool = false; cfg_if::cfg_if! { @@ -1538,7 +1537,7 @@ foreach_interrupt!( }; (USB_OTG_HS, otg, $block:ident, GLOBAL, $irq:ident) => { - impl sealed::Instance for crate::peripherals::USB_OTG_HS { + impl SealedInstance for crate::peripherals::USB_OTG_HS { const HIGH_SPEED: bool = true; cfg_if::cfg_if! { diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index c4f9140da..f48808cb3 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs @@ -15,7 +15,7 @@ use embassy_usb_driver::{ use crate::pac::usb::regs; use crate::pac::usb::vals::{EpType, Stat}; use crate::pac::USBRAM; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::RccPeripheral; use crate::{interrupt, Peripheral}; /// Interrupt handler. @@ -277,8 +277,8 @@ impl<'d, T: Instance> Driver<'d, T> { #[cfg(not(stm32l1))] { - dp.set_as_af(dp.af_num(), crate::gpio::sealed::AFType::OutputPushPull); - dm.set_as_af(dm.af_num(), crate::gpio::sealed::AFType::OutputPushPull); + dp.set_as_af(dp.af_num(), crate::gpio::AFType::OutputPushPull); + dm.set_as_af(dm.af_num(), crate::gpio::AFType::OutputPushPull); } #[cfg(stm32l1)] let _ = (dp, dm); // suppress "unused" warnings. @@ -1037,14 +1037,13 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { } } -pub(crate) mod sealed { - pub trait Instance { - fn regs() -> crate::pac::usb::Usb; - } +trait SealedInstance { + fn regs() -> crate::pac::usb::Usb; } /// USB instance trait. -pub trait Instance: sealed::Instance + RccPeripheral + 'static { +#[allow(private_bounds)] +pub trait Instance: SealedInstance + RccPeripheral + 'static { /// Interrupt for this USB instance. type Interrupt: interrupt::typelevel::Interrupt; } @@ -1055,7 +1054,7 @@ pin_trait!(DmPin, Instance); foreach_interrupt!( ($inst:ident, usb, $block:ident, LP, $irq:ident) => { - impl sealed::Instance for crate::peripherals::$inst { + impl SealedInstance for crate::peripherals::$inst { fn regs() -> crate::pac::usb::Usb { crate::pac::$inst } diff --git a/embassy-stm32/src/wdg/mod.rs b/embassy-stm32/src/wdg/mod.rs index 2ff0db09e..ab21c4b6b 100644 --- a/embassy-stm32/src/wdg/mod.rs +++ b/embassy-stm32/src/wdg/mod.rs @@ -80,18 +80,17 @@ impl<'d, T: Instance> IndependentWatchdog<'d, T> { } } -mod sealed { - pub trait Instance { - fn regs() -> crate::pac::iwdg::Iwdg; - } +trait SealedInstance { + fn regs() -> crate::pac::iwdg::Iwdg; } /// IWDG instance trait. -pub trait Instance: sealed::Instance {} +#[allow(private_bounds)] +pub trait Instance: SealedInstance {} foreach_peripheral!( (iwdg, $inst:ident) => { - impl sealed::Instance for crate::peripherals::$inst { + impl SealedInstance for crate::peripherals::$inst { fn regs() -> crate::pac::iwdg::Iwdg { crate::pac::$inst } diff --git a/examples/stm32f4/src/bin/ws2812_pwm.rs b/examples/stm32f4/src/bin/ws2812_pwm.rs index 6122cea2d..cbaff75fc 100644 --- a/examples/stm32f4/src/bin/ws2812_pwm.rs +++ b/examples/stm32f4/src/bin/ws2812_pwm.rs @@ -15,8 +15,9 @@ use embassy_executor::Spawner; use embassy_stm32::gpio::OutputType; use embassy_stm32::time::khz; +use embassy_stm32::timer::low_level::CountingMode; use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; -use embassy_stm32::timer::{Channel, CountingMode}; +use embassy_stm32::timer::Channel; use embassy_time::{Duration, Ticker, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -60,7 +61,7 @@ async fn main(_spawner: Spawner) { // construct ws2812 non-return-to-zero (NRZ) code bit by bit // ws2812 only need 24 bits for each LED, but we add one bit more to keep PWM output low - let max_duty = ws2812_pwm.get_max_duty(); + let max_duty = ws2812_pwm.get_max_duty() as u16; let n0 = 8 * max_duty / 25; // ws2812 Bit 0 high level timing let n1 = 2 * n0; // ws2812 Bit 1 high level timing diff --git a/examples/stm32h7/src/bin/dac_dma.rs b/examples/stm32h7/src/bin/dac_dma.rs index feec28993..3a9887e3c 100644 --- a/examples/stm32h7/src/bin/dac_dma.rs +++ b/examples/stm32h7/src/bin/dac_dma.rs @@ -6,9 +6,9 @@ use embassy_executor::Spawner; use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; use embassy_stm32::pac::timer::vals::Mms; use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; -use embassy_stm32::rcc::low_level::RccPeripheral; +use embassy_stm32::rcc::frequency; use embassy_stm32::time::Hertz; -use embassy_stm32::timer::low_level::BasicInstance; +use embassy_stm32::timer::low_level::Timer; use micromath::F32Ext; use {defmt_rtt as _, panic_probe as _}; @@ -51,19 +51,19 @@ async fn main(spawner: Spawner) { // Obtain two independent channels (p.DAC1 can only be consumed once, though!) let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split(); - spawner.spawn(dac_task1(dac_ch1)).ok(); - spawner.spawn(dac_task2(dac_ch2)).ok(); + spawner.spawn(dac_task1(p.TIM6, dac_ch1)).ok(); + spawner.spawn(dac_task2(p.TIM7, dac_ch2)).ok(); } #[embassy_executor::task] -async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { +async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { let data: &[u8; 256] = &calculate_array::<256>(); - info!("TIM6 frequency is {}", TIM6::frequency()); + info!("TIM6 frequency is {}", frequency::()); const FREQUENCY: Hertz = Hertz::hz(200); // Compute the reload value such that we obtain the FREQUENCY for the sine - let reload: u32 = (TIM6::frequency().0 / FREQUENCY.0) / data.len() as u32; + let reload: u32 = (frequency::().0 / FREQUENCY.0) / data.len() as u32; // Depends on your clock and on the specific chip used, you may need higher or lower values here if reload < 10 { @@ -74,17 +74,17 @@ async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { dac.set_triggering(true); dac.enable(); - TIM6::enable_and_reset(); - TIM6::regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); - TIM6::regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); - TIM6::regs_basic().cr1().modify(|w| { + let tim = Timer::new(tim); + tim.regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); + tim.regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); + tim.regs_basic().cr1().modify(|w| { w.set_opm(false); w.set_cen(true); }); debug!( "TIM6 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", - TIM6::frequency(), + frequency::(), FREQUENCY, reload, reload as u16, @@ -99,22 +99,22 @@ async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { } #[embassy_executor::task] -async fn dac_task2(mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { +async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { let data: &[u8; 256] = &calculate_array::<256>(); - info!("TIM7 frequency is {}", TIM7::frequency()); + info!("TIM7 frequency is {}", frequency::()); const FREQUENCY: Hertz = Hertz::hz(600); - let reload: u32 = (TIM7::frequency().0 / FREQUENCY.0) / data.len() as u32; + let reload: u32 = (frequency::().0 / FREQUENCY.0) / data.len() as u32; if reload < 10 { error!("Reload value {} below threshold!", reload); } - TIM7::enable_and_reset(); - TIM7::regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); - TIM7::regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); - TIM7::regs_basic().cr1().modify(|w| { + let tim = Timer::new(tim); + tim.regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); + tim.regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); + tim.regs_basic().cr1().modify(|w| { w.set_opm(false); w.set_cen(true); }); @@ -125,7 +125,7 @@ async fn dac_task2(mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { debug!( "TIM7 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", - TIM7::frequency(), + frequency::(), FREQUENCY, reload, reload as u16, diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs index 049d9967d..a95b44b74 100644 --- a/examples/stm32h7/src/bin/low_level_timer_api.rs +++ b/examples/stm32h7/src/bin/low_level_timer_api.rs @@ -3,11 +3,11 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::gpio::low_level::AFType; -use embassy_stm32::gpio::Speed; +use embassy_stm32::gpio::{AFType, Flex, Pull, Speed}; use embassy_stm32::time::{khz, Hertz}; -use embassy_stm32::timer::*; -use embassy_stm32::{into_ref, Config, Peripheral, PeripheralRef}; +use embassy_stm32::timer::low_level::{OutputCompareMode, Timer as LLTimer}; +use embassy_stm32::timer::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance32bit4Channel}; +use embassy_stm32::{into_ref, Config, Peripheral}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; @@ -56,11 +56,15 @@ async fn main(_spawner: Spawner) { Timer::after_millis(300).await; } } -pub struct SimplePwm32<'d, T: CaptureCompare32bitInstance> { - inner: PeripheralRef<'d, T>, +pub struct SimplePwm32<'d, T: GeneralInstance32bit4Channel> { + tim: LLTimer<'d, T>, + _ch1: Flex<'d>, + _ch2: Flex<'d>, + _ch3: Flex<'d>, + _ch4: Flex<'d>, } -impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> { +impl<'d, T: GeneralInstance32bit4Channel> SimplePwm32<'d, T> { pub fn new( tim: impl Peripheral

+ 'd, ch1: impl Peripheral

> + 'd, @@ -69,25 +73,33 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> { ch4: impl Peripheral

> + 'd, freq: Hertz, ) -> Self { - into_ref!(tim, ch1, ch2, ch3, ch4); + into_ref!(ch1, ch2, ch3, ch4); - T::enable_and_reset(); + let af1 = ch1.af_num(); + let af2 = ch2.af_num(); + let af3 = ch3.af_num(); + let af4 = ch4.af_num(); + let mut ch1 = Flex::new(ch1); + let mut ch2 = Flex::new(ch2); + let mut ch3 = Flex::new(ch3); + let mut ch4 = Flex::new(ch4); + ch1.set_as_af_unchecked(af1, AFType::OutputPushPull, Pull::None, Speed::VeryHigh); + ch2.set_as_af_unchecked(af2, AFType::OutputPushPull, Pull::None, Speed::VeryHigh); + ch3.set_as_af_unchecked(af3, AFType::OutputPushPull, Pull::None, Speed::VeryHigh); + ch4.set_as_af_unchecked(af4, AFType::OutputPushPull, Pull::None, Speed::VeryHigh); - ch1.set_speed(Speed::VeryHigh); - ch1.set_as_af(ch1.af_num(), AFType::OutputPushPull); - ch2.set_speed(Speed::VeryHigh); - ch2.set_as_af(ch1.af_num(), AFType::OutputPushPull); - ch3.set_speed(Speed::VeryHigh); - ch3.set_as_af(ch1.af_num(), AFType::OutputPushPull); - ch4.set_speed(Speed::VeryHigh); - ch4.set_as_af(ch1.af_num(), AFType::OutputPushPull); - - let mut this = Self { inner: tim }; + let mut this = Self { + tim: LLTimer::new(tim), + _ch1: ch1, + _ch2: ch2, + _ch3: ch3, + _ch4: ch4, + }; this.set_frequency(freq); - this.inner.start(); + this.tim.start(); - let r = T::regs_gp32(); + let r = this.tim.regs_gp32(); r.ccmr_output(0) .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into())); r.ccmr_output(0) @@ -101,23 +113,26 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> { } pub fn enable(&mut self, channel: Channel) { - T::regs_gp32().ccer().modify(|w| w.set_cce(channel.index(), true)); + self.tim.regs_gp32().ccer().modify(|w| w.set_cce(channel.index(), true)); } pub fn disable(&mut self, channel: Channel) { - T::regs_gp32().ccer().modify(|w| w.set_cce(channel.index(), false)); + self.tim + .regs_gp32() + .ccer() + .modify(|w| w.set_cce(channel.index(), false)); } pub fn set_frequency(&mut self, freq: Hertz) { - ::set_frequency(&mut self.inner, freq); + self.tim.set_frequency(freq); } pub fn get_max_duty(&self) -> u32 { - T::regs_gp32().arr().read() + self.tim.regs_gp32().arr().read() } pub fn set_duty(&mut self, channel: Channel, duty: u32) { defmt::assert!(duty < self.get_max_duty()); - T::regs_gp32().ccr(channel.index()).write_value(duty) + self.tim.regs_gp32().ccr(channel.index()).write_value(duty) } } diff --git a/examples/stm32l4/src/bin/dac_dma.rs b/examples/stm32l4/src/bin/dac_dma.rs index f227812cd..d01b016c0 100644 --- a/examples/stm32l4/src/bin/dac_dma.rs +++ b/examples/stm32l4/src/bin/dac_dma.rs @@ -6,9 +6,9 @@ use embassy_executor::Spawner; use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; use embassy_stm32::pac::timer::vals::Mms; use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; -use embassy_stm32::rcc::low_level::RccPeripheral; +use embassy_stm32::rcc::frequency; use embassy_stm32::time::Hertz; -use embassy_stm32::timer::low_level::BasicInstance; +use embassy_stm32::timer::low_level::Timer; use micromath::F32Ext; use {defmt_rtt as _, panic_probe as _}; @@ -22,19 +22,19 @@ async fn main(spawner: Spawner) { // Obtain two independent channels (p.DAC1 can only be consumed once, though!) let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split(); - spawner.spawn(dac_task1(dac_ch1)).ok(); - spawner.spawn(dac_task2(dac_ch2)).ok(); + spawner.spawn(dac_task1(p.TIM6, dac_ch1)).ok(); + spawner.spawn(dac_task2(p.TIM7, dac_ch2)).ok(); } #[embassy_executor::task] -async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { +async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { let data: &[u8; 256] = &calculate_array::<256>(); - info!("TIM6 frequency is {}", TIM6::frequency()); + info!("TIM6 frequency is {}", frequency::()); const FREQUENCY: Hertz = Hertz::hz(200); // Compute the reload value such that we obtain the FREQUENCY for the sine - let reload: u32 = (TIM6::frequency().0 / FREQUENCY.0) / data.len() as u32; + let reload: u32 = (frequency::().0 / FREQUENCY.0) / data.len() as u32; // Depends on your clock and on the specific chip used, you may need higher or lower values here if reload < 10 { @@ -45,17 +45,17 @@ async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { dac.set_triggering(true); dac.enable(); - TIM6::enable_and_reset(); - TIM6::regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); - TIM6::regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); - TIM6::regs_basic().cr1().modify(|w| { + let tim = Timer::new(tim); + tim.regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); + tim.regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); + tim.regs_basic().cr1().modify(|w| { w.set_opm(false); w.set_cen(true); }); debug!( "TIM6 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", - TIM6::frequency(), + frequency::(), FREQUENCY, reload, reload as u16, @@ -70,22 +70,22 @@ async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { } #[embassy_executor::task] -async fn dac_task2(mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { +async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { let data: &[u8; 256] = &calculate_array::<256>(); - info!("TIM7 frequency is {}", TIM7::frequency()); + info!("TIM7 frequency is {}", frequency::()); const FREQUENCY: Hertz = Hertz::hz(600); - let reload: u32 = (TIM7::frequency().0 / FREQUENCY.0) / data.len() as u32; + let reload: u32 = (frequency::().0 / FREQUENCY.0) / data.len() as u32; if reload < 10 { error!("Reload value {} below threshold!", reload); } - TIM7::enable_and_reset(); - TIM7::regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); - TIM7::regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); - TIM7::regs_basic().cr1().modify(|w| { + let tim = Timer::new(tim); + tim.regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); + tim.regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); + tim.regs_basic().cr1().modify(|w| { w.set_opm(false); w.set_cen(true); }); @@ -96,7 +96,7 @@ async fn dac_task2(mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { debug!( "TIM7 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", - TIM7::frequency(), + frequency::(), FREQUENCY, reload, reload as u16,