stm32/gpio: expose all functionality as inherent methods.

This commit is contained in:
Dario Nieuwenhuis
2022-01-14 22:02:00 +01:00
parent 52e156b429
commit 58fc64722c
34 changed files with 266 additions and 210 deletions

View File

@ -94,17 +94,25 @@ impl<'d, T: GpioPin> ExtiInput<'d, T> {
pub fn new(pin: Input<'d, T>, _ch: impl Unborrow<Target = T::ExtiChannel> + 'd) -> Self {
Self { pin }
}
pub fn is_high(&self) -> bool {
self.pin.is_high()
}
pub fn is_low(&self) -> bool {
self.pin.is_low()
}
}
impl<'d, T: GpioPin> InputPin for ExtiInput<'d, T> {
type Error = Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
self.pin.is_high()
Ok(self.is_high())
}
fn is_low(&self) -> Result<bool, Self::Error> {
self.pin.is_low()
Ok(self.is_low())
}
}

View File

@ -3,7 +3,7 @@ use core::convert::Infallible;
use core::marker::PhantomData;
use embassy::util::Unborrow;
use embassy_hal_common::{unborrow, unsafe_impl_unborrow};
use embedded_hal::digital::v2::{toggleable, InputPin, OutputPin, StatefulOutputPin};
use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, ToggleableOutputPin};
use crate::pac;
use crate::pac::gpio::{self, vals};
@ -113,6 +113,15 @@ impl<'d, T: Pin> Input<'d, T> {
phantom: PhantomData,
}
}
pub fn is_high(&self) -> bool {
!self.is_low()
}
pub fn is_low(&self) -> bool {
let state = unsafe { self.pin.block().idr().read().idr(self.pin.pin() as _) };
state == vals::Idr::LOW
}
}
impl<'d, T: Pin> Drop for Input<'d, T> {
@ -132,19 +141,6 @@ impl<'d, T: Pin> Drop for Input<'d, T> {
}
}
impl<'d, T: Pin> InputPin for Input<'d, T> {
type Error = Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
self.is_low().map(|v| !v)
}
fn is_low(&self) -> Result<bool, Self::Error> {
let state = unsafe { self.pin.block().idr().read().idr(self.pin.pin() as _) };
Ok(state == vals::Idr::LOW)
}
}
/// Digital input or output level.
#[derive(Debug, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@ -191,6 +187,36 @@ impl<'d, T: Pin> Output<'d, T> {
phantom: PhantomData,
}
}
/// Set the output as high.
pub fn set_high(&mut self) {
self.pin.set_high();
}
/// Set the output as low.
pub fn set_low(&mut self) {
self.pin.set_low();
}
/// Is the output pin set as high?
pub fn is_set_high(&self) -> bool {
!self.is_set_low()
}
/// Is the output pin set as low?
pub fn is_set_low(&self) -> bool {
let state = unsafe { self.pin.block().odr().read().odr(self.pin.pin() as _) };
state == vals::Odr::LOW
}
/// Toggle pin output
pub fn toggle(&mut self) {
if self.is_set_low() {
self.set_high()
} else {
self.set_low()
}
}
}
impl<'d, T: Pin> Drop for Output<'d, T> {
@ -214,37 +240,6 @@ impl<'d, T: Pin> Drop for Output<'d, T> {
}
}
impl<'d, T: Pin> OutputPin for Output<'d, T> {
type Error = Infallible;
/// Set the output as high.
fn set_high(&mut self) -> Result<(), Self::Error> {
self.pin.set_high();
Ok(())
}
/// Set the output as low.
fn set_low(&mut self) -> Result<(), Self::Error> {
self.pin.set_low();
Ok(())
}
}
impl<'d, T: Pin> StatefulOutputPin for Output<'d, T> {
/// Is the output pin set as high?
fn is_set_high(&self) -> Result<bool, Self::Error> {
self.is_set_low().map(|v| !v)
}
/// Is the output pin set as low?
fn is_set_low(&self) -> Result<bool, Self::Error> {
let state = unsafe { self.pin.block().odr().read().odr(self.pin.pin() as _) };
Ok(state == vals::Odr::LOW)
}
}
impl<'d, T: Pin> toggleable::Default for Output<'d, T> {}
/// GPIO output open-drain driver.
pub struct OutputOpenDrain<'d, T: Pin> {
pub(crate) pin: T,
@ -294,6 +289,45 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
phantom: PhantomData,
}
}
pub fn is_high(&self) -> bool {
!self.is_low()
}
pub fn is_low(&self) -> bool {
let state = unsafe { self.pin.block().idr().read().idr(self.pin.pin() as _) };
state == vals::Idr::LOW
}
/// Set the output as high.
pub fn set_high(&mut self) {
self.pin.set_high();
}
/// Set the output as low.
pub fn set_low(&mut self) {
self.pin.set_low();
}
/// Is the output pin set as high?
pub fn is_set_high(&self) -> bool {
!self.is_set_low()
}
/// Is the output pin set as low?
pub fn is_set_low(&self) -> bool {
let state = unsafe { self.pin.block().odr().read().odr(self.pin.pin() as _) };
state == vals::Odr::LOW
}
/// Toggle pin output
pub fn toggle(&mut self) {
if self.is_set_low() {
self.set_high()
} else {
self.set_low()
}
}
}
impl<'d, T: Pin> Drop for OutputOpenDrain<'d, T> {
@ -317,36 +351,6 @@ impl<'d, T: Pin> Drop for OutputOpenDrain<'d, T> {
}
}
impl<'d, T: Pin> OutputPin for OutputOpenDrain<'d, T> {
type Error = Infallible;
/// Set the output as high.
fn set_high(&mut self) -> Result<(), Self::Error> {
self.pin.set_high();
Ok(())
}
/// Set the output as low.
fn set_low(&mut self) -> Result<(), Self::Error> {
self.pin.set_low();
Ok(())
}
}
impl<'d, T: Pin> InputPin for OutputOpenDrain<'d, T> {
type Error = Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
self.is_low().map(|v| !v)
}
fn is_low(&self) -> Result<bool, Self::Error> {
// NOTE(safety) Atomic read
let state = unsafe { self.pin.block().idr().read().idr(self.pin.pin() as usize) };
Ok(state == vals::Idr::LOW)
}
}
pub(crate) mod sealed {
use super::*;
@ -612,3 +616,79 @@ pub(crate) unsafe fn init() {
};
}
}
mod eh02 {
use super::*;
impl<'d, T: Pin> InputPin for Input<'d, T> {
type Error = Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
Ok(self.is_high())
}
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(self.is_low())
}
}
impl<'d, T: Pin> OutputPin for Output<'d, T> {
type Error = Infallible;
fn set_high(&mut self) -> Result<(), Self::Error> {
Ok(self.set_high())
}
fn set_low(&mut self) -> Result<(), Self::Error> {
Ok(self.set_low())
}
}
impl<'d, T: Pin> StatefulOutputPin for Output<'d, T> {
fn is_set_high(&self) -> Result<bool, Self::Error> {
Ok(self.is_set_high())
}
/// Is the output pin set as low?
fn is_set_low(&self) -> Result<bool, Self::Error> {
Ok(self.is_set_low())
}
}
impl<'d, T: Pin> ToggleableOutputPin for Output<'d, T> {
type Error = Infallible;
fn toggle(&mut self) -> Result<(), Self::Error> {
Ok(self.toggle())
}
}
impl<'d, T: Pin> OutputPin for OutputOpenDrain<'d, T> {
type Error = Infallible;
fn set_high(&mut self) -> Result<(), Self::Error> {
Ok(self.set_high())
}
fn set_low(&mut self) -> Result<(), Self::Error> {
Ok(self.set_low())
}
}
impl<'d, T: Pin> StatefulOutputPin for OutputOpenDrain<'d, T> {
fn is_set_high(&self) -> Result<bool, Self::Error> {
Ok(self.is_set_high())
}
/// Is the output pin set as low?
fn is_set_low(&self) -> Result<bool, Self::Error> {
Ok(self.is_set_low())
}
}
impl<'d, T: Pin> ToggleableOutputPin for OutputOpenDrain<'d, T> {
type Error = Infallible;
fn toggle(&mut self) -> Result<(), Self::Error> {
Ok(self.toggle())
}
}
}