aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-06-27 19:29:18 +0200
committerGitHub <[email protected]>2021-06-27 19:29:18 +0200
commitcdb0c72849558db2b210301f5d13a922308e6bf1 (patch)
tree7e6eb381344d908805e88c8dbb95f70d36c6fbb7
parente6d6e82e54bca88ab1144802d2b716b867934225 (diff)
parentc5022b1196e45fb772d902fd0f4dbced2ef120eb (diff)
Merge pull request #255 from thalesfragoso/od-pin
stm32: Allow for open drain configuration for output pin
-rw-r--r--embassy-stm32/src/gpio.rs132
-rw-r--r--examples/stm32f4/src/bin/blinky.rs4
-rw-r--r--examples/stm32f4/src/bin/button.rs8
-rw-r--r--examples/stm32f4/src/bin/spi.rs4
-rw-r--r--examples/stm32h7/src/bin/blinky.rs10
-rw-r--r--examples/stm32l0/src/bin/blinky.rs4
-rw-r--r--examples/stm32l0/src/bin/button.rs6
-rw-r--r--examples/stm32l0/src/bin/spi.rs4
-rw-r--r--examples/stm32l4/src/bin/blinky.rs4
-rw-r--r--examples/stm32l4/src/bin/button.rs6
-rw-r--r--examples/stm32l4/src/bin/spi.rs4
-rw-r--r--examples/stm32wb55/src/bin/blinky.rs4
12 files changed, 153 insertions, 37 deletions
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs
index 873c73b4e..bf8400ca9 100644
--- a/embassy-stm32/src/gpio.rs
+++ b/embassy-stm32/src/gpio.rs
@@ -18,6 +18,43 @@ pub enum Pull {
18 Down, 18 Down,
19} 19}
20 20
21impl From<Pull> for vals::Pupdr {
22 fn from(pull: Pull) -> Self {
23 use Pull::*;
24
25 match pull {
26 None => vals::Pupdr::FLOATING,
27 Up => vals::Pupdr::PULLUP,
28 Down => vals::Pupdr::PULLDOWN,
29 }
30 }
31}
32
33/// Speed settings
34#[derive(Debug)]
35#[cfg_attr(feature = "defmt", derive(defmt::Format))]
36pub enum Speed {
37 Low,
38 Medium,
39 #[cfg(not(syscfg_f0))]
40 High,
41 VeryHigh,
42}
43
44impl From<Speed> for vals::Ospeedr {
45 fn from(speed: Speed) -> Self {
46 use Speed::*;
47
48 match speed {
49 Low => vals::Ospeedr::LOWSPEED,
50 Medium => vals::Ospeedr::MEDIUMSPEED,
51 #[cfg(not(syscfg_f0))]
52 High => vals::Ospeedr::HIGHSPEED,
53 VeryHigh => vals::Ospeedr::VERYHIGHSPEED,
54 }
55 }
56}
57
21/// GPIO input driver. 58/// GPIO input driver.
22pub struct Input<'d, T: Pin> { 59pub struct Input<'d, T: Pin> {
23 pub(crate) pin: T, 60 pub(crate) pin: T,
@@ -31,12 +68,7 @@ impl<'d, T: Pin> Input<'d, T> {
31 cortex_m::interrupt::free(|_| unsafe { 68 cortex_m::interrupt::free(|_| unsafe {
32 let r = pin.block(); 69 let r = pin.block();
33 let n = pin.pin() as usize; 70 let n = pin.pin() as usize;
34 let val = match pull { 71 r.pupdr().modify(|w| w.set_pupdr(n, pull.into()));
35 Pull::None => vals::Pupdr::FLOATING,
36 Pull::Up => vals::Pupdr::PULLUP,
37 Pull::Down => vals::Pupdr::PULLDOWN,
38 };
39 r.pupdr().modify(|w| w.set_pupdr(n, val));
40 r.otyper().modify(|w| w.set_ot(n, vals::Ot::PUSHPULL)); 72 r.otyper().modify(|w| w.set_ot(n, vals::Ot::PUSHPULL));
41 r.moder().modify(|w| w.set_moder(n, vals::Moder::INPUT)); 73 r.moder().modify(|w| w.set_moder(n, vals::Moder::INPUT));
42 }); 74 });
@@ -86,7 +118,7 @@ pub struct Output<'d, T: Pin> {
86} 118}
87 119
88impl<'d, T: Pin> Output<'d, T> { 120impl<'d, T: Pin> Output<'d, T> {
89 pub fn new(pin: impl Unborrow<Target = T> + 'd, initial_output: Level) -> Self { 121 pub fn new(pin: impl Unborrow<Target = T> + 'd, initial_output: Level, speed: Speed) -> Self {
90 unborrow!(pin); 122 unborrow!(pin);
91 123
92 match initial_output { 124 match initial_output {
@@ -99,6 +131,8 @@ impl<'d, T: Pin> Output<'d, T> {
99 let n = pin.pin() as usize; 131 let n = pin.pin() as usize;
100 r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING)); 132 r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING));
101 r.moder().modify(|w| w.set_moder(n, vals::Moder::OUTPUT)); 133 r.moder().modify(|w| w.set_moder(n, vals::Moder::OUTPUT));
134 r.otyper().modify(|w| w.set_ot(n, vals::Ot::PUSHPULL));
135 pin.set_speed(speed);
102 }); 136 });
103 137
104 Self { 138 Self {
@@ -150,6 +184,83 @@ impl<'d, T: Pin> StatefulOutputPin for Output<'d, T> {
150 184
151impl<'d, T: Pin> toggleable::Default for Output<'d, T> {} 185impl<'d, T: Pin> toggleable::Default for Output<'d, T> {}
152 186
187/// GPIO output open-drain driver.
188pub struct OutputOpenDrain<'d, T: Pin> {
189 pub(crate) pin: T,
190 phantom: PhantomData<&'d mut T>,
191}
192
193impl<'d, T: Pin> OutputOpenDrain<'d, T> {
194 pub fn new(
195 pin: impl Unborrow<Target = T> + 'd,
196 initial_output: Level,
197 speed: Speed,
198 pull: Pull,
199 ) -> Self {
200 unborrow!(pin);
201
202 match initial_output {
203 Level::High => pin.set_high(),
204 Level::Low => pin.set_low(),
205 }
206
207 cortex_m::interrupt::free(|_| unsafe {
208 let r = pin.block();
209 let n = pin.pin() as usize;
210 r.pupdr().modify(|w| w.set_pupdr(n, pull.into()));
211 r.moder().modify(|w| w.set_moder(n, vals::Moder::OUTPUT));
212 r.otyper().modify(|w| w.set_ot(n, vals::Ot::OPENDRAIN));
213 pin.set_speed(speed);
214 });
215
216 Self {
217 pin,
218 phantom: PhantomData,
219 }
220 }
221}
222
223impl<'d, T: Pin> Drop for OutputOpenDrain<'d, T> {
224 fn drop(&mut self) {
225 cortex_m::interrupt::free(|_| unsafe {
226 let r = self.pin.block();
227 let n = self.pin.pin() as usize;
228 r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING));
229 r.moder().modify(|w| w.set_moder(n, vals::Moder::INPUT));
230 });
231 }
232}
233
234impl<'d, T: Pin> OutputPin for OutputOpenDrain<'d, T> {
235 type Error = Infallible;
236
237 /// Set the output as high.
238 fn set_high(&mut self) -> Result<(), Self::Error> {
239 self.pin.set_high();
240 Ok(())
241 }
242
243 /// Set the output as low.
244 fn set_low(&mut self) -> Result<(), Self::Error> {
245 self.pin.set_low();
246 Ok(())
247 }
248}
249
250impl<'d, T: Pin> InputPin for OutputOpenDrain<'d, T> {
251 type Error = Infallible;
252
253 fn is_high(&self) -> Result<bool, Self::Error> {
254 self.is_low().map(|v| !v)
255 }
256
257 fn is_low(&self) -> Result<bool, Self::Error> {
258 // NOTE(safety) Atomic read
259 let state = unsafe { self.pin.block().idr().read().idr(self.pin.pin() as usize) };
260 Ok(state == vals::Idr::LOW)
261 }
262}
263
153pub(crate) mod sealed { 264pub(crate) mod sealed {
154 use super::*; 265 use super::*;
155 266
@@ -206,6 +317,13 @@ pub(crate) mod sealed {
206 .moder() 317 .moder()
207 .modify(|w| w.set_moder(pin, vals::Moder::ANALOG)); 318 .modify(|w| w.set_moder(pin, vals::Moder::ANALOG));
208 } 319 }
320
321 unsafe fn set_speed(&self, speed: Speed) {
322 let pin = self._pin() as usize;
323 self.block()
324 .ospeedr()
325 .modify(|w| w.set_ospeedr(pin, speed.into()));
326 }
209 } 327 }
210 328
211 pub trait OptionalPin {} 329 pub trait OptionalPin {}
diff --git a/examples/stm32f4/src/bin/blinky.rs b/examples/stm32f4/src/bin/blinky.rs
index 7590764d8..d2b607c2c 100644
--- a/examples/stm32f4/src/bin/blinky.rs
+++ b/examples/stm32f4/src/bin/blinky.rs
@@ -8,7 +8,7 @@
8 8
9#[path = "../example_common.rs"] 9#[path = "../example_common.rs"]
10mod example_common; 10mod example_common;
11use embassy_stm32::gpio::{Level, Output}; 11use embassy_stm32::gpio::{Level, Output, Speed};
12use embedded_hal::digital::v2::OutputPin; 12use embedded_hal::digital::v2::OutputPin;
13use example_common::*; 13use example_common::*;
14 14
@@ -40,7 +40,7 @@ fn main() -> ! {
40 40
41 let p = embassy_stm32::init(Default::default()); 41 let p = embassy_stm32::init(Default::default());
42 42
43 let mut led = Output::new(p.PB7, Level::High); 43 let mut led = Output::new(p.PB7, Level::High, Speed::Low);
44 44
45 loop { 45 loop {
46 info!("high"); 46 info!("high");
diff --git a/examples/stm32f4/src/bin/button.rs b/examples/stm32f4/src/bin/button.rs
index 1ee99f527..c7160d219 100644
--- a/examples/stm32f4/src/bin/button.rs
+++ b/examples/stm32f4/src/bin/button.rs
@@ -8,7 +8,7 @@
8 8
9#[path = "../example_common.rs"] 9#[path = "../example_common.rs"]
10mod example_common; 10mod example_common;
11use embassy_stm32::gpio::{Input, Level, Output, Pull}; 11use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
12use embedded_hal::digital::v2::{InputPin, OutputPin}; 12use embedded_hal::digital::v2::{InputPin, OutputPin};
13use example_common::*; 13use example_common::*;
14 14
@@ -41,9 +41,9 @@ fn main() -> ! {
41 let p = embassy_stm32::init(Default::default()); 41 let p = embassy_stm32::init(Default::default());
42 42
43 let button = Input::new(p.PC13, Pull::Down); 43 let button = Input::new(p.PC13, Pull::Down);
44 let mut led1 = Output::new(p.PB0, Level::High); 44 let mut led1 = Output::new(p.PB0, Level::High, Speed::Low);
45 let _led2 = Output::new(p.PB7, Level::High); 45 let _led2 = Output::new(p.PB7, Level::High, Speed::Low);
46 let mut led3 = Output::new(p.PB14, Level::High); 46 let mut led3 = Output::new(p.PB14, Level::High, Speed::Low);
47 47
48 loop { 48 loop {
49 if button.is_high().unwrap() { 49 if button.is_high().unwrap() {
diff --git a/examples/stm32f4/src/bin/spi.rs b/examples/stm32f4/src/bin/spi.rs
index 610bb64e9..dda0ee4ed 100644
--- a/examples/stm32f4/src/bin/spi.rs
+++ b/examples/stm32f4/src/bin/spi.rs
@@ -9,7 +9,7 @@
9#[path = "../example_common.rs"] 9#[path = "../example_common.rs"]
10mod example_common; 10mod example_common;
11 11
12use embassy_stm32::gpio::{Level, Output}; 12use embassy_stm32::gpio::{Level, Output, Speed};
13use embedded_hal::digital::v2::OutputPin; 13use embedded_hal::digital::v2::OutputPin;
14use example_common::*; 14use example_common::*;
15 15
@@ -58,7 +58,7 @@ fn main() -> ! {
58 Config::default(), 58 Config::default(),
59 ); 59 );
60 60
61 let mut cs = Output::new(p.PE0, Level::High); 61 let mut cs = Output::new(p.PE0, Level::High, Speed::VeryHigh);
62 62
63 loop { 63 loop {
64 let mut buf = [0x0A; 4]; 64 let mut buf = [0x0A; 4];
diff --git a/examples/stm32h7/src/bin/blinky.rs b/examples/stm32h7/src/bin/blinky.rs
index c425b7f8e..d9f891e49 100644
--- a/examples/stm32h7/src/bin/blinky.rs
+++ b/examples/stm32h7/src/bin/blinky.rs
@@ -8,15 +8,15 @@
8 8
9#[path = "../example_common.rs"] 9#[path = "../example_common.rs"]
10mod example_common; 10mod example_common;
11use embassy_stm32::gpio::{Level, Output}; 11use embassy_stm32::gpio::{Level, Output, Speed};
12use embedded_hal::digital::v2::OutputPin; 12use embedded_hal::digital::v2::OutputPin;
13use example_common::*; 13use example_common::*;
14 14
15use cortex_m_rt::entry; 15use cortex_m_rt::entry;
16use stm32h7::stm32h743 as pac; 16use stm32h7::stm32h743 as pac;
17 17
18use stm32h7xx_hal as hal;
19use hal::prelude::*; 18use hal::prelude::*;
19use stm32h7xx_hal as hal;
20 20
21#[entry] 21#[entry]
22fn main() -> ! { 22fn main() -> ! {
@@ -24,8 +24,7 @@ fn main() -> ! {
24 24
25 let pp = pac::Peripherals::take().unwrap(); 25 let pp = pac::Peripherals::take().unwrap();
26 26
27 let pwrcfg = pp.PWR.constrain() 27 let pwrcfg = pp.PWR.constrain().freeze();
28 .freeze();
29 28
30 let rcc = pp.RCC.constrain(); 29 let rcc = pp.RCC.constrain();
31 30
@@ -60,7 +59,7 @@ fn main() -> ! {
60 59
61 let p = embassy_stm32::init(Default::default()); 60 let p = embassy_stm32::init(Default::default());
62 61
63 let mut led = Output::new(p.PB14, Level::High); 62 let mut led = Output::new(p.PB14, Level::High, Speed::Low);
64 63
65 loop { 64 loop {
66 info!("high"); 65 info!("high");
@@ -71,5 +70,4 @@ fn main() -> ! {
71 led.set_low().unwrap(); 70 led.set_low().unwrap();
72 cortex_m::asm::delay(10_000_000); 71 cortex_m::asm::delay(10_000_000);
73 } 72 }
74
75} 73}
diff --git a/examples/stm32l0/src/bin/blinky.rs b/examples/stm32l0/src/bin/blinky.rs
index ab0a2bdb2..833c14fbf 100644
--- a/examples/stm32l0/src/bin/blinky.rs
+++ b/examples/stm32l0/src/bin/blinky.rs
@@ -9,7 +9,7 @@
9#[path = "../example_common.rs"] 9#[path = "../example_common.rs"]
10mod example_common; 10mod example_common;
11use embassy_stm32::{ 11use embassy_stm32::{
12 gpio::{Level, Output}, 12 gpio::{Level, Output, Speed},
13 rcc::*, 13 rcc::*,
14}; 14};
15use embedded_hal::digital::v2::OutputPin; 15use embedded_hal::digital::v2::OutputPin;
@@ -25,7 +25,7 @@ fn main() -> ! {
25 25
26 Rcc::new(p.RCC).enable_debug_wfe(&mut p.DBGMCU, true); 26 Rcc::new(p.RCC).enable_debug_wfe(&mut p.DBGMCU, true);
27 27
28 let mut led = Output::new(p.PB5, Level::High); 28 let mut led = Output::new(p.PB5, Level::High, Speed::Low);
29 29
30 loop { 30 loop {
31 info!("high"); 31 info!("high");
diff --git a/examples/stm32l0/src/bin/button.rs b/examples/stm32l0/src/bin/button.rs
index 04c48112a..5f46ec794 100644
--- a/examples/stm32l0/src/bin/button.rs
+++ b/examples/stm32l0/src/bin/button.rs
@@ -9,7 +9,7 @@
9#[path = "../example_common.rs"] 9#[path = "../example_common.rs"]
10mod example_common; 10mod example_common;
11use embassy_stm32::{ 11use embassy_stm32::{
12 gpio::{Input, Level, Output, Pull}, 12 gpio::{Input, Level, Output, Pull, Speed},
13 rcc::*, 13 rcc::*,
14}; 14};
15use embedded_hal::digital::v2::{InputPin, OutputPin}; 15use embedded_hal::digital::v2::{InputPin, OutputPin};
@@ -25,8 +25,8 @@ fn main() -> ! {
25 Rcc::new(p.RCC).enable_debug_wfe(&mut p.DBGMCU, true); 25 Rcc::new(p.RCC).enable_debug_wfe(&mut p.DBGMCU, true);
26 26
27 let button = Input::new(p.PB2, Pull::Up); 27 let button = Input::new(p.PB2, Pull::Up);
28 let mut led1 = Output::new(p.PA5, Level::High); 28 let mut led1 = Output::new(p.PA5, Level::High, Speed::Low);
29 let mut led2 = Output::new(p.PB5, Level::High); 29 let mut led2 = Output::new(p.PB5, Level::High, Speed::Low);
30 30
31 loop { 31 loop {
32 if button.is_high().unwrap() { 32 if button.is_high().unwrap() {
diff --git a/examples/stm32l0/src/bin/spi.rs b/examples/stm32l0/src/bin/spi.rs
index 0e828c436..9bb9b741e 100644
--- a/examples/stm32l0/src/bin/spi.rs
+++ b/examples/stm32l0/src/bin/spi.rs
@@ -9,7 +9,7 @@
9#[path = "../example_common.rs"] 9#[path = "../example_common.rs"]
10mod example_common; 10mod example_common;
11 11
12use embassy_stm32::gpio::{Level, Output}; 12use embassy_stm32::gpio::{Level, Output, Speed};
13use embedded_hal::digital::v2::OutputPin; 13use embedded_hal::digital::v2::OutputPin;
14use example_common::*; 14use example_common::*;
15 15
@@ -36,7 +36,7 @@ fn main() -> ! {
36 Config::default(), 36 Config::default(),
37 ); 37 );
38 38
39 let mut cs = Output::new(p.PA15, Level::High); 39 let mut cs = Output::new(p.PA15, Level::High, Speed::VeryHigh);
40 40
41 loop { 41 loop {
42 let mut buf = [0x0A; 4]; 42 let mut buf = [0x0A; 4];
diff --git a/examples/stm32l4/src/bin/blinky.rs b/examples/stm32l4/src/bin/blinky.rs
index 42c9333f4..ae4b3d1d1 100644
--- a/examples/stm32l4/src/bin/blinky.rs
+++ b/examples/stm32l4/src/bin/blinky.rs
@@ -8,7 +8,7 @@
8 8
9#[path = "../example_common.rs"] 9#[path = "../example_common.rs"]
10mod example_common; 10mod example_common;
11use embassy_stm32::gpio::{Level, Output}; 11use embassy_stm32::gpio::{Level, Output, Speed};
12use embedded_hal::digital::v2::OutputPin; 12use embedded_hal::digital::v2::OutputPin;
13use example_common::*; 13use example_common::*;
14 14
@@ -39,7 +39,7 @@ fn main() -> ! {
39 39
40 let p = embassy_stm32::init(Default::default()); 40 let p = embassy_stm32::init(Default::default());
41 41
42 let mut led = Output::new(p.PB14, Level::High); 42 let mut led = Output::new(p.PB14, Level::High, Speed::Low);
43 43
44 loop { 44 loop {
45 info!("high"); 45 info!("high");
diff --git a/examples/stm32l4/src/bin/button.rs b/examples/stm32l4/src/bin/button.rs
index 962d5aa75..3efeee20f 100644
--- a/examples/stm32l4/src/bin/button.rs
+++ b/examples/stm32l4/src/bin/button.rs
@@ -8,7 +8,7 @@
8 8
9#[path = "../example_common.rs"] 9#[path = "../example_common.rs"]
10mod example_common; 10mod example_common;
11use embassy_stm32::gpio::{Input, Level, Output, Pull}; 11use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
12use embedded_hal::digital::v2::{InputPin, OutputPin}; 12use embedded_hal::digital::v2::{InputPin, OutputPin};
13use example_common::*; 13use example_common::*;
14 14
@@ -40,8 +40,8 @@ fn main() -> ! {
40 let p = embassy_stm32::init(Default::default()); 40 let p = embassy_stm32::init(Default::default());
41 41
42 let button = Input::new(p.PC13, Pull::Up); 42 let button = Input::new(p.PC13, Pull::Up);
43 let mut led1 = Output::new(p.PA5, Level::High); 43 let mut led1 = Output::new(p.PA5, Level::High, Speed::Low);
44 let mut led2 = Output::new(p.PB14, Level::High); 44 let mut led2 = Output::new(p.PB14, Level::High, Speed::Low);
45 45
46 loop { 46 loop {
47 if button.is_high().unwrap() { 47 if button.is_high().unwrap() {
diff --git a/examples/stm32l4/src/bin/spi.rs b/examples/stm32l4/src/bin/spi.rs
index 7c672b70d..28c563c19 100644
--- a/examples/stm32l4/src/bin/spi.rs
+++ b/examples/stm32l4/src/bin/spi.rs
@@ -9,7 +9,7 @@
9#[path = "../example_common.rs"] 9#[path = "../example_common.rs"]
10mod example_common; 10mod example_common;
11 11
12use embassy_stm32::gpio::{Level, Output}; 12use embassy_stm32::gpio::{Level, Output, Speed};
13use embedded_hal::digital::v2::OutputPin; 13use embedded_hal::digital::v2::OutputPin;
14use example_common::*; 14use example_common::*;
15 15
@@ -52,7 +52,7 @@ fn main() -> ! {
52 Config::default(), 52 Config::default(),
53 ); 53 );
54 54
55 let mut cs = Output::new(p.PE0, Level::High); 55 let mut cs = Output::new(p.PE0, Level::High, Speed::VeryHigh);
56 56
57 loop { 57 loop {
58 let mut buf = [0x0A; 4]; 58 let mut buf = [0x0A; 4];
diff --git a/examples/stm32wb55/src/bin/blinky.rs b/examples/stm32wb55/src/bin/blinky.rs
index 8ce78a3c3..d53ad611a 100644
--- a/examples/stm32wb55/src/bin/blinky.rs
+++ b/examples/stm32wb55/src/bin/blinky.rs
@@ -8,7 +8,7 @@
8 8
9#[path = "../example_common.rs"] 9#[path = "../example_common.rs"]
10mod example_common; 10mod example_common;
11use embassy_stm32::gpio::{Level, Output}; 11use embassy_stm32::gpio::{Level, Output, Speed};
12use embedded_hal::digital::v2::OutputPin; 12use embedded_hal::digital::v2::OutputPin;
13use example_common::*; 13use example_common::*;
14 14
@@ -28,7 +28,7 @@ fn main() -> ! {
28 28
29 let p = embassy_stm32::init(Default::default()); 29 let p = embassy_stm32::init(Default::default());
30 30
31 let mut led = Output::new(p.PB0, Level::High); 31 let mut led = Output::new(p.PB0, Level::High, Speed::Low);
32 32
33 loop { 33 loop {
34 info!("high"); 34 info!("high");