aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author[email protected] <[email protected]>2022-07-04 22:38:05 +0200
committer[email protected] <[email protected]>2022-07-04 22:38:05 +0200
commit4e54d09ab1802705bc8d3c52b4c81616303899cb (patch)
tree7645ce85102d43b7d0997b2070034ea5a9082073
parent13b259d7cdcfb23f76497b5d9db8aa2b1e1d558d (diff)
Have added OutputOpenDrain with Flex
-rw-r--r--embassy-stm32/src/gpio.rs97
1 files changed, 34 insertions, 63 deletions
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs
index 6c989b52e..81969c4c2 100644
--- a/embassy-stm32/src/gpio.rs
+++ b/embassy-stm32/src/gpio.rs
@@ -93,6 +93,32 @@ impl<'d, T: Pin> Flex<'d, T> {
93 } 93 }
94 94
95 #[inline] 95 #[inline]
96 fn set_as_input_output(&mut self,speed: Speed, pull : Pull) {
97 critical_section::with(|_| unsafe {
98 let r = self.pin.block();
99 let n = self.pin.pin() as usize;
100 #[cfg(gpio_v1)]
101 {
102 let crlh = if n < 8 { 0 } else { 1 };
103 match pull {
104 Pull::Up => r.bsrr().write(|w| w.set_bs(n, true)),
105 Pull::Down => r.bsrr().write(|w| w.set_br(n, true)),
106 Pull::None => {}
107 }
108 r.cr(crlh).modify(|w| w.set_mode(n % 8, speed.into()));
109 r.cr(crlh).modify(|w| w.set_cnf_out(n % 8, vals::CnfOut::OPENDRAIN));
110 }
111 #[cfg(gpio_v2)]
112 {
113 r.pupdr().modify(|w| w.set_pupdr(n, pull.into()));
114 r.otyper().modify(|w| w.set_ot(n, vals::Ot::OPENDRAIN));
115 pin.set_speed(speed);
116 r.moder().modify(|w| w.set_moder(n, vals::Moder::OUTPUT));
117 }
118 });
119 }
120
121 #[inline]
96 pub fn is_high(&self) -> bool { 122 pub fn is_high(&self) -> bool {
97 !self.is_low() 123 !self.is_low()
98 } 124 }
@@ -304,58 +330,31 @@ impl<'d, T: Pin> Output<'d, T> {
304 330
305/// GPIO output open-drain driver. 331/// GPIO output open-drain driver.
306pub struct OutputOpenDrain<'d, T: Pin> { 332pub struct OutputOpenDrain<'d, T: Pin> {
307 pub(crate) pin: T, 333 pub(crate) pin: Flex<'d, T>
308 phantom: PhantomData<&'d mut T>,
309} 334}
310 335
311impl<'d, T: Pin> OutputOpenDrain<'d, T> { 336impl<'d, T: Pin> OutputOpenDrain<'d, T> {
312 #[inline] 337 #[inline]
313 pub fn new(pin: impl Unborrow<Target = T> + 'd, initial_output: Level, speed: Speed, pull: Pull) -> Self { 338 pub fn new(pin: impl Unborrow<Target = T> + 'd, initial_output: Level, speed: Speed, pull: Pull) -> Self {
314 unborrow!(pin); 339 let mut pin = Flex::new(pin);
315 340
316 match initial_output { 341 match initial_output {
317 Level::High => pin.set_high(), 342 Level::High => pin.set_high(),
318 Level::Low => pin.set_low(), 343 Level::Low => pin.set_low(),
319 } 344 }
320 345
321 critical_section::with(|_| unsafe { 346 pin.set_as_input_output(speed, pull);
322 let r = pin.block(); 347 Self { pin }
323 let n = pin.pin() as usize;
324 #[cfg(gpio_v1)]
325 {
326 let crlh = if n < 8 { 0 } else { 1 };
327 match pull {
328 Pull::Up => r.bsrr().write(|w| w.set_bs(n, true)),
329 Pull::Down => r.bsrr().write(|w| w.set_br(n, true)),
330 Pull::None => {}
331 }
332 r.cr(crlh).modify(|w| w.set_mode(n % 8, speed.into()));
333 r.cr(crlh).modify(|w| w.set_cnf_out(n % 8, vals::CnfOut::OPENDRAIN));
334 }
335 #[cfg(gpio_v2)]
336 {
337 r.pupdr().modify(|w| w.set_pupdr(n, pull.into()));
338 r.otyper().modify(|w| w.set_ot(n, vals::Ot::OPENDRAIN));
339 pin.set_speed(speed);
340 r.moder().modify(|w| w.set_moder(n, vals::Moder::OUTPUT));
341 }
342 });
343
344 Self {
345 pin,
346 phantom: PhantomData,
347 }
348 } 348 }
349 349
350 #[inline] 350 #[inline]
351 pub fn is_high(&self) -> bool { 351 pub fn is_high(&self) -> bool {
352 !self.is_low() 352 !self.pin.is_low()
353 } 353 }
354 354
355 #[inline] 355 #[inline]
356 pub fn is_low(&self) -> bool { 356 pub fn is_low(&self) -> bool {
357 let state = unsafe { self.pin.block().idr().read().idr(self.pin.pin() as _) }; 357 self.pin.is_low()
358 state == vals::Idr::LOW
359 } 358 }
360 359
361 /// Set the output as high. 360 /// Set the output as high.
@@ -379,41 +378,13 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
379 /// Is the output pin set as low? 378 /// Is the output pin set as low?
380 #[inline] 379 #[inline]
381 pub fn is_set_low(&self) -> bool { 380 pub fn is_set_low(&self) -> bool {
382 let state = unsafe { self.pin.block().odr().read().odr(self.pin.pin() as _) }; 381 self.pin.is_set_low()
383 state == vals::Odr::LOW
384 } 382 }
385 383
386 /// Toggle pin output 384 /// Toggle pin output
387 #[inline] 385 #[inline]
388 pub fn toggle(&mut self) { 386 pub fn toggle(&mut self) {
389 if self.is_set_low() { 387 self.pin.toggle()
390 self.set_high()
391 } else {
392 self.set_low()
393 }
394 }
395}
396
397impl<'d, T: Pin> Drop for OutputOpenDrain<'d, T> {
398 #[inline]
399 fn drop(&mut self) {
400 critical_section::with(|_| unsafe {
401 let r = self.pin.block();
402 let n = self.pin.pin() as usize;
403 #[cfg(gpio_v1)]
404 {
405 let crlh = if n < 8 { 0 } else { 1 };
406 r.cr(crlh).modify(|w| {
407 w.set_mode(n % 8, vals::Mode::INPUT);
408 w.set_cnf_in(n % 8, vals::CnfIn::FLOATING);
409 });
410 }
411 #[cfg(gpio_v2)]
412 {
413 r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING));
414 r.moder().modify(|w| w.set_moder(n, vals::Moder::INPUT));
415 }
416 });
417 } 388 }
418} 389}
419 390