diff options
| author | Dario Nieuwenhuis <[email protected]> | 2022-02-10 02:34:59 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2022-02-10 02:38:10 +0100 |
| commit | 550da471be7b56927b50b5955a6de0916ebe6b1f (patch) | |
| tree | 27b37e111dce9a3a5327c901c1bf139b1c1486d0 | |
| parent | 1d265b73b2f46baf60a481c8b8036e50c2b6583f (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.rs | 8 | ||||
| -rw-r--r-- | embassy-stm32/src/dac/v2.rs | 221 | ||||
| -rw-r--r-- | embassy-stm32/src/dcmi.rs | 314 | ||||
| -rw-r--r-- | embassy-stm32/src/gpio.rs | 48 | ||||
| -rw-r--r-- | embassy-stm32/src/pwm/mod.rs | 25 | ||||
| -rw-r--r-- | embassy-stm32/src/pwm/pins.rs | 70 | ||||
| -rw-r--r-- | embassy-stm32/src/pwm/simple_pwm.rs | 64 | ||||
| -rw-r--r-- | embassy-stm32/src/spi/mod.rs | 169 | ||||
| -rw-r--r-- | embassy-stm32/src/subghz/mod.rs | 10 | ||||
| -rw-r--r-- | examples/stm32g4/src/bin/pwm.rs | 3 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/camera.rs | 33 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/dac.rs | 3 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/low_level_timer_api.rs | 3 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/pwm.rs | 3 | ||||
| -rw-r--r-- | examples/stm32l4/src/bin/dac.rs | 3 |
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")] |
| 5 | mod _version; | 5 | mod _version; |
| 6 | use crate::gpio::NoPin; | ||
| 7 | use crate::peripherals; | 6 | use crate::peripherals; |
| 8 | pub use _version::*; | 7 | pub use _version::*; |
| 9 | 8 | ||
| 10 | pub(crate) mod sealed { | 9 | pub(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 | ||
| 20 | pub trait Instance: sealed::Instance + 'static {} | 17 | pub trait Instance: sealed::Instance + 'static {} |
| 21 | 18 | ||
| 22 | pub trait DacPin<T: Instance, const C: u8>: sealed::DacPin<T, C> + 'static {} | 19 | pub trait DacPin<T: Instance, const C: u8>: sealed::DacPin<T, C> + 'static {} |
| 23 | 20 | ||
| 24 | impl<T: Instance, const C: u8> DacPin<T, C> for NoPin {} | ||
| 25 | impl<T: Instance, const C: u8> sealed::DacPin<T, C> for NoPin {} | ||
| 26 | |||
| 27 | crate::pac::peripherals!( | 21 | crate::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 @@ | |||
| 1 | use crate::dac::{DacPin, Instance}; | 1 | use crate::dac::{DacPin, Instance}; |
| 2 | use crate::gpio::AnyPin; | ||
| 3 | use crate::pac::dac; | 2 | use crate::pac::dac; |
| 4 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 5 | use embassy::util::Unborrow; | 4 | use embassy::util::Unborrow; |
| 6 | use embassy_hal_common::unborrow; | 5 | use 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. | ||
| 10 | unsafe 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))] |
| 21 | pub enum Error { | 9 | pub 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))] | ||
| 26 | pub enum Channel { | 16 | pub 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))] | ||
| 31 | pub enum Ch1Trigger { | 23 | pub 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))] | ||
| 55 | pub enum Ch2Trigger { | 49 | pub 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))] | ||
| 81 | pub enum Alignment { | 77 | pub 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))] | ||
| 86 | pub enum Value { | 84 | pub enum Value { |
| 87 | Bit8(u8), | 85 | Bit8(u8), |
| 88 | Bit12(u16, Alignment), | 86 | Bit12(u16, Alignment), |
| 89 | } | 87 | } |
| 90 | 88 | ||
| 91 | pub struct Dac<'d, T: Instance> { | 89 | pub 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 | ||
| 97 | impl<'d, T: Instance> Dac<'d, T> { | 94 | impl<'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; | |||
| 9 | use embassy_hal_common::unborrow; | 9 | use embassy_hal_common::unborrow; |
| 10 | use futures::future::poll_fn; | 10 | use futures::future::poll_fn; |
| 11 | 11 | ||
| 12 | #[macro_export] | ||
| 13 | macro_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)] |
| 14 | pub enum VSyncDataInvalidLevel { | 23 | pub enum VSyncDataInvalidLevel { |
| @@ -50,6 +59,23 @@ pub enum Error { | |||
| 50 | PeripheralError, | 59 | PeripheralError, |
| 51 | } | 60 | } |
| 52 | 61 | ||
| 62 | #[non_exhaustive] | ||
| 63 | pub struct Config { | ||
| 64 | pub vsync_level: VSyncDataInvalidLevel, | ||
| 65 | pub hsync_level: HSyncDataInvalidLevel, | ||
| 66 | pub pixclk_polarity: PixelClockPolarity, | ||
| 67 | } | ||
| 68 | |||
| 69 | impl 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 | |||
| 53 | pub struct Dcmi<'d, T: Instance, Dma: FrameDma> { | 79 | pub 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 | ||
| 411 | macro_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 | |||
| 420 | impl_no_pin!(D8Pin); | ||
| 421 | impl_no_pin!(D9Pin); | ||
| 422 | impl_no_pin!(D10Pin); | ||
| 423 | impl_no_pin!(D11Pin); | ||
| 424 | impl_no_pin!(D12Pin); | ||
| 425 | impl_no_pin!(D13Pin); | ||
| 426 | impl_no_pin!(HSyncPin); | ||
| 427 | impl_no_pin!(VSyncPin); | ||
| 428 | |||
| 429 | crate::pac::peripheral_pins!( | 575 | crate::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 | ||
| 547 | pub 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 | |||
| 560 | impl<T: Pin> sealed::OptionalPin for T {} | ||
| 561 | impl<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)] | ||
| 576 | pub struct NoPin; | ||
| 577 | unsafe_impl_unborrow!(NoPin); | ||
| 578 | impl sealed::OptionalPin for NoPin {} | ||
| 579 | impl 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 | |||
| 595 | crate::pac::pins!( | 547 | crate::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)] | ||
| 252 | macro_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 | |||
| 272 | crate::pac::peripherals!( | ||
| 273 | (timer, $inst:ident) => { impl_pwm_nopin!($inst); }; | ||
| 274 | ); | ||
| 275 | |||
| 276 | crate::pac::peripheral_pins!( | 251 | crate::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 @@ | |||
| 1 | use crate::gpio::OptionalPin; | 1 | use crate::gpio::Pin; |
| 2 | 2 | ||
| 3 | #[cfg(feature = "unstable-pac")] | 3 | #[cfg(feature = "unstable-pac")] |
| 4 | pub mod low_level { | 4 | pub mod low_level { |
| @@ -6,118 +6,106 @@ pub mod low_level { | |||
| 6 | } | 6 | } |
| 7 | 7 | ||
| 8 | pub(crate) mod sealed { | 8 | pub(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 | } |
| 63 | pub trait Channel1Pin<Timer>: sealed::Channel1Pin<Timer> + OptionalPin + 'static {} | 63 | pub trait Channel1Pin<Timer>: sealed::Channel1Pin<Timer> + Pin + 'static {} |
| 64 | pub trait Channel1ComplementaryPin<Timer>: | 64 | pub trait Channel1ComplementaryPin<Timer>: |
| 65 | sealed::Channel1ComplementaryPin<Timer> + OptionalPin + 'static | 65 | sealed::Channel1ComplementaryPin<Timer> + Pin + 'static |
| 66 | { | 66 | { |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | pub trait Channel2Pin<Timer>: sealed::Channel2Pin<Timer> + 'static {} | 69 | pub trait Channel2Pin<Timer>: sealed::Channel2Pin<Timer> + 'static {} |
| 70 | pub trait Channel2ComplementaryPin<Timer>: | 70 | pub trait Channel2ComplementaryPin<Timer>: |
| 71 | sealed::Channel2ComplementaryPin<Timer> + OptionalPin + 'static | 71 | sealed::Channel2ComplementaryPin<Timer> + Pin + 'static |
| 72 | { | 72 | { |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | pub trait Channel3Pin<Timer>: sealed::Channel3Pin<Timer> + 'static {} | 75 | pub trait Channel3Pin<Timer>: sealed::Channel3Pin<Timer> + 'static {} |
| 76 | pub trait Channel3ComplementaryPin<Timer>: | 76 | pub trait Channel3ComplementaryPin<Timer>: |
| 77 | sealed::Channel3ComplementaryPin<Timer> + OptionalPin + 'static | 77 | sealed::Channel3ComplementaryPin<Timer> + Pin + 'static |
| 78 | { | 78 | { |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | pub trait Channel4Pin<Timer>: sealed::Channel4Pin<Timer> + 'static {} | 81 | pub trait Channel4Pin<Timer>: sealed::Channel4Pin<Timer> + 'static {} |
| 82 | pub trait Channel4ComplementaryPin<Timer>: | 82 | pub trait Channel4ComplementaryPin<Timer>: |
| 83 | sealed::Channel4ComplementaryPin<Timer> + OptionalPin + 'static | 83 | sealed::Channel4ComplementaryPin<Timer> + Pin + 'static |
| 84 | { | 84 | { |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | pub trait ExternalTriggerPin<Timer>: | 87 | pub trait ExternalTriggerPin<Timer>: sealed::ExternalTriggerPin<Timer> + Pin + 'static {} |
| 88 | sealed::ExternalTriggerPin<Timer> + OptionalPin + 'static | ||
| 89 | { | ||
| 90 | } | ||
| 91 | 88 | ||
| 92 | pub trait BreakInputPin<Timer>: sealed::BreakInputPin<Timer> + OptionalPin + 'static {} | 89 | pub trait BreakInputPin<Timer>: sealed::BreakInputPin<Timer> + Pin + 'static {} |
| 93 | pub trait BreakInputComparator1Pin<Timer>: | 90 | pub trait BreakInputComparator1Pin<Timer>: |
| 94 | sealed::BreakInputComparator1Pin<Timer> + OptionalPin + 'static | 91 | sealed::BreakInputComparator1Pin<Timer> + Pin + 'static |
| 95 | { | 92 | { |
| 96 | } | 93 | } |
| 97 | pub trait BreakInputComparator2Pin<Timer>: | 94 | pub trait BreakInputComparator2Pin<Timer>: |
| 98 | sealed::BreakInputComparator2Pin<Timer> + OptionalPin + 'static | 95 | sealed::BreakInputComparator2Pin<Timer> + Pin + 'static |
| 99 | { | 96 | { |
| 100 | } | 97 | } |
| 101 | 98 | ||
| 102 | pub trait BreakInput2Pin<Timer>: sealed::BreakInput2Pin<Timer> + OptionalPin + 'static {} | 99 | pub trait BreakInput2Pin<Timer>: sealed::BreakInput2Pin<Timer> + Pin + 'static {} |
| 103 | pub trait BreakInput2Comparator1Pin<Timer>: | 100 | pub trait BreakInput2Comparator1Pin<Timer>: |
| 104 | sealed::BreakInput2Comparator1Pin<Timer> + OptionalPin + 'static | 101 | sealed::BreakInput2Comparator1Pin<Timer> + Pin + 'static |
| 105 | { | 102 | { |
| 106 | } | 103 | } |
| 107 | pub trait BreakInput2Comparator2Pin<Timer>: | 104 | pub trait BreakInput2Comparator2Pin<Timer>: |
| 108 | sealed::BreakInput2Comparator2Pin<Timer> + OptionalPin + 'static | 105 | sealed::BreakInput2Comparator2Pin<Timer> + Pin + 'static |
| 109 | { | 106 | { |
| 110 | } | 107 | } |
| 111 | 108 | ||
| 112 | macro_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)] |
| 122 | macro_rules! impl_pin { | 110 | macro_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 | ||
| 14 | impl<'d, T: CaptureCompareCapable16bitInstance> SimplePwm<'d, T> { | 14 | impl<'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; | |||
| 8 | use self::sealed::WordSize; | 8 | use self::sealed::WordSize; |
| 9 | use crate::dma; | 9 | use crate::dma; |
| 10 | use crate::dma::NoDma; | 10 | use crate::dma::NoDma; |
| 11 | use crate::gpio::sealed::{AFType, Pin}; | 11 | use crate::gpio::sealed::{AFType, Pin as _}; |
| 12 | use crate::gpio::{AnyPin, NoPin, OptionalPin}; | 12 | use crate::gpio::{AnyPin, Pin}; |
| 13 | use crate::pac::spi::{regs, vals}; | 13 | use crate::pac::spi::{regs, vals}; |
| 14 | use crate::peripherals; | 14 | use crate::peripherals; |
| 15 | use crate::rcc::RccPeripheral; | 15 | use crate::rcc::RccPeripheral; |
| @@ -92,44 +92,125 @@ pub struct Spi<'d, T: Instance, Tx, Rx> { | |||
| 92 | 92 | ||
| 93 | impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | 93 | impl<'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 | ||
| 868 | macro_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 | |||
| 880 | crate::pac::peripherals!( | ||
| 881 | (spi, $inst:ident) => { | ||
| 882 | impl_nopin!($inst, SckPin); | ||
| 883 | impl_nopin!($inst, MosiPin); | ||
| 884 | impl_nopin!($inst, MisoPin); | ||
| 885 | }; | ||
| 886 | ); | ||
| 887 | |||
| 888 | macro_rules! impl_dma { | 949 | macro_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 @@ | |||
| 6 | mod example_common; | 6 | mod example_common; |
| 7 | use embassy::executor::Spawner; | 7 | use embassy::executor::Spawner; |
| 8 | use embassy::time::{Duration, Timer}; | 8 | use embassy::time::{Duration, Timer}; |
| 9 | use embassy_stm32::gpio::NoPin; | ||
| 10 | use embassy_stm32::pwm::{simple_pwm::SimplePwm, Channel}; | 9 | use embassy_stm32::pwm::{simple_pwm::SimplePwm, Channel}; |
| 11 | use embassy_stm32::time::U32Ext; | 10 | use embassy_stm32::time::U32Ext; |
| 12 | use embassy_stm32::Peripherals; | 11 | use embassy_stm32::Peripherals; |
| @@ -16,7 +15,7 @@ use example_common::*; | |||
| 16 | async fn main(_spawner: Spawner, p: Peripherals) { | 15 | async 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 | ||
| 5 | use embassy::executor::Spawner; | 5 | use embassy::executor::Spawner; |
| 6 | use embassy::time::{Duration, Timer}; | 6 | use embassy::time::{Duration, Timer}; |
| 7 | use embassy_stm32::dcmi::*; | 7 | use embassy_stm32::dcmi::{self, *}; |
| 8 | use embassy_stm32::gpio::{Level, NoPin, Output, Speed}; | 8 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 9 | use embassy_stm32::i2c::I2c; | 9 | use embassy_stm32::i2c::I2c; |
| 10 | use embassy_stm32::interrupt; | 10 | use embassy_stm32::interrupt; |
| 11 | use embassy_stm32::rcc::{Mco, Mco1Source, McoClock}; | 11 | use 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"] |
| 6 | mod example_common; | 6 | mod example_common; |
| 7 | 7 | ||
| 8 | use embassy_stm32::gpio::NoPin; | ||
| 9 | use example_common::*; | 8 | use example_common::*; |
| 10 | 9 | ||
| 11 | use cortex_m_rt::entry; | 10 | use 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; | |||
| 10 | use embassy::time::{Duration, Timer}; | 10 | use embassy::time::{Duration, Timer}; |
| 11 | use embassy::util::Unborrow; | 11 | use embassy::util::Unborrow; |
| 12 | use embassy_hal_common::unborrow; | 12 | use embassy_hal_common::unborrow; |
| 13 | use embassy_stm32::gpio::NoPin; | ||
| 14 | use embassy_stm32::pwm::{pins::*, Channel, OutputCompareMode}; | 13 | use embassy_stm32::pwm::{pins::*, Channel, OutputCompareMode}; |
| 15 | use embassy_stm32::time::{Hertz, U32Ext}; | 14 | use embassy_stm32::time::{Hertz, U32Ext}; |
| 16 | use embassy_stm32::timer::GeneralPurpose32bitInstance; | 15 | use embassy_stm32::timer::GeneralPurpose32bitInstance; |
| @@ -33,7 +32,7 @@ pub fn config() -> Config { | |||
| 33 | async fn main(_spawner: Spawner, p: Peripherals) { | 32 | async 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 @@ | |||
| 6 | mod example_common; | 6 | mod example_common; |
| 7 | use embassy::executor::Spawner; | 7 | use embassy::executor::Spawner; |
| 8 | use embassy::time::{Duration, Timer}; | 8 | use embassy::time::{Duration, Timer}; |
| 9 | use embassy_stm32::gpio::NoPin; | ||
| 10 | use embassy_stm32::pwm::{simple_pwm::SimplePwm, Channel}; | 9 | use embassy_stm32::pwm::{simple_pwm::SimplePwm, Channel}; |
| 11 | use embassy_stm32::time::U32Ext; | 10 | use embassy_stm32::time::U32Ext; |
| 12 | use embassy_stm32::{Config, Peripherals}; | 11 | use embassy_stm32::{Config, Peripherals}; |
| @@ -28,7 +27,7 @@ pub fn config() -> Config { | |||
| 28 | async fn main(_spawner: Spawner, p: Peripherals) { | 27 | async 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 @@ | |||
| 6 | mod example_common; | 6 | mod example_common; |
| 7 | 7 | ||
| 8 | use embassy_stm32::dac::{Channel, Dac, Value}; | 8 | use embassy_stm32::dac::{Channel, Dac, Value}; |
| 9 | use embassy_stm32::gpio::NoPin; | ||
| 10 | use embassy_stm32::pac; | 9 | use embassy_stm32::pac; |
| 11 | use example_common::*; | 10 | use 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 { |
