nrf/gpio: remove generics.

This commit is contained in:
Dario Nieuwenhuis 2024-01-22 21:19:18 +01:00
parent 3387ee7238
commit 2bc5e9523d
9 changed files with 86 additions and 89 deletions

View file

@ -4,12 +4,11 @@
use defmt::*;
use embassy_executor::Spawner;
use embassy_nrf::gpio::{Level, Output, OutputDrive};
use embassy_nrf::peripherals::P0_13;
use embassy_time::{Duration, Timer};
use {defmt_rtt as _, panic_probe as _}; // global logger
#[embassy_executor::task]
async fn blinker(mut led: Output<'static, P0_13>, interval: Duration) {
async fn blinker(mut led: Output<'static>, interval: Duration) {
loop {
led.set_high();
Timer::after(interval).await;

View file

@ -36,14 +36,14 @@ pub enum Pull {
}
/// GPIO input driver.
pub struct Input<'d, T: Pin> {
pub(crate) pin: Flex<'d, T>,
pub struct Input<'d> {
pub(crate) pin: Flex<'d>,
}
impl<'d, T: Pin> Input<'d, T> {
impl<'d> Input<'d> {
/// Create GPIO input driver for a [Pin] with the provided [Pull] configuration.
#[inline]
pub fn new(pin: impl Peripheral<P = T> + 'd, pull: Pull) -> Self {
pub fn new(pin: impl Peripheral<P = impl Pin> + 'd, pull: Pull) -> Self {
let mut pin = Flex::new(pin);
pin.set_as_input(pull);
@ -122,14 +122,14 @@ pub enum OutputDrive {
}
/// GPIO output driver.
pub struct Output<'d, T: Pin> {
pub(crate) pin: Flex<'d, T>,
pub struct Output<'d> {
pub(crate) pin: Flex<'d>,
}
impl<'d, T: Pin> Output<'d, T> {
impl<'d> Output<'d> {
/// Create GPIO output driver for a [Pin] with the provided [Level] and [OutputDriver] configuration.
#[inline]
pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level, drive: OutputDrive) -> Self {
pub fn new(pin: impl Peripheral<P = impl Pin> + 'd, initial_output: Level, drive: OutputDrive) -> Self {
let mut pin = Flex::new(pin);
match initial_output {
Level::High => pin.set_high(),
@ -209,20 +209,20 @@ fn convert_pull(pull: Pull) -> PULL_A {
/// This pin can either be a disconnected, input, or output pin, or both. The level register bit will remain
/// set while not in output mode, so the pin's level will be 'remembered' when it is not in output
/// mode.
pub struct Flex<'d, T: Pin> {
pub(crate) pin: PeripheralRef<'d, T>,
pub struct Flex<'d> {
pub(crate) pin: PeripheralRef<'d, AnyPin>,
}
impl<'d, T: Pin> Flex<'d, T> {
impl<'d> Flex<'d> {
/// Wrap the pin in a `Flex`.
///
/// The pin remains disconnected. The initial output level is unspecified, but can be changed
/// before the pin is put into output mode.
#[inline]
pub fn new(pin: impl Peripheral<P = T> + 'd) -> Self {
pub fn new(pin: impl Peripheral<P = impl Pin> + 'd) -> Self {
into_ref!(pin);
// Pin will be in disconnected state.
Self { pin }
Self { pin: pin.map_into() }
}
/// Put the pin into input mode.
@ -349,7 +349,7 @@ impl<'d, T: Pin> Flex<'d, T> {
}
}
impl<'d, T: Pin> Drop for Flex<'d, T> {
impl<'d> Drop for Flex<'d> {
fn drop(&mut self) {
self.pin.conf().reset();
}
@ -510,7 +510,7 @@ macro_rules! impl_pin {
mod eh02 {
use super::*;
impl<'d, T: Pin> embedded_hal_02::digital::v2::InputPin for Input<'d, T> {
impl<'d> embedded_hal_02::digital::v2::InputPin for Input<'d> {
type Error = Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
@ -522,7 +522,7 @@ mod eh02 {
}
}
impl<'d, T: Pin> embedded_hal_02::digital::v2::OutputPin for Output<'d, T> {
impl<'d> embedded_hal_02::digital::v2::OutputPin for Output<'d> {
type Error = Infallible;
fn set_high(&mut self) -> Result<(), Self::Error> {
@ -534,7 +534,7 @@ mod eh02 {
}
}
impl<'d, T: Pin> embedded_hal_02::digital::v2::StatefulOutputPin for Output<'d, T> {
impl<'d> embedded_hal_02::digital::v2::StatefulOutputPin for Output<'d> {
fn is_set_high(&self) -> Result<bool, Self::Error> {
Ok(self.is_set_high())
}
@ -544,7 +544,7 @@ mod eh02 {
}
}
impl<'d, T: Pin> embedded_hal_02::digital::v2::ToggleableOutputPin for Output<'d, T> {
impl<'d> embedded_hal_02::digital::v2::ToggleableOutputPin for Output<'d> {
type Error = Infallible;
#[inline]
fn toggle(&mut self) -> Result<(), Self::Error> {
@ -556,7 +556,7 @@ mod eh02 {
/// Implement [`embedded_hal_02::digital::v2::InputPin`] for [`Flex`];
///
/// If the pin is not in input mode the result is unspecified.
impl<'d, T: Pin> embedded_hal_02::digital::v2::InputPin for Flex<'d, T> {
impl<'d> embedded_hal_02::digital::v2::InputPin for Flex<'d> {
type Error = Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
@ -568,7 +568,7 @@ mod eh02 {
}
}
impl<'d, T: Pin> embedded_hal_02::digital::v2::OutputPin for Flex<'d, T> {
impl<'d> embedded_hal_02::digital::v2::OutputPin for Flex<'d> {
type Error = Infallible;
fn set_high(&mut self) -> Result<(), Self::Error> {
@ -580,7 +580,7 @@ mod eh02 {
}
}
impl<'d, T: Pin> embedded_hal_02::digital::v2::StatefulOutputPin for Flex<'d, T> {
impl<'d> embedded_hal_02::digital::v2::StatefulOutputPin for Flex<'d> {
fn is_set_high(&self) -> Result<bool, Self::Error> {
Ok(self.is_set_high())
}
@ -590,7 +590,7 @@ mod eh02 {
}
}
impl<'d, T: Pin> embedded_hal_02::digital::v2::ToggleableOutputPin for Flex<'d, T> {
impl<'d> embedded_hal_02::digital::v2::ToggleableOutputPin for Flex<'d> {
type Error = Infallible;
#[inline]
fn toggle(&mut self) -> Result<(), Self::Error> {
@ -600,11 +600,11 @@ mod eh02 {
}
}
impl<'d, T: Pin> embedded_hal_1::digital::ErrorType for Input<'d, T> {
impl<'d> embedded_hal_1::digital::ErrorType for Input<'d> {
type Error = Infallible;
}
impl<'d, T: Pin> embedded_hal_1::digital::InputPin for Input<'d, T> {
impl<'d> embedded_hal_1::digital::InputPin for Input<'d> {
fn is_high(&mut self) -> Result<bool, Self::Error> {
Ok((*self).is_high())
}
@ -614,11 +614,11 @@ impl<'d, T: Pin> embedded_hal_1::digital::InputPin for Input<'d, T> {
}
}
impl<'d, T: Pin> embedded_hal_1::digital::ErrorType for Output<'d, T> {
impl<'d> embedded_hal_1::digital::ErrorType for Output<'d> {
type Error = Infallible;
}
impl<'d, T: Pin> embedded_hal_1::digital::OutputPin for Output<'d, T> {
impl<'d> embedded_hal_1::digital::OutputPin for Output<'d> {
fn set_high(&mut self) -> Result<(), Self::Error> {
Ok(self.set_high())
}
@ -628,7 +628,7 @@ impl<'d, T: Pin> embedded_hal_1::digital::OutputPin for Output<'d, T> {
}
}
impl<'d, T: Pin> embedded_hal_1::digital::StatefulOutputPin for Output<'d, T> {
impl<'d> embedded_hal_1::digital::StatefulOutputPin for Output<'d> {
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
Ok((*self).is_set_high())
}
@ -638,14 +638,14 @@ impl<'d, T: Pin> embedded_hal_1::digital::StatefulOutputPin for Output<'d, T> {
}
}
impl<'d, T: Pin> embedded_hal_1::digital::ErrorType for Flex<'d, T> {
impl<'d> embedded_hal_1::digital::ErrorType for Flex<'d> {
type Error = Infallible;
}
/// Implement [`InputPin`] for [`Flex`];
///
/// If the pin is not in input mode the result is unspecified.
impl<'d, T: Pin> embedded_hal_1::digital::InputPin for Flex<'d, T> {
impl<'d> embedded_hal_1::digital::InputPin for Flex<'d> {
fn is_high(&mut self) -> Result<bool, Self::Error> {
Ok((*self).is_high())
}
@ -655,7 +655,7 @@ impl<'d, T: Pin> embedded_hal_1::digital::InputPin for Flex<'d, T> {
}
}
impl<'d, T: Pin> embedded_hal_1::digital::OutputPin for Flex<'d, T> {
impl<'d> embedded_hal_1::digital::OutputPin for Flex<'d> {
fn set_high(&mut self) -> Result<(), Self::Error> {
Ok(self.set_high())
}
@ -665,7 +665,7 @@ impl<'d, T: Pin> embedded_hal_1::digital::OutputPin for Flex<'d, T> {
}
}
impl<'d, T: Pin> embedded_hal_1::digital::StatefulOutputPin for Flex<'d, T> {
impl<'d> embedded_hal_1::digital::StatefulOutputPin for Flex<'d> {
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
Ok((*self).is_set_high())
}

View file

@ -156,12 +156,12 @@ impl Iterator for BitIter {
}
/// GPIOTE channel driver in input mode
pub struct InputChannel<'d, C: Channel, T: GpioPin> {
ch: PeripheralRef<'d, C>,
pin: Input<'d, T>,
pub struct InputChannel<'d> {
ch: PeripheralRef<'d, AnyChannel>,
pin: Input<'d>,
}
impl<'d, C: Channel, T: GpioPin> Drop for InputChannel<'d, C, T> {
impl<'d> Drop for InputChannel<'d> {
fn drop(&mut self) {
let g = regs();
let num = self.ch.number();
@ -170,9 +170,9 @@ impl<'d, C: Channel, T: GpioPin> Drop for InputChannel<'d, C, T> {
}
}
impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> {
impl<'d> InputChannel<'d> {
/// Create a new GPIOTE input channel driver.
pub fn new(ch: impl Peripheral<P = C> + 'd, pin: Input<'d, T>, polarity: InputChannelPolarity) -> Self {
pub fn new(ch: impl Peripheral<P = impl Channel> + 'd, pin: Input<'d>, polarity: InputChannelPolarity) -> Self {
into_ref!(ch);
let g = regs();
@ -195,7 +195,7 @@ impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> {
g.events_in[num].reset();
InputChannel { ch, pin }
InputChannel { ch: ch.map_into(), pin }
}
/// Asynchronously wait for an event in this channel.
@ -227,12 +227,12 @@ impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> {
}
/// GPIOTE channel driver in output mode
pub struct OutputChannel<'d, C: Channel, T: GpioPin> {
ch: PeripheralRef<'d, C>,
_pin: Output<'d, T>,
pub struct OutputChannel<'d> {
ch: PeripheralRef<'d, AnyChannel>,
_pin: Output<'d>,
}
impl<'d, C: Channel, T: GpioPin> Drop for OutputChannel<'d, C, T> {
impl<'d> Drop for OutputChannel<'d> {
fn drop(&mut self) {
let g = regs();
let num = self.ch.number();
@ -241,9 +241,9 @@ impl<'d, C: Channel, T: GpioPin> Drop for OutputChannel<'d, C, T> {
}
}
impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> {
impl<'d> OutputChannel<'d> {
/// Create a new GPIOTE output channel driver.
pub fn new(ch: impl Peripheral<P = C> + 'd, pin: Output<'d, T>, polarity: OutputChannelPolarity) -> Self {
pub fn new(ch: impl Peripheral<P = impl Channel> + 'd, pin: Output<'d>, polarity: OutputChannelPolarity) -> Self {
into_ref!(ch);
let g = regs();
let num = ch.number();
@ -267,7 +267,10 @@ impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> {
unsafe { w.psel().bits(pin.pin.pin.pin()) }
});
OutputChannel { ch, _pin: pin }
OutputChannel {
ch: ch.map_into(),
_pin: pin,
}
}
/// Triggers the OUT task (does the action as configured with task_out_polarity, defaults to Toggle).
@ -348,7 +351,7 @@ impl<'a> Future for PortInputFuture<'a> {
}
}
impl<'d, T: GpioPin> Input<'d, T> {
impl<'d> Input<'d> {
/// Wait until the pin is high. If it is already high, return immediately.
pub async fn wait_for_high(&mut self) {
self.pin.wait_for_high().await
@ -375,7 +378,7 @@ impl<'d, T: GpioPin> Input<'d, T> {
}
}
impl<'d, T: GpioPin> Flex<'d, T> {
impl<'d> Flex<'d> {
/// Wait until the pin is high. If it is already high, return immediately.
pub async fn wait_for_high(&mut self) {
self.pin.conf().modify(|_, w| w.sense().high());
@ -420,7 +423,7 @@ mod sealed {
/// GPIOTE channel trait.
///
/// Implemented by all GPIOTE channels.
pub trait Channel: sealed::Channel + Sized {
pub trait Channel: sealed::Channel + Into<AnyChannel> + Sized + 'static {
/// Get the channel number.
fn number(&self) -> usize;
@ -460,6 +463,12 @@ macro_rules! impl_channel {
$number as usize
}
}
impl From<peripherals::$type> for AnyChannel {
fn from(val: peripherals::$type) -> Self {
Channel::degrade(val)
}
}
};
}
@ -477,7 +486,7 @@ impl_channel!(GPIOTE_CH7, 7);
mod eh02 {
use super::*;
impl<'d, C: Channel, T: GpioPin> embedded_hal_02::digital::v2::InputPin for InputChannel<'d, C, T> {
impl<'d> embedded_hal_02::digital::v2::InputPin for InputChannel<'d> {
type Error = Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
@ -490,11 +499,11 @@ mod eh02 {
}
}
impl<'d, C: Channel, T: GpioPin> embedded_hal_1::digital::ErrorType for InputChannel<'d, C, T> {
impl<'d> embedded_hal_1::digital::ErrorType for InputChannel<'d> {
type Error = Infallible;
}
impl<'d, C: Channel, T: GpioPin> embedded_hal_1::digital::InputPin for InputChannel<'d, C, T> {
impl<'d> embedded_hal_1::digital::InputPin for InputChannel<'d> {
fn is_high(&mut self) -> Result<bool, Self::Error> {
Ok(self.pin.is_high())
}
@ -504,7 +513,7 @@ impl<'d, C: Channel, T: GpioPin> embedded_hal_1::digital::InputPin for InputChan
}
}
impl<'d, T: GpioPin> embedded_hal_async::digital::Wait for Input<'d, T> {
impl<'d> embedded_hal_async::digital::Wait for Input<'d> {
async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
Ok(self.wait_for_high().await)
}
@ -526,7 +535,7 @@ impl<'d, T: GpioPin> embedded_hal_async::digital::Wait for Input<'d, T> {
}
}
impl<'d, T: GpioPin> embedded_hal_async::digital::Wait for Flex<'d, T> {
impl<'d> embedded_hal_async::digital::Wait for Flex<'d> {
async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
Ok(self.wait_for_high().await)
}

View file

@ -24,10 +24,7 @@ bind_interrupts!(struct Irqs {
#[embassy_executor::task]
async fn net_task(
stack: &'static Stack<
Enc28j60<
ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static, peripherals::P0_15>, Delay>,
Output<'static, peripherals::P0_13>,
>,
Enc28j60<ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static>, Delay>, Output<'static>>,
>,
) -> ! {
stack.run().await
@ -71,12 +68,7 @@ async fn main(spawner: Spawner) {
// Init network stack
static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
static STACK: StaticCell<
Stack<
Enc28j60<
ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static, peripherals::P0_15>, Delay>,
Output<'static, peripherals::P0_13>,
>,
>,
Stack<Enc28j60<ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static>, Delay>, Output<'static>>>,
> = StaticCell::new();
let stack = STACK.init(Stack::new(
device,

View file

@ -3,11 +3,11 @@
use defmt::{info, unwrap};
use embassy_executor::Spawner;
use embassy_nrf::gpio::{AnyPin, Input, Pin as _, Pull};
use embassy_nrf::gpio::{Input, Pull};
use {defmt_rtt as _, panic_probe as _};
#[embassy_executor::task(pool_size = 4)]
async fn button_task(n: usize, mut pin: Input<'static, AnyPin>) {
async fn button_task(n: usize, mut pin: Input<'static>) {
loop {
pin.wait_for_low().await;
info!("Button {:?} pressed!", n);
@ -21,10 +21,10 @@ async fn main(spawner: Spawner) {
let p = embassy_nrf::init(Default::default());
info!("Starting!");
let btn1 = Input::new(p.P0_11.degrade(), Pull::Up);
let btn2 = Input::new(p.P0_12.degrade(), Pull::Up);
let btn3 = Input::new(p.P0_24.degrade(), Pull::Up);
let btn4 = Input::new(p.P0_25.degrade(), Pull::Up);
let btn1 = Input::new(p.P0_11, Pull::Up);
let btn2 = Input::new(p.P0_12, Pull::Up);
let btn3 = Input::new(p.P0_24, Pull::Up);
let btn4 = Input::new(p.P0_25, Pull::Up);
unwrap!(spawner.spawn(button_task(1, btn1)));
unwrap!(spawner.spawn(button_task(2, btn2)));

View file

@ -8,7 +8,7 @@ use defmt::*;
use embassy_executor::Spawner;
use embassy_futures::join::join;
use embassy_futures::select::{select, Either};
use embassy_nrf::gpio::{Input, Pin, Pull};
use embassy_nrf::gpio::{Input, Pull};
use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
use embassy_nrf::usb::Driver;
use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
@ -97,7 +97,7 @@ async fn main(_spawner: Spawner) {
}
};
let mut button = Input::new(p.P0_11.degrade(), Pull::Up);
let mut button = Input::new(p.P0_11, Pull::Up);
let (reader, mut writer) = hid.split();

View file

@ -5,7 +5,7 @@ use defmt::{info, unwrap, warn};
use embassy_executor::Spawner;
use embassy_net::tcp::TcpSocket;
use embassy_net::{Stack, StackResources};
use embassy_nrf::gpio::{AnyPin, Input, Level, Output, OutputDrive, Pin, Pull};
use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull};
use embassy_nrf::rng::Rng;
use embassy_nrf::spim::{self, Spim};
use embassy_nrf::{bind_interrupts, peripherals};
@ -27,9 +27,9 @@ bind_interrupts!(struct Irqs {
async fn wifi_task(
runner: hosted::Runner<
'static,
ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static, peripherals::P0_31>, Delay>,
Input<'static, AnyPin>,
Output<'static, peripherals::P1_05>,
ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static>, Delay>,
Input<'static>,
Output<'static>,
>,
) -> ! {
runner.run().await
@ -50,8 +50,8 @@ async fn main(spawner: Spawner) {
let sck = p.P0_29;
let mosi = p.P0_30;
let cs = Output::new(p.P0_31, Level::High, OutputDrive::HighDrive);
let handshake = Input::new(p.P1_01.degrade(), Pull::Up);
let ready = Input::new(p.P1_04.degrade(), Pull::None);
let handshake = Input::new(p.P1_01, Pull::Up);
let ready = Input::new(p.P1_04, Pull::None);
let reset = Output::new(p.P1_05, Level::Low, OutputDrive::Standard);
let mut config = spim::Config::default();

View file

@ -21,10 +21,7 @@ bind_interrupts!(struct Irqs {
RNG => embassy_nrf::rng::InterruptHandler<peripherals::RNG>;
});
type MyDriver = Enc28j60<
ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static, peripherals::P0_15>, Delay>,
Output<'static, peripherals::P0_13>,
>;
type MyDriver = Enc28j60<ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static>, Delay>, Output<'static>>;
#[embassy_executor::task]
async fn net_task(stack: &'static Stack<MyDriver>) -> ! {

View file

@ -6,7 +6,7 @@ teleprobe_meta::timeout!(120);
use defmt::{info, unwrap};
use embassy_executor::Spawner;
use embassy_net::{Config, Stack, StackResources};
use embassy_nrf::gpio::{AnyPin, Input, Level, Output, OutputDrive, Pin, Pull};
use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull};
use embassy_nrf::rng::Rng;
use embassy_nrf::spim::{self, Spim};
use embassy_nrf::{bind_interrupts, peripherals};
@ -28,9 +28,9 @@ const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud";
async fn wifi_task(
runner: hosted::Runner<
'static,
ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static, peripherals::P0_31>, Delay>,
Input<'static, AnyPin>,
Output<'static, peripherals::P1_05>,
ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static>, Delay>,
Input<'static>,
Output<'static>,
>,
) -> ! {
runner.run().await
@ -53,8 +53,8 @@ async fn main(spawner: Spawner) {
let sck = p.P0_29;
let mosi = p.P0_30;
let cs = Output::new(p.P0_31, Level::High, OutputDrive::HighDrive);
let handshake = Input::new(p.P1_01.degrade(), Pull::Up);
let ready = Input::new(p.P1_04.degrade(), Pull::None);
let handshake = Input::new(p.P1_01, Pull::Up);
let ready = Input::new(p.P1_04, Pull::None);
let reset = Output::new(p.P1_05, Level::Low, OutputDrive::Standard);
let mut config = spim::Config::default();