diff options
| author | Dario Nieuwenhuis <[email protected]> | 2024-03-23 01:55:42 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-03-23 01:55:42 +0100 |
| commit | 1171e116553f6ac43e12505b387b6eabe3037bf9 (patch) | |
| tree | f64be3f155db4c1a7a9cf452d2669abcb7213709 | |
| parent | 2fd6f0e718931d6b06ce2db16da012544757b00c (diff) | |
| parent | 2bca875b5f72578cbd20404010d174795d263313 (diff) | |
Merge pull request #2730 from embassy-rs/stm32-sealed
stm32: use private_bounds for sealed traits.
63 files changed, 1798 insertions, 2045 deletions
| @@ -124,6 +124,7 @@ cargo batch \ | |||
| 124 | --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,exti,time-driver-any,time \ | 124 | --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,exti,time-driver-any,time \ |
| 125 | --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h725re,defmt,exti,time-driver-any,time \ | 125 | --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h725re,defmt,exti,time-driver-any,time \ |
| 126 | --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7b3ai,defmt,exti,time-driver-any,time \ | 126 | --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7b3ai,defmt,exti,time-driver-any,time \ |
| 127 | --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7b3ai,defmt,exti,time-driver-tim1,time \ | ||
| 127 | --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l431cb,defmt,exti,time-driver-any,time \ | 128 | --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l431cb,defmt,exti,time-driver-any,time \ |
| 128 | --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any,time \ | 129 | --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any,time \ |
| 129 | --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l422cb,defmt,exti,time-driver-any,time \ | 130 | --- 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() { | |||
| 584 | }; | 584 | }; |
| 585 | 585 | ||
| 586 | g.extend(quote! { | 586 | g.extend(quote! { |
| 587 | impl crate::rcc::sealed::RccPeripheral for peripherals::#pname { | 587 | impl crate::rcc::SealedRccPeripheral for peripherals::#pname { |
| 588 | fn frequency() -> crate::time::Hertz { | 588 | fn frequency() -> crate::time::Hertz { |
| 589 | #clock_frequency | 589 | #clock_frequency |
| 590 | } | 590 | } |
| @@ -1486,7 +1486,7 @@ fn main() { | |||
| 1486 | #[crate::interrupt] | 1486 | #[crate::interrupt] |
| 1487 | unsafe fn #irq () { | 1487 | unsafe fn #irq () { |
| 1488 | #( | 1488 | #( |
| 1489 | <crate::peripherals::#channels as crate::dma::sealed::ChannelInterrupt>::on_irq(); | 1489 | <crate::peripherals::#channels as crate::dma::ChannelInterrupt>::on_irq(); |
| 1490 | )* | 1490 | )* |
| 1491 | } | 1491 | } |
| 1492 | } | 1492 | } |
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<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 33 | 33 | ||
| 34 | pub struct Vref; | 34 | pub struct Vref; |
| 35 | impl<T: Instance> AdcPin<T> for Vref {} | 35 | impl<T: Instance> AdcPin<T> for Vref {} |
| 36 | impl<T: Instance> super::sealed::AdcPin<T> for Vref { | 36 | impl<T: Instance> super::SealedAdcPin<T> for Vref { |
| 37 | fn channel(&self) -> u8 { | 37 | fn channel(&self) -> u8 { |
| 38 | 17 | 38 | 17 |
| 39 | } | 39 | } |
| @@ -41,7 +41,7 @@ impl<T: Instance> super::sealed::AdcPin<T> for Vref { | |||
| 41 | 41 | ||
| 42 | pub struct Temperature; | 42 | pub struct Temperature; |
| 43 | impl<T: Instance> AdcPin<T> for Temperature {} | 43 | impl<T: Instance> AdcPin<T> for Temperature {} |
| 44 | impl<T: Instance> super::sealed::AdcPin<T> for Temperature { | 44 | impl<T: Instance> super::SealedAdcPin<T> for Temperature { |
| 45 | fn channel(&self) -> u8 { | 45 | fn channel(&self) -> u8 { |
| 46 | 16 | 46 | 16 |
| 47 | } | 47 | } |
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<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 33 | 33 | ||
| 34 | pub struct Vref; | 34 | pub struct Vref; |
| 35 | impl<T: Instance> AdcPin<T> for Vref {} | 35 | impl<T: Instance> AdcPin<T> for Vref {} |
| 36 | impl<T: Instance> super::sealed::AdcPin<T> for Vref { | 36 | impl<T: Instance> super::SealedAdcPin<T> for Vref { |
| 37 | fn channel(&self) -> u8 { | 37 | fn channel(&self) -> u8 { |
| 38 | 18 | 38 | 18 |
| 39 | } | 39 | } |
| @@ -48,7 +48,7 @@ impl Vref { | |||
| 48 | 48 | ||
| 49 | pub struct Temperature; | 49 | pub struct Temperature; |
| 50 | impl<T: Instance> AdcPin<T> for Temperature {} | 50 | impl<T: Instance> AdcPin<T> for Temperature {} |
| 51 | impl<T: Instance> super::sealed::AdcPin<T> for Temperature { | 51 | impl<T: Instance> super::SealedAdcPin<T> for Temperature { |
| 52 | fn channel(&self) -> u8 { | 52 | fn channel(&self) -> u8 { |
| 53 | 16 | 53 | 16 |
| 54 | } | 54 | } |
| @@ -102,7 +102,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | fn freq() -> Hertz { | 104 | fn freq() -> Hertz { |
| 105 | <T as crate::rcc::sealed::RccPeripheral>::frequency() | 105 | <T as crate::rcc::SealedRccPeripheral>::frequency() |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | pub fn sample_time_for_us(&self, us: u32) -> SampleTime { | 108 | 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<T: Instance>(op: i8) { | |||
| 65 | 65 | ||
| 66 | pub struct Vref<T: Instance>(core::marker::PhantomData<T>); | 66 | pub struct Vref<T: Instance>(core::marker::PhantomData<T>); |
| 67 | impl<T: Instance> AdcPin<T> for Vref<T> {} | 67 | impl<T: Instance> AdcPin<T> for Vref<T> {} |
| 68 | impl<T: Instance> super::sealed::AdcPin<T> for Vref<T> { | 68 | impl<T: Instance> super::SealedAdcPin<T> for Vref<T> { |
| 69 | fn channel(&self) -> u8 { | 69 | fn channel(&self) -> u8 { |
| 70 | 17 | 70 | 17 |
| 71 | } | 71 | } |
| @@ -124,7 +124,7 @@ impl<T: Instance> Drop for Vref<T> { | |||
| 124 | 124 | ||
| 125 | pub struct Temperature<T: Instance>(core::marker::PhantomData<T>); | 125 | pub struct Temperature<T: Instance>(core::marker::PhantomData<T>); |
| 126 | impl<T: Instance> AdcPin<T> for Temperature<T> {} | 126 | impl<T: Instance> AdcPin<T> for Temperature<T> {} |
| 127 | impl<T: Instance> super::sealed::AdcPin<T> for Temperature<T> { | 127 | impl<T: Instance> super::SealedAdcPin<T> for Temperature<T> { |
| 128 | fn channel(&self) -> u8 { | 128 | fn channel(&self) -> u8 { |
| 129 | 16 | 129 | 16 |
| 130 | } | 130 | } |
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; | |||
| 17 | #[allow(unused)] | 17 | #[allow(unused)] |
| 18 | #[cfg(not(adc_f3_v2))] | 18 | #[cfg(not(adc_f3_v2))] |
| 19 | pub use _version::*; | 19 | pub use _version::*; |
| 20 | #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] | ||
| 21 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 20 | 22 | ||
| 21 | #[cfg(not(any(adc_f1, adc_f3_v2)))] | 23 | #[cfg(not(any(adc_f1, adc_f3_v2)))] |
| 22 | pub use crate::pac::adc::vals::Res as Resolution; | 24 | pub use crate::pac::adc::vals::Res as Resolution; |
| @@ -31,63 +33,65 @@ pub struct Adc<'d, T: Instance> { | |||
| 31 | sample_time: SampleTime, | 33 | sample_time: SampleTime, |
| 32 | } | 34 | } |
| 33 | 35 | ||
| 34 | pub(crate) mod sealed { | 36 | #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] |
| 35 | #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] | 37 | pub struct State { |
| 36 | use embassy_sync::waitqueue::AtomicWaker; | 38 | pub waker: AtomicWaker, |
| 37 | 39 | } | |
| 38 | #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] | ||
| 39 | pub struct State { | ||
| 40 | pub waker: AtomicWaker, | ||
| 41 | } | ||
| 42 | 40 | ||
| 43 | #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] | 41 | #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] |
| 44 | impl State { | 42 | impl State { |
| 45 | pub const fn new() -> Self { | 43 | pub const fn new() -> Self { |
| 46 | Self { | 44 | Self { |
| 47 | waker: AtomicWaker::new(), | 45 | waker: AtomicWaker::new(), |
| 48 | } | ||
| 49 | } | 46 | } |
| 50 | } | 47 | } |
| 48 | } | ||
| 51 | 49 | ||
| 52 | pub trait InterruptableInstance { | 50 | trait SealedInstance { |
| 53 | type Interrupt: crate::interrupt::typelevel::Interrupt; | 51 | #[allow(unused)] |
| 54 | } | 52 | fn regs() -> crate::pac::adc::Adc; |
| 55 | 53 | #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))] | |
| 56 | pub trait Instance: InterruptableInstance { | 54 | fn common_regs() -> crate::pac::adccommon::AdcCommon; |
| 57 | fn regs() -> crate::pac::adc::Adc; | 55 | #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] |
| 58 | #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))] | 56 | fn state() -> &'static State; |
| 59 | fn common_regs() -> crate::pac::adccommon::AdcCommon; | 57 | } |
| 60 | #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] | ||
| 61 | fn state() -> &'static State; | ||
| 62 | } | ||
| 63 | 58 | ||
| 64 | pub trait AdcPin<T: Instance> { | 59 | pub(crate) trait SealedAdcPin<T: Instance> { |
| 65 | #[cfg(any(adc_v1, adc_l0, adc_v2))] | 60 | #[cfg(any(adc_v1, adc_l0, adc_v2))] |
| 66 | fn set_as_analog(&mut self) {} | 61 | fn set_as_analog(&mut self) {} |
| 67 | 62 | ||
| 68 | fn channel(&self) -> u8; | 63 | #[allow(unused)] |
| 69 | } | 64 | fn channel(&self) -> u8; |
| 65 | } | ||
| 70 | 66 | ||
| 71 | pub trait InternalChannel<T> { | 67 | trait SealedInternalChannel<T> { |
| 72 | fn channel(&self) -> u8; | 68 | #[allow(unused)] |
| 73 | } | 69 | fn channel(&self) -> u8; |
| 74 | } | 70 | } |
| 75 | 71 | ||
| 76 | /// ADC instance. | 72 | /// ADC instance. |
| 77 | #[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)))] | 73 | #[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)))] |
| 78 | pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> {} | 74 | #[allow(private_bounds)] |
| 75 | pub trait Instance: SealedInstance + crate::Peripheral<P = Self> { | ||
| 76 | type Interrupt: crate::interrupt::typelevel::Interrupt; | ||
| 77 | } | ||
| 79 | /// ADC instance. | 78 | /// ADC instance. |
| 80 | #[cfg(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0, adc_h5))] | 79 | #[cfg(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0, adc_h5))] |
| 81 | pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {} | 80 | #[allow(private_bounds)] |
| 81 | pub trait Instance: SealedInstance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral { | ||
| 82 | type Interrupt: crate::interrupt::typelevel::Interrupt; | ||
| 83 | } | ||
| 82 | 84 | ||
| 83 | /// ADC pin. | 85 | /// ADC pin. |
| 84 | pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {} | 86 | #[allow(private_bounds)] |
| 87 | pub trait AdcPin<T: Instance>: SealedAdcPin<T> {} | ||
| 85 | /// ADC internal channel. | 88 | /// ADC internal channel. |
| 86 | pub trait InternalChannel<T>: sealed::InternalChannel<T> {} | 89 | #[allow(private_bounds)] |
| 90 | pub trait InternalChannel<T>: SealedInternalChannel<T> {} | ||
| 87 | 91 | ||
| 88 | foreach_adc!( | 92 | foreach_adc!( |
| 89 | ($inst:ident, $common_inst:ident, $clock:ident) => { | 93 | ($inst:ident, $common_inst:ident, $clock:ident) => { |
| 90 | impl crate::adc::sealed::Instance for peripherals::$inst { | 94 | impl crate::adc::SealedInstance for peripherals::$inst { |
| 91 | fn regs() -> crate::pac::adc::Adc { | 95 | fn regs() -> crate::pac::adc::Adc { |
| 92 | crate::pac::$inst | 96 | crate::pac::$inst |
| 93 | } | 97 | } |
| @@ -98,21 +102,15 @@ foreach_adc!( | |||
| 98 | } | 102 | } |
| 99 | 103 | ||
| 100 | #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] | 104 | #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] |
| 101 | fn state() -> &'static sealed::State { | 105 | fn state() -> &'static State { |
| 102 | static STATE: sealed::State = sealed::State::new(); | 106 | static STATE: State = State::new(); |
| 103 | &STATE | 107 | &STATE |
| 104 | } | 108 | } |
| 105 | } | 109 | } |
| 106 | 110 | ||
| 107 | foreach_interrupt!( | 111 | impl crate::adc::Instance for peripherals::$inst { |
| 108 | ($inst,adc,ADC,GLOBAL,$irq:ident) => { | 112 | type Interrupt = crate::_generated::peripheral_interrupts::$inst::GLOBAL; |
| 109 | impl sealed::InterruptableInstance for peripherals::$inst { | 113 | } |
| 110 | type Interrupt = crate::interrupt::typelevel::$irq; | ||
| 111 | } | ||
| 112 | }; | ||
| 113 | ); | ||
| 114 | |||
| 115 | impl crate::adc::Instance for peripherals::$inst {} | ||
| 116 | }; | 114 | }; |
| 117 | ); | 115 | ); |
| 118 | 116 | ||
| @@ -120,10 +118,10 @@ macro_rules! impl_adc_pin { | |||
| 120 | ($inst:ident, $pin:ident, $ch:expr) => { | 118 | ($inst:ident, $pin:ident, $ch:expr) => { |
| 121 | impl crate::adc::AdcPin<peripherals::$inst> for crate::peripherals::$pin {} | 119 | impl crate::adc::AdcPin<peripherals::$inst> for crate::peripherals::$pin {} |
| 122 | 120 | ||
| 123 | impl crate::adc::sealed::AdcPin<peripherals::$inst> for crate::peripherals::$pin { | 121 | impl crate::adc::SealedAdcPin<peripherals::$inst> for crate::peripherals::$pin { |
| 124 | #[cfg(any(adc_v1, adc_l0, adc_v2))] | 122 | #[cfg(any(adc_v1, adc_l0, adc_v2))] |
| 125 | fn set_as_analog(&mut self) { | 123 | fn set_as_analog(&mut self) { |
| 126 | <Self as crate::gpio::sealed::Pin>::set_as_analog(self); | 124 | <Self as crate::gpio::SealedPin>::set_as_analog(self); |
| 127 | } | 125 | } |
| 128 | 126 | ||
| 129 | fn channel(&self) -> u8 { | 127 | 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; | |||
| 39 | impl AdcPin<ADC> for Vbat {} | 39 | impl AdcPin<ADC> for Vbat {} |
| 40 | 40 | ||
| 41 | #[cfg(not(adc_l0))] | 41 | #[cfg(not(adc_l0))] |
| 42 | impl super::sealed::AdcPin<ADC> for Vbat { | 42 | impl super::SealedAdcPin<ADC> for Vbat { |
| 43 | fn channel(&self) -> u8 { | 43 | fn channel(&self) -> u8 { |
| 44 | 18 | 44 | 18 |
| 45 | } | 45 | } |
| @@ -47,7 +47,7 @@ impl super::sealed::AdcPin<ADC> for Vbat { | |||
| 47 | 47 | ||
| 48 | pub struct Vref; | 48 | pub struct Vref; |
| 49 | impl AdcPin<ADC> for Vref {} | 49 | impl AdcPin<ADC> for Vref {} |
| 50 | impl super::sealed::AdcPin<ADC> for Vref { | 50 | impl super::SealedAdcPin<ADC> for Vref { |
| 51 | fn channel(&self) -> u8 { | 51 | fn channel(&self) -> u8 { |
| 52 | 17 | 52 | 17 |
| 53 | } | 53 | } |
| @@ -55,7 +55,7 @@ impl super::sealed::AdcPin<ADC> for Vref { | |||
| 55 | 55 | ||
| 56 | pub struct Temperature; | 56 | pub struct Temperature; |
| 57 | impl AdcPin<ADC> for Temperature {} | 57 | impl AdcPin<ADC> for Temperature {} |
| 58 | impl super::sealed::AdcPin<ADC> for Temperature { | 58 | impl super::SealedAdcPin<ADC> for Temperature { |
| 59 | fn channel(&self) -> u8 { | 59 | fn channel(&self) -> u8 { |
| 60 | 16 | 60 | 16 |
| 61 | } | 61 | } |
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; | |||
| 16 | 16 | ||
| 17 | pub struct VrefInt; | 17 | pub struct VrefInt; |
| 18 | impl AdcPin<ADC1> for VrefInt {} | 18 | impl AdcPin<ADC1> for VrefInt {} |
| 19 | impl super::sealed::AdcPin<ADC1> for VrefInt { | 19 | impl super::SealedAdcPin<ADC1> for VrefInt { |
| 20 | fn channel(&self) -> u8 { | 20 | fn channel(&self) -> u8 { |
| 21 | 17 | 21 | 17 |
| 22 | } | 22 | } |
| @@ -31,7 +31,7 @@ impl VrefInt { | |||
| 31 | 31 | ||
| 32 | pub struct Temperature; | 32 | pub struct Temperature; |
| 33 | impl AdcPin<ADC1> for Temperature {} | 33 | impl AdcPin<ADC1> for Temperature {} |
| 34 | impl super::sealed::AdcPin<ADC1> for Temperature { | 34 | impl super::SealedAdcPin<ADC1> for Temperature { |
| 35 | fn channel(&self) -> u8 { | 35 | fn channel(&self) -> u8 { |
| 36 | cfg_if::cfg_if! { | 36 | cfg_if::cfg_if! { |
| 37 | if #[cfg(any(stm32f2, stm32f40, stm32f41))] { | 37 | if #[cfg(any(stm32f2, stm32f40, stm32f41))] { |
| @@ -52,7 +52,7 @@ impl Temperature { | |||
| 52 | 52 | ||
| 53 | pub struct Vbat; | 53 | pub struct Vbat; |
| 54 | impl AdcPin<ADC1> for Vbat {} | 54 | impl AdcPin<ADC1> for Vbat {} |
| 55 | impl super::sealed::AdcPin<ADC1> for Vbat { | 55 | impl super::SealedAdcPin<ADC1> for Vbat { |
| 56 | fn channel(&self) -> u8 { | 56 | fn channel(&self) -> u8 { |
| 57 | 18 | 57 | 18 |
| 58 | } | 58 | } |
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; | |||
| 12 | 12 | ||
| 13 | pub struct VrefInt; | 13 | pub struct VrefInt; |
| 14 | impl<T: Instance> AdcPin<T> for VrefInt {} | 14 | impl<T: Instance> AdcPin<T> for VrefInt {} |
| 15 | impl<T: Instance> super::sealed::AdcPin<T> for VrefInt { | 15 | impl<T: Instance> super::SealedAdcPin<T> for VrefInt { |
| 16 | fn channel(&self) -> u8 { | 16 | fn channel(&self) -> u8 { |
| 17 | cfg_if! { | 17 | cfg_if! { |
| 18 | if #[cfg(adc_g0)] { | 18 | if #[cfg(adc_g0)] { |
| @@ -29,7 +29,7 @@ impl<T: Instance> super::sealed::AdcPin<T> for VrefInt { | |||
| 29 | 29 | ||
| 30 | pub struct Temperature; | 30 | pub struct Temperature; |
| 31 | impl<T: Instance> AdcPin<T> for Temperature {} | 31 | impl<T: Instance> AdcPin<T> for Temperature {} |
| 32 | impl<T: Instance> super::sealed::AdcPin<T> for Temperature { | 32 | impl<T: Instance> super::SealedAdcPin<T> for Temperature { |
| 33 | fn channel(&self) -> u8 { | 33 | fn channel(&self) -> u8 { |
| 34 | cfg_if! { | 34 | cfg_if! { |
| 35 | if #[cfg(adc_g0)] { | 35 | if #[cfg(adc_g0)] { |
| @@ -46,7 +46,7 @@ impl<T: Instance> super::sealed::AdcPin<T> for Temperature { | |||
| 46 | 46 | ||
| 47 | pub struct Vbat; | 47 | pub struct Vbat; |
| 48 | impl<T: Instance> AdcPin<T> for Vbat {} | 48 | impl<T: Instance> AdcPin<T> for Vbat {} |
| 49 | impl<T: Instance> super::sealed::AdcPin<T> for Vbat { | 49 | impl<T: Instance> super::SealedAdcPin<T> for Vbat { |
| 50 | fn channel(&self) -> u8 { | 50 | fn channel(&self) -> u8 { |
| 51 | cfg_if! { | 51 | cfg_if! { |
| 52 | if #[cfg(adc_g0)] { | 52 | if #[cfg(adc_g0)] { |
| @@ -65,7 +65,7 @@ cfg_if! { | |||
| 65 | if #[cfg(adc_h5)] { | 65 | if #[cfg(adc_h5)] { |
| 66 | pub struct VddCore; | 66 | pub struct VddCore; |
| 67 | impl<T: Instance> AdcPin<T> for VddCore {} | 67 | impl<T: Instance> AdcPin<T> for VddCore {} |
| 68 | impl<T: Instance> super::sealed::AdcPin<T> for VddCore { | 68 | impl<T: Instance> super::SealedAdcPin<T> for VddCore { |
| 69 | fn channel(&self) -> u8 { | 69 | fn channel(&self) -> u8 { |
| 70 | 6 | 70 | 6 |
| 71 | } | 71 | } |
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; | |||
| 35 | /// Internal voltage reference channel. | 35 | /// Internal voltage reference channel. |
| 36 | pub struct VrefInt; | 36 | pub struct VrefInt; |
| 37 | impl<T: Instance> InternalChannel<T> for VrefInt {} | 37 | impl<T: Instance> InternalChannel<T> for VrefInt {} |
| 38 | impl<T: Instance> super::sealed::InternalChannel<T> for VrefInt { | 38 | impl<T: Instance> super::SealedInternalChannel<T> for VrefInt { |
| 39 | fn channel(&self) -> u8 { | 39 | fn channel(&self) -> u8 { |
| 40 | VREF_CHANNEL | 40 | VREF_CHANNEL |
| 41 | } | 41 | } |
| @@ -44,7 +44,7 @@ impl<T: Instance> super::sealed::InternalChannel<T> for VrefInt { | |||
| 44 | /// Internal temperature channel. | 44 | /// Internal temperature channel. |
| 45 | pub struct Temperature; | 45 | pub struct Temperature; |
| 46 | impl<T: Instance> InternalChannel<T> for Temperature {} | 46 | impl<T: Instance> InternalChannel<T> for Temperature {} |
| 47 | impl<T: Instance> super::sealed::InternalChannel<T> for Temperature { | 47 | impl<T: Instance> super::SealedInternalChannel<T> for Temperature { |
| 48 | fn channel(&self) -> u8 { | 48 | fn channel(&self) -> u8 { |
| 49 | TEMP_CHANNEL | 49 | TEMP_CHANNEL |
| 50 | } | 50 | } |
| @@ -53,7 +53,7 @@ impl<T: Instance> super::sealed::InternalChannel<T> for Temperature { | |||
| 53 | /// Internal battery voltage channel. | 53 | /// Internal battery voltage channel. |
| 54 | pub struct Vbat; | 54 | pub struct Vbat; |
| 55 | impl<T: Instance> InternalChannel<T> for Vbat {} | 55 | impl<T: Instance> InternalChannel<T> for Vbat {} |
| 56 | impl<T: Instance> super::sealed::InternalChannel<T> for Vbat { | 56 | impl<T: Instance> super::SealedInternalChannel<T> for Vbat { |
| 57 | fn channel(&self) -> u8 { | 57 | fn channel(&self) -> u8 { |
| 58 | VBAT_CHANNEL | 58 | VBAT_CHANNEL |
| 59 | } | 59 | } |
| @@ -276,7 +276,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 276 | pub fn read<P>(&mut self, pin: &mut P) -> u16 | 276 | pub fn read<P>(&mut self, pin: &mut P) -> u16 |
| 277 | where | 277 | where |
| 278 | P: AdcPin<T>, | 278 | P: AdcPin<T>, |
| 279 | P: crate::gpio::sealed::Pin, | 279 | P: crate::gpio::Pin, |
| 280 | { | 280 | { |
| 281 | pin.set_as_analog(); | 281 | pin.set_as_analog(); |
| 282 | 282 | ||
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; | |||
| 7 | 7 | ||
| 8 | pub use bx::{filter, Data, ExtendedId, Fifo, Frame, Header, Id, StandardId}; | 8 | pub use bx::{filter, Data, ExtendedId, Fifo, Frame, Header, Id, StandardId}; |
| 9 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 9 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 10 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 11 | use embassy_sync::channel::Channel; | ||
| 12 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 10 | use futures::FutureExt; | 13 | use futures::FutureExt; |
| 11 | 14 | ||
| 12 | use crate::gpio::sealed::AFType; | 15 | use crate::gpio::AFType; |
| 13 | use crate::interrupt::typelevel::Interrupt; | 16 | use crate::interrupt::typelevel::Interrupt; |
| 14 | use crate::pac::can::vals::{Ide, Lec}; | 17 | use crate::pac::can::vals::{Ide, Lec}; |
| 15 | use crate::rcc::RccPeripheral; | 18 | use crate::rcc::RccPeripheral; |
| @@ -485,37 +488,30 @@ impl<'d, T: Instance> DerefMut for Can<'d, T> { | |||
| 485 | } | 488 | } |
| 486 | } | 489 | } |
| 487 | 490 | ||
| 488 | pub(crate) mod sealed { | 491 | struct State { |
| 489 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 492 | pub tx_waker: AtomicWaker, |
| 490 | use embassy_sync::channel::Channel; | 493 | pub err_waker: AtomicWaker, |
| 491 | use embassy_sync::waitqueue::AtomicWaker; | 494 | pub rx_queue: Channel<CriticalSectionRawMutex, Envelope, 32>, |
| 492 | 495 | } | |
| 493 | use super::Envelope; | ||
| 494 | |||
| 495 | pub struct State { | ||
| 496 | pub tx_waker: AtomicWaker, | ||
| 497 | pub err_waker: AtomicWaker, | ||
| 498 | pub rx_queue: Channel<CriticalSectionRawMutex, Envelope, 32>, | ||
| 499 | } | ||
| 500 | 496 | ||
| 501 | impl State { | 497 | impl State { |
| 502 | pub const fn new() -> Self { | 498 | pub const fn new() -> Self { |
| 503 | Self { | 499 | Self { |
| 504 | tx_waker: AtomicWaker::new(), | 500 | tx_waker: AtomicWaker::new(), |
| 505 | err_waker: AtomicWaker::new(), | 501 | err_waker: AtomicWaker::new(), |
| 506 | rx_queue: Channel::new(), | 502 | rx_queue: Channel::new(), |
| 507 | } | ||
| 508 | } | 503 | } |
| 509 | } | 504 | } |
| 505 | } | ||
| 510 | 506 | ||
| 511 | pub trait Instance { | 507 | trait SealedInstance { |
| 512 | fn regs() -> crate::pac::can::Can; | 508 | fn regs() -> crate::pac::can::Can; |
| 513 | fn state() -> &'static State; | 509 | fn state() -> &'static State; |
| 514 | } | ||
| 515 | } | 510 | } |
| 516 | 511 | ||
| 517 | /// CAN instance trait. | 512 | /// CAN instance trait. |
| 518 | pub trait Instance: sealed::Instance + RccPeripheral + 'static { | 513 | #[allow(private_bounds)] |
| 514 | pub trait Instance: SealedInstance + RccPeripheral + 'static { | ||
| 519 | /// TX interrupt for this instance. | 515 | /// TX interrupt for this instance. |
| 520 | type TXInterrupt: crate::interrupt::typelevel::Interrupt; | 516 | type TXInterrupt: crate::interrupt::typelevel::Interrupt; |
| 521 | /// RX0 interrupt for this instance. | 517 | /// RX0 interrupt for this instance. |
| @@ -533,14 +529,14 @@ unsafe impl<'d, T: Instance> crate::can::bx::Instance for BxcanInstance<'d, T> { | |||
| 533 | 529 | ||
| 534 | foreach_peripheral!( | 530 | foreach_peripheral!( |
| 535 | (can, $inst:ident) => { | 531 | (can, $inst:ident) => { |
| 536 | impl sealed::Instance for peripherals::$inst { | 532 | impl SealedInstance for peripherals::$inst { |
| 537 | 533 | ||
| 538 | fn regs() -> crate::pac::can::Can { | 534 | fn regs() -> crate::pac::can::Can { |
| 539 | crate::pac::$inst | 535 | crate::pac::$inst |
| 540 | } | 536 | } |
| 541 | 537 | ||
| 542 | fn state() -> &'static sealed::State { | 538 | fn state() -> &'static State { |
| 543 | static STATE: sealed::State = sealed::State::new(); | 539 | static STATE: State = State::new(); |
| 544 | &STATE | 540 | &STATE |
| 545 | } | 541 | } |
| 546 | } | 542 | } |
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 { | |||
| 325 | */ | 325 | */ |
| 326 | } | 326 | } |
| 327 | 327 | ||
| 328 | /// Disables the CAN interface and returns back the raw peripheral it was created from. | ||
| 329 | #[inline] | ||
| 330 | pub fn free(mut self) { | ||
| 331 | //self.disable_interrupts(Interrupts::all()); | ||
| 332 | |||
| 333 | //TODO check this! | ||
| 334 | self.enter_init_mode(); | ||
| 335 | self.set_power_down_mode(true); | ||
| 336 | //self.control.instance | ||
| 337 | } | ||
| 338 | |||
| 339 | /// Applies the settings of a new FdCanConfig See [`FdCanConfig`] | 328 | /// Applies the settings of a new FdCanConfig See [`FdCanConfig`] |
| 340 | #[inline] | 329 | #[inline] |
| 341 | pub fn apply_config(&mut self, config: FdCanConfig) { | 330 | pub fn apply_config(&mut self, config: FdCanConfig) { |
| @@ -419,55 +408,6 @@ impl Registers { | |||
| 419 | self.leave_init_mode(config); | 408 | self.leave_init_mode(config); |
| 420 | } | 409 | } |
| 421 | 410 | ||
| 422 | /// Moves out of ConfigMode and into InternalLoopbackMode | ||
| 423 | #[inline] | ||
| 424 | pub fn into_internal_loopback(mut self, config: FdCanConfig) { | ||
| 425 | self.set_loopback_mode(LoopbackMode::Internal); | ||
| 426 | self.leave_init_mode(config); | ||
| 427 | } | ||
| 428 | |||
| 429 | /// Moves out of ConfigMode and into ExternalLoopbackMode | ||
| 430 | #[inline] | ||
| 431 | pub fn into_external_loopback(mut self, config: FdCanConfig) { | ||
| 432 | self.set_loopback_mode(LoopbackMode::External); | ||
| 433 | self.leave_init_mode(config); | ||
| 434 | } | ||
| 435 | |||
| 436 | /// Moves out of ConfigMode and into RestrictedOperationMode | ||
| 437 | #[inline] | ||
| 438 | pub fn into_restricted(mut self, config: FdCanConfig) { | ||
| 439 | self.set_restricted_operations(true); | ||
| 440 | self.leave_init_mode(config); | ||
| 441 | } | ||
| 442 | |||
| 443 | /// Moves out of ConfigMode and into NormalOperationMode | ||
| 444 | #[inline] | ||
| 445 | pub fn into_normal(mut self, config: FdCanConfig) { | ||
| 446 | self.set_normal_operations(true); | ||
| 447 | self.leave_init_mode(config); | ||
| 448 | } | ||
| 449 | |||
| 450 | /// Moves out of ConfigMode and into BusMonitoringMode | ||
| 451 | #[inline] | ||
| 452 | pub fn into_bus_monitoring(mut self, config: FdCanConfig) { | ||
| 453 | self.set_bus_monitoring_mode(true); | ||
| 454 | self.leave_init_mode(config); | ||
| 455 | } | ||
| 456 | |||
| 457 | /// Moves out of ConfigMode and into Testmode | ||
| 458 | #[inline] | ||
| 459 | pub fn into_test_mode(mut self, config: FdCanConfig) { | ||
| 460 | self.set_test_mode(true); | ||
| 461 | self.leave_init_mode(config); | ||
| 462 | } | ||
| 463 | |||
| 464 | /// Moves out of ConfigMode and into PoweredDownmode | ||
| 465 | #[inline] | ||
| 466 | pub fn into_powered_down(mut self, config: FdCanConfig) { | ||
| 467 | self.set_power_down_mode(true); | ||
| 468 | self.leave_init_mode(config); | ||
| 469 | } | ||
| 470 | |||
| 471 | /// Configures the bit timings. | 411 | /// Configures the bit timings. |
| 472 | /// | 412 | /// |
| 473 | /// You can use <http://www.bittiming.can-wiki.info/> to calculate the `btr` parameter. Enter | 413 | /// You can use <http://www.bittiming.can-wiki.info/> to calculate the `btr` parameter. Enter |
| @@ -565,6 +505,7 @@ impl Registers { | |||
| 565 | 505 | ||
| 566 | /// Configures and resets the timestamp counter | 506 | /// Configures and resets the timestamp counter |
| 567 | #[inline] | 507 | #[inline] |
| 508 | #[allow(unused)] | ||
| 568 | pub fn set_timestamp_counter_source(&mut self, select: TimestampSource) { | 509 | pub fn set_timestamp_counter_source(&mut self, select: TimestampSource) { |
| 569 | #[cfg(stm32h7)] | 510 | #[cfg(stm32h7)] |
| 570 | let (tcp, tss) = match select { | 511 | 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; | |||
| 5 | 5 | ||
| 6 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 6 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 7 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 7 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 8 | use embassy_sync::channel::Channel; | 8 | use embassy_sync::channel::{Channel, DynamicReceiver, DynamicSender}; |
| 9 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 9 | 10 | ||
| 10 | use crate::can::fd::peripheral::Registers; | 11 | use crate::can::fd::peripheral::Registers; |
| 11 | use crate::gpio::sealed::AFType; | 12 | use crate::gpio::AFType; |
| 12 | use crate::interrupt::typelevel::Interrupt; | 13 | use crate::interrupt::typelevel::Interrupt; |
| 13 | use crate::rcc::RccPeripheral; | 14 | use crate::rcc::RccPeripheral; |
| 14 | use crate::{interrupt, peripherals, Peripheral}; | 15 | use crate::{interrupt, peripherals, Peripheral}; |
| @@ -53,8 +54,8 @@ impl<T: Instance> interrupt::typelevel::Handler<T::IT0Interrupt> for IT0Interrup | |||
| 53 | } | 54 | } |
| 54 | 55 | ||
| 55 | match &T::state().tx_mode { | 56 | match &T::state().tx_mode { |
| 56 | sealed::TxMode::NonBuffered(waker) => waker.wake(), | 57 | TxMode::NonBuffered(waker) => waker.wake(), |
| 57 | sealed::TxMode::ClassicBuffered(buf) => { | 58 | TxMode::ClassicBuffered(buf) => { |
| 58 | if !T::registers().tx_queue_is_full() { | 59 | if !T::registers().tx_queue_is_full() { |
| 59 | match buf.tx_receiver.try_receive() { | 60 | match buf.tx_receiver.try_receive() { |
| 60 | Ok(frame) => { | 61 | Ok(frame) => { |
| @@ -64,7 +65,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::IT0Interrupt> for IT0Interrup | |||
| 64 | } | 65 | } |
| 65 | } | 66 | } |
| 66 | } | 67 | } |
| 67 | sealed::TxMode::FdBuffered(buf) => { | 68 | TxMode::FdBuffered(buf) => { |
| 68 | if !T::registers().tx_queue_is_full() { | 69 | if !T::registers().tx_queue_is_full() { |
| 69 | match buf.tx_receiver.try_receive() { | 70 | match buf.tx_receiver.try_receive() { |
| 70 | Ok(frame) => { | 71 | Ok(frame) => { |
| @@ -467,14 +468,14 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | |||
| 467 | fn setup(self) -> Self { | 468 | fn setup(self) -> Self { |
| 468 | // We don't want interrupts being processed while we change modes. | 469 | // We don't want interrupts being processed while we change modes. |
| 469 | critical_section::with(|_| unsafe { | 470 | critical_section::with(|_| unsafe { |
| 470 | let rx_inner = sealed::ClassicBufferedRxInner { | 471 | let rx_inner = ClassicBufferedRxInner { |
| 471 | rx_sender: self.rx_buf.sender().into(), | 472 | rx_sender: self.rx_buf.sender().into(), |
| 472 | }; | 473 | }; |
| 473 | let tx_inner = sealed::ClassicBufferedTxInner { | 474 | let tx_inner = ClassicBufferedTxInner { |
| 474 | tx_receiver: self.tx_buf.receiver().into(), | 475 | tx_receiver: self.tx_buf.receiver().into(), |
| 475 | }; | 476 | }; |
| 476 | T::mut_state().rx_mode = sealed::RxMode::ClassicBuffered(rx_inner); | 477 | T::mut_state().rx_mode = RxMode::ClassicBuffered(rx_inner); |
| 477 | T::mut_state().tx_mode = sealed::TxMode::ClassicBuffered(tx_inner); | 478 | T::mut_state().tx_mode = TxMode::ClassicBuffered(tx_inner); |
| 478 | }); | 479 | }); |
| 479 | self | 480 | self |
| 480 | } | 481 | } |
| @@ -509,8 +510,8 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Dr | |||
| 509 | { | 510 | { |
| 510 | fn drop(&mut self) { | 511 | fn drop(&mut self) { |
| 511 | critical_section::with(|_| unsafe { | 512 | critical_section::with(|_| unsafe { |
| 512 | T::mut_state().rx_mode = sealed::RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | 513 | T::mut_state().rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); |
| 513 | T::mut_state().tx_mode = sealed::TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | 514 | T::mut_state().tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); |
| 514 | }); | 515 | }); |
| 515 | } | 516 | } |
| 516 | } | 517 | } |
| @@ -585,14 +586,14 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | |||
| 585 | fn setup(self) -> Self { | 586 | fn setup(self) -> Self { |
| 586 | // We don't want interrupts being processed while we change modes. | 587 | // We don't want interrupts being processed while we change modes. |
| 587 | critical_section::with(|_| unsafe { | 588 | critical_section::with(|_| unsafe { |
| 588 | let rx_inner = sealed::FdBufferedRxInner { | 589 | let rx_inner = FdBufferedRxInner { |
| 589 | rx_sender: self.rx_buf.sender().into(), | 590 | rx_sender: self.rx_buf.sender().into(), |
| 590 | }; | 591 | }; |
| 591 | let tx_inner = sealed::FdBufferedTxInner { | 592 | let tx_inner = FdBufferedTxInner { |
| 592 | tx_receiver: self.tx_buf.receiver().into(), | 593 | tx_receiver: self.tx_buf.receiver().into(), |
| 593 | }; | 594 | }; |
| 594 | T::mut_state().rx_mode = sealed::RxMode::FdBuffered(rx_inner); | 595 | T::mut_state().rx_mode = RxMode::FdBuffered(rx_inner); |
| 595 | T::mut_state().tx_mode = sealed::TxMode::FdBuffered(tx_inner); | 596 | T::mut_state().tx_mode = TxMode::FdBuffered(tx_inner); |
| 596 | }); | 597 | }); |
| 597 | self | 598 | self |
| 598 | } | 599 | } |
| @@ -627,8 +628,8 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Dr | |||
| 627 | { | 628 | { |
| 628 | fn drop(&mut self) { | 629 | fn drop(&mut self) { |
| 629 | critical_section::with(|_| unsafe { | 630 | critical_section::with(|_| unsafe { |
| 630 | T::mut_state().rx_mode = sealed::RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | 631 | T::mut_state().rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); |
| 631 | T::mut_state().tx_mode = sealed::TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | 632 | T::mut_state().tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); |
| 632 | }); | 633 | }); |
| 633 | } | 634 | } |
| 634 | } | 635 | } |
| @@ -677,192 +678,180 @@ impl<'c, 'd, T: Instance> FdcanRx<'d, T> { | |||
| 677 | } | 678 | } |
| 678 | } | 679 | } |
| 679 | 680 | ||
| 680 | pub(crate) mod sealed { | 681 | struct ClassicBufferedRxInner { |
| 681 | use core::future::poll_fn; | 682 | rx_sender: DynamicSender<'static, Result<(ClassicFrame, Timestamp), BusError>>, |
| 682 | use core::task::Poll; | 683 | } |
| 683 | 684 | struct ClassicBufferedTxInner { | |
| 684 | use embassy_sync::channel::{DynamicReceiver, DynamicSender}; | 685 | tx_receiver: DynamicReceiver<'static, ClassicFrame>, |
| 685 | use embassy_sync::waitqueue::AtomicWaker; | 686 | } |
| 686 | |||
| 687 | use super::CanHeader; | ||
| 688 | use crate::can::_version::{BusError, Timestamp}; | ||
| 689 | use crate::can::frame::{ClassicFrame, FdFrame}; | ||
| 690 | |||
| 691 | pub struct ClassicBufferedRxInner { | ||
| 692 | pub rx_sender: DynamicSender<'static, Result<(ClassicFrame, Timestamp), BusError>>, | ||
| 693 | } | ||
| 694 | pub struct ClassicBufferedTxInner { | ||
| 695 | pub tx_receiver: DynamicReceiver<'static, ClassicFrame>, | ||
| 696 | } | ||
| 697 | 687 | ||
| 698 | pub struct FdBufferedRxInner { | 688 | struct FdBufferedRxInner { |
| 699 | pub rx_sender: DynamicSender<'static, Result<(FdFrame, Timestamp), BusError>>, | 689 | rx_sender: DynamicSender<'static, Result<(FdFrame, Timestamp), BusError>>, |
| 700 | } | 690 | } |
| 701 | pub struct FdBufferedTxInner { | 691 | struct FdBufferedTxInner { |
| 702 | pub tx_receiver: DynamicReceiver<'static, FdFrame>, | 692 | tx_receiver: DynamicReceiver<'static, FdFrame>, |
| 703 | } | 693 | } |
| 704 | 694 | ||
| 705 | pub enum RxMode { | 695 | enum RxMode { |
| 706 | NonBuffered(AtomicWaker), | 696 | NonBuffered(AtomicWaker), |
| 707 | ClassicBuffered(ClassicBufferedRxInner), | 697 | ClassicBuffered(ClassicBufferedRxInner), |
| 708 | FdBuffered(FdBufferedRxInner), | 698 | FdBuffered(FdBufferedRxInner), |
| 709 | } | 699 | } |
| 710 | 700 | ||
| 711 | impl RxMode { | 701 | impl RxMode { |
| 712 | pub fn register(&self, arg: &core::task::Waker) { | 702 | fn register(&self, arg: &core::task::Waker) { |
| 713 | match self { | 703 | match self { |
| 714 | RxMode::NonBuffered(waker) => waker.register(arg), | 704 | RxMode::NonBuffered(waker) => waker.register(arg), |
| 715 | _ => { | 705 | _ => { |
| 716 | panic!("Bad Mode") | 706 | panic!("Bad Mode") |
| 717 | } | ||
| 718 | } | 707 | } |
| 719 | } | 708 | } |
| 709 | } | ||
| 720 | 710 | ||
| 721 | pub fn on_interrupt<T: Instance>(&self, fifonr: usize) { | 711 | fn on_interrupt<T: Instance>(&self, fifonr: usize) { |
| 722 | T::regs().ir().write(|w| w.set_rfn(fifonr, true)); | 712 | T::regs().ir().write(|w| w.set_rfn(fifonr, true)); |
| 723 | match self { | 713 | match self { |
| 724 | RxMode::NonBuffered(waker) => { | 714 | RxMode::NonBuffered(waker) => { |
| 725 | waker.wake(); | 715 | waker.wake(); |
| 726 | } | 716 | } |
| 727 | RxMode::ClassicBuffered(buf) => { | 717 | RxMode::ClassicBuffered(buf) => { |
| 728 | if let Some(result) = self.read::<T, _>() { | 718 | if let Some(result) = self.read::<T, _>() { |
| 729 | let _ = buf.rx_sender.try_send(result); | 719 | let _ = buf.rx_sender.try_send(result); |
| 730 | } | ||
| 731 | } | ||
| 732 | RxMode::FdBuffered(buf) => { | ||
| 733 | if let Some(result) = self.read::<T, _>() { | ||
| 734 | let _ = buf.rx_sender.try_send(result); | ||
| 735 | } | ||
| 736 | } | 720 | } |
| 737 | } | 721 | } |
| 738 | } | 722 | RxMode::FdBuffered(buf) => { |
| 739 | 723 | if let Some(result) = self.read::<T, _>() { | |
| 740 | fn read<T: Instance, F: CanHeader>(&self) -> Option<Result<(F, Timestamp), BusError>> { | 724 | let _ = buf.rx_sender.try_send(result); |
| 741 | if let Some((msg, ts)) = T::registers().read(0) { | 725 | } |
| 742 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); | ||
| 743 | Some(Ok((msg, ts))) | ||
| 744 | } else if let Some((msg, ts)) = T::registers().read(1) { | ||
| 745 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); | ||
| 746 | Some(Ok((msg, ts))) | ||
| 747 | } else if let Some(err) = T::registers().curr_error() { | ||
| 748 | // TODO: this is probably wrong | ||
| 749 | Some(Err(err)) | ||
| 750 | } else { | ||
| 751 | None | ||
| 752 | } | 726 | } |
| 753 | } | 727 | } |
| 728 | } | ||
| 754 | 729 | ||
| 755 | async fn read_async<T: Instance, F: CanHeader>(&self) -> Result<(F, Timestamp), BusError> { | 730 | fn read<T: Instance, F: CanHeader>(&self) -> Option<Result<(F, Timestamp), BusError>> { |
| 756 | poll_fn(|cx| { | 731 | if let Some((msg, ts)) = T::registers().read(0) { |
| 757 | T::state().err_waker.register(cx.waker()); | 732 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); |
| 758 | self.register(cx.waker()); | 733 | Some(Ok((msg, ts))) |
| 759 | match self.read::<T, _>() { | 734 | } else if let Some((msg, ts)) = T::registers().read(1) { |
| 760 | Some(result) => Poll::Ready(result), | 735 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); |
| 761 | None => Poll::Pending, | 736 | Some(Ok((msg, ts))) |
| 762 | } | 737 | } else if let Some(err) = T::registers().curr_error() { |
| 763 | }) | 738 | // TODO: this is probably wrong |
| 764 | .await | 739 | Some(Err(err)) |
| 740 | } else { | ||
| 741 | None | ||
| 765 | } | 742 | } |
| 743 | } | ||
| 766 | 744 | ||
| 767 | pub async fn read_classic<T: Instance>(&self) -> Result<(ClassicFrame, Timestamp), BusError> { | 745 | async fn read_async<T: Instance, F: CanHeader>(&self) -> Result<(F, Timestamp), BusError> { |
| 768 | self.read_async::<T, _>().await | 746 | poll_fn(|cx| { |
| 769 | } | 747 | T::state().err_waker.register(cx.waker()); |
| 748 | self.register(cx.waker()); | ||
| 749 | match self.read::<T, _>() { | ||
| 750 | Some(result) => Poll::Ready(result), | ||
| 751 | None => Poll::Pending, | ||
| 752 | } | ||
| 753 | }) | ||
| 754 | .await | ||
| 755 | } | ||
| 770 | 756 | ||
| 771 | pub async fn read_fd<T: Instance>(&self) -> Result<(FdFrame, Timestamp), BusError> { | 757 | async fn read_classic<T: Instance>(&self) -> Result<(ClassicFrame, Timestamp), BusError> { |
| 772 | self.read_async::<T, _>().await | 758 | self.read_async::<T, _>().await |
| 773 | } | ||
| 774 | } | 759 | } |
| 775 | 760 | ||
| 776 | pub enum TxMode { | 761 | async fn read_fd<T: Instance>(&self) -> Result<(FdFrame, Timestamp), BusError> { |
| 777 | NonBuffered(AtomicWaker), | 762 | self.read_async::<T, _>().await |
| 778 | ClassicBuffered(ClassicBufferedTxInner), | ||
| 779 | FdBuffered(FdBufferedTxInner), | ||
| 780 | } | 763 | } |
| 764 | } | ||
| 781 | 765 | ||
| 782 | impl TxMode { | 766 | enum TxMode { |
| 783 | pub fn register(&self, arg: &core::task::Waker) { | 767 | NonBuffered(AtomicWaker), |
| 784 | match self { | 768 | ClassicBuffered(ClassicBufferedTxInner), |
| 785 | TxMode::NonBuffered(waker) => { | 769 | FdBuffered(FdBufferedTxInner), |
| 786 | waker.register(arg); | 770 | } |
| 787 | } | 771 | |
| 788 | _ => { | 772 | impl TxMode { |
| 789 | panic!("Bad mode"); | 773 | fn register(&self, arg: &core::task::Waker) { |
| 790 | } | 774 | match self { |
| 775 | TxMode::NonBuffered(waker) => { | ||
| 776 | waker.register(arg); | ||
| 777 | } | ||
| 778 | _ => { | ||
| 779 | panic!("Bad mode"); | ||
| 791 | } | 780 | } |
| 792 | } | 781 | } |
| 782 | } | ||
| 793 | 783 | ||
| 794 | /// Queues the message to be sent but exerts backpressure. If a lower-priority | 784 | /// Queues the message to be sent but exerts backpressure. If a lower-priority |
| 795 | /// frame is dropped from the mailbox, it is returned. If no lower-priority frames | 785 | /// frame is dropped from the mailbox, it is returned. If no lower-priority frames |
| 796 | /// can be replaced, this call asynchronously waits for a frame to be successfully | 786 | /// can be replaced, this call asynchronously waits for a frame to be successfully |
| 797 | /// transmitted, then tries again. | 787 | /// transmitted, then tries again. |
| 798 | async fn write_generic<T: Instance, F: embedded_can::Frame + CanHeader>(&self, frame: &F) -> Option<F> { | 788 | async fn write_generic<T: Instance, F: embedded_can::Frame + CanHeader>(&self, frame: &F) -> Option<F> { |
| 799 | poll_fn(|cx| { | 789 | poll_fn(|cx| { |
| 800 | self.register(cx.waker()); | 790 | self.register(cx.waker()); |
| 801 | 791 | ||
| 802 | if let Ok(dropped) = T::registers().write(frame) { | 792 | if let Ok(dropped) = T::registers().write(frame) { |
| 803 | return Poll::Ready(dropped); | 793 | return Poll::Ready(dropped); |
| 804 | } | 794 | } |
| 805 | 795 | ||
| 806 | // Couldn't replace any lower priority frames. Need to wait for some mailboxes | 796 | // Couldn't replace any lower priority frames. Need to wait for some mailboxes |
| 807 | // to clear. | 797 | // to clear. |
| 808 | Poll::Pending | 798 | Poll::Pending |
| 809 | }) | 799 | }) |
| 810 | .await | 800 | .await |
| 811 | } | 801 | } |
| 812 | 802 | ||
| 813 | /// Queues the message to be sent but exerts backpressure. If a lower-priority | 803 | /// Queues the message to be sent but exerts backpressure. If a lower-priority |
| 814 | /// frame is dropped from the mailbox, it is returned. If no lower-priority frames | 804 | /// frame is dropped from the mailbox, it is returned. If no lower-priority frames |
| 815 | /// can be replaced, this call asynchronously waits for a frame to be successfully | 805 | /// can be replaced, this call asynchronously waits for a frame to be successfully |
| 816 | /// transmitted, then tries again. | 806 | /// transmitted, then tries again. |
| 817 | pub async fn write<T: Instance>(&self, frame: &ClassicFrame) -> Option<ClassicFrame> { | 807 | async fn write<T: Instance>(&self, frame: &ClassicFrame) -> Option<ClassicFrame> { |
| 818 | self.write_generic::<T, _>(frame).await | 808 | self.write_generic::<T, _>(frame).await |
| 819 | } | 809 | } |
| 820 | 810 | ||
| 821 | /// Queues the message to be sent but exerts backpressure. If a lower-priority | 811 | /// Queues the message to be sent but exerts backpressure. If a lower-priority |
| 822 | /// frame is dropped from the mailbox, it is returned. If no lower-priority frames | 812 | /// frame is dropped from the mailbox, it is returned. If no lower-priority frames |
| 823 | /// can be replaced, this call asynchronously waits for a frame to be successfully | 813 | /// can be replaced, this call asynchronously waits for a frame to be successfully |
| 824 | /// transmitted, then tries again. | 814 | /// transmitted, then tries again. |
| 825 | pub async fn write_fd<T: Instance>(&self, frame: &FdFrame) -> Option<FdFrame> { | 815 | async fn write_fd<T: Instance>(&self, frame: &FdFrame) -> Option<FdFrame> { |
| 826 | self.write_generic::<T, _>(frame).await | 816 | self.write_generic::<T, _>(frame).await |
| 827 | } | ||
| 828 | } | 817 | } |
| 818 | } | ||
| 829 | 819 | ||
| 830 | pub struct State { | 820 | struct State { |
| 831 | pub rx_mode: RxMode, | 821 | pub rx_mode: RxMode, |
| 832 | pub tx_mode: TxMode, | 822 | pub tx_mode: TxMode, |
| 833 | pub ns_per_timer_tick: u64, | 823 | pub ns_per_timer_tick: u64, |
| 834 | 824 | ||
| 835 | pub err_waker: AtomicWaker, | 825 | pub err_waker: AtomicWaker, |
| 836 | } | 826 | } |
| 837 | 827 | ||
| 838 | impl State { | 828 | impl State { |
| 839 | pub const fn new() -> Self { | 829 | const fn new() -> Self { |
| 840 | Self { | 830 | Self { |
| 841 | rx_mode: RxMode::NonBuffered(AtomicWaker::new()), | 831 | rx_mode: RxMode::NonBuffered(AtomicWaker::new()), |
| 842 | tx_mode: TxMode::NonBuffered(AtomicWaker::new()), | 832 | tx_mode: TxMode::NonBuffered(AtomicWaker::new()), |
| 843 | ns_per_timer_tick: 0, | 833 | ns_per_timer_tick: 0, |
| 844 | err_waker: AtomicWaker::new(), | 834 | err_waker: AtomicWaker::new(), |
| 845 | } | ||
| 846 | } | 835 | } |
| 847 | } | 836 | } |
| 837 | } | ||
| 848 | 838 | ||
| 849 | pub trait Instance { | 839 | trait SealedInstance { |
| 850 | const MSG_RAM_OFFSET: usize; | 840 | const MSG_RAM_OFFSET: usize; |
| 851 | 841 | ||
| 852 | fn regs() -> &'static crate::pac::can::Fdcan; | 842 | fn regs() -> &'static crate::pac::can::Fdcan; |
| 853 | fn registers() -> crate::can::fd::peripheral::Registers; | 843 | fn registers() -> crate::can::fd::peripheral::Registers; |
| 854 | fn ram() -> &'static crate::pac::fdcanram::Fdcanram; | 844 | fn state() -> &'static State; |
| 855 | fn state() -> &'static State; | 845 | unsafe fn mut_state() -> &'static mut State; |
| 856 | unsafe fn mut_state() -> &'static mut State; | 846 | fn calc_timestamp(ns_per_timer_tick: u64, ts_val: u16) -> Timestamp; |
| 857 | fn calc_timestamp(ns_per_timer_tick: u64, ts_val: u16) -> Timestamp; | ||
| 858 | } | ||
| 859 | } | 847 | } |
| 860 | 848 | ||
| 861 | /// Instance trait | 849 | /// Instance trait |
| 862 | pub trait Instance: sealed::Instance + RccPeripheral + 'static { | 850 | #[allow(private_bounds)] |
| 851 | pub trait Instance: SealedInstance + RccPeripheral + 'static { | ||
| 863 | /// Interrupt 0 | 852 | /// Interrupt 0 |
| 864 | type IT0Interrupt: crate::interrupt::typelevel::Interrupt; | 853 | type IT0Interrupt: crate::interrupt::typelevel::Interrupt; |
| 865 | /// Interrupt 0 | 854 | /// Interrupt 1 |
| 866 | type IT1Interrupt: crate::interrupt::typelevel::Interrupt; | 855 | type IT1Interrupt: crate::interrupt::typelevel::Interrupt; |
| 867 | } | 856 | } |
| 868 | 857 | ||
| @@ -871,7 +860,7 @@ pub struct FdcanInstance<'a, T>(PeripheralRef<'a, T>); | |||
| 871 | 860 | ||
| 872 | macro_rules! impl_fdcan { | 861 | macro_rules! impl_fdcan { |
| 873 | ($inst:ident, $msg_ram_inst:ident, $msg_ram_offset:literal) => { | 862 | ($inst:ident, $msg_ram_inst:ident, $msg_ram_offset:literal) => { |
| 874 | impl sealed::Instance for peripherals::$inst { | 863 | impl SealedInstance for peripherals::$inst { |
| 875 | const MSG_RAM_OFFSET: usize = $msg_ram_offset; | 864 | const MSG_RAM_OFFSET: usize = $msg_ram_offset; |
| 876 | 865 | ||
| 877 | fn regs() -> &'static crate::pac::can::Fdcan { | 866 | fn regs() -> &'static crate::pac::can::Fdcan { |
| @@ -880,14 +869,11 @@ macro_rules! impl_fdcan { | |||
| 880 | fn registers() -> Registers { | 869 | fn registers() -> Registers { |
| 881 | Registers{regs: &crate::pac::$inst, msgram: &crate::pac::$msg_ram_inst, msg_ram_offset: Self::MSG_RAM_OFFSET} | 870 | Registers{regs: &crate::pac::$inst, msgram: &crate::pac::$msg_ram_inst, msg_ram_offset: Self::MSG_RAM_OFFSET} |
| 882 | } | 871 | } |
| 883 | fn ram() -> &'static crate::pac::fdcanram::Fdcanram { | 872 | unsafe fn mut_state() -> &'static mut State { |
| 884 | &crate::pac::$msg_ram_inst | 873 | static mut STATE: State = State::new(); |
| 885 | } | ||
| 886 | unsafe fn mut_state() -> &'static mut sealed::State { | ||
| 887 | static mut STATE: sealed::State = sealed::State::new(); | ||
| 888 | &mut *core::ptr::addr_of_mut!(STATE) | 874 | &mut *core::ptr::addr_of_mut!(STATE) |
| 889 | } | 875 | } |
| 890 | fn state() -> &'static sealed::State { | 876 | fn state() -> &'static State { |
| 891 | unsafe { peripherals::$inst::mut_state() } | 877 | unsafe { peripherals::$inst::mut_state() } |
| 892 | } | 878 | } |
| 893 | 879 | ||
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}; | |||
| 2 | 2 | ||
| 3 | use crate::pac::CRC as PAC_CRC; | 3 | use crate::pac::CRC as PAC_CRC; |
| 4 | use crate::peripherals::CRC; | 4 | use crate::peripherals::CRC; |
| 5 | use crate::rcc::sealed::RccPeripheral; | 5 | use crate::rcc::SealedRccPeripheral; |
| 6 | use crate::Peripheral; | 6 | use crate::Peripheral; |
| 7 | 7 | ||
| 8 | /// CRC driver. | 8 | /// 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}; | |||
| 3 | use crate::pac::crc::vals; | 3 | use crate::pac::crc::vals; |
| 4 | use crate::pac::CRC as PAC_CRC; | 4 | use crate::pac::CRC as PAC_CRC; |
| 5 | use crate::peripherals::CRC; | 5 | use crate::peripherals::CRC; |
| 6 | use crate::rcc::sealed::RccPeripheral; | 6 | use crate::rcc::SealedRccPeripheral; |
| 7 | use crate::Peripheral; | 7 | use crate::Peripheral; |
| 8 | 8 | ||
| 9 | /// CRC driver. | 9 | /// 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> { | |||
| 1885 | } | 1885 | } |
| 1886 | } | 1886 | } |
| 1887 | 1887 | ||
| 1888 | pub(crate) mod sealed { | 1888 | trait SealedInstance { |
| 1889 | use super::*; | 1889 | fn regs() -> pac::cryp::Cryp; |
| 1890 | |||
| 1891 | pub trait Instance { | ||
| 1892 | fn regs() -> pac::cryp::Cryp; | ||
| 1893 | } | ||
| 1894 | } | 1890 | } |
| 1895 | 1891 | ||
| 1896 | /// CRYP instance trait. | 1892 | /// CRYP instance trait. |
| 1897 | pub trait Instance: sealed::Instance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send { | 1893 | #[allow(private_bounds)] |
| 1894 | pub trait Instance: SealedInstance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send { | ||
| 1898 | /// Interrupt for this CRYP instance. | 1895 | /// Interrupt for this CRYP instance. |
| 1899 | type Interrupt: interrupt::typelevel::Interrupt; | 1896 | type Interrupt: interrupt::typelevel::Interrupt; |
| 1900 | } | 1897 | } |
| @@ -1905,7 +1902,7 @@ foreach_interrupt!( | |||
| 1905 | type Interrupt = crate::interrupt::typelevel::$irq; | 1902 | type Interrupt = crate::interrupt::typelevel::$irq; |
| 1906 | } | 1903 | } |
| 1907 | 1904 | ||
| 1908 | impl sealed::Instance for peripherals::$inst { | 1905 | impl SealedInstance for peripherals::$inst { |
| 1909 | fn regs() -> crate::pac::cryp::Cryp { | 1906 | fn regs() -> crate::pac::cryp::Cryp { |
| 1910 | crate::pac::$inst | 1907 | crate::pac::$inst |
| 1911 | } | 1908 | } |
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> { | |||
| 127 | pub fn new( | 127 | pub fn new( |
| 128 | _peri: impl Peripheral<P = T> + 'd, | 128 | _peri: impl Peripheral<P = T> + 'd, |
| 129 | dma: impl Peripheral<P = DMA> + 'd, | 129 | dma: impl Peripheral<P = DMA> + 'd, |
| 130 | pin: impl Peripheral<P = impl DacPin<T, N> + crate::gpio::sealed::Pin> + 'd, | 130 | pin: impl Peripheral<P = impl DacPin<T, N> + crate::gpio::Pin> + 'd, |
| 131 | ) -> Self { | 131 | ) -> Self { |
| 132 | into_ref!(dma, pin); | 132 | into_ref!(dma, pin); |
| 133 | pin.set_as_analog(); | 133 | pin.set_as_analog(); |
| @@ -392,8 +392,8 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { | |||
| 392 | _peri: impl Peripheral<P = T> + 'd, | 392 | _peri: impl Peripheral<P = T> + 'd, |
| 393 | dma_ch1: impl Peripheral<P = DMACh1> + 'd, | 393 | dma_ch1: impl Peripheral<P = DMACh1> + 'd, |
| 394 | dma_ch2: impl Peripheral<P = DMACh2> + 'd, | 394 | dma_ch2: impl Peripheral<P = DMACh2> + 'd, |
| 395 | pin_ch1: impl Peripheral<P = impl DacPin<T, 1> + crate::gpio::sealed::Pin> + 'd, | 395 | pin_ch1: impl Peripheral<P = impl DacPin<T, 1> + crate::gpio::Pin> + 'd, |
| 396 | pin_ch2: impl Peripheral<P = impl DacPin<T, 2> + crate::gpio::sealed::Pin> + 'd, | 396 | pin_ch2: impl Peripheral<P = impl DacPin<T, 2> + crate::gpio::Pin> + 'd, |
| 397 | ) -> Self { | 397 | ) -> Self { |
| 398 | into_ref!(dma_ch1, dma_ch2, pin_ch1, pin_ch2); | 398 | into_ref!(dma_ch1, dma_ch2, pin_ch1, pin_ch2); |
| 399 | pin_ch1.set_as_analog(); | 399 | pin_ch1.set_as_analog(); |
| @@ -488,14 +488,13 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { | |||
| 488 | } | 488 | } |
| 489 | } | 489 | } |
| 490 | 490 | ||
| 491 | pub(crate) mod sealed { | 491 | trait SealedInstance { |
| 492 | pub trait Instance { | 492 | fn regs() -> &'static crate::pac::dac::Dac; |
| 493 | fn regs() -> &'static crate::pac::dac::Dac; | ||
| 494 | } | ||
| 495 | } | 493 | } |
| 496 | 494 | ||
| 497 | /// DAC instance. | 495 | /// DAC instance. |
| 498 | pub trait Instance: sealed::Instance + RccPeripheral + 'static {} | 496 | #[allow(private_bounds)] |
| 497 | pub trait Instance: SealedInstance + RccPeripheral + 'static {} | ||
| 499 | dma_trait!(DacDma1, Instance); | 498 | dma_trait!(DacDma1, Instance); |
| 500 | dma_trait!(DacDma2, Instance); | 499 | dma_trait!(DacDma2, Instance); |
| 501 | 500 | ||
| @@ -504,7 +503,7 @@ pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin + 'static {} | |||
| 504 | 503 | ||
| 505 | foreach_peripheral!( | 504 | foreach_peripheral!( |
| 506 | (dac, $inst:ident) => { | 505 | (dac, $inst:ident) => { |
| 507 | impl crate::dac::sealed::Instance for peripherals::$inst { | 506 | impl crate::dac::SealedInstance for peripherals::$inst { |
| 508 | fn regs() -> &'static crate::pac::dac::Dac { | 507 | fn regs() -> &'static crate::pac::dac::Dac { |
| 509 | &crate::pac::$inst | 508 | &crate::pac::$inst |
| 510 | } | 509 | } |
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}; | |||
| 7 | use embassy_sync::waitqueue::AtomicWaker; | 7 | use embassy_sync::waitqueue::AtomicWaker; |
| 8 | 8 | ||
| 9 | use crate::dma::Transfer; | 9 | use crate::dma::Transfer; |
| 10 | use crate::gpio::sealed::AFType; | 10 | use crate::gpio::{AFType, Speed}; |
| 11 | use crate::gpio::Speed; | ||
| 12 | use crate::interrupt::typelevel::Interrupt; | 11 | use crate::interrupt::typelevel::Interrupt; |
| 13 | use crate::{interrupt, Peripheral}; | 12 | use crate::{interrupt, Peripheral}; |
| 14 | 13 | ||
| @@ -431,14 +430,13 @@ where | |||
| 431 | } | 430 | } |
| 432 | } | 431 | } |
| 433 | 432 | ||
| 434 | mod sealed { | 433 | trait SealedInstance: crate::rcc::RccPeripheral { |
| 435 | pub trait Instance: crate::rcc::RccPeripheral { | 434 | fn regs(&self) -> crate::pac::dcmi::Dcmi; |
| 436 | fn regs(&self) -> crate::pac::dcmi::Dcmi; | ||
| 437 | } | ||
| 438 | } | 435 | } |
| 439 | 436 | ||
| 440 | /// DCMI instance. | 437 | /// DCMI instance. |
| 441 | pub trait Instance: sealed::Instance + 'static { | 438 | #[allow(private_bounds)] |
| 439 | pub trait Instance: SealedInstance + 'static { | ||
| 442 | /// Interrupt for this instance. | 440 | /// Interrupt for this instance. |
| 443 | type Interrupt: interrupt::typelevel::Interrupt; | 441 | type Interrupt: interrupt::typelevel::Interrupt; |
| 444 | } | 442 | } |
| @@ -465,7 +463,7 @@ pin_trait!(PixClkPin, Instance); | |||
| 465 | #[allow(unused)] | 463 | #[allow(unused)] |
| 466 | macro_rules! impl_peripheral { | 464 | macro_rules! impl_peripheral { |
| 467 | ($inst:ident, $irq:ident) => { | 465 | ($inst:ident, $irq:ident) => { |
| 468 | impl sealed::Instance for crate::peripherals::$inst { | 466 | impl SealedInstance for crate::peripherals::$inst { |
| 469 | fn regs(&self) -> crate::pac::dcmi::Dcmi { | 467 | fn regs(&self) -> crate::pac::dcmi::Dcmi { |
| 470 | crate::pac::$inst | 468 | crate::pac::$inst |
| 471 | } | 469 | } |
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) { | |||
| 19 | }); | 19 | }); |
| 20 | } | 20 | } |
| 21 | 21 | ||
| 22 | pub(crate) mod dmamux_sealed { | 22 | pub(crate) trait SealedMuxChannel {} |
| 23 | pub trait MuxChannel {} | ||
| 24 | } | ||
| 25 | 23 | ||
| 26 | /// DMAMUX1 instance. | 24 | /// DMAMUX1 instance. |
| 27 | pub struct DMAMUX1; | 25 | pub struct DMAMUX1; |
| @@ -30,14 +28,15 @@ pub struct DMAMUX1; | |||
| 30 | pub struct DMAMUX2; | 28 | pub struct DMAMUX2; |
| 31 | 29 | ||
| 32 | /// DMAMUX channel trait. | 30 | /// DMAMUX channel trait. |
| 33 | pub trait MuxChannel: dmamux_sealed::MuxChannel { | 31 | #[allow(private_bounds)] |
| 32 | pub trait MuxChannel: SealedMuxChannel { | ||
| 34 | /// DMAMUX instance this channel is on. | 33 | /// DMAMUX instance this channel is on. |
| 35 | type Mux; | 34 | type Mux; |
| 36 | } | 35 | } |
| 37 | 36 | ||
| 38 | macro_rules! dmamux_channel_impl { | 37 | macro_rules! dmamux_channel_impl { |
| 39 | ($channel_peri:ident, $dmamux:ident) => { | 38 | ($channel_peri:ident, $dmamux:ident) => { |
| 40 | impl crate::dma::dmamux_sealed::MuxChannel for crate::peripherals::$channel_peri {} | 39 | impl crate::dma::SealedMuxChannel for crate::peripherals::$channel_peri {} |
| 41 | impl crate::dma::MuxChannel for crate::peripherals::$channel_peri { | 40 | impl crate::dma::MuxChannel for crate::peripherals::$channel_peri { |
| 42 | type Mux = crate::dma::$dmamux; | 41 | type Mux = crate::dma::$dmamux; |
| 43 | } | 42 | } |
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; | |||
| 39 | #[cfg(not(any(dma_v2, bdma_v2, gpdma, dmamux)))] | 39 | #[cfg(not(any(dma_v2, bdma_v2, gpdma, dmamux)))] |
| 40 | pub type Request = (); | 40 | pub type Request = (); |
| 41 | 41 | ||
| 42 | pub(crate) mod sealed { | 42 | pub(crate) trait SealedChannel { |
| 43 | pub trait Channel { | 43 | fn id(&self) -> u8; |
| 44 | fn id(&self) -> u8; | 44 | } |
| 45 | } | 45 | |
| 46 | pub trait ChannelInterrupt { | 46 | pub(crate) trait ChannelInterrupt { |
| 47 | #[cfg_attr(not(feature = "rt"), allow(unused))] | 47 | #[cfg_attr(not(feature = "rt"), allow(unused))] |
| 48 | unsafe fn on_irq(); | 48 | unsafe fn on_irq(); |
| 49 | } | ||
| 50 | } | 49 | } |
| 51 | 50 | ||
| 52 | /// DMA channel. | 51 | /// DMA channel. |
| 53 | pub trait Channel: sealed::Channel + Peripheral<P = Self> + Into<AnyChannel> + 'static { | 52 | #[allow(private_bounds)] |
| 53 | pub trait Channel: SealedChannel + Peripheral<P = Self> + Into<AnyChannel> + 'static { | ||
| 54 | /// Type-erase (degrade) this pin into an `AnyChannel`. | 54 | /// Type-erase (degrade) this pin into an `AnyChannel`. |
| 55 | /// | 55 | /// |
| 56 | /// This converts DMA channel singletons (`DMA1_CH3`, `DMA2_CH1`, ...), which | 56 | /// This converts DMA channel singletons (`DMA1_CH3`, `DMA2_CH1`, ...), which |
| @@ -64,12 +64,12 @@ pub trait Channel: sealed::Channel + Peripheral<P = Self> + Into<AnyChannel> + ' | |||
| 64 | 64 | ||
| 65 | macro_rules! dma_channel_impl { | 65 | macro_rules! dma_channel_impl { |
| 66 | ($channel_peri:ident, $index:expr) => { | 66 | ($channel_peri:ident, $index:expr) => { |
| 67 | impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri { | 67 | impl crate::dma::SealedChannel for crate::peripherals::$channel_peri { |
| 68 | fn id(&self) -> u8 { | 68 | fn id(&self) -> u8 { |
| 69 | $index | 69 | $index |
| 70 | } | 70 | } |
| 71 | } | 71 | } |
| 72 | impl crate::dma::sealed::ChannelInterrupt for crate::peripherals::$channel_peri { | 72 | impl crate::dma::ChannelInterrupt for crate::peripherals::$channel_peri { |
| 73 | unsafe fn on_irq() { | 73 | unsafe fn on_irq() { |
| 74 | crate::dma::AnyChannel { id: $index }.on_irq(); | 74 | crate::dma::AnyChannel { id: $index }.on_irq(); |
| 75 | } | 75 | } |
| @@ -97,7 +97,7 @@ impl AnyChannel { | |||
| 97 | } | 97 | } |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | impl sealed::Channel for AnyChannel { | 100 | impl SealedChannel for AnyChannel { |
| 101 | fn id(&self) -> u8 { | 101 | fn id(&self) -> u8 { |
| 102 | self.id | 102 | self.id |
| 103 | } | 103 | } |
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 { | |||
| 20 | } | 20 | } |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | mod sealed { | 23 | trait SealedWord {} |
| 24 | pub trait Word {} | ||
| 25 | } | ||
| 26 | 24 | ||
| 27 | /// DMA word trait. | 25 | /// DMA word trait. |
| 28 | /// | 26 | /// |
| 29 | /// This is implemented for u8, u16, u32, etc. | 27 | /// This is implemented for u8, u16, u32, etc. |
| 30 | pub trait Word: sealed::Word + Default + Copy + 'static { | 28 | #[allow(private_bounds)] |
| 29 | pub trait Word: SealedWord + Default + Copy + 'static { | ||
| 31 | /// Word size | 30 | /// Word size |
| 32 | fn size() -> WordSize; | 31 | fn size() -> WordSize; |
| 33 | /// Amount of bits of this word size. | 32 | /// Amount of bits of this word size. |
| @@ -36,7 +35,7 @@ pub trait Word: sealed::Word + Default + Copy + 'static { | |||
| 36 | 35 | ||
| 37 | macro_rules! impl_word { | 36 | macro_rules! impl_word { |
| 38 | (_, $T:ident, $bits:literal, $size:ident) => { | 37 | (_, $T:ident, $bits:literal, $size:ident) => { |
| 39 | impl sealed::Word for $T {} | 38 | impl SealedWord for $T {} |
| 40 | impl Word for $T { | 39 | impl Word for $T { |
| 41 | fn bits() -> usize { | 40 | fn bits() -> usize { |
| 42 | $bits | 41 | $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 { | |||
| 177 | fn poll_link<S: StationManagement>(&mut self, sm: &mut S, cx: &mut Context) -> bool; | 177 | fn poll_link<S: StationManagement>(&mut self, sm: &mut S, cx: &mut Context) -> bool; |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | pub(crate) mod sealed { | 180 | trait SealedInstance { |
| 181 | pub trait Instance { | 181 | fn regs() -> crate::pac::eth::Eth; |
| 182 | fn regs() -> crate::pac::eth::Eth; | ||
| 183 | } | ||
| 184 | } | 182 | } |
| 185 | 183 | ||
| 186 | /// Ethernet instance. | 184 | /// Ethernet instance. |
| 187 | pub trait Instance: sealed::Instance + RccPeripheral + Send + 'static {} | 185 | #[allow(private_bounds)] |
| 186 | pub trait Instance: SealedInstance + RccPeripheral + Send + 'static {} | ||
| 188 | 187 | ||
| 189 | impl sealed::Instance for crate::peripherals::ETH { | 188 | impl SealedInstance for crate::peripherals::ETH { |
| 190 | fn regs() -> crate::pac::eth::Eth { | 189 | fn regs() -> crate::pac::eth::Eth { |
| 191 | crate::pac::ETH | 190 | crate::pac::ETH |
| 192 | } | 191 | } |
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 | |||
| 12 | pub(crate) use self::rx_desc::{RDes, RDesRing}; | 12 | pub(crate) use self::rx_desc::{RDes, RDesRing}; |
| 13 | pub(crate) use self::tx_desc::{TDes, TDesRing}; | 13 | pub(crate) use self::tx_desc::{TDes, TDesRing}; |
| 14 | use super::*; | 14 | use super::*; |
| 15 | use crate::gpio::sealed::{AFType, Pin as __GpioPin}; | 15 | use crate::gpio::{AFType, AnyPin, SealedPin}; |
| 16 | use crate::gpio::AnyPin; | ||
| 17 | use crate::interrupt::InterruptExt; | 16 | use crate::interrupt::InterruptExt; |
| 18 | #[cfg(eth_v1a)] | 17 | #[cfg(eth_v1a)] |
| 19 | use crate::pac::AFIO; | 18 | use crate::pac::AFIO; |
| 20 | #[cfg(any(eth_v1b, eth_v1c))] | 19 | #[cfg(any(eth_v1b, eth_v1c))] |
| 21 | use crate::pac::SYSCFG; | 20 | use crate::pac::SYSCFG; |
| 22 | use crate::pac::{ETH, RCC}; | 21 | use crate::pac::{ETH, RCC}; |
| 23 | use crate::rcc::sealed::RccPeripheral; | 22 | use crate::rcc::SealedRccPeripheral; |
| 24 | use crate::{interrupt, Peripheral}; | 23 | use crate::{interrupt, Peripheral}; |
| 25 | 24 | ||
| 26 | /// Interrupt handler. | 25 | /// Interrupt handler. |
| @@ -149,8 +148,8 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | |||
| 149 | #[cfg(any(eth_v1b, eth_v1c))] | 148 | #[cfg(any(eth_v1b, eth_v1c))] |
| 150 | config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); | 149 | config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); |
| 151 | 150 | ||
| 152 | let dma = ETH.ethernet_dma(); | 151 | let dma = T::regs().ethernet_dma(); |
| 153 | let mac = ETH.ethernet_mac(); | 152 | let mac = T::regs().ethernet_mac(); |
| 154 | 153 | ||
| 155 | // Reset and wait | 154 | // Reset and wait |
| 156 | dma.dmabmr().modify(|w| w.set_sr(true)); | 155 | dma.dmabmr().modify(|w| w.set_sr(true)); |
| @@ -192,7 +191,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | |||
| 192 | 191 | ||
| 193 | // TODO MTU size setting not found for v1 ethernet, check if correct | 192 | // TODO MTU size setting not found for v1 ethernet, check if correct |
| 194 | 193 | ||
| 195 | let hclk = <T as RccPeripheral>::frequency(); | 194 | let hclk = <T as SealedRccPeripheral>::frequency(); |
| 196 | let hclk_mhz = hclk.0 / 1_000_000; | 195 | let hclk_mhz = hclk.0 / 1_000_000; |
| 197 | 196 | ||
| 198 | // Set the MDC clock frequency in the range 1MHz - 2.5MHz | 197 | // 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> { | |||
| 235 | 234 | ||
| 236 | fence(Ordering::SeqCst); | 235 | fence(Ordering::SeqCst); |
| 237 | 236 | ||
| 238 | let mac = ETH.ethernet_mac(); | 237 | let mac = T::regs().ethernet_mac(); |
| 239 | let dma = ETH.ethernet_dma(); | 238 | let dma = T::regs().ethernet_dma(); |
| 240 | 239 | ||
| 241 | mac.maccr().modify(|w| { | 240 | mac.maccr().modify(|w| { |
| 242 | w.set_re(true); | 241 | w.set_re(true); |
| @@ -275,7 +274,7 @@ pub struct EthernetStationManagement<T: Instance> { | |||
| 275 | 274 | ||
| 276 | unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> { | 275 | unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> { |
| 277 | fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 { | 276 | fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 { |
| 278 | let mac = ETH.ethernet_mac(); | 277 | let mac = T::regs().ethernet_mac(); |
| 279 | 278 | ||
| 280 | mac.macmiiar().modify(|w| { | 279 | mac.macmiiar().modify(|w| { |
| 281 | w.set_pa(phy_addr); | 280 | w.set_pa(phy_addr); |
| @@ -289,7 +288,7 @@ unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> { | |||
| 289 | } | 288 | } |
| 290 | 289 | ||
| 291 | fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) { | 290 | fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) { |
| 292 | let mac = ETH.ethernet_mac(); | 291 | let mac = T::regs().ethernet_mac(); |
| 293 | 292 | ||
| 294 | mac.macmiidr().write(|w| w.set_md(val)); | 293 | mac.macmiidr().write(|w| w.set_md(val)); |
| 295 | mac.macmiiar().modify(|w| { | 294 | mac.macmiiar().modify(|w| { |
| @@ -305,8 +304,8 @@ unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> { | |||
| 305 | 304 | ||
| 306 | impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { | 305 | impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { |
| 307 | fn drop(&mut self) { | 306 | fn drop(&mut self) { |
| 308 | let dma = ETH.ethernet_dma(); | 307 | let dma = T::regs().ethernet_dma(); |
| 309 | let mac = ETH.ethernet_mac(); | 308 | let mac = T::regs().ethernet_mac(); |
| 310 | 309 | ||
| 311 | // Disable the TX DMA and wait for any previous transmissions to be completed | 310 | // Disable the TX DMA and wait for any previous transmissions to be completed |
| 312 | dma.dmaomr().modify(|w| w.set_st(St::STOPPED)); | 311 | 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}; | |||
| 7 | 7 | ||
| 8 | pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing}; | 8 | pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing}; |
| 9 | use super::*; | 9 | use super::*; |
| 10 | use crate::gpio::sealed::{AFType, Pin as _}; | 10 | use crate::gpio::{AFType, AnyPin, SealedPin as _, Speed}; |
| 11 | use crate::gpio::{AnyPin, Speed}; | ||
| 12 | use crate::interrupt::InterruptExt; | 11 | use crate::interrupt::InterruptExt; |
| 13 | use crate::pac::ETH; | 12 | use crate::pac::ETH; |
| 14 | use crate::rcc::sealed::RccPeripheral; | 13 | use crate::rcc::SealedRccPeripheral; |
| 15 | use crate::{interrupt, Peripheral}; | 14 | use crate::{interrupt, Peripheral}; |
| 16 | 15 | ||
| 17 | /// Interrupt handler. | 16 | /// Interrupt handler. |
| @@ -207,9 +206,9 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | |||
| 207 | phy: P, | 206 | phy: P, |
| 208 | mac_addr: [u8; 6], | 207 | mac_addr: [u8; 6], |
| 209 | ) -> Self { | 208 | ) -> Self { |
| 210 | let dma = ETH.ethernet_dma(); | 209 | let dma = T::regs().ethernet_dma(); |
| 211 | let mac = ETH.ethernet_mac(); | 210 | let mac = T::regs().ethernet_mac(); |
| 212 | let mtl = ETH.ethernet_mtl(); | 211 | let mtl = T::regs().ethernet_mtl(); |
| 213 | 212 | ||
| 214 | // Reset and wait | 213 | // Reset and wait |
| 215 | dma.dmamr().modify(|w| w.set_swr(true)); | 214 | dma.dmamr().modify(|w| w.set_swr(true)); |
| @@ -265,7 +264,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | |||
| 265 | w.set_rbsz(RX_BUFFER_SIZE as u16); | 264 | w.set_rbsz(RX_BUFFER_SIZE as u16); |
| 266 | }); | 265 | }); |
| 267 | 266 | ||
| 268 | let hclk = <T as RccPeripheral>::frequency(); | 267 | let hclk = <T as SealedRccPeripheral>::frequency(); |
| 269 | let hclk_mhz = hclk.0 / 1_000_000; | 268 | let hclk_mhz = hclk.0 / 1_000_000; |
| 270 | 269 | ||
| 271 | // Set the MDC clock frequency in the range 1MHz - 2.5MHz | 270 | // 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> { | |||
| 296 | 295 | ||
| 297 | fence(Ordering::SeqCst); | 296 | fence(Ordering::SeqCst); |
| 298 | 297 | ||
| 299 | let mac = ETH.ethernet_mac(); | 298 | let mac = T::regs().ethernet_mac(); |
| 300 | let mtl = ETH.ethernet_mtl(); | 299 | let mtl = T::regs().ethernet_mtl(); |
| 301 | let dma = ETH.ethernet_dma(); | 300 | let dma = T::regs().ethernet_dma(); |
| 302 | 301 | ||
| 303 | mac.maccr().modify(|w| { | 302 | mac.maccr().modify(|w| { |
| 304 | w.set_re(true); | 303 | w.set_re(true); |
| @@ -334,7 +333,7 @@ pub struct EthernetStationManagement<T: Instance> { | |||
| 334 | 333 | ||
| 335 | unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> { | 334 | unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> { |
| 336 | fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 { | 335 | fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 { |
| 337 | let mac = ETH.ethernet_mac(); | 336 | let mac = T::regs().ethernet_mac(); |
| 338 | 337 | ||
| 339 | mac.macmdioar().modify(|w| { | 338 | mac.macmdioar().modify(|w| { |
| 340 | w.set_pa(phy_addr); | 339 | w.set_pa(phy_addr); |
| @@ -348,7 +347,7 @@ unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> { | |||
| 348 | } | 347 | } |
| 349 | 348 | ||
| 350 | fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) { | 349 | fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) { |
| 351 | let mac = ETH.ethernet_mac(); | 350 | let mac = T::regs().ethernet_mac(); |
| 352 | 351 | ||
| 353 | mac.macmdiodr().write(|w| w.set_md(val)); | 352 | mac.macmdiodr().write(|w| w.set_md(val)); |
| 354 | mac.macmdioar().modify(|w| { | 353 | mac.macmdioar().modify(|w| { |
| @@ -364,9 +363,9 @@ unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> { | |||
| 364 | 363 | ||
| 365 | impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { | 364 | impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { |
| 366 | fn drop(&mut self) { | 365 | fn drop(&mut self) { |
| 367 | let dma = ETH.ethernet_dma(); | 366 | let dma = T::regs().ethernet_dma(); |
| 368 | let mac = ETH.ethernet_mac(); | 367 | let mac = T::regs().ethernet_mac(); |
| 369 | let mtl = ETH.ethernet_mtl(); | 368 | let mtl = T::regs().ethernet_mtl(); |
| 370 | 369 | ||
| 371 | // Disable the TX DMA and wait for any previous transmissions to be completed | 370 | // Disable the TX DMA and wait for any previous transmissions to be completed |
| 372 | dma.dmactx_cr().modify(|w| w.set_st(false)); | 371 | 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 { | |||
| 330 | 330 | ||
| 331 | foreach_exti_irq!(impl_irq); | 331 | foreach_exti_irq!(impl_irq); |
| 332 | 332 | ||
| 333 | pub(crate) mod sealed { | 333 | trait SealedChannel {} |
| 334 | pub trait Channel {} | ||
| 335 | } | ||
| 336 | 334 | ||
| 337 | /// EXTI channel trait. | 335 | /// EXTI channel trait. |
| 338 | pub trait Channel: sealed::Channel + Sized { | 336 | #[allow(private_bounds)] |
| 337 | pub trait Channel: SealedChannel + Sized { | ||
| 339 | /// Get the EXTI channel number. | 338 | /// Get the EXTI channel number. |
| 340 | fn number(&self) -> u8; | 339 | fn number(&self) -> u8; |
| 341 | 340 | ||
| @@ -359,7 +358,7 @@ pub struct AnyChannel { | |||
| 359 | } | 358 | } |
| 360 | 359 | ||
| 361 | impl_peripheral!(AnyChannel); | 360 | impl_peripheral!(AnyChannel); |
| 362 | impl sealed::Channel for AnyChannel {} | 361 | impl SealedChannel for AnyChannel {} |
| 363 | impl Channel for AnyChannel { | 362 | impl Channel for AnyChannel { |
| 364 | fn number(&self) -> u8 { | 363 | fn number(&self) -> u8 { |
| 365 | self.number | 364 | self.number |
| @@ -368,7 +367,7 @@ impl Channel for AnyChannel { | |||
| 368 | 367 | ||
| 369 | macro_rules! impl_exti { | 368 | macro_rules! impl_exti { |
| 370 | ($type:ident, $number:expr) => { | 369 | ($type:ident, $number:expr) => { |
| 371 | impl sealed::Channel for peripherals::$type {} | 370 | impl SealedChannel for peripherals::$type {} |
| 372 | impl Channel for peripherals::$type { | 371 | impl Channel for peripherals::$type { |
| 373 | fn number(&self) -> u8 { | 372 | fn number(&self) -> u8 { |
| 374 | $number | 373 | $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; | |||
| 3 | 3 | ||
| 4 | use embassy_hal_internal::into_ref; | 4 | use embassy_hal_internal::into_ref; |
| 5 | 5 | ||
| 6 | use crate::gpio::sealed::AFType; | 6 | use crate::gpio::{AFType, Pull, Speed}; |
| 7 | use crate::gpio::{Pull, Speed}; | ||
| 8 | use crate::Peripheral; | 7 | use crate::Peripheral; |
| 9 | 8 | ||
| 10 | /// FMC driver | 9 | /// FMC driver |
| @@ -44,7 +43,7 @@ where | |||
| 44 | 43 | ||
| 45 | /// Get the kernel clock currently in use for this FMC instance. | 44 | /// Get the kernel clock currently in use for this FMC instance. |
| 46 | pub fn source_clock_hz(&self) -> u32 { | 45 | pub fn source_clock_hz(&self) -> u32 { |
| 47 | <T as crate::rcc::sealed::RccPeripheral>::frequency().0 | 46 | <T as crate::rcc::SealedRccPeripheral>::frequency().0 |
| 48 | } | 47 | } |
| 49 | } | 48 | } |
| 50 | 49 | ||
| @@ -69,7 +68,7 @@ where | |||
| 69 | } | 68 | } |
| 70 | 69 | ||
| 71 | fn source_clock_hz(&self) -> u32 { | 70 | fn source_clock_hz(&self) -> u32 { |
| 72 | <T as crate::rcc::sealed::RccPeripheral>::frequency().0 | 71 | <T as crate::rcc::SealedRccPeripheral>::frequency().0 |
| 73 | } | 72 | } |
| 74 | } | 73 | } |
| 75 | 74 | ||
| @@ -201,18 +200,17 @@ impl<'d, T: Instance> Fmc<'d, T> { | |||
| 201 | )); | 200 | )); |
| 202 | } | 201 | } |
| 203 | 202 | ||
| 204 | pub(crate) mod sealed { | 203 | trait SealedInstance: crate::rcc::SealedRccPeripheral { |
| 205 | pub trait Instance: crate::rcc::sealed::RccPeripheral { | 204 | const REGS: crate::pac::fmc::Fmc; |
| 206 | const REGS: crate::pac::fmc::Fmc; | ||
| 207 | } | ||
| 208 | } | 205 | } |
| 209 | 206 | ||
| 210 | /// FMC instance trait. | 207 | /// FMC instance trait. |
| 211 | pub trait Instance: sealed::Instance + 'static {} | 208 | #[allow(private_bounds)] |
| 209 | pub trait Instance: SealedInstance + 'static {} | ||
| 212 | 210 | ||
| 213 | foreach_peripheral!( | 211 | foreach_peripheral!( |
| 214 | (fmc, $inst:ident) => { | 212 | (fmc, $inst:ident) => { |
| 215 | impl crate::fmc::sealed::Instance for crate::peripherals::$inst { | 213 | impl crate::fmc::SealedInstance for crate::peripherals::$inst { |
| 216 | const REGS: crate::pac::fmc::Fmc = crate::pac::$inst; | 214 | const REGS: crate::pac::fmc::Fmc = crate::pac::$inst; |
| 217 | } | 215 | } |
| 218 | impl crate::fmc::Instance for crate::peripherals::$inst {} | 216 | 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; | |||
| 6 | use critical_section::CriticalSection; | 6 | use critical_section::CriticalSection; |
| 7 | use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef}; | 7 | use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef}; |
| 8 | 8 | ||
| 9 | use self::sealed::Pin as _; | ||
| 10 | use crate::pac::gpio::{self, vals}; | 9 | use crate::pac::gpio::{self, vals}; |
| 11 | use crate::{pac, peripherals, Peripheral}; | 10 | use crate::{pac, peripherals, Peripheral}; |
| 12 | 11 | ||
| @@ -129,6 +128,18 @@ impl<'d> Flex<'d> { | |||
| 129 | }); | 128 | }); |
| 130 | } | 129 | } |
| 131 | 130 | ||
| 131 | /// Put the pin into AF mode, unchecked. | ||
| 132 | /// | ||
| 133 | /// This puts the pin into the AF mode, with the requested number, pull and speed. This is | ||
| 134 | /// completely unchecked, it can attach the pin to literally any peripheral, so use with care. | ||
| 135 | #[inline] | ||
| 136 | pub fn set_as_af_unchecked(&mut self, af_num: u8, af_type: AFType, pull: Pull, speed: Speed) { | ||
| 137 | critical_section::with(|_| { | ||
| 138 | self.pin.set_as_af_pull(af_num, af_type, pull); | ||
| 139 | self.pin.set_speed(speed); | ||
| 140 | }); | ||
| 141 | } | ||
| 142 | |||
| 132 | /// Get whether the pin input level is high. | 143 | /// Get whether the pin input level is high. |
| 133 | #[inline] | 144 | #[inline] |
| 134 | pub fn is_high(&self) -> bool { | 145 | pub fn is_high(&self) -> bool { |
| @@ -508,172 +519,168 @@ pub enum OutputType { | |||
| 508 | OpenDrain, | 519 | OpenDrain, |
| 509 | } | 520 | } |
| 510 | 521 | ||
| 511 | impl From<OutputType> for sealed::AFType { | 522 | impl From<OutputType> for AFType { |
| 512 | fn from(value: OutputType) -> Self { | 523 | fn from(value: OutputType) -> Self { |
| 513 | match value { | 524 | match value { |
| 514 | OutputType::OpenDrain => sealed::AFType::OutputOpenDrain, | 525 | OutputType::OpenDrain => AFType::OutputOpenDrain, |
| 515 | OutputType::PushPull => sealed::AFType::OutputPushPull, | 526 | OutputType::PushPull => AFType::OutputPushPull, |
| 516 | } | 527 | } |
| 517 | } | 528 | } |
| 518 | } | 529 | } |
| 519 | 530 | ||
| 520 | #[allow(missing_docs)] | 531 | /// Alternate function type settings |
| 521 | pub(crate) mod sealed { | 532 | #[derive(Debug, Copy, Clone)] |
| 522 | use super::*; | 533 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 523 | 534 | pub enum AFType { | |
| 524 | /// Alternate function type settings | 535 | /// Input |
| 525 | #[derive(Debug, Copy, Clone)] | 536 | Input, |
| 526 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 537 | /// Output, drive the pin both high or low. |
| 527 | pub enum AFType { | 538 | OutputPushPull, |
| 528 | /// Input | 539 | /// Output, drive the pin low, or don't drive it at all if the output level is high. |
| 529 | Input, | 540 | OutputOpenDrain, |
| 530 | /// Output, drive the pin both high or low. | 541 | } |
| 531 | OutputPushPull, | ||
| 532 | /// Output, drive the pin low, or don't drive it at all if the output level is high. | ||
| 533 | OutputOpenDrain, | ||
| 534 | } | ||
| 535 | |||
| 536 | pub trait Pin { | ||
| 537 | fn pin_port(&self) -> u8; | ||
| 538 | |||
| 539 | #[inline] | ||
| 540 | fn _pin(&self) -> u8 { | ||
| 541 | self.pin_port() % 16 | ||
| 542 | } | ||
| 543 | #[inline] | ||
| 544 | fn _port(&self) -> u8 { | ||
| 545 | self.pin_port() / 16 | ||
| 546 | } | ||
| 547 | 542 | ||
| 548 | #[inline] | 543 | pub(crate) trait SealedPin { |
| 549 | fn block(&self) -> gpio::Gpio { | 544 | fn pin_port(&self) -> u8; |
| 550 | pac::GPIO(self._port() as _) | ||
| 551 | } | ||
| 552 | 545 | ||
| 553 | /// Set the output as high. | 546 | #[inline] |
| 554 | #[inline] | 547 | fn _pin(&self) -> u8 { |
| 555 | fn set_high(&self) { | 548 | self.pin_port() % 16 |
| 556 | let n = self._pin() as _; | 549 | } |
| 557 | self.block().bsrr().write(|w| w.set_bs(n, true)); | 550 | #[inline] |
| 558 | } | 551 | fn _port(&self) -> u8 { |
| 552 | self.pin_port() / 16 | ||
| 553 | } | ||
| 559 | 554 | ||
| 560 | /// Set the output as low. | 555 | #[inline] |
| 561 | #[inline] | 556 | fn block(&self) -> gpio::Gpio { |
| 562 | fn set_low(&self) { | 557 | pac::GPIO(self._port() as _) |
| 563 | let n = self._pin() as _; | 558 | } |
| 564 | self.block().bsrr().write(|w| w.set_br(n, true)); | ||
| 565 | } | ||
| 566 | 559 | ||
| 567 | #[inline] | 560 | /// Set the output as high. |
| 568 | fn set_as_af(&self, af_num: u8, af_type: AFType) { | 561 | #[inline] |
| 569 | self.set_as_af_pull(af_num, af_type, Pull::None); | 562 | fn set_high(&self) { |
| 570 | } | 563 | let n = self._pin() as _; |
| 564 | self.block().bsrr().write(|w| w.set_bs(n, true)); | ||
| 565 | } | ||
| 571 | 566 | ||
| 572 | #[cfg(gpio_v1)] | 567 | /// Set the output as low. |
| 573 | #[inline] | 568 | #[inline] |
| 574 | fn set_as_af_pull(&self, _af_num: u8, af_type: AFType, pull: Pull) { | 569 | fn set_low(&self) { |
| 575 | // F1 uses the AFIO register for remapping. | 570 | let n = self._pin() as _; |
| 576 | // For now, this is not implemented, so af_num is ignored | 571 | self.block().bsrr().write(|w| w.set_br(n, true)); |
| 577 | // _af_num should be zero here, since it is not set by stm32-data | 572 | } |
| 578 | let r = self.block(); | ||
| 579 | let n = self._pin() as usize; | ||
| 580 | let crlh = if n < 8 { 0 } else { 1 }; | ||
| 581 | match af_type { | ||
| 582 | AFType::Input => { | ||
| 583 | let cnf = match pull { | ||
| 584 | Pull::Up => { | ||
| 585 | r.bsrr().write(|w| w.set_bs(n, true)); | ||
| 586 | vals::CnfIn::PULL | ||
| 587 | } | ||
| 588 | Pull::Down => { | ||
| 589 | r.bsrr().write(|w| w.set_br(n, true)); | ||
| 590 | vals::CnfIn::PULL | ||
| 591 | } | ||
| 592 | Pull::None => vals::CnfIn::FLOATING, | ||
| 593 | }; | ||
| 594 | |||
| 595 | r.cr(crlh).modify(|w| { | ||
| 596 | w.set_mode(n % 8, vals::Mode::INPUT); | ||
| 597 | w.set_cnf_in(n % 8, cnf); | ||
| 598 | }); | ||
| 599 | } | ||
| 600 | AFType::OutputPushPull => { | ||
| 601 | r.cr(crlh).modify(|w| { | ||
| 602 | w.set_mode(n % 8, vals::Mode::OUTPUT50MHZ); | ||
| 603 | w.set_cnf_out(n % 8, vals::CnfOut::ALTPUSHPULL); | ||
| 604 | }); | ||
| 605 | } | ||
| 606 | AFType::OutputOpenDrain => { | ||
| 607 | r.cr(crlh).modify(|w| { | ||
| 608 | w.set_mode(n % 8, vals::Mode::OUTPUT50MHZ); | ||
| 609 | w.set_cnf_out(n % 8, vals::CnfOut::ALTOPENDRAIN); | ||
| 610 | }); | ||
| 611 | } | ||
| 612 | } | ||
| 613 | } | ||
| 614 | 573 | ||
| 615 | #[cfg(gpio_v2)] | 574 | #[inline] |
| 616 | #[inline] | 575 | fn set_as_af(&self, af_num: u8, af_type: AFType) { |
| 617 | fn set_as_af_pull(&self, af_num: u8, af_type: AFType, pull: Pull) { | 576 | self.set_as_af_pull(af_num, af_type, Pull::None); |
| 618 | let pin = self._pin() as usize; | 577 | } |
| 619 | let block = self.block(); | ||
| 620 | block.afr(pin / 8).modify(|w| w.set_afr(pin % 8, af_num)); | ||
| 621 | match af_type { | ||
| 622 | AFType::Input => {} | ||
| 623 | AFType::OutputPushPull => block.otyper().modify(|w| w.set_ot(pin, vals::Ot::PUSHPULL)), | ||
| 624 | AFType::OutputOpenDrain => block.otyper().modify(|w| w.set_ot(pin, vals::Ot::OPENDRAIN)), | ||
| 625 | } | ||
| 626 | block.pupdr().modify(|w| w.set_pupdr(pin, pull.into())); | ||
| 627 | 578 | ||
| 628 | block.moder().modify(|w| w.set_moder(pin, vals::Moder::ALTERNATE)); | 579 | #[cfg(gpio_v1)] |
| 629 | } | 580 | #[inline] |
| 581 | fn set_as_af_pull(&self, _af_num: u8, af_type: AFType, pull: Pull) { | ||
| 582 | // F1 uses the AFIO register for remapping. | ||
| 583 | // For now, this is not implemented, so af_num is ignored | ||
| 584 | // _af_num should be zero here, since it is not set by stm32-data | ||
| 585 | let r = self.block(); | ||
| 586 | let n = self._pin() as usize; | ||
| 587 | let crlh = if n < 8 { 0 } else { 1 }; | ||
| 588 | match af_type { | ||
| 589 | AFType::Input => { | ||
| 590 | let cnf = match pull { | ||
| 591 | Pull::Up => { | ||
| 592 | r.bsrr().write(|w| w.set_bs(n, true)); | ||
| 593 | vals::CnfIn::PULL | ||
| 594 | } | ||
| 595 | Pull::Down => { | ||
| 596 | r.bsrr().write(|w| w.set_br(n, true)); | ||
| 597 | vals::CnfIn::PULL | ||
| 598 | } | ||
| 599 | Pull::None => vals::CnfIn::FLOATING, | ||
| 600 | }; | ||
| 630 | 601 | ||
| 631 | #[inline] | 602 | r.cr(crlh).modify(|w| { |
| 632 | fn set_as_analog(&self) { | 603 | w.set_mode(n % 8, vals::Mode::INPUT); |
| 633 | let pin = self._pin() as usize; | 604 | w.set_cnf_in(n % 8, cnf); |
| 634 | let block = self.block(); | ||
| 635 | #[cfg(gpio_v1)] | ||
| 636 | { | ||
| 637 | let crlh = if pin < 8 { 0 } else { 1 }; | ||
| 638 | block.cr(crlh).modify(|w| { | ||
| 639 | w.set_mode(pin % 8, vals::Mode::INPUT); | ||
| 640 | w.set_cnf_in(pin % 8, vals::CnfIn::ANALOG); | ||
| 641 | }); | 605 | }); |
| 642 | } | 606 | } |
| 643 | #[cfg(gpio_v2)] | 607 | AFType::OutputPushPull => { |
| 644 | block.moder().modify(|w| w.set_moder(pin, vals::Moder::ANALOG)); | 608 | r.cr(crlh).modify(|w| { |
| 609 | w.set_mode(n % 8, vals::Mode::OUTPUT50MHZ); | ||
| 610 | w.set_cnf_out(n % 8, vals::CnfOut::ALTPUSHPULL); | ||
| 611 | }); | ||
| 612 | } | ||
| 613 | AFType::OutputOpenDrain => { | ||
| 614 | r.cr(crlh).modify(|w| { | ||
| 615 | w.set_mode(n % 8, vals::Mode::OUTPUT50MHZ); | ||
| 616 | w.set_cnf_out(n % 8, vals::CnfOut::ALTOPENDRAIN); | ||
| 617 | }); | ||
| 618 | } | ||
| 619 | } | ||
| 620 | } | ||
| 621 | |||
| 622 | #[cfg(gpio_v2)] | ||
| 623 | #[inline] | ||
| 624 | fn set_as_af_pull(&self, af_num: u8, af_type: AFType, pull: Pull) { | ||
| 625 | let pin = self._pin() as usize; | ||
| 626 | let block = self.block(); | ||
| 627 | block.afr(pin / 8).modify(|w| w.set_afr(pin % 8, af_num)); | ||
| 628 | match af_type { | ||
| 629 | AFType::Input => {} | ||
| 630 | AFType::OutputPushPull => block.otyper().modify(|w| w.set_ot(pin, vals::Ot::PUSHPULL)), | ||
| 631 | AFType::OutputOpenDrain => block.otyper().modify(|w| w.set_ot(pin, vals::Ot::OPENDRAIN)), | ||
| 645 | } | 632 | } |
| 633 | block.pupdr().modify(|w| w.set_pupdr(pin, pull.into())); | ||
| 634 | |||
| 635 | block.moder().modify(|w| w.set_moder(pin, vals::Moder::ALTERNATE)); | ||
| 636 | } | ||
| 646 | 637 | ||
| 647 | /// Set the pin as "disconnected", ie doing nothing and consuming the lowest | 638 | #[inline] |
| 648 | /// amount of power possible. | 639 | fn set_as_analog(&self) { |
| 649 | /// | 640 | let pin = self._pin() as usize; |
| 650 | /// This is currently the same as set_as_analog but is semantically different really. | 641 | let block = self.block(); |
| 651 | /// Drivers should set_as_disconnected pins when dropped. | 642 | #[cfg(gpio_v1)] |
| 652 | #[inline] | 643 | { |
| 653 | fn set_as_disconnected(&self) { | 644 | let crlh = if pin < 8 { 0 } else { 1 }; |
| 654 | self.set_as_analog(); | 645 | block.cr(crlh).modify(|w| { |
| 646 | w.set_mode(pin % 8, vals::Mode::INPUT); | ||
| 647 | w.set_cnf_in(pin % 8, vals::CnfIn::ANALOG); | ||
| 648 | }); | ||
| 655 | } | 649 | } |
| 650 | #[cfg(gpio_v2)] | ||
| 651 | block.moder().modify(|w| w.set_moder(pin, vals::Moder::ANALOG)); | ||
| 652 | } | ||
| 656 | 653 | ||
| 657 | #[inline] | 654 | /// Set the pin as "disconnected", ie doing nothing and consuming the lowest |
| 658 | fn set_speed(&self, speed: Speed) { | 655 | /// amount of power possible. |
| 659 | let pin = self._pin() as usize; | 656 | /// |
| 657 | /// This is currently the same as set_as_analog but is semantically different really. | ||
| 658 | /// Drivers should set_as_disconnected pins when dropped. | ||
| 659 | #[inline] | ||
| 660 | fn set_as_disconnected(&self) { | ||
| 661 | self.set_as_analog(); | ||
| 662 | } | ||
| 660 | 663 | ||
| 661 | #[cfg(gpio_v1)] | 664 | #[inline] |
| 662 | { | 665 | fn set_speed(&self, speed: Speed) { |
| 663 | let crlh = if pin < 8 { 0 } else { 1 }; | 666 | let pin = self._pin() as usize; |
| 664 | self.block().cr(crlh).modify(|w| { | ||
| 665 | w.set_mode(pin % 8, speed.into()); | ||
| 666 | }); | ||
| 667 | } | ||
| 668 | 667 | ||
| 669 | #[cfg(gpio_v2)] | 668 | #[cfg(gpio_v1)] |
| 670 | self.block().ospeedr().modify(|w| w.set_ospeedr(pin, speed.into())); | 669 | { |
| 670 | let crlh = if pin < 8 { 0 } else { 1 }; | ||
| 671 | self.block().cr(crlh).modify(|w| { | ||
| 672 | w.set_mode(pin % 8, speed.into()); | ||
| 673 | }); | ||
| 671 | } | 674 | } |
| 675 | |||
| 676 | #[cfg(gpio_v2)] | ||
| 677 | self.block().ospeedr().modify(|w| w.set_ospeedr(pin, speed.into())); | ||
| 672 | } | 678 | } |
| 673 | } | 679 | } |
| 674 | 680 | ||
| 675 | /// GPIO pin trait. | 681 | /// GPIO pin trait. |
| 676 | pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static { | 682 | #[allow(private_bounds)] |
| 683 | pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + SealedPin + Sized + 'static { | ||
| 677 | /// EXTI channel assigned to this pin. | 684 | /// EXTI channel assigned to this pin. |
| 678 | /// | 685 | /// |
| 679 | /// For example, PC4 uses EXTI4. | 686 | /// For example, PC4 uses EXTI4. |
| @@ -737,7 +744,7 @@ impl Pin for AnyPin { | |||
| 737 | #[cfg(feature = "exti")] | 744 | #[cfg(feature = "exti")] |
| 738 | type ExtiChannel = crate::exti::AnyChannel; | 745 | type ExtiChannel = crate::exti::AnyChannel; |
| 739 | } | 746 | } |
| 740 | impl sealed::Pin for AnyPin { | 747 | impl SealedPin for AnyPin { |
| 741 | #[inline] | 748 | #[inline] |
| 742 | fn pin_port(&self) -> u8 { | 749 | fn pin_port(&self) -> u8 { |
| 743 | self.pin_port | 750 | self.pin_port |
| @@ -752,7 +759,7 @@ foreach_pin!( | |||
| 752 | #[cfg(feature = "exti")] | 759 | #[cfg(feature = "exti")] |
| 753 | type ExtiChannel = peripherals::$exti_ch; | 760 | type ExtiChannel = peripherals::$exti_ch; |
| 754 | } | 761 | } |
| 755 | impl sealed::Pin for peripherals::$pin_name { | 762 | impl SealedPin for peripherals::$pin_name { |
| 756 | #[inline] | 763 | #[inline] |
| 757 | fn pin_port(&self) -> u8 { | 764 | fn pin_port(&self) -> u8 { |
| 758 | $port_num * 16 + $pin_num | 765 | $port_num * 16 + $pin_num |
| @@ -769,7 +776,7 @@ foreach_pin!( | |||
| 769 | 776 | ||
| 770 | pub(crate) unsafe fn init(_cs: CriticalSection) { | 777 | pub(crate) unsafe fn init(_cs: CriticalSection) { |
| 771 | #[cfg(afio)] | 778 | #[cfg(afio)] |
| 772 | <crate::peripherals::AFIO as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(_cs); | 779 | <crate::peripherals::AFIO as crate::rcc::SealedRccPeripheral>::enable_and_reset_with_cs(_cs); |
| 773 | 780 | ||
| 774 | crate::_generated::init_gpio(); | 781 | crate::_generated::init_gpio(); |
| 775 | 782 | ||
| @@ -1061,9 +1068,3 @@ impl<'d> embedded_hal_1::digital::StatefulOutputPin for Flex<'d> { | |||
| 1061 | Ok((*self).is_set_low()) | 1068 | Ok((*self).is_set_low()) |
| 1062 | } | 1069 | } |
| 1063 | } | 1070 | } |
| 1064 | |||
| 1065 | /// Low-level GPIO manipulation. | ||
| 1066 | #[cfg(feature = "unstable-pac")] | ||
| 1067 | pub mod low_level { | ||
| 1068 | pub use super::sealed::*; | ||
| 1069 | } | ||
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; | |||
| 17 | use crate::dma::Transfer; | 17 | use crate::dma::Transfer; |
| 18 | use crate::interrupt::typelevel::Interrupt; | 18 | use crate::interrupt::typelevel::Interrupt; |
| 19 | use crate::peripherals::HASH; | 19 | use crate::peripherals::HASH; |
| 20 | use crate::rcc::sealed::RccPeripheral; | 20 | use crate::rcc::SealedRccPeripheral; |
| 21 | use crate::{interrupt, pac, peripherals, Peripheral}; | 21 | use crate::{interrupt, pac, peripherals, Peripheral}; |
| 22 | 22 | ||
| 23 | #[cfg(hash_v1)] | 23 | #[cfg(hash_v1)] |
| @@ -561,16 +561,13 @@ impl<'d, T: Instance, D> Hash<'d, T, D> { | |||
| 561 | } | 561 | } |
| 562 | } | 562 | } |
| 563 | 563 | ||
| 564 | pub(crate) mod sealed { | 564 | trait SealedInstance { |
| 565 | use super::*; | 565 | fn regs() -> pac::hash::Hash; |
| 566 | |||
| 567 | pub trait Instance { | ||
| 568 | fn regs() -> pac::hash::Hash; | ||
| 569 | } | ||
| 570 | } | 566 | } |
| 571 | 567 | ||
| 572 | /// HASH instance trait. | 568 | /// HASH instance trait. |
| 573 | pub trait Instance: sealed::Instance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send { | 569 | #[allow(private_bounds)] |
| 570 | pub trait Instance: SealedInstance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send { | ||
| 574 | /// Interrupt for this HASH instance. | 571 | /// Interrupt for this HASH instance. |
| 575 | type Interrupt: interrupt::typelevel::Interrupt; | 572 | type Interrupt: interrupt::typelevel::Interrupt; |
| 576 | } | 573 | } |
| @@ -581,7 +578,7 @@ foreach_interrupt!( | |||
| 581 | type Interrupt = crate::interrupt::typelevel::$irq; | 578 | type Interrupt = crate::interrupt::typelevel::$irq; |
| 582 | } | 579 | } |
| 583 | 580 | ||
| 584 | impl sealed::Instance for peripherals::$inst { | 581 | impl SealedInstance for peripherals::$inst { |
| 585 | fn regs() -> crate::pac::hash::Hash { | 582 | fn regs() -> crate::pac::hash::Hash { |
| 586 | crate::pac::$inst | 583 | crate::pac::$inst |
| 587 | } | 584 | } |
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; | |||
| 7 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 7 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 8 | pub use traits::Instance; | 8 | pub use traits::Instance; |
| 9 | 9 | ||
| 10 | #[allow(unused_imports)] | 10 | use crate::gpio::{AFType, AnyPin}; |
| 11 | use crate::gpio::sealed::{AFType, Pin}; | ||
| 12 | use crate::gpio::AnyPin; | ||
| 13 | use crate::time::Hertz; | 11 | use crate::time::Hertz; |
| 14 | use crate::Peripheral; | 12 | use crate::Peripheral; |
| 15 | 13 | ||
| @@ -54,16 +52,13 @@ pub struct ChF<T: Instance> { | |||
| 54 | phantom: PhantomData<T>, | 52 | phantom: PhantomData<T>, |
| 55 | } | 53 | } |
| 56 | 54 | ||
| 57 | mod sealed { | 55 | trait SealedAdvancedChannel<T: Instance> { |
| 58 | use super::Instance; | 56 | fn raw() -> usize; |
| 59 | |||
| 60 | pub trait AdvancedChannel<T: Instance> { | ||
| 61 | fn raw() -> usize; | ||
| 62 | } | ||
| 63 | } | 57 | } |
| 64 | 58 | ||
| 65 | /// Advanced channel instance trait. | 59 | /// Advanced channel instance trait. |
| 66 | pub trait AdvancedChannel<T: Instance>: sealed::AdvancedChannel<T> {} | 60 | #[allow(private_bounds)] |
| 61 | pub trait AdvancedChannel<T: Instance>: SealedAdvancedChannel<T> {} | ||
| 67 | 62 | ||
| 68 | /// HRTIM PWM pin. | 63 | /// HRTIM PWM pin. |
| 69 | pub struct PwmPin<'d, T, C> { | 64 | pub struct PwmPin<'d, T, C> { |
| @@ -113,7 +108,7 @@ macro_rules! advanced_channel_impl { | |||
| 113 | } | 108 | } |
| 114 | } | 109 | } |
| 115 | 110 | ||
| 116 | impl<T: Instance> sealed::AdvancedChannel<T> for $channel<T> { | 111 | impl<T: Instance> SealedAdvancedChannel<T> for $channel<T> { |
| 117 | fn raw() -> usize { | 112 | fn raw() -> usize { |
| 118 | $ch_num | 113 | $ch_num |
| 119 | } | 114 | } |
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 @@ | |||
| 1 | use crate::rcc::sealed::RccPeripheral; | 1 | use crate::rcc::RccPeripheral; |
| 2 | use crate::time::Hertz; | 2 | use crate::time::Hertz; |
| 3 | 3 | ||
| 4 | #[repr(u8)] | 4 | #[repr(u8)] |
| @@ -72,94 +72,92 @@ impl Prescaler { | |||
| 72 | } | 72 | } |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | pub(crate) mod sealed { | 75 | pub(crate) trait SealedInstance: RccPeripheral { |
| 76 | use super::*; | 76 | fn regs() -> crate::pac::hrtim::Hrtim; |
| 77 | 77 | ||
| 78 | pub trait Instance: RccPeripheral { | 78 | #[allow(unused)] |
| 79 | fn regs() -> crate::pac::hrtim::Hrtim; | 79 | fn set_master_frequency(frequency: Hertz) { |
| 80 | let f = frequency.0; | ||
| 80 | 81 | ||
| 81 | fn set_master_frequency(frequency: Hertz) { | 82 | // TODO: wire up HRTIM to the RCC mux infra. |
| 82 | let f = frequency.0; | 83 | //#[cfg(stm32f334)] |
| 84 | //let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0; | ||
| 85 | //#[cfg(not(stm32f334))] | ||
| 86 | let timer_f = Self::frequency().0; | ||
| 83 | 87 | ||
| 84 | // TODO: wire up HRTIM to the RCC mux infra. | 88 | let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); |
| 85 | //#[cfg(stm32f334)] | 89 | let psc = if Self::regs().isr().read().dllrdy() { |
| 86 | //let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0; | 90 | Prescaler::compute_min_high_res(psc_min) |
| 87 | //#[cfg(not(stm32f334))] | 91 | } else { |
| 88 | let timer_f = Self::frequency().0; | 92 | Prescaler::compute_min_low_res(psc_min) |
| 93 | }; | ||
| 89 | 94 | ||
| 90 | let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); | 95 | let timer_f = 32 * (timer_f / psc as u32); |
| 91 | let psc = if Self::regs().isr().read().dllrdy() { | 96 | let per: u16 = (timer_f / f) as u16; |
| 92 | Prescaler::compute_min_high_res(psc_min) | ||
| 93 | } else { | ||
| 94 | Prescaler::compute_min_low_res(psc_min) | ||
| 95 | }; | ||
| 96 | 97 | ||
| 97 | let timer_f = 32 * (timer_f / psc as u32); | 98 | let regs = Self::regs(); |
| 98 | let per: u16 = (timer_f / f) as u16; | ||
| 99 | 99 | ||
| 100 | let regs = Self::regs(); | 100 | regs.mcr().modify(|w| w.set_ckpsc(psc.into())); |
| 101 | 101 | regs.mper().modify(|w| w.set_mper(per)); | |
| 102 | regs.mcr().modify(|w| w.set_ckpsc(psc.into())); | 102 | } |
| 103 | regs.mper().modify(|w| w.set_mper(per)); | ||
| 104 | } | ||
| 105 | 103 | ||
| 106 | fn set_channel_frequency(channel: usize, frequency: Hertz) { | 104 | fn set_channel_frequency(channel: usize, frequency: Hertz) { |
| 107 | let f = frequency.0; | 105 | let f = frequency.0; |
| 108 | 106 | ||
| 109 | // TODO: wire up HRTIM to the RCC mux infra. | 107 | // TODO: wire up HRTIM to the RCC mux infra. |
| 110 | //#[cfg(stm32f334)] | 108 | //#[cfg(stm32f334)] |
| 111 | //let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0; | 109 | //let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0; |
| 112 | //#[cfg(not(stm32f334))] | 110 | //#[cfg(not(stm32f334))] |
| 113 | let timer_f = Self::frequency().0; | 111 | let timer_f = Self::frequency().0; |
| 114 | 112 | ||
| 115 | let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); | 113 | let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); |
| 116 | let psc = if Self::regs().isr().read().dllrdy() { | 114 | let psc = if Self::regs().isr().read().dllrdy() { |
| 117 | Prescaler::compute_min_high_res(psc_min) | 115 | Prescaler::compute_min_high_res(psc_min) |
| 118 | } else { | 116 | } else { |
| 119 | Prescaler::compute_min_low_res(psc_min) | 117 | Prescaler::compute_min_low_res(psc_min) |
| 120 | }; | 118 | }; |
| 121 | 119 | ||
| 122 | let timer_f = 32 * (timer_f / psc as u32); | 120 | let timer_f = 32 * (timer_f / psc as u32); |
| 123 | let per: u16 = (timer_f / f) as u16; | 121 | let per: u16 = (timer_f / f) as u16; |
| 124 | 122 | ||
| 125 | let regs = Self::regs(); | 123 | let regs = Self::regs(); |
| 126 | 124 | ||
| 127 | regs.tim(channel).cr().modify(|w| w.set_ckpsc(psc.into())); | 125 | regs.tim(channel).cr().modify(|w| w.set_ckpsc(psc.into())); |
| 128 | regs.tim(channel).per().modify(|w| w.set_per(per)); | 126 | regs.tim(channel).per().modify(|w| w.set_per(per)); |
| 129 | } | 127 | } |
| 130 | 128 | ||
| 131 | /// Set the dead time as a proportion of max_duty | 129 | /// Set the dead time as a proportion of max_duty |
| 132 | fn set_channel_dead_time(channel: usize, dead_time: u16) { | 130 | fn set_channel_dead_time(channel: usize, dead_time: u16) { |
| 133 | let regs = Self::regs(); | 131 | let regs = Self::regs(); |
| 134 | 132 | ||
| 135 | let channel_psc: Prescaler = regs.tim(channel).cr().read().ckpsc().into(); | 133 | let channel_psc: Prescaler = regs.tim(channel).cr().read().ckpsc().into(); |
| 136 | 134 | ||
| 137 | // The dead-time base clock runs 4 times slower than the hrtim base clock | 135 | // The dead-time base clock runs 4 times slower than the hrtim base clock |
| 138 | // u9::MAX = 511 | 136 | // u9::MAX = 511 |
| 139 | let psc_min = (channel_psc as u32 * dead_time as u32) / (4 * 511); | 137 | let psc_min = (channel_psc as u32 * dead_time as u32) / (4 * 511); |
| 140 | let psc = if Self::regs().isr().read().dllrdy() { | 138 | let psc = if Self::regs().isr().read().dllrdy() { |
| 141 | Prescaler::compute_min_high_res(psc_min) | 139 | Prescaler::compute_min_high_res(psc_min) |
| 142 | } else { | 140 | } else { |
| 143 | Prescaler::compute_min_low_res(psc_min) | 141 | Prescaler::compute_min_low_res(psc_min) |
| 144 | }; | 142 | }; |
| 145 | 143 | ||
| 146 | let dt_val = (psc as u32 * dead_time as u32) / (4 * channel_psc as u32); | 144 | let dt_val = (psc as u32 * dead_time as u32) / (4 * channel_psc as u32); |
| 147 | 145 | ||
| 148 | regs.tim(channel).dt().modify(|w| { | 146 | regs.tim(channel).dt().modify(|w| { |
| 149 | w.set_dtprsc(psc.into()); | 147 | w.set_dtprsc(psc.into()); |
| 150 | w.set_dtf(dt_val as u16); | 148 | w.set_dtf(dt_val as u16); |
| 151 | w.set_dtr(dt_val as u16); | 149 | w.set_dtr(dt_val as u16); |
| 152 | }); | 150 | }); |
| 153 | } | ||
| 154 | } | 151 | } |
| 155 | } | 152 | } |
| 156 | 153 | ||
| 157 | /// HRTIM instance trait. | 154 | /// HRTIM instance trait. |
| 158 | pub trait Instance: sealed::Instance + 'static {} | 155 | #[allow(private_bounds)] |
| 156 | pub trait Instance: SealedInstance + 'static {} | ||
| 159 | 157 | ||
| 160 | foreach_interrupt! { | 158 | foreach_interrupt! { |
| 161 | ($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => { | 159 | ($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => { |
| 162 | impl sealed::Instance for crate::peripherals::$inst { | 160 | impl SealedInstance for crate::peripherals::$inst { |
| 163 | fn regs() -> crate::pac::hrtim::Hrtim { | 161 | fn regs() -> crate::pac::hrtim::Hrtim { |
| 164 | crate::pac::$inst | 162 | crate::pac::$inst |
| 165 | } | 163 | } |
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; | |||
| 14 | use embassy_time::{Duration, Instant}; | 14 | use embassy_time::{Duration, Instant}; |
| 15 | 15 | ||
| 16 | use crate::dma::NoDma; | 16 | use crate::dma::NoDma; |
| 17 | use crate::gpio::sealed::AFType; | 17 | use crate::gpio::{AFType, Pull}; |
| 18 | use crate::gpio::Pull; | ||
| 19 | use crate::interrupt::typelevel::Interrupt; | 18 | use crate::interrupt::typelevel::Interrupt; |
| 20 | use crate::time::Hertz; | 19 | use crate::time::Hertz; |
| 21 | use crate::{interrupt, peripherals}; | 20 | use crate::{interrupt, peripherals}; |
| @@ -175,30 +174,27 @@ impl Timeout { | |||
| 175 | } | 174 | } |
| 176 | } | 175 | } |
| 177 | 176 | ||
| 178 | pub(crate) mod sealed { | 177 | struct State { |
| 179 | use super::*; | 178 | #[allow(unused)] |
| 180 | 179 | waker: AtomicWaker, | |
| 181 | pub struct State { | 180 | } |
| 182 | #[allow(unused)] | ||
| 183 | pub waker: AtomicWaker, | ||
| 184 | } | ||
| 185 | 181 | ||
| 186 | impl State { | 182 | impl State { |
| 187 | pub const fn new() -> Self { | 183 | const fn new() -> Self { |
| 188 | Self { | 184 | Self { |
| 189 | waker: AtomicWaker::new(), | 185 | waker: AtomicWaker::new(), |
| 190 | } | ||
| 191 | } | 186 | } |
| 192 | } | 187 | } |
| 188 | } | ||
| 193 | 189 | ||
| 194 | pub trait Instance: crate::rcc::RccPeripheral { | 190 | trait SealedInstance: crate::rcc::RccPeripheral { |
| 195 | fn regs() -> crate::pac::i2c::I2c; | 191 | fn regs() -> crate::pac::i2c::I2c; |
| 196 | fn state() -> &'static State; | 192 | fn state() -> &'static State; |
| 197 | } | ||
| 198 | } | 193 | } |
| 199 | 194 | ||
| 200 | /// I2C peripheral instance | 195 | /// I2C peripheral instance |
| 201 | pub trait Instance: sealed::Instance + 'static { | 196 | #[allow(private_bounds)] |
| 197 | pub trait Instance: SealedInstance + 'static { | ||
| 202 | /// Event interrupt for this instance | 198 | /// Event interrupt for this instance |
| 203 | type EventInterrupt: interrupt::typelevel::Interrupt; | 199 | type EventInterrupt: interrupt::typelevel::Interrupt; |
| 204 | /// Error interrupt for this instance | 200 | /// Error interrupt for this instance |
| @@ -234,13 +230,13 @@ impl<T: Instance> interrupt::typelevel::Handler<T::ErrorInterrupt> for ErrorInte | |||
| 234 | 230 | ||
| 235 | foreach_peripheral!( | 231 | foreach_peripheral!( |
| 236 | (i2c, $inst:ident) => { | 232 | (i2c, $inst:ident) => { |
| 237 | impl sealed::Instance for peripherals::$inst { | 233 | impl SealedInstance for peripherals::$inst { |
| 238 | fn regs() -> crate::pac::i2c::I2c { | 234 | fn regs() -> crate::pac::i2c::I2c { |
| 239 | crate::pac::$inst | 235 | crate::pac::$inst |
| 240 | } | 236 | } |
| 241 | 237 | ||
| 242 | fn state() -> &'static sealed::State { | 238 | fn state() -> &'static State { |
| 243 | static STATE: sealed::State = sealed::State::new(); | 239 | static STATE: State = State::new(); |
| 244 | &STATE | 240 | &STATE |
| 245 | } | 241 | } |
| 246 | } | 242 | } |
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 @@ | |||
| 1 | //! Inter-IC Sound (I2S) | 1 | //! Inter-IC Sound (I2S) |
| 2 | use embassy_hal_internal::into_ref; | 2 | use embassy_hal_internal::into_ref; |
| 3 | 3 | ||
| 4 | use crate::gpio::sealed::{AFType, Pin as _}; | 4 | use crate::gpio::{AFType, AnyPin, SealedPin}; |
| 5 | use crate::gpio::AnyPin; | ||
| 6 | use crate::pac::spi::vals; | 5 | use crate::pac::spi::vals; |
| 7 | use crate::spi::{Config as SpiConfig, *}; | 6 | use crate::spi::{Config as SpiConfig, *}; |
| 8 | use crate::time::Hertz; | 7 | 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; | |||
| 4 | use core::sync::atomic::{compiler_fence, Ordering}; | 4 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 5 | use core::task::Poll; | 5 | use core::task::Poll; |
| 6 | 6 | ||
| 7 | use self::sealed::Instance; | 7 | use embassy_sync::waitqueue::AtomicWaker; |
| 8 | |||
| 8 | use crate::interrupt; | 9 | use crate::interrupt; |
| 9 | use crate::interrupt::typelevel::Interrupt; | 10 | use crate::interrupt::typelevel::Interrupt; |
| 10 | use crate::peripherals::IPCC; | 11 | use crate::peripherals::IPCC; |
| 11 | use crate::rcc::sealed::RccPeripheral; | 12 | use crate::rcc::SealedRccPeripheral; |
| 12 | 13 | ||
| 13 | /// Interrupt handler. | 14 | /// Interrupt handler. |
| 14 | pub struct ReceiveInterruptHandler {} | 15 | pub struct ReceiveInterruptHandler {} |
| @@ -207,7 +208,7 @@ impl Ipcc { | |||
| 207 | } | 208 | } |
| 208 | } | 209 | } |
| 209 | 210 | ||
| 210 | impl sealed::Instance for crate::peripherals::IPCC { | 211 | impl SealedInstance for crate::peripherals::IPCC { |
| 211 | fn regs() -> crate::pac::ipcc::Ipcc { | 212 | fn regs() -> crate::pac::ipcc::Ipcc { |
| 212 | crate::pac::IPCC | 213 | crate::pac::IPCC |
| 213 | } | 214 | } |
| @@ -216,58 +217,52 @@ impl sealed::Instance for crate::peripherals::IPCC { | |||
| 216 | crate::pac::PWR.cr4().modify(|w| w.set_c2boot(enabled)); | 217 | crate::pac::PWR.cr4().modify(|w| w.set_c2boot(enabled)); |
| 217 | } | 218 | } |
| 218 | 219 | ||
| 219 | fn state() -> &'static self::sealed::State { | 220 | fn state() -> &'static State { |
| 220 | static STATE: self::sealed::State = self::sealed::State::new(); | 221 | static STATE: State = State::new(); |
| 221 | &STATE | 222 | &STATE |
| 222 | } | 223 | } |
| 223 | } | 224 | } |
| 224 | 225 | ||
| 225 | pub(crate) mod sealed { | 226 | struct State { |
| 226 | use embassy_sync::waitqueue::AtomicWaker; | 227 | rx_wakers: [AtomicWaker; 6], |
| 227 | 228 | tx_wakers: [AtomicWaker; 6], | |
| 228 | use super::*; | 229 | } |
| 229 | |||
| 230 | pub struct State { | ||
| 231 | rx_wakers: [AtomicWaker; 6], | ||
| 232 | tx_wakers: [AtomicWaker; 6], | ||
| 233 | } | ||
| 234 | 230 | ||
| 235 | impl State { | 231 | impl State { |
| 236 | pub const fn new() -> Self { | 232 | const fn new() -> Self { |
| 237 | const WAKER: AtomicWaker = AtomicWaker::new(); | 233 | const WAKER: AtomicWaker = AtomicWaker::new(); |
| 238 | 234 | ||
| 239 | Self { | 235 | Self { |
| 240 | rx_wakers: [WAKER; 6], | 236 | rx_wakers: [WAKER; 6], |
| 241 | tx_wakers: [WAKER; 6], | 237 | tx_wakers: [WAKER; 6], |
| 242 | } | ||
| 243 | } | 238 | } |
| 239 | } | ||
| 244 | 240 | ||
| 245 | pub const fn rx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker { | 241 | const fn rx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker { |
| 246 | match channel { | 242 | match channel { |
| 247 | IpccChannel::Channel1 => &self.rx_wakers[0], | 243 | IpccChannel::Channel1 => &self.rx_wakers[0], |
| 248 | IpccChannel::Channel2 => &self.rx_wakers[1], | 244 | IpccChannel::Channel2 => &self.rx_wakers[1], |
| 249 | IpccChannel::Channel3 => &self.rx_wakers[2], | 245 | IpccChannel::Channel3 => &self.rx_wakers[2], |
| 250 | IpccChannel::Channel4 => &self.rx_wakers[3], | 246 | IpccChannel::Channel4 => &self.rx_wakers[3], |
| 251 | IpccChannel::Channel5 => &self.rx_wakers[4], | 247 | IpccChannel::Channel5 => &self.rx_wakers[4], |
| 252 | IpccChannel::Channel6 => &self.rx_wakers[5], | 248 | IpccChannel::Channel6 => &self.rx_wakers[5], |
| 253 | } | ||
| 254 | } | 249 | } |
| 250 | } | ||
| 255 | 251 | ||
| 256 | pub const fn tx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker { | 252 | const fn tx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker { |
| 257 | match channel { | 253 | match channel { |
| 258 | IpccChannel::Channel1 => &self.tx_wakers[0], | 254 | IpccChannel::Channel1 => &self.tx_wakers[0], |
| 259 | IpccChannel::Channel2 => &self.tx_wakers[1], | 255 | IpccChannel::Channel2 => &self.tx_wakers[1], |
| 260 | IpccChannel::Channel3 => &self.tx_wakers[2], | 256 | IpccChannel::Channel3 => &self.tx_wakers[2], |
| 261 | IpccChannel::Channel4 => &self.tx_wakers[3], | 257 | IpccChannel::Channel4 => &self.tx_wakers[3], |
| 262 | IpccChannel::Channel5 => &self.tx_wakers[4], | 258 | IpccChannel::Channel5 => &self.tx_wakers[4], |
| 263 | IpccChannel::Channel6 => &self.tx_wakers[5], | 259 | IpccChannel::Channel6 => &self.tx_wakers[5], |
| 264 | } | ||
| 265 | } | 260 | } |
| 266 | } | 261 | } |
| 262 | } | ||
| 267 | 263 | ||
| 268 | pub trait Instance: crate::rcc::RccPeripheral { | 264 | trait SealedInstance: crate::rcc::RccPeripheral { |
| 269 | fn regs() -> crate::pac::ipcc::Ipcc; | 265 | fn regs() -> crate::pac::ipcc::Ipcc; |
| 270 | fn set_cpu2(enabled: bool); | 266 | fn set_cpu2(enabled: bool); |
| 271 | fn state() -> &'static State; | 267 | fn state() -> &'static State; |
| 272 | } | ||
| 273 | } | 268 | } |
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; | |||
| 158 | use crate::interrupt::Priority; | 158 | use crate::interrupt::Priority; |
| 159 | #[cfg(feature = "rt")] | 159 | #[cfg(feature = "rt")] |
| 160 | pub use crate::pac::NVIC_PRIO_BITS; | 160 | pub use crate::pac::NVIC_PRIO_BITS; |
| 161 | use crate::rcc::sealed::RccPeripheral; | 161 | use crate::rcc::SealedRccPeripheral; |
| 162 | 162 | ||
| 163 | /// `embassy-stm32` global configuration. | 163 | /// `embassy-stm32` global configuration. |
| 164 | #[non_exhaustive] | 164 | #[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> { | |||
| 81 | /// [`OpAmpOutput`] is dropped. | 81 | /// [`OpAmpOutput`] is dropped. |
| 82 | pub fn buffer_ext( | 82 | pub fn buffer_ext( |
| 83 | &'d mut self, | 83 | &'d mut self, |
| 84 | in_pin: impl Peripheral<P = impl NonInvertingPin<T> + crate::gpio::sealed::Pin>, | 84 | in_pin: impl Peripheral<P = impl NonInvertingPin<T> + crate::gpio::Pin>, |
| 85 | out_pin: impl Peripheral<P = impl OutputPin<T> + crate::gpio::sealed::Pin> + 'd, | 85 | out_pin: impl Peripheral<P = impl OutputPin<T> + crate::gpio::Pin> + 'd, |
| 86 | gain: OpAmpGain, | 86 | gain: OpAmpGain, |
| 87 | ) -> OpAmpOutput<'d, T> { | 87 | ) -> OpAmpOutput<'d, T> { |
| 88 | into_ref!(in_pin); | 88 | into_ref!(in_pin); |
| @@ -122,7 +122,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { | |||
| 122 | #[cfg(opamp_g4)] | 122 | #[cfg(opamp_g4)] |
| 123 | pub fn buffer_int( | 123 | pub fn buffer_int( |
| 124 | &'d mut self, | 124 | &'d mut self, |
| 125 | pin: impl Peripheral<P = impl NonInvertingPin<T> + crate::gpio::sealed::Pin>, | 125 | pin: impl Peripheral<P = impl NonInvertingPin<T> + crate::gpio::Pin>, |
| 126 | gain: OpAmpGain, | 126 | gain: OpAmpGain, |
| 127 | ) -> OpAmpInternalOutput<'d, T> { | 127 | ) -> OpAmpInternalOutput<'d, T> { |
| 128 | into_ref!(pin); | 128 | into_ref!(pin); |
| @@ -166,37 +166,39 @@ impl<'d, T: Instance> Drop for OpAmpInternalOutput<'d, T> { | |||
| 166 | } | 166 | } |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | /// Opamp instance trait. | 169 | pub(crate) trait SealedInstance { |
| 170 | pub trait Instance: sealed::Instance + 'static {} | 170 | fn regs() -> crate::pac::opamp::Opamp; |
| 171 | 171 | } | |
| 172 | pub(crate) mod sealed { | ||
| 173 | pub trait Instance { | ||
| 174 | fn regs() -> crate::pac::opamp::Opamp; | ||
| 175 | } | ||
| 176 | |||
| 177 | pub trait NonInvertingPin<T: Instance> { | ||
| 178 | fn channel(&self) -> u8; | ||
| 179 | } | ||
| 180 | 172 | ||
| 181 | pub trait InvertingPin<T: Instance> { | 173 | pub(crate) trait SealedNonInvertingPin<T: Instance> { |
| 182 | fn channel(&self) -> u8; | 174 | fn channel(&self) -> u8; |
| 183 | } | 175 | } |
| 184 | 176 | ||
| 185 | pub trait OutputPin<T: Instance> {} | 177 | pub(crate) trait SealedInvertingPin<T: Instance> { |
| 178 | #[allow(unused)] | ||
| 179 | fn channel(&self) -> u8; | ||
| 186 | } | 180 | } |
| 187 | 181 | ||
| 182 | pub(crate) trait SealedOutputPin<T: Instance> {} | ||
| 183 | |||
| 184 | /// Opamp instance trait. | ||
| 185 | #[allow(private_bounds)] | ||
| 186 | pub trait Instance: SealedInstance + 'static {} | ||
| 188 | /// Non-inverting pin trait. | 187 | /// Non-inverting pin trait. |
| 189 | pub trait NonInvertingPin<T: Instance>: sealed::NonInvertingPin<T> {} | 188 | #[allow(private_bounds)] |
| 189 | pub trait NonInvertingPin<T: Instance>: SealedNonInvertingPin<T> {} | ||
| 190 | /// Inverting pin trait. | 190 | /// Inverting pin trait. |
| 191 | pub trait InvertingPin<T: Instance>: sealed::InvertingPin<T> {} | 191 | #[allow(private_bounds)] |
| 192 | pub trait InvertingPin<T: Instance>: SealedInvertingPin<T> {} | ||
| 192 | /// Output pin trait. | 193 | /// Output pin trait. |
| 193 | pub trait OutputPin<T: Instance>: sealed::OutputPin<T> {} | 194 | #[allow(private_bounds)] |
| 195 | pub trait OutputPin<T: Instance>: SealedOutputPin<T> {} | ||
| 194 | 196 | ||
| 195 | macro_rules! impl_opamp_external_output { | 197 | macro_rules! impl_opamp_external_output { |
| 196 | ($inst:ident, $adc:ident, $ch:expr) => { | 198 | ($inst:ident, $adc:ident, $ch:expr) => { |
| 197 | foreach_adc!( | 199 | foreach_adc!( |
| 198 | ($adc, $common_inst:ident, $adc_clock:ident) => { | 200 | ($adc, $common_inst:ident, $adc_clock:ident) => { |
| 199 | impl<'d> crate::adc::sealed::AdcPin<crate::peripherals::$adc> | 201 | impl<'d> crate::adc::SealedAdcPin<crate::peripherals::$adc> |
| 200 | for OpAmpOutput<'d, crate::peripherals::$inst> | 202 | for OpAmpOutput<'d, crate::peripherals::$inst> |
| 201 | { | 203 | { |
| 202 | fn channel(&self) -> u8 { | 204 | fn channel(&self) -> u8 { |
| @@ -242,7 +244,7 @@ macro_rules! impl_opamp_internal_output { | |||
| 242 | ($inst:ident, $adc:ident, $ch:expr) => { | 244 | ($inst:ident, $adc:ident, $ch:expr) => { |
| 243 | foreach_adc!( | 245 | foreach_adc!( |
| 244 | ($adc, $common_inst:ident, $adc_clock:ident) => { | 246 | ($adc, $common_inst:ident, $adc_clock:ident) => { |
| 245 | impl<'d> crate::adc::sealed::AdcPin<crate::peripherals::$adc> | 247 | impl<'d> crate::adc::SealedAdcPin<crate::peripherals::$adc> |
| 246 | for OpAmpInternalOutput<'d, crate::peripherals::$inst> | 248 | for OpAmpInternalOutput<'d, crate::peripherals::$inst> |
| 247 | { | 249 | { |
| 248 | fn channel(&self) -> u8 { | 250 | fn channel(&self) -> u8 { |
| @@ -291,7 +293,7 @@ foreach_peripheral!( | |||
| 291 | 293 | ||
| 292 | foreach_peripheral! { | 294 | foreach_peripheral! { |
| 293 | (opamp, $inst:ident) => { | 295 | (opamp, $inst:ident) => { |
| 294 | impl sealed::Instance for crate::peripherals::$inst { | 296 | impl SealedInstance for crate::peripherals::$inst { |
| 295 | fn regs() -> crate::pac::opamp::Opamp { | 297 | fn regs() -> crate::pac::opamp::Opamp { |
| 296 | crate::pac::$inst | 298 | crate::pac::$inst |
| 297 | } | 299 | } |
| @@ -306,7 +308,7 @@ foreach_peripheral! { | |||
| 306 | macro_rules! impl_opamp_vp_pin { | 308 | macro_rules! impl_opamp_vp_pin { |
| 307 | ($inst:ident, $pin:ident, $ch:expr) => { | 309 | ($inst:ident, $pin:ident, $ch:expr) => { |
| 308 | impl crate::opamp::NonInvertingPin<peripherals::$inst> for crate::peripherals::$pin {} | 310 | impl crate::opamp::NonInvertingPin<peripherals::$inst> for crate::peripherals::$pin {} |
| 309 | impl crate::opamp::sealed::NonInvertingPin<peripherals::$inst> for crate::peripherals::$pin { | 311 | impl crate::opamp::SealedNonInvertingPin<peripherals::$inst> for crate::peripherals::$pin { |
| 310 | fn channel(&self) -> u8 { | 312 | fn channel(&self) -> u8 { |
| 311 | $ch | 313 | $ch |
| 312 | } | 314 | } |
| @@ -318,6 +320,6 @@ macro_rules! impl_opamp_vp_pin { | |||
| 318 | macro_rules! impl_opamp_vout_pin { | 320 | macro_rules! impl_opamp_vout_pin { |
| 319 | ($inst:ident, $pin:ident) => { | 321 | ($inst:ident, $pin:ident) => { |
| 320 | impl crate::opamp::OutputPin<peripherals::$inst> for crate::peripherals::$pin {} | 322 | impl crate::opamp::OutputPin<peripherals::$inst> for crate::peripherals::$pin {} |
| 321 | impl crate::opamp::sealed::OutputPin<peripherals::$inst> for crate::peripherals::$pin {} | 323 | impl crate::opamp::SealedOutputPin<peripherals::$inst> for crate::peripherals::$pin {} |
| 322 | }; | 324 | }; |
| 323 | } | 325 | } |
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}; | |||
| 8 | use enums::*; | 8 | use enums::*; |
| 9 | 9 | ||
| 10 | use crate::dma::Transfer; | 10 | use crate::dma::Transfer; |
| 11 | use crate::gpio::sealed::AFType; | 11 | use crate::gpio::{AFType, AnyPin, Pull}; |
| 12 | use crate::gpio::{AnyPin, Pull}; | ||
| 13 | use crate::pac::quadspi::Quadspi as Regs; | 12 | use crate::pac::quadspi::Quadspi as Regs; |
| 14 | use crate::rcc::RccPeripheral; | 13 | use crate::rcc::RccPeripheral; |
| 15 | use crate::{peripherals, Peripheral}; | 14 | use crate::{peripherals, Peripheral}; |
| @@ -381,16 +380,13 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { | |||
| 381 | } | 380 | } |
| 382 | } | 381 | } |
| 383 | 382 | ||
| 384 | pub(crate) mod sealed { | 383 | trait SealedInstance { |
| 385 | use super::*; | 384 | const REGS: Regs; |
| 386 | |||
| 387 | pub trait Instance { | ||
| 388 | const REGS: Regs; | ||
| 389 | } | ||
| 390 | } | 385 | } |
| 391 | 386 | ||
| 392 | /// QSPI instance trait. | 387 | /// QSPI instance trait. |
| 393 | pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} | 388 | #[allow(private_bounds)] |
| 389 | pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {} | ||
| 394 | 390 | ||
| 395 | pin_trait!(SckPin, Instance); | 391 | pin_trait!(SckPin, Instance); |
| 396 | pin_trait!(BK1D0Pin, Instance); | 392 | pin_trait!(BK1D0Pin, Instance); |
| @@ -409,7 +405,7 @@ dma_trait!(QuadDma, Instance); | |||
| 409 | 405 | ||
| 410 | foreach_peripheral!( | 406 | foreach_peripheral!( |
| 411 | (quadspi, $inst:ident) => { | 407 | (quadspi, $inst:ident) => { |
| 412 | impl sealed::Instance for peripherals::$inst { | 408 | impl SealedInstance for peripherals::$inst { |
| 413 | const REGS: Regs = crate::pac::$inst; | 409 | const REGS: Regs = crate::pac::$inst; |
| 414 | } | 410 | } |
| 415 | 411 | ||
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 @@ | |||
| 2 | 2 | ||
| 3 | use crate::pac::crs::vals::Syncsrc; | 3 | use crate::pac::crs::vals::Syncsrc; |
| 4 | use crate::pac::{CRS, RCC}; | 4 | use crate::pac::{CRS, RCC}; |
| 5 | use crate::rcc::sealed::RccPeripheral; | 5 | use crate::rcc::SealedRccPeripheral; |
| 6 | use crate::time::Hertz; | 6 | use crate::time::Hertz; |
| 7 | 7 | ||
| 8 | /// HSI48 speed | 8 | /// 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; | |||
| 2 | 2 | ||
| 3 | use embassy_hal_internal::into_ref; | 3 | use embassy_hal_internal::into_ref; |
| 4 | 4 | ||
| 5 | use crate::gpio::sealed::AFType; | 5 | use crate::gpio::{AFType, Speed}; |
| 6 | use crate::gpio::Speed; | ||
| 7 | #[cfg(not(any(stm32f1, rcc_f0v1, rcc_f3v1, rcc_f37)))] | 6 | #[cfg(not(any(stm32f1, rcc_f0v1, rcc_f3v1, rcc_f37)))] |
| 8 | pub use crate::pac::rcc::vals::Mcopre as McoPrescaler; | 7 | pub use crate::pac::rcc::vals::Mcopre as McoPrescaler; |
| 9 | #[cfg(not(any(rcc_f2, rcc_f410, rcc_f4, rcc_f7, rcc_h50, rcc_h5, rcc_h7ab, rcc_h7rm0433, rcc_h7)))] | 8 | #[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 { | |||
| 19 | DIV1, | 18 | DIV1, |
| 20 | } | 19 | } |
| 21 | 20 | ||
| 22 | pub(crate) mod sealed { | 21 | pub(crate) trait SealedMcoInstance {} |
| 23 | pub trait McoInstance { | ||
| 24 | type Source; | ||
| 25 | unsafe fn apply_clock_settings(source: Self::Source, prescaler: super::McoPrescaler); | ||
| 26 | } | ||
| 27 | } | ||
| 28 | 22 | ||
| 29 | pub trait McoInstance: sealed::McoInstance + 'static {} | 23 | #[allow(private_bounds)] |
| 24 | pub trait McoInstance: SealedMcoInstance + 'static { | ||
| 25 | type Source; | ||
| 26 | |||
| 27 | #[doc(hidden)] | ||
| 28 | unsafe fn _apply_clock_settings(source: Self::Source, prescaler: super::McoPrescaler); | ||
| 29 | } | ||
| 30 | 30 | ||
| 31 | pin_trait!(McoPin, McoInstance); | 31 | pin_trait!(McoPin, McoInstance); |
| 32 | 32 | ||
| 33 | macro_rules! impl_peri { | 33 | macro_rules! impl_peri { |
| 34 | ($peri:ident, $source:ident, $set_source:ident, $set_prescaler:ident) => { | 34 | ($peri:ident, $source:ident, $set_source:ident, $set_prescaler:ident) => { |
| 35 | impl sealed::McoInstance for peripherals::$peri { | 35 | impl SealedMcoInstance for peripherals::$peri {} |
| 36 | impl McoInstance for peripherals::$peri { | ||
| 36 | type Source = $source; | 37 | type Source = $source; |
| 37 | 38 | ||
| 38 | unsafe fn apply_clock_settings(source: Self::Source, _prescaler: McoPrescaler) { | 39 | unsafe fn _apply_clock_settings(source: Self::Source, _prescaler: McoPrescaler) { |
| 39 | #[cfg(not(any(stm32u5, stm32wba)))] | 40 | #[cfg(not(any(stm32u5, stm32wba)))] |
| 40 | let r = RCC.cfgr(); | 41 | let r = RCC.cfgr(); |
| 41 | #[cfg(any(stm32u5, stm32wba))] | 42 | #[cfg(any(stm32u5, stm32wba))] |
| @@ -48,8 +49,6 @@ macro_rules! impl_peri { | |||
| 48 | }); | 49 | }); |
| 49 | } | 50 | } |
| 50 | } | 51 | } |
| 51 | |||
| 52 | impl McoInstance for peripherals::$peri {} | ||
| 53 | }; | 52 | }; |
| 54 | } | 53 | } |
| 55 | 54 | ||
| @@ -79,7 +78,7 @@ impl<'d, T: McoInstance> Mco<'d, T> { | |||
| 79 | into_ref!(pin); | 78 | into_ref!(pin); |
| 80 | 79 | ||
| 81 | critical_section::with(|_| unsafe { | 80 | critical_section::with(|_| unsafe { |
| 82 | T::apply_clock_settings(source, prescaler); | 81 | T::_apply_clock_settings(source, prescaler); |
| 83 | pin.set_as_af(pin.af_num(), AFType::OutputPushPull); | 82 | pin.set_as_af(pin.af_num(), AFType::OutputPushPull); |
| 84 | pin.set_speed(Speed::VeryHigh); | 83 | pin.set_speed(Speed::VeryHigh); |
| 85 | }); | 84 | }); |
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::*; | |||
| 10 | 10 | ||
| 11 | #[cfg(any(mco, mco1, mco2))] | 11 | #[cfg(any(mco, mco1, mco2))] |
| 12 | mod mco; | 12 | mod mco; |
| 13 | use critical_section::CriticalSection; | ||
| 13 | #[cfg(any(mco, mco1, mco2))] | 14 | #[cfg(any(mco, mco1, mco2))] |
| 14 | pub use mco::*; | 15 | pub use mco::*; |
| 15 | 16 | ||
| @@ -32,6 +33,7 @@ mod _version; | |||
| 32 | pub use _version::*; | 33 | pub use _version::*; |
| 33 | 34 | ||
| 34 | pub use crate::_generated::{mux, Clocks}; | 35 | pub use crate::_generated::{mux, Clocks}; |
| 36 | use crate::time::Hertz; | ||
| 35 | 37 | ||
| 36 | #[cfg(feature = "low-power")] | 38 | #[cfg(feature = "low-power")] |
| 37 | /// Must be written within a critical section | 39 | /// Must be written within a critical section |
| @@ -63,29 +65,21 @@ pub(crate) unsafe fn get_freqs() -> &'static Clocks { | |||
| 63 | CLOCK_FREQS.assume_init_ref() | 65 | CLOCK_FREQS.assume_init_ref() |
| 64 | } | 66 | } |
| 65 | 67 | ||
| 66 | #[cfg(feature = "unstable-pac")] | 68 | pub(crate) trait SealedRccPeripheral { |
| 67 | pub mod low_level { | 69 | fn frequency() -> crate::time::Hertz; |
| 68 | pub use super::sealed::*; | 70 | fn enable_and_reset_with_cs(cs: CriticalSection); |
| 69 | } | 71 | fn disable_with_cs(cs: CriticalSection); |
| 70 | |||
| 71 | pub(crate) mod sealed { | ||
| 72 | use critical_section::CriticalSection; | ||
| 73 | |||
| 74 | pub trait RccPeripheral { | ||
| 75 | fn frequency() -> crate::time::Hertz; | ||
| 76 | fn enable_and_reset_with_cs(cs: CriticalSection); | ||
| 77 | fn disable_with_cs(cs: CriticalSection); | ||
| 78 | 72 | ||
| 79 | fn enable_and_reset() { | 73 | fn enable_and_reset() { |
| 80 | critical_section::with(|cs| Self::enable_and_reset_with_cs(cs)) | 74 | critical_section::with(|cs| Self::enable_and_reset_with_cs(cs)) |
| 81 | } | 75 | } |
| 82 | fn disable() { | 76 | fn disable() { |
| 83 | critical_section::with(|cs| Self::disable_with_cs(cs)) | 77 | critical_section::with(|cs| Self::disable_with_cs(cs)) |
| 84 | } | ||
| 85 | } | 78 | } |
| 86 | } | 79 | } |
| 87 | 80 | ||
| 88 | pub trait RccPeripheral: sealed::RccPeripheral + 'static {} | 81 | #[allow(private_bounds)] |
| 82 | pub trait RccPeripheral: SealedRccPeripheral + 'static {} | ||
| 89 | 83 | ||
| 90 | #[allow(unused)] | 84 | #[allow(unused)] |
| 91 | mod util { | 85 | mod util { |
| @@ -116,3 +110,12 @@ mod util { | |||
| 116 | Ok(Some(x)) | 110 | Ok(Some(x)) |
| 117 | } | 111 | } |
| 118 | } | 112 | } |
| 113 | |||
| 114 | /// Get the kernel clocok frequency of the peripheral `T`. | ||
| 115 | /// | ||
| 116 | /// # Panics | ||
| 117 | /// | ||
| 118 | /// Panics if the clock is not active. | ||
| 119 | pub fn frequency<T: RccPeripheral>() -> Hertz { | ||
| 120 | T::frequency() | ||
| 121 | } | ||
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> { | |||
| 222 | 222 | ||
| 223 | impl<'d, T: Instance> CryptoRng for Rng<'d, T> {} | 223 | impl<'d, T: Instance> CryptoRng for Rng<'d, T> {} |
| 224 | 224 | ||
| 225 | pub(crate) mod sealed { | 225 | trait SealedInstance { |
| 226 | use super::*; | 226 | fn regs() -> pac::rng::Rng; |
| 227 | |||
| 228 | pub trait Instance { | ||
| 229 | fn regs() -> pac::rng::Rng; | ||
| 230 | } | ||
| 231 | } | 227 | } |
| 232 | 228 | ||
| 233 | /// RNG instance trait. | 229 | /// RNG instance trait. |
| 234 | pub trait Instance: sealed::Instance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send { | 230 | #[allow(private_bounds)] |
| 231 | pub trait Instance: SealedInstance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send { | ||
| 235 | /// Interrupt for this RNG instance. | 232 | /// Interrupt for this RNG instance. |
| 236 | type Interrupt: interrupt::typelevel::Interrupt; | 233 | type Interrupt: interrupt::typelevel::Interrupt; |
| 237 | } | 234 | } |
| @@ -242,7 +239,7 @@ foreach_interrupt!( | |||
| 242 | type Interrupt = crate::interrupt::typelevel::$irq; | 239 | type Interrupt = crate::interrupt::typelevel::$irq; |
| 243 | } | 240 | } |
| 244 | 241 | ||
| 245 | impl sealed::Instance for peripherals::$inst { | 242 | impl SealedInstance for peripherals::$inst { |
| 246 | fn regs() -> crate::pac::rng::Rng { | 243 | fn regs() -> crate::pac::rng::Rng { |
| 247 | crate::pac::$inst | 244 | crate::pac::$inst |
| 248 | } | 245 | } |
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}; | |||
| 4 | #[cfg(any(feature = "defmt", feature = "time"))] | 4 | #[cfg(any(feature = "defmt", feature = "time"))] |
| 5 | use crate::peripherals::RTC; | 5 | use crate::peripherals::RTC; |
| 6 | #[cfg(any(feature = "defmt", feature = "time"))] | 6 | #[cfg(any(feature = "defmt", feature = "time"))] |
| 7 | use crate::rtc::sealed::Instance; | 7 | use crate::rtc::SealedInstance; |
| 8 | 8 | ||
| 9 | /// Represents an instant in time that can be substracted to compute a duration | 9 | /// Represents an instant in time that can be substracted to compute a duration |
| 10 | pub struct RtcInstant { | 10 | 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::*; | |||
| 31 | use embassy_hal_internal::Peripheral; | 31 | use embassy_hal_internal::Peripheral; |
| 32 | 32 | ||
| 33 | use crate::peripherals::RTC; | 33 | use crate::peripherals::RTC; |
| 34 | use crate::rtc::sealed::Instance; | ||
| 35 | 34 | ||
| 36 | #[allow(dead_code)] | 35 | #[allow(dead_code)] |
| 37 | #[repr(u8)] | 36 | #[repr(u8)] |
| @@ -212,7 +211,7 @@ impl Rtc { | |||
| 212 | /// Create a new RTC instance. | 211 | /// Create a new RTC instance. |
| 213 | pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self { | 212 | pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self { |
| 214 | #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))] | 213 | #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))] |
| 215 | <RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset(); | 214 | <RTC as crate::rcc::SealedRccPeripheral>::enable_and_reset(); |
| 216 | 215 | ||
| 217 | let mut this = Self { | 216 | let mut this = Self { |
| 218 | #[cfg(feature = "low-power")] | 217 | #[cfg(feature = "low-power")] |
| @@ -437,7 +436,7 @@ impl Rtc { | |||
| 437 | .fpr(0) | 436 | .fpr(0) |
| 438 | .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); | 437 | .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); |
| 439 | 438 | ||
| 440 | <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::unpend(); | 439 | <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::unpend(); |
| 441 | }); | 440 | }); |
| 442 | } | 441 | } |
| 443 | 442 | ||
| @@ -449,8 +448,8 @@ impl Rtc { | |||
| 449 | use crate::interrupt::typelevel::Interrupt; | 448 | use crate::interrupt::typelevel::Interrupt; |
| 450 | use crate::pac::EXTI; | 449 | use crate::pac::EXTI; |
| 451 | 450 | ||
| 452 | <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::unpend(); | 451 | <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::unpend(); |
| 453 | unsafe { <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::enable() }; | 452 | unsafe { <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::enable() }; |
| 454 | 453 | ||
| 455 | EXTI.rtsr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); | 454 | EXTI.rtsr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); |
| 456 | EXTI.imr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); | 455 | 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 { | |||
| 477 | tmp + (value & 0x0F) | 476 | tmp + (value & 0x0F) |
| 478 | } | 477 | } |
| 479 | 478 | ||
| 480 | pub(crate) mod sealed { | 479 | trait SealedInstance { |
| 481 | use crate::pac::rtc::Rtc; | 480 | const BACKUP_REGISTER_COUNT: usize; |
| 482 | 481 | ||
| 483 | pub trait Instance { | 482 | #[cfg(feature = "low-power")] |
| 484 | const BACKUP_REGISTER_COUNT: usize; | 483 | const EXTI_WAKEUP_LINE: usize; |
| 485 | |||
| 486 | #[cfg(feature = "low-power")] | ||
| 487 | const EXTI_WAKEUP_LINE: usize; | ||
| 488 | 484 | ||
| 489 | #[cfg(feature = "low-power")] | 485 | #[cfg(feature = "low-power")] |
| 490 | type WakeupInterrupt: crate::interrupt::typelevel::Interrupt; | 486 | type WakeupInterrupt: crate::interrupt::typelevel::Interrupt; |
| 491 | 487 | ||
| 492 | fn regs() -> Rtc { | 488 | fn regs() -> crate::pac::rtc::Rtc { |
| 493 | crate::pac::RTC | 489 | crate::pac::RTC |
| 494 | } | 490 | } |
| 495 | 491 | ||
| 496 | /// Read content of the backup register. | 492 | /// Read content of the backup register. |
| 497 | /// | 493 | /// |
| 498 | /// The registers retain their values during wakes from standby mode or system resets. They also | 494 | /// The registers retain their values during wakes from standby mode or system resets. They also |
| 499 | /// retain their value when Vdd is switched off as long as V_BAT is powered. | 495 | /// retain their value when Vdd is switched off as long as V_BAT is powered. |
| 500 | fn read_backup_register(rtc: &Rtc, register: usize) -> Option<u32>; | 496 | fn read_backup_register(rtc: &crate::pac::rtc::Rtc, register: usize) -> Option<u32>; |
| 501 | 497 | ||
| 502 | /// Set content of the backup register. | 498 | /// Set content of the backup register. |
| 503 | /// | 499 | /// |
| 504 | /// The registers retain their values during wakes from standby mode or system resets. They also | 500 | /// The registers retain their values during wakes from standby mode or system resets. They also |
| 505 | /// retain their value when Vdd is switched off as long as V_BAT is powered. | 501 | /// retain their value when Vdd is switched off as long as V_BAT is powered. |
| 506 | fn write_backup_register(rtc: &Rtc, register: usize, value: u32); | 502 | fn write_backup_register(rtc: &crate::pac::rtc::Rtc, register: usize, value: u32); |
| 507 | 503 | ||
| 508 | // fn apply_config(&mut self, rtc_config: RtcConfig); | 504 | // fn apply_config(&mut self, rtc_config: RtcConfig); |
| 509 | } | ||
| 510 | } | 505 | } |
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 @@ | |||
| 1 | use stm32_metapac::rtc::vals::{Osel, Pol}; | 1 | use stm32_metapac::rtc::vals::{Osel, Pol}; |
| 2 | 2 | ||
| 3 | use super::sealed; | 3 | use super::SealedInstance; |
| 4 | use crate::pac::rtc::Rtc; | 4 | use crate::pac::rtc::Rtc; |
| 5 | use crate::peripherals::RTC; | 5 | use crate::peripherals::RTC; |
| 6 | use crate::rtc::sealed::Instance; | ||
| 7 | 6 | ||
| 8 | #[allow(dead_code)] | 7 | #[allow(dead_code)] |
| 9 | impl super::Rtc { | 8 | impl super::Rtc { |
| @@ -126,7 +125,7 @@ impl super::Rtc { | |||
| 126 | } | 125 | } |
| 127 | } | 126 | } |
| 128 | 127 | ||
| 129 | impl sealed::Instance for crate::peripherals::RTC { | 128 | impl SealedInstance for crate::peripherals::RTC { |
| 130 | const BACKUP_REGISTER_COUNT: usize = 20; | 129 | const BACKUP_REGISTER_COUNT: usize = 20; |
| 131 | 130 | ||
| 132 | #[cfg(all(feature = "low-power", stm32f4))] | 131 | #[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 @@ | |||
| 1 | use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Key, Osel, Pol, TampalrmType}; | 1 | use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Key, Osel, Pol, TampalrmType}; |
| 2 | 2 | ||
| 3 | use super::{sealed, RtcCalibrationCyclePeriod}; | 3 | use super::RtcCalibrationCyclePeriod; |
| 4 | use crate::pac::rtc::Rtc; | 4 | use crate::pac::rtc::Rtc; |
| 5 | use crate::peripherals::RTC; | 5 | use crate::peripherals::RTC; |
| 6 | use crate::rtc::sealed::Instance; | 6 | use crate::rtc::SealedInstance; |
| 7 | 7 | ||
| 8 | impl super::Rtc { | 8 | impl super::Rtc { |
| 9 | /// Applies the RTC config | 9 | /// Applies the RTC config |
| @@ -126,7 +126,7 @@ impl super::Rtc { | |||
| 126 | } | 126 | } |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | impl sealed::Instance for crate::peripherals::RTC { | 129 | impl SealedInstance for crate::peripherals::RTC { |
| 130 | const BACKUP_REGISTER_COUNT: usize = 32; | 130 | const BACKUP_REGISTER_COUNT: usize = 32; |
| 131 | 131 | ||
| 132 | #[cfg(all(feature = "low-power", stm32g4))] | 132 | #[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; | |||
| 6 | 6 | ||
| 7 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 7 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 8 | 8 | ||
| 9 | use self::sealed::WhichSubBlock; | ||
| 10 | pub use crate::dma::word; | 9 | pub use crate::dma::word; |
| 11 | #[cfg(not(gpdma))] | 10 | #[cfg(not(gpdma))] |
| 12 | use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer}; | 11 | use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer}; |
| 13 | use crate::gpio::sealed::{AFType, Pin as _}; | 12 | use crate::gpio::{AFType, AnyPin, SealedPin as _}; |
| 14 | use crate::gpio::AnyPin; | ||
| 15 | use crate::pac::sai::{vals, Sai as Regs}; | 13 | use crate::pac::sai::{vals, Sai as Regs}; |
| 16 | use crate::rcc::RccPeripheral; | 14 | use crate::rcc::RccPeripheral; |
| 17 | use crate::{peripherals, Peripheral}; | 15 | use crate::{peripherals, Peripheral}; |
| @@ -1041,43 +1039,42 @@ impl<'d, T: Instance, W: word::Word> Drop for Sai<'d, T, W> { | |||
| 1041 | } | 1039 | } |
| 1042 | } | 1040 | } |
| 1043 | 1041 | ||
| 1044 | pub(crate) mod sealed { | 1042 | trait SealedInstance { |
| 1045 | use super::*; | 1043 | const REGS: Regs; |
| 1046 | 1044 | } | |
| 1047 | pub trait Instance { | ||
| 1048 | const REGS: Regs; | ||
| 1049 | } | ||
| 1050 | 1045 | ||
| 1051 | #[derive(Copy, Clone)] | 1046 | #[derive(Copy, Clone)] |
| 1052 | pub enum WhichSubBlock { | 1047 | enum WhichSubBlock { |
| 1053 | A = 0, | 1048 | A = 0, |
| 1054 | B = 1, | 1049 | B = 1, |
| 1055 | } | 1050 | } |
| 1056 | 1051 | ||
| 1057 | pub trait SubBlock { | 1052 | trait SealedSubBlock { |
| 1058 | const WHICH: WhichSubBlock; | 1053 | const WHICH: WhichSubBlock; |
| 1059 | } | ||
| 1060 | } | 1054 | } |
| 1061 | 1055 | ||
| 1062 | /// Sub-block instance trait. | 1056 | /// Sub-block instance trait. |
| 1063 | pub trait SubBlockInstance: sealed::SubBlock {} | 1057 | #[allow(private_bounds)] |
| 1058 | pub trait SubBlockInstance: SealedSubBlock {} | ||
| 1064 | 1059 | ||
| 1065 | /// Sub-block A. | 1060 | /// Sub-block A. |
| 1066 | pub enum A {} | 1061 | pub enum A {} |
| 1067 | impl sealed::SubBlock for A { | 1062 | impl SealedSubBlock for A { |
| 1068 | const WHICH: WhichSubBlock = WhichSubBlock::A; | 1063 | const WHICH: WhichSubBlock = WhichSubBlock::A; |
| 1069 | } | 1064 | } |
| 1070 | impl SubBlockInstance for A {} | 1065 | impl SubBlockInstance for A {} |
| 1071 | 1066 | ||
| 1072 | /// Sub-block B. | 1067 | /// Sub-block B. |
| 1073 | pub enum B {} | 1068 | pub enum B {} |
| 1074 | impl sealed::SubBlock for B { | 1069 | impl SealedSubBlock for B { |
| 1075 | const WHICH: WhichSubBlock = WhichSubBlock::B; | 1070 | const WHICH: WhichSubBlock = WhichSubBlock::B; |
| 1076 | } | 1071 | } |
| 1077 | impl SubBlockInstance for B {} | 1072 | impl SubBlockInstance for B {} |
| 1078 | 1073 | ||
| 1079 | /// SAI instance trait. | 1074 | /// SAI instance trait. |
| 1080 | pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} | 1075 | #[allow(private_bounds)] |
| 1076 | pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {} | ||
| 1077 | |||
| 1081 | pin_trait!(SckPin, Instance, SubBlockInstance); | 1078 | pin_trait!(SckPin, Instance, SubBlockInstance); |
| 1082 | pin_trait!(FsPin, Instance, SubBlockInstance); | 1079 | pin_trait!(FsPin, Instance, SubBlockInstance); |
| 1083 | pin_trait!(SdPin, Instance, SubBlockInstance); | 1080 | pin_trait!(SdPin, Instance, SubBlockInstance); |
| @@ -1087,7 +1084,7 @@ dma_trait!(Dma, Instance, SubBlockInstance); | |||
| 1087 | 1084 | ||
| 1088 | foreach_peripheral!( | 1085 | foreach_peripheral!( |
| 1089 | (sai, $inst:ident) => { | 1086 | (sai, $inst:ident) => { |
| 1090 | impl sealed::Instance for peripherals::$inst { | 1087 | impl SealedInstance for peripherals::$inst { |
| 1091 | const REGS: Regs = crate::pac::$inst; | 1088 | const REGS: Regs = crate::pac::$inst; |
| 1092 | } | 1089 | } |
| 1093 | 1090 | ||
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; | |||
| 13 | use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; | 13 | use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; |
| 14 | 14 | ||
| 15 | use crate::dma::NoDma; | 15 | use crate::dma::NoDma; |
| 16 | use crate::gpio::sealed::{AFType, Pin}; | 16 | use crate::gpio::{AFType, AnyPin, Pull, SealedPin, Speed}; |
| 17 | use crate::gpio::{AnyPin, Pull, Speed}; | ||
| 18 | use crate::interrupt::typelevel::Interrupt; | 17 | use crate::interrupt::typelevel::Interrupt; |
| 19 | use crate::pac::sdmmc::Sdmmc as RegBlock; | 18 | use crate::pac::sdmmc::Sdmmc as RegBlock; |
| 20 | use crate::rcc::RccPeripheral; | 19 | use crate::rcc::RccPeripheral; |
| @@ -1418,19 +1417,17 @@ impl Cmd { | |||
| 1418 | 1417 | ||
| 1419 | ////////////////////////////////////////////////////// | 1418 | ////////////////////////////////////////////////////// |
| 1420 | 1419 | ||
| 1421 | pub(crate) mod sealed { | 1420 | trait SealedInstance { |
| 1422 | use super::*; | 1421 | fn regs() -> RegBlock; |
| 1423 | 1422 | fn state() -> &'static AtomicWaker; | |
| 1424 | pub trait Instance { | ||
| 1425 | type Interrupt: interrupt::typelevel::Interrupt; | ||
| 1426 | |||
| 1427 | fn regs() -> RegBlock; | ||
| 1428 | fn state() -> &'static AtomicWaker; | ||
| 1429 | } | ||
| 1430 | } | 1423 | } |
| 1431 | 1424 | ||
| 1432 | /// SDMMC instance trait. | 1425 | /// SDMMC instance trait. |
| 1433 | pub trait Instance: sealed::Instance + RccPeripheral + 'static {} | 1426 | #[allow(private_bounds)] |
| 1427 | pub trait Instance: SealedInstance + RccPeripheral + 'static { | ||
| 1428 | /// Interrupt for this instance. | ||
| 1429 | type Interrupt: interrupt::typelevel::Interrupt; | ||
| 1430 | } | ||
| 1434 | 1431 | ||
| 1435 | pin_trait!(CkPin, Instance); | 1432 | pin_trait!(CkPin, Instance); |
| 1436 | pin_trait!(CmdPin, Instance); | 1433 | pin_trait!(CmdPin, Instance); |
| @@ -1457,9 +1454,7 @@ impl<T: Instance> SdmmcDma<T> for NoDma {} | |||
| 1457 | 1454 | ||
| 1458 | foreach_peripheral!( | 1455 | foreach_peripheral!( |
| 1459 | (sdmmc, $inst:ident) => { | 1456 | (sdmmc, $inst:ident) => { |
| 1460 | impl sealed::Instance for peripherals::$inst { | 1457 | impl SealedInstance for peripherals::$inst { |
| 1461 | type Interrupt = crate::interrupt::typelevel::$inst; | ||
| 1462 | |||
| 1463 | fn regs() -> RegBlock { | 1458 | fn regs() -> RegBlock { |
| 1464 | crate::pac::$inst | 1459 | crate::pac::$inst |
| 1465 | } | 1460 | } |
| @@ -1470,6 +1465,8 @@ foreach_peripheral!( | |||
| 1470 | } | 1465 | } |
| 1471 | } | 1466 | } |
| 1472 | 1467 | ||
| 1473 | impl Instance for peripherals::$inst {} | 1468 | impl Instance for peripherals::$inst { |
| 1469 | type Interrupt = crate::interrupt::typelevel::$inst; | ||
| 1470 | } | ||
| 1474 | }; | 1471 | }; |
| 1475 | ); | 1472 | ); |
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}; | |||
| 9 | pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; | 9 | pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; |
| 10 | 10 | ||
| 11 | use crate::dma::{slice_ptr_parts, word, Transfer}; | 11 | use crate::dma::{slice_ptr_parts, word, Transfer}; |
| 12 | use crate::gpio::sealed::{AFType, Pin as _}; | 12 | use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _}; |
| 13 | use crate::gpio::{AnyPin, Pull}; | ||
| 14 | use crate::pac::spi::{regs, vals, Spi as Regs}; | 13 | use crate::pac::spi::{regs, vals, Spi as Regs}; |
| 15 | use crate::rcc::RccPeripheral; | 14 | use crate::rcc::RccPeripheral; |
| 16 | use crate::time::Hertz; | 15 | use crate::time::Hertz; |
| @@ -210,7 +209,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 210 | // see RM0453 rev 1 section 7.2.13 page 291 | 209 | // see RM0453 rev 1 section 7.2.13 page 291 |
| 211 | // The SUBGHZSPI_SCK frequency is obtained by PCLK3 divided by two. | 210 | // The SUBGHZSPI_SCK frequency is obtained by PCLK3 divided by two. |
| 212 | // The SUBGHZSPI_SCK clock maximum speed must not exceed 16 MHz. | 211 | // The SUBGHZSPI_SCK clock maximum speed must not exceed 16 MHz. |
| 213 | let pclk3_freq = <peripherals::SUBGHZSPI as crate::rcc::sealed::RccPeripheral>::frequency().0; | 212 | let pclk3_freq = <peripherals::SUBGHZSPI as crate::rcc::SealedRccPeripheral>::frequency().0; |
| 214 | let freq = Hertz(core::cmp::min(pclk3_freq / 2, 16_000_000)); | 213 | let freq = Hertz(core::cmp::min(pclk3_freq / 2, 16_000_000)); |
| 215 | let mut config = Config::default(); | 214 | let mut config = Config::default(); |
| 216 | config.mode = MODE_0; | 215 | config.mode = MODE_0; |
| @@ -271,13 +270,13 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 271 | if mosi.is_none() { | 270 | if mosi.is_none() { |
| 272 | w.set_rxonly(vals::Rxonly::OUTPUTDISABLED); | 271 | w.set_rxonly(vals::Rxonly::OUTPUTDISABLED); |
| 273 | } | 272 | } |
| 274 | w.set_dff(<u8 as sealed::Word>::CONFIG) | 273 | w.set_dff(<u8 as SealedWord>::CONFIG) |
| 275 | }); | 274 | }); |
| 276 | } | 275 | } |
| 277 | #[cfg(spi_v2)] | 276 | #[cfg(spi_v2)] |
| 278 | { | 277 | { |
| 279 | T::REGS.cr2().modify(|w| { | 278 | T::REGS.cr2().modify(|w| { |
| 280 | let (ds, frxth) = <u8 as sealed::Word>::CONFIG; | 279 | let (ds, frxth) = <u8 as SealedWord>::CONFIG; |
| 281 | w.set_frxth(frxth); | 280 | w.set_frxth(frxth); |
| 282 | w.set_ds(ds); | 281 | w.set_ds(ds); |
| 283 | w.set_ssoe(false); | 282 | w.set_ssoe(false); |
| @@ -317,7 +316,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 317 | T::REGS.cfg1().modify(|w| { | 316 | T::REGS.cfg1().modify(|w| { |
| 318 | w.set_crcen(false); | 317 | w.set_crcen(false); |
| 319 | w.set_mbr(br); | 318 | w.set_mbr(br); |
| 320 | w.set_dsize(<u8 as sealed::Word>::CONFIG); | 319 | w.set_dsize(<u8 as SealedWord>::CONFIG); |
| 321 | w.set_fthlv(vals::Fthlv::ONEFRAME); | 320 | w.set_fthlv(vals::Fthlv::ONEFRAME); |
| 322 | }); | 321 | }); |
| 323 | T::REGS.cr2().modify(|w| { | 322 | T::REGS.cr2().modify(|w| { |
| @@ -336,7 +335,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 336 | miso, | 335 | miso, |
| 337 | txdma, | 336 | txdma, |
| 338 | rxdma, | 337 | rxdma, |
| 339 | current_word_size: <u8 as sealed::Word>::CONFIG, | 338 | current_word_size: <u8 as SealedWord>::CONFIG, |
| 340 | } | 339 | } |
| 341 | } | 340 | } |
| 342 | 341 | ||
| @@ -975,24 +974,21 @@ impl<'d, T: Instance, Tx: TxDma<T>, Rx: RxDma<T>, W: Word> embedded_hal_async::s | |||
| 975 | } | 974 | } |
| 976 | } | 975 | } |
| 977 | 976 | ||
| 978 | pub(crate) mod sealed { | 977 | pub(crate) trait SealedInstance { |
| 979 | use super::*; | 978 | const REGS: Regs; |
| 980 | 979 | } | |
| 981 | pub trait Instance { | ||
| 982 | const REGS: Regs; | ||
| 983 | } | ||
| 984 | 980 | ||
| 985 | pub trait Word { | 981 | trait SealedWord { |
| 986 | const CONFIG: word_impl::Config; | 982 | const CONFIG: word_impl::Config; |
| 987 | } | ||
| 988 | } | 983 | } |
| 989 | 984 | ||
| 990 | /// Word sizes usable for SPI. | 985 | /// Word sizes usable for SPI. |
| 991 | pub trait Word: word::Word + sealed::Word {} | 986 | #[allow(private_bounds)] |
| 987 | pub trait Word: word::Word + SealedWord {} | ||
| 992 | 988 | ||
| 993 | macro_rules! impl_word { | 989 | macro_rules! impl_word { |
| 994 | ($T:ty, $config:expr) => { | 990 | ($T:ty, $config:expr) => { |
| 995 | impl sealed::Word for $T { | 991 | impl SealedWord for $T { |
| 996 | const CONFIG: Config = $config; | 992 | const CONFIG: Config = $config; |
| 997 | } | 993 | } |
| 998 | impl Word for $T {} | 994 | impl Word for $T {} |
| @@ -1068,7 +1064,8 @@ mod word_impl { | |||
| 1068 | } | 1064 | } |
| 1069 | 1065 | ||
| 1070 | /// SPI instance trait. | 1066 | /// SPI instance trait. |
| 1071 | pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} | 1067 | #[allow(private_bounds)] |
| 1068 | pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {} | ||
| 1072 | 1069 | ||
| 1073 | pin_trait!(SckPin, Instance); | 1070 | pin_trait!(SckPin, Instance); |
| 1074 | pin_trait!(MosiPin, Instance); | 1071 | pin_trait!(MosiPin, Instance); |
| @@ -1082,7 +1079,7 @@ dma_trait!(TxDma, Instance); | |||
| 1082 | 1079 | ||
| 1083 | foreach_peripheral!( | 1080 | foreach_peripheral!( |
| 1084 | (spi, $inst:ident) => { | 1081 | (spi, $inst:ident) => { |
| 1085 | impl sealed::Instance for peripherals::$inst { | 1082 | impl SealedInstance for peripherals::$inst { |
| 1086 | const REGS: Regs = crate::pac::$inst; | 1083 | const REGS: Regs = crate::pac::$inst; |
| 1087 | } | 1084 | } |
| 1088 | 1085 | ||
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; | |||
| 8 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 8 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 9 | use embassy_sync::blocking_mutex::Mutex; | 9 | use embassy_sync::blocking_mutex::Mutex; |
| 10 | use embassy_time_driver::{AlarmHandle, Driver, TICK_HZ}; | 10 | use embassy_time_driver::{AlarmHandle, Driver, TICK_HZ}; |
| 11 | use stm32_metapac::timer::regs; | 11 | use stm32_metapac::timer::{regs, TimGp16}; |
| 12 | 12 | ||
| 13 | use crate::interrupt::typelevel::Interrupt; | 13 | use crate::interrupt::typelevel::Interrupt; |
| 14 | use crate::pac::timer::vals; | 14 | use crate::pac::timer::vals; |
| 15 | use crate::rcc::sealed::RccPeripheral; | 15 | use crate::rcc::SealedRccPeripheral; |
| 16 | #[cfg(feature = "low-power")] | 16 | #[cfg(feature = "low-power")] |
| 17 | use crate::rtc::Rtc; | 17 | use crate::rtc::Rtc; |
| 18 | #[cfg(any(time_driver_tim1, time_driver_tim8, time_driver_tim20))] | 18 | #[cfg(any(time_driver_tim1, time_driver_tim8, time_driver_tim20))] |
| 19 | use crate::timer::sealed::AdvancedControlInstance; | 19 | use crate::timer::AdvancedInstance1Channel; |
| 20 | use crate::timer::sealed::{CoreInstance, GeneralPurpose16bitInstance as Instance}; | 20 | use crate::timer::CoreInstance; |
| 21 | use crate::{interrupt, peripherals}; | 21 | use crate::{interrupt, peripherals}; |
| 22 | 22 | ||
| 23 | // NOTE regarding ALARM_COUNT: | 23 | // NOTE regarding ALARM_COUNT: |
| @@ -207,6 +207,10 @@ foreach_interrupt! { | |||
| 207 | }; | 207 | }; |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | fn regs_gp16() -> TimGp16 { | ||
| 211 | unsafe { TimGp16::from_ptr(T::regs()) } | ||
| 212 | } | ||
| 213 | |||
| 210 | // Clock timekeeping works with something we call "periods", which are time intervals | 214 | // Clock timekeeping works with something we call "periods", which are time intervals |
| 211 | // of 2^15 ticks. The Clock counter value is 16 bits, so one "overflow cycle" is 2 periods. | 215 | // of 2^15 ticks. The Clock counter value is 16 bits, so one "overflow cycle" is 2 periods. |
| 212 | // | 216 | // |
| @@ -271,9 +275,9 @@ embassy_time_driver::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver { | |||
| 271 | 275 | ||
| 272 | impl RtcDriver { | 276 | impl RtcDriver { |
| 273 | fn init(&'static self, cs: critical_section::CriticalSection) { | 277 | fn init(&'static self, cs: critical_section::CriticalSection) { |
| 274 | let r = T::regs_gp16(); | 278 | let r = regs_gp16(); |
| 275 | 279 | ||
| 276 | <T as RccPeripheral>::enable_and_reset_with_cs(cs); | 280 | <T as SealedRccPeripheral>::enable_and_reset_with_cs(cs); |
| 277 | 281 | ||
| 278 | let timer_freq = T::frequency(); | 282 | let timer_freq = T::frequency(); |
| 279 | 283 | ||
| @@ -308,9 +312,9 @@ impl RtcDriver { | |||
| 308 | 312 | ||
| 309 | #[cfg(any(time_driver_tim1, time_driver_tim8, time_driver_tim20))] | 313 | #[cfg(any(time_driver_tim1, time_driver_tim8, time_driver_tim20))] |
| 310 | { | 314 | { |
| 311 | <T as AdvancedControlInstance>::CaptureCompareInterrupt::unpend(); | 315 | <T as AdvancedInstance1Channel>::CaptureCompareInterrupt::unpend(); |
| 312 | unsafe { | 316 | unsafe { |
| 313 | <T as AdvancedControlInstance>::CaptureCompareInterrupt::enable(); | 317 | <T as AdvancedInstance1Channel>::CaptureCompareInterrupt::enable(); |
| 314 | } | 318 | } |
| 315 | } | 319 | } |
| 316 | 320 | ||
| @@ -318,7 +322,7 @@ impl RtcDriver { | |||
| 318 | } | 322 | } |
| 319 | 323 | ||
| 320 | fn on_interrupt(&self) { | 324 | fn on_interrupt(&self) { |
| 321 | let r = T::regs_gp16(); | 325 | let r = regs_gp16(); |
| 322 | 326 | ||
| 323 | // XXX: reduce the size of this critical section ? | 327 | // XXX: reduce the size of this critical section ? |
| 324 | critical_section::with(|cs| { | 328 | critical_section::with(|cs| { |
| @@ -349,7 +353,7 @@ impl RtcDriver { | |||
| 349 | } | 353 | } |
| 350 | 354 | ||
| 351 | fn next_period(&self) { | 355 | fn next_period(&self) { |
| 352 | let r = T::regs_gp16(); | 356 | let r = regs_gp16(); |
| 353 | 357 | ||
| 354 | // We only modify the period from the timer interrupt, so we know this can't race. | 358 | // We only modify the period from the timer interrupt, so we know this can't race. |
| 355 | let period = self.period.load(Ordering::Relaxed) + 1; | 359 | let period = self.period.load(Ordering::Relaxed) + 1; |
| @@ -413,7 +417,7 @@ impl RtcDriver { | |||
| 413 | /// Add the given offset to the current time | 417 | /// Add the given offset to the current time |
| 414 | fn add_time(&self, offset: embassy_time::Duration, cs: CriticalSection) { | 418 | fn add_time(&self, offset: embassy_time::Duration, cs: CriticalSection) { |
| 415 | let offset = offset.as_ticks(); | 419 | let offset = offset.as_ticks(); |
| 416 | let cnt = T::regs_gp16().cnt().read().cnt() as u32; | 420 | let cnt = regs_gp16().cnt().read().cnt() as u32; |
| 417 | let period = self.period.load(Ordering::SeqCst); | 421 | let period = self.period.load(Ordering::SeqCst); |
| 418 | 422 | ||
| 419 | // Correct the race, if it exists | 423 | // Correct the race, if it exists |
| @@ -439,7 +443,7 @@ impl RtcDriver { | |||
| 439 | let period = if cnt > u16::MAX as u32 / 2 { period + 1 } else { period }; | 443 | let period = if cnt > u16::MAX as u32 / 2 { period + 1 } else { period }; |
| 440 | 444 | ||
| 441 | self.period.store(period, Ordering::SeqCst); | 445 | self.period.store(period, Ordering::SeqCst); |
| 442 | T::regs_gp16().cnt().write(|w| w.set_cnt(cnt as u16)); | 446 | regs_gp16().cnt().write(|w| w.set_cnt(cnt as u16)); |
| 443 | 447 | ||
| 444 | // Now, recompute all alarms | 448 | // Now, recompute all alarms |
| 445 | for i in 0..ALARM_COUNT { | 449 | for i in 0..ALARM_COUNT { |
| @@ -496,7 +500,7 @@ impl RtcDriver { | |||
| 496 | .unwrap() | 500 | .unwrap() |
| 497 | .start_wakeup_alarm(time_until_next_alarm, cs); | 501 | .start_wakeup_alarm(time_until_next_alarm, cs); |
| 498 | 502 | ||
| 499 | T::regs_gp16().cr1().modify(|w| w.set_cen(false)); | 503 | regs_gp16().cr1().modify(|w| w.set_cen(false)); |
| 500 | 504 | ||
| 501 | Ok(()) | 505 | Ok(()) |
| 502 | } | 506 | } |
| @@ -506,7 +510,7 @@ impl RtcDriver { | |||
| 506 | #[cfg(feature = "low-power")] | 510 | #[cfg(feature = "low-power")] |
| 507 | /// Resume the timer with the given offset | 511 | /// Resume the timer with the given offset |
| 508 | pub(crate) fn resume_time(&self) { | 512 | pub(crate) fn resume_time(&self) { |
| 509 | if T::regs_gp16().cr1().read().cen() { | 513 | if regs_gp16().cr1().read().cen() { |
| 510 | // Time isn't currently stopped | 514 | // Time isn't currently stopped |
| 511 | 515 | ||
| 512 | return; | 516 | return; |
| @@ -515,14 +519,14 @@ impl RtcDriver { | |||
| 515 | critical_section::with(|cs| { | 519 | critical_section::with(|cs| { |
| 516 | self.stop_wakeup_alarm(cs); | 520 | self.stop_wakeup_alarm(cs); |
| 517 | 521 | ||
| 518 | T::regs_gp16().cr1().modify(|w| w.set_cen(true)); | 522 | regs_gp16().cr1().modify(|w| w.set_cen(true)); |
| 519 | }) | 523 | }) |
| 520 | } | 524 | } |
| 521 | } | 525 | } |
| 522 | 526 | ||
| 523 | impl Driver for RtcDriver { | 527 | impl Driver for RtcDriver { |
| 524 | fn now(&self) -> u64 { | 528 | fn now(&self) -> u64 { |
| 525 | let r = T::regs_gp16(); | 529 | let r = regs_gp16(); |
| 526 | 530 | ||
| 527 | let period = self.period.load(Ordering::Relaxed); | 531 | let period = self.period.load(Ordering::Relaxed); |
| 528 | compiler_fence(Ordering::Acquire); | 532 | compiler_fence(Ordering::Acquire); |
| @@ -553,7 +557,7 @@ impl Driver for RtcDriver { | |||
| 553 | 557 | ||
| 554 | fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) -> bool { | 558 | fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) -> bool { |
| 555 | critical_section::with(|cs| { | 559 | critical_section::with(|cs| { |
| 556 | let r = T::regs_gp16(); | 560 | let r = regs_gp16(); |
| 557 | 561 | ||
| 558 | let n = alarm.id() as usize; | 562 | let n = alarm.id() as usize; |
| 559 | let alarm = self.get_alarm(cs, alarm); | 563 | 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; | |||
| 5 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 5 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 6 | use stm32_metapac::timer::vals::Ckd; | 6 | use stm32_metapac::timer::vals::Ckd; |
| 7 | 7 | ||
| 8 | use super::simple_pwm::*; | 8 | use super::low_level::{CountingMode, OutputPolarity, Timer}; |
| 9 | use super::*; | 9 | use super::simple_pwm::{Ch1, Ch2, Ch3, Ch4, PwmPin}; |
| 10 | #[allow(unused_imports)] | 10 | use super::{ |
| 11 | use crate::gpio::sealed::{AFType, Pin}; | 11 | AdvancedInstance4Channel, Channel, Channel1ComplementaryPin, Channel2ComplementaryPin, Channel3ComplementaryPin, |
| 12 | Channel4ComplementaryPin, | ||
| 13 | }; | ||
| 12 | use crate::gpio::{AnyPin, OutputType}; | 14 | use crate::gpio::{AnyPin, OutputType}; |
| 15 | use crate::time::Hertz; | ||
| 16 | use crate::timer::low_level::OutputCompareMode; | ||
| 13 | use crate::Peripheral; | 17 | use crate::Peripheral; |
| 14 | 18 | ||
| 15 | /// Complementary PWM pin wrapper. | 19 | /// Complementary PWM pin wrapper. |
| @@ -22,7 +26,7 @@ pub struct ComplementaryPwmPin<'d, T, C> { | |||
| 22 | 26 | ||
| 23 | macro_rules! complementary_channel_impl { | 27 | macro_rules! complementary_channel_impl { |
| 24 | ($new_chx:ident, $channel:ident, $pin_trait:ident) => { | 28 | ($new_chx:ident, $channel:ident, $pin_trait:ident) => { |
| 25 | impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwmPin<'d, T, $channel> { | 29 | impl<'d, T: AdvancedInstance4Channel> ComplementaryPwmPin<'d, T, $channel> { |
| 26 | #[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")] | 30 | #[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")] |
| 27 | pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self { | 31 | pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self { |
| 28 | into_ref!(pin); | 32 | into_ref!(pin); |
| @@ -47,11 +51,11 @@ complementary_channel_impl!(new_ch3, Ch3, Channel3ComplementaryPin); | |||
| 47 | complementary_channel_impl!(new_ch4, Ch4, Channel4ComplementaryPin); | 51 | complementary_channel_impl!(new_ch4, Ch4, Channel4ComplementaryPin); |
| 48 | 52 | ||
| 49 | /// PWM driver with support for standard and complementary outputs. | 53 | /// PWM driver with support for standard and complementary outputs. |
| 50 | pub struct ComplementaryPwm<'d, T> { | 54 | pub struct ComplementaryPwm<'d, T: AdvancedInstance4Channel> { |
| 51 | inner: PeripheralRef<'d, T>, | 55 | inner: Timer<'d, T>, |
| 52 | } | 56 | } |
| 53 | 57 | ||
| 54 | impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { | 58 | impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { |
| 55 | /// Create a new complementary PWM driver. | 59 | /// Create a new complementary PWM driver. |
| 56 | #[allow(clippy::too_many_arguments)] | 60 | #[allow(clippy::too_many_arguments)] |
| 57 | pub fn new( | 61 | pub fn new( |
| @@ -71,11 +75,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { | |||
| 71 | } | 75 | } |
| 72 | 76 | ||
| 73 | fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, counting_mode: CountingMode) -> Self { | 77 | fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, counting_mode: CountingMode) -> Self { |
| 74 | into_ref!(tim); | 78 | let mut this = Self { inner: Timer::new(tim) }; |
| 75 | |||
| 76 | T::enable_and_reset(); | ||
| 77 | |||
| 78 | let mut this = Self { inner: tim }; | ||
| 79 | 79 | ||
| 80 | this.inner.set_counting_mode(counting_mode); | 80 | this.inner.set_counting_mode(counting_mode); |
| 81 | this.set_frequency(freq); | 81 | this.set_frequency(freq); |
| @@ -122,7 +122,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { | |||
| 122 | /// | 122 | /// |
| 123 | /// This value depends on the configured frequency and the timer's clock rate from RCC. | 123 | /// This value depends on the configured frequency and the timer's clock rate from RCC. |
| 124 | pub fn get_max_duty(&self) -> u16 { | 124 | pub fn get_max_duty(&self) -> u16 { |
| 125 | self.inner.get_max_compare_value() + 1 | 125 | self.inner.get_max_compare_value() as u16 + 1 |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | /// Set the duty for a given channel. | 128 | /// Set the duty for a given channel. |
| @@ -130,7 +130,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { | |||
| 130 | /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. | 130 | /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. |
| 131 | pub fn set_duty(&mut self, channel: Channel, duty: u16) { | 131 | pub fn set_duty(&mut self, channel: Channel, duty: u16) { |
| 132 | assert!(duty <= self.get_max_duty()); | 132 | assert!(duty <= self.get_max_duty()); |
| 133 | self.inner.set_compare_value(channel, duty) | 133 | self.inner.set_compare_value(channel, duty as _) |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | /// Set the output polarity for a given channel. | 136 | /// Set the output polarity for a given channel. |
| @@ -148,7 +148,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { | |||
| 148 | } | 148 | } |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | impl<'d, T: ComplementaryCaptureCompare16bitInstance> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> { | 151 | impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> { |
| 152 | type Channel = Channel; | 152 | type Channel = Channel; |
| 153 | type Time = Hertz; | 153 | type Time = Hertz; |
| 154 | type Duty = u16; | 154 | type Duty = u16; |
| @@ -168,16 +168,16 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> embedded_hal_02::Pwm for C | |||
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | fn get_duty(&self, channel: Self::Channel) -> Self::Duty { | 170 | fn get_duty(&self, channel: Self::Channel) -> Self::Duty { |
| 171 | self.inner.get_compare_value(channel) | 171 | self.inner.get_compare_value(channel) as u16 |
| 172 | } | 172 | } |
| 173 | 173 | ||
| 174 | fn get_max_duty(&self) -> Self::Duty { | 174 | fn get_max_duty(&self) -> Self::Duty { |
| 175 | self.inner.get_max_compare_value() + 1 | 175 | self.inner.get_max_compare_value() as u16 + 1 |
| 176 | } | 176 | } |
| 177 | 177 | ||
| 178 | fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) { | 178 | fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) { |
| 179 | assert!(duty <= self.get_max_duty()); | 179 | assert!(duty <= self.get_max_duty()); |
| 180 | self.inner.set_compare_value(channel, duty) | 180 | self.inner.set_compare_value(channel, duty as u32) |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | fn set_period<P>(&mut self, period: P) | 183 | fn set_period<P>(&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 @@ | |||
| 1 | //! Low-level timer driver. | ||
| 2 | //! | ||
| 3 | //! This is an unopinionated, very low-level driver for all STM32 timers. It allows direct register | ||
| 4 | //! manipulation with the `regs_*()` methods, and has utility functions that are thin wrappers | ||
| 5 | //! over the registers. | ||
| 6 | //! | ||
| 7 | //! The available functionality depends on the timer type. | ||
| 8 | |||
| 9 | use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; | ||
| 10 | |||
| 11 | use super::*; | ||
| 12 | use crate::pac::timer::vals; | ||
| 13 | use crate::time::Hertz; | ||
| 14 | |||
| 15 | /// Input capture mode. | ||
| 16 | #[derive(Clone, Copy)] | ||
| 17 | pub enum InputCaptureMode { | ||
| 18 | /// Rising edge only. | ||
| 19 | Rising, | ||
| 20 | /// Falling edge only. | ||
| 21 | Falling, | ||
| 22 | /// Both rising or falling edges. | ||
| 23 | BothEdges, | ||
| 24 | } | ||
| 25 | |||
| 26 | /// Input TI selection. | ||
| 27 | #[derive(Clone, Copy)] | ||
| 28 | pub enum InputTISelection { | ||
| 29 | /// Normal | ||
| 30 | Normal, | ||
| 31 | /// Alternate | ||
| 32 | Alternate, | ||
| 33 | /// TRC | ||
| 34 | TRC, | ||
| 35 | } | ||
| 36 | |||
| 37 | impl From<InputTISelection> for stm32_metapac::timer::vals::CcmrInputCcs { | ||
| 38 | fn from(tisel: InputTISelection) -> Self { | ||
| 39 | match tisel { | ||
| 40 | InputTISelection::Normal => stm32_metapac::timer::vals::CcmrInputCcs::TI4, | ||
| 41 | InputTISelection::Alternate => stm32_metapac::timer::vals::CcmrInputCcs::TI3, | ||
| 42 | InputTISelection::TRC => stm32_metapac::timer::vals::CcmrInputCcs::TRC, | ||
| 43 | } | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | /// Timer counting mode. | ||
| 48 | #[repr(u8)] | ||
| 49 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] | ||
| 50 | pub enum CountingMode { | ||
| 51 | #[default] | ||
| 52 | /// The timer counts up to the reload value and then resets back to 0. | ||
| 53 | EdgeAlignedUp, | ||
| 54 | /// The timer counts down to 0 and then resets back to the reload value. | ||
| 55 | EdgeAlignedDown, | ||
| 56 | /// The timer counts up to the reload value and then counts back to 0. | ||
| 57 | /// | ||
| 58 | /// The output compare interrupt flags of channels configured in output are | ||
| 59 | /// set when the counter is counting down. | ||
| 60 | CenterAlignedDownInterrupts, | ||
| 61 | /// The timer counts up to the reload value and then counts back to 0. | ||
| 62 | /// | ||
| 63 | /// The output compare interrupt flags of channels configured in output are | ||
| 64 | /// set when the counter is counting up. | ||
| 65 | CenterAlignedUpInterrupts, | ||
| 66 | /// The timer counts up to the reload value and then counts back to 0. | ||
| 67 | /// | ||
| 68 | /// The output compare interrupt flags of channels configured in output are | ||
| 69 | /// set when the counter is counting both up or down. | ||
| 70 | CenterAlignedBothInterrupts, | ||
| 71 | } | ||
| 72 | |||
| 73 | impl CountingMode { | ||
| 74 | /// Return whether this mode is edge-aligned (up or down). | ||
| 75 | pub fn is_edge_aligned(&self) -> bool { | ||
| 76 | matches!(self, CountingMode::EdgeAlignedUp | CountingMode::EdgeAlignedDown) | ||
| 77 | } | ||
| 78 | |||
| 79 | /// Return whether this mode is center-aligned. | ||
| 80 | pub fn is_center_aligned(&self) -> bool { | ||
| 81 | matches!( | ||
| 82 | self, | ||
| 83 | CountingMode::CenterAlignedDownInterrupts | ||
| 84 | | CountingMode::CenterAlignedUpInterrupts | ||
| 85 | | CountingMode::CenterAlignedBothInterrupts | ||
| 86 | ) | ||
| 87 | } | ||
| 88 | } | ||
| 89 | |||
| 90 | impl From<CountingMode> for (vals::Cms, vals::Dir) { | ||
| 91 | fn from(value: CountingMode) -> Self { | ||
| 92 | match value { | ||
| 93 | CountingMode::EdgeAlignedUp => (vals::Cms::EDGEALIGNED, vals::Dir::UP), | ||
| 94 | CountingMode::EdgeAlignedDown => (vals::Cms::EDGEALIGNED, vals::Dir::DOWN), | ||
| 95 | CountingMode::CenterAlignedDownInterrupts => (vals::Cms::CENTERALIGNED1, vals::Dir::UP), | ||
| 96 | CountingMode::CenterAlignedUpInterrupts => (vals::Cms::CENTERALIGNED2, vals::Dir::UP), | ||
| 97 | CountingMode::CenterAlignedBothInterrupts => (vals::Cms::CENTERALIGNED3, vals::Dir::UP), | ||
| 98 | } | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | impl From<(vals::Cms, vals::Dir)> for CountingMode { | ||
| 103 | fn from(value: (vals::Cms, vals::Dir)) -> Self { | ||
| 104 | match value { | ||
| 105 | (vals::Cms::EDGEALIGNED, vals::Dir::UP) => CountingMode::EdgeAlignedUp, | ||
| 106 | (vals::Cms::EDGEALIGNED, vals::Dir::DOWN) => CountingMode::EdgeAlignedDown, | ||
| 107 | (vals::Cms::CENTERALIGNED1, _) => CountingMode::CenterAlignedDownInterrupts, | ||
| 108 | (vals::Cms::CENTERALIGNED2, _) => CountingMode::CenterAlignedUpInterrupts, | ||
| 109 | (vals::Cms::CENTERALIGNED3, _) => CountingMode::CenterAlignedBothInterrupts, | ||
| 110 | } | ||
| 111 | } | ||
| 112 | } | ||
| 113 | |||
| 114 | /// Output compare mode. | ||
| 115 | #[derive(Clone, Copy)] | ||
| 116 | pub enum OutputCompareMode { | ||
| 117 | /// The comparison between the output compare register TIMx_CCRx and | ||
| 118 | /// the counter TIMx_CNT has no effect on the outputs. | ||
| 119 | /// (this mode is used to generate a timing base). | ||
| 120 | Frozen, | ||
| 121 | /// Set channel to active level on match. OCxREF signal is forced high when the | ||
| 122 | /// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx). | ||
| 123 | ActiveOnMatch, | ||
| 124 | /// Set channel to inactive level on match. OCxREF signal is forced low when the | ||
| 125 | /// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx). | ||
| 126 | InactiveOnMatch, | ||
| 127 | /// Toggle - OCxREF toggles when TIMx_CNT=TIMx_CCRx. | ||
| 128 | Toggle, | ||
| 129 | /// Force inactive level - OCxREF is forced low. | ||
| 130 | ForceInactive, | ||
| 131 | /// Force active level - OCxREF is forced high. | ||
| 132 | ForceActive, | ||
| 133 | /// PWM mode 1 - In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRx | ||
| 134 | /// else inactive. In downcounting, channel is inactive (OCxREF=0) as long as | ||
| 135 | /// TIMx_CNT>TIMx_CCRx else active (OCxREF=1). | ||
| 136 | PwmMode1, | ||
| 137 | /// PWM mode 2 - In upcounting, channel is inactive as long as | ||
| 138 | /// TIMx_CNT<TIMx_CCRx else active. In downcounting, channel is active as long as | ||
| 139 | /// TIMx_CNT>TIMx_CCRx else inactive. | ||
| 140 | PwmMode2, | ||
| 141 | // TODO: there's more modes here depending on the chip family. | ||
| 142 | } | ||
| 143 | |||
| 144 | impl From<OutputCompareMode> for stm32_metapac::timer::vals::Ocm { | ||
| 145 | fn from(mode: OutputCompareMode) -> Self { | ||
| 146 | match mode { | ||
| 147 | OutputCompareMode::Frozen => stm32_metapac::timer::vals::Ocm::FROZEN, | ||
| 148 | OutputCompareMode::ActiveOnMatch => stm32_metapac::timer::vals::Ocm::ACTIVEONMATCH, | ||
| 149 | OutputCompareMode::InactiveOnMatch => stm32_metapac::timer::vals::Ocm::INACTIVEONMATCH, | ||
| 150 | OutputCompareMode::Toggle => stm32_metapac::timer::vals::Ocm::TOGGLE, | ||
| 151 | OutputCompareMode::ForceInactive => stm32_metapac::timer::vals::Ocm::FORCEINACTIVE, | ||
| 152 | OutputCompareMode::ForceActive => stm32_metapac::timer::vals::Ocm::FORCEACTIVE, | ||
| 153 | OutputCompareMode::PwmMode1 => stm32_metapac::timer::vals::Ocm::PWMMODE1, | ||
| 154 | OutputCompareMode::PwmMode2 => stm32_metapac::timer::vals::Ocm::PWMMODE2, | ||
| 155 | } | ||
| 156 | } | ||
| 157 | } | ||
| 158 | |||
| 159 | /// Timer output pin polarity. | ||
| 160 | #[derive(Clone, Copy)] | ||
| 161 | pub enum OutputPolarity { | ||
| 162 | /// Active high (higher duty value makes the pin spend more time high). | ||
| 163 | ActiveHigh, | ||
| 164 | /// Active low (higher duty value makes the pin spend more time low). | ||
| 165 | ActiveLow, | ||
| 166 | } | ||
| 167 | |||
| 168 | impl From<OutputPolarity> for bool { | ||
| 169 | fn from(mode: OutputPolarity) -> Self { | ||
| 170 | match mode { | ||
| 171 | OutputPolarity::ActiveHigh => false, | ||
| 172 | OutputPolarity::ActiveLow => true, | ||
| 173 | } | ||
| 174 | } | ||
| 175 | } | ||
| 176 | |||
| 177 | /// Low-level timer driver. | ||
| 178 | pub struct Timer<'d, T: CoreInstance> { | ||
| 179 | tim: PeripheralRef<'d, T>, | ||
| 180 | } | ||
| 181 | |||
| 182 | impl<'d, T: CoreInstance> Drop for Timer<'d, T> { | ||
| 183 | fn drop(&mut self) { | ||
| 184 | T::disable() | ||
| 185 | } | ||
| 186 | } | ||
| 187 | |||
| 188 | impl<'d, T: CoreInstance> Timer<'d, T> { | ||
| 189 | /// Create a new timer driver. | ||
| 190 | pub fn new(tim: impl Peripheral<P = T> + 'd) -> Self { | ||
| 191 | into_ref!(tim); | ||
| 192 | |||
| 193 | T::enable_and_reset(); | ||
| 194 | |||
| 195 | Self { tim } | ||
| 196 | } | ||
| 197 | |||
| 198 | /// Get access to the virutal core 16bit timer registers. | ||
| 199 | /// | ||
| 200 | /// Note: This works even if the timer is more capable, because registers | ||
| 201 | /// for the less capable timers are a subset. This allows writing a driver | ||
| 202 | /// for a given set of capabilities, and having it transparently work with | ||
| 203 | /// more capable timers. | ||
| 204 | pub fn regs_core(&self) -> crate::pac::timer::TimCore { | ||
| 205 | unsafe { crate::pac::timer::TimCore::from_ptr(T::regs()) } | ||
| 206 | } | ||
| 207 | |||
| 208 | #[cfg(not(stm32l0))] | ||
| 209 | fn regs_gp32_unchecked(&self) -> crate::pac::timer::TimGp32 { | ||
| 210 | unsafe { crate::pac::timer::TimGp32::from_ptr(T::regs()) } | ||
| 211 | } | ||
| 212 | |||
| 213 | /// Start the timer. | ||
| 214 | pub fn start(&self) { | ||
| 215 | self.regs_core().cr1().modify(|r| r.set_cen(true)); | ||
| 216 | } | ||
| 217 | |||
| 218 | /// Stop the timer. | ||
| 219 | pub fn stop(&self) { | ||
| 220 | self.regs_core().cr1().modify(|r| r.set_cen(false)); | ||
| 221 | } | ||
| 222 | |||
| 223 | /// Reset the counter value to 0 | ||
| 224 | pub fn reset(&self) { | ||
| 225 | self.regs_core().cnt().write(|r| r.set_cnt(0)); | ||
| 226 | } | ||
| 227 | |||
| 228 | /// Set the frequency of how many times per second the timer counts up to the max value or down to 0. | ||
| 229 | /// | ||
| 230 | /// This means that in the default edge-aligned mode, | ||
| 231 | /// the timer counter will wrap around at the same frequency as is being set. | ||
| 232 | /// In center-aligned mode (which not all timers support), the wrap-around frequency is effectively halved | ||
| 233 | /// because it needs to count up and down. | ||
| 234 | pub fn set_frequency(&self, frequency: Hertz) { | ||
| 235 | let f = frequency.0; | ||
| 236 | assert!(f > 0); | ||
| 237 | let timer_f = T::frequency().0; | ||
| 238 | |||
| 239 | match T::BITS { | ||
| 240 | TimerBits::Bits16 => { | ||
| 241 | let pclk_ticks_per_timer_period = timer_f / f; | ||
| 242 | let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 16)).try_into()); | ||
| 243 | let divide_by = pclk_ticks_per_timer_period / (u32::from(psc) + 1); | ||
| 244 | |||
| 245 | // the timer counts `0..=arr`, we want it to count `0..divide_by` | ||
| 246 | let arr = unwrap!(u16::try_from(divide_by - 1)); | ||
| 247 | |||
| 248 | let regs = self.regs_core(); | ||
| 249 | regs.psc().write_value(psc); | ||
| 250 | regs.arr().write(|r| r.set_arr(arr)); | ||
| 251 | |||
| 252 | regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); | ||
| 253 | regs.egr().write(|r| r.set_ug(true)); | ||
| 254 | regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); | ||
| 255 | } | ||
| 256 | #[cfg(not(stm32l0))] | ||
| 257 | TimerBits::Bits32 => { | ||
| 258 | let pclk_ticks_per_timer_period = (timer_f / f) as u64; | ||
| 259 | let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into()); | ||
| 260 | let arr: u32 = unwrap!((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into()); | ||
| 261 | |||
| 262 | let regs = self.regs_gp32_unchecked(); | ||
| 263 | regs.psc().write_value(psc); | ||
| 264 | regs.arr().write_value(arr); | ||
| 265 | |||
| 266 | regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); | ||
| 267 | regs.egr().write(|r| r.set_ug(true)); | ||
| 268 | regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); | ||
| 269 | } | ||
| 270 | } | ||
| 271 | } | ||
| 272 | |||
| 273 | /// Clear update interrupt. | ||
| 274 | /// | ||
| 275 | /// Returns whether the update interrupt flag was set. | ||
| 276 | pub fn clear_update_interrupt(&self) -> bool { | ||
| 277 | let regs = self.regs_core(); | ||
| 278 | let sr = regs.sr().read(); | ||
| 279 | if sr.uif() { | ||
| 280 | regs.sr().modify(|r| { | ||
| 281 | r.set_uif(false); | ||
| 282 | }); | ||
| 283 | true | ||
| 284 | } else { | ||
| 285 | false | ||
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 289 | /// Enable/disable the update interrupt. | ||
| 290 | pub fn enable_update_interrupt(&self, enable: bool) { | ||
| 291 | self.regs_core().dier().modify(|r| r.set_uie(enable)); | ||
| 292 | } | ||
| 293 | |||
| 294 | /// Enable/disable autoreload preload. | ||
| 295 | pub fn set_autoreload_preload(&self, enable: bool) { | ||
| 296 | self.regs_core().cr1().modify(|r| r.set_arpe(enable)); | ||
| 297 | } | ||
| 298 | |||
| 299 | /// Get the timer frequency. | ||
| 300 | pub fn get_frequency(&self) -> Hertz { | ||
| 301 | let timer_f = T::frequency(); | ||
| 302 | |||
| 303 | match T::BITS { | ||
| 304 | TimerBits::Bits16 => { | ||
| 305 | let regs = self.regs_core(); | ||
| 306 | let arr = regs.arr().read().arr(); | ||
| 307 | let psc = regs.psc().read(); | ||
| 308 | |||
| 309 | timer_f / arr / (psc + 1) | ||
| 310 | } | ||
| 311 | #[cfg(not(stm32l0))] | ||
| 312 | TimerBits::Bits32 => { | ||
| 313 | let regs = self.regs_gp32_unchecked(); | ||
| 314 | let arr = regs.arr().read(); | ||
| 315 | let psc = regs.psc().read(); | ||
| 316 | |||
| 317 | timer_f / arr / (psc + 1) | ||
| 318 | } | ||
| 319 | } | ||
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 323 | impl<'d, T: BasicNoCr2Instance> Timer<'d, T> { | ||
| 324 | /// Get access to the Baisc 16bit timer registers. | ||
| 325 | /// | ||
| 326 | /// Note: This works even if the timer is more capable, because registers | ||
| 327 | /// for the less capable timers are a subset. This allows writing a driver | ||
| 328 | /// for a given set of capabilities, and having it transparently work with | ||
| 329 | /// more capable timers. | ||
| 330 | pub fn regs_basic_no_cr2(&self) -> crate::pac::timer::TimBasicNoCr2 { | ||
| 331 | unsafe { crate::pac::timer::TimBasicNoCr2::from_ptr(T::regs()) } | ||
| 332 | } | ||
| 333 | |||
| 334 | /// Enable/disable the update dma. | ||
| 335 | pub fn enable_update_dma(&self, enable: bool) { | ||
| 336 | self.regs_basic_no_cr2().dier().modify(|r| r.set_ude(enable)); | ||
| 337 | } | ||
| 338 | |||
| 339 | /// Get the update dma enable/disable state. | ||
| 340 | pub fn get_update_dma_state(&self) -> bool { | ||
| 341 | self.regs_basic_no_cr2().dier().read().ude() | ||
| 342 | } | ||
| 343 | } | ||
| 344 | |||
| 345 | impl<'d, T: BasicInstance> Timer<'d, T> { | ||
| 346 | /// Get access to the Baisc 16bit timer registers. | ||
| 347 | /// | ||
| 348 | /// Note: This works even if the timer is more capable, because registers | ||
| 349 | /// for the less capable timers are a subset. This allows writing a driver | ||
| 350 | /// for a given set of capabilities, and having it transparently work with | ||
| 351 | /// more capable timers. | ||
| 352 | pub fn regs_basic(&self) -> crate::pac::timer::TimBasic { | ||
| 353 | unsafe { crate::pac::timer::TimBasic::from_ptr(T::regs()) } | ||
| 354 | } | ||
| 355 | } | ||
| 356 | |||
| 357 | impl<'d, T: GeneralInstance1Channel> Timer<'d, T> { | ||
| 358 | /// Get access to the general purpose 1 channel 16bit timer registers. | ||
| 359 | /// | ||
| 360 | /// Note: This works even if the timer is more capable, because registers | ||
| 361 | /// for the less capable timers are a subset. This allows writing a driver | ||
| 362 | /// for a given set of capabilities, and having it transparently work with | ||
| 363 | /// more capable timers. | ||
| 364 | pub fn regs_1ch(&self) -> crate::pac::timer::Tim1ch { | ||
| 365 | unsafe { crate::pac::timer::Tim1ch::from_ptr(T::regs()) } | ||
| 366 | } | ||
| 367 | |||
| 368 | /// Set clock divider. | ||
| 369 | pub fn set_clock_division(&self, ckd: vals::Ckd) { | ||
| 370 | self.regs_1ch().cr1().modify(|r| r.set_ckd(ckd)); | ||
| 371 | } | ||
| 372 | |||
| 373 | /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC. | ||
| 374 | pub fn get_max_compare_value(&self) -> u32 { | ||
| 375 | match T::BITS { | ||
| 376 | TimerBits::Bits16 => self.regs_1ch().arr().read().arr() as u32, | ||
| 377 | #[cfg(not(stm32l0))] | ||
| 378 | TimerBits::Bits32 => self.regs_gp32_unchecked().arr().read(), | ||
| 379 | } | ||
| 380 | } | ||
| 381 | } | ||
| 382 | |||
| 383 | impl<'d, T: GeneralInstance2Channel> Timer<'d, T> { | ||
| 384 | /// Get access to the general purpose 2 channel 16bit timer registers. | ||
| 385 | /// | ||
| 386 | /// Note: This works even if the timer is more capable, because registers | ||
| 387 | /// for the less capable timers are a subset. This allows writing a driver | ||
| 388 | /// for a given set of capabilities, and having it transparently work with | ||
| 389 | /// more capable timers. | ||
| 390 | pub fn regs_2ch(&self) -> crate::pac::timer::Tim2ch { | ||
| 391 | unsafe { crate::pac::timer::Tim2ch::from_ptr(T::regs()) } | ||
| 392 | } | ||
| 393 | } | ||
| 394 | |||
| 395 | impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { | ||
| 396 | /// Get access to the general purpose 16bit timer registers. | ||
| 397 | /// | ||
| 398 | /// Note: This works even if the timer is more capable, because registers | ||
| 399 | /// for the less capable timers are a subset. This allows writing a driver | ||
| 400 | /// for a given set of capabilities, and having it transparently work with | ||
| 401 | /// more capable timers. | ||
| 402 | pub fn regs_gp16(&self) -> crate::pac::timer::TimGp16 { | ||
| 403 | unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) } | ||
| 404 | } | ||
| 405 | |||
| 406 | /// Enable timer outputs. | ||
| 407 | pub fn enable_outputs(&self) { | ||
| 408 | self.tim.enable_outputs() | ||
| 409 | } | ||
| 410 | |||
| 411 | /// Set counting mode. | ||
| 412 | pub fn set_counting_mode(&self, mode: CountingMode) { | ||
| 413 | let (cms, dir) = mode.into(); | ||
| 414 | |||
| 415 | let timer_enabled = self.regs_core().cr1().read().cen(); | ||
| 416 | // Changing from edge aligned to center aligned (and vice versa) is not allowed while the timer is running. | ||
| 417 | // Changing direction is discouraged while the timer is running. | ||
| 418 | assert!(!timer_enabled); | ||
| 419 | |||
| 420 | self.regs_gp16().cr1().modify(|r| r.set_dir(dir)); | ||
| 421 | self.regs_gp16().cr1().modify(|r| r.set_cms(cms)) | ||
| 422 | } | ||
| 423 | |||
| 424 | /// Get counting mode. | ||
| 425 | pub fn get_counting_mode(&self) -> CountingMode { | ||
| 426 | let cr1 = self.regs_gp16().cr1().read(); | ||
| 427 | (cr1.cms(), cr1.dir()).into() | ||
| 428 | } | ||
| 429 | |||
| 430 | /// Set input capture filter. | ||
| 431 | pub fn set_input_capture_filter(&self, channel: Channel, icf: vals::FilterValue) { | ||
| 432 | let raw_channel = channel.index(); | ||
| 433 | self.regs_gp16() | ||
| 434 | .ccmr_input(raw_channel / 2) | ||
| 435 | .modify(|r| r.set_icf(raw_channel % 2, icf)); | ||
| 436 | } | ||
| 437 | |||
| 438 | /// Clear input interrupt. | ||
| 439 | pub fn clear_input_interrupt(&self, channel: Channel) { | ||
| 440 | self.regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false)); | ||
| 441 | } | ||
| 442 | |||
| 443 | /// Enable input interrupt. | ||
| 444 | pub fn enable_input_interrupt(&self, channel: Channel, enable: bool) { | ||
| 445 | self.regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable)); | ||
| 446 | } | ||
| 447 | |||
| 448 | /// Set input capture prescaler. | ||
| 449 | pub fn set_input_capture_prescaler(&self, channel: Channel, factor: u8) { | ||
| 450 | let raw_channel = channel.index(); | ||
| 451 | self.regs_gp16() | ||
| 452 | .ccmr_input(raw_channel / 2) | ||
| 453 | .modify(|r| r.set_icpsc(raw_channel % 2, factor)); | ||
| 454 | } | ||
| 455 | |||
| 456 | /// Set input TI selection. | ||
| 457 | pub fn set_input_ti_selection(&self, channel: Channel, tisel: InputTISelection) { | ||
| 458 | let raw_channel = channel.index(); | ||
| 459 | self.regs_gp16() | ||
| 460 | .ccmr_input(raw_channel / 2) | ||
| 461 | .modify(|r| r.set_ccs(raw_channel % 2, tisel.into())); | ||
| 462 | } | ||
| 463 | |||
| 464 | /// Set input capture mode. | ||
| 465 | pub fn set_input_capture_mode(&self, channel: Channel, mode: InputCaptureMode) { | ||
| 466 | self.regs_gp16().ccer().modify(|r| match mode { | ||
| 467 | InputCaptureMode::Rising => { | ||
| 468 | r.set_ccnp(channel.index(), false); | ||
| 469 | r.set_ccp(channel.index(), false); | ||
| 470 | } | ||
| 471 | InputCaptureMode::Falling => { | ||
| 472 | r.set_ccnp(channel.index(), false); | ||
| 473 | r.set_ccp(channel.index(), true); | ||
| 474 | } | ||
| 475 | InputCaptureMode::BothEdges => { | ||
| 476 | r.set_ccnp(channel.index(), true); | ||
| 477 | r.set_ccp(channel.index(), true); | ||
| 478 | } | ||
| 479 | }); | ||
| 480 | } | ||
| 481 | |||
| 482 | /// Set output compare mode. | ||
| 483 | pub fn set_output_compare_mode(&self, channel: Channel, mode: OutputCompareMode) { | ||
| 484 | let raw_channel: usize = channel.index(); | ||
| 485 | self.regs_gp16() | ||
| 486 | .ccmr_output(raw_channel / 2) | ||
| 487 | .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); | ||
| 488 | } | ||
| 489 | |||
| 490 | /// Set output polarity. | ||
| 491 | pub fn set_output_polarity(&self, channel: Channel, polarity: OutputPolarity) { | ||
| 492 | self.regs_gp16() | ||
| 493 | .ccer() | ||
| 494 | .modify(|w| w.set_ccp(channel.index(), polarity.into())); | ||
| 495 | } | ||
| 496 | |||
| 497 | /// Enable/disable a channel. | ||
| 498 | pub fn enable_channel(&self, channel: Channel, enable: bool) { | ||
| 499 | self.regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable)); | ||
| 500 | } | ||
| 501 | |||
| 502 | /// Get enable/disable state of a channel | ||
| 503 | pub fn get_channel_enable_state(&self, channel: Channel) -> bool { | ||
| 504 | self.regs_gp16().ccer().read().cce(channel.index()) | ||
| 505 | } | ||
| 506 | |||
| 507 | /// Set compare value for a channel. | ||
| 508 | pub fn set_compare_value(&self, channel: Channel, value: u32) { | ||
| 509 | match T::BITS { | ||
| 510 | TimerBits::Bits16 => { | ||
| 511 | let value = unwrap!(u16::try_from(value)); | ||
| 512 | self.regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value)); | ||
| 513 | } | ||
| 514 | #[cfg(not(stm32l0))] | ||
| 515 | TimerBits::Bits32 => { | ||
| 516 | self.regs_gp32_unchecked().ccr(channel.index()).write_value(value); | ||
| 517 | } | ||
| 518 | } | ||
| 519 | } | ||
| 520 | |||
| 521 | /// Get compare value for a channel. | ||
| 522 | pub fn get_compare_value(&self, channel: Channel) -> u32 { | ||
| 523 | match T::BITS { | ||
| 524 | TimerBits::Bits16 => self.regs_gp16().ccr(channel.index()).read().ccr() as u32, | ||
| 525 | #[cfg(not(stm32l0))] | ||
| 526 | TimerBits::Bits32 => self.regs_gp32_unchecked().ccr(channel.index()).read(), | ||
| 527 | } | ||
| 528 | } | ||
| 529 | |||
| 530 | /// Get capture value for a channel. | ||
| 531 | pub fn get_capture_value(&self, channel: Channel) -> u32 { | ||
| 532 | self.get_compare_value(channel) | ||
| 533 | } | ||
| 534 | |||
| 535 | /// Set output compare preload. | ||
| 536 | pub fn set_output_compare_preload(&self, channel: Channel, preload: bool) { | ||
| 537 | let channel_index = channel.index(); | ||
| 538 | self.regs_gp16() | ||
| 539 | .ccmr_output(channel_index / 2) | ||
| 540 | .modify(|w| w.set_ocpe(channel_index % 2, preload)); | ||
| 541 | } | ||
| 542 | |||
| 543 | /// Get capture compare DMA selection | ||
| 544 | pub fn get_cc_dma_selection(&self) -> vals::Ccds { | ||
| 545 | self.regs_gp16().cr2().read().ccds() | ||
| 546 | } | ||
| 547 | |||
| 548 | /// Set capture compare DMA selection | ||
| 549 | pub fn set_cc_dma_selection(&self, ccds: vals::Ccds) { | ||
| 550 | self.regs_gp16().cr2().modify(|w| w.set_ccds(ccds)) | ||
| 551 | } | ||
| 552 | |||
| 553 | /// Get capture compare DMA enable state | ||
| 554 | pub fn get_cc_dma_enable_state(&self, channel: Channel) -> bool { | ||
| 555 | self.regs_gp16().dier().read().ccde(channel.index()) | ||
| 556 | } | ||
| 557 | |||
| 558 | /// Set capture compare DMA enable state | ||
| 559 | pub fn set_cc_dma_enable_state(&self, channel: Channel, ccde: bool) { | ||
| 560 | self.regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde)) | ||
| 561 | } | ||
| 562 | } | ||
| 563 | |||
| 564 | #[cfg(not(stm32l0))] | ||
| 565 | impl<'d, T: GeneralInstance32bit4Channel> Timer<'d, T> { | ||
| 566 | /// Get access to the general purpose 32bit timer registers. | ||
| 567 | /// | ||
| 568 | /// Note: This works even if the timer is more capable, because registers | ||
| 569 | /// for the less capable timers are a subset. This allows writing a driver | ||
| 570 | /// for a given set of capabilities, and having it transparently work with | ||
| 571 | /// more capable timers. | ||
| 572 | pub fn regs_gp32(&self) -> crate::pac::timer::TimGp32 { | ||
| 573 | unsafe { crate::pac::timer::TimGp32::from_ptr(T::regs()) } | ||
| 574 | } | ||
| 575 | } | ||
| 576 | |||
| 577 | #[cfg(not(stm32l0))] | ||
| 578 | impl<'d, T: AdvancedInstance1Channel> Timer<'d, T> { | ||
| 579 | /// Get access to the general purpose 1 channel with one complementary 16bit timer registers. | ||
| 580 | /// | ||
| 581 | /// Note: This works even if the timer is more capable, because registers | ||
| 582 | /// for the less capable timers are a subset. This allows writing a driver | ||
| 583 | /// for a given set of capabilities, and having it transparently work with | ||
| 584 | /// more capable timers. | ||
| 585 | pub fn regs_1ch_cmp(&self) -> crate::pac::timer::Tim1chCmp { | ||
| 586 | unsafe { crate::pac::timer::Tim1chCmp::from_ptr(T::regs()) } | ||
| 587 | } | ||
| 588 | |||
| 589 | /// Set clock divider for the dead time. | ||
| 590 | pub fn set_dead_time_clock_division(&self, value: vals::Ckd) { | ||
| 591 | self.regs_1ch_cmp().cr1().modify(|w| w.set_ckd(value)); | ||
| 592 | } | ||
| 593 | |||
| 594 | /// Set dead time, as a fraction of the max duty value. | ||
| 595 | pub fn set_dead_time_value(&self, value: u8) { | ||
| 596 | self.regs_1ch_cmp().bdtr().modify(|w| w.set_dtg(value)); | ||
| 597 | } | ||
| 598 | |||
| 599 | /// Set state of MOE-bit in BDTR register to en-/disable output | ||
| 600 | pub fn set_moe(&self, enable: bool) { | ||
| 601 | self.regs_1ch_cmp().bdtr().modify(|w| w.set_moe(enable)); | ||
| 602 | } | ||
| 603 | } | ||
| 604 | |||
| 605 | #[cfg(not(stm32l0))] | ||
| 606 | impl<'d, T: AdvancedInstance2Channel> Timer<'d, T> { | ||
| 607 | /// Get access to the general purpose 2 channel with one complementary 16bit timer registers. | ||
| 608 | /// | ||
| 609 | /// Note: This works even if the timer is more capable, because registers | ||
| 610 | /// for the less capable timers are a subset. This allows writing a driver | ||
| 611 | /// for a given set of capabilities, and having it transparently work with | ||
| 612 | /// more capable timers. | ||
| 613 | pub fn regs_2ch_cmp(&self) -> crate::pac::timer::Tim2chCmp { | ||
| 614 | unsafe { crate::pac::timer::Tim2chCmp::from_ptr(T::regs()) } | ||
| 615 | } | ||
| 616 | } | ||
| 617 | |||
| 618 | #[cfg(not(stm32l0))] | ||
| 619 | impl<'d, T: AdvancedInstance4Channel> Timer<'d, T> { | ||
| 620 | /// Get access to the advanced timer registers. | ||
| 621 | pub fn regs_advanced(&self) -> crate::pac::timer::TimAdv { | ||
| 622 | unsafe { crate::pac::timer::TimAdv::from_ptr(T::regs()) } | ||
| 623 | } | ||
| 624 | |||
| 625 | /// Set complementary output polarity. | ||
| 626 | pub fn set_complementary_output_polarity(&self, channel: Channel, polarity: OutputPolarity) { | ||
| 627 | self.regs_advanced() | ||
| 628 | .ccer() | ||
| 629 | .modify(|w| w.set_ccnp(channel.index(), polarity.into())); | ||
| 630 | } | ||
| 631 | |||
| 632 | /// Enable/disable a complementary channel. | ||
| 633 | pub fn enable_complementary_channel(&self, channel: Channel, enable: bool) { | ||
| 634 | self.regs_advanced() | ||
| 635 | .ccer() | ||
| 636 | .modify(|w| w.set_ccne(channel.index(), enable)); | ||
| 637 | } | ||
| 638 | } | ||
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 @@ | |||
| 1 | //! Timers, PWM, quadrature decoder. | 1 | //! Timers, PWM, quadrature decoder. |
| 2 | //! | ||
| 3 | |||
| 4 | //! Timer inheritance | ||
| 5 | //! | ||
| 6 | |||
| 7 | // sealed: | ||
| 8 | // | ||
| 9 | // Core -------------------------> 1CH -------------------------> 1CH_CMP | ||
| 10 | // | | ^ | | ||
| 11 | // +--> Basic_NoCr2 --> Basic +--> 2CH --> GP16 --> GP32 | +--> 2CH_CMP --> ADV | ||
| 12 | // | | | ^ | | ^ ^ | ||
| 13 | // | | +------|--|--------------|-----------+ | | ||
| 14 | // | +--------------------+ +--------------|-----------|---------+ | ||
| 15 | // | | | | | ||
| 16 | // | +--------------------------------------|-----------+ | ||
| 17 | // +----------------------------------------------------+ | ||
| 18 | |||
| 19 | //! ```text | ||
| 20 | //! BasicInstance --> CaptureCompare16bitInstance --+--> ComplementaryCaptureCompare16bitInstance | ||
| 21 | //! | | ||
| 22 | //! +--> CaptureCompare32bitInstance | ||
| 23 | //! ``` | ||
| 24 | //! | ||
| 25 | //! Mapping: | ||
| 26 | //! | ||
| 27 | //! | trait | timer | | ||
| 28 | //! | :----------------------------------------: | ------------------------------------------------------------------------------------------------- | | ||
| 29 | //! | [BasicInstance] | Basic Timer | | ||
| 30 | //! | [CaptureCompare16bitInstance] | 1-channel Timer, 2-channel Timer, General Purpose 16-bit Timer | | ||
| 31 | //! | [CaptureCompare32bitInstance] | General Purpose 32-bit Timer | | ||
| 32 | //! | [ComplementaryCaptureCompare16bitInstance] | 1-channel with one complentary Timer, 2-channel with one complentary Timer, Advance Control Timer | | ||
| 33 | 2 | ||
| 34 | #[cfg(not(stm32l0))] | 3 | #[cfg(not(stm32l0))] |
| 35 | pub mod complementary_pwm; | 4 | pub mod complementary_pwm; |
| 5 | pub mod low_level; | ||
| 36 | pub mod qei; | 6 | pub mod qei; |
| 37 | pub mod simple_pwm; | 7 | pub mod simple_pwm; |
| 38 | 8 | ||
| 39 | use stm32_metapac::timer::vals; | ||
| 40 | |||
| 41 | use crate::interrupt; | 9 | use crate::interrupt; |
| 42 | use crate::rcc::RccPeripheral; | 10 | use crate::rcc::RccPeripheral; |
| 43 | use crate::time::Hertz; | ||
| 44 | |||
| 45 | /// Low-level timer access. | ||
| 46 | #[cfg(feature = "unstable-pac")] | ||
| 47 | pub mod low_level { | ||
| 48 | pub use super::sealed::*; | ||
| 49 | } | ||
| 50 | |||
| 51 | pub(crate) mod sealed { | ||
| 52 | use super::*; | ||
| 53 | |||
| 54 | /// Virtual Core 16-bit timer instance. | ||
| 55 | pub trait CoreInstance: RccPeripheral { | ||
| 56 | /// Interrupt for this timer. | ||
| 57 | type Interrupt: interrupt::typelevel::Interrupt; | ||
| 58 | |||
| 59 | /// Get access to the virutal core 16bit timer registers. | ||
| 60 | /// | ||
| 61 | /// Note: This works even if the timer is more capable, because registers | ||
| 62 | /// for the less capable timers are a subset. This allows writing a driver | ||
| 63 | /// for a given set of capabilities, and having it transparently work with | ||
| 64 | /// more capable timers. | ||
| 65 | fn regs_core() -> crate::pac::timer::TimCore; | ||
| 66 | |||
| 67 | /// Start the timer. | ||
| 68 | fn start(&self) { | ||
| 69 | Self::regs_core().cr1().modify(|r| r.set_cen(true)); | ||
| 70 | } | ||
| 71 | |||
| 72 | /// Stop the timer. | ||
| 73 | fn stop(&self) { | ||
| 74 | Self::regs_core().cr1().modify(|r| r.set_cen(false)); | ||
| 75 | } | ||
| 76 | |||
| 77 | /// Reset the counter value to 0 | ||
| 78 | fn reset(&self) { | ||
| 79 | Self::regs_core().cnt().write(|r| r.set_cnt(0)); | ||
| 80 | } | ||
| 81 | |||
| 82 | /// Set the frequency of how many times per second the timer counts up to the max value or down to 0. | ||
| 83 | /// | ||
| 84 | /// This means that in the default edge-aligned mode, | ||
| 85 | /// the timer counter will wrap around at the same frequency as is being set. | ||
| 86 | /// In center-aligned mode (which not all timers support), the wrap-around frequency is effectively halved | ||
| 87 | /// because it needs to count up and down. | ||
| 88 | fn set_frequency(&self, frequency: Hertz) { | ||
| 89 | let f = frequency.0; | ||
| 90 | let timer_f = Self::frequency().0; | ||
| 91 | assert!(f > 0); | ||
| 92 | let pclk_ticks_per_timer_period = timer_f / f; | ||
| 93 | let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 16)).try_into()); | ||
| 94 | let divide_by = pclk_ticks_per_timer_period / (u32::from(psc) + 1); | ||
| 95 | |||
| 96 | // the timer counts `0..=arr`, we want it to count `0..divide_by` | ||
| 97 | let arr = unwrap!(u16::try_from(divide_by - 1)); | ||
| 98 | |||
| 99 | let regs = Self::regs_core(); | ||
| 100 | regs.psc().write_value(psc); | ||
| 101 | regs.arr().write(|r| r.set_arr(arr)); | ||
| 102 | |||
| 103 | regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); | ||
| 104 | regs.egr().write(|r| r.set_ug(true)); | ||
| 105 | regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); | ||
| 106 | } | ||
| 107 | |||
| 108 | /// Clear update interrupt. | ||
| 109 | /// | ||
| 110 | /// Returns whether the update interrupt flag was set. | ||
| 111 | fn clear_update_interrupt(&self) -> bool { | ||
| 112 | let regs = Self::regs_core(); | ||
| 113 | let sr = regs.sr().read(); | ||
| 114 | if sr.uif() { | ||
| 115 | regs.sr().modify(|r| { | ||
| 116 | r.set_uif(false); | ||
| 117 | }); | ||
| 118 | true | ||
| 119 | } else { | ||
| 120 | false | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | /// Enable/disable the update interrupt. | ||
| 125 | fn enable_update_interrupt(&self, enable: bool) { | ||
| 126 | Self::regs_core().dier().modify(|r| r.set_uie(enable)); | ||
| 127 | } | ||
| 128 | |||
| 129 | /// Enable/disable autoreload preload. | ||
| 130 | fn set_autoreload_preload(&self, enable: bool) { | ||
| 131 | Self::regs_core().cr1().modify(|r| r.set_arpe(enable)); | ||
| 132 | } | ||
| 133 | |||
| 134 | /// Get the timer frequency. | ||
| 135 | fn get_frequency(&self) -> Hertz { | ||
| 136 | let timer_f = Self::frequency(); | ||
| 137 | |||
| 138 | let regs = Self::regs_core(); | ||
| 139 | let arr = regs.arr().read().arr(); | ||
| 140 | let psc = regs.psc().read(); | ||
| 141 | |||
| 142 | timer_f / arr / (psc + 1) | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | /// Virtual Basic without CR2 16-bit timer instance. | ||
| 147 | pub trait BasicNoCr2Instance: CoreInstance { | ||
| 148 | /// Get access to the Baisc 16bit timer registers. | ||
| 149 | /// | ||
| 150 | /// Note: This works even if the timer is more capable, because registers | ||
| 151 | /// for the less capable timers are a subset. This allows writing a driver | ||
| 152 | /// for a given set of capabilities, and having it transparently work with | ||
| 153 | /// more capable timers. | ||
| 154 | fn regs_basic_no_cr2() -> crate::pac::timer::TimBasicNoCr2; | ||
| 155 | |||
| 156 | /// Enable/disable the update dma. | ||
| 157 | fn enable_update_dma(&self, enable: bool) { | ||
| 158 | Self::regs_basic_no_cr2().dier().modify(|r| r.set_ude(enable)); | ||
| 159 | } | ||
| 160 | |||
| 161 | /// Get the update dma enable/disable state. | ||
| 162 | fn get_update_dma_state(&self) -> bool { | ||
| 163 | Self::regs_basic_no_cr2().dier().read().ude() | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | /// Basic 16-bit timer instance. | ||
| 168 | pub trait BasicInstance: BasicNoCr2Instance { | ||
| 169 | /// Get access to the Baisc 16bit timer registers. | ||
| 170 | /// | ||
| 171 | /// Note: This works even if the timer is more capable, because registers | ||
| 172 | /// for the less capable timers are a subset. This allows writing a driver | ||
| 173 | /// for a given set of capabilities, and having it transparently work with | ||
| 174 | /// more capable timers. | ||
| 175 | fn regs_basic() -> crate::pac::timer::TimBasic; | ||
| 176 | } | ||
| 177 | |||
| 178 | /// Gneral-purpose 1 channel 16-bit timer instance. | ||
| 179 | pub trait GeneralPurpose1ChannelInstance: CoreInstance { | ||
| 180 | /// Get access to the general purpose 1 channel 16bit timer registers. | ||
| 181 | /// | ||
| 182 | /// Note: This works even if the timer is more capable, because registers | ||
| 183 | /// for the less capable timers are a subset. This allows writing a driver | ||
| 184 | /// for a given set of capabilities, and having it transparently work with | ||
| 185 | /// more capable timers. | ||
| 186 | fn regs_1ch() -> crate::pac::timer::Tim1ch; | ||
| 187 | |||
| 188 | /// Set clock divider. | ||
| 189 | fn set_clock_division(&self, ckd: vals::Ckd) { | ||
| 190 | Self::regs_1ch().cr1().modify(|r| r.set_ckd(ckd)); | ||
| 191 | } | ||
| 192 | |||
| 193 | /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC. | ||
| 194 | fn get_max_compare_value(&self) -> u16 { | ||
| 195 | Self::regs_1ch().arr().read().arr() | ||
| 196 | } | ||
| 197 | } | ||
| 198 | |||
| 199 | /// Gneral-purpose 1 channel 16-bit timer instance. | ||
| 200 | pub trait GeneralPurpose2ChannelInstance: GeneralPurpose1ChannelInstance { | ||
| 201 | /// Get access to the general purpose 2 channel 16bit timer registers. | ||
| 202 | /// | ||
| 203 | /// Note: This works even if the timer is more capable, because registers | ||
| 204 | /// for the less capable timers are a subset. This allows writing a driver | ||
| 205 | /// for a given set of capabilities, and having it transparently work with | ||
| 206 | /// more capable timers. | ||
| 207 | fn regs_2ch() -> crate::pac::timer::Tim2ch; | ||
| 208 | } | ||
| 209 | |||
| 210 | /// Gneral-purpose 16-bit timer instance. | ||
| 211 | pub trait GeneralPurpose16bitInstance: BasicInstance + GeneralPurpose2ChannelInstance { | ||
| 212 | /// Get access to the general purpose 16bit timer registers. | ||
| 213 | /// | ||
| 214 | /// Note: This works even if the timer is more capable, because registers | ||
| 215 | /// for the less capable timers are a subset. This allows writing a driver | ||
| 216 | /// for a given set of capabilities, and having it transparently work with | ||
| 217 | /// more capable timers. | ||
| 218 | fn regs_gp16() -> crate::pac::timer::TimGp16; | ||
| 219 | |||
| 220 | /// Set counting mode. | ||
| 221 | fn set_counting_mode(&self, mode: CountingMode) { | ||
| 222 | let (cms, dir) = mode.into(); | ||
| 223 | |||
| 224 | let timer_enabled = Self::regs_core().cr1().read().cen(); | ||
| 225 | // Changing from edge aligned to center aligned (and vice versa) is not allowed while the timer is running. | ||
| 226 | // Changing direction is discouraged while the timer is running. | ||
| 227 | assert!(!timer_enabled); | ||
| 228 | |||
| 229 | Self::regs_gp16().cr1().modify(|r| r.set_dir(dir)); | ||
| 230 | Self::regs_gp16().cr1().modify(|r| r.set_cms(cms)) | ||
| 231 | } | ||
| 232 | |||
| 233 | /// Get counting mode. | ||
| 234 | fn get_counting_mode(&self) -> CountingMode { | ||
| 235 | let cr1 = Self::regs_gp16().cr1().read(); | ||
| 236 | (cr1.cms(), cr1.dir()).into() | ||
| 237 | } | ||
| 238 | |||
| 239 | /// Set input capture filter. | ||
| 240 | fn set_input_capture_filter(&self, channel: Channel, icf: vals::FilterValue) { | ||
| 241 | let raw_channel = channel.index(); | ||
| 242 | Self::regs_gp16() | ||
| 243 | .ccmr_input(raw_channel / 2) | ||
| 244 | .modify(|r| r.set_icf(raw_channel % 2, icf)); | ||
| 245 | } | ||
| 246 | |||
| 247 | /// Clear input interrupt. | ||
| 248 | fn clear_input_interrupt(&self, channel: Channel) { | ||
| 249 | Self::regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false)); | ||
| 250 | } | ||
| 251 | |||
| 252 | /// Enable input interrupt. | ||
| 253 | fn enable_input_interrupt(&self, channel: Channel, enable: bool) { | ||
| 254 | Self::regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable)); | ||
| 255 | } | ||
| 256 | |||
| 257 | /// Set input capture prescaler. | ||
| 258 | fn set_input_capture_prescaler(&self, channel: Channel, factor: u8) { | ||
| 259 | let raw_channel = channel.index(); | ||
| 260 | Self::regs_gp16() | ||
| 261 | .ccmr_input(raw_channel / 2) | ||
| 262 | .modify(|r| r.set_icpsc(raw_channel % 2, factor)); | ||
| 263 | } | ||
| 264 | |||
| 265 | /// Set input TI selection. | ||
| 266 | fn set_input_ti_selection(&self, channel: Channel, tisel: InputTISelection) { | ||
| 267 | let raw_channel = channel.index(); | ||
| 268 | Self::regs_gp16() | ||
| 269 | .ccmr_input(raw_channel / 2) | ||
| 270 | .modify(|r| r.set_ccs(raw_channel % 2, tisel.into())); | ||
| 271 | } | ||
| 272 | |||
| 273 | /// Set input capture mode. | ||
| 274 | fn set_input_capture_mode(&self, channel: Channel, mode: InputCaptureMode) { | ||
| 275 | Self::regs_gp16().ccer().modify(|r| match mode { | ||
| 276 | InputCaptureMode::Rising => { | ||
| 277 | r.set_ccnp(channel.index(), false); | ||
| 278 | r.set_ccp(channel.index(), false); | ||
| 279 | } | ||
| 280 | InputCaptureMode::Falling => { | ||
| 281 | r.set_ccnp(channel.index(), false); | ||
| 282 | r.set_ccp(channel.index(), true); | ||
| 283 | } | ||
| 284 | InputCaptureMode::BothEdges => { | ||
| 285 | r.set_ccnp(channel.index(), true); | ||
| 286 | r.set_ccp(channel.index(), true); | ||
| 287 | } | ||
| 288 | }); | ||
| 289 | } | ||
| 290 | |||
| 291 | /// Set output compare mode. | ||
| 292 | fn set_output_compare_mode(&self, channel: Channel, mode: OutputCompareMode) { | ||
| 293 | let raw_channel: usize = channel.index(); | ||
| 294 | Self::regs_gp16() | ||
| 295 | .ccmr_output(raw_channel / 2) | ||
| 296 | .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); | ||
| 297 | } | ||
| 298 | |||
| 299 | /// Set output polarity. | ||
| 300 | fn set_output_polarity(&self, channel: Channel, polarity: OutputPolarity) { | ||
| 301 | Self::regs_gp16() | ||
| 302 | .ccer() | ||
| 303 | .modify(|w| w.set_ccp(channel.index(), polarity.into())); | ||
| 304 | } | ||
| 305 | |||
| 306 | /// Enable/disable a channel. | ||
| 307 | fn enable_channel(&self, channel: Channel, enable: bool) { | ||
| 308 | Self::regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable)); | ||
| 309 | } | ||
| 310 | |||
| 311 | /// Get enable/disable state of a channel | ||
| 312 | fn get_channel_enable_state(&self, channel: Channel) -> bool { | ||
| 313 | Self::regs_gp16().ccer().read().cce(channel.index()) | ||
| 314 | } | ||
| 315 | |||
| 316 | /// Set compare value for a channel. | ||
| 317 | fn set_compare_value(&self, channel: Channel, value: u16) { | ||
| 318 | Self::regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value)); | ||
| 319 | } | ||
| 320 | |||
| 321 | /// Get capture value for a channel. | ||
| 322 | fn get_capture_value(&self, channel: Channel) -> u16 { | ||
| 323 | Self::regs_gp16().ccr(channel.index()).read().ccr() | ||
| 324 | } | ||
| 325 | |||
| 326 | /// Get compare value for a channel. | ||
| 327 | fn get_compare_value(&self, channel: Channel) -> u16 { | ||
| 328 | Self::regs_gp16().ccr(channel.index()).read().ccr() | ||
| 329 | } | ||
| 330 | |||
| 331 | /// Set output compare preload. | ||
| 332 | fn set_output_compare_preload(&self, channel: Channel, preload: bool) { | ||
| 333 | let channel_index = channel.index(); | ||
| 334 | Self::regs_gp16() | ||
| 335 | .ccmr_output(channel_index / 2) | ||
| 336 | .modify(|w| w.set_ocpe(channel_index % 2, preload)); | ||
| 337 | } | ||
| 338 | |||
| 339 | /// Get capture compare DMA selection | ||
| 340 | fn get_cc_dma_selection(&self) -> super::vals::Ccds { | ||
| 341 | Self::regs_gp16().cr2().read().ccds() | ||
| 342 | } | ||
| 343 | |||
| 344 | /// Set capture compare DMA selection | ||
| 345 | fn set_cc_dma_selection(&self, ccds: super::vals::Ccds) { | ||
| 346 | Self::regs_gp16().cr2().modify(|w| w.set_ccds(ccds)) | ||
| 347 | } | ||
| 348 | |||
| 349 | /// Get capture compare DMA enable state | ||
| 350 | fn get_cc_dma_enable_state(&self, channel: Channel) -> bool { | ||
| 351 | Self::regs_gp16().dier().read().ccde(channel.index()) | ||
| 352 | } | ||
| 353 | |||
| 354 | /// Set capture compare DMA enable state | ||
| 355 | fn set_cc_dma_enable_state(&self, channel: Channel, ccde: bool) { | ||
| 356 | Self::regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde)) | ||
| 357 | } | ||
| 358 | } | ||
| 359 | |||
| 360 | #[cfg(not(stm32l0))] | ||
| 361 | /// Gneral-purpose 32-bit timer instance. | ||
| 362 | pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance { | ||
| 363 | /// Get access to the general purpose 32bit timer registers. | ||
| 364 | /// | ||
| 365 | /// Note: This works even if the timer is more capable, because registers | ||
| 366 | /// for the less capable timers are a subset. This allows writing a driver | ||
| 367 | /// for a given set of capabilities, and having it transparently work with | ||
| 368 | /// more capable timers. | ||
| 369 | fn regs_gp32() -> crate::pac::timer::TimGp32; | ||
| 370 | |||
| 371 | /// Set timer frequency. | ||
| 372 | fn set_frequency(&self, frequency: Hertz) { | ||
| 373 | let f = frequency.0; | ||
| 374 | assert!(f > 0); | ||
| 375 | let timer_f = Self::frequency().0; | ||
| 376 | let pclk_ticks_per_timer_period = (timer_f / f) as u64; | ||
| 377 | let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into()); | ||
| 378 | let arr: u32 = unwrap!((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into()); | ||
| 379 | |||
| 380 | let regs = Self::regs_gp32(); | ||
| 381 | regs.psc().write_value(psc); | ||
| 382 | regs.arr().write_value(arr); | ||
| 383 | |||
| 384 | regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); | ||
| 385 | regs.egr().write(|r| r.set_ug(true)); | ||
| 386 | regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); | ||
| 387 | } | ||
| 388 | |||
| 389 | /// Get timer frequency. | ||
| 390 | fn get_frequency(&self) -> Hertz { | ||
| 391 | let timer_f = Self::frequency(); | ||
| 392 | |||
| 393 | let regs = Self::regs_gp32(); | ||
| 394 | let arr = regs.arr().read(); | ||
| 395 | let psc = regs.psc().read(); | ||
| 396 | |||
| 397 | timer_f / arr / (psc + 1) | ||
| 398 | } | ||
| 399 | |||
| 400 | /// Set comapre value for a channel. | ||
| 401 | fn set_compare_value(&self, channel: Channel, value: u32) { | ||
| 402 | Self::regs_gp32().ccr(channel.index()).write_value(value); | ||
| 403 | } | ||
| 404 | |||
| 405 | /// Get capture value for a channel. | ||
| 406 | fn get_capture_value(&self, channel: Channel) -> u32 { | ||
| 407 | Self::regs_gp32().ccr(channel.index()).read() | ||
| 408 | } | ||
| 409 | |||
| 410 | /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC. | ||
| 411 | fn get_max_compare_value(&self) -> u32 { | ||
| 412 | Self::regs_gp32().arr().read() | ||
| 413 | } | ||
| 414 | |||
| 415 | /// Get compare value for a channel. | ||
| 416 | fn get_compare_value(&self, channel: Channel) -> u32 { | ||
| 417 | Self::regs_gp32().ccr(channel.index()).read() | ||
| 418 | } | ||
| 419 | } | ||
| 420 | |||
| 421 | #[cfg(not(stm32l0))] | ||
| 422 | /// Gneral-purpose 1 channel with one complementary 16-bit timer instance. | ||
| 423 | pub trait GeneralPurpose1ChannelComplementaryInstance: BasicNoCr2Instance + GeneralPurpose1ChannelInstance { | ||
| 424 | /// Get access to the general purpose 1 channel with one complementary 16bit timer registers. | ||
| 425 | /// | ||
| 426 | /// Note: This works even if the timer is more capable, because registers | ||
| 427 | /// for the less capable timers are a subset. This allows writing a driver | ||
| 428 | /// for a given set of capabilities, and having it transparently work with | ||
| 429 | /// more capable timers. | ||
| 430 | fn regs_1ch_cmp() -> crate::pac::timer::Tim1chCmp; | ||
| 431 | |||
| 432 | /// Set clock divider for the dead time. | ||
| 433 | fn set_dead_time_clock_division(&self, value: vals::Ckd) { | ||
| 434 | Self::regs_1ch_cmp().cr1().modify(|w| w.set_ckd(value)); | ||
| 435 | } | ||
| 436 | |||
| 437 | /// Set dead time, as a fraction of the max duty value. | ||
| 438 | fn set_dead_time_value(&self, value: u8) { | ||
| 439 | Self::regs_1ch_cmp().bdtr().modify(|w| w.set_dtg(value)); | ||
| 440 | } | ||
| 441 | |||
| 442 | /// Set state of MOE-bit in BDTR register to en-/disable output | ||
| 443 | fn set_moe(&self, enable: bool) { | ||
| 444 | Self::regs_1ch_cmp().bdtr().modify(|w| w.set_moe(enable)); | ||
| 445 | } | ||
| 446 | } | ||
| 447 | |||
| 448 | #[cfg(not(stm32l0))] | ||
| 449 | /// Gneral-purpose 2 channel with one complementary 16-bit timer instance. | ||
| 450 | pub trait GeneralPurpose2ChannelComplementaryInstance: | ||
| 451 | BasicInstance + GeneralPurpose2ChannelInstance + GeneralPurpose1ChannelComplementaryInstance | ||
| 452 | { | ||
| 453 | /// Get access to the general purpose 2 channel with one complementary 16bit timer registers. | ||
| 454 | /// | ||
| 455 | /// Note: This works even if the timer is more capable, because registers | ||
| 456 | /// for the less capable timers are a subset. This allows writing a driver | ||
| 457 | /// for a given set of capabilities, and having it transparently work with | ||
| 458 | /// more capable timers. | ||
| 459 | fn regs_2ch_cmp() -> crate::pac::timer::Tim2chCmp; | ||
| 460 | } | ||
| 461 | |||
| 462 | #[cfg(not(stm32l0))] | ||
| 463 | /// Advanced control timer instance. | ||
| 464 | pub trait AdvancedControlInstance: | ||
| 465 | GeneralPurpose2ChannelComplementaryInstance + GeneralPurpose16bitInstance | ||
| 466 | { | ||
| 467 | /// Capture compare interrupt for this timer. | ||
| 468 | type CaptureCompareInterrupt: interrupt::typelevel::Interrupt; | ||
| 469 | |||
| 470 | /// Get access to the advanced timer registers. | ||
| 471 | fn regs_advanced() -> crate::pac::timer::TimAdv; | ||
| 472 | |||
| 473 | /// Set complementary output polarity. | ||
| 474 | fn set_complementary_output_polarity(&self, channel: Channel, polarity: OutputPolarity) { | ||
| 475 | Self::regs_advanced() | ||
| 476 | .ccer() | ||
| 477 | .modify(|w| w.set_ccnp(channel.index(), polarity.into())); | ||
| 478 | } | ||
| 479 | |||
| 480 | /// Enable/disable a complementary channel. | ||
| 481 | fn enable_complementary_channel(&self, channel: Channel, enable: bool) { | ||
| 482 | Self::regs_advanced() | ||
| 483 | .ccer() | ||
| 484 | .modify(|w| w.set_ccne(channel.index(), enable)); | ||
| 485 | } | ||
| 486 | } | ||
| 487 | } | ||
| 488 | 11 | ||
| 489 | /// Timer channel. | 12 | /// Timer channel. |
| 490 | #[derive(Clone, Copy)] | 13 | #[derive(Clone, Copy)] |
| @@ -511,181 +34,44 @@ impl Channel { | |||
| 511 | } | 34 | } |
| 512 | } | 35 | } |
| 513 | 36 | ||
| 514 | /// Input capture mode. | 37 | /// Amount of bits of a timer. |
| 515 | #[derive(Clone, Copy)] | 38 | #[derive(Clone, Copy, PartialEq, Eq, Debug)] |
| 516 | pub enum InputCaptureMode { | 39 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 517 | /// Rising edge only. | 40 | pub enum TimerBits { |
| 518 | Rising, | 41 | /// 16 bits. |
| 519 | /// Falling edge only. | 42 | Bits16, |
| 520 | Falling, | 43 | /// 32 bits. |
| 521 | /// Both rising or falling edges. | 44 | #[cfg(not(stm32l0))] |
| 522 | BothEdges, | 45 | Bits32, |
| 523 | } | 46 | } |
| 524 | 47 | ||
| 525 | /// Input TI selection. | 48 | /// Core timer instance. |
| 526 | #[derive(Clone, Copy)] | 49 | pub trait CoreInstance: RccPeripheral + 'static { |
| 527 | pub enum InputTISelection { | 50 | /// Interrupt for this timer. |
| 528 | /// Normal | 51 | type Interrupt: interrupt::typelevel::Interrupt; |
| 529 | Normal, | ||
| 530 | /// Alternate | ||
| 531 | Alternate, | ||
| 532 | /// TRC | ||
| 533 | TRC, | ||
| 534 | } | ||
| 535 | 52 | ||
| 536 | impl From<InputTISelection> for stm32_metapac::timer::vals::CcmrInputCcs { | 53 | /// Amount of bits this timer has. |
| 537 | fn from(tisel: InputTISelection) -> Self { | 54 | const BITS: TimerBits; |
| 538 | match tisel { | ||
| 539 | InputTISelection::Normal => stm32_metapac::timer::vals::CcmrInputCcs::TI4, | ||
| 540 | InputTISelection::Alternate => stm32_metapac::timer::vals::CcmrInputCcs::TI3, | ||
| 541 | InputTISelection::TRC => stm32_metapac::timer::vals::CcmrInputCcs::TRC, | ||
| 542 | } | ||
| 543 | } | ||
| 544 | } | ||
| 545 | 55 | ||
| 546 | /// Timer counting mode. | 56 | /// Registers for this timer. |
| 547 | #[repr(u8)] | ||
| 548 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] | ||
| 549 | pub enum CountingMode { | ||
| 550 | #[default] | ||
| 551 | /// The timer counts up to the reload value and then resets back to 0. | ||
| 552 | EdgeAlignedUp, | ||
| 553 | /// The timer counts down to 0 and then resets back to the reload value. | ||
| 554 | EdgeAlignedDown, | ||
| 555 | /// The timer counts up to the reload value and then counts back to 0. | ||
| 556 | /// | 57 | /// |
| 557 | /// The output compare interrupt flags of channels configured in output are | 58 | /// This is a raw pointer to the register block. The actual register block layout varies depending on the timer type. |
| 558 | /// set when the counter is counting down. | 59 | fn regs() -> *mut (); |
| 559 | CenterAlignedDownInterrupts, | ||
| 560 | /// The timer counts up to the reload value and then counts back to 0. | ||
| 561 | /// | ||
| 562 | /// The output compare interrupt flags of channels configured in output are | ||
| 563 | /// set when the counter is counting up. | ||
| 564 | CenterAlignedUpInterrupts, | ||
| 565 | /// The timer counts up to the reload value and then counts back to 0. | ||
| 566 | /// | ||
| 567 | /// The output compare interrupt flags of channels configured in output are | ||
| 568 | /// set when the counter is counting both up or down. | ||
| 569 | CenterAlignedBothInterrupts, | ||
| 570 | } | ||
| 571 | |||
| 572 | impl CountingMode { | ||
| 573 | /// Return whether this mode is edge-aligned (up or down). | ||
| 574 | pub fn is_edge_aligned(&self) -> bool { | ||
| 575 | matches!(self, CountingMode::EdgeAlignedUp | CountingMode::EdgeAlignedDown) | ||
| 576 | } | ||
| 577 | |||
| 578 | /// Return whether this mode is center-aligned. | ||
| 579 | pub fn is_center_aligned(&self) -> bool { | ||
| 580 | matches!( | ||
| 581 | self, | ||
| 582 | CountingMode::CenterAlignedDownInterrupts | ||
| 583 | | CountingMode::CenterAlignedUpInterrupts | ||
| 584 | | CountingMode::CenterAlignedBothInterrupts | ||
| 585 | ) | ||
| 586 | } | ||
| 587 | } | ||
| 588 | |||
| 589 | impl From<CountingMode> for (vals::Cms, vals::Dir) { | ||
| 590 | fn from(value: CountingMode) -> Self { | ||
| 591 | match value { | ||
| 592 | CountingMode::EdgeAlignedUp => (vals::Cms::EDGEALIGNED, vals::Dir::UP), | ||
| 593 | CountingMode::EdgeAlignedDown => (vals::Cms::EDGEALIGNED, vals::Dir::DOWN), | ||
| 594 | CountingMode::CenterAlignedDownInterrupts => (vals::Cms::CENTERALIGNED1, vals::Dir::UP), | ||
| 595 | CountingMode::CenterAlignedUpInterrupts => (vals::Cms::CENTERALIGNED2, vals::Dir::UP), | ||
| 596 | CountingMode::CenterAlignedBothInterrupts => (vals::Cms::CENTERALIGNED3, vals::Dir::UP), | ||
| 597 | } | ||
| 598 | } | ||
| 599 | } | ||
| 600 | |||
| 601 | impl From<(vals::Cms, vals::Dir)> for CountingMode { | ||
| 602 | fn from(value: (vals::Cms, vals::Dir)) -> Self { | ||
| 603 | match value { | ||
| 604 | (vals::Cms::EDGEALIGNED, vals::Dir::UP) => CountingMode::EdgeAlignedUp, | ||
| 605 | (vals::Cms::EDGEALIGNED, vals::Dir::DOWN) => CountingMode::EdgeAlignedDown, | ||
| 606 | (vals::Cms::CENTERALIGNED1, _) => CountingMode::CenterAlignedDownInterrupts, | ||
| 607 | (vals::Cms::CENTERALIGNED2, _) => CountingMode::CenterAlignedUpInterrupts, | ||
| 608 | (vals::Cms::CENTERALIGNED3, _) => CountingMode::CenterAlignedBothInterrupts, | ||
| 609 | } | ||
| 610 | } | ||
| 611 | } | ||
| 612 | |||
| 613 | /// Output compare mode. | ||
| 614 | #[derive(Clone, Copy)] | ||
| 615 | pub enum OutputCompareMode { | ||
| 616 | /// The comparison between the output compare register TIMx_CCRx and | ||
| 617 | /// the counter TIMx_CNT has no effect on the outputs. | ||
| 618 | /// (this mode is used to generate a timing base). | ||
| 619 | Frozen, | ||
| 620 | /// Set channel to active level on match. OCxREF signal is forced high when the | ||
| 621 | /// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx). | ||
| 622 | ActiveOnMatch, | ||
| 623 | /// Set channel to inactive level on match. OCxREF signal is forced low when the | ||
| 624 | /// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx). | ||
| 625 | InactiveOnMatch, | ||
| 626 | /// Toggle - OCxREF toggles when TIMx_CNT=TIMx_CCRx. | ||
| 627 | Toggle, | ||
| 628 | /// Force inactive level - OCxREF is forced low. | ||
| 629 | ForceInactive, | ||
| 630 | /// Force active level - OCxREF is forced high. | ||
| 631 | ForceActive, | ||
| 632 | /// PWM mode 1 - In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRx | ||
| 633 | /// else inactive. In downcounting, channel is inactive (OCxREF=0) as long as | ||
| 634 | /// TIMx_CNT>TIMx_CCRx else active (OCxREF=1). | ||
| 635 | PwmMode1, | ||
| 636 | /// PWM mode 2 - In upcounting, channel is inactive as long as | ||
| 637 | /// TIMx_CNT<TIMx_CCRx else active. In downcounting, channel is active as long as | ||
| 638 | /// TIMx_CNT>TIMx_CCRx else inactive. | ||
| 639 | PwmMode2, | ||
| 640 | // TODO: there's more modes here depending on the chip family. | ||
| 641 | } | ||
| 642 | |||
| 643 | impl From<OutputCompareMode> for stm32_metapac::timer::vals::Ocm { | ||
| 644 | fn from(mode: OutputCompareMode) -> Self { | ||
| 645 | match mode { | ||
| 646 | OutputCompareMode::Frozen => stm32_metapac::timer::vals::Ocm::FROZEN, | ||
| 647 | OutputCompareMode::ActiveOnMatch => stm32_metapac::timer::vals::Ocm::ACTIVEONMATCH, | ||
| 648 | OutputCompareMode::InactiveOnMatch => stm32_metapac::timer::vals::Ocm::INACTIVEONMATCH, | ||
| 649 | OutputCompareMode::Toggle => stm32_metapac::timer::vals::Ocm::TOGGLE, | ||
| 650 | OutputCompareMode::ForceInactive => stm32_metapac::timer::vals::Ocm::FORCEINACTIVE, | ||
| 651 | OutputCompareMode::ForceActive => stm32_metapac::timer::vals::Ocm::FORCEACTIVE, | ||
| 652 | OutputCompareMode::PwmMode1 => stm32_metapac::timer::vals::Ocm::PWMMODE1, | ||
| 653 | OutputCompareMode::PwmMode2 => stm32_metapac::timer::vals::Ocm::PWMMODE2, | ||
| 654 | } | ||
| 655 | } | ||
| 656 | } | 60 | } |
| 61 | /// Cut-down basic timer instance. | ||
| 62 | pub trait BasicNoCr2Instance: CoreInstance {} | ||
| 63 | /// Basic timer instance. | ||
| 64 | pub trait BasicInstance: BasicNoCr2Instance {} | ||
| 657 | 65 | ||
| 658 | /// Timer output pin polarity. | 66 | /// General-purpose 16-bit timer with 1 channel instance. |
| 659 | #[derive(Clone, Copy)] | 67 | pub trait GeneralInstance1Channel: CoreInstance {} |
| 660 | pub enum OutputPolarity { | ||
| 661 | /// Active high (higher duty value makes the pin spend more time high). | ||
| 662 | ActiveHigh, | ||
| 663 | /// Active low (higher duty value makes the pin spend more time low). | ||
| 664 | ActiveLow, | ||
| 665 | } | ||
| 666 | 68 | ||
| 667 | impl From<OutputPolarity> for bool { | 69 | /// General-purpose 16-bit timer with 2 channels instance. |
| 668 | fn from(mode: OutputPolarity) -> Self { | 70 | pub trait GeneralInstance2Channel: GeneralInstance1Channel {} |
| 669 | match mode { | ||
| 670 | OutputPolarity::ActiveHigh => false, | ||
| 671 | OutputPolarity::ActiveLow => true, | ||
| 672 | } | ||
| 673 | } | ||
| 674 | } | ||
| 675 | 71 | ||
| 676 | /// Basic 16-bit timer instance. | 72 | /// General-purpose 16-bit timer with 4 channels instance. |
| 677 | pub trait BasicInstance: sealed::BasicInstance + sealed::BasicNoCr2Instance + sealed::CoreInstance + 'static {} | 73 | pub trait GeneralInstance4Channel: BasicInstance + GeneralInstance2Channel { |
| 678 | 74 | // SimplePwm<'d, T> is implemented for T: GeneralInstance4Channel | |
| 679 | // It's just a General-purpose 16-bit timer instance. | ||
| 680 | /// Capture Compare timer instance. | ||
| 681 | pub trait CaptureCompare16bitInstance: | ||
| 682 | BasicInstance | ||
| 683 | + sealed::GeneralPurpose2ChannelInstance | ||
| 684 | + sealed::GeneralPurpose1ChannelInstance | ||
| 685 | + sealed::GeneralPurpose16bitInstance | ||
| 686 | + 'static | ||
| 687 | { | ||
| 688 | // SimplePwm<'d, T> is implemented for T: CaptureCompare16bitInstance | ||
| 689 | // Advanced timers implement this trait, but the output needs to be | 75 | // Advanced timers implement this trait, but the output needs to be |
| 690 | // enabled explicitly. | 76 | // enabled explicitly. |
| 691 | // To support general-purpose and advanced timers, this function is added | 77 | // To support general-purpose and advanced timers, this function is added |
| @@ -694,296 +80,149 @@ pub trait CaptureCompare16bitInstance: | |||
| 694 | fn enable_outputs(&self) {} | 80 | fn enable_outputs(&self) {} |
| 695 | } | 81 | } |
| 696 | 82 | ||
| 697 | #[cfg(not(stm32l0))] | 83 | /// General-purpose 32-bit timer with 4 channels instance. |
| 698 | // It's just a General-purpose 32-bit timer instance. | 84 | pub trait GeneralInstance32bit4Channel: GeneralInstance4Channel {} |
| 699 | /// Capture Compare 32-bit timer instance. | ||
| 700 | pub trait CaptureCompare32bitInstance: | ||
| 701 | CaptureCompare16bitInstance + sealed::GeneralPurpose32bitInstance + 'static | ||
| 702 | { | ||
| 703 | } | ||
| 704 | |||
| 705 | #[cfg(not(stm32l0))] | ||
| 706 | // It's just a Advanced Control timer instance. | ||
| 707 | /// Complementary Capture Compare 32-bit timer instance. | ||
| 708 | pub trait ComplementaryCaptureCompare16bitInstance: | ||
| 709 | CaptureCompare16bitInstance | ||
| 710 | + sealed::GeneralPurpose1ChannelComplementaryInstance | ||
| 711 | + sealed::GeneralPurpose2ChannelComplementaryInstance | ||
| 712 | + sealed::AdvancedControlInstance | ||
| 713 | + 'static | ||
| 714 | { | ||
| 715 | } | ||
| 716 | |||
| 717 | pin_trait!(Channel1Pin, CaptureCompare16bitInstance); | ||
| 718 | pin_trait!(Channel2Pin, CaptureCompare16bitInstance); | ||
| 719 | pin_trait!(Channel3Pin, CaptureCompare16bitInstance); | ||
| 720 | pin_trait!(Channel4Pin, CaptureCompare16bitInstance); | ||
| 721 | pin_trait!(ExternalTriggerPin, CaptureCompare16bitInstance); | ||
| 722 | |||
| 723 | cfg_if::cfg_if! { | ||
| 724 | if #[cfg(not(stm32l0))] { | ||
| 725 | pin_trait!(Channel1ComplementaryPin, ComplementaryCaptureCompare16bitInstance); | ||
| 726 | pin_trait!(Channel2ComplementaryPin, ComplementaryCaptureCompare16bitInstance); | ||
| 727 | pin_trait!(Channel3ComplementaryPin, ComplementaryCaptureCompare16bitInstance); | ||
| 728 | pin_trait!(Channel4ComplementaryPin, ComplementaryCaptureCompare16bitInstance); | ||
| 729 | |||
| 730 | pin_trait!(BreakInputPin, ComplementaryCaptureCompare16bitInstance); | ||
| 731 | pin_trait!(BreakInput2Pin, ComplementaryCaptureCompare16bitInstance); | ||
| 732 | 85 | ||
| 733 | pin_trait!(BreakInputComparator1Pin, ComplementaryCaptureCompare16bitInstance); | 86 | /// Advanced 16-bit timer with 1 channel instance. |
| 734 | pin_trait!(BreakInputComparator2Pin, ComplementaryCaptureCompare16bitInstance); | 87 | pub trait AdvancedInstance1Channel: BasicNoCr2Instance + GeneralInstance1Channel { |
| 735 | 88 | /// Capture compare interrupt for this timer. | |
| 736 | pin_trait!(BreakInput2Comparator1Pin, ComplementaryCaptureCompare16bitInstance); | 89 | type CaptureCompareInterrupt: interrupt::typelevel::Interrupt; |
| 737 | pin_trait!(BreakInput2Comparator2Pin, ComplementaryCaptureCompare16bitInstance); | ||
| 738 | } | ||
| 739 | } | 90 | } |
| 91 | /// Advanced 16-bit timer with 2 channels instance. | ||
| 740 | 92 | ||
| 741 | #[allow(unused)] | 93 | pub trait AdvancedInstance2Channel: BasicInstance + GeneralInstance2Channel + AdvancedInstance1Channel {} |
| 742 | macro_rules! impl_core_timer { | ||
| 743 | ($inst:ident, $irq:ident) => { | ||
| 744 | impl sealed::CoreInstance for crate::peripherals::$inst { | ||
| 745 | type Interrupt = crate::interrupt::typelevel::$irq; | ||
| 746 | 94 | ||
| 747 | fn regs_core() -> crate::pac::timer::TimCore { | 95 | /// Advanced 16-bit timer with 4 channels instance. |
| 748 | unsafe { crate::pac::timer::TimCore::from_ptr(crate::pac::$inst.as_ptr()) } | 96 | pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {} |
| 749 | } | ||
| 750 | } | ||
| 751 | }; | ||
| 752 | } | ||
| 753 | 97 | ||
| 754 | #[allow(unused)] | 98 | pin_trait!(Channel1Pin, GeneralInstance4Channel); |
| 755 | macro_rules! impl_basic_no_cr2_timer { | 99 | pin_trait!(Channel2Pin, GeneralInstance4Channel); |
| 756 | ($inst:ident) => { | 100 | pin_trait!(Channel3Pin, GeneralInstance4Channel); |
| 757 | impl sealed::BasicNoCr2Instance for crate::peripherals::$inst { | 101 | pin_trait!(Channel4Pin, GeneralInstance4Channel); |
| 758 | fn regs_basic_no_cr2() -> crate::pac::timer::TimBasicNoCr2 { | 102 | pin_trait!(ExternalTriggerPin, GeneralInstance4Channel); |
| 759 | unsafe { crate::pac::timer::TimBasicNoCr2::from_ptr(crate::pac::$inst.as_ptr()) } | ||
| 760 | } | ||
| 761 | } | ||
| 762 | }; | ||
| 763 | } | ||
| 764 | 103 | ||
| 765 | #[allow(unused)] | 104 | pin_trait!(Channel1ComplementaryPin, AdvancedInstance4Channel); |
| 766 | macro_rules! impl_basic_timer { | 105 | pin_trait!(Channel2ComplementaryPin, AdvancedInstance4Channel); |
| 767 | ($inst:ident) => { | 106 | pin_trait!(Channel3ComplementaryPin, AdvancedInstance4Channel); |
| 768 | impl sealed::BasicInstance for crate::peripherals::$inst { | 107 | pin_trait!(Channel4ComplementaryPin, AdvancedInstance4Channel); |
| 769 | fn regs_basic() -> crate::pac::timer::TimBasic { | ||
| 770 | unsafe { crate::pac::timer::TimBasic::from_ptr(crate::pac::$inst.as_ptr()) } | ||
| 771 | } | ||
| 772 | } | ||
| 773 | }; | ||
| 774 | } | ||
| 775 | 108 | ||
| 776 | #[allow(unused)] | 109 | pin_trait!(BreakInputPin, AdvancedInstance4Channel); |
| 777 | macro_rules! impl_1ch_timer { | 110 | pin_trait!(BreakInput2Pin, AdvancedInstance4Channel); |
| 778 | ($inst:ident) => { | ||
| 779 | impl sealed::GeneralPurpose1ChannelInstance for crate::peripherals::$inst { | ||
| 780 | fn regs_1ch() -> crate::pac::timer::Tim1ch { | ||
| 781 | unsafe { crate::pac::timer::Tim1ch::from_ptr(crate::pac::$inst.as_ptr()) } | ||
| 782 | } | ||
| 783 | } | ||
| 784 | }; | ||
| 785 | } | ||
| 786 | 111 | ||
| 787 | #[allow(unused)] | 112 | pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel); |
| 788 | macro_rules! impl_2ch_timer { | 113 | pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel); |
| 789 | ($inst:ident) => { | ||
| 790 | impl sealed::GeneralPurpose2ChannelInstance for crate::peripherals::$inst { | ||
| 791 | fn regs_2ch() -> crate::pac::timer::Tim2ch { | ||
| 792 | unsafe { crate::pac::timer::Tim2ch::from_ptr(crate::pac::$inst.as_ptr()) } | ||
| 793 | } | ||
| 794 | } | ||
| 795 | }; | ||
| 796 | } | ||
| 797 | 114 | ||
| 798 | #[allow(unused)] | 115 | pin_trait!(BreakInput2Comparator1Pin, AdvancedInstance4Channel); |
| 799 | macro_rules! impl_gp16_timer { | 116 | pin_trait!(BreakInput2Comparator2Pin, AdvancedInstance4Channel); |
| 800 | ($inst:ident) => { | ||
| 801 | impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { | ||
| 802 | fn regs_gp16() -> crate::pac::timer::TimGp16 { | ||
| 803 | unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } | ||
| 804 | } | ||
| 805 | } | ||
| 806 | }; | ||
| 807 | } | ||
| 808 | 117 | ||
| 809 | #[allow(unused)] | 118 | // Update Event trigger DMA for every timer |
| 810 | macro_rules! impl_gp32_timer { | 119 | dma_trait!(UpDma, BasicInstance); |
| 811 | ($inst:ident) => { | ||
| 812 | impl sealed::GeneralPurpose32bitInstance for crate::peripherals::$inst { | ||
| 813 | fn regs_gp32() -> crate::pac::timer::TimGp32 { | ||
| 814 | crate::pac::$inst | ||
| 815 | } | ||
| 816 | } | ||
| 817 | }; | ||
| 818 | } | ||
| 819 | 120 | ||
| 820 | #[allow(unused)] | 121 | dma_trait!(Ch1Dma, GeneralInstance4Channel); |
| 821 | macro_rules! impl_1ch_cmp_timer { | 122 | dma_trait!(Ch2Dma, GeneralInstance4Channel); |
| 822 | ($inst:ident) => { | 123 | dma_trait!(Ch3Dma, GeneralInstance4Channel); |
| 823 | impl sealed::GeneralPurpose1ChannelComplementaryInstance for crate::peripherals::$inst { | 124 | dma_trait!(Ch4Dma, GeneralInstance4Channel); |
| 824 | fn regs_1ch_cmp() -> crate::pac::timer::Tim1chCmp { | ||
| 825 | unsafe { crate::pac::timer::Tim1chCmp::from_ptr(crate::pac::$inst.as_ptr()) } | ||
| 826 | } | ||
| 827 | } | ||
| 828 | }; | ||
| 829 | } | ||
| 830 | 125 | ||
| 831 | #[allow(unused)] | 126 | #[allow(unused)] |
| 832 | macro_rules! impl_2ch_cmp_timer { | 127 | macro_rules! impl_core_timer { |
| 833 | ($inst:ident) => { | 128 | ($inst:ident, $bits:expr) => { |
| 834 | impl sealed::GeneralPurpose2ChannelComplementaryInstance for crate::peripherals::$inst { | 129 | impl CoreInstance for crate::peripherals::$inst { |
| 835 | fn regs_2ch_cmp() -> crate::pac::timer::Tim2chCmp { | 130 | type Interrupt = crate::_generated::peripheral_interrupts::$inst::UP; |
| 836 | unsafe { crate::pac::timer::Tim2chCmp::from_ptr(crate::pac::$inst.as_ptr()) } | ||
| 837 | } | ||
| 838 | } | ||
| 839 | }; | ||
| 840 | } | ||
| 841 | 131 | ||
| 842 | #[allow(unused)] | 132 | const BITS: TimerBits = $bits; |
| 843 | macro_rules! impl_adv_timer { | ||
| 844 | ($inst:ident, $irq:ident) => { | ||
| 845 | impl sealed::AdvancedControlInstance for crate::peripherals::$inst { | ||
| 846 | type CaptureCompareInterrupt = crate::interrupt::typelevel::$irq; | ||
| 847 | 133 | ||
| 848 | fn regs_advanced() -> crate::pac::timer::TimAdv { | 134 | fn regs() -> *mut () { |
| 849 | unsafe { crate::pac::timer::TimAdv::from_ptr(crate::pac::$inst.as_ptr()) } | 135 | crate::pac::$inst.as_ptr() |
| 850 | } | 136 | } |
| 851 | } | 137 | } |
| 852 | }; | 138 | }; |
| 853 | } | 139 | } |
| 854 | 140 | ||
| 855 | foreach_interrupt! { | 141 | foreach_interrupt! { |
| 856 | |||
| 857 | ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => { | 142 | ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => { |
| 858 | impl_core_timer!($inst, $irq); | 143 | impl_core_timer!($inst, TimerBits::Bits16); |
| 859 | impl_basic_no_cr2_timer!($inst); | 144 | impl BasicNoCr2Instance for crate::peripherals::$inst {} |
| 860 | impl_basic_timer!($inst); | ||
| 861 | impl BasicInstance for crate::peripherals::$inst {} | 145 | impl BasicInstance for crate::peripherals::$inst {} |
| 862 | }; | 146 | }; |
| 863 | 147 | ||
| 864 | ($inst:ident, timer, TIM_1CH, UP, $irq:ident) => { | 148 | ($inst:ident, timer, TIM_1CH, UP, $irq:ident) => { |
| 865 | impl_core_timer!($inst, $irq); | 149 | impl_core_timer!($inst, TimerBits::Bits16); |
| 866 | impl_basic_no_cr2_timer!($inst); | 150 | impl BasicNoCr2Instance for crate::peripherals::$inst {} |
| 867 | impl_basic_timer!($inst); | ||
| 868 | impl_1ch_timer!($inst); | ||
| 869 | impl_2ch_timer!($inst); | ||
| 870 | impl_gp16_timer!($inst); | ||
| 871 | impl BasicInstance for crate::peripherals::$inst {} | 151 | impl BasicInstance for crate::peripherals::$inst {} |
| 872 | impl CaptureCompare16bitInstance for crate::peripherals::$inst {} | 152 | impl GeneralInstance1Channel for crate::peripherals::$inst {} |
| 153 | impl GeneralInstance2Channel for crate::peripherals::$inst {} | ||
| 154 | impl GeneralInstance4Channel for crate::peripherals::$inst {} | ||
| 873 | }; | 155 | }; |
| 874 | 156 | ||
| 875 | |||
| 876 | ($inst:ident, timer, TIM_2CH, UP, $irq:ident) => { | 157 | ($inst:ident, timer, TIM_2CH, UP, $irq:ident) => { |
| 877 | impl_core_timer!($inst, $irq); | 158 | impl_core_timer!($inst, TimerBits::Bits16); |
| 878 | impl_basic_no_cr2_timer!($inst); | 159 | impl BasicNoCr2Instance for crate::peripherals::$inst {} |
| 879 | impl_basic_timer!($inst); | ||
| 880 | impl_1ch_timer!($inst); | ||
| 881 | impl_2ch_timer!($inst); | ||
| 882 | impl_gp16_timer!($inst); | ||
| 883 | impl BasicInstance for crate::peripherals::$inst {} | 160 | impl BasicInstance for crate::peripherals::$inst {} |
| 884 | impl CaptureCompare16bitInstance for crate::peripherals::$inst {} | 161 | impl GeneralInstance1Channel for crate::peripherals::$inst {} |
| 162 | impl GeneralInstance2Channel for crate::peripherals::$inst {} | ||
| 163 | impl GeneralInstance4Channel for crate::peripherals::$inst {} | ||
| 885 | }; | 164 | }; |
| 886 | 165 | ||
| 887 | ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => { | 166 | ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => { |
| 888 | impl_core_timer!($inst, $irq); | 167 | impl_core_timer!($inst, TimerBits::Bits16); |
| 889 | impl_basic_no_cr2_timer!($inst); | 168 | impl BasicNoCr2Instance for crate::peripherals::$inst {} |
| 890 | impl_basic_timer!($inst); | ||
| 891 | impl_1ch_timer!($inst); | ||
| 892 | impl_2ch_timer!($inst); | ||
| 893 | impl_gp16_timer!($inst); | ||
| 894 | impl BasicInstance for crate::peripherals::$inst {} | 169 | impl BasicInstance for crate::peripherals::$inst {} |
| 895 | impl CaptureCompare16bitInstance for crate::peripherals::$inst {} | 170 | impl GeneralInstance1Channel for crate::peripherals::$inst {} |
| 171 | impl GeneralInstance2Channel for crate::peripherals::$inst {} | ||
| 172 | impl GeneralInstance4Channel for crate::peripherals::$inst {} | ||
| 896 | }; | 173 | }; |
| 897 | 174 | ||
| 898 | ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => { | 175 | ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => { |
| 899 | impl_core_timer!($inst, $irq); | 176 | impl_core_timer!($inst, TimerBits::Bits32); |
| 900 | impl_basic_no_cr2_timer!($inst); | 177 | impl BasicNoCr2Instance for crate::peripherals::$inst {} |
| 901 | impl_basic_timer!($inst); | ||
| 902 | impl_1ch_timer!($inst); | ||
| 903 | impl_2ch_timer!($inst); | ||
| 904 | impl_gp16_timer!($inst); | ||
| 905 | impl_gp32_timer!($inst); | ||
| 906 | impl BasicInstance for crate::peripherals::$inst {} | 178 | impl BasicInstance for crate::peripherals::$inst {} |
| 907 | impl CaptureCompare16bitInstance for crate::peripherals::$inst {} | 179 | impl GeneralInstance1Channel for crate::peripherals::$inst {} |
| 908 | impl CaptureCompare32bitInstance for crate::peripherals::$inst {} | 180 | impl GeneralInstance2Channel for crate::peripherals::$inst {} |
| 181 | impl GeneralInstance4Channel for crate::peripherals::$inst {} | ||
| 182 | impl GeneralInstance32bit4Channel for crate::peripherals::$inst {} | ||
| 909 | }; | 183 | }; |
| 910 | 184 | ||
| 911 | ($inst:ident, timer, TIM_1CH_CMP, UP, $irq:ident) => { | 185 | ($inst:ident, timer, TIM_1CH_CMP, UP, $irq:ident) => { |
| 912 | impl_core_timer!($inst, $irq); | 186 | impl_core_timer!($inst, TimerBits::Bits16); |
| 913 | impl_basic_no_cr2_timer!($inst); | 187 | impl BasicNoCr2Instance for crate::peripherals::$inst {} |
| 914 | impl_basic_timer!($inst); | ||
| 915 | impl_1ch_timer!($inst); | ||
| 916 | impl_2ch_timer!($inst); | ||
| 917 | impl_gp16_timer!($inst); | ||
| 918 | impl_1ch_cmp_timer!($inst); | ||
| 919 | impl_2ch_cmp_timer!($inst); | ||
| 920 | impl BasicInstance for crate::peripherals::$inst {} | 188 | impl BasicInstance for crate::peripherals::$inst {} |
| 921 | impl CaptureCompare16bitInstance for crate::peripherals::$inst { | 189 | impl GeneralInstance1Channel for crate::peripherals::$inst {} |
| 922 | /// Enable timer outputs. | 190 | impl GeneralInstance2Channel for crate::peripherals::$inst {} |
| 923 | fn enable_outputs(&self) { | 191 | impl GeneralInstance4Channel for crate::peripherals::$inst { fn enable_outputs(&self) { set_moe::<Self>() }} |
| 924 | use crate::timer::sealed::GeneralPurpose1ChannelComplementaryInstance; | 192 | impl AdvancedInstance1Channel for crate::peripherals::$inst { type CaptureCompareInterrupt = crate::_generated::peripheral_interrupts::$inst::CC; } |
| 925 | self.set_moe(true); | 193 | impl AdvancedInstance2Channel for crate::peripherals::$inst {} |
| 926 | } | 194 | impl AdvancedInstance4Channel for crate::peripherals::$inst {} |
| 927 | } | ||
| 928 | impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} | ||
| 929 | }; | ||
| 930 | ($inst:ident, timer, TIM_1CH_CMP, CC, $irq:ident) => { | ||
| 931 | impl_adv_timer!($inst, $irq); | ||
| 932 | }; | 195 | }; |
| 933 | 196 | ||
| 934 | |||
| 935 | ($inst:ident, timer, TIM_2CH_CMP, UP, $irq:ident) => { | 197 | ($inst:ident, timer, TIM_2CH_CMP, UP, $irq:ident) => { |
| 936 | impl_core_timer!($inst, $irq); | 198 | impl_core_timer!($inst, TimerBits::Bits16); |
| 937 | impl_basic_no_cr2_timer!($inst); | 199 | impl BasicNoCr2Instance for crate::peripherals::$inst {} |
| 938 | impl_basic_timer!($inst); | ||
| 939 | impl_1ch_timer!($inst); | ||
| 940 | impl_2ch_timer!($inst); | ||
| 941 | impl_gp16_timer!($inst); | ||
| 942 | impl_1ch_cmp_timer!($inst); | ||
| 943 | impl_2ch_cmp_timer!($inst); | ||
| 944 | impl BasicInstance for crate::peripherals::$inst {} | 200 | impl BasicInstance for crate::peripherals::$inst {} |
| 945 | impl CaptureCompare16bitInstance for crate::peripherals::$inst { | 201 | impl GeneralInstance1Channel for crate::peripherals::$inst {} |
| 946 | /// Enable timer outputs. | 202 | impl GeneralInstance2Channel for crate::peripherals::$inst {} |
| 947 | fn enable_outputs(&self) { | 203 | impl GeneralInstance4Channel for crate::peripherals::$inst { fn enable_outputs(&self) { set_moe::<Self>() }} |
| 948 | use crate::timer::sealed::GeneralPurpose1ChannelComplementaryInstance; | 204 | impl AdvancedInstance1Channel for crate::peripherals::$inst { type CaptureCompareInterrupt = crate::_generated::peripheral_interrupts::$inst::CC; } |
| 949 | self.set_moe(true); | 205 | impl AdvancedInstance2Channel for crate::peripherals::$inst {} |
| 950 | } | 206 | impl AdvancedInstance4Channel for crate::peripherals::$inst {} |
| 951 | } | ||
| 952 | impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} | ||
| 953 | }; | ||
| 954 | ($inst:ident, timer, TIM_2CH_CMP, CC, $irq:ident) => { | ||
| 955 | impl_adv_timer!($inst, $irq); | ||
| 956 | }; | 207 | }; |
| 957 | 208 | ||
| 958 | |||
| 959 | ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { | 209 | ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { |
| 960 | impl_core_timer!($inst, $irq); | 210 | impl_core_timer!($inst, TimerBits::Bits16); |
| 961 | impl_basic_no_cr2_timer!($inst); | 211 | impl BasicNoCr2Instance for crate::peripherals::$inst {} |
| 962 | impl_basic_timer!($inst); | ||
| 963 | impl_1ch_timer!($inst); | ||
| 964 | impl_2ch_timer!($inst); | ||
| 965 | impl_gp16_timer!($inst); | ||
| 966 | impl_1ch_cmp_timer!($inst); | ||
| 967 | impl_2ch_cmp_timer!($inst); | ||
| 968 | impl BasicInstance for crate::peripherals::$inst {} | 212 | impl BasicInstance for crate::peripherals::$inst {} |
| 969 | impl CaptureCompare16bitInstance for crate::peripherals::$inst { | 213 | impl GeneralInstance1Channel for crate::peripherals::$inst {} |
| 970 | /// Enable timer outputs. | 214 | impl GeneralInstance2Channel for crate::peripherals::$inst {} |
| 971 | fn enable_outputs(&self) { | 215 | impl GeneralInstance4Channel for crate::peripherals::$inst { fn enable_outputs(&self) { set_moe::<Self>() }} |
| 972 | use crate::timer::sealed::GeneralPurpose1ChannelComplementaryInstance; | 216 | impl AdvancedInstance1Channel for crate::peripherals::$inst { type CaptureCompareInterrupt = crate::_generated::peripheral_interrupts::$inst::CC; } |
| 973 | self.set_moe(true); | 217 | impl AdvancedInstance2Channel for crate::peripherals::$inst {} |
| 974 | } | 218 | impl AdvancedInstance4Channel for crate::peripherals::$inst {} |
| 975 | } | ||
| 976 | impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} | ||
| 977 | }; | ||
| 978 | ($inst:ident, timer, TIM_ADV, CC, $irq:ident) => { | ||
| 979 | impl_adv_timer!($inst, $irq); | ||
| 980 | }; | 219 | }; |
| 981 | } | 220 | } |
| 982 | 221 | ||
| 983 | // Update Event trigger DMA for every timer | 222 | #[cfg(not(stm32l0))] |
| 984 | dma_trait!(UpDma, BasicInstance); | 223 | #[allow(unused)] |
| 985 | 224 | fn set_moe<T: GeneralInstance4Channel>() { | |
| 986 | dma_trait!(Ch1Dma, CaptureCompare16bitInstance); | 225 | unsafe { crate::pac::timer::Tim1chCmp::from_ptr(T::regs()) } |
| 987 | dma_trait!(Ch2Dma, CaptureCompare16bitInstance); | 226 | .bdtr() |
| 988 | dma_trait!(Ch3Dma, CaptureCompare16bitInstance); | 227 | .modify(|w| w.set_moe(true)); |
| 989 | dma_trait!(Ch4Dma, CaptureCompare16bitInstance); | 228 | } |
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 @@ | |||
| 3 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 4 | 4 | ||
| 5 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 5 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 6 | use stm32_metapac::timer::vals; | ||
| 6 | 7 | ||
| 7 | use super::*; | 8 | use super::low_level::Timer; |
| 8 | use crate::gpio::sealed::AFType; | 9 | use super::{Channel1Pin, Channel2Pin, GeneralInstance4Channel}; |
| 9 | use crate::gpio::AnyPin; | 10 | use crate::gpio::{AFType, AnyPin}; |
| 10 | use crate::Peripheral; | 11 | use crate::Peripheral; |
| 11 | 12 | ||
| 12 | /// Counting direction | 13 | /// Counting direction |
| @@ -30,7 +31,7 @@ pub struct QeiPin<'d, T, Channel> { | |||
| 30 | 31 | ||
| 31 | macro_rules! channel_impl { | 32 | macro_rules! channel_impl { |
| 32 | ($new_chx:ident, $channel:ident, $pin_trait:ident) => { | 33 | ($new_chx:ident, $channel:ident, $pin_trait:ident) => { |
| 33 | impl<'d, T: CaptureCompare16bitInstance> QeiPin<'d, T, $channel> { | 34 | impl<'d, T: GeneralInstance4Channel> QeiPin<'d, T, $channel> { |
| 34 | #[doc = concat!("Create a new ", stringify!($channel), " QEI pin instance.")] | 35 | #[doc = concat!("Create a new ", stringify!($channel), " QEI pin instance.")] |
| 35 | pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd) -> Self { | 36 | pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd) -> Self { |
| 36 | into_ref!(pin); | 37 | into_ref!(pin); |
| @@ -53,29 +54,28 @@ channel_impl!(new_ch1, Ch1, Channel1Pin); | |||
| 53 | channel_impl!(new_ch2, Ch2, Channel2Pin); | 54 | channel_impl!(new_ch2, Ch2, Channel2Pin); |
| 54 | 55 | ||
| 55 | /// Quadrature decoder driver. | 56 | /// Quadrature decoder driver. |
| 56 | pub struct Qei<'d, T> { | 57 | pub struct Qei<'d, T: GeneralInstance4Channel> { |
| 57 | _inner: PeripheralRef<'d, T>, | 58 | inner: Timer<'d, T>, |
| 58 | } | 59 | } |
| 59 | 60 | ||
| 60 | impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> { | 61 | impl<'d, T: GeneralInstance4Channel> Qei<'d, T> { |
| 61 | /// Create a new quadrature decoder driver. | 62 | /// Create a new quadrature decoder driver. |
| 62 | pub fn new(tim: impl Peripheral<P = T> + 'd, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self { | 63 | pub fn new(tim: impl Peripheral<P = T> + 'd, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self { |
| 63 | Self::new_inner(tim) | 64 | Self::new_inner(tim) |
| 64 | } | 65 | } |
| 65 | 66 | ||
| 66 | fn new_inner(tim: impl Peripheral<P = T> + 'd) -> Self { | 67 | fn new_inner(tim: impl Peripheral<P = T> + 'd) -> Self { |
| 67 | into_ref!(tim); | 68 | let inner = Timer::new(tim); |
| 68 | 69 | let r = inner.regs_gp16(); | |
| 69 | T::enable_and_reset(); | ||
| 70 | 70 | ||
| 71 | // Configure TxC1 and TxC2 as captures | 71 | // Configure TxC1 and TxC2 as captures |
| 72 | T::regs_gp16().ccmr_input(0).modify(|w| { | 72 | r.ccmr_input(0).modify(|w| { |
| 73 | w.set_ccs(0, vals::CcmrInputCcs::TI4); | 73 | w.set_ccs(0, vals::CcmrInputCcs::TI4); |
| 74 | w.set_ccs(1, vals::CcmrInputCcs::TI4); | 74 | w.set_ccs(1, vals::CcmrInputCcs::TI4); |
| 75 | }); | 75 | }); |
| 76 | 76 | ||
| 77 | // enable and configure to capture on rising edge | 77 | // enable and configure to capture on rising edge |
| 78 | T::regs_gp16().ccer().modify(|w| { | 78 | r.ccer().modify(|w| { |
| 79 | w.set_cce(0, true); | 79 | w.set_cce(0, true); |
| 80 | w.set_cce(1, true); | 80 | w.set_cce(1, true); |
| 81 | 81 | ||
| @@ -83,19 +83,19 @@ impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> { | |||
| 83 | w.set_ccp(1, false); | 83 | w.set_ccp(1, false); |
| 84 | }); | 84 | }); |
| 85 | 85 | ||
| 86 | T::regs_gp16().smcr().modify(|w| { | 86 | r.smcr().modify(|w| { |
| 87 | w.set_sms(vals::Sms::ENCODER_MODE_3); | 87 | w.set_sms(vals::Sms::ENCODER_MODE_3); |
| 88 | }); | 88 | }); |
| 89 | 89 | ||
| 90 | T::regs_gp16().arr().modify(|w| w.set_arr(u16::MAX)); | 90 | r.arr().modify(|w| w.set_arr(u16::MAX)); |
| 91 | T::regs_gp16().cr1().modify(|w| w.set_cen(true)); | 91 | r.cr1().modify(|w| w.set_cen(true)); |
| 92 | 92 | ||
| 93 | Self { _inner: tim } | 93 | Self { inner } |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | /// Get direction. | 96 | /// Get direction. |
| 97 | pub fn read_direction(&self) -> Direction { | 97 | pub fn read_direction(&self) -> Direction { |
| 98 | match T::regs_gp16().cr1().read().dir() { | 98 | match self.inner.regs_gp16().cr1().read().dir() { |
| 99 | vals::Dir::DOWN => Direction::Downcounting, | 99 | vals::Dir::DOWN => Direction::Downcounting, |
| 100 | vals::Dir::UP => Direction::Upcounting, | 100 | vals::Dir::UP => Direction::Upcounting, |
| 101 | } | 101 | } |
| @@ -103,6 +103,6 @@ impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> { | |||
| 103 | 103 | ||
| 104 | /// Get count. | 104 | /// Get count. |
| 105 | pub fn count(&self) -> u16 { | 105 | pub fn count(&self) -> u16 { |
| 106 | T::regs_gp16().cnt().read().cnt() | 106 | self.inner.regs_gp16().cnt().read().cnt() |
| 107 | } | 107 | } |
| 108 | } | 108 | } |
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; | |||
| 4 | 4 | ||
| 5 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 5 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 6 | 6 | ||
| 7 | use super::*; | 7 | use super::low_level::{CountingMode, OutputCompareMode, OutputPolarity, Timer}; |
| 8 | #[allow(unused_imports)] | 8 | use super::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance4Channel}; |
| 9 | use crate::gpio::sealed::{AFType, Pin}; | ||
| 10 | use crate::gpio::{AnyPin, OutputType}; | 9 | use crate::gpio::{AnyPin, OutputType}; |
| 10 | use crate::time::Hertz; | ||
| 11 | use crate::Peripheral; | 11 | use crate::Peripheral; |
| 12 | 12 | ||
| 13 | /// Channel 1 marker type. | 13 | /// Channel 1 marker type. |
| @@ -29,7 +29,7 @@ pub struct PwmPin<'d, T, C> { | |||
| 29 | 29 | ||
| 30 | macro_rules! channel_impl { | 30 | macro_rules! channel_impl { |
| 31 | ($new_chx:ident, $channel:ident, $pin_trait:ident) => { | 31 | ($new_chx:ident, $channel:ident, $pin_trait:ident) => { |
| 32 | impl<'d, T: CaptureCompare16bitInstance> PwmPin<'d, T, $channel> { | 32 | impl<'d, T: GeneralInstance4Channel> PwmPin<'d, T, $channel> { |
| 33 | #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")] | 33 | #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")] |
| 34 | pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self { | 34 | pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self { |
| 35 | into_ref!(pin); | 35 | into_ref!(pin); |
| @@ -54,11 +54,11 @@ channel_impl!(new_ch3, Ch3, Channel3Pin); | |||
| 54 | channel_impl!(new_ch4, Ch4, Channel4Pin); | 54 | channel_impl!(new_ch4, Ch4, Channel4Pin); |
| 55 | 55 | ||
| 56 | /// Simple PWM driver. | 56 | /// Simple PWM driver. |
| 57 | pub struct SimplePwm<'d, T> { | 57 | pub struct SimplePwm<'d, T: GeneralInstance4Channel> { |
| 58 | inner: PeripheralRef<'d, T>, | 58 | inner: Timer<'d, T>, |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { | 61 | impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { |
| 62 | /// Create a new simple PWM driver. | 62 | /// Create a new simple PWM driver. |
| 63 | pub fn new( | 63 | pub fn new( |
| 64 | tim: impl Peripheral<P = T> + 'd, | 64 | tim: impl Peripheral<P = T> + 'd, |
| @@ -73,15 +73,11 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { | |||
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, counting_mode: CountingMode) -> Self { | 75 | fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, counting_mode: CountingMode) -> Self { |
| 76 | into_ref!(tim); | 76 | let mut this = Self { inner: Timer::new(tim) }; |
| 77 | |||
| 78 | T::enable_and_reset(); | ||
| 79 | |||
| 80 | let mut this = Self { inner: tim }; | ||
| 81 | 77 | ||
| 82 | this.inner.set_counting_mode(counting_mode); | 78 | this.inner.set_counting_mode(counting_mode); |
| 83 | this.set_frequency(freq); | 79 | this.set_frequency(freq); |
| 84 | this.inner.enable_outputs(); // Required for advanced timers, see CaptureCompare16bitInstance for details | 80 | this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details |
| 85 | this.inner.start(); | 81 | this.inner.start(); |
| 86 | 82 | ||
| 87 | [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4] | 83 | [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4] |
| @@ -126,14 +122,14 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { | |||
| 126 | /// Get max duty value. | 122 | /// Get max duty value. |
| 127 | /// | 123 | /// |
| 128 | /// This value depends on the configured frequency and the timer's clock rate from RCC. | 124 | /// This value depends on the configured frequency and the timer's clock rate from RCC. |
| 129 | pub fn get_max_duty(&self) -> u16 { | 125 | pub fn get_max_duty(&self) -> u32 { |
| 130 | self.inner.get_max_compare_value() + 1 | 126 | self.inner.get_max_compare_value() + 1 |
| 131 | } | 127 | } |
| 132 | 128 | ||
| 133 | /// Set the duty for a given channel. | 129 | /// Set the duty for a given channel. |
| 134 | /// | 130 | /// |
| 135 | /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. | 131 | /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. |
| 136 | pub fn set_duty(&mut self, channel: Channel, duty: u16) { | 132 | pub fn set_duty(&mut self, channel: Channel, duty: u32) { |
| 137 | assert!(duty <= self.get_max_duty()); | 133 | assert!(duty <= self.get_max_duty()); |
| 138 | self.inner.set_compare_value(channel, duty) | 134 | self.inner.set_compare_value(channel, duty) |
| 139 | } | 135 | } |
| @@ -141,7 +137,7 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { | |||
| 141 | /// Get the duty for a given channel. | 137 | /// Get the duty for a given channel. |
| 142 | /// | 138 | /// |
| 143 | /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. | 139 | /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. |
| 144 | pub fn get_duty(&self, channel: Channel) -> u16 { | 140 | pub fn get_duty(&self, channel: Channel) -> u32 { |
| 145 | self.inner.get_compare_value(channel) | 141 | self.inner.get_compare_value(channel) |
| 146 | } | 142 | } |
| 147 | 143 | ||
| @@ -165,8 +161,6 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { | |||
| 165 | channel: Channel, | 161 | channel: Channel, |
| 166 | duty: &[u16], | 162 | duty: &[u16], |
| 167 | ) { | 163 | ) { |
| 168 | assert!(duty.iter().all(|v| *v <= self.get_max_duty())); | ||
| 169 | |||
| 170 | into_ref!(dma); | 164 | into_ref!(dma); |
| 171 | 165 | ||
| 172 | #[allow(clippy::let_unit_value)] // eg. stm32f334 | 166 | #[allow(clippy::let_unit_value)] // eg. stm32f334 |
| @@ -201,7 +195,7 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { | |||
| 201 | &mut dma, | 195 | &mut dma, |
| 202 | req, | 196 | req, |
| 203 | duty, | 197 | duty, |
| 204 | T::regs_1ch().ccr(channel.index()).as_ptr() as *mut _, | 198 | self.inner.regs_1ch().ccr(channel.index()).as_ptr() as *mut _, |
| 205 | dma_transfer_option, | 199 | dma_transfer_option, |
| 206 | ) | 200 | ) |
| 207 | .await | 201 | .await |
| @@ -227,22 +221,20 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { | |||
| 227 | 221 | ||
| 228 | macro_rules! impl_waveform_chx { | 222 | macro_rules! impl_waveform_chx { |
| 229 | ($fn_name:ident, $dma_ch:ident, $cc_ch:ident) => { | 223 | ($fn_name:ident, $dma_ch:ident, $cc_ch:ident) => { |
| 230 | impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { | 224 | impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { |
| 231 | /// Generate a sequence of PWM waveform | 225 | /// Generate a sequence of PWM waveform |
| 232 | /// | 226 | /// |
| 233 | /// Note: | 227 | /// Note: |
| 234 | /// you will need to provide corresponding TIMx_CHy DMA channel to use this method. | 228 | /// you will need to provide corresponding TIMx_CHy DMA channel to use this method. |
| 235 | pub async fn $fn_name(&mut self, dma: impl Peripheral<P = impl super::$dma_ch<T>>, duty: &[u16]) { | 229 | pub async fn $fn_name(&mut self, dma: impl Peripheral<P = impl super::$dma_ch<T>>, duty: &[u16]) { |
| 236 | use super::vals::Ccds; | 230 | use crate::pac::timer::vals::Ccds; |
| 237 | |||
| 238 | assert!(duty.iter().all(|v| *v <= self.get_max_duty())); | ||
| 239 | 231 | ||
| 240 | into_ref!(dma); | 232 | into_ref!(dma); |
| 241 | 233 | ||
| 242 | #[allow(clippy::let_unit_value)] // eg. stm32f334 | 234 | #[allow(clippy::let_unit_value)] // eg. stm32f334 |
| 243 | let req = dma.request(); | 235 | let req = dma.request(); |
| 244 | 236 | ||
| 245 | let cc_channel = super::Channel::$cc_ch; | 237 | let cc_channel = Channel::$cc_ch; |
| 246 | 238 | ||
| 247 | let original_duty_state = self.get_duty(cc_channel); | 239 | let original_duty_state = self.get_duty(cc_channel); |
| 248 | let original_enable_state = self.is_enabled(cc_channel); | 240 | let original_enable_state = self.is_enabled(cc_channel); |
| @@ -279,7 +271,7 @@ macro_rules! impl_waveform_chx { | |||
| 279 | &mut dma, | 271 | &mut dma, |
| 280 | req, | 272 | req, |
| 281 | duty, | 273 | duty, |
| 282 | T::regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut _, | 274 | self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut _, |
| 283 | dma_transfer_option, | 275 | dma_transfer_option, |
| 284 | ) | 276 | ) |
| 285 | .await | 277 | .await |
| @@ -314,10 +306,10 @@ impl_waveform_chx!(waveform_ch2, Ch2Dma, Ch2); | |||
| 314 | impl_waveform_chx!(waveform_ch3, Ch3Dma, Ch3); | 306 | impl_waveform_chx!(waveform_ch3, Ch3Dma, Ch3); |
| 315 | impl_waveform_chx!(waveform_ch4, Ch4Dma, Ch4); | 307 | impl_waveform_chx!(waveform_ch4, Ch4Dma, Ch4); |
| 316 | 308 | ||
| 317 | impl<'d, T: CaptureCompare16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d, T> { | 309 | impl<'d, T: GeneralInstance4Channel> embedded_hal_02::Pwm for SimplePwm<'d, T> { |
| 318 | type Channel = Channel; | 310 | type Channel = Channel; |
| 319 | type Time = Hertz; | 311 | type Time = Hertz; |
| 320 | type Duty = u16; | 312 | type Duty = u32; |
| 321 | 313 | ||
| 322 | fn disable(&mut self, channel: Self::Channel) { | 314 | fn disable(&mut self, channel: Self::Channel) { |
| 323 | self.inner.enable_channel(channel, false); | 315 | 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 @@ | |||
| 16 | 16 | ||
| 17 | use core::future::poll_fn; | 17 | use core::future::poll_fn; |
| 18 | use core::marker::PhantomData; | 18 | use core::marker::PhantomData; |
| 19 | use core::sync::atomic::Ordering; | 19 | use core::sync::atomic::{AtomicBool, Ordering}; |
| 20 | use core::task::Poll; | 20 | use core::task::Poll; |
| 21 | 21 | ||
| 22 | use embassy_hal_internal::drop::OnDrop; | 22 | use embassy_hal_internal::drop::OnDrop; |
| 23 | use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; | 23 | use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; |
| 24 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 24 | 25 | ||
| 25 | use crate::dma::{AnyChannel, Request, Transfer, TransferOptions}; | 26 | use crate::dma::{AnyChannel, Request, Transfer, TransferOptions}; |
| 26 | use crate::interrupt; | 27 | use crate::interrupt; |
| @@ -555,50 +556,47 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 555 | } | 556 | } |
| 556 | } | 557 | } |
| 557 | 558 | ||
| 558 | /// UCPD instance trait. | 559 | struct State { |
| 559 | pub trait Instance: sealed::Instance + RccPeripheral {} | 560 | waker: AtomicWaker, |
| 560 | 561 | // Inverted logic for a default state of 0 so that the data goes into the .bss section. | |
| 561 | mod sealed { | 562 | drop_not_ready: AtomicBool, |
| 562 | use core::sync::atomic::AtomicBool; | 563 | } |
| 563 | |||
| 564 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 565 | |||
| 566 | pub struct State { | ||
| 567 | pub waker: AtomicWaker, | ||
| 568 | // Inverted logic for a default state of 0 so that the data goes into the .bss section. | ||
| 569 | pub drop_not_ready: AtomicBool, | ||
| 570 | } | ||
| 571 | 564 | ||
| 572 | impl State { | 565 | impl State { |
| 573 | pub const fn new() -> Self { | 566 | pub const fn new() -> Self { |
| 574 | Self { | 567 | Self { |
| 575 | waker: AtomicWaker::new(), | 568 | waker: AtomicWaker::new(), |
| 576 | drop_not_ready: AtomicBool::new(false), | 569 | drop_not_ready: AtomicBool::new(false), |
| 577 | } | ||
| 578 | } | 570 | } |
| 579 | } | 571 | } |
| 572 | } | ||
| 580 | 573 | ||
| 581 | pub trait Instance { | 574 | trait SealedInstance { |
| 582 | type Interrupt: crate::interrupt::typelevel::Interrupt; | 575 | const REGS: crate::pac::ucpd::Ucpd; |
| 583 | const REGS: crate::pac::ucpd::Ucpd; | 576 | fn state() -> &'static State; |
| 584 | fn state() -> &'static crate::ucpd::sealed::State; | 577 | } |
| 585 | } | 578 | |
| 579 | /// UCPD instance trait. | ||
| 580 | #[allow(private_bounds)] | ||
| 581 | pub trait Instance: SealedInstance + RccPeripheral { | ||
| 582 | /// Interrupt for this instance. | ||
| 583 | type Interrupt: crate::interrupt::typelevel::Interrupt; | ||
| 586 | } | 584 | } |
| 587 | 585 | ||
| 588 | foreach_interrupt!( | 586 | foreach_interrupt!( |
| 589 | ($inst:ident, ucpd, UCPD, GLOBAL, $irq:ident) => { | 587 | ($inst:ident, ucpd, UCPD, GLOBAL, $irq:ident) => { |
| 590 | impl sealed::Instance for crate::peripherals::$inst { | 588 | impl SealedInstance for crate::peripherals::$inst { |
| 591 | type Interrupt = crate::interrupt::typelevel::$irq; | ||
| 592 | |||
| 593 | const REGS: crate::pac::ucpd::Ucpd = crate::pac::$inst; | 589 | const REGS: crate::pac::ucpd::Ucpd = crate::pac::$inst; |
| 594 | 590 | ||
| 595 | fn state() -> &'static crate::ucpd::sealed::State { | 591 | fn state() -> &'static State { |
| 596 | static STATE: crate::ucpd::sealed::State = crate::ucpd::sealed::State::new(); | 592 | static STATE: State = State::new(); |
| 597 | &STATE | 593 | &STATE |
| 598 | } | 594 | } |
| 599 | } | 595 | } |
| 600 | 596 | ||
| 601 | impl Instance for crate::peripherals::$inst {} | 597 | impl Instance for crate::peripherals::$inst { |
| 598 | type Interrupt = crate::interrupt::typelevel::$irq; | ||
| 599 | } | ||
| 602 | }; | 600 | }; |
| 603 | ); | 601 | ); |
| 604 | 602 | ||
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; | |||
| 10 | use embassy_embedded_hal::SetConfig; | 10 | use embassy_embedded_hal::SetConfig; |
| 11 | use embassy_hal_internal::drop::OnDrop; | 11 | use embassy_hal_internal::drop::OnDrop; |
| 12 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 12 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 13 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 13 | use futures::future::{select, Either}; | 14 | use futures::future::{select, Either}; |
| 14 | 15 | ||
| 15 | use crate::dma::{NoDma, Transfer}; | 16 | use crate::dma::{NoDma, Transfer}; |
| 16 | use crate::gpio::sealed::AFType; | 17 | use crate::gpio::AFType; |
| 17 | use crate::interrupt::typelevel::Interrupt; | 18 | use crate::interrupt::typelevel::Interrupt; |
| 18 | #[allow(unused_imports)] | 19 | #[allow(unused_imports)] |
| 19 | #[cfg(not(any(usart_v1, usart_v2)))] | 20 | #[cfg(not(any(usart_v1, usart_v2)))] |
| @@ -1326,8 +1327,6 @@ mod ringbuffered; | |||
| 1326 | #[cfg(not(gpdma))] | 1327 | #[cfg(not(gpdma))] |
| 1327 | pub use ringbuffered::RingBufferedUartRx; | 1328 | pub use ringbuffered::RingBufferedUartRx; |
| 1328 | 1329 | ||
| 1329 | use self::sealed::Kind; | ||
| 1330 | |||
| 1331 | #[cfg(any(usart_v1, usart_v2))] | 1330 | #[cfg(any(usart_v1, usart_v2))] |
| 1332 | fn tdr(r: crate::pac::usart::Usart) -> *mut u8 { | 1331 | fn tdr(r: crate::pac::usart::Usart) -> *mut u8 { |
| 1333 | r.dr().as_ptr() as _ | 1332 | r.dr().as_ptr() as _ |
| @@ -1370,52 +1369,50 @@ fn clear_interrupt_flags(r: Regs, sr: regs::Isr) { | |||
| 1370 | r.icr().write(|w| *w = regs::Icr(sr.0)); | 1369 | r.icr().write(|w| *w = regs::Icr(sr.0)); |
| 1371 | } | 1370 | } |
| 1372 | 1371 | ||
| 1373 | pub(crate) mod sealed { | 1372 | #[derive(Clone, Copy, PartialEq, Eq)] |
| 1374 | use embassy_sync::waitqueue::AtomicWaker; | 1373 | enum Kind { |
| 1375 | 1374 | Uart, | |
| 1376 | use super::*; | 1375 | #[cfg(any(usart_v3, usart_v4))] |
| 1377 | 1376 | #[allow(unused)] | |
| 1378 | #[derive(Clone, Copy, PartialEq, Eq)] | 1377 | Lpuart, |
| 1379 | pub enum Kind { | 1378 | } |
| 1380 | Uart, | ||
| 1381 | #[cfg(any(usart_v3, usart_v4))] | ||
| 1382 | Lpuart, | ||
| 1383 | } | ||
| 1384 | 1379 | ||
| 1385 | pub struct State { | 1380 | struct State { |
| 1386 | pub rx_waker: AtomicWaker, | 1381 | rx_waker: AtomicWaker, |
| 1387 | pub tx_waker: AtomicWaker, | 1382 | } |
| 1388 | } | ||
| 1389 | 1383 | ||
| 1390 | impl State { | 1384 | impl State { |
| 1391 | pub const fn new() -> Self { | 1385 | const fn new() -> Self { |
| 1392 | Self { | 1386 | Self { |
| 1393 | rx_waker: AtomicWaker::new(), | 1387 | rx_waker: AtomicWaker::new(), |
| 1394 | tx_waker: AtomicWaker::new(), | ||
| 1395 | } | ||
| 1396 | } | 1388 | } |
| 1397 | } | 1389 | } |
| 1390 | } | ||
| 1398 | 1391 | ||
| 1399 | pub trait BasicInstance: crate::rcc::RccPeripheral { | 1392 | trait SealedBasicInstance: crate::rcc::RccPeripheral { |
| 1400 | const KIND: Kind; | 1393 | const KIND: Kind; |
| 1401 | type Interrupt: interrupt::typelevel::Interrupt; | ||
| 1402 | 1394 | ||
| 1403 | fn regs() -> Regs; | 1395 | fn regs() -> Regs; |
| 1404 | fn state() -> &'static State; | 1396 | fn state() -> &'static State; |
| 1405 | 1397 | ||
| 1406 | fn buffered_state() -> &'static buffered::State; | 1398 | fn buffered_state() -> &'static buffered::State; |
| 1407 | } | 1399 | } |
| 1408 | 1400 | ||
| 1409 | pub trait FullInstance: BasicInstance { | 1401 | trait SealedFullInstance: SealedBasicInstance { |
| 1410 | fn regs_uart() -> crate::pac::usart::Usart; | 1402 | #[allow(unused)] |
| 1411 | } | 1403 | fn regs_uart() -> crate::pac::usart::Usart; |
| 1412 | } | 1404 | } |
| 1413 | 1405 | ||
| 1414 | /// Basic UART driver instance | 1406 | /// Basic UART driver instance |
| 1415 | pub trait BasicInstance: Peripheral<P = Self> + sealed::BasicInstance + 'static + Send {} | 1407 | #[allow(private_bounds)] |
| 1408 | pub trait BasicInstance: Peripheral<P = Self> + SealedBasicInstance + 'static + Send { | ||
| 1409 | /// Interrupt for this instance. | ||
| 1410 | type Interrupt: interrupt::typelevel::Interrupt; | ||
| 1411 | } | ||
| 1416 | 1412 | ||
| 1417 | /// Full UART driver instance | 1413 | /// Full UART driver instance |
| 1418 | pub trait FullInstance: sealed::FullInstance {} | 1414 | #[allow(private_bounds)] |
| 1415 | pub trait FullInstance: SealedFullInstance {} | ||
| 1419 | 1416 | ||
| 1420 | pin_trait!(RxPin, BasicInstance); | 1417 | pin_trait!(RxPin, BasicInstance); |
| 1421 | pin_trait!(TxPin, BasicInstance); | 1418 | pin_trait!(TxPin, BasicInstance); |
| @@ -1429,16 +1426,15 @@ dma_trait!(RxDma, BasicInstance); | |||
| 1429 | 1426 | ||
| 1430 | macro_rules! impl_usart { | 1427 | macro_rules! impl_usart { |
| 1431 | ($inst:ident, $irq:ident, $kind:expr) => { | 1428 | ($inst:ident, $irq:ident, $kind:expr) => { |
| 1432 | impl sealed::BasicInstance for crate::peripherals::$inst { | 1429 | impl SealedBasicInstance for crate::peripherals::$inst { |
| 1433 | const KIND: Kind = $kind; | 1430 | const KIND: Kind = $kind; |
| 1434 | type Interrupt = crate::interrupt::typelevel::$irq; | ||
| 1435 | 1431 | ||
| 1436 | fn regs() -> Regs { | 1432 | fn regs() -> Regs { |
| 1437 | unsafe { Regs::from_ptr(crate::pac::$inst.as_ptr()) } | 1433 | unsafe { Regs::from_ptr(crate::pac::$inst.as_ptr()) } |
| 1438 | } | 1434 | } |
| 1439 | 1435 | ||
| 1440 | fn state() -> &'static crate::usart::sealed::State { | 1436 | fn state() -> &'static crate::usart::State { |
| 1441 | static STATE: crate::usart::sealed::State = crate::usart::sealed::State::new(); | 1437 | static STATE: crate::usart::State = crate::usart::State::new(); |
| 1442 | &STATE | 1438 | &STATE |
| 1443 | } | 1439 | } |
| 1444 | 1440 | ||
| @@ -1448,7 +1444,9 @@ macro_rules! impl_usart { | |||
| 1448 | } | 1444 | } |
| 1449 | } | 1445 | } |
| 1450 | 1446 | ||
| 1451 | impl BasicInstance for peripherals::$inst {} | 1447 | impl BasicInstance for peripherals::$inst { |
| 1448 | type Interrupt = crate::interrupt::typelevel::$irq; | ||
| 1449 | } | ||
| 1452 | }; | 1450 | }; |
| 1453 | } | 1451 | } |
| 1454 | 1452 | ||
| @@ -1460,7 +1458,7 @@ foreach_interrupt!( | |||
| 1460 | ($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => { | 1458 | ($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => { |
| 1461 | impl_usart!($inst, $irq, Kind::Uart); | 1459 | impl_usart!($inst, $irq, Kind::Uart); |
| 1462 | 1460 | ||
| 1463 | impl sealed::FullInstance for peripherals::$inst { | 1461 | impl SealedFullInstance for peripherals::$inst { |
| 1464 | fn regs_uart() -> crate::pac::usart::Usart { | 1462 | fn regs_uart() -> crate::pac::usart::Usart { |
| 1465 | crate::pac::$inst | 1463 | crate::pac::$inst |
| 1466 | } | 1464 | } |
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; | |||
| 6 | pub use _version::*; | 6 | pub use _version::*; |
| 7 | 7 | ||
| 8 | use crate::interrupt::typelevel::Interrupt; | 8 | use crate::interrupt::typelevel::Interrupt; |
| 9 | use crate::rcc::sealed::RccPeripheral; | 9 | use crate::rcc::SealedRccPeripheral; |
| 10 | 10 | ||
| 11 | /// clock, power initialization stuff that's common for USB and OTG. | 11 | /// clock, power initialization stuff that's common for USB and OTG. |
| 12 | fn common_init<T: Instance>() { | 12 | fn common_init<T: Instance>() { |
| @@ -65,5 +65,5 @@ fn common_init<T: Instance>() { | |||
| 65 | T::Interrupt::unpend(); | 65 | T::Interrupt::unpend(); |
| 66 | unsafe { T::Interrupt::enable() }; | 66 | unsafe { T::Interrupt::enable() }; |
| 67 | 67 | ||
| 68 | <T as RccPeripheral>::enable_and_reset(); | 68 | <T as SealedRccPeripheral>::enable_and_reset(); |
| 69 | } | 69 | } |
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::{ | |||
| 11 | }; | 11 | }; |
| 12 | use futures::future::poll_fn; | 12 | use futures::future::poll_fn; |
| 13 | 13 | ||
| 14 | use crate::gpio::sealed::AFType; | 14 | use crate::gpio::AFType; |
| 15 | use crate::interrupt; | 15 | use crate::interrupt; |
| 16 | use crate::interrupt::typelevel::Interrupt; | 16 | use crate::interrupt::typelevel::Interrupt; |
| 17 | use crate::pac::otg::{regs, vals}; | 17 | use crate::pac::otg::{regs, vals}; |
| 18 | use crate::rcc::sealed::RccPeripheral; | 18 | use crate::rcc::{RccPeripheral, SealedRccPeripheral}; |
| 19 | use crate::time::Hertz; | 19 | use crate::time::Hertz; |
| 20 | 20 | ||
| 21 | /// Interrupt handler. | 21 | /// Interrupt handler. |
| @@ -809,7 +809,7 @@ impl<'d, T: Instance> Bus<'d, T> { | |||
| 809 | fn disable(&mut self) { | 809 | fn disable(&mut self) { |
| 810 | T::Interrupt::disable(); | 810 | T::Interrupt::disable(); |
| 811 | 811 | ||
| 812 | <T as RccPeripheral>::disable(); | 812 | <T as SealedRccPeripheral>::disable(); |
| 813 | 813 | ||
| 814 | #[cfg(stm32l4)] | 814 | #[cfg(stm32l4)] |
| 815 | crate::pac::PWR.cr2().modify(|w| w.set_usv(false)); | 815 | 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 { | |||
| 1436 | // Using Instance::ENDPOINT_COUNT requires feature(const_generic_expr) so just define maximum eps | 1436 | // Using Instance::ENDPOINT_COUNT requires feature(const_generic_expr) so just define maximum eps |
| 1437 | const MAX_EP_COUNT: usize = 9; | 1437 | const MAX_EP_COUNT: usize = 9; |
| 1438 | 1438 | ||
| 1439 | pub(crate) mod sealed { | 1439 | trait SealedInstance { |
| 1440 | pub trait Instance { | 1440 | const HIGH_SPEED: bool; |
| 1441 | const HIGH_SPEED: bool; | 1441 | const FIFO_DEPTH_WORDS: u16; |
| 1442 | const FIFO_DEPTH_WORDS: u16; | 1442 | const ENDPOINT_COUNT: usize; |
| 1443 | const ENDPOINT_COUNT: usize; | ||
| 1444 | 1443 | ||
| 1445 | fn regs() -> crate::pac::otg::Otg; | 1444 | fn regs() -> crate::pac::otg::Otg; |
| 1446 | fn state() -> &'static super::State<{ super::MAX_EP_COUNT }>; | 1445 | fn state() -> &'static super::State<{ MAX_EP_COUNT }>; |
| 1447 | } | ||
| 1448 | } | 1446 | } |
| 1449 | 1447 | ||
| 1450 | /// USB instance trait. | 1448 | /// USB instance trait. |
| 1451 | pub trait Instance: sealed::Instance + RccPeripheral + 'static { | 1449 | #[allow(private_bounds)] |
| 1450 | pub trait Instance: SealedInstance + RccPeripheral + 'static { | ||
| 1452 | /// Interrupt for this USB instance. | 1451 | /// Interrupt for this USB instance. |
| 1453 | type Interrupt: interrupt::typelevel::Interrupt; | 1452 | type Interrupt: interrupt::typelevel::Interrupt; |
| 1454 | } | 1453 | } |
| @@ -1473,7 +1472,7 @@ pin_trait!(UlpiD7Pin, Instance); | |||
| 1473 | 1472 | ||
| 1474 | foreach_interrupt!( | 1473 | foreach_interrupt!( |
| 1475 | (USB_OTG_FS, otg, $block:ident, GLOBAL, $irq:ident) => { | 1474 | (USB_OTG_FS, otg, $block:ident, GLOBAL, $irq:ident) => { |
| 1476 | impl sealed::Instance for crate::peripherals::USB_OTG_FS { | 1475 | impl SealedInstance for crate::peripherals::USB_OTG_FS { |
| 1477 | const HIGH_SPEED: bool = false; | 1476 | const HIGH_SPEED: bool = false; |
| 1478 | 1477 | ||
| 1479 | cfg_if::cfg_if! { | 1478 | cfg_if::cfg_if! { |
| @@ -1538,7 +1537,7 @@ foreach_interrupt!( | |||
| 1538 | }; | 1537 | }; |
| 1539 | 1538 | ||
| 1540 | (USB_OTG_HS, otg, $block:ident, GLOBAL, $irq:ident) => { | 1539 | (USB_OTG_HS, otg, $block:ident, GLOBAL, $irq:ident) => { |
| 1541 | impl sealed::Instance for crate::peripherals::USB_OTG_HS { | 1540 | impl SealedInstance for crate::peripherals::USB_OTG_HS { |
| 1542 | const HIGH_SPEED: bool = true; | 1541 | const HIGH_SPEED: bool = true; |
| 1543 | 1542 | ||
| 1544 | cfg_if::cfg_if! { | 1543 | 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::{ | |||
| 15 | use crate::pac::usb::regs; | 15 | use crate::pac::usb::regs; |
| 16 | use crate::pac::usb::vals::{EpType, Stat}; | 16 | use crate::pac::usb::vals::{EpType, Stat}; |
| 17 | use crate::pac::USBRAM; | 17 | use crate::pac::USBRAM; |
| 18 | use crate::rcc::sealed::RccPeripheral; | 18 | use crate::rcc::RccPeripheral; |
| 19 | use crate::{interrupt, Peripheral}; | 19 | use crate::{interrupt, Peripheral}; |
| 20 | 20 | ||
| 21 | /// Interrupt handler. | 21 | /// Interrupt handler. |
| @@ -277,8 +277,8 @@ impl<'d, T: Instance> Driver<'d, T> { | |||
| 277 | 277 | ||
| 278 | #[cfg(not(stm32l1))] | 278 | #[cfg(not(stm32l1))] |
| 279 | { | 279 | { |
| 280 | dp.set_as_af(dp.af_num(), crate::gpio::sealed::AFType::OutputPushPull); | 280 | dp.set_as_af(dp.af_num(), crate::gpio::AFType::OutputPushPull); |
| 281 | dm.set_as_af(dm.af_num(), crate::gpio::sealed::AFType::OutputPushPull); | 281 | dm.set_as_af(dm.af_num(), crate::gpio::AFType::OutputPushPull); |
| 282 | } | 282 | } |
| 283 | #[cfg(stm32l1)] | 283 | #[cfg(stm32l1)] |
| 284 | let _ = (dp, dm); // suppress "unused" warnings. | 284 | let _ = (dp, dm); // suppress "unused" warnings. |
| @@ -1037,14 +1037,13 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { | |||
| 1037 | } | 1037 | } |
| 1038 | } | 1038 | } |
| 1039 | 1039 | ||
| 1040 | pub(crate) mod sealed { | 1040 | trait SealedInstance { |
| 1041 | pub trait Instance { | 1041 | fn regs() -> crate::pac::usb::Usb; |
| 1042 | fn regs() -> crate::pac::usb::Usb; | ||
| 1043 | } | ||
| 1044 | } | 1042 | } |
| 1045 | 1043 | ||
| 1046 | /// USB instance trait. | 1044 | /// USB instance trait. |
| 1047 | pub trait Instance: sealed::Instance + RccPeripheral + 'static { | 1045 | #[allow(private_bounds)] |
| 1046 | pub trait Instance: SealedInstance + RccPeripheral + 'static { | ||
| 1048 | /// Interrupt for this USB instance. | 1047 | /// Interrupt for this USB instance. |
| 1049 | type Interrupt: interrupt::typelevel::Interrupt; | 1048 | type Interrupt: interrupt::typelevel::Interrupt; |
| 1050 | } | 1049 | } |
| @@ -1055,7 +1054,7 @@ pin_trait!(DmPin, Instance); | |||
| 1055 | 1054 | ||
| 1056 | foreach_interrupt!( | 1055 | foreach_interrupt!( |
| 1057 | ($inst:ident, usb, $block:ident, LP, $irq:ident) => { | 1056 | ($inst:ident, usb, $block:ident, LP, $irq:ident) => { |
| 1058 | impl sealed::Instance for crate::peripherals::$inst { | 1057 | impl SealedInstance for crate::peripherals::$inst { |
| 1059 | fn regs() -> crate::pac::usb::Usb { | 1058 | fn regs() -> crate::pac::usb::Usb { |
| 1060 | crate::pac::$inst | 1059 | crate::pac::$inst |
| 1061 | } | 1060 | } |
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> { | |||
| 80 | } | 80 | } |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | mod sealed { | 83 | trait SealedInstance { |
| 84 | pub trait Instance { | 84 | fn regs() -> crate::pac::iwdg::Iwdg; |
| 85 | fn regs() -> crate::pac::iwdg::Iwdg; | ||
| 86 | } | ||
| 87 | } | 85 | } |
| 88 | 86 | ||
| 89 | /// IWDG instance trait. | 87 | /// IWDG instance trait. |
| 90 | pub trait Instance: sealed::Instance {} | 88 | #[allow(private_bounds)] |
| 89 | pub trait Instance: SealedInstance {} | ||
| 91 | 90 | ||
| 92 | foreach_peripheral!( | 91 | foreach_peripheral!( |
| 93 | (iwdg, $inst:ident) => { | 92 | (iwdg, $inst:ident) => { |
| 94 | impl sealed::Instance for crate::peripherals::$inst { | 93 | impl SealedInstance for crate::peripherals::$inst { |
| 95 | fn regs() -> crate::pac::iwdg::Iwdg { | 94 | fn regs() -> crate::pac::iwdg::Iwdg { |
| 96 | crate::pac::$inst | 95 | crate::pac::$inst |
| 97 | } | 96 | } |
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 @@ | |||
| 15 | use embassy_executor::Spawner; | 15 | use embassy_executor::Spawner; |
| 16 | use embassy_stm32::gpio::OutputType; | 16 | use embassy_stm32::gpio::OutputType; |
| 17 | use embassy_stm32::time::khz; | 17 | use embassy_stm32::time::khz; |
| 18 | use embassy_stm32::timer::low_level::CountingMode; | ||
| 18 | use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; | 19 | use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; |
| 19 | use embassy_stm32::timer::{Channel, CountingMode}; | 20 | use embassy_stm32::timer::Channel; |
| 20 | use embassy_time::{Duration, Ticker, Timer}; | 21 | use embassy_time::{Duration, Ticker, Timer}; |
| 21 | use {defmt_rtt as _, panic_probe as _}; | 22 | use {defmt_rtt as _, panic_probe as _}; |
| 22 | 23 | ||
| @@ -60,7 +61,7 @@ async fn main(_spawner: Spawner) { | |||
| 60 | // construct ws2812 non-return-to-zero (NRZ) code bit by bit | 61 | // construct ws2812 non-return-to-zero (NRZ) code bit by bit |
| 61 | // ws2812 only need 24 bits for each LED, but we add one bit more to keep PWM output low | 62 | // ws2812 only need 24 bits for each LED, but we add one bit more to keep PWM output low |
| 62 | 63 | ||
| 63 | let max_duty = ws2812_pwm.get_max_duty(); | 64 | let max_duty = ws2812_pwm.get_max_duty() as u16; |
| 64 | let n0 = 8 * max_duty / 25; // ws2812 Bit 0 high level timing | 65 | let n0 = 8 * max_duty / 25; // ws2812 Bit 0 high level timing |
| 65 | let n1 = 2 * n0; // ws2812 Bit 1 high level timing | 66 | let n1 = 2 * n0; // ws2812 Bit 1 high level timing |
| 66 | 67 | ||
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; | |||
| 6 | use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; | 6 | use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; |
| 7 | use embassy_stm32::pac::timer::vals::Mms; | 7 | use embassy_stm32::pac::timer::vals::Mms; |
| 8 | use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; | 8 | use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; |
| 9 | use embassy_stm32::rcc::low_level::RccPeripheral; | 9 | use embassy_stm32::rcc::frequency; |
| 10 | use embassy_stm32::time::Hertz; | 10 | use embassy_stm32::time::Hertz; |
| 11 | use embassy_stm32::timer::low_level::BasicInstance; | 11 | use embassy_stm32::timer::low_level::Timer; |
| 12 | use micromath::F32Ext; | 12 | use micromath::F32Ext; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 14 | ||
| @@ -51,19 +51,19 @@ async fn main(spawner: Spawner) { | |||
| 51 | // Obtain two independent channels (p.DAC1 can only be consumed once, though!) | 51 | // Obtain two independent channels (p.DAC1 can only be consumed once, though!) |
| 52 | let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split(); | 52 | let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split(); |
| 53 | 53 | ||
| 54 | spawner.spawn(dac_task1(dac_ch1)).ok(); | 54 | spawner.spawn(dac_task1(p.TIM6, dac_ch1)).ok(); |
| 55 | spawner.spawn(dac_task2(dac_ch2)).ok(); | 55 | spawner.spawn(dac_task2(p.TIM7, dac_ch2)).ok(); |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | #[embassy_executor::task] | 58 | #[embassy_executor::task] |
| 59 | async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { | 59 | async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { |
| 60 | let data: &[u8; 256] = &calculate_array::<256>(); | 60 | let data: &[u8; 256] = &calculate_array::<256>(); |
| 61 | 61 | ||
| 62 | info!("TIM6 frequency is {}", TIM6::frequency()); | 62 | info!("TIM6 frequency is {}", frequency::<TIM6>()); |
| 63 | const FREQUENCY: Hertz = Hertz::hz(200); | 63 | const FREQUENCY: Hertz = Hertz::hz(200); |
| 64 | 64 | ||
| 65 | // Compute the reload value such that we obtain the FREQUENCY for the sine | 65 | // Compute the reload value such that we obtain the FREQUENCY for the sine |
| 66 | let reload: u32 = (TIM6::frequency().0 / FREQUENCY.0) / data.len() as u32; | 66 | let reload: u32 = (frequency::<TIM6>().0 / FREQUENCY.0) / data.len() as u32; |
| 67 | 67 | ||
| 68 | // Depends on your clock and on the specific chip used, you may need higher or lower values here | 68 | // Depends on your clock and on the specific chip used, you may need higher or lower values here |
| 69 | if reload < 10 { | 69 | if reload < 10 { |
| @@ -74,17 +74,17 @@ async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { | |||
| 74 | dac.set_triggering(true); | 74 | dac.set_triggering(true); |
| 75 | dac.enable(); | 75 | dac.enable(); |
| 76 | 76 | ||
| 77 | TIM6::enable_and_reset(); | 77 | let tim = Timer::new(tim); |
| 78 | TIM6::regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); | 78 | tim.regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); |
| 79 | TIM6::regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); | 79 | tim.regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); |
| 80 | TIM6::regs_basic().cr1().modify(|w| { | 80 | tim.regs_basic().cr1().modify(|w| { |
| 81 | w.set_opm(false); | 81 | w.set_opm(false); |
| 82 | w.set_cen(true); | 82 | w.set_cen(true); |
| 83 | }); | 83 | }); |
| 84 | 84 | ||
| 85 | debug!( | 85 | debug!( |
| 86 | "TIM6 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", | 86 | "TIM6 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", |
| 87 | TIM6::frequency(), | 87 | frequency::<TIM6>(), |
| 88 | FREQUENCY, | 88 | FREQUENCY, |
| 89 | reload, | 89 | reload, |
| 90 | reload as u16, | 90 | reload as u16, |
| @@ -99,22 +99,22 @@ async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { | |||
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | #[embassy_executor::task] | 101 | #[embassy_executor::task] |
| 102 | async fn dac_task2(mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { | 102 | async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { |
| 103 | let data: &[u8; 256] = &calculate_array::<256>(); | 103 | let data: &[u8; 256] = &calculate_array::<256>(); |
| 104 | 104 | ||
| 105 | info!("TIM7 frequency is {}", TIM7::frequency()); | 105 | info!("TIM7 frequency is {}", frequency::<TIM6>()); |
| 106 | 106 | ||
| 107 | const FREQUENCY: Hertz = Hertz::hz(600); | 107 | const FREQUENCY: Hertz = Hertz::hz(600); |
| 108 | let reload: u32 = (TIM7::frequency().0 / FREQUENCY.0) / data.len() as u32; | 108 | let reload: u32 = (frequency::<TIM7>().0 / FREQUENCY.0) / data.len() as u32; |
| 109 | 109 | ||
| 110 | if reload < 10 { | 110 | if reload < 10 { |
| 111 | error!("Reload value {} below threshold!", reload); | 111 | error!("Reload value {} below threshold!", reload); |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | TIM7::enable_and_reset(); | 114 | let tim = Timer::new(tim); |
| 115 | TIM7::regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); | 115 | tim.regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); |
| 116 | TIM7::regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); | 116 | tim.regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); |
| 117 | TIM7::regs_basic().cr1().modify(|w| { | 117 | tim.regs_basic().cr1().modify(|w| { |
| 118 | w.set_opm(false); | 118 | w.set_opm(false); |
| 119 | w.set_cen(true); | 119 | w.set_cen(true); |
| 120 | }); | 120 | }); |
| @@ -125,7 +125,7 @@ async fn dac_task2(mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { | |||
| 125 | 125 | ||
| 126 | debug!( | 126 | debug!( |
| 127 | "TIM7 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", | 127 | "TIM7 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", |
| 128 | TIM7::frequency(), | 128 | frequency::<TIM7>(), |
| 129 | FREQUENCY, | 129 | FREQUENCY, |
| 130 | reload, | 130 | reload, |
| 131 | reload as u16, | 131 | 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 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::gpio::low_level::AFType; | 6 | use embassy_stm32::gpio::{AFType, Flex, Pull, Speed}; |
| 7 | use embassy_stm32::gpio::Speed; | ||
| 8 | use embassy_stm32::time::{khz, Hertz}; | 7 | use embassy_stm32::time::{khz, Hertz}; |
| 9 | use embassy_stm32::timer::*; | 8 | use embassy_stm32::timer::low_level::{OutputCompareMode, Timer as LLTimer}; |
| 10 | use embassy_stm32::{into_ref, Config, Peripheral, PeripheralRef}; | 9 | use embassy_stm32::timer::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance32bit4Channel}; |
| 10 | use embassy_stm32::{into_ref, Config, Peripheral}; | ||
| 11 | use embassy_time::Timer; | 11 | use embassy_time::Timer; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| @@ -56,11 +56,15 @@ async fn main(_spawner: Spawner) { | |||
| 56 | Timer::after_millis(300).await; | 56 | Timer::after_millis(300).await; |
| 57 | } | 57 | } |
| 58 | } | 58 | } |
| 59 | pub struct SimplePwm32<'d, T: CaptureCompare32bitInstance> { | 59 | pub struct SimplePwm32<'d, T: GeneralInstance32bit4Channel> { |
| 60 | inner: PeripheralRef<'d, T>, | 60 | tim: LLTimer<'d, T>, |
| 61 | _ch1: Flex<'d>, | ||
| 62 | _ch2: Flex<'d>, | ||
| 63 | _ch3: Flex<'d>, | ||
| 64 | _ch4: Flex<'d>, | ||
| 61 | } | 65 | } |
| 62 | 66 | ||
| 63 | impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> { | 67 | impl<'d, T: GeneralInstance32bit4Channel> SimplePwm32<'d, T> { |
| 64 | pub fn new( | 68 | pub fn new( |
| 65 | tim: impl Peripheral<P = T> + 'd, | 69 | tim: impl Peripheral<P = T> + 'd, |
| 66 | ch1: impl Peripheral<P = impl Channel1Pin<T>> + 'd, | 70 | ch1: impl Peripheral<P = impl Channel1Pin<T>> + 'd, |
| @@ -69,25 +73,33 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> { | |||
| 69 | ch4: impl Peripheral<P = impl Channel4Pin<T>> + 'd, | 73 | ch4: impl Peripheral<P = impl Channel4Pin<T>> + 'd, |
| 70 | freq: Hertz, | 74 | freq: Hertz, |
| 71 | ) -> Self { | 75 | ) -> Self { |
| 72 | into_ref!(tim, ch1, ch2, ch3, ch4); | 76 | into_ref!(ch1, ch2, ch3, ch4); |
| 73 | 77 | ||
| 74 | T::enable_and_reset(); | 78 | let af1 = ch1.af_num(); |
| 75 | 79 | let af2 = ch2.af_num(); | |
| 76 | ch1.set_speed(Speed::VeryHigh); | 80 | let af3 = ch3.af_num(); |
| 77 | ch1.set_as_af(ch1.af_num(), AFType::OutputPushPull); | 81 | let af4 = ch4.af_num(); |
| 78 | ch2.set_speed(Speed::VeryHigh); | 82 | let mut ch1 = Flex::new(ch1); |
| 79 | ch2.set_as_af(ch1.af_num(), AFType::OutputPushPull); | 83 | let mut ch2 = Flex::new(ch2); |
| 80 | ch3.set_speed(Speed::VeryHigh); | 84 | let mut ch3 = Flex::new(ch3); |
| 81 | ch3.set_as_af(ch1.af_num(), AFType::OutputPushPull); | 85 | let mut ch4 = Flex::new(ch4); |
| 82 | ch4.set_speed(Speed::VeryHigh); | 86 | ch1.set_as_af_unchecked(af1, AFType::OutputPushPull, Pull::None, Speed::VeryHigh); |
| 83 | ch4.set_as_af(ch1.af_num(), AFType::OutputPushPull); | 87 | ch2.set_as_af_unchecked(af2, AFType::OutputPushPull, Pull::None, Speed::VeryHigh); |
| 84 | 88 | ch3.set_as_af_unchecked(af3, AFType::OutputPushPull, Pull::None, Speed::VeryHigh); | |
| 85 | let mut this = Self { inner: tim }; | 89 | ch4.set_as_af_unchecked(af4, AFType::OutputPushPull, Pull::None, Speed::VeryHigh); |
| 90 | |||
| 91 | let mut this = Self { | ||
| 92 | tim: LLTimer::new(tim), | ||
| 93 | _ch1: ch1, | ||
| 94 | _ch2: ch2, | ||
| 95 | _ch3: ch3, | ||
| 96 | _ch4: ch4, | ||
| 97 | }; | ||
| 86 | 98 | ||
| 87 | this.set_frequency(freq); | 99 | this.set_frequency(freq); |
| 88 | this.inner.start(); | 100 | this.tim.start(); |
| 89 | 101 | ||
| 90 | let r = T::regs_gp32(); | 102 | let r = this.tim.regs_gp32(); |
| 91 | r.ccmr_output(0) | 103 | r.ccmr_output(0) |
| 92 | .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into())); | 104 | .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into())); |
| 93 | r.ccmr_output(0) | 105 | r.ccmr_output(0) |
| @@ -101,23 +113,26 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> { | |||
| 101 | } | 113 | } |
| 102 | 114 | ||
| 103 | pub fn enable(&mut self, channel: Channel) { | 115 | pub fn enable(&mut self, channel: Channel) { |
| 104 | T::regs_gp32().ccer().modify(|w| w.set_cce(channel.index(), true)); | 116 | self.tim.regs_gp32().ccer().modify(|w| w.set_cce(channel.index(), true)); |
| 105 | } | 117 | } |
| 106 | 118 | ||
| 107 | pub fn disable(&mut self, channel: Channel) { | 119 | pub fn disable(&mut self, channel: Channel) { |
| 108 | T::regs_gp32().ccer().modify(|w| w.set_cce(channel.index(), false)); | 120 | self.tim |
| 121 | .regs_gp32() | ||
| 122 | .ccer() | ||
| 123 | .modify(|w| w.set_cce(channel.index(), false)); | ||
| 109 | } | 124 | } |
| 110 | 125 | ||
| 111 | pub fn set_frequency(&mut self, freq: Hertz) { | 126 | pub fn set_frequency(&mut self, freq: Hertz) { |
| 112 | <T as embassy_stm32::timer::low_level::GeneralPurpose32bitInstance>::set_frequency(&mut self.inner, freq); | 127 | self.tim.set_frequency(freq); |
| 113 | } | 128 | } |
| 114 | 129 | ||
| 115 | pub fn get_max_duty(&self) -> u32 { | 130 | pub fn get_max_duty(&self) -> u32 { |
| 116 | T::regs_gp32().arr().read() | 131 | self.tim.regs_gp32().arr().read() |
| 117 | } | 132 | } |
| 118 | 133 | ||
| 119 | pub fn set_duty(&mut self, channel: Channel, duty: u32) { | 134 | pub fn set_duty(&mut self, channel: Channel, duty: u32) { |
| 120 | defmt::assert!(duty < self.get_max_duty()); | 135 | defmt::assert!(duty < self.get_max_duty()); |
| 121 | T::regs_gp32().ccr(channel.index()).write_value(duty) | 136 | self.tim.regs_gp32().ccr(channel.index()).write_value(duty) |
| 122 | } | 137 | } |
| 123 | } | 138 | } |
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; | |||
| 6 | use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; | 6 | use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; |
| 7 | use embassy_stm32::pac::timer::vals::Mms; | 7 | use embassy_stm32::pac::timer::vals::Mms; |
| 8 | use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; | 8 | use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; |
| 9 | use embassy_stm32::rcc::low_level::RccPeripheral; | 9 | use embassy_stm32::rcc::frequency; |
| 10 | use embassy_stm32::time::Hertz; | 10 | use embassy_stm32::time::Hertz; |
| 11 | use embassy_stm32::timer::low_level::BasicInstance; | 11 | use embassy_stm32::timer::low_level::Timer; |
| 12 | use micromath::F32Ext; | 12 | use micromath::F32Ext; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 14 | ||
| @@ -22,19 +22,19 @@ async fn main(spawner: Spawner) { | |||
| 22 | // Obtain two independent channels (p.DAC1 can only be consumed once, though!) | 22 | // Obtain two independent channels (p.DAC1 can only be consumed once, though!) |
| 23 | let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split(); | 23 | let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split(); |
| 24 | 24 | ||
| 25 | spawner.spawn(dac_task1(dac_ch1)).ok(); | 25 | spawner.spawn(dac_task1(p.TIM6, dac_ch1)).ok(); |
| 26 | spawner.spawn(dac_task2(dac_ch2)).ok(); | 26 | spawner.spawn(dac_task2(p.TIM7, dac_ch2)).ok(); |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | #[embassy_executor::task] | 29 | #[embassy_executor::task] |
| 30 | async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { | 30 | async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { |
| 31 | let data: &[u8; 256] = &calculate_array::<256>(); | 31 | let data: &[u8; 256] = &calculate_array::<256>(); |
| 32 | 32 | ||
| 33 | info!("TIM6 frequency is {}", TIM6::frequency()); | 33 | info!("TIM6 frequency is {}", frequency::<TIM6>()); |
| 34 | const FREQUENCY: Hertz = Hertz::hz(200); | 34 | const FREQUENCY: Hertz = Hertz::hz(200); |
| 35 | 35 | ||
| 36 | // Compute the reload value such that we obtain the FREQUENCY for the sine | 36 | // Compute the reload value such that we obtain the FREQUENCY for the sine |
| 37 | let reload: u32 = (TIM6::frequency().0 / FREQUENCY.0) / data.len() as u32; | 37 | let reload: u32 = (frequency::<TIM6>().0 / FREQUENCY.0) / data.len() as u32; |
| 38 | 38 | ||
| 39 | // Depends on your clock and on the specific chip used, you may need higher or lower values here | 39 | // Depends on your clock and on the specific chip used, you may need higher or lower values here |
| 40 | if reload < 10 { | 40 | if reload < 10 { |
| @@ -45,17 +45,17 @@ async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { | |||
| 45 | dac.set_triggering(true); | 45 | dac.set_triggering(true); |
| 46 | dac.enable(); | 46 | dac.enable(); |
| 47 | 47 | ||
| 48 | TIM6::enable_and_reset(); | 48 | let tim = Timer::new(tim); |
| 49 | TIM6::regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); | 49 | tim.regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); |
| 50 | TIM6::regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); | 50 | tim.regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); |
| 51 | TIM6::regs_basic().cr1().modify(|w| { | 51 | tim.regs_basic().cr1().modify(|w| { |
| 52 | w.set_opm(false); | 52 | w.set_opm(false); |
| 53 | w.set_cen(true); | 53 | w.set_cen(true); |
| 54 | }); | 54 | }); |
| 55 | 55 | ||
| 56 | debug!( | 56 | debug!( |
| 57 | "TIM6 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", | 57 | "TIM6 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", |
| 58 | TIM6::frequency(), | 58 | frequency::<TIM6>(), |
| 59 | FREQUENCY, | 59 | FREQUENCY, |
| 60 | reload, | 60 | reload, |
| 61 | reload as u16, | 61 | reload as u16, |
| @@ -70,22 +70,22 @@ async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { | |||
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | #[embassy_executor::task] | 72 | #[embassy_executor::task] |
| 73 | async fn dac_task2(mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { | 73 | async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { |
| 74 | let data: &[u8; 256] = &calculate_array::<256>(); | 74 | let data: &[u8; 256] = &calculate_array::<256>(); |
| 75 | 75 | ||
| 76 | info!("TIM7 frequency is {}", TIM7::frequency()); | 76 | info!("TIM7 frequency is {}", frequency::<TIM7>()); |
| 77 | 77 | ||
| 78 | const FREQUENCY: Hertz = Hertz::hz(600); | 78 | const FREQUENCY: Hertz = Hertz::hz(600); |
| 79 | let reload: u32 = (TIM7::frequency().0 / FREQUENCY.0) / data.len() as u32; | 79 | let reload: u32 = (frequency::<TIM7>().0 / FREQUENCY.0) / data.len() as u32; |
| 80 | 80 | ||
| 81 | if reload < 10 { | 81 | if reload < 10 { |
| 82 | error!("Reload value {} below threshold!", reload); | 82 | error!("Reload value {} below threshold!", reload); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | TIM7::enable_and_reset(); | 85 | let tim = Timer::new(tim); |
| 86 | TIM7::regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); | 86 | tim.regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); |
| 87 | TIM7::regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); | 87 | tim.regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); |
| 88 | TIM7::regs_basic().cr1().modify(|w| { | 88 | tim.regs_basic().cr1().modify(|w| { |
| 89 | w.set_opm(false); | 89 | w.set_opm(false); |
| 90 | w.set_cen(true); | 90 | w.set_cen(true); |
| 91 | }); | 91 | }); |
| @@ -96,7 +96,7 @@ async fn dac_task2(mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { | |||
| 96 | 96 | ||
| 97 | debug!( | 97 | debug!( |
| 98 | "TIM7 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", | 98 | "TIM7 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", |
| 99 | TIM7::frequency(), | 99 | frequency::<TIM7>(), |
| 100 | FREQUENCY, | 100 | FREQUENCY, |
| 101 | reload, | 101 | reload, |
| 102 | reload as u16, | 102 | reload as u16, |
