Skip to content

Commit 83c37fa

Browse files
committed
gpio: implement embedded-hal 1 digital traits
1 parent b50f7d2 commit 83c37fa

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

@@ -580,6 +652,24 @@ macro_rules! gpio {
580652
}
581653
}
582654

655+
impl<MODE> hal1::digital::ErrorType for $PXi<Output<MODE>> {
656+
type Error = core::convert::Infallible;
657+
}
658+
659+
impl<MODE> hal1::digital::OutputPin for $PXi<Output<MODE>> {
660+
fn set_high(&mut self) -> Result<(), Self::Error> {
661+
// NOTE(unsafe) atomic write to a stateless register
662+
unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i)) };
663+
Ok(())
664+
}
665+
666+
fn set_low(&mut self) -> Result<(), Self::Error>{
667+
// NOTE(unsafe) atomic write to a stateless register
668+
unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << ($i + 16))) };
669+
Ok(())
670+
}
671+
}
672+
583673
impl<MODE> StatefulOutputPin for $PXi<Output<MODE>> {
584674
fn is_set_high(&self) -> Result<bool, ()> {
585675
let is_set_high = !self.is_set_low()?;
@@ -593,7 +683,29 @@ macro_rules! gpio {
593683
}
594684
}
595685

596-
impl<MODE> toggleable::Default for $PXi<Output<MODE>> {
686+
impl<MODE> hal1::digital::StatefulOutputPin for $PXi<Output<MODE>> {
687+
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
688+
let is_set_high = !self.is_set_low()?;
689+
Ok(is_set_high)
690+
}
691+
692+
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
693+
// NOTE(unsafe) atomic read with no side effects
694+
let is_set_low = unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << $i) == 0 };
695+
Ok(is_set_low)
696+
}
697+
}
698+
699+
impl<MODE> toggleable::Default for $PXi<Output<MODE>> {}
700+
701+
impl<MODE> hal1::digital::ToggleableOutputPin for $PXi<Output<MODE>> {
702+
fn toggle(&mut self) -> Result<(), Self::Error> {
703+
if <Self as hal1::digital::StatefulOutputPin>::is_set_high(self)? {
704+
<Self as hal1::digital::OutputPin>::set_low(self)
705+
} else {
706+
<Self as hal1::digital::OutputPin>::set_high(self)
707+
}
708+
}
597709
}
598710

599711
impl<MODE> InputPin for $PXi<Output<MODE>> {
@@ -611,6 +723,19 @@ macro_rules! gpio {
611723
}
612724
}
613725

726+
impl<MODE> hal1::digital::InputPin for $PXi<Output<MODE>> {
727+
fn is_high(&mut self) -> Result<bool, Self::Error> {
728+
let is_high = !self.is_low()?;
729+
Ok(is_high)
730+
}
731+
732+
fn is_low(&mut self) -> Result<bool, Self::Error> {
733+
// NOTE(unsafe) atomic read with no side effects
734+
let is_low = unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 };
735+
Ok(is_low)
736+
}
737+
}
738+
614739
impl<MODE> $PXi<Input<MODE>> {
615740
/// Erases the pin number from the type
616741
///
@@ -621,6 +746,23 @@ macro_rules! gpio {
621746
}
622747
}
623748

749+
impl<MODE> hal1::digital::ErrorType for $PXi<Input<MODE>> {
750+
type Error = core::convert::Infallible;
751+
}
752+
753+
impl<MODE> hal1::digital::InputPin for $PXi<Input<MODE>> {
754+
fn is_high(&mut self) -> Result<bool, Self::Error> {
755+
let is_high = !self.is_low()?;
756+
Ok(is_high)
757+
}
758+
759+
fn is_low(&mut self) -> Result<bool, Self::Error> {
760+
// NOTE(unsafe) atomic read with no side effects
761+
let is_low = unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 };
762+
Ok(is_low)
763+
}
764+
}
765+
624766
impl<MODE> InputPin for $PXi<Input<MODE>> {
625767
type Error = ();
626768

0 commit comments

Comments
 (0)