aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-03-23 01:55:42 +0100
committerGitHub <[email protected]>2024-03-23 01:55:42 +0100
commit1171e116553f6ac43e12505b387b6eabe3037bf9 (patch)
treef64be3f155db4c1a7a9cf452d2669abcb7213709
parent2fd6f0e718931d6b06ce2db16da012544757b00c (diff)
parent2bca875b5f72578cbd20404010d174795d263313 (diff)
Merge pull request #2730 from embassy-rs/stm32-sealed
stm32: use private_bounds for sealed traits.
-rwxr-xr-xci.sh1
-rw-r--r--embassy-stm32/build.rs4
-rw-r--r--embassy-stm32/src/adc/f1.rs4
-rw-r--r--embassy-stm32/src/adc/f3.rs6
-rw-r--r--embassy-stm32/src/adc/f3_v1_1.rs4
-rw-r--r--embassy-stm32/src/adc/mod.rs100
-rw-r--r--embassy-stm32/src/adc/v1.rs6
-rw-r--r--embassy-stm32/src/adc/v2.rs6
-rw-r--r--embassy-stm32/src/adc/v3.rs8
-rw-r--r--embassy-stm32/src/adc/v4.rs8
-rw-r--r--embassy-stm32/src/can/bxcan.rs52
-rw-r--r--embassy-stm32/src/can/fd/peripheral.rs61
-rw-r--r--embassy-stm32/src/can/fdcan.rs330
-rw-r--r--embassy-stm32/src/crc/v1.rs2
-rw-r--r--embassy-stm32/src/crc/v2v3.rs2
-rw-r--r--embassy-stm32/src/cryp/mod.rs13
-rw-r--r--embassy-stm32/src/dac/mod.rs17
-rw-r--r--embassy-stm32/src/dcmi.rs14
-rw-r--r--embassy-stm32/src/dma/dmamux.rs9
-rw-r--r--embassy-stm32/src/dma/mod.rs24
-rw-r--r--embassy-stm32/src/dma/word.rs9
-rw-r--r--embassy-stm32/src/eth/mod.rs11
-rw-r--r--embassy-stm32/src/eth/v1/mod.rs23
-rw-r--r--embassy-stm32/src/eth/v2/mod.rs29
-rw-r--r--embassy-stm32/src/exti.rs11
-rw-r--r--embassy-stm32/src/fmc.rs18
-rw-r--r--embassy-stm32/src/gpio.rs299
-rw-r--r--embassy-stm32/src/hash/mod.rs15
-rw-r--r--embassy-stm32/src/hrtim/mod.rs17
-rw-r--r--embassy-stm32/src/hrtim/traits.rs128
-rw-r--r--embassy-stm32/src/i2c/mod.rs40
-rw-r--r--embassy-stm32/src/i2s.rs3
-rw-r--r--embassy-stm32/src/ipcc.rs83
-rw-r--r--embassy-stm32/src/lib.rs2
-rw-r--r--embassy-stm32/src/opamp.rs54
-rw-r--r--embassy-stm32/src/qspi/mod.rs16
-rw-r--r--embassy-stm32/src/rcc/hsi48.rs2
-rw-r--r--embassy-stm32/src/rcc/mco.rs27
-rw-r--r--embassy-stm32/src/rcc/mod.rs41
-rw-r--r--embassy-stm32/src/rng.rs13
-rw-r--r--embassy-stm32/src/rtc/datetime.rs2
-rw-r--r--embassy-stm32/src/rtc/mod.rs53
-rw-r--r--embassy-stm32/src/rtc/v2.rs5
-rw-r--r--embassy-stm32/src/rtc/v3.rs6
-rw-r--r--embassy-stm32/src/sai/mod.rs41
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs29
-rw-r--r--embassy-stm32/src/spi/mod.rs37
-rw-r--r--embassy-stm32/src/time_driver.rs38
-rw-r--r--embassy-stm32/src/timer/complementary_pwm.rs38
-rw-r--r--embassy-stm32/src/timer/low_level.rs638
-rw-r--r--embassy-stm32/src/timer/mod.rs1005
-rw-r--r--embassy-stm32/src/timer/qei.rs36
-rw-r--r--embassy-stm32/src/timer/simple_pwm.rs46
-rw-r--r--embassy-stm32/src/ucpd.rs60
-rw-r--r--embassy-stm32/src/usart/mod.rs82
-rw-r--r--embassy-stm32/src/usb/mod.rs4
-rw-r--r--embassy-stm32/src/usb/otg.rs27
-rw-r--r--embassy-stm32/src/usb/usb.rs17
-rw-r--r--embassy-stm32/src/wdg/mod.rs11
-rw-r--r--examples/stm32f4/src/bin/ws2812_pwm.rs5
-rw-r--r--examples/stm32h7/src/bin/dac_dma.rs40
-rw-r--r--examples/stm32h7/src/bin/low_level_timer_api.rs71
-rw-r--r--examples/stm32l4/src/bin/dac_dma.rs40
63 files changed, 1798 insertions, 2045 deletions
diff --git a/ci.sh b/ci.sh
index cd82af2f1..d17f4e13e 100755
--- a/ci.sh
+++ b/ci.sh
@@ -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
34pub struct Vref; 34pub struct Vref;
35impl<T: Instance> AdcPin<T> for Vref {} 35impl<T: Instance> AdcPin<T> for Vref {}
36impl<T: Instance> super::sealed::AdcPin<T> for Vref { 36impl<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
42pub struct Temperature; 42pub struct Temperature;
43impl<T: Instance> AdcPin<T> for Temperature {} 43impl<T: Instance> AdcPin<T> for Temperature {}
44impl<T: Instance> super::sealed::AdcPin<T> for Temperature { 44impl<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
34pub struct Vref; 34pub struct Vref;
35impl<T: Instance> AdcPin<T> for Vref {} 35impl<T: Instance> AdcPin<T> for Vref {}
36impl<T: Instance> super::sealed::AdcPin<T> for Vref { 36impl<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
49pub struct Temperature; 49pub struct Temperature;
50impl<T: Instance> AdcPin<T> for Temperature {} 50impl<T: Instance> AdcPin<T> for Temperature {}
51impl<T: Instance> super::sealed::AdcPin<T> for Temperature { 51impl<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
66pub struct Vref<T: Instance>(core::marker::PhantomData<T>); 66pub struct Vref<T: Instance>(core::marker::PhantomData<T>);
67impl<T: Instance> AdcPin<T> for Vref<T> {} 67impl<T: Instance> AdcPin<T> for Vref<T> {}
68impl<T: Instance> super::sealed::AdcPin<T> for Vref<T> { 68impl<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
125pub struct Temperature<T: Instance>(core::marker::PhantomData<T>); 125pub struct Temperature<T: Instance>(core::marker::PhantomData<T>);
126impl<T: Instance> AdcPin<T> for Temperature<T> {} 126impl<T: Instance> AdcPin<T> for Temperature<T> {}
127impl<T: Instance> super::sealed::AdcPin<T> for Temperature<T> { 127impl<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))]
19pub use _version::*; 19pub use _version::*;
20#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
21use embassy_sync::waitqueue::AtomicWaker;
20 22
21#[cfg(not(any(adc_f1, adc_f3_v2)))] 23#[cfg(not(any(adc_f1, adc_f3_v2)))]
22pub use crate::pac::adc::vals::Res as Resolution; 24pub 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
34pub(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))] 37pub 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 { 42impl 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 { 50trait 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> { 59pub(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> { 67trait 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)))]
78pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> {} 74#[allow(private_bounds)]
75pub 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))]
81pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {} 80#[allow(private_bounds)]
81pub 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.
84pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {} 86#[allow(private_bounds)]
87pub trait AdcPin<T: Instance>: SealedAdcPin<T> {}
85/// ADC internal channel. 88/// ADC internal channel.
86pub trait InternalChannel<T>: sealed::InternalChannel<T> {} 89#[allow(private_bounds)]
90pub trait InternalChannel<T>: SealedInternalChannel<T> {}
87 91
88foreach_adc!( 92foreach_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;
39impl AdcPin<ADC> for Vbat {} 39impl AdcPin<ADC> for Vbat {}
40 40
41#[cfg(not(adc_l0))] 41#[cfg(not(adc_l0))]
42impl super::sealed::AdcPin<ADC> for Vbat { 42impl 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
48pub struct Vref; 48pub struct Vref;
49impl AdcPin<ADC> for Vref {} 49impl AdcPin<ADC> for Vref {}
50impl super::sealed::AdcPin<ADC> for Vref { 50impl 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
56pub struct Temperature; 56pub struct Temperature;
57impl AdcPin<ADC> for Temperature {} 57impl AdcPin<ADC> for Temperature {}
58impl super::sealed::AdcPin<ADC> for Temperature { 58impl 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
17pub struct VrefInt; 17pub struct VrefInt;
18impl AdcPin<ADC1> for VrefInt {} 18impl AdcPin<ADC1> for VrefInt {}
19impl super::sealed::AdcPin<ADC1> for VrefInt { 19impl 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
32pub struct Temperature; 32pub struct Temperature;
33impl AdcPin<ADC1> for Temperature {} 33impl AdcPin<ADC1> for Temperature {}
34impl super::sealed::AdcPin<ADC1> for Temperature { 34impl 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
53pub struct Vbat; 53pub struct Vbat;
54impl AdcPin<ADC1> for Vbat {} 54impl AdcPin<ADC1> for Vbat {}
55impl super::sealed::AdcPin<ADC1> for Vbat { 55impl 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
13pub struct VrefInt; 13pub struct VrefInt;
14impl<T: Instance> AdcPin<T> for VrefInt {} 14impl<T: Instance> AdcPin<T> for VrefInt {}
15impl<T: Instance> super::sealed::AdcPin<T> for VrefInt { 15impl<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
30pub struct Temperature; 30pub struct Temperature;
31impl<T: Instance> AdcPin<T> for Temperature {} 31impl<T: Instance> AdcPin<T> for Temperature {}
32impl<T: Instance> super::sealed::AdcPin<T> for Temperature { 32impl<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
47pub struct Vbat; 47pub struct Vbat;
48impl<T: Instance> AdcPin<T> for Vbat {} 48impl<T: Instance> AdcPin<T> for Vbat {}
49impl<T: Instance> super::sealed::AdcPin<T> for Vbat { 49impl<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.
36pub struct VrefInt; 36pub struct VrefInt;
37impl<T: Instance> InternalChannel<T> for VrefInt {} 37impl<T: Instance> InternalChannel<T> for VrefInt {}
38impl<T: Instance> super::sealed::InternalChannel<T> for VrefInt { 38impl<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.
45pub struct Temperature; 45pub struct Temperature;
46impl<T: Instance> InternalChannel<T> for Temperature {} 46impl<T: Instance> InternalChannel<T> for Temperature {}
47impl<T: Instance> super::sealed::InternalChannel<T> for Temperature { 47impl<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.
54pub struct Vbat; 54pub struct Vbat;
55impl<T: Instance> InternalChannel<T> for Vbat {} 55impl<T: Instance> InternalChannel<T> for Vbat {}
56impl<T: Instance> super::sealed::InternalChannel<T> for Vbat { 56impl<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
8pub use bx::{filter, Data, ExtendedId, Fifo, Frame, Header, Id, StandardId}; 8pub use bx::{filter, Data, ExtendedId, Fifo, Frame, Header, Id, StandardId};
9use embassy_hal_internal::{into_ref, PeripheralRef}; 9use embassy_hal_internal::{into_ref, PeripheralRef};
10use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
11use embassy_sync::channel::Channel;
12use embassy_sync::waitqueue::AtomicWaker;
10use futures::FutureExt; 13use futures::FutureExt;
11 14
12use crate::gpio::sealed::AFType; 15use crate::gpio::AFType;
13use crate::interrupt::typelevel::Interrupt; 16use crate::interrupt::typelevel::Interrupt;
14use crate::pac::can::vals::{Ide, Lec}; 17use crate::pac::can::vals::{Ide, Lec};
15use crate::rcc::RccPeripheral; 18use crate::rcc::RccPeripheral;
@@ -485,37 +488,30 @@ impl<'d, T: Instance> DerefMut for Can<'d, T> {
485 } 488 }
486} 489}
487 490
488pub(crate) mod sealed { 491struct 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 { 497impl 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 { 507trait 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.
518pub trait Instance: sealed::Instance + RccPeripheral + 'static { 513#[allow(private_bounds)]
514pub 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
534foreach_peripheral!( 530foreach_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
6use embassy_hal_internal::{into_ref, PeripheralRef}; 6use embassy_hal_internal::{into_ref, PeripheralRef};
7use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 7use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
8use embassy_sync::channel::Channel; 8use embassy_sync::channel::{Channel, DynamicReceiver, DynamicSender};
9use embassy_sync::waitqueue::AtomicWaker;
9 10
10use crate::can::fd::peripheral::Registers; 11use crate::can::fd::peripheral::Registers;
11use crate::gpio::sealed::AFType; 12use crate::gpio::AFType;
12use crate::interrupt::typelevel::Interrupt; 13use crate::interrupt::typelevel::Interrupt;
13use crate::rcc::RccPeripheral; 14use crate::rcc::RccPeripheral;
14use crate::{interrupt, peripherals, Peripheral}; 15use 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
680pub(crate) mod sealed { 681struct ClassicBufferedRxInner {
681 use core::future::poll_fn; 682 rx_sender: DynamicSender<'static, Result<(ClassicFrame, Timestamp), BusError>>,
682 use core::task::Poll; 683}
683 684struct 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 { 688struct 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 { 691struct FdBufferedTxInner {
702 pub tx_receiver: DynamicReceiver<'static, FdFrame>, 692 tx_receiver: DynamicReceiver<'static, FdFrame>,
703 } 693}
704 694
705 pub enum RxMode { 695enum 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 { 701impl 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 { 766enum 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 _ => { 772impl 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 { 820struct 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 { 828impl 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 { 839trait 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
862pub trait Instance: sealed::Instance + RccPeripheral + 'static { 850#[allow(private_bounds)]
851pub 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
872macro_rules! impl_fdcan { 861macro_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
3use crate::pac::CRC as PAC_CRC; 3use crate::pac::CRC as PAC_CRC;
4use crate::peripherals::CRC; 4use crate::peripherals::CRC;
5use crate::rcc::sealed::RccPeripheral; 5use crate::rcc::SealedRccPeripheral;
6use crate::Peripheral; 6use 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};
3use crate::pac::crc::vals; 3use crate::pac::crc::vals;
4use crate::pac::CRC as PAC_CRC; 4use crate::pac::CRC as PAC_CRC;
5use crate::peripherals::CRC; 5use crate::peripherals::CRC;
6use crate::rcc::sealed::RccPeripheral; 6use crate::rcc::SealedRccPeripheral;
7use crate::Peripheral; 7use 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
1888pub(crate) mod sealed { 1888trait 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.
1897pub trait Instance: sealed::Instance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send { 1893#[allow(private_bounds)]
1894pub 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
491pub(crate) mod sealed { 491trait 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.
498pub trait Instance: sealed::Instance + RccPeripheral + 'static {} 496#[allow(private_bounds)]
497pub trait Instance: SealedInstance + RccPeripheral + 'static {}
499dma_trait!(DacDma1, Instance); 498dma_trait!(DacDma1, Instance);
500dma_trait!(DacDma2, Instance); 499dma_trait!(DacDma2, Instance);
501 500
@@ -504,7 +503,7 @@ pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin + 'static {}
504 503
505foreach_peripheral!( 504foreach_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};
7use embassy_sync::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
8 8
9use crate::dma::Transfer; 9use crate::dma::Transfer;
10use crate::gpio::sealed::AFType; 10use crate::gpio::{AFType, Speed};
11use crate::gpio::Speed;
12use crate::interrupt::typelevel::Interrupt; 11use crate::interrupt::typelevel::Interrupt;
13use crate::{interrupt, Peripheral}; 12use crate::{interrupt, Peripheral};
14 13
@@ -431,14 +430,13 @@ where
431 } 430 }
432} 431}
433 432
434mod sealed { 433trait 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.
441pub trait Instance: sealed::Instance + 'static { 438#[allow(private_bounds)]
439pub 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)]
466macro_rules! impl_peripheral { 464macro_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
22pub(crate) mod dmamux_sealed { 22pub(crate) trait SealedMuxChannel {}
23 pub trait MuxChannel {}
24}
25 23
26/// DMAMUX1 instance. 24/// DMAMUX1 instance.
27pub struct DMAMUX1; 25pub struct DMAMUX1;
@@ -30,14 +28,15 @@ pub struct DMAMUX1;
30pub struct DMAMUX2; 28pub struct DMAMUX2;
31 29
32/// DMAMUX channel trait. 30/// DMAMUX channel trait.
33pub trait MuxChannel: dmamux_sealed::MuxChannel { 31#[allow(private_bounds)]
32pub 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
38macro_rules! dmamux_channel_impl { 37macro_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)))]
40pub type Request = (); 40pub type Request = ();
41 41
42pub(crate) mod sealed { 42pub(crate) trait SealedChannel {
43 pub trait Channel { 43 fn id(&self) -> u8;
44 fn id(&self) -> u8; 44}
45 } 45
46 pub trait ChannelInterrupt { 46pub(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.
53pub trait Channel: sealed::Channel + Peripheral<P = Self> + Into<AnyChannel> + 'static { 52#[allow(private_bounds)]
53pub 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
65macro_rules! dma_channel_impl { 65macro_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
100impl sealed::Channel for AnyChannel { 100impl 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
23mod sealed { 23trait 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.
30pub trait Word: sealed::Word + Default + Copy + 'static { 28#[allow(private_bounds)]
29pub 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
37macro_rules! impl_word { 36macro_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
180pub(crate) mod sealed { 180trait 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.
187pub trait Instance: sealed::Instance + RccPeripheral + Send + 'static {} 185#[allow(private_bounds)]
186pub trait Instance: SealedInstance + RccPeripheral + Send + 'static {}
188 187
189impl sealed::Instance for crate::peripherals::ETH { 188impl 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
12pub(crate) use self::rx_desc::{RDes, RDesRing}; 12pub(crate) use self::rx_desc::{RDes, RDesRing};
13pub(crate) use self::tx_desc::{TDes, TDesRing}; 13pub(crate) use self::tx_desc::{TDes, TDesRing};
14use super::*; 14use super::*;
15use crate::gpio::sealed::{AFType, Pin as __GpioPin}; 15use crate::gpio::{AFType, AnyPin, SealedPin};
16use crate::gpio::AnyPin;
17use crate::interrupt::InterruptExt; 16use crate::interrupt::InterruptExt;
18#[cfg(eth_v1a)] 17#[cfg(eth_v1a)]
19use crate::pac::AFIO; 18use crate::pac::AFIO;
20#[cfg(any(eth_v1b, eth_v1c))] 19#[cfg(any(eth_v1b, eth_v1c))]
21use crate::pac::SYSCFG; 20use crate::pac::SYSCFG;
22use crate::pac::{ETH, RCC}; 21use crate::pac::{ETH, RCC};
23use crate::rcc::sealed::RccPeripheral; 22use crate::rcc::SealedRccPeripheral;
24use crate::{interrupt, Peripheral}; 23use 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
276unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> { 275unsafe 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
306impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { 305impl<'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
8pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing}; 8pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing};
9use super::*; 9use super::*;
10use crate::gpio::sealed::{AFType, Pin as _}; 10use crate::gpio::{AFType, AnyPin, SealedPin as _, Speed};
11use crate::gpio::{AnyPin, Speed};
12use crate::interrupt::InterruptExt; 11use crate::interrupt::InterruptExt;
13use crate::pac::ETH; 12use crate::pac::ETH;
14use crate::rcc::sealed::RccPeripheral; 13use crate::rcc::SealedRccPeripheral;
15use crate::{interrupt, Peripheral}; 14use 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
335unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> { 334unsafe 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
365impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { 364impl<'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
331foreach_exti_irq!(impl_irq); 331foreach_exti_irq!(impl_irq);
332 332
333pub(crate) mod sealed { 333trait SealedChannel {}
334 pub trait Channel {}
335}
336 334
337/// EXTI channel trait. 335/// EXTI channel trait.
338pub trait Channel: sealed::Channel + Sized { 336#[allow(private_bounds)]
337pub 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
361impl_peripheral!(AnyChannel); 360impl_peripheral!(AnyChannel);
362impl sealed::Channel for AnyChannel {} 361impl SealedChannel for AnyChannel {}
363impl Channel for AnyChannel { 362impl 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
369macro_rules! impl_exti { 368macro_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
4use embassy_hal_internal::into_ref; 4use embassy_hal_internal::into_ref;
5 5
6use crate::gpio::sealed::AFType; 6use crate::gpio::{AFType, Pull, Speed};
7use crate::gpio::{Pull, Speed};
8use crate::Peripheral; 7use 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
204pub(crate) mod sealed { 203trait 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.
211pub trait Instance: sealed::Instance + 'static {} 208#[allow(private_bounds)]
209pub trait Instance: SealedInstance + 'static {}
212 210
213foreach_peripheral!( 211foreach_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;
6use critical_section::CriticalSection; 6use critical_section::CriticalSection;
7use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef}; 7use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef};
8 8
9use self::sealed::Pin as _;
10use crate::pac::gpio::{self, vals}; 9use crate::pac::gpio::{self, vals};
11use crate::{pac, peripherals, Peripheral}; 10use 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
511impl From<OutputType> for sealed::AFType { 522impl 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
521pub(crate) mod sealed { 532#[derive(Debug, Copy, Clone)]
522 use super::*; 533#[cfg_attr(feature = "defmt", derive(defmt::Format))]
523 534pub 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] 543pub(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.
676pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static { 682#[allow(private_bounds)]
683pub 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}
740impl sealed::Pin for AnyPin { 747impl 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
770pub(crate) unsafe fn init(_cs: CriticalSection) { 777pub(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")]
1067pub 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;
17use crate::dma::Transfer; 17use crate::dma::Transfer;
18use crate::interrupt::typelevel::Interrupt; 18use crate::interrupt::typelevel::Interrupt;
19use crate::peripherals::HASH; 19use crate::peripherals::HASH;
20use crate::rcc::sealed::RccPeripheral; 20use crate::rcc::SealedRccPeripheral;
21use crate::{interrupt, pac, peripherals, Peripheral}; 21use 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
564pub(crate) mod sealed { 564trait 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.
573pub trait Instance: sealed::Instance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send { 569#[allow(private_bounds)]
570pub 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;
7use embassy_hal_internal::{into_ref, PeripheralRef}; 7use embassy_hal_internal::{into_ref, PeripheralRef};
8pub use traits::Instance; 8pub use traits::Instance;
9 9
10#[allow(unused_imports)] 10use crate::gpio::{AFType, AnyPin};
11use crate::gpio::sealed::{AFType, Pin};
12use crate::gpio::AnyPin;
13use crate::time::Hertz; 11use crate::time::Hertz;
14use crate::Peripheral; 12use 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
57mod sealed { 55trait 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.
66pub trait AdvancedChannel<T: Instance>: sealed::AdvancedChannel<T> {} 60#[allow(private_bounds)]
61pub trait AdvancedChannel<T: Instance>: SealedAdvancedChannel<T> {}
67 62
68/// HRTIM PWM pin. 63/// HRTIM PWM pin.
69pub struct PwmPin<'d, T, C> { 64pub 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 @@
1use crate::rcc::sealed::RccPeripheral; 1use crate::rcc::RccPeripheral;
2use crate::time::Hertz; 2use crate::time::Hertz;
3 3
4#[repr(u8)] 4#[repr(u8)]
@@ -72,94 +72,92 @@ impl Prescaler {
72 } 72 }
73} 73}
74 74
75pub(crate) mod sealed { 75pub(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.
158pub trait Instance: sealed::Instance + 'static {} 155#[allow(private_bounds)]
156pub trait Instance: SealedInstance + 'static {}
159 157
160foreach_interrupt! { 158foreach_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;
14use embassy_time::{Duration, Instant}; 14use embassy_time::{Duration, Instant};
15 15
16use crate::dma::NoDma; 16use crate::dma::NoDma;
17use crate::gpio::sealed::AFType; 17use crate::gpio::{AFType, Pull};
18use crate::gpio::Pull;
19use crate::interrupt::typelevel::Interrupt; 18use crate::interrupt::typelevel::Interrupt;
20use crate::time::Hertz; 19use crate::time::Hertz;
21use crate::{interrupt, peripherals}; 20use crate::{interrupt, peripherals};
@@ -175,30 +174,27 @@ impl Timeout {
175 } 174 }
176} 175}
177 176
178pub(crate) mod sealed { 177struct 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 { 182impl 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 { 190trait 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
201pub trait Instance: sealed::Instance + 'static { 196#[allow(private_bounds)]
197pub 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
235foreach_peripheral!( 231foreach_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)
2use embassy_hal_internal::into_ref; 2use embassy_hal_internal::into_ref;
3 3
4use crate::gpio::sealed::{AFType, Pin as _}; 4use crate::gpio::{AFType, AnyPin, SealedPin};
5use crate::gpio::AnyPin;
6use crate::pac::spi::vals; 5use crate::pac::spi::vals;
7use crate::spi::{Config as SpiConfig, *}; 6use crate::spi::{Config as SpiConfig, *};
8use crate::time::Hertz; 7use 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;
4use core::sync::atomic::{compiler_fence, Ordering}; 4use core::sync::atomic::{compiler_fence, Ordering};
5use core::task::Poll; 5use core::task::Poll;
6 6
7use self::sealed::Instance; 7use embassy_sync::waitqueue::AtomicWaker;
8
8use crate::interrupt; 9use crate::interrupt;
9use crate::interrupt::typelevel::Interrupt; 10use crate::interrupt::typelevel::Interrupt;
10use crate::peripherals::IPCC; 11use crate::peripherals::IPCC;
11use crate::rcc::sealed::RccPeripheral; 12use crate::rcc::SealedRccPeripheral;
12 13
13/// Interrupt handler. 14/// Interrupt handler.
14pub struct ReceiveInterruptHandler {} 15pub struct ReceiveInterruptHandler {}
@@ -207,7 +208,7 @@ impl Ipcc {
207 } 208 }
208} 209}
209 210
210impl sealed::Instance for crate::peripherals::IPCC { 211impl 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
225pub(crate) mod sealed { 226struct 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 { 231impl 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 { 264trait 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;
158use crate::interrupt::Priority; 158use crate::interrupt::Priority;
159#[cfg(feature = "rt")] 159#[cfg(feature = "rt")]
160pub use crate::pac::NVIC_PRIO_BITS; 160pub use crate::pac::NVIC_PRIO_BITS;
161use crate::rcc::sealed::RccPeripheral; 161use 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. 169pub(crate) trait SealedInstance {
170pub trait Instance: sealed::Instance + 'static {} 170 fn regs() -> crate::pac::opamp::Opamp;
171 171}
172pub(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> { 173pub(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> {} 177pub(crate) trait SealedInvertingPin<T: Instance> {
178 #[allow(unused)]
179 fn channel(&self) -> u8;
186} 180}
187 181
182pub(crate) trait SealedOutputPin<T: Instance> {}
183
184/// Opamp instance trait.
185#[allow(private_bounds)]
186pub trait Instance: SealedInstance + 'static {}
188/// Non-inverting pin trait. 187/// Non-inverting pin trait.
189pub trait NonInvertingPin<T: Instance>: sealed::NonInvertingPin<T> {} 188#[allow(private_bounds)]
189pub trait NonInvertingPin<T: Instance>: SealedNonInvertingPin<T> {}
190/// Inverting pin trait. 190/// Inverting pin trait.
191pub trait InvertingPin<T: Instance>: sealed::InvertingPin<T> {} 191#[allow(private_bounds)]
192pub trait InvertingPin<T: Instance>: SealedInvertingPin<T> {}
192/// Output pin trait. 193/// Output pin trait.
193pub trait OutputPin<T: Instance>: sealed::OutputPin<T> {} 194#[allow(private_bounds)]
195pub trait OutputPin<T: Instance>: SealedOutputPin<T> {}
194 196
195macro_rules! impl_opamp_external_output { 197macro_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
292foreach_peripheral! { 294foreach_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! {
306macro_rules! impl_opamp_vp_pin { 308macro_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 {
318macro_rules! impl_opamp_vout_pin { 320macro_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};
8use enums::*; 8use enums::*;
9 9
10use crate::dma::Transfer; 10use crate::dma::Transfer;
11use crate::gpio::sealed::AFType; 11use crate::gpio::{AFType, AnyPin, Pull};
12use crate::gpio::{AnyPin, Pull};
13use crate::pac::quadspi::Quadspi as Regs; 12use crate::pac::quadspi::Quadspi as Regs;
14use crate::rcc::RccPeripheral; 13use crate::rcc::RccPeripheral;
15use crate::{peripherals, Peripheral}; 14use crate::{peripherals, Peripheral};
@@ -381,16 +380,13 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
381 } 380 }
382} 381}
383 382
384pub(crate) mod sealed { 383trait 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.
393pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} 388#[allow(private_bounds)]
389pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {}
394 390
395pin_trait!(SckPin, Instance); 391pin_trait!(SckPin, Instance);
396pin_trait!(BK1D0Pin, Instance); 392pin_trait!(BK1D0Pin, Instance);
@@ -409,7 +405,7 @@ dma_trait!(QuadDma, Instance);
409 405
410foreach_peripheral!( 406foreach_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
3use crate::pac::crs::vals::Syncsrc; 3use crate::pac::crs::vals::Syncsrc;
4use crate::pac::{CRS, RCC}; 4use crate::pac::{CRS, RCC};
5use crate::rcc::sealed::RccPeripheral; 5use crate::rcc::SealedRccPeripheral;
6use crate::time::Hertz; 6use 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
3use embassy_hal_internal::into_ref; 3use embassy_hal_internal::into_ref;
4 4
5use crate::gpio::sealed::AFType; 5use crate::gpio::{AFType, Speed};
6use 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)))]
8pub use crate::pac::rcc::vals::Mcopre as McoPrescaler; 7pub 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
22pub(crate) mod sealed { 21pub(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
29pub trait McoInstance: sealed::McoInstance + 'static {} 23#[allow(private_bounds)]
24pub 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
31pin_trait!(McoPin, McoInstance); 31pin_trait!(McoPin, McoInstance);
32 32
33macro_rules! impl_peri { 33macro_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))]
12mod mco; 12mod mco;
13use critical_section::CriticalSection;
13#[cfg(any(mco, mco1, mco2))] 14#[cfg(any(mco, mco1, mco2))]
14pub use mco::*; 15pub use mco::*;
15 16
@@ -32,6 +33,7 @@ mod _version;
32pub use _version::*; 33pub use _version::*;
33 34
34pub use crate::_generated::{mux, Clocks}; 35pub use crate::_generated::{mux, Clocks};
36use 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")] 68pub(crate) trait SealedRccPeripheral {
67pub 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
71pub(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
88pub trait RccPeripheral: sealed::RccPeripheral + 'static {} 81#[allow(private_bounds)]
82pub trait RccPeripheral: SealedRccPeripheral + 'static {}
89 83
90#[allow(unused)] 84#[allow(unused)]
91mod util { 85mod 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.
119pub 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
223impl<'d, T: Instance> CryptoRng for Rng<'d, T> {} 223impl<'d, T: Instance> CryptoRng for Rng<'d, T> {}
224 224
225pub(crate) mod sealed { 225trait 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.
234pub trait Instance: sealed::Instance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send { 230#[allow(private_bounds)]
231pub 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"))]
5use crate::peripherals::RTC; 5use crate::peripherals::RTC;
6#[cfg(any(feature = "defmt", feature = "time"))] 6#[cfg(any(feature = "defmt", feature = "time"))]
7use crate::rtc::sealed::Instance; 7use 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
10pub struct RtcInstant { 10pub 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::*;
31use embassy_hal_internal::Peripheral; 31use embassy_hal_internal::Peripheral;
32 32
33use crate::peripherals::RTC; 33use crate::peripherals::RTC;
34use 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
480pub(crate) mod sealed { 479trait 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 @@
1use stm32_metapac::rtc::vals::{Osel, Pol}; 1use stm32_metapac::rtc::vals::{Osel, Pol};
2 2
3use super::sealed; 3use super::SealedInstance;
4use crate::pac::rtc::Rtc; 4use crate::pac::rtc::Rtc;
5use crate::peripherals::RTC; 5use crate::peripherals::RTC;
6use crate::rtc::sealed::Instance;
7 6
8#[allow(dead_code)] 7#[allow(dead_code)]
9impl super::Rtc { 8impl super::Rtc {
@@ -126,7 +125,7 @@ impl super::Rtc {
126 } 125 }
127} 126}
128 127
129impl sealed::Instance for crate::peripherals::RTC { 128impl 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 @@
1use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Key, Osel, Pol, TampalrmType}; 1use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Key, Osel, Pol, TampalrmType};
2 2
3use super::{sealed, RtcCalibrationCyclePeriod}; 3use super::RtcCalibrationCyclePeriod;
4use crate::pac::rtc::Rtc; 4use crate::pac::rtc::Rtc;
5use crate::peripherals::RTC; 5use crate::peripherals::RTC;
6use crate::rtc::sealed::Instance; 6use crate::rtc::SealedInstance;
7 7
8impl super::Rtc { 8impl 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
129impl sealed::Instance for crate::peripherals::RTC { 129impl 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
7use embassy_hal_internal::{into_ref, PeripheralRef}; 7use embassy_hal_internal::{into_ref, PeripheralRef};
8 8
9use self::sealed::WhichSubBlock;
10pub use crate::dma::word; 9pub use crate::dma::word;
11#[cfg(not(gpdma))] 10#[cfg(not(gpdma))]
12use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer}; 11use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer};
13use crate::gpio::sealed::{AFType, Pin as _}; 12use crate::gpio::{AFType, AnyPin, SealedPin as _};
14use crate::gpio::AnyPin;
15use crate::pac::sai::{vals, Sai as Regs}; 13use crate::pac::sai::{vals, Sai as Regs};
16use crate::rcc::RccPeripheral; 14use crate::rcc::RccPeripheral;
17use crate::{peripherals, Peripheral}; 15use 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
1044pub(crate) mod sealed { 1042trait 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 { 1047enum WhichSubBlock {
1053 A = 0, 1048 A = 0,
1054 B = 1, 1049 B = 1,
1055 } 1050}
1056 1051
1057 pub trait SubBlock { 1052trait SealedSubBlock {
1058 const WHICH: WhichSubBlock; 1053 const WHICH: WhichSubBlock;
1059 }
1060} 1054}
1061 1055
1062/// Sub-block instance trait. 1056/// Sub-block instance trait.
1063pub trait SubBlockInstance: sealed::SubBlock {} 1057#[allow(private_bounds)]
1058pub trait SubBlockInstance: SealedSubBlock {}
1064 1059
1065/// Sub-block A. 1060/// Sub-block A.
1066pub enum A {} 1061pub enum A {}
1067impl sealed::SubBlock for A { 1062impl SealedSubBlock for A {
1068 const WHICH: WhichSubBlock = WhichSubBlock::A; 1063 const WHICH: WhichSubBlock = WhichSubBlock::A;
1069} 1064}
1070impl SubBlockInstance for A {} 1065impl SubBlockInstance for A {}
1071 1066
1072/// Sub-block B. 1067/// Sub-block B.
1073pub enum B {} 1068pub enum B {}
1074impl sealed::SubBlock for B { 1069impl SealedSubBlock for B {
1075 const WHICH: WhichSubBlock = WhichSubBlock::B; 1070 const WHICH: WhichSubBlock = WhichSubBlock::B;
1076} 1071}
1077impl SubBlockInstance for B {} 1072impl SubBlockInstance for B {}
1078 1073
1079/// SAI instance trait. 1074/// SAI instance trait.
1080pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} 1075#[allow(private_bounds)]
1076pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {}
1077
1081pin_trait!(SckPin, Instance, SubBlockInstance); 1078pin_trait!(SckPin, Instance, SubBlockInstance);
1082pin_trait!(FsPin, Instance, SubBlockInstance); 1079pin_trait!(FsPin, Instance, SubBlockInstance);
1083pin_trait!(SdPin, Instance, SubBlockInstance); 1080pin_trait!(SdPin, Instance, SubBlockInstance);
@@ -1087,7 +1084,7 @@ dma_trait!(Dma, Instance, SubBlockInstance);
1087 1084
1088foreach_peripheral!( 1085foreach_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;
13use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; 13use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR};
14 14
15use crate::dma::NoDma; 15use crate::dma::NoDma;
16use crate::gpio::sealed::{AFType, Pin}; 16use crate::gpio::{AFType, AnyPin, Pull, SealedPin, Speed};
17use crate::gpio::{AnyPin, Pull, Speed};
18use crate::interrupt::typelevel::Interrupt; 17use crate::interrupt::typelevel::Interrupt;
19use crate::pac::sdmmc::Sdmmc as RegBlock; 18use crate::pac::sdmmc::Sdmmc as RegBlock;
20use crate::rcc::RccPeripheral; 19use crate::rcc::RccPeripheral;
@@ -1418,19 +1417,17 @@ impl Cmd {
1418 1417
1419////////////////////////////////////////////////////// 1418//////////////////////////////////////////////////////
1420 1419
1421pub(crate) mod sealed { 1420trait 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.
1433pub trait Instance: sealed::Instance + RccPeripheral + 'static {} 1426#[allow(private_bounds)]
1427pub trait Instance: SealedInstance + RccPeripheral + 'static {
1428 /// Interrupt for this instance.
1429 type Interrupt: interrupt::typelevel::Interrupt;
1430}
1434 1431
1435pin_trait!(CkPin, Instance); 1432pin_trait!(CkPin, Instance);
1436pin_trait!(CmdPin, Instance); 1433pin_trait!(CmdPin, Instance);
@@ -1457,9 +1454,7 @@ impl<T: Instance> SdmmcDma<T> for NoDma {}
1457 1454
1458foreach_peripheral!( 1455foreach_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};
9pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; 9pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
10 10
11use crate::dma::{slice_ptr_parts, word, Transfer}; 11use crate::dma::{slice_ptr_parts, word, Transfer};
12use crate::gpio::sealed::{AFType, Pin as _}; 12use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _};
13use crate::gpio::{AnyPin, Pull};
14use crate::pac::spi::{regs, vals, Spi as Regs}; 13use crate::pac::spi::{regs, vals, Spi as Regs};
15use crate::rcc::RccPeripheral; 14use crate::rcc::RccPeripheral;
16use crate::time::Hertz; 15use 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
978pub(crate) mod sealed { 977pub(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 { 981trait 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.
991pub trait Word: word::Word + sealed::Word {} 986#[allow(private_bounds)]
987pub trait Word: word::Word + SealedWord {}
992 988
993macro_rules! impl_word { 989macro_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.
1071pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} 1067#[allow(private_bounds)]
1068pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {}
1072 1069
1073pin_trait!(SckPin, Instance); 1070pin_trait!(SckPin, Instance);
1074pin_trait!(MosiPin, Instance); 1071pin_trait!(MosiPin, Instance);
@@ -1082,7 +1079,7 @@ dma_trait!(TxDma, Instance);
1082 1079
1083foreach_peripheral!( 1080foreach_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;
8use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 8use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
9use embassy_sync::blocking_mutex::Mutex; 9use embassy_sync::blocking_mutex::Mutex;
10use embassy_time_driver::{AlarmHandle, Driver, TICK_HZ}; 10use embassy_time_driver::{AlarmHandle, Driver, TICK_HZ};
11use stm32_metapac::timer::regs; 11use stm32_metapac::timer::{regs, TimGp16};
12 12
13use crate::interrupt::typelevel::Interrupt; 13use crate::interrupt::typelevel::Interrupt;
14use crate::pac::timer::vals; 14use crate::pac::timer::vals;
15use crate::rcc::sealed::RccPeripheral; 15use crate::rcc::SealedRccPeripheral;
16#[cfg(feature = "low-power")] 16#[cfg(feature = "low-power")]
17use crate::rtc::Rtc; 17use 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))]
19use crate::timer::sealed::AdvancedControlInstance; 19use crate::timer::AdvancedInstance1Channel;
20use crate::timer::sealed::{CoreInstance, GeneralPurpose16bitInstance as Instance}; 20use crate::timer::CoreInstance;
21use crate::{interrupt, peripherals}; 21use 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
210fn 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
272impl RtcDriver { 276impl 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
523impl Driver for RtcDriver { 527impl 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;
5use embassy_hal_internal::{into_ref, PeripheralRef}; 5use embassy_hal_internal::{into_ref, PeripheralRef};
6use stm32_metapac::timer::vals::Ckd; 6use stm32_metapac::timer::vals::Ckd;
7 7
8use super::simple_pwm::*; 8use super::low_level::{CountingMode, OutputPolarity, Timer};
9use super::*; 9use super::simple_pwm::{Ch1, Ch2, Ch3, Ch4, PwmPin};
10#[allow(unused_imports)] 10use super::{
11use crate::gpio::sealed::{AFType, Pin}; 11 AdvancedInstance4Channel, Channel, Channel1ComplementaryPin, Channel2ComplementaryPin, Channel3ComplementaryPin,
12 Channel4ComplementaryPin,
13};
12use crate::gpio::{AnyPin, OutputType}; 14use crate::gpio::{AnyPin, OutputType};
15use crate::time::Hertz;
16use crate::timer::low_level::OutputCompareMode;
13use crate::Peripheral; 17use 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
23macro_rules! complementary_channel_impl { 27macro_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);
47complementary_channel_impl!(new_ch4, Ch4, Channel4ComplementaryPin); 51complementary_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.
50pub struct ComplementaryPwm<'d, T> { 54pub struct ComplementaryPwm<'d, T: AdvancedInstance4Channel> {
51 inner: PeripheralRef<'d, T>, 55 inner: Timer<'d, T>,
52} 56}
53 57
54impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { 58impl<'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
151impl<'d, T: ComplementaryCaptureCompare16bitInstance> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> { 151impl<'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
9use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
10
11use super::*;
12use crate::pac::timer::vals;
13use crate::time::Hertz;
14
15/// Input capture mode.
16#[derive(Clone, Copy)]
17pub 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)]
28pub enum InputTISelection {
29 /// Normal
30 Normal,
31 /// Alternate
32 Alternate,
33 /// TRC
34 TRC,
35}
36
37impl 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)]
50pub 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
73impl 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
90impl 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
102impl 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)]
116pub 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
144impl 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)]
161pub 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
168impl 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.
178pub struct Timer<'d, T: CoreInstance> {
179 tim: PeripheralRef<'d, T>,
180}
181
182impl<'d, T: CoreInstance> Drop for Timer<'d, T> {
183 fn drop(&mut self) {
184 T::disable()
185 }
186}
187
188impl<'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
323impl<'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
345impl<'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
357impl<'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
383impl<'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
395impl<'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))]
565impl<'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))]
578impl<'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))]
606impl<'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))]
619impl<'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))]
35pub mod complementary_pwm; 4pub mod complementary_pwm;
5pub mod low_level;
36pub mod qei; 6pub mod qei;
37pub mod simple_pwm; 7pub mod simple_pwm;
38 8
39use stm32_metapac::timer::vals;
40
41use crate::interrupt; 9use crate::interrupt;
42use crate::rcc::RccPeripheral; 10use crate::rcc::RccPeripheral;
43use crate::time::Hertz;
44
45/// Low-level timer access.
46#[cfg(feature = "unstable-pac")]
47pub mod low_level {
48 pub use super::sealed::*;
49}
50
51pub(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)]
516pub enum InputCaptureMode { 39#[cfg_attr(feature = "defmt", derive(defmt::Format))]
517 /// Rising edge only. 40pub 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)] 49pub trait CoreInstance: RccPeripheral + 'static {
527pub 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
536impl 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)]
549pub 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
572impl 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
589impl 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
601impl 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)]
615pub 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
643impl 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.
62pub trait BasicNoCr2Instance: CoreInstance {}
63/// Basic timer instance.
64pub trait BasicInstance: BasicNoCr2Instance {}
657 65
658/// Timer output pin polarity. 66/// General-purpose 16-bit timer with 1 channel instance.
659#[derive(Clone, Copy)] 67pub trait GeneralInstance1Channel: CoreInstance {}
660pub 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
667impl From<OutputPolarity> for bool { 69/// General-purpose 16-bit timer with 2 channels instance.
668 fn from(mode: OutputPolarity) -> Self { 70pub 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.
677pub trait BasicInstance: sealed::BasicInstance + sealed::BasicNoCr2Instance + sealed::CoreInstance + 'static {} 73pub 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.
681pub 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. 84pub trait GeneralInstance32bit4Channel: GeneralInstance4Channel {}
699/// Capture Compare 32-bit timer instance.
700pub 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.
708pub trait ComplementaryCaptureCompare16bitInstance:
709 CaptureCompare16bitInstance
710 + sealed::GeneralPurpose1ChannelComplementaryInstance
711 + sealed::GeneralPurpose2ChannelComplementaryInstance
712 + sealed::AdvancedControlInstance
713 + 'static
714{
715}
716
717pin_trait!(Channel1Pin, CaptureCompare16bitInstance);
718pin_trait!(Channel2Pin, CaptureCompare16bitInstance);
719pin_trait!(Channel3Pin, CaptureCompare16bitInstance);
720pin_trait!(Channel4Pin, CaptureCompare16bitInstance);
721pin_trait!(ExternalTriggerPin, CaptureCompare16bitInstance);
722
723cfg_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); 87pub 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)] 93pub trait AdvancedInstance2Channel: BasicInstance + GeneralInstance2Channel + AdvancedInstance1Channel {}
742macro_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()) } 96pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {}
749 }
750 }
751 };
752}
753 97
754#[allow(unused)] 98pin_trait!(Channel1Pin, GeneralInstance4Channel);
755macro_rules! impl_basic_no_cr2_timer { 99pin_trait!(Channel2Pin, GeneralInstance4Channel);
756 ($inst:ident) => { 100pin_trait!(Channel3Pin, GeneralInstance4Channel);
757 impl sealed::BasicNoCr2Instance for crate::peripherals::$inst { 101pin_trait!(Channel4Pin, GeneralInstance4Channel);
758 fn regs_basic_no_cr2() -> crate::pac::timer::TimBasicNoCr2 { 102pin_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)] 104pin_trait!(Channel1ComplementaryPin, AdvancedInstance4Channel);
766macro_rules! impl_basic_timer { 105pin_trait!(Channel2ComplementaryPin, AdvancedInstance4Channel);
767 ($inst:ident) => { 106pin_trait!(Channel3ComplementaryPin, AdvancedInstance4Channel);
768 impl sealed::BasicInstance for crate::peripherals::$inst { 107pin_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)] 109pin_trait!(BreakInputPin, AdvancedInstance4Channel);
777macro_rules! impl_1ch_timer { 110pin_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)] 112pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel);
788macro_rules! impl_2ch_timer { 113pin_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)] 115pin_trait!(BreakInput2Comparator1Pin, AdvancedInstance4Channel);
799macro_rules! impl_gp16_timer { 116pin_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
810macro_rules! impl_gp32_timer { 119dma_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)] 121dma_trait!(Ch1Dma, GeneralInstance4Channel);
821macro_rules! impl_1ch_cmp_timer { 122dma_trait!(Ch2Dma, GeneralInstance4Channel);
822 ($inst:ident) => { 123dma_trait!(Ch3Dma, GeneralInstance4Channel);
823 impl sealed::GeneralPurpose1ChannelComplementaryInstance for crate::peripherals::$inst { 124dma_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)]
832macro_rules! impl_2ch_cmp_timer { 127macro_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;
843macro_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
855foreach_interrupt! { 141foreach_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))]
984dma_trait!(UpDma, BasicInstance); 223#[allow(unused)]
985 224fn set_moe<T: GeneralInstance4Channel>() {
986dma_trait!(Ch1Dma, CaptureCompare16bitInstance); 225 unsafe { crate::pac::timer::Tim1chCmp::from_ptr(T::regs()) }
987dma_trait!(Ch2Dma, CaptureCompare16bitInstance); 226 .bdtr()
988dma_trait!(Ch3Dma, CaptureCompare16bitInstance); 227 .modify(|w| w.set_moe(true));
989dma_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 @@
3use core::marker::PhantomData; 3use core::marker::PhantomData;
4 4
5use embassy_hal_internal::{into_ref, PeripheralRef}; 5use embassy_hal_internal::{into_ref, PeripheralRef};
6use stm32_metapac::timer::vals;
6 7
7use super::*; 8use super::low_level::Timer;
8use crate::gpio::sealed::AFType; 9use super::{Channel1Pin, Channel2Pin, GeneralInstance4Channel};
9use crate::gpio::AnyPin; 10use crate::gpio::{AFType, AnyPin};
10use crate::Peripheral; 11use crate::Peripheral;
11 12
12/// Counting direction 13/// Counting direction
@@ -30,7 +31,7 @@ pub struct QeiPin<'d, T, Channel> {
30 31
31macro_rules! channel_impl { 32macro_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);
53channel_impl!(new_ch2, Ch2, Channel2Pin); 54channel_impl!(new_ch2, Ch2, Channel2Pin);
54 55
55/// Quadrature decoder driver. 56/// Quadrature decoder driver.
56pub struct Qei<'d, T> { 57pub struct Qei<'d, T: GeneralInstance4Channel> {
57 _inner: PeripheralRef<'d, T>, 58 inner: Timer<'d, T>,
58} 59}
59 60
60impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> { 61impl<'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
5use embassy_hal_internal::{into_ref, PeripheralRef}; 5use embassy_hal_internal::{into_ref, PeripheralRef};
6 6
7use super::*; 7use super::low_level::{CountingMode, OutputCompareMode, OutputPolarity, Timer};
8#[allow(unused_imports)] 8use super::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance4Channel};
9use crate::gpio::sealed::{AFType, Pin};
10use crate::gpio::{AnyPin, OutputType}; 9use crate::gpio::{AnyPin, OutputType};
10use crate::time::Hertz;
11use crate::Peripheral; 11use 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
30macro_rules! channel_impl { 30macro_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);
54channel_impl!(new_ch4, Ch4, Channel4Pin); 54channel_impl!(new_ch4, Ch4, Channel4Pin);
55 55
56/// Simple PWM driver. 56/// Simple PWM driver.
57pub struct SimplePwm<'d, T> { 57pub struct SimplePwm<'d, T: GeneralInstance4Channel> {
58 inner: PeripheralRef<'d, T>, 58 inner: Timer<'d, T>,
59} 59}
60 60
61impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { 61impl<'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
228macro_rules! impl_waveform_chx { 222macro_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);
314impl_waveform_chx!(waveform_ch3, Ch3Dma, Ch3); 306impl_waveform_chx!(waveform_ch3, Ch3Dma, Ch3);
315impl_waveform_chx!(waveform_ch4, Ch4Dma, Ch4); 307impl_waveform_chx!(waveform_ch4, Ch4Dma, Ch4);
316 308
317impl<'d, T: CaptureCompare16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d, T> { 309impl<'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
17use core::future::poll_fn; 17use core::future::poll_fn;
18use core::marker::PhantomData; 18use core::marker::PhantomData;
19use core::sync::atomic::Ordering; 19use core::sync::atomic::{AtomicBool, Ordering};
20use core::task::Poll; 20use core::task::Poll;
21 21
22use embassy_hal_internal::drop::OnDrop; 22use embassy_hal_internal::drop::OnDrop;
23use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; 23use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
24use embassy_sync::waitqueue::AtomicWaker;
24 25
25use crate::dma::{AnyChannel, Request, Transfer, TransferOptions}; 26use crate::dma::{AnyChannel, Request, Transfer, TransferOptions};
26use crate::interrupt; 27use 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. 559struct State {
559pub 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.
561mod 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 { 565impl 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 { 574trait 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)]
581pub trait Instance: SealedInstance + RccPeripheral {
582 /// Interrupt for this instance.
583 type Interrupt: crate::interrupt::typelevel::Interrupt;
586} 584}
587 585
588foreach_interrupt!( 586foreach_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;
10use embassy_embedded_hal::SetConfig; 10use embassy_embedded_hal::SetConfig;
11use embassy_hal_internal::drop::OnDrop; 11use embassy_hal_internal::drop::OnDrop;
12use embassy_hal_internal::{into_ref, PeripheralRef}; 12use embassy_hal_internal::{into_ref, PeripheralRef};
13use embassy_sync::waitqueue::AtomicWaker;
13use futures::future::{select, Either}; 14use futures::future::{select, Either};
14 15
15use crate::dma::{NoDma, Transfer}; 16use crate::dma::{NoDma, Transfer};
16use crate::gpio::sealed::AFType; 17use crate::gpio::AFType;
17use crate::interrupt::typelevel::Interrupt; 18use 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))]
1327pub use ringbuffered::RingBufferedUartRx; 1328pub use ringbuffered::RingBufferedUartRx;
1328 1329
1329use self::sealed::Kind;
1330
1331#[cfg(any(usart_v1, usart_v2))] 1330#[cfg(any(usart_v1, usart_v2))]
1332fn tdr(r: crate::pac::usart::Usart) -> *mut u8 { 1331fn 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
1373pub(crate) mod sealed { 1372#[derive(Clone, Copy, PartialEq, Eq)]
1374 use embassy_sync::waitqueue::AtomicWaker; 1373enum 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 { 1380struct State {
1386 pub rx_waker: AtomicWaker, 1381 rx_waker: AtomicWaker,
1387 pub tx_waker: AtomicWaker, 1382}
1388 }
1389 1383
1390 impl State { 1384impl 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 { 1392trait 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 { 1401trait 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
1415pub trait BasicInstance: Peripheral<P = Self> + sealed::BasicInstance + 'static + Send {} 1407#[allow(private_bounds)]
1408pub 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
1418pub trait FullInstance: sealed::FullInstance {} 1414#[allow(private_bounds)]
1415pub trait FullInstance: SealedFullInstance {}
1419 1416
1420pin_trait!(RxPin, BasicInstance); 1417pin_trait!(RxPin, BasicInstance);
1421pin_trait!(TxPin, BasicInstance); 1418pin_trait!(TxPin, BasicInstance);
@@ -1429,16 +1426,15 @@ dma_trait!(RxDma, BasicInstance);
1429 1426
1430macro_rules! impl_usart { 1427macro_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;
6pub use _version::*; 6pub use _version::*;
7 7
8use crate::interrupt::typelevel::Interrupt; 8use crate::interrupt::typelevel::Interrupt;
9use crate::rcc::sealed::RccPeripheral; 9use 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.
12fn common_init<T: Instance>() { 12fn 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};
12use futures::future::poll_fn; 12use futures::future::poll_fn;
13 13
14use crate::gpio::sealed::AFType; 14use crate::gpio::AFType;
15use crate::interrupt; 15use crate::interrupt;
16use crate::interrupt::typelevel::Interrupt; 16use crate::interrupt::typelevel::Interrupt;
17use crate::pac::otg::{regs, vals}; 17use crate::pac::otg::{regs, vals};
18use crate::rcc::sealed::RccPeripheral; 18use crate::rcc::{RccPeripheral, SealedRccPeripheral};
19use crate::time::Hertz; 19use 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
1437const MAX_EP_COUNT: usize = 9; 1437const MAX_EP_COUNT: usize = 9;
1438 1438
1439pub(crate) mod sealed { 1439trait 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.
1451pub trait Instance: sealed::Instance + RccPeripheral + 'static { 1449#[allow(private_bounds)]
1450pub 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
1474foreach_interrupt!( 1473foreach_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::{
15use crate::pac::usb::regs; 15use crate::pac::usb::regs;
16use crate::pac::usb::vals::{EpType, Stat}; 16use crate::pac::usb::vals::{EpType, Stat};
17use crate::pac::USBRAM; 17use crate::pac::USBRAM;
18use crate::rcc::sealed::RccPeripheral; 18use crate::rcc::RccPeripheral;
19use crate::{interrupt, Peripheral}; 19use 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
1040pub(crate) mod sealed { 1040trait 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.
1047pub trait Instance: sealed::Instance + RccPeripheral + 'static { 1045#[allow(private_bounds)]
1046pub 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
1056foreach_interrupt!( 1055foreach_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
83mod sealed { 83trait 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.
90pub trait Instance: sealed::Instance {} 88#[allow(private_bounds)]
89pub trait Instance: SealedInstance {}
91 90
92foreach_peripheral!( 91foreach_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 @@
15use embassy_executor::Spawner; 15use embassy_executor::Spawner;
16use embassy_stm32::gpio::OutputType; 16use embassy_stm32::gpio::OutputType;
17use embassy_stm32::time::khz; 17use embassy_stm32::time::khz;
18use embassy_stm32::timer::low_level::CountingMode;
18use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; 19use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
19use embassy_stm32::timer::{Channel, CountingMode}; 20use embassy_stm32::timer::Channel;
20use embassy_time::{Duration, Ticker, Timer}; 21use embassy_time::{Duration, Ticker, Timer};
21use {defmt_rtt as _, panic_probe as _}; 22use {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;
6use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; 6use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray};
7use embassy_stm32::pac::timer::vals::Mms; 7use embassy_stm32::pac::timer::vals::Mms;
8use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; 8use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7};
9use embassy_stm32::rcc::low_level::RccPeripheral; 9use embassy_stm32::rcc::frequency;
10use embassy_stm32::time::Hertz; 10use embassy_stm32::time::Hertz;
11use embassy_stm32::timer::low_level::BasicInstance; 11use embassy_stm32::timer::low_level::Timer;
12use micromath::F32Ext; 12use micromath::F32Ext;
13use {defmt_rtt as _, panic_probe as _}; 13use {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]
59async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { 59async 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]
102async fn dac_task2(mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { 102async 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
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::gpio::low_level::AFType; 6use embassy_stm32::gpio::{AFType, Flex, Pull, Speed};
7use embassy_stm32::gpio::Speed;
8use embassy_stm32::time::{khz, Hertz}; 7use embassy_stm32::time::{khz, Hertz};
9use embassy_stm32::timer::*; 8use embassy_stm32::timer::low_level::{OutputCompareMode, Timer as LLTimer};
10use embassy_stm32::{into_ref, Config, Peripheral, PeripheralRef}; 9use embassy_stm32::timer::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance32bit4Channel};
10use embassy_stm32::{into_ref, Config, Peripheral};
11use embassy_time::Timer; 11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 12use {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}
59pub struct SimplePwm32<'d, T: CaptureCompare32bitInstance> { 59pub 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
63impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> { 67impl<'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;
6use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; 6use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray};
7use embassy_stm32::pac::timer::vals::Mms; 7use embassy_stm32::pac::timer::vals::Mms;
8use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; 8use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7};
9use embassy_stm32::rcc::low_level::RccPeripheral; 9use embassy_stm32::rcc::frequency;
10use embassy_stm32::time::Hertz; 10use embassy_stm32::time::Hertz;
11use embassy_stm32::timer::low_level::BasicInstance; 11use embassy_stm32::timer::low_level::Timer;
12use micromath::F32Ext; 12use micromath::F32Ext;
13use {defmt_rtt as _, panic_probe as _}; 13use {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]
30async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { 30async 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]
73async fn dac_task2(mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { 73async 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,