542: nrf/gpiote: remove PortInput, move impls to Input/FlexPin. r=Dirbaio a=Dirbaio

`PortInput` is just a dumb wrapper around `Input`, it has no reason whatsoever to exist. This PR moves the `wait_for_x` functionality to `Input` directly.

It also adds it to `FlexPin` for completeness and consistency with `Input`.

(The reason `PortInput` exists is a while ago `GPIOTE` was an owned singleton that you had to initialize, so `PortInput::new()` would require it to enforce it's been initialized. This doesn't apply anymore now that GPIOTE is "global")

Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
This commit is contained in:
bors[bot] 2021-12-14 14:09:59 +00:00 committed by GitHub
commit 1a7b9e3279
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 107 additions and 87 deletions

View File

@ -1,6 +1,7 @@
#![macro_use] #![macro_use]
use core::convert::Infallible; use core::convert::Infallible;
use core::future::Future;
use core::hint::unreachable_unchecked; use core::hint::unreachable_unchecked;
use core::marker::PhantomData; use core::marker::PhantomData;
@ -72,6 +73,54 @@ impl<'d, T: Pin> InputPin for Input<'d, T> {
} }
} }
#[cfg(feature = "gpiote")]
impl<'d, T: Pin> embassy::traits::gpio::WaitForHigh for Input<'d, T> {
#[rustfmt::skip]
type Future<'a> where Self: 'a = impl Future<Output=()> + Unpin + 'a;
fn wait_for_high<'a>(&'a mut self) -> Self::Future<'a> {
self.pin.conf().modify(|_, w| w.sense().high());
crate::gpiote::PortInputFuture {
pin_port: self.pin.pin_port(),
phantom: PhantomData,
}
}
}
#[cfg(feature = "gpiote")]
impl<'d, T: Pin> embassy::traits::gpio::WaitForLow for Input<'d, T> {
#[rustfmt::skip]
type Future<'a> where Self: 'a = impl Future<Output=()> + Unpin + 'a;
fn wait_for_low<'a>(&'a mut self) -> Self::Future<'a> {
self.pin.conf().modify(|_, w| w.sense().low());
crate::gpiote::PortInputFuture {
pin_port: self.pin.pin_port(),
phantom: PhantomData,
}
}
}
#[cfg(feature = "gpiote")]
impl<'d, T: Pin> embassy::traits::gpio::WaitForAnyEdge for Input<'d, T> {
#[rustfmt::skip]
type Future<'a> where Self: 'a = impl Future<Output=()> + Unpin + 'a;
fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> {
if self.is_high().ok().unwrap() {
self.pin.conf().modify(|_, w| w.sense().low());
} else {
self.pin.conf().modify(|_, w| w.sense().high());
}
crate::gpiote::PortInputFuture {
pin_port: self.pin.pin_port(),
phantom: PhantomData,
}
}
}
/// Digital input or output level. /// Digital input or output level.
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
@ -277,6 +326,54 @@ impl<'d, T: Pin> StatefulOutputPin for FlexPin<'d, T> {
} }
} }
#[cfg(feature = "gpiote")]
impl<'d, T: Pin> embassy::traits::gpio::WaitForHigh for FlexPin<'d, T> {
#[rustfmt::skip]
type Future<'a> where Self: 'a = impl Future<Output=()> + Unpin + 'a;
fn wait_for_high<'a>(&'a mut self) -> Self::Future<'a> {
self.pin.conf().modify(|_, w| w.sense().high());
crate::gpiote::PortInputFuture {
pin_port: self.pin.pin_port(),
phantom: PhantomData,
}
}
}
#[cfg(feature = "gpiote")]
impl<'d, T: Pin> embassy::traits::gpio::WaitForLow for FlexPin<'d, T> {
#[rustfmt::skip]
type Future<'a> where Self: 'a = impl Future<Output=()> + Unpin + 'a;
fn wait_for_low<'a>(&'a mut self) -> Self::Future<'a> {
self.pin.conf().modify(|_, w| w.sense().low());
crate::gpiote::PortInputFuture {
pin_port: self.pin.pin_port(),
phantom: PhantomData,
}
}
}
#[cfg(feature = "gpiote")]
impl<'d, T: Pin> embassy::traits::gpio::WaitForAnyEdge for FlexPin<'d, T> {
#[rustfmt::skip]
type Future<'a> where Self: 'a = impl Future<Output=()> + Unpin + 'a;
fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> {
if self.is_high().ok().unwrap() {
self.pin.conf().modify(|_, w| w.sense().low());
} else {
self.pin.conf().modify(|_, w| w.sense().high());
}
crate::gpiote::PortInputFuture {
pin_port: self.pin.pin_port(),
phantom: PhantomData,
}
}
}
pub(crate) mod sealed { pub(crate) mod sealed {
use super::*; use super::*;

View File

@ -3,7 +3,6 @@ use core::future::Future;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::task::{Context, Poll}; use core::task::{Context, Poll};
use embassy::interrupt::{Interrupt, InterruptExt}; use embassy::interrupt::{Interrupt, InterruptExt};
use embassy::traits::gpio::{WaitForAnyEdge, WaitForHigh, WaitForLow};
use embassy::waitqueue::AtomicWaker; use embassy::waitqueue::AtomicWaker;
use embassy_hal_common::unsafe_impl_unborrow; use embassy_hal_common::unsafe_impl_unborrow;
use embedded_hal::digital::v2::{InputPin, StatefulOutputPin}; use embedded_hal::digital::v2::{InputPin, StatefulOutputPin};
@ -312,86 +311,12 @@ impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> {
} }
} }
/// GPIOTE port input driver pub(crate) struct PortInputFuture<'a> {
pub struct PortInput<'d, T: GpioPin> { pub(crate) pin_port: u8,
pin: Input<'d, T>, pub(crate) phantom: PhantomData<&'a mut AnyPin>,
} }
impl<'d, T: GpioPin> Unpin for PortInput<'d, T> {} impl<'a> Unpin for PortInputFuture<'a> {}
impl<'d, T: GpioPin> PortInput<'d, T> {
pub fn new(pin: Input<'d, T>) -> Self {
Self { pin }
}
}
impl<'d, T: GpioPin> InputPin for PortInput<'d, T> {
type Error = Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
self.pin.is_high()
}
fn is_low(&self) -> Result<bool, Self::Error> {
self.pin.is_low()
}
}
impl<'d, T: GpioPin> WaitForHigh for PortInput<'d, T> {
type Future<'a>
where
Self: 'a,
= PortInputFuture<'a>;
fn wait_for_high<'a>(&'a mut self) -> Self::Future<'a> {
self.pin.pin.conf().modify(|_, w| w.sense().high());
PortInputFuture {
pin_port: self.pin.pin.pin_port(),
phantom: PhantomData,
}
}
}
impl<'d, T: GpioPin> WaitForLow for PortInput<'d, T> {
type Future<'a>
where
Self: 'a,
= PortInputFuture<'a>;
fn wait_for_low<'a>(&'a mut self) -> Self::Future<'a> {
self.pin.pin.conf().modify(|_, w| w.sense().low());
PortInputFuture {
pin_port: self.pin.pin.pin_port(),
phantom: PhantomData,
}
}
}
impl<'d, T: GpioPin> WaitForAnyEdge for PortInput<'d, T> {
type Future<'a>
where
Self: 'a,
= PortInputFuture<'a>;
fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> {
if self.is_high().ok().unwrap() {
self.pin.pin.conf().modify(|_, w| w.sense().low());
} else {
self.pin.pin.conf().modify(|_, w| w.sense().high());
}
PortInputFuture {
pin_port: self.pin.pin.pin_port(),
phantom: PhantomData,
}
}
}
pub struct PortInputFuture<'a> {
pin_port: u8,
phantom: PhantomData<&'a mut AnyPin>,
}
impl<'a> Drop for PortInputFuture<'a> { impl<'a> Drop for PortInputFuture<'a> {
fn drop(&mut self) { fn drop(&mut self) {

View File

@ -8,12 +8,11 @@ mod example_common;
use embassy::executor::Spawner; use embassy::executor::Spawner;
use embassy::traits::gpio::{WaitForHigh, WaitForLow}; use embassy::traits::gpio::{WaitForHigh, WaitForLow};
use embassy_nrf::gpio::{AnyPin, Input, Pin as _, Pull}; use embassy_nrf::gpio::{AnyPin, Input, Pin as _, Pull};
use embassy_nrf::gpiote::PortInput;
use embassy_nrf::Peripherals; use embassy_nrf::Peripherals;
use example_common::*; use example_common::*;
#[embassy::task(pool_size = 4)] #[embassy::task(pool_size = 4)]
async fn button_task(n: usize, mut pin: PortInput<'static, AnyPin>) { async fn button_task(n: usize, mut pin: Input<'static, AnyPin>) {
loop { loop {
pin.wait_for_low().await; pin.wait_for_low().await;
info!("Button {:?} pressed!", n); info!("Button {:?} pressed!", n);
@ -26,10 +25,10 @@ async fn button_task(n: usize, mut pin: PortInput<'static, AnyPin>) {
async fn main(spawner: Spawner, p: Peripherals) { async fn main(spawner: Spawner, p: Peripherals) {
info!("Starting!"); info!("Starting!");
let btn1 = PortInput::new(Input::new(p.P0_11.degrade(), Pull::Up)); let btn1 = Input::new(p.P0_11.degrade(), Pull::Up);
let btn2 = PortInput::new(Input::new(p.P0_12.degrade(), Pull::Up)); let btn2 = Input::new(p.P0_12.degrade(), Pull::Up);
let btn3 = PortInput::new(Input::new(p.P0_24.degrade(), Pull::Up)); let btn3 = Input::new(p.P0_24.degrade(), Pull::Up);
let btn4 = PortInput::new(Input::new(p.P0_25.degrade(), Pull::Up)); let btn4 = Input::new(p.P0_25.degrade(), Pull::Up);
unwrap!(spawner.spawn(button_task(1, btn1))); unwrap!(spawner.spawn(button_task(1, btn1)));
unwrap!(spawner.spawn(button_task(2, btn2))); unwrap!(spawner.spawn(button_task(2, btn2)));

View File

@ -8,7 +8,6 @@ mod example_common;
use defmt::*; use defmt::*;
use embassy::executor::Spawner; use embassy::executor::Spawner;
use embassy_nrf::gpio::{Input, Pull}; use embassy_nrf::gpio::{Input, Pull};
use embassy_nrf::gpiote::PortInput;
use embassy_nrf::wdt::{Config, Watchdog}; use embassy_nrf::wdt::{Config, Watchdog};
use embassy_nrf::Peripherals; use embassy_nrf::Peripherals;
use embassy_traits::gpio::{WaitForHigh, WaitForLow}; use embassy_traits::gpio::{WaitForHigh, WaitForLow};
@ -32,7 +31,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
} }
}; };
let mut button = PortInput::new(Input::new(p.P0_11, Pull::Up)); let mut button = Input::new(p.P0_11, Pull::Up);
info!("Watchdog started, press button 1 to pet it or I'll reset in 3 seconds!"); info!("Watchdog started, press button 1 to pet it or I'll reset in 3 seconds!");