aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThales Fragoso <[email protected]>2021-06-23 19:22:53 -0300
committerThales Fragoso <[email protected]>2021-06-24 20:42:43 -0300
commitefb3b3a0a8577059896100336f430c4eb45c544f (patch)
treeef21daa36cca9245c2cc48919e603b0eadcd1042
parente1880a19df2f91757aa34a21b670da22ccb81440 (diff)
stm32: Allow for open drain configuration for output pin
-rw-r--r--embassy-stm32/src/gpio.rs57
1 files changed, 56 insertions, 1 deletions
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs
index 873c73b4e..e562dcab7 100644
--- a/embassy-stm32/src/gpio.rs
+++ b/embassy-stm32/src/gpio.rs
@@ -18,6 +18,31 @@ pub enum Pull {
18 Down, 18 Down,
19} 19}
20 20
21/// Pull setting for an input.
22#[derive(Debug)]
23#[cfg_attr(feature = "defmt", derive(defmt::Format))]
24pub enum Speed {
25 LowSpeed,
26 MediumSpeed,
27 #[cfg(not(syscfg_f0))]
28 HighSpeed,
29 VeryHighSpeed,
30}
31
32impl From<Speed> for vals::Ospeedr {
33 fn from(speed: Speed) -> Self {
34 use Speed::*;
35
36 match speed {
37 LowSpeed => vals::Ospeedr::LOWSPEED,
38 MediumSpeed => vals::Ospeedr::MEDIUMSPEED,
39 #[cfg(not(syscfg_f0))]
40 HighSpeed => vals::Ospeedr::HIGHSPEED,
41 VeryHighSpeed => vals::Ospeedr::VERYHIGHSPEED,
42 }
43 }
44}
45
21/// GPIO input driver. 46/// GPIO input driver.
22pub struct Input<'d, T: Pin> { 47pub struct Input<'d, T: Pin> {
23 pub(crate) pin: T, 48 pub(crate) pin: T,
@@ -86,7 +111,12 @@ pub struct Output<'d, T: Pin> {
86} 111}
87 112
88impl<'d, T: Pin> Output<'d, T> { 113impl<'d, T: Pin> Output<'d, T> {
89 pub fn new(pin: impl Unborrow<Target = T> + 'd, initial_output: Level) -> Self { 114 pub fn new(
115 pin: impl Unborrow<Target = T> + 'd,
116 initial_output: Level,
117 speed: Speed,
118 open_drain: bool,
119 ) -> Self {
90 unborrow!(pin); 120 unborrow!(pin);
91 121
92 match initial_output { 122 match initial_output {
@@ -99,6 +129,10 @@ impl<'d, T: Pin> Output<'d, T> {
99 let n = pin.pin() as usize; 129 let n = pin.pin() as usize;
100 r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING)); 130 r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING));
101 r.moder().modify(|w| w.set_moder(n, vals::Moder::OUTPUT)); 131 r.moder().modify(|w| w.set_moder(n, vals::Moder::OUTPUT));
132 if open_drain {
133 r.otyper().modify(|w| w.set_ot(n, vals::Ot::OPENDRAIN));
134 }
135 pin.set_speed(speed);
102 }); 136 });
103 137
104 Self { 138 Self {
@@ -115,6 +149,8 @@ impl<'d, T: Pin> Drop for Output<'d, T> {
115 let n = self.pin.pin() as usize; 149 let n = self.pin.pin() as usize;
116 r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING)); 150 r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING));
117 r.moder().modify(|w| w.set_moder(n, vals::Moder::INPUT)); 151 r.moder().modify(|w| w.set_moder(n, vals::Moder::INPUT));
152 r.otyper().modify(|w| w.set_ot(n, vals::Ot::PUSHPULL));
153 self.pin.set_speed(Speed::LowSpeed);
118 }); 154 });
119 } 155 }
120} 156}
@@ -148,6 +184,18 @@ impl<'d, T: Pin> StatefulOutputPin for Output<'d, T> {
148 } 184 }
149} 185}
150 186
187impl<'d, T: Pin> InputPin for Output<'d, T> {
188 type Error = Infallible;
189
190 fn is_high(&self) -> Result<bool, Self::Error> {
191 self.is_set_high()
192 }
193
194 fn is_low(&self) -> Result<bool, Self::Error> {
195 self.is_set_low()
196 }
197}
198
151impl<'d, T: Pin> toggleable::Default for Output<'d, T> {} 199impl<'d, T: Pin> toggleable::Default for Output<'d, T> {}
152 200
153pub(crate) mod sealed { 201pub(crate) mod sealed {
@@ -206,6 +254,13 @@ pub(crate) mod sealed {
206 .moder() 254 .moder()
207 .modify(|w| w.set_moder(pin, vals::Moder::ANALOG)); 255 .modify(|w| w.set_moder(pin, vals::Moder::ANALOG));
208 } 256 }
257
258 unsafe fn set_speed(&self, speed: Speed) {
259 let pin = self._pin() as usize;
260 self.block()
261 .ospeedr()
262 .modify(|w| w.set_ospeedr(pin, speed.into()));
263 }
209 } 264 }
210 265
211 pub trait OptionalPin {} 266 pub trait OptionalPin {}