Skip to content

Commit 1720ce6

Browse files
techmccatusbalbin
authored andcommitted
gpio: implement embedded-hal 1 digital traits
1 parent 4d87d52 commit 1720ce6

File tree

1 file changed

+144
-2
lines changed

1 file changed

+144
-2
lines changed

src/gpio.rs

Lines changed: 144 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ macro_rules! gpio {
241241
pub mod $gpiox {
242242
use core::marker::PhantomData;
243243
use hal::digital::v2::{toggleable, InputPin, OutputPin, StatefulOutputPin};
244+
use embedded_hal_one as hal1;
244245
use crate::stm32::{EXTI, $GPIOX};
245246
use crate::exti::{ExtiExt, Event};
246247
use crate::rcc::Rcc;
@@ -288,6 +289,24 @@ macro_rules! gpio {
288289
}
289290
}
290291

292+
impl<MODE> hal1::digital::ErrorType for $PXx<Output<MODE>> {
293+
type Error = core::convert::Infallible;
294+
}
295+
296+
impl<MODE> hal1::digital::OutputPin for $PXx<Output<MODE>> {
297+
fn set_high(&mut self) -> Result<(), Self::Error> {
298+
// NOTE(unsafe) atomic write to a stateless register
299+
unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << self.i)) };
300+
Ok(())
301+
}
302+
303+
fn set_low(&mut self) -> Result<(), Self::Error> {
304+
// NOTE(unsafe) atomic write to a stateless register
305+
unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (self.i + 16))) };
306+
Ok(())
307+
}
308+
}
309+
291310
impl<MODE> StatefulOutputPin for $PXx<Output<MODE>> {
292311
fn is_set_high(&self) -> Result<bool, ()> {
293312
let is_set_high = !self.is_set_low()?;
@@ -301,9 +320,31 @@ macro_rules! gpio {
301320
}
302321
}
303322

304-
impl<MODE> toggleable::Default for $PXx<Output<MODE>> {
323+
impl<MODE> hal1::digital::StatefulOutputPin for $PXx<Output<MODE>> {
324+
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
325+
let is_set_high = !self.is_set_low()?;
326+
Ok(is_set_high)
327+
}
328+
329+
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
330+
// NOTE(unsafe) atomic read with no side effects
331+
let is_set_low = unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << self.i) == 0 };
332+
Ok(is_set_low)
333+
}
334+
}
335+
336+
impl<MODE> hal1::digital::ToggleableOutputPin for $PXx<Output<MODE>> {
337+
fn toggle(&mut self) -> Result<(), Self::Error> {
338+
if <Self as hal1::digital::StatefulOutputPin>::is_set_high(self)? {
339+
<Self as hal1::digital::OutputPin>::set_low(self)
340+
} else {
341+
<Self as hal1::digital::OutputPin>::set_high(self)
342+
}
343+
}
305344
}
306345

346+
impl<MODE> toggleable::Default for $PXx<Output<MODE>> {}
347+
307348
impl<MODE> InputPin for $PXx<Output<MODE>> {
308349
type Error = ();
309350

@@ -319,6 +360,20 @@ macro_rules! gpio {
319360
}
320361
}
321362

363+
impl<MODE> hal1::digital::InputPin for $PXx<Output<MODE>> {
364+
fn is_high(&mut self) -> Result<bool, Self::Error> {
365+
let is_high = !self.is_low()?;
366+
Ok(is_high)
367+
}
368+
369+
fn is_low(&mut self) -> Result<bool, Self::Error> {
370+
// NOTE(unsafe) atomic read with no side effects
371+
let is_low = unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 };
372+
Ok(is_low)
373+
}
374+
}
375+
376+
322377
impl<MODE> InputPin for $PXx<Input<MODE>> {
323378
type Error = ();
324379

@@ -334,6 +389,23 @@ macro_rules! gpio {
334389
}
335390
}
336391

392+
impl<MODE> hal1::digital::ErrorType for $PXx<Input<MODE>> {
393+
type Error = core::convert::Infallible;
394+
}
395+
396+
impl<MODE> hal1::digital::InputPin for $PXx<Input<MODE>> {
397+
fn is_high(&mut self) -> Result<bool, Self::Error> {
398+
let is_high = !self.is_low()?;
399+
Ok(is_high)
400+
}
401+
402+
fn is_low(&mut self) -> Result<bool, Self::Error> {
403+
// NOTE(unsafe) atomic read with no side effects
404+
let is_low = unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 };
405+
Ok(is_low)
406+
}
407+
}
408+
337409
exti_erased!($PXx<Output<MODE>>, $Pxn);
338410
exti_erased!($PXx<Input<MODE>>, $Pxn);
339411

