aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2022-02-10 02:34:59 +0100
committerDario Nieuwenhuis <[email protected]>2022-02-10 02:38:10 +0100
commit550da471be7b56927b50b5955a6de0916ebe6b1f (patch)
tree27b37e111dce9a3a5327c901c1bf139b1c1486d0
parent1d265b73b2f46baf60a481c8b8036e50c2b6583f (diff)
stm32: Remove OptionalPin
The idea behind OptionalPin has a few problems: - you need to impl the signal traits for NoPin which is a bit weird https://github.com/embassy-rs/embassy/blob/master/embassy-stm32/src/dcmi.rs#L413-L416 - you can pass any combination of set/unset pins, which needs checking at runtime https://github.com/embassy-rs/embassy/blob/master/embassy-stm32/src/dcmi.rs#L130 The replacement is to do multiple `new` constructors for each combination of pins you want to take.
-rw-r--r--embassy-stm32/src/dac/mod.rs8
-rw-r--r--embassy-stm32/src/dac/v2.rs221
-rw-r--r--embassy-stm32/src/dcmi.rs314
-rw-r--r--embassy-stm32/src/gpio.rs48
-rw-r--r--embassy-stm32/src/pwm/mod.rs25
-rw-r--r--embassy-stm32/src/pwm/pins.rs70
-rw-r--r--embassy-stm32/src/pwm/simple_pwm.rs64
-rw-r--r--embassy-stm32/src/spi/mod.rs169
-rw-r--r--embassy-stm32/src/subghz/mod.rs10
-rw-r--r--examples/stm32g4/src/bin/pwm.rs3
-rw-r--r--examples/stm32h7/src/bin/camera.rs33
-rw-r--r--examples/stm32h7/src/bin/dac.rs3
-rw-r--r--examples/stm32h7/src/bin/low_level_timer_api.rs3
-rw-r--r--examples/stm32h7/src/bin/pwm.rs3
-rw-r--r--examples/stm32l4/src/bin/dac.rs3
15 files changed, 546 insertions, 431 deletions
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs
index a54c40833..1acb0a9ae 100644
--- a/embassy-stm32/src/dac/mod.rs
+++ b/embassy-stm32/src/dac/mod.rs
@@ -3,27 +3,21 @@
3#[cfg_attr(dac_v1, path = "v1.rs")] 3#[cfg_attr(dac_v1, path = "v1.rs")]
4#[cfg_attr(dac_v2, path = "v2.rs")] 4#[cfg_attr(dac_v2, path = "v2.rs")]
5mod _version; 5mod _version;
6use crate::gpio::NoPin;
7use crate::peripherals; 6use crate::peripherals;
8pub use _version::*; 7pub use _version::*;
9 8
10pub(crate) mod sealed { 9pub(crate) mod sealed {
11 use crate::gpio::OptionalPin;
12
13 pub trait Instance { 10 pub trait Instance {
14 fn regs() -> &'static crate::pac::dac::Dac; 11 fn regs() -> &'static crate::pac::dac::Dac;
15 } 12 }
16 13
17 pub trait DacPin<T: Instance, const C: u8>: OptionalPin {} 14 pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin {}
18} 15}
19 16
20pub trait Instance: sealed::Instance + 'static {} 17pub trait Instance: sealed::Instance + 'static {}
21 18
22pub trait DacPin<T: Instance, const C: u8>: sealed::DacPin<T, C> + 'static {} 19pub trait DacPin<T: Instance, const C: u8>: sealed::DacPin<T, C> + 'static {}
23 20
24impl<T: Instance, const C: u8> DacPin<T, C> for NoPin {}
25impl<T: Instance, const C: u8> sealed::DacPin<T, C> for NoPin {}
26
27crate::pac::peripherals!( 21crate::pac::peripherals!(
28 (dac, $inst:ident) => { 22 (dac, $inst:ident) => {
29 impl crate::dac::sealed::Instance for peripherals::$inst { 23 impl crate::dac::sealed::Instance for peripherals::$inst {
diff --git a/embassy-stm32/src/dac/v2.rs b/embassy-stm32/src/dac/v2.rs
index 49da48e88..751eebf79 100644
--- a/embassy-stm32/src/dac/v2.rs
+++ b/embassy-stm32/src/dac/v2.rs
@@ -1,33 +1,25 @@
1use crate::dac::{DacPin, Instance}; 1use crate::dac::{DacPin, Instance};
2use crate::gpio::AnyPin;
3use crate::pac::dac; 2use crate::pac::dac;
4use core::marker::PhantomData; 3use core::marker::PhantomData;
5use embassy::util::Unborrow; 4use embassy::util::Unborrow;
6use embassy_hal_common::unborrow; 5use embassy_hal_common::unborrow;
7 6
8/// Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent DAC clock 7#[derive(Debug, Copy, Clone, Eq, PartialEq)]
9/// configuration.
10unsafe fn enable() {
11 #[cfg(rcc_h7)]
12 crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true));
13 #[cfg(rcc_g0)]
14 crate::pac::RCC.apbenr1().modify(|w| w.set_dac1en(true));
15 #[cfg(rcc_l4)]
16 crate::pac::RCC.apb1enr1().modify(|w| w.set_dac1en(true));
17}
18
19#[derive(Debug)]
20#[cfg_attr(feature = "defmt", derive(defmt::Format))] 8#[cfg_attr(feature = "defmt", derive(defmt::Format))]
21pub enum Error { 9pub enum Error {
22 UnconfiguredChannel, 10 UnconfiguredChannel,
23 InvalidValue, 11 InvalidValue,
24} 12}
25 13
14#[derive(Debug, Copy, Clone, Eq, PartialEq)]
15#[cfg_attr(feature = "defmt", derive(defmt::Format))]
26pub enum Channel { 16pub enum Channel {
27 Ch1, 17 Ch1,
28 Ch2, 18 Ch2,
29} 19}
30 20
21#[derive(Debug, Copy, Clone, Eq, PartialEq)]
22#[cfg_attr(feature = "defmt", derive(defmt::Format))]
31pub enum Ch1Trigger { 23pub enum Ch1Trigger {
32 Tim6, 24 Tim6,
33 Tim3, 25 Tim3,
@@ -52,6 +44,8 @@ impl Ch1Trigger {
52 } 44 }
53} 45}
54 46
47#[derive(Debug, Copy, Clone, Eq, PartialEq)]
48#[cfg_attr(feature = "defmt", derive(defmt::Format))]
55pub enum Ch2Trigger { 49pub enum Ch2Trigger {
56 Tim6, 50 Tim6,
57 Tim8, 51 Tim8,
@@ -78,46 +72,61 @@ impl Ch2Trigger {
78 } 72 }
79} 73}
80 74
75#[derive(Debug, Copy, Clone, Eq, PartialEq)]
76#[cfg_attr(feature = "defmt", derive(defmt::Format))]
81pub enum Alignment { 77pub enum Alignment {
82 Left, 78 Left,
83 Right, 79 Right,
84} 80}
85 81
82#[derive(Debug, Copy, Clone, Eq, PartialEq)]
83#[cfg_attr(feature = "defmt", derive(defmt::Format))]
86pub enum Value { 84pub enum Value {
87 Bit8(u8), 85 Bit8(u8),
88 Bit12(u16, Alignment), 86 Bit12(u16, Alignment),
89} 87}
90 88
91pub struct Dac<'d, T: Instance> { 89pub struct Dac<'d, T: Instance> {
92 ch1: Option<AnyPin>, 90 channels: u8,
93 ch2: Option<AnyPin>,
94 phantom: PhantomData<&'d mut T>, 91 phantom: PhantomData<&'d mut T>,
95} 92}
96 93
97impl<'d, T: Instance> Dac<'d, T> { 94impl<'d, T: Instance> Dac<'d, T> {
98 pub fn new( 95 pub fn new_1ch(
99 _peri: impl Unborrow<Target = T> + 'd, 96 peri: impl Unborrow<Target = T> + 'd,
100 ch1: impl Unborrow<Target = impl DacPin<T, 1>>, 97 _ch1: impl Unborrow<Target = impl DacPin<T, 1>> + 'd,
101 ch2: impl Unborrow<Target = impl DacPin<T, 2>>, 98 ) -> Self {
99 unborrow!(peri);
100 Self::new_inner(peri, 1)
101 }
102
103 pub fn new_2ch(
104 peri: impl Unborrow<Target = T> + 'd,
105 _ch1: impl Unborrow<Target = impl DacPin<T, 1>> + 'd,
106 _ch2: impl Unborrow<Target = impl DacPin<T, 2>> + 'd,
102 ) -> Self { 107 ) -> Self {
103 unborrow!(ch1, ch2); 108 unborrow!(peri);
109 Self::new_inner(peri, 2)
110 }
104 111
112 fn new_inner(_peri: T, channels: u8) -> Self {
105 unsafe { 113 unsafe {
106 enable(); 114 // Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent DAC clock
107 } 115 // configuration.
108 116 #[cfg(rcc_h7)]
109 let ch1 = ch1.degrade_optional(); 117 crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true));
110 if ch1.is_some() { 118 #[cfg(rcc_g0)]
111 unsafe { 119 crate::pac::RCC.apbenr1().modify(|w| w.set_dac1en(true));
120 #[cfg(rcc_l4)]
121 crate::pac::RCC.apb1enr1().modify(|w| w.set_dac1en(true));
122
123 if channels >= 1 {
112 T::regs().cr().modify(|reg| { 124 T::regs().cr().modify(|reg| {
113 reg.set_en1(true); 125 reg.set_en1(true);
114 }); 126 });
115 } 127 }
116 }
117 128
118 let ch2 = ch2.degrade_optional(); 129 if channels >= 2 {
119 if ch2.is_some() {
120 unsafe {
121 T::regs().cr().modify(|reg| { 130 T::regs().cr().modify(|reg| {
122 reg.set_en2(true); 131 reg.set_en2(true);
123 }); 132 });
@@ -125,39 +134,35 @@ impl<'d, T: Instance> Dac<'d, T> {
125 } 134 }
126 135
127 Self { 136 Self {
128 ch1, 137 channels,
129 ch2,
130 phantom: PhantomData, 138 phantom: PhantomData,
131 } 139 }
132 } 140 }
133 141
142 /// Check the channel is configured
143 fn check_channel_exists(&self, ch: Channel) -> Result<(), Error> {
144 if ch == Channel::Ch2 && self.channels < 2 {
145 Err(Error::UnconfiguredChannel)
146 } else {
147 Ok(())
148 }
149 }
150
134 fn set_channel_enable(&mut self, ch: Channel, on: bool) -> Result<(), Error> { 151 fn set_channel_enable(&mut self, ch: Channel, on: bool) -> Result<(), Error> {
152 self.check_channel_exists(ch)?;
135 match ch { 153 match ch {
136 Channel::Ch1 => { 154 Channel::Ch1 => unsafe {
137 if self.ch1.is_none() { 155 T::regs().cr().modify(|reg| {
138 Err(Error::UnconfiguredChannel) 156 reg.set_en1(on);
139 } else { 157 })
140 unsafe { 158 },
141 T::regs().cr().modify(|reg| { 159 Channel::Ch2 => unsafe {
142 reg.set_en1(on); 160 T::regs().cr().modify(|reg| {
143 }); 161 reg.set_en2(on);
144 } 162 });
145 Ok(()) 163 },
146 }
147 }
148 Channel::Ch2 => {
149 if self.ch2.is_none() {
150 Err(Error::UnconfiguredChannel)
151 } else {
152 unsafe {
153 T::regs().cr().modify(|reg| {
154 reg.set_en2(on);
155 });
156 }
157 Ok(())
158 }
159 }
160 } 164 }
165 Ok(())
161 } 166 }
162 167
163 pub fn enable_channel(&mut self, ch: Channel) -> Result<(), Error> { 168 pub fn enable_channel(&mut self, ch: Channel) -> Result<(), Error> {
@@ -169,9 +174,7 @@ impl<'d, T: Instance> Dac<'d, T> {
169 } 174 }
170 175
171 pub fn select_trigger_ch1(&mut self, trigger: Ch1Trigger) -> Result<(), Error> { 176 pub fn select_trigger_ch1(&mut self, trigger: Ch1Trigger) -> Result<(), Error> {
172 if self.ch1.is_none() { 177 self.check_channel_exists(Channel::Ch1)?;
173 return Err(Error::UnconfiguredChannel);
174 }
175 unwrap!(self.disable_channel(Channel::Ch1)); 178 unwrap!(self.disable_channel(Channel::Ch1));
176 unsafe { 179 unsafe {
177 T::regs().cr().modify(|reg| { 180 T::regs().cr().modify(|reg| {
@@ -182,9 +185,7 @@ impl<'d, T: Instance> Dac<'d, T> {
182 } 185 }
183 186
184 pub fn select_trigger_ch2(&mut self, trigger: Ch2Trigger) -> Result<(), Error> { 187 pub fn select_trigger_ch2(&mut self, trigger: Ch2Trigger) -> Result<(), Error> {
185 if self.ch2.is_none() { 188 self.check_channel_exists(Channel::Ch2)?;
186 return Err(Error::UnconfiguredChannel);
187 }
188 unwrap!(self.disable_channel(Channel::Ch2)); 189 unwrap!(self.disable_channel(Channel::Ch2));
189 unsafe { 190 unsafe {
190 T::regs().cr().modify(|reg| { 191 T::regs().cr().modify(|reg| {
@@ -195,32 +196,20 @@ impl<'d, T: Instance> Dac<'d, T> {
195 } 196 }
196 197
197 pub fn trigger(&mut self, ch: Channel) -> Result<(), Error> { 198 pub fn trigger(&mut self, ch: Channel) -> Result<(), Error> {
199 self.check_channel_exists(ch)?;
198 match ch { 200 match ch {
199 Channel::Ch1 => { 201 Channel::Ch1 => unsafe {
200 if self.ch1.is_none() { 202 T::regs().swtrigr().write(|reg| {
201 Err(Error::UnconfiguredChannel) 203 reg.set_swtrig1(true);
202 } else { 204 });
203 unsafe { 205 },
204 T::regs().swtrigr().write(|reg| { 206 Channel::Ch2 => unsafe {
205 reg.set_swtrig1(true); 207 T::regs().swtrigr().write(|reg| {
206 }); 208 reg.set_swtrig2(true);
207 } 209 })
208 Ok(()) 210 },
209 }
210 }
211 Channel::Ch2 => {
212 if self.ch2.is_none() {
213 Err(Error::UnconfiguredChannel)
214 } else {
215 unsafe {
216 T::regs().swtrigr().write(|reg| {
217 reg.set_swtrig2(true);
218 });
219 }
220 Ok(())
221 }
222 }
223 } 211 }
212 Ok(())
224 } 213 }
225 214
226 pub fn trigger_all(&mut self) { 215 pub fn trigger_all(&mut self) {
@@ -233,43 +222,31 @@ impl<'d, T: Instance> Dac<'d, T> {
233 } 222 }
234 223
235 pub fn set(&mut self, ch: Channel, value: Value) -> Result<(), Error> { 224 pub fn set(&mut self, ch: Channel, value: Value) -> Result<(), Error> {
225 self.check_channel_exists(Channel::Ch2)?;
236 match ch { 226 match ch {
237 Channel::Ch1 => { 227 Channel::Ch1 => match value {
238 if self.ch1.is_none() { 228 Value::Bit8(v) => unsafe {
239 Err(Error::UnconfiguredChannel) 229 T::regs().dhr8r1().write(|reg| reg.set_dacc1dhr(v));
240 } else { 230 },
241 match value { 231 Value::Bit12(v, Alignment::Left) => unsafe {
242 Value::Bit8(v) => unsafe { 232 T::regs().dhr12l1().write(|reg| reg.set_dacc1dhr(v));
243 T::regs().dhr8r1().write(|reg| reg.set_dacc1dhr(v)); 233 },
244 }, 234 Value::Bit12(v, Alignment::Right) => unsafe {
245 Value::Bit12(v, Alignment::Left) => unsafe { 235 T::regs().dhr12r1().write(|reg| reg.set_dacc1dhr(v));
246 T::regs().dhr12l1().write(|reg| reg.set_dacc1dhr(v)); 236 },
247 }, 237 },
248 Value::Bit12(v, Alignment::Right) => unsafe { 238 Channel::Ch2 => match value {
249 T::regs().dhr12r1().write(|reg| reg.set_dacc1dhr(v)); 239 Value::Bit8(v) => unsafe {
250 }, 240 T::regs().dhr8r2().write(|reg| reg.set_dacc2dhr(v));
251 } 241 },
252 Ok(()) 242 Value::Bit12(v, Alignment::Left) => unsafe {
253 } 243 T::regs().dhr12l2().write(|reg| reg.set_dacc2dhr(v));
254 } 244 },
255 Channel::Ch2 => { 245 Value::Bit12(v, Alignment::Right) => unsafe {
256 if self.ch2.is_none() { 246 T::regs().dhr12r2().write(|reg| reg.set_dacc2dhr(v));
257 Err(Error::UnconfiguredChannel) 247 },
258 } else { 248 },
259 match value {
260 Value::Bit8(v) => unsafe {
261 T::regs().dhr8r2().write(|reg| reg.set_dacc2dhr(v));
262 },
263 Value::Bit12(v, Alignment::Left) => unsafe {
264 T::regs().dhr12l2().write(|reg| reg.set_dacc2dhr(v));
265 },
266 Value::Bit12(v, Alignment::Right) => unsafe {
267 T::regs().dhr12r2().write(|reg| reg.set_dacc2dhr(v));
268 },
269 }
270 Ok(())
271 }
272 }
273 } 249 }
250 Ok(())
274 } 251 }
275} 252}
diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs
index 315aa363c..cbfa5f098 100644
--- a/embassy-stm32/src/dcmi.rs
+++ b/embassy-stm32/src/dcmi.rs
@@ -9,6 +9,15 @@ use embassy::waitqueue::AtomicWaker;
9use embassy_hal_common::unborrow; 9use embassy_hal_common::unborrow;
10use futures::future::poll_fn; 10use futures::future::poll_fn;
11 11
12#[macro_export]
13macro_rules! configure {
14 ($($name:ident),*) => {
15 $(
16 unsafe { $name.unborrow() }.configure();
17 )*
18 }
19}
20
12/// The level on the VSync pin when the data is not valid on the parallel interface. 21/// The level on the VSync pin when the data is not valid on the parallel interface.
13#[derive(Clone, Copy, PartialEq)] 22#[derive(Clone, Copy, PartialEq)]
14pub enum VSyncDataInvalidLevel { 23pub enum VSyncDataInvalidLevel {
@@ -50,6 +59,23 @@ pub enum Error {
50 PeripheralError, 59 PeripheralError,
51} 60}
52 61
62#[non_exhaustive]
63pub struct Config {
64 pub vsync_level: VSyncDataInvalidLevel,
65 pub hsync_level: HSyncDataInvalidLevel,
66 pub pixclk_polarity: PixelClockPolarity,
67}
68
69impl Default for Config {
70 fn default() -> Self {
71 Self {
72 vsync_level: VSyncDataInvalidLevel::High,
73 hsync_level: HSyncDataInvalidLevel::Low,
74 pixclk_polarity: PixelClockPolarity::RisingEdge,
75 }
76 }
77}
78
53pub struct Dcmi<'d, T: Instance, Dma: FrameDma> { 79pub struct Dcmi<'d, T: Instance, Dma: FrameDma> {
54 inner: T, 80 inner: T,
55 dma: Dma, 81 dma: Dma,
@@ -61,13 +87,85 @@ where
61 T: Instance, 87 T: Instance,
62 Dma: FrameDma, 88 Dma: FrameDma,
63{ 89{
64 pub fn new( 90 pub fn new_8bit(
91 peri: impl Unborrow<Target = T> + 'd,
92 dma: impl Unborrow<Target = Dma> + 'd,
93 irq: impl Unborrow<Target = T::Interrupt> + 'd,
94 d0: impl Unborrow<Target = impl D0Pin> + 'd,
95 d1: impl Unborrow<Target = impl D1Pin> + 'd,
96 d2: impl Unborrow<Target = impl D2Pin> + 'd,
97 d3: impl Unborrow<Target = impl D3Pin> + 'd,
98 d4: impl Unborrow<Target = impl D4Pin> + 'd,
99 d5: impl Unborrow<Target = impl D5Pin> + 'd,
100 d6: impl Unborrow<Target = impl D6Pin> + 'd,
101 d7: impl Unborrow<Target = impl D7Pin> + 'd,
102 v_sync: impl Unborrow<Target = impl VSyncPin> + 'd,
103 h_sync: impl Unborrow<Target = impl HSyncPin> + 'd,
104 pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
105 config: Config,
106 ) -> Self {
107 unborrow!(peri, dma, irq);
108 configure!(d0, d1, d2, d3, d4, d5, d6, d7);
109 configure!(v_sync, h_sync, pixclk);
110
111 Self::new_inner(peri, dma, irq, config, false, 0b00)
112 }
113 pub fn new_10bit(
114 peri: impl Unborrow<Target = T> + 'd,
115 dma: impl Unborrow<Target = Dma> + 'd,
116 irq: impl Unborrow<Target = T::Interrupt> + 'd,
117 d0: impl Unborrow<Target = impl D0Pin> + 'd,
118 d1: impl Unborrow<Target = impl D1Pin> + 'd,
119 d2: impl Unborrow<Target = impl D2Pin> + 'd,
120 d3: impl Unborrow<Target = impl D3Pin> + 'd,
121 d4: impl Unborrow<Target = impl D4Pin> + 'd,
122 d5: impl Unborrow<Target = impl D5Pin> + 'd,
123 d6: impl Unborrow<Target = impl D6Pin> + 'd,
124 d7: impl Unborrow<Target = impl D7Pin> + 'd,
125 d8: impl Unborrow<Target = impl D8Pin> + 'd,
126 d9: impl Unborrow<Target = impl D9Pin> + 'd,
127 v_sync: impl Unborrow<Target = impl VSyncPin> + 'd,
128 h_sync: impl Unborrow<Target = impl HSyncPin> + 'd,
129 pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
130 config: Config,
131 ) -> Self {
132 unborrow!(peri, dma, irq);
133 configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9);
134 configure!(v_sync, h_sync, pixclk);
135
136 Self::new_inner(peri, dma, irq, config, false, 0b01)
137 }
138
139 pub fn new_12bit(
140 peri: impl Unborrow<Target = T> + 'd,
141 dma: impl Unborrow<Target = Dma> + 'd,
142 irq: impl Unborrow<Target = T::Interrupt> + 'd,
143 d0: impl Unborrow<Target = impl D0Pin> + 'd,
144 d1: impl Unborrow<Target = impl D1Pin> + 'd,
145 d2: impl Unborrow<Target = impl D2Pin> + 'd,
146 d3: impl Unborrow<Target = impl D3Pin> + 'd,
147 d4: impl Unborrow<Target = impl D4Pin> + 'd,
148 d5: impl Unborrow<Target = impl D5Pin> + 'd,
149 d6: impl Unborrow<Target = impl D6Pin> + 'd,
150 d7: impl Unborrow<Target = impl D7Pin> + 'd,
151 d8: impl Unborrow<Target = impl D8Pin> + 'd,
152 d9: impl Unborrow<Target = impl D9Pin> + 'd,
153 d10: impl Unborrow<Target = impl D10Pin> + 'd,
154 d11: impl Unborrow<Target = impl D11Pin> + 'd,
155 v_sync: impl Unborrow<Target = impl VSyncPin> + 'd,
156 h_sync: impl Unborrow<Target = impl HSyncPin> + 'd,
157 pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
158 config: Config,
159 ) -> Self {
160 unborrow!(peri, dma, irq);
161 configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11);
162 configure!(v_sync, h_sync, pixclk);
163
164 Self::new_inner(peri, dma, irq, config, false, 0b10)
165 }
166 pub fn new_14bit(
65 peri: impl Unborrow<Target = T> + 'd, 167 peri: impl Unborrow<Target = T> + 'd,
66 dma: impl Unborrow<Target = Dma> + 'd, 168 dma: impl Unborrow<Target = Dma> + 'd,
67 vsync_level: VSyncDataInvalidLevel,
68 hsync_level: HSyncDataInvalidLevel,
69 pixclk_polarity: PixelClockPolarity,
70 use_embedded_synchronization: bool,
71 irq: impl Unborrow<Target = T::Interrupt> + 'd, 169 irq: impl Unborrow<Target = T::Interrupt> + 'd,
72 d0: impl Unborrow<Target = impl D0Pin> + 'd, 170 d0: impl Unborrow<Target = impl D0Pin> + 'd,
73 d1: impl Unborrow<Target = impl D1Pin> + 'd, 171 d1: impl Unborrow<Target = impl D1Pin> + 'd,
@@ -86,58 +184,132 @@ where
86 v_sync: impl Unborrow<Target = impl VSyncPin> + 'd, 184 v_sync: impl Unborrow<Target = impl VSyncPin> + 'd,
87 h_sync: impl Unborrow<Target = impl HSyncPin> + 'd, 185 h_sync: impl Unborrow<Target = impl HSyncPin> + 'd,
88 pixclk: impl Unborrow<Target = impl PixClkPin> + 'd, 186 pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
187 config: Config,
188 ) -> Self {
189 unborrow!(peri, dma, irq);
190 configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13);
191 configure!(v_sync, h_sync, pixclk);
192
193 Self::new_inner(peri, dma, irq, config, false, 0b11)
194 }
195
196 pub fn new_es_8bit(
197 peri: impl Unborrow<Target = T> + 'd,
198 dma: impl Unborrow<Target = Dma> + 'd,
199 irq: impl Unborrow<Target = T::Interrupt> + 'd,
200 d0: impl Unborrow<Target = impl D0Pin> + 'd,
201 d1: impl Unborrow<Target = impl D1Pin> + 'd,
202 d2: impl Unborrow<Target = impl D2Pin> + 'd,
203 d3: impl Unborrow<Target = impl D3Pin> + 'd,
204 d4: impl Unborrow<Target = impl D4Pin> + 'd,
205 d5: impl Unborrow<Target = impl D5Pin> + 'd,
206 d6: impl Unborrow<Target = impl D6Pin> + 'd,
207 d7: impl Unborrow<Target = impl D7Pin> + 'd,
208 pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
209 config: Config,
210 ) -> Self {
211 unborrow!(peri, dma, irq);
212 configure!(d0, d1, d2, d3, d4, d5, d6, d7);
213 configure!(pixclk);
214
215 Self::new_inner(peri, dma, irq, config, true, 0b00)
216 }
217
218 pub fn new_es_10bit(
219 peri: impl Unborrow<Target = T> + 'd,
220 dma: impl Unborrow<Target = Dma> + 'd,
221 irq: impl Unborrow<Target = T::Interrupt> + 'd,
222 d0: impl Unborrow<Target = impl D0Pin> + 'd,
223 d1: impl Unborrow<Target = impl D1Pin> + 'd,
224 d2: impl Unborrow<Target = impl D2Pin> + 'd,
225 d3: impl Unborrow<Target = impl D3Pin> + 'd,
226 d4: impl Unborrow<Target = impl D4Pin> + 'd,
227 d5: impl Unborrow<Target = impl D5Pin> + 'd,
228 d6: impl Unborrow<Target = impl D6Pin> + 'd,
229 d7: impl Unborrow<Target = impl D7Pin> + 'd,
230 d8: impl Unborrow<Target = impl D8Pin> + 'd,
231 d9: impl Unborrow<Target = impl D9Pin> + 'd,
232 pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
233 config: Config,
234 ) -> Self {
235 unborrow!(peri, dma, irq);
236 configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9);
237 configure!(pixclk);
238
239 Self::new_inner(peri, dma, irq, config, true, 0b01)
240 }
241
242 pub fn new_es_12bit(
243 peri: impl Unborrow<Target = T> + 'd,
244 dma: impl Unborrow<Target = Dma> + 'd,
245 irq: impl Unborrow<Target = T::Interrupt> + 'd,
246 d0: impl Unborrow<Target = impl D0Pin> + 'd,
247 d1: impl Unborrow<Target = impl D1Pin> + 'd,
248 d2: impl Unborrow<Target = impl D2Pin> + 'd,
249 d3: impl Unborrow<Target = impl D3Pin> + 'd,
250 d4: impl Unborrow<Target = impl D4Pin> + 'd,
251 d5: impl Unborrow<Target = impl D5Pin> + 'd,
252 d6: impl Unborrow<Target = impl D6Pin> + 'd,
253 d7: impl Unborrow<Target = impl D7Pin> + 'd,
254 d8: impl Unborrow<Target = impl D8Pin> + 'd,
255 d9: impl Unborrow<Target = impl D9Pin> + 'd,
256 d10: impl Unborrow<Target = impl D10Pin> + 'd,
257 d11: impl Unborrow<Target = impl D11Pin> + 'd,
258 pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
259 config: Config,
260 ) -> Self {
261 unborrow!(peri, dma, irq);
262 configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11);
263 configure!(pixclk);
264
265 Self::new_inner(peri, dma, irq, config, true, 0b10)
266 }
267 pub fn new_es_14bit(
268 peri: impl Unborrow<Target = T> + 'd,
269 dma: impl Unborrow<Target = Dma> + 'd,
270 irq: impl Unborrow<Target = T::Interrupt> + 'd,
271 d0: impl Unborrow<Target = impl D0Pin> + 'd,
272 d1: impl Unborrow<Target = impl D1Pin> + 'd,
273 d2: impl Unborrow<Target = impl D2Pin> + 'd,
274 d3: impl Unborrow<Target = impl D3Pin> + 'd,
275 d4: impl Unborrow<Target = impl D4Pin> + 'd,
276 d5: impl Unborrow<Target = impl D5Pin> + 'd,
277 d6: impl Unborrow<Target = impl D6Pin> + 'd,
278 d7: impl Unborrow<Target = impl D7Pin> + 'd,
279 d8: impl Unborrow<Target = impl D8Pin> + 'd,
280 d9: impl Unborrow<Target = impl D9Pin> + 'd,
281 d10: impl Unborrow<Target = impl D10Pin> + 'd,
282 d11: impl Unborrow<Target = impl D11Pin> + 'd,
283 d12: impl Unborrow<Target = impl D12Pin> + 'd,
284 d13: impl Unborrow<Target = impl D13Pin> + 'd,
285 pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
286 config: Config,
287 ) -> Self {
288 unborrow!(peri, dma, irq);
289 configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13);
290 configure!(pixclk);
291
292 Self::new_inner(peri, dma, irq, config, true, 0b11)
293 }
294
295 fn new_inner(
296 peri: T,
297 dma: Dma,
298 irq: T::Interrupt,
299 config: Config,
300 use_embedded_synchronization: bool,
301 edm: u8,
89 ) -> Self { 302 ) -> Self {
90 T::reset(); 303 T::reset();
91 T::enable(); 304 T::enable();
92 305
93 unborrow!(
94 peri, dma, irq, d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, v_sync,
95 h_sync, pixclk
96 );
97
98 d0.configure();
99 d1.configure();
100 d2.configure();
101 d3.configure();
102 d4.configure();
103 d5.configure();
104 d6.configure();
105 d7.configure();
106 d8.configure();
107 d9.configure();
108 d10.configure();
109 d11.configure();
110 d12.configure();
111 d13.configure();
112
113 v_sync.configure();
114 h_sync.configure();
115 pixclk.configure();
116
117 let edm = match (
118 d8.pin().is_some(),
119 d9.pin().is_some(),
120 d10.pin().is_some(),
121 d11.pin().is_some(),
122 d12.pin().is_some(),
123 d13.pin().is_some(),
124 ) {
125 (true, true, true, true, true, true) => 0b11, // 14 bits
126 (true, true, true, true, false, false) => 0b10, // 12 bits
127 (true, true, false, false, false, false) => 0b01, // 10 bits
128 (false, false, false, false, false, false) => 0b00, // 8 bits
129 _ => {
130 panic!("Invalid pin configuration.");
131 }
132 };
133
134 unsafe { 306 unsafe {
135 peri.regs().cr().modify(|r| { 307 peri.regs().cr().modify(|r| {
136 r.set_cm(true); // disable continuous mode (snapshot mode) 308 r.set_cm(true); // disable continuous mode (snapshot mode)
137 r.set_ess(use_embedded_synchronization); 309 r.set_ess(use_embedded_synchronization);
138 r.set_pckpol(pixclk_polarity == PixelClockPolarity::RisingEdge); 310 r.set_pckpol(config.pixclk_polarity == PixelClockPolarity::RisingEdge);
139 r.set_vspol(vsync_level == VSyncDataInvalidLevel::High); 311 r.set_vspol(config.vsync_level == VSyncDataInvalidLevel::High);
140 r.set_hspol(hsync_level == HSyncDataInvalidLevel::High); 312 r.set_hspol(config.hsync_level == HSyncDataInvalidLevel::High);
141 r.set_fcrc(0x00); // capture every frame 313 r.set_fcrc(0x00); // capture every frame
142 r.set_edm(edm); // extended data mode 314 r.set_edm(edm); // extended data mode
143 }); 315 });
@@ -271,14 +443,6 @@ mod sealed {
271 }; 443 };
272 } 444 }
273 445
274 macro_rules! optional_pin {
275 ($name:ident) => {
276 pub trait $name: crate::gpio::OptionalPin {
277 fn configure(&mut self);
278 }
279 };
280 }
281
282 pin!(D0Pin); 446 pin!(D0Pin);
283 pin!(D1Pin); 447 pin!(D1Pin);
284 pin!(D2Pin); 448 pin!(D2Pin);
@@ -287,15 +451,15 @@ mod sealed {
287 pin!(D5Pin); 451 pin!(D5Pin);
288 pin!(D6Pin); 452 pin!(D6Pin);
289 pin!(D7Pin); 453 pin!(D7Pin);
290 optional_pin!(D8Pin); 454 pin!(D8Pin);
291 optional_pin!(D9Pin); 455 pin!(D9Pin);
292 optional_pin!(D10Pin); 456 pin!(D10Pin);
293 optional_pin!(D11Pin); 457 pin!(D11Pin);
294 optional_pin!(D12Pin); 458 pin!(D12Pin);
295 optional_pin!(D13Pin); 459 pin!(D13Pin);
296 460
297 optional_pin!(HSyncPin); 461 pin!(HSyncPin);
298 optional_pin!(VSyncPin); 462 pin!(VSyncPin);
299 pin!(PixClkPin); 463 pin!(PixClkPin);
300} 464}
301 465
@@ -408,24 +572,6 @@ macro_rules! impl_pin {
408 }; 572 };
409} 573}
410 574
411macro_rules! impl_no_pin {
412 ($signal:ident) => {
413 impl sealed::$signal for crate::gpio::NoPin {
414 fn configure(&mut self) {}
415 }
416 impl $signal for crate::gpio::NoPin {}
417 };
418}
419
420impl_no_pin!(D8Pin);
421impl_no_pin!(D9Pin);
422impl_no_pin!(D10Pin);
423impl_no_pin!(D11Pin);
424impl_no_pin!(D12Pin);
425impl_no_pin!(D13Pin);
426impl_no_pin!(HSyncPin);
427impl_no_pin!(VSyncPin);
428
429crate::pac::peripheral_pins!( 575crate::pac::peripheral_pins!(
430 ($inst:ident, dcmi, DCMI, $pin:ident, D0, $af:expr) => { 576 ($inst:ident, dcmi, DCMI, $pin:ident, D0, $af:expr) => {
431 impl_pin!($pin, D0Pin, $af); 577 impl_pin!($pin, D0Pin, $af);
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs
index f154a66c4..175abbd27 100644
--- a/embassy-stm32/src/gpio.rs
+++ b/embassy-stm32/src/gpio.rs
@@ -544,54 +544,6 @@ impl sealed::Pin for AnyPin {
544 544
545// ==================== 545// ====================
546 546
547pub trait OptionalPin: sealed::OptionalPin + Sized {
548 type Pin: Pin;
549 fn pin(&self) -> Option<&Self::Pin>;
550 fn pin_mut(&mut self) -> Option<&mut Self::Pin>;
551
552 /// Convert from concrete pin type PX_XX to type erased `Option<AnyPin>`.
553 #[inline]
554 fn degrade_optional(mut self) -> Option<AnyPin> {
555 self.pin_mut()
556 .map(|pin| unsafe { core::ptr::read(pin) }.degrade())
557 }
558}
559
560impl<T: Pin> sealed::OptionalPin for T {}
561impl<T: Pin> OptionalPin for T {
562 type Pin = T;
563
564 #[inline]
565 fn pin(&self) -> Option<&T> {
566 Some(self)
567 }
568
569 #[inline]
570 fn pin_mut(&mut self) -> Option<&mut T> {
571 Some(self)
572 }
573}
574
575#[derive(Clone, Copy, Debug)]
576pub struct NoPin;
577unsafe_impl_unborrow!(NoPin);
578impl sealed::OptionalPin for NoPin {}
579impl OptionalPin for NoPin {
580 type Pin = AnyPin;
581
582 #[inline]
583 fn pin(&self) -> Option<&AnyPin> {
584 None
585 }
586
587 #[inline]
588 fn pin_mut(&mut self) -> Option<&mut AnyPin> {
589 None
590 }
591}
592
593// ====================
594
595crate::pac::pins!( 547crate::pac::pins!(
596 ($pin_name:ident, $port_name:ident, $port_num:expr, $pin_num:expr, $exti_ch:ident) => { 548 ($pin_name:ident, $port_name:ident, $port_num:expr, $pin_num:expr, $exti_ch:ident) => {
597 impl Pin for peripherals::$pin_name { 549 impl Pin for peripherals::$pin_name {
diff --git a/embassy-stm32/src/pwm/mod.rs b/embassy-stm32/src/pwm/mod.rs
index 1cb191a95..17a7cbd0a 100644
--- a/embassy-stm32/src/pwm/mod.rs
+++ b/embassy-stm32/src/pwm/mod.rs
@@ -248,31 +248,6 @@ crate::pac::interrupts! {
248 }; 248 };
249} 249}
250 250
251#[allow(unused)]
252macro_rules! impl_pwm_nopin {
253 ($inst:ident) => {
254 impl_no_pin!($inst, Channel1Pin);
255 impl_no_pin!($inst, Channel1ComplementaryPin);
256 impl_no_pin!($inst, Channel2Pin);
257 impl_no_pin!($inst, Channel2ComplementaryPin);
258 impl_no_pin!($inst, Channel3Pin);
259 impl_no_pin!($inst, Channel3ComplementaryPin);
260 impl_no_pin!($inst, Channel4Pin);
261 impl_no_pin!($inst, Channel4ComplementaryPin);
262 impl_no_pin!($inst, ExternalTriggerPin);
263 impl_no_pin!($inst, BreakInputPin);
264 impl_no_pin!($inst, BreakInputComparator1Pin);
265 impl_no_pin!($inst, BreakInputComparator2Pin);
266 impl_no_pin!($inst, BreakInput2Pin);
267 impl_no_pin!($inst, BreakInput2Comparator1Pin);
268 impl_no_pin!($inst, BreakInput2Comparator2Pin);
269 };
270}
271
272crate::pac::peripherals!(
273 (timer, $inst:ident) => { impl_pwm_nopin!($inst); };
274);
275
276crate::pac::peripheral_pins!( 251crate::pac::peripheral_pins!(
277 ($inst:ident, timer, $block:ident, $pin:ident, CH1, $af:expr) => { 252 ($inst:ident, timer, $block:ident, $pin:ident, CH1, $af:expr) => {
278 impl_pin!($inst, Channel1Pin, $pin, $af); 253 impl_pin!($inst, Channel1Pin, $pin, $af);
diff --git a/embassy-stm32/src/pwm/pins.rs b/embassy-stm32/src/pwm/pins.rs
index 77ba1f6d5..059e76231 100644
--- a/embassy-stm32/src/pwm/pins.rs
+++ b/embassy-stm32/src/pwm/pins.rs
@@ -1,4 +1,4 @@
1use crate::gpio::OptionalPin; 1use crate::gpio::Pin;
2 2
3#[cfg(feature = "unstable-pac")] 3#[cfg(feature = "unstable-pac")]
4pub mod low_level { 4pub mod low_level {
@@ -6,118 +6,106 @@ pub mod low_level {
6} 6}
7 7
8pub(crate) mod sealed { 8pub(crate) mod sealed {
9 use crate::gpio::sealed::OptionalPin; 9 use crate::gpio::sealed::Pin;
10 10
11 pub trait Channel1Pin<Timer>: OptionalPin { 11 pub trait Channel1Pin<Timer>: Pin {
12 unsafe fn configure(&mut self); 12 unsafe fn configure(&mut self);
13 } 13 }
14 pub trait Channel1ComplementaryPin<Timer>: OptionalPin { 14 pub trait Channel1ComplementaryPin<Timer>: Pin {
15 unsafe fn configure(&mut self); 15 unsafe fn configure(&mut self);
16 } 16 }
17 17
18 pub trait Channel2Pin<Timer>: OptionalPin { 18 pub trait Channel2Pin<Timer>: Pin {
19 unsafe fn configure(&mut self); 19 unsafe fn configure(&mut self);
20 } 20 }
21 pub trait Channel2ComplementaryPin<Timer>: OptionalPin { 21 pub trait Channel2ComplementaryPin<Timer>: Pin {
22 unsafe fn configure(&mut self); 22 unsafe fn configure(&mut self);
23 } 23 }
24 24
25 pub trait Channel3Pin<Timer>: OptionalPin { 25 pub trait Channel3Pin<Timer>: Pin {
26 unsafe fn configure(&mut self); 26 unsafe fn configure(&mut self);
27 } 27 }
28 pub trait Channel3ComplementaryPin<Timer>: OptionalPin { 28 pub trait Channel3ComplementaryPin<Timer>: Pin {
29 unsafe fn configure(&mut self); 29 unsafe fn configure(&mut self);
30 } 30 }
31 31
32 pub trait Channel4Pin<Timer>: OptionalPin { 32 pub trait Channel4Pin<Timer>: Pin {
33 unsafe fn configure(&mut self); 33 unsafe fn configure(&mut self);
34 } 34 }
35 pub trait Channel4ComplementaryPin<Timer>: OptionalPin { 35 pub trait Channel4ComplementaryPin<Timer>: Pin {
36 unsafe fn configure(&mut self); 36 unsafe fn configure(&mut self);
37 } 37 }
38 38
39 pub trait ExternalTriggerPin<Timer>: OptionalPin { 39 pub trait ExternalTriggerPin<Timer>: Pin {
40 unsafe fn configure(&mut self); 40 unsafe fn configure(&mut self);
41 } 41 }
42 42
43 pub trait BreakInputPin<Timer>: OptionalPin { 43 pub trait BreakInputPin<Timer>: Pin {
44 unsafe fn configure(&mut self); 44 unsafe fn configure(&mut self);
45 } 45 }
46 pub trait BreakInputComparator1Pin<Timer>: OptionalPin { 46 pub trait BreakInputComparator1Pin<Timer>: Pin {
47 unsafe fn configure(&mut self); 47 unsafe fn configure(&mut self);
48 } 48 }
49 pub trait BreakInputComparator2Pin<Timer>: OptionalPin { 49 pub trait BreakInputComparator2Pin<Timer>: Pin {
50 unsafe fn configure(&mut self); 50 unsafe fn configure(&mut self);
51 } 51 }
52 52
53 pub trait BreakInput2Pin<Timer>: OptionalPin { 53 pub trait BreakInput2Pin<Timer>: Pin {
54 unsafe fn configure(&mut self); 54 unsafe fn configure(&mut self);
55 } 55 }
56 pub trait BreakInput2Comparator1Pin<Timer>: OptionalPin { 56 pub trait BreakInput2Comparator1Pin<Timer>: Pin {
57 unsafe fn configure(&mut self); 57 unsafe fn configure(&mut self);
58 } 58 }
59 pub trait BreakInput2Comparator2Pin<Timer>: OptionalPin { 59 pub trait BreakInput2Comparator2Pin<Timer>: Pin {
60 unsafe fn configure(&mut self); 60 unsafe fn configure(&mut self);
61 } 61 }
62} 62}
63pub trait Channel1Pin<Timer>: sealed::Channel1Pin<Timer> + OptionalPin + 'static {} 63pub trait Channel1Pin<Timer>: sealed::Channel1Pin<Timer> + Pin + 'static {}
64pub trait Channel1ComplementaryPin<Timer>: 64pub trait Channel1ComplementaryPin<Timer>:
65 sealed::Channel1ComplementaryPin<Timer> + OptionalPin + 'static 65 sealed::Channel1ComplementaryPin<Timer> + Pin + 'static
66{ 66{
67} 67}
68 68
69pub trait Channel2Pin<Timer>: sealed::Channel2Pin<Timer> + 'static {} 69pub trait Channel2Pin<Timer>: sealed::Channel2Pin<Timer> + 'static {}
70pub trait Channel2ComplementaryPin<Timer>: 70pub trait Channel2ComplementaryPin<Timer>:
71 sealed::Channel2ComplementaryPin<Timer> + OptionalPin + 'static 71 sealed::Channel2ComplementaryPin<Timer> + Pin + 'static
72{ 72{
73} 73}
74 74
75pub trait Channel3Pin<Timer>: sealed::Channel3Pin<Timer> + 'static {} 75pub trait Channel3Pin<Timer>: sealed::Channel3Pin<Timer> + 'static {}
76pub trait Channel3ComplementaryPin<Timer>: 76pub trait Channel3ComplementaryPin<Timer>:
77 sealed::Channel3ComplementaryPin<Timer> + OptionalPin + 'static 77 sealed::Channel3ComplementaryPin<Timer> + Pin + 'static
78{ 78{
79} 79}
80 80
81pub trait Channel4Pin<Timer>: sealed::Channel4Pin<Timer> + 'static {} 81pub trait Channel4Pin<Timer>: sealed::Channel4Pin<Timer> + 'static {}
82pub trait Channel4ComplementaryPin<Timer>: 82pub trait Channel4ComplementaryPin<Timer>:
83 sealed::Channel4ComplementaryPin<Timer> + OptionalPin + 'static 83 sealed::Channel4ComplementaryPin<Timer> + Pin + 'static
84{ 84{
85} 85}
86 86
87pub trait ExternalTriggerPin<Timer>: 87pub trait ExternalTriggerPin<Timer>: sealed::ExternalTriggerPin<Timer> + Pin + 'static {}
88 sealed::ExternalTriggerPin<Timer> + OptionalPin + 'static
89{
90}
91 88
92pub trait BreakInputPin<Timer>: sealed::BreakInputPin<Timer> + OptionalPin + 'static {} 89pub trait BreakInputPin<Timer>: sealed::BreakInputPin<Timer> + Pin + 'static {}
93pub trait BreakInputComparator1Pin<Timer>: 90pub trait BreakInputComparator1Pin<Timer>:
94 sealed::BreakInputComparator1Pin<Timer> + OptionalPin + 'static 91 sealed::BreakInputComparator1Pin<Timer> + Pin + 'static
95{ 92{
96} 93}
97pub trait BreakInputComparator2Pin<Timer>: 94pub trait BreakInputComparator2Pin<Timer>:
98 sealed::BreakInputComparator2Pin<Timer> + OptionalPin + 'static 95 sealed::BreakInputComparator2Pin<Timer> + Pin + 'static
99{ 96{
100} 97}
101 98
102pub trait BreakInput2Pin<Timer>: sealed::BreakInput2Pin<Timer> + OptionalPin + 'static {} 99pub trait BreakInput2Pin<Timer>: sealed::BreakInput2Pin<Timer> + Pin + 'static {}
103pub trait BreakInput2Comparator1Pin<Timer>: 100pub trait BreakInput2Comparator1Pin<Timer>:
104 sealed::BreakInput2Comparator1Pin<Timer> + OptionalPin + 'static 101 sealed::BreakInput2Comparator1Pin<Timer> + Pin + 'static
105{ 102{
106} 103}
107pub trait BreakInput2Comparator2Pin<Timer>: 104pub trait BreakInput2Comparator2Pin<Timer>:
108 sealed::BreakInput2Comparator2Pin<Timer> + OptionalPin + 'static 105 sealed::BreakInput2Comparator2Pin<Timer> + Pin + 'static
109{ 106{
110} 107}
111 108
112macro_rules! impl_no_pin {
113 ($timer:ident, $signal:ident) => {
114 impl crate::pwm::pins::sealed::$signal<crate::peripherals::$timer> for crate::gpio::NoPin {
115 unsafe fn configure(&mut self) {}
116 }
117 impl crate::pwm::pins::$signal<crate::peripherals::$timer> for crate::gpio::NoPin {}
118 };
119}
120
121#[allow(unused)] 109#[allow(unused)]
122macro_rules! impl_pin { 110macro_rules! impl_pin {
123 ($timer:ident, $signal:ident, $pin:ident, $af:expr) => { 111 ($timer:ident, $signal:ident, $pin:ident, $af:expr) => {
diff --git a/embassy-stm32/src/pwm/simple_pwm.rs b/embassy-stm32/src/pwm/simple_pwm.rs
index 3dc46e6e8..6e1b9ce0d 100644
--- a/embassy-stm32/src/pwm/simple_pwm.rs
+++ b/embassy-stm32/src/pwm/simple_pwm.rs
@@ -12,25 +12,73 @@ pub struct SimplePwm<'d, T> {
12} 12}
13 13
14impl<'d, T: CaptureCompareCapable16bitInstance> SimplePwm<'d, T> { 14impl<'d, T: CaptureCompareCapable16bitInstance> SimplePwm<'d, T> {
15 pub fn new<F: Into<Hertz>>( 15 pub fn new_1ch<F: Into<Hertz>>(
16 tim: impl Unborrow<Target = T> + 'd,
17 ch1: impl Unborrow<Target = impl Channel1Pin<T>> + 'd,
18 freq: F,
19 ) -> Self {
20 unborrow!(ch1);
21 Self::new_inner(tim, freq, move || unsafe {
22 ch1.configure();
23 })
24 }
25
26 pub fn new_2ch<F: Into<Hertz>>(
16 tim: impl Unborrow<Target = T> + 'd, 27 tim: impl Unborrow<Target = T> + 'd,
17 ch1: impl Unborrow<Target = impl Channel1Pin<T>> + 'd, 28 ch1: impl Unborrow<Target = impl Channel1Pin<T>> + 'd,
18 ch2: impl Unborrow<Target = impl Channel2Pin<T>> + 'd, 29 ch2: impl Unborrow<Target = impl Channel2Pin<T>> + 'd,
19 ch3: impl Unborrow<Target = impl Channel3Pin<T>> + 'd,
20 ch4: impl Unborrow<Target = impl Channel4Pin<T>> + 'd,
21 freq: F, 30 freq: F,
22 ) -> Self { 31 ) -> Self {
23 unborrow!(tim, ch1, ch2, ch3, ch4); 32 unborrow!(ch1, ch2);
33 Self::new_inner(tim, freq, move || unsafe {
34 ch1.configure();
35 ch2.configure();
36 })
37 }
24 38
25 T::enable(); 39 pub fn new_3ch<F: Into<Hertz>>(
26 <T as crate::rcc::sealed::RccPeripheral>::reset(); 40 tim: impl Unborrow<Target = T> + 'd,
41 ch1: impl Unborrow<Target = impl Channel1Pin<T>> + 'd,
42 ch2: impl Unborrow<Target = impl Channel2Pin<T>> + 'd,
43 ch3: impl Unborrow<Target = impl Channel3Pin<T>> + 'd,
44 freq: F,
45 ) -> Self {
46 unborrow!(ch1, ch2, ch3);
47 Self::new_inner(tim, freq, move || unsafe {
48 ch1.configure();
49 ch2.configure();
50 ch3.configure();
51 })
52 }
27 53
28 unsafe { 54 pub fn new_4ch<F: Into<Hertz>>(
55 tim: impl Unborrow<Target = T> + 'd,
56 ch1: impl Unborrow<Target = impl Channel1Pin<T>> + 'd,
57 ch2: impl Unborrow<Target = impl Channel2Pin<T>> + 'd,
58 ch3: impl Unborrow<Target = impl Channel3Pin<T>> + 'd,
59 ch4: impl Unborrow<Target = impl Channel4Pin<T>> + 'd,
60 freq: F,
61 ) -> Self {
62 unborrow!(ch1, ch2, ch3, ch4);
63 Self::new_inner(tim, freq, move || unsafe {
29 ch1.configure(); 64 ch1.configure();
30 ch2.configure(); 65 ch2.configure();
31 ch3.configure(); 66 ch3.configure();
32 ch4.configure(); 67 ch4.configure();
33 } 68 })
69 }
70
71 fn new_inner<F: Into<Hertz>>(
72 tim: impl Unborrow<Target = T> + 'd,
73 freq: F,
74 configure_pins: impl FnOnce(),
75 ) -> Self {
76 unborrow!(tim);
77
78 T::enable();
79 <T as crate::rcc::sealed::RccPeripheral>::reset();
80
81 configure_pins();
34 82
35 let mut this = Self { 83 let mut this = Self {
36 inner: tim, 84 inner: tim,
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index 4cf45f6f9..469216236 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -8,8 +8,8 @@ use embassy_hal_common::unborrow;
8use self::sealed::WordSize; 8use self::sealed::WordSize;
9use crate::dma; 9use crate::dma;
10use crate::dma::NoDma; 10use crate::dma::NoDma;
11use crate::gpio::sealed::{AFType, Pin}; 11use crate::gpio::sealed::{AFType, Pin as _};
12use crate::gpio::{AnyPin, NoPin, OptionalPin}; 12use crate::gpio::{AnyPin, Pin};
13use crate::pac::spi::{regs, vals}; 13use crate::pac::spi::{regs, vals};
14use crate::peripherals; 14use crate::peripherals;
15use crate::rcc::RccPeripheral; 15use crate::rcc::RccPeripheral;
@@ -92,44 +92,125 @@ pub struct Spi<'d, T: Instance, Tx, Rx> {
92 92
93impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { 93impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
94 pub fn new<F>( 94 pub fn new<F>(
95 _peri: impl Unborrow<Target = T> + 'd, 95 peri: impl Unborrow<Target = T> + 'd,
96 sck: impl Unborrow<Target = impl SckPin<T>>, 96 sck: impl Unborrow<Target = impl SckPin<T>> + 'd,
97 mosi: impl Unborrow<Target = impl MosiPin<T>>, 97 mosi: impl Unborrow<Target = impl MosiPin<T>> + 'd,
98 miso: impl Unborrow<Target = impl MisoPin<T>>, 98 miso: impl Unborrow<Target = impl MisoPin<T>> + 'd,
99 txdma: impl Unborrow<Target = Tx>, 99 txdma: impl Unborrow<Target = Tx> + 'd,
100 rxdma: impl Unborrow<Target = Rx>, 100 rxdma: impl Unborrow<Target = Rx> + 'd,
101 freq: F, 101 freq: F,
102 config: Config, 102 config: Config,
103 ) -> Self 103 ) -> Self
104 where 104 where
105 F: Into<Hertz>, 105 F: Into<Hertz>,
106 { 106 {
107 unborrow!(sck, mosi, miso, txdma, rxdma); 107 unborrow!(sck, mosi, miso);
108 unsafe {
109 sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
110 #[cfg(any(spi_v2, spi_v3))]
111 sck.set_speed(crate::gpio::Speed::VeryHigh);
112 mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull);
113 #[cfg(any(spi_v2, spi_v3))]
114 mosi.set_speed(crate::gpio::Speed::VeryHigh);
115 miso.set_as_af(miso.af_num(), AFType::Input);
116 #[cfg(any(spi_v2, spi_v3))]
117 miso.set_speed(crate::gpio::Speed::VeryHigh);
118 }
119
120 Self::new_inner(
121 peri,
122 Some(sck.degrade()),
123 Some(mosi.degrade()),
124 Some(miso.degrade()),
125 txdma,
126 rxdma,
127 freq,
128 config,
129 )
130 }
108 131
109 let sck_af = sck.af_num(); 132 pub fn new_rxonly<F>(
110 let mosi_af = mosi.af_num(); 133 peri: impl Unborrow<Target = T> + 'd,
111 let miso_af = miso.af_num(); 134 sck: impl Unborrow<Target = impl SckPin<T>> + 'd,
112 let sck = sck.degrade_optional(); 135 miso: impl Unborrow<Target = impl MisoPin<T>> + 'd,
113 let mosi = mosi.degrade_optional(); 136 txdma: impl Unborrow<Target = Tx> + 'd, // TODO remove
114 let miso = miso.degrade_optional(); 137 rxdma: impl Unborrow<Target = Rx> + 'd,
138 freq: F,
139 config: Config,
140 ) -> Self
141 where
142 F: Into<Hertz>,
143 {
144 unborrow!(sck, miso);
145 unsafe {
146 sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
147 #[cfg(any(spi_v2, spi_v3))]
148 sck.set_speed(crate::gpio::Speed::VeryHigh);
149 miso.set_as_af(miso.af_num(), AFType::Input);
150 #[cfg(any(spi_v2, spi_v3))]
151 miso.set_speed(crate::gpio::Speed::VeryHigh);
152 }
153
154 Self::new_inner(
155 peri,
156 Some(sck.degrade()),
157 None,
158 Some(miso.degrade()),
159 txdma,
160 rxdma,
161 freq,
162 config,
163 )
164 }
115 165
166 pub fn new_txonly<F>(
167 peri: impl Unborrow<Target = T> + 'd,
168 sck: impl Unborrow<Target = impl SckPin<T>> + 'd,
169 mosi: impl Unborrow<Target = impl MosiPin<T>> + 'd,
170 txdma: impl Unborrow<Target = Tx> + 'd,
171 rxdma: impl Unborrow<Target = Rx> + 'd, // TODO remove
172 freq: F,
173 config: Config,
174 ) -> Self
175 where
176 F: Into<Hertz>,
177 {
178 unborrow!(sck, mosi);
116 unsafe { 179 unsafe {
117 sck.as_ref().map(|x| { 180 sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
118 x.set_as_af(sck_af, AFType::OutputPushPull); 181 #[cfg(any(spi_v2, spi_v3))]
119 #[cfg(any(spi_v2, spi_v3))] 182 sck.set_speed(crate::gpio::Speed::VeryHigh);
120 x.set_speed(crate::gpio::Speed::VeryHigh); 183 mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull);
121 }); 184 #[cfg(any(spi_v2, spi_v3))]
122 mosi.as_ref().map(|x| { 185 mosi.set_speed(crate::gpio::Speed::VeryHigh);
123 x.set_as_af(mosi_af, AFType::OutputPushPull); 186 }
124 #[cfg(any(spi_v2, spi_v3))] 187
125 x.set_speed(crate::gpio::Speed::VeryHigh); 188 Self::new_inner(
126 }); 189 peri,
127 miso.as_ref().map(|x| { 190 Some(sck.degrade()),
128 x.set_as_af(miso_af, AFType::Input); 191 Some(mosi.degrade()),
129 #[cfg(any(spi_v2, spi_v3))] 192 None,
130 x.set_speed(crate::gpio::Speed::VeryHigh); 193 txdma,
131 }); 194 rxdma,
132 } 195 freq,
196 config,
197 )
198 }
199
200 fn new_inner<F>(
201 _peri: impl Unborrow<Target = T> + 'd,
202 sck: Option<AnyPin>,
203 mosi: Option<AnyPin>,
204 miso: Option<AnyPin>,
205 txdma: impl Unborrow<Target = Tx>,
206 rxdma: impl Unborrow<Target = Rx>,
207 freq: F,
208 config: Config,
209 ) -> Self
210 where
211 F: Into<Hertz>,
212 {
213 unborrow!(txdma, rxdma);
133 214
134 let pclk = T::frequency(); 215 let pclk = T::frequency();
135 let br = compute_baud_rate(pclk, freq.into()); 216 let br = compute_baud_rate(pclk, freq.into());
@@ -719,15 +800,15 @@ pub(crate) mod sealed {
719 fn regs() -> &'static crate::pac::spi::Spi; 800 fn regs() -> &'static crate::pac::spi::Spi;
720 } 801 }
721 802
722 pub trait SckPin<T: Instance>: OptionalPin { 803 pub trait SckPin<T: Instance>: Pin {
723 fn af_num(&self) -> u8; 804 fn af_num(&self) -> u8;
724 } 805 }
725 806
726 pub trait MosiPin<T: Instance>: OptionalPin { 807 pub trait MosiPin<T: Instance>: Pin {
727 fn af_num(&self) -> u8; 808 fn af_num(&self) -> u8;
728 } 809 }
729 810
730 pub trait MisoPin<T: Instance>: OptionalPin { 811 pub trait MisoPin<T: Instance>: Pin {
731 fn af_num(&self) -> u8; 812 fn af_num(&self) -> u8;
732 } 813 }
733 814
@@ -865,26 +946,6 @@ crate::pac::peripheral_pins!(
865 }; 946 };
866); 947);
867 948
868macro_rules! impl_nopin {
869 ($inst:ident, $signal:ident) => {
870 impl $signal<peripherals::$inst> for NoPin {}
871
872 impl sealed::$signal<peripherals::$inst> for NoPin {
873 fn af_num(&self) -> u8 {
874 0
875 }
876 }
877 };
878}
879
880crate::pac::peripherals!(
881 (spi, $inst:ident) => {
882 impl_nopin!($inst, SckPin);
883 impl_nopin!($inst, MosiPin);
884 impl_nopin!($inst, MisoPin);
885 };
886);
887
888macro_rules! impl_dma { 949macro_rules! impl_dma {
889 ($inst:ident, {dmamux: $dmamux:ident}, $signal:ident, $request:expr) => { 950 ($inst:ident, {dmamux: $dmamux:ident}, $signal:ident, $request:expr) => {
890 impl<T> sealed::$signal<peripherals::$inst> for T 951 impl<T> sealed::$signal<peripherals::$inst> for T
diff --git a/embassy-stm32/src/subghz/mod.rs b/embassy-stm32/src/subghz/mod.rs
index 87f376c40..9c8b7f7ec 100644
--- a/embassy-stm32/src/subghz/mod.rs
+++ b/embassy-stm32/src/subghz/mod.rs
@@ -215,11 +215,11 @@ impl<'d, Tx, Rx> SubGhz<'d, Tx, Rx> {
215 /// clock. 215 /// clock.
216 pub fn new( 216 pub fn new(
217 peri: impl Unborrow<Target = SUBGHZSPI> + 'd, 217 peri: impl Unborrow<Target = SUBGHZSPI> + 'd,
218 sck: impl Unborrow<Target = impl SckPin<SUBGHZSPI>>, 218 sck: impl Unborrow<Target = impl SckPin<SUBGHZSPI>> + 'd,
219 mosi: impl Unborrow<Target = impl MosiPin<SUBGHZSPI>>, 219 mosi: impl Unborrow<Target = impl MosiPin<SUBGHZSPI>> + 'd,
220 miso: impl Unborrow<Target = impl MisoPin<SUBGHZSPI>>, 220 miso: impl Unborrow<Target = impl MisoPin<SUBGHZSPI>> + 'd,
221 txdma: impl Unborrow<Target = Tx>, 221 txdma: impl Unborrow<Target = Tx> + 'd,
222 rxdma: impl Unborrow<Target = Rx>, 222 rxdma: impl Unborrow<Target = Rx> + 'd,
223 ) -> Self { 223 ) -> Self {
224 Self::pulse_radio_reset(); 224 Self::pulse_radio_reset();
225 225
diff --git a/examples/stm32g4/src/bin/pwm.rs b/examples/stm32g4/src/bin/pwm.rs
index 3dd45318d..fb71c8b7d 100644
--- a/examples/stm32g4/src/bin/pwm.rs
+++ b/examples/stm32g4/src/bin/pwm.rs
@@ -6,7 +6,6 @@
6mod example_common; 6mod example_common;
7use embassy::executor::Spawner; 7use embassy::executor::Spawner;
8use embassy::time::{Duration, Timer}; 8use embassy::time::{Duration, Timer};
9use embassy_stm32::gpio::NoPin;
10use embassy_stm32::pwm::{simple_pwm::SimplePwm, Channel}; 9use embassy_stm32::pwm::{simple_pwm::SimplePwm, Channel};
11use embassy_stm32::time::U32Ext; 10use embassy_stm32::time::U32Ext;
12use embassy_stm32::Peripherals; 11use embassy_stm32::Peripherals;
@@ -16,7 +15,7 @@ use example_common::*;
16async fn main(_spawner: Spawner, p: Peripherals) { 15async fn main(_spawner: Spawner, p: Peripherals) {
17 info!("Hello World!"); 16 info!("Hello World!");
18 17
19 let mut pwm = SimplePwm::new(p.TIM2, p.PA5, NoPin, NoPin, NoPin, 10000.hz()); 18 let mut pwm = SimplePwm::new_1ch(p.TIM2, p.PA5, 10000.hz());
20 let max = pwm.get_max_duty(); 19 let max = pwm.get_max_duty();
21 pwm.enable(Channel::Ch1); 20 pwm.enable(Channel::Ch1);
22 21
diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs
index 9760d0f74..f87b27f4f 100644
--- a/examples/stm32h7/src/bin/camera.rs
+++ b/examples/stm32h7/src/bin/camera.rs
@@ -4,8 +4,8 @@
4 4
5use embassy::executor::Spawner; 5use embassy::executor::Spawner;
6use embassy::time::{Duration, Timer}; 6use embassy::time::{Duration, Timer};
7use embassy_stm32::dcmi::*; 7use embassy_stm32::dcmi::{self, *};
8use embassy_stm32::gpio::{Level, NoPin, Output, Speed}; 8use embassy_stm32::gpio::{Level, Output, Speed};
9use embassy_stm32::i2c::I2c; 9use embassy_stm32::i2c::I2c;
10use embassy_stm32::interrupt; 10use embassy_stm32::interrupt;
11use embassy_stm32::rcc::{Mco, Mco1Source, McoClock}; 11use embassy_stm32::rcc::{Mco, Mco1Source, McoClock};
@@ -78,31 +78,10 @@ async fn main(_spawner: Spawner, p: Peripherals) {
78 ); 78 );
79 79
80 let dcmi_irq = interrupt::take!(DCMI); 80 let dcmi_irq = interrupt::take!(DCMI);
81 let mut dcmi = Dcmi::new( 81 let config = dcmi::Config::default();
82 p.DCMI, 82 let mut dcmi = Dcmi::new_8bit(
83 p.DMA1_CH0, 83 p.DCMI, p.DMA1_CH0, dcmi_irq, p.PC6, p.PC7, p.PE0, p.PE1, p.PE4, p.PD3, p.PE5, p.PE6,
84 VSyncDataInvalidLevel::High, 84 p.PB7, p.PA4, p.PA6, config,
85 HSyncDataInvalidLevel::Low,
86 PixelClockPolarity::RisingEdge,
87 false,
88 dcmi_irq,
89 p.PC6,
90 p.PC7,
91 p.PE0,
92 p.PE1,
93 p.PE4,
94 p.PD3,
95 p.PE5,
96 p.PE6,
97 NoPin,
98 NoPin,
99 NoPin,
100 NoPin,
101 NoPin,
102 NoPin,
103 p.PB7,
104 p.PA4,
105 p.PA6,
106 ); 85 );
107 86
108 defmt::info!("attempting capture"); 87 defmt::info!("attempting capture");
diff --git a/examples/stm32h7/src/bin/dac.rs b/examples/stm32h7/src/bin/dac.rs
index 4cd2f2cd1..8353405ad 100644
--- a/examples/stm32h7/src/bin/dac.rs
+++ b/examples/stm32h7/src/bin/dac.rs
@@ -5,7 +5,6 @@
5#[path = "../example_common.rs"] 5#[path = "../example_common.rs"]
6mod example_common; 6mod example_common;
7 7
8use embassy_stm32::gpio::NoPin;
9use example_common::*; 8use example_common::*;
10 9
11use cortex_m_rt::entry; 10use cortex_m_rt::entry;
@@ -17,7 +16,7 @@ fn main() -> ! {
17 16
18 let p = embassy_stm32::init(config()); 17 let p = embassy_stm32::init(config());
19 18
20 let mut dac = Dac::new(p.DAC1, p.PA4, NoPin); 19 let mut dac = Dac::new_1ch(p.DAC1, p.PA4);
21 20
22 loop { 21 loop {
23 for v in 0..=255 { 22 for v in 0..=255 {
diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs
index 2640f249d..1bf69104d 100644
--- a/examples/stm32h7/src/bin/low_level_timer_api.rs
+++ b/examples/stm32h7/src/bin/low_level_timer_api.rs
@@ -10,7 +10,6 @@ use embassy::executor::Spawner;
10use embassy::time::{Duration, Timer}; 10use embassy::time::{Duration, Timer};
11use embassy::util::Unborrow; 11use embassy::util::Unborrow;
12use embassy_hal_common::unborrow; 12use embassy_hal_common::unborrow;
13use embassy_stm32::gpio::NoPin;
14use embassy_stm32::pwm::{pins::*, Channel, OutputCompareMode}; 13use embassy_stm32::pwm::{pins::*, Channel, OutputCompareMode};
15use embassy_stm32::time::{Hertz, U32Ext}; 14use embassy_stm32::time::{Hertz, U32Ext};
16use embassy_stm32::timer::GeneralPurpose32bitInstance; 15use embassy_stm32::timer::GeneralPurpose32bitInstance;
@@ -33,7 +32,7 @@ pub fn config() -> Config {
33async fn main(_spawner: Spawner, p: Peripherals) { 32async fn main(_spawner: Spawner, p: Peripherals) {
34 info!("Hello World!"); 33 info!("Hello World!");
35 34
36 let mut pwm = SimplePwm32::new(p.TIM5, p.PA0, NoPin, NoPin, NoPin, 10000.hz()); 35 let mut pwm = SimplePwm32::new(p.TIM5, p.PA0, p.PA1, p.PA2, p.PA3, 10000.hz());
37 let max = pwm.get_max_duty(); 36 let max = pwm.get_max_duty();
38 pwm.enable(Channel::Ch1); 37 pwm.enable(Channel::Ch1);
39 38
diff --git a/examples/stm32h7/src/bin/pwm.rs b/examples/stm32h7/src/bin/pwm.rs
index 020150a39..b3edbde68 100644
--- a/examples/stm32h7/src/bin/pwm.rs
+++ b/examples/stm32h7/src/bin/pwm.rs
@@ -6,7 +6,6 @@
6mod example_common; 6mod example_common;
7use embassy::executor::Spawner; 7use embassy::executor::Spawner;
8use embassy::time::{Duration, Timer}; 8use embassy::time::{Duration, Timer};
9use embassy_stm32::gpio::NoPin;
10use embassy_stm32::pwm::{simple_pwm::SimplePwm, Channel}; 9use embassy_stm32::pwm::{simple_pwm::SimplePwm, Channel};
11use embassy_stm32::time::U32Ext; 10use embassy_stm32::time::U32Ext;
12use embassy_stm32::{Config, Peripherals}; 11use embassy_stm32::{Config, Peripherals};
@@ -28,7 +27,7 @@ pub fn config() -> Config {
28async fn main(_spawner: Spawner, p: Peripherals) { 27async fn main(_spawner: Spawner, p: Peripherals) {
29 info!("Hello World!"); 28 info!("Hello World!");
30 29
31 let mut pwm = SimplePwm::new(p.TIM3, p.PA6, NoPin, NoPin, NoPin, 10000.hz()); 30 let mut pwm = SimplePwm::new_1ch(p.TIM3, p.PA6, 10000.hz());
32 let max = pwm.get_max_duty(); 31 let max = pwm.get_max_duty();
33 pwm.enable(Channel::Ch1); 32 pwm.enable(Channel::Ch1);
34 33
diff --git a/examples/stm32l4/src/bin/dac.rs b/examples/stm32l4/src/bin/dac.rs
index 6cdd6d3ff..201ba473b 100644
--- a/examples/stm32l4/src/bin/dac.rs
+++ b/examples/stm32l4/src/bin/dac.rs
@@ -6,7 +6,6 @@
6mod example_common; 6mod example_common;
7 7
8use embassy_stm32::dac::{Channel, Dac, Value}; 8use embassy_stm32::dac::{Channel, Dac, Value};
9use embassy_stm32::gpio::NoPin;
10use embassy_stm32::pac; 9use embassy_stm32::pac;
11use example_common::*; 10use example_common::*;
12 11
@@ -22,7 +21,7 @@ fn main() -> ! {
22 21
23 let p = embassy_stm32::init(Default::default()); 22 let p = embassy_stm32::init(Default::default());
24 23
25 let mut dac = Dac::new(p.DAC1, p.PA4, NoPin); 24 let mut dac = Dac::new_1ch(p.DAC1, p.PA4);
26 25
27 loop { 26 loop {
28 for v in 0..=255 { 27 for v in 0..=255 {