From a08d7814420ed575ead6744f4254bfbb431bbc27 Mon Sep 17 00:00:00 2001 From: Richard Dodd Date: Wed, 24 Mar 2021 18:31:11 +0100 Subject: [PATCH] nrf/gpio: allow borrowed pins. --- embassy-nrf-examples/src/bin/gpiote_port.rs | 2 +- embassy-nrf/src/gpio.rs | 44 +++++++++++++++------ embassy-nrf/src/gpiote.rs | 19 ++++----- 3 files changed, 42 insertions(+), 23 deletions(-) diff --git a/embassy-nrf-examples/src/bin/gpiote_port.rs b/embassy-nrf-examples/src/bin/gpiote_port.rs index 593261ae..556a199f 100644 --- a/embassy-nrf-examples/src/bin/gpiote_port.rs +++ b/embassy-nrf-examples/src/bin/gpiote_port.rs @@ -19,7 +19,7 @@ use embassy_nrf::interrupt; use embassy_nrf::Peripherals; use example_common::*; -async fn button(n: usize, mut pin: PortInput) { +async fn button(n: usize, mut pin: PortInput<'static, AnyPin>) { loop { Pin::new(&mut pin).wait_for_low().await; info!("Button {:?} pressed!", n); diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs index d48ad3d0..0d566ff3 100644 --- a/embassy-nrf/src/gpio.rs +++ b/embassy-nrf/src/gpio.rs @@ -1,7 +1,9 @@ use core::convert::Infallible; use core::hint::unreachable_unchecked; +use core::marker::PhantomData; use embassy::util::PeripheralBorrow; +use embassy_extras::unborrow; use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin}; use gpio::pin_cnf::DRIVE_A; @@ -30,12 +32,15 @@ pub enum Pull { } /// GPIO input driver. -pub struct Input { +pub struct Input<'d, T: Pin> { pub(crate) pin: T, + phantom: PhantomData<&'d mut T>, } -impl Input { - pub fn new(pin: T, pull: Pull) -> Self { +impl<'d, T: Pin> Input<'d, T> { + pub fn new(pin: impl PeripheralBorrow + 'd, pull: Pull) -> Self { + unborrow!(pin); + pin.conf().write(|w| { w.dir().input(); w.input().connect(); @@ -55,17 +60,20 @@ impl Input { w }); - Self { pin } + Self { + pin, + phantom: PhantomData, + } } } -impl Drop for Input { +impl<'d, T: Pin> Drop for Input<'d, T> { fn drop(&mut self) { self.pin.conf().reset(); } } -impl InputPin for Input { +impl<'d, T: Pin> InputPin for Input<'d, T> { type Error = Infallible; fn is_high(&self) -> Result { @@ -108,12 +116,19 @@ pub enum OutputDrive { } /// GPIO output driver. -pub struct Output { +pub struct Output<'d, T: Pin> { pin: T, + phantom: PhantomData<&'d mut T>, } -impl Output { - pub fn new(pin: T, initial_output: Level, drive: OutputDrive) -> Self { +impl<'d, T: Pin> Output<'d, T> { + pub fn new( + pin: impl PeripheralBorrow + 'd, + initial_output: Level, + drive: OutputDrive, + ) -> Self { + unborrow!(pin); + match initial_output { Level::High => pin.set_high(), Level::Low => pin.set_low(), @@ -139,17 +154,20 @@ impl Output { w }); - Self { pin } + Self { + pin, + phantom: PhantomData, + } } } -impl Drop for Output { +impl<'d, T: Pin> Drop for Output<'d, T> { fn drop(&mut self) { self.pin.conf().reset(); } } -impl OutputPin for Output { +impl<'d, T: Pin> OutputPin for Output<'d, T> { type Error = Infallible; /// Set the output as high. @@ -175,7 +193,7 @@ impl OutputPin for Output { } } -impl StatefulOutputPin for Output { +impl<'d, T: Pin> StatefulOutputPin for Output<'d, T> { /// Is the output pin set as high? fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs index dc96a7eb..9a7642c5 100644 --- a/embassy-nrf/src/gpiote.rs +++ b/embassy-nrf/src/gpiote.rs @@ -9,7 +9,7 @@ use core::ptr; use core::task::{Context, Poll}; use embassy::interrupt::InterruptExt; use embassy::traits::gpio::{WaitForHigh, WaitForLow}; -use embassy::util::{AtomicWakerRegistration, Signal}; +use embassy::util::{AtomicWakerRegistration, PeripheralBorrow, Signal}; use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin}; use crate::gpio::sealed::Pin as _; @@ -338,18 +338,19 @@ impl OutputChannel { */ /// GPIO input driver with support -pub struct PortInput { - pin: Input, +pub struct PortInput<'d, T: GpioPin> { + pin: Input<'d, T>, } -impl Unpin for PortInput {} -impl PortInput { - pub fn new(_init: Initialized, pin: Input) -> Self { +impl<'d, T: GpioPin> Unpin for PortInput<'d, T> {} + +impl<'d, T: GpioPin> PortInput<'d, T> { + pub fn new(_init: Initialized, pin: Input<'d, T>) -> Self { Self { pin } } } -impl InputPin for PortInput { +impl<'d, T: GpioPin> InputPin for PortInput<'d, T> { type Error = Infallible; fn is_high(&self) -> Result { @@ -361,7 +362,7 @@ impl InputPin for PortInput { } } -impl WaitForHigh for PortInput { +impl<'d, T: GpioPin> WaitForHigh for PortInput<'d, T> { type Future<'a> = PortInputFuture<'a>; fn wait_for_high<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> { @@ -374,7 +375,7 @@ impl WaitForHigh for PortInput { } } -impl WaitForLow for PortInput { +impl<'d, T: GpioPin> WaitForLow for PortInput<'d, T> { type Future<'a> = PortInputFuture<'a>; fn wait_for_low<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> {