gpiote: change port api to directly return futures.

This commit is contained in:
Dario Nieuwenhuis 2020-11-09 01:04:34 +01:00
parent 61b1d4e188
commit 2e062f5627
3 changed files with 34 additions and 36 deletions

View File

@ -1,6 +1,8 @@
use anyfmt::{panic, *}; use anyfmt::{panic, *};
use core::cell::Cell; use core::cell::Cell;
use core::future::Future;
use core::ptr; use core::ptr;
use core::task::{Context, Poll};
use embassy::util::Signal; use embassy::util::Signal;
use crate::hal::gpio::{Input, Level, Output, Pin, Port}; use crate::hal::gpio::{Input, Level, Output, Pin, Port};
@ -201,10 +203,18 @@ impl Gpiote {
}) })
} }
pub fn new_port_input<'a, T>(&'a self, pin: Pin<Input<T>>) -> PortInput<'a, T> { pub fn wait_port_input<'a, T>(
&'a self,
pin: &'a Pin<Input<T>>,
polarity: PortInputPolarity,
) -> PortInputFuture<'a, T> {
interrupt::free(|_| { interrupt::free(|_| {
unsafe { INSTANCE = self }; unsafe { INSTANCE = self };
PortInput { gpiote: self, pin } PortInputFuture {
gpiote: self,
pin,
polarity,
}
}) })
} }
@ -285,29 +295,28 @@ impl Gpiote {
} }
} }
pub struct PortInput<'a, T> { pub struct PortInputFuture<'a, T> {
gpiote: &'a Gpiote, gpiote: &'a Gpiote,
pin: Pin<Input<T>>, pin: &'a Pin<Input<T>>,
polarity: PortInputPolarity,
} }
impl<'a, T> Drop for PortInput<'a, T> { impl<'a, T> Drop for PortInputFuture<'a, T> {
fn drop(&mut self) { fn drop(&mut self) {
pin_conf(&self.pin).modify(|_, w| w.sense().disabled()); pin_conf(&self.pin).modify(|_, w| w.sense().disabled());
self.gpiote.port_signals[pin_num(&self.pin)].reset(); self.gpiote.port_signals[pin_num(&self.pin)].reset();
} }
} }
impl<'a, T> PortInput<'a, T> { impl<'a, T> Future for PortInputFuture<'a, T> {
pub async fn wait(&self, polarity: PortInputPolarity) { type Output = ();
pin_conf(&self.pin).modify(|_, w| match polarity {
fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
pin_conf(&self.pin).modify(|_, w| match self.polarity {
PortInputPolarity::Low => w.sense().low(), PortInputPolarity::Low => w.sense().low(),
PortInputPolarity::High => w.sense().high(), PortInputPolarity::High => w.sense().high(),
}); });
self.gpiote.port_signals[pin_num(&self.pin)].wait().await; self.gpiote.port_signals[pin_num(&self.pin)].poll_wait(cx)
}
pub fn pin(&self) -> &Pin<Input<T>> {
&self.pin
} }
} }

View File

@ -2,7 +2,6 @@ use anyfmt::panic;
use core::cell::UnsafeCell; use core::cell::UnsafeCell;
use core::future::Future; use core::future::Future;
use core::mem; use core::mem;
use core::pin::Pin;
use core::task::{Context, Poll, Waker}; use core::task::{Context, Poll, Waker};
pub struct Signal<T> { pub struct Signal<T> {
@ -42,21 +41,9 @@ impl<T: Send> Signal<T> {
}) })
} }
pub fn wait<'a>(&'a self) -> impl Future<Output = T> + 'a { pub fn poll_wait(&self, cx: &mut Context<'_>) -> Poll<T> {
WaitFuture { signal: self }
}
}
struct WaitFuture<'a, T> {
signal: &'a Signal<T>,
}
impl<'a, T: Send> Future for WaitFuture<'a, T> {
type Output = T;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
cortex_m::interrupt::free(|_| unsafe { cortex_m::interrupt::free(|_| unsafe {
let state = &mut *self.signal.state.get(); let state = &mut *self.state.get();
match state { match state {
State::None => { State::None => {
*state = State::Waiting(cx.waker().clone()); *state = State::Waiting(cx.waker().clone());
@ -71,4 +58,8 @@ impl<'a, T: Send> Future for WaitFuture<'a, T> {
} }
}) })
} }
pub fn wait(&self) -> impl Future<Output = T> + '_ {
futures::future::poll_fn(move |cx| self.poll_wait(cx))
}
} }

View File

@ -12,15 +12,13 @@ use nrf52840_hal::gpio;
use embassy::executor::{task, Executor}; use embassy::executor::{task, Executor};
use embassy::util::Forever; use embassy::util::Forever;
use embassy_nrf::gpiote; use embassy_nrf::gpiote::{Gpiote, PortInputPolarity};
async fn button(g: &gpiote::Gpiote, n: usize, pin: gpio::Pin<gpio::Input<gpio::PullUp>>) {
let ch = g.new_port_input(pin);
async fn button(g: &Gpiote, n: usize, pin: gpio::Pin<gpio::Input<gpio::PullUp>>) {
loop { loop {
ch.wait(gpiote::PortInputPolarity::Low).await; g.wait_port_input(&pin, PortInputPolarity::Low).await;
info!("Button {:?} pressed!", n); info!("Button {:?} pressed!", n);
ch.wait(gpiote::PortInputPolarity::High).await; g.wait_port_input(&pin, PortInputPolarity::High).await;
info!("Button {:?} released!", n); info!("Button {:?} released!", n);
} }
} }
@ -30,12 +28,12 @@ async fn run() {
let p = unwrap!(embassy_nrf::pac::Peripherals::take()); let p = unwrap!(embassy_nrf::pac::Peripherals::take());
let port0 = gpio::p0::Parts::new(p.P0); let port0 = gpio::p0::Parts::new(p.P0);
let g = gpiote::Gpiote::new(p.GPIOTE); let g = Gpiote::new(p.GPIOTE);
info!( info!(
"sizeof Signal<()> = {:usize}", "sizeof Signal<()> = {:usize}",
mem::size_of::<embassy::util::Signal<()>>() mem::size_of::<embassy::util::Signal<()>>()
); );
info!("sizeof gpiote = {:usize}", mem::size_of::<gpiote::Gpiote>()); info!("sizeof gpiote = {:usize}", mem::size_of::<Gpiote>());
info!("Starting!"); info!("Starting!");