@@ -572,6 +644,24 @@ macro_rules! gpio {
572644
}
573645
}
574646

647+
impl<MODE> hal1::digital::ErrorType for $PXi<Output<MODE>> {
648+
type Error = core::convert::Infallible;
649+
}
650+
651+
impl<MODE> hal1::digital::OutputPin for $PXi<Output<MODE>> {
652+
fn set_high(&mut self) -> Result<(), Self::Error> {
653+
// NOTE(unsafe) atomic write to a stateless register
654+
unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i)) };
655+
Ok(())
656+
}
657+
658+
fn set_low(&mut self) -> Result<(), Self::Error>{
659+
// NOTE(unsafe) atomic write to a stateless register
660+
unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << ($i + 16))) };
661+
Ok(())
662+
}
663+
}
664+
575665
impl<MODE> StatefulOutputPin for $PXi<Output<MODE>> {
576666
fn is_set_high(&self) -> Result<bool, ()> {
577667
let is_set_high = !self.is_set_low()?;
@@ -585,7 +675,29 @@ macro_rules! gpio {
585675
}
586676
}
587677

588-
impl<MODE> toggleable::Default for $PXi<Output<MODE>> {
678+
impl<MODE> hal1::digital::StatefulOutputPin for $PXi<Output<MODE>> {
679+
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
680+
let is_set_high = !self.is_set_low()?;
681+
Ok(is_set_high)
682+
}
683+
684+
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
685+
// NOTE(unsafe) atomic read with no side effects
686+
let is_set_low = unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << $i) == 0 };
687+
Ok(is_set_low)
688+
}
689+
}
690+
691+
impl<MODE> toggleable::Default for $PXi<Output<MODE>> {}
692+
693+
impl<MODE> hal1::digital::ToggleableOutputPin for $PXi<Output<MODE>> {
694+
fn toggle(&mut self) -> Result<(), Self::Error> {
695+
if <Self as hal1::digital::StatefulOutputPin>::is_set_high(self)? {
696+
<Self as hal1::digital::OutputPin>::set_low(self)
697+
} else {
698+
<Self as hal1::digital::OutputPin>::set_high(self)
699+
}
700+
}
589701
}
590702

591703
impl<MODE> InputPin for $PXi<Output<MODE>> {
@@ -603,6 +715,19 @@ macro_rules! gpio {
603715
}
604716
}
605717

718+
impl<MODE> hal1::digital::InputPin for $PXi<Output<MODE>> {
719+
fn is_high(&mut self) -> Result<bool, Self::Error> {
720+
let is_high = !self.is_low()?;
721+
Ok(is_high)
722+
}
723+
724+
fn is_low(&mut self) -> Result<bool, Self::Error> {
725+
// NOTE(unsafe) atomic read with no side effects
726+
let is_low = unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 };
727+
Ok(is_low)
728+
}
729+
}
730+
606731
impl<MODE> $PXi<Input<MODE>> {
607732
/// Erases the pin number from the type
608733
///
@@ -613,6 +738,23 @@ macro_rules! gpio {
613738
}
614739
}
615740

741+
impl<MODE> hal1::digital::ErrorType for $PXi<Input<MODE>> {
742+
type Error = core::convert::Infallible;
743+
}
744+
745+
impl<MODE> hal1::digital::InputPin for $PXi<Input<MODE>> {
746+
fn is_high(&mut self) -> Result<bool, Self::Error> {
747+
let is_high = !self.is_low()?;
748+
Ok(is_high)
749+
}
750+
751+
fn is_low(&mut self) -> Result<bool, Self::Error> {
752+
// NOTE(unsafe) atomic read with no side effects
753+
let is_low = unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 };
754+
Ok(is_low)
755+
}
756+
}
757+
616758
impl<MODE> InputPin for $PXi<Input<MODE>> {
617759
type Error = ();
618760

0 commit comments

Comments
 (0)