nrf/gpiote: update input channel to new API
This commit is contained in:
		
							parent
							
								
									a338841797
								
							
						
					
					
						commit
						2bd9323f28
					
				@ -11,31 +11,44 @@ use example_common::*;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use cortex_m_rt::entry;
 | 
					use cortex_m_rt::entry;
 | 
				
			||||||
use defmt::panic;
 | 
					use defmt::panic;
 | 
				
			||||||
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::{Gpiote, InputChannel, InputChannelPolarity};
 | 
					use embassy_nrf::gpio::{Input, Pull};
 | 
				
			||||||
use embassy_nrf::interrupt;
 | 
					use embassy_nrf::gpiote::{self, InputChannel, InputChannelPolarity};
 | 
				
			||||||
 | 
					use embassy_nrf::{interrupt, Peripherals};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[task]
 | 
					#[task]
 | 
				
			||||||
async fn run() {
 | 
					async fn run() {
 | 
				
			||||||
    let p = unwrap!(embassy_nrf::pac::Peripherals::take());
 | 
					    let p = Peripherals::take().unwrap();
 | 
				
			||||||
    let port0 = gpio::p0::Parts::new(p.P0);
 | 
					    let g = gpiote::initialize(p.GPIOTE, interrupt::take!(GPIOTE));
 | 
				
			||||||
 | 
					 | 
				
			||||||
    let (g, chs) = Gpiote::new(p.GPIOTE, interrupt::take!(GPIOTE));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    info!("Starting!");
 | 
					    info!("Starting!");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let pin1 = port0.p0_11.into_pullup_input().degrade();
 | 
					    let ch1 = InputChannel::new(
 | 
				
			||||||
    let pin2 = port0.p0_12.into_pullup_input().degrade();
 | 
					        g,
 | 
				
			||||||
    let pin3 = port0.p0_24.into_pullup_input().degrade();
 | 
					        p.GPIOTE_CH0,
 | 
				
			||||||
    let pin4 = port0.p0_25.into_pullup_input().degrade();
 | 
					        Input::new(p.P0_11, Pull::Up),
 | 
				
			||||||
 | 
					        InputChannelPolarity::HiToLo,
 | 
				
			||||||
    let ch1 = InputChannel::new(g, chs.ch0, pin1, InputChannelPolarity::HiToLo);
 | 
					    );
 | 
				
			||||||
    let ch2 = InputChannel::new(g, chs.ch1, pin2, InputChannelPolarity::LoToHi);
 | 
					    let ch2 = InputChannel::new(
 | 
				
			||||||
    let ch3 = InputChannel::new(g, chs.ch2, pin3, InputChannelPolarity::Toggle);
 | 
					        g,
 | 
				
			||||||
    let ch4 = InputChannel::new(g, chs.ch3, pin4, InputChannelPolarity::Toggle);
 | 
					        p.GPIOTE_CH1,
 | 
				
			||||||
 | 
					        Input::new(p.P0_12, Pull::Up),
 | 
				
			||||||
 | 
					        InputChannelPolarity::LoToHi,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    let ch3 = InputChannel::new(
 | 
				
			||||||
 | 
					        g,
 | 
				
			||||||
 | 
					        p.GPIOTE_CH2,
 | 
				
			||||||
 | 
					        Input::new(p.P0_24, Pull::Up),
 | 
				
			||||||
 | 
					        InputChannelPolarity::Toggle,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    let ch4 = InputChannel::new(
 | 
				
			||||||
 | 
					        g,
 | 
				
			||||||
 | 
					        p.GPIOTE_CH3,
 | 
				
			||||||
 | 
					        Input::new(p.P0_25, Pull::Up),
 | 
				
			||||||
 | 
					        InputChannelPolarity::Toggle,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let button1 = async {
 | 
					    let button1 = async {
 | 
				
			||||||
        loop {
 | 
					        loop {
 | 
				
			||||||
 | 
				
			|||||||
@ -10,10 +10,12 @@ use core::task::{Context, Poll};
 | 
				
			|||||||
use embassy::interrupt::InterruptExt;
 | 
					use embassy::interrupt::InterruptExt;
 | 
				
			||||||
use embassy::traits::gpio::{WaitForHigh, WaitForLow};
 | 
					use embassy::traits::gpio::{WaitForHigh, WaitForLow};
 | 
				
			||||||
use embassy::util::{AtomicWaker, PeripheralBorrow, Signal};
 | 
					use embassy::util::{AtomicWaker, PeripheralBorrow, Signal};
 | 
				
			||||||
 | 
					use embassy_extras::impl_unborrow;
 | 
				
			||||||
use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
 | 
					use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
 | 
				
			||||||
 | 
					use futures::future::poll_fn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::gpio::sealed::Pin as _;
 | 
					use crate::gpio::sealed::Pin as _;
 | 
				
			||||||
use crate::gpio::{AnyPin, Input, Pin as GpioPin, Pull};
 | 
					use crate::gpio::{AnyPin, Input, Pin as GpioPin, Port, Pull};
 | 
				
			||||||
use crate::pac;
 | 
					use crate::pac;
 | 
				
			||||||
use crate::pac::generic::Reg;
 | 
					use crate::pac::generic::Reg;
 | 
				
			||||||
use crate::pac::gpiote::_TASKS_OUT;
 | 
					use crate::pac::gpiote::_TASKS_OUT;
 | 
				
			||||||
@ -30,44 +32,6 @@ pub const PIN_COUNT: usize = 48;
 | 
				
			|||||||
#[cfg(not(any(feature = "52833", feature = "52840")))]
 | 
					#[cfg(not(any(feature = "52833", feature = "52840")))]
 | 
				
			||||||
pub const PIN_COUNT: usize = 32;
 | 
					pub const PIN_COUNT: usize = 32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub trait ChannelID {
 | 
					 | 
				
			||||||
    fn number(&self) -> usize;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
macro_rules! impl_channel {
 | 
					 | 
				
			||||||
    ($ChX:ident, $n:expr) => {
 | 
					 | 
				
			||||||
        pub struct $ChX(());
 | 
					 | 
				
			||||||
        impl $ChX {
 | 
					 | 
				
			||||||
            pub fn degrade(self) -> ChAny {
 | 
					 | 
				
			||||||
                ChAny($n)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        impl ChannelID for $ChX {
 | 
					 | 
				
			||||||
            fn number(&self) -> usize {
 | 
					 | 
				
			||||||
                $n
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl_channel!(Ch0, 0);
 | 
					 | 
				
			||||||
impl_channel!(Ch1, 1);
 | 
					 | 
				
			||||||
impl_channel!(Ch2, 2);
 | 
					 | 
				
			||||||
impl_channel!(Ch3, 3);
 | 
					 | 
				
			||||||
impl_channel!(Ch4, 4);
 | 
					 | 
				
			||||||
impl_channel!(Ch5, 5);
 | 
					 | 
				
			||||||
impl_channel!(Ch6, 6);
 | 
					 | 
				
			||||||
impl_channel!(Ch7, 7);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub struct ChAny(u8);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl ChannelID for ChAny {
 | 
					 | 
				
			||||||
    fn number(&self) -> usize {
 | 
					 | 
				
			||||||
        self.0 as usize
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const NEW_AWR: AtomicWaker = AtomicWaker::new();
 | 
					const NEW_AWR: AtomicWaker = AtomicWaker::new();
 | 
				
			||||||
static CHANNEL_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [NEW_AWR; CHANNEL_COUNT];
 | 
					static CHANNEL_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [NEW_AWR; CHANNEL_COUNT];
 | 
				
			||||||
static PORT_WAKERS: [AtomicWaker; PIN_COUNT] = [NEW_AWR; PIN_COUNT];
 | 
					static PORT_WAKERS: [AtomicWaker; PIN_COUNT] = [NEW_AWR; PIN_COUNT];
 | 
				
			||||||
@ -123,7 +87,7 @@ unsafe fn on_irq(_ctx: *mut ()) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    for i in 0..CHANNEL_COUNT {
 | 
					    for i in 0..CHANNEL_COUNT {
 | 
				
			||||||
        if g.events_in[i].read().bits() != 0 {
 | 
					        if g.events_in[i].read().bits() != 0 {
 | 
				
			||||||
            g.events_in[i].write(|w| w);
 | 
					            g.intenclr.write(|w| unsafe { w.bits(1 << i) });
 | 
				
			||||||
            CHANNEL_WAKERS[i].wake();
 | 
					            CHANNEL_WAKERS[i].wake();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -163,32 +127,31 @@ impl Iterator for BitIter {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					pub struct InputChannel<'d, C: Channel, T: GpioPin> {
 | 
				
			||||||
pub struct InputChannel<C: ChannelID, T> {
 | 
					 | 
				
			||||||
    ch: C,
 | 
					    ch: C,
 | 
				
			||||||
    pin: GpioPin<Input<T>>,
 | 
					    pin: Input<'d, T>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<C: ChannelID, T> Drop for InputChannel<C, T> {
 | 
					impl<'d, C: Channel, T: GpioPin> Drop for InputChannel<'d, C, T> {
 | 
				
			||||||
    fn drop(&mut self) {
 | 
					    fn drop(&mut self) {
 | 
				
			||||||
        let g = unsafe { &*GPIOTE::ptr() };
 | 
					        let g = unsafe { &*pac::GPIOTE::ptr() };
 | 
				
			||||||
        let index = self.ch.number();
 | 
					        let num = self.ch.number() as usize;
 | 
				
			||||||
        g.config[index].write(|w| w.mode().disabled());
 | 
					        g.config[num].write(|w| w.mode().disabled());
 | 
				
			||||||
        g.intenclr.write(|w| unsafe { w.bits(1 << index) });
 | 
					        g.intenclr.write(|w| unsafe { w.bits(1 << num) });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<C: ChannelID, T> InputChannel<C, T> {
 | 
					impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> {
 | 
				
			||||||
    pub fn new(
 | 
					    pub fn new(
 | 
				
			||||||
        _init: Initialized,
 | 
					        _init: Initialized,
 | 
				
			||||||
        ch: C,
 | 
					        ch: C,
 | 
				
			||||||
        pin: GpioPin<Input<T>>,
 | 
					        pin: Input<'d, T>,
 | 
				
			||||||
        polarity: InputChannelPolarity,
 | 
					        polarity: InputChannelPolarity,
 | 
				
			||||||
    ) -> Self {
 | 
					    ) -> Self {
 | 
				
			||||||
        let g = unsafe { &*GPIOTE::ptr() };
 | 
					        let g = unsafe { &*pac::GPIOTE::ptr() };
 | 
				
			||||||
        let index = ch.number();
 | 
					        let num = ch.number() as usize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        g.config[index].write(|w| {
 | 
					        g.config[num].write(|w| {
 | 
				
			||||||
            match polarity {
 | 
					            match polarity {
 | 
				
			||||||
                InputChannelPolarity::HiToLo => w.mode().event().polarity().hi_to_lo(),
 | 
					                InputChannelPolarity::HiToLo => w.mode().event().polarity().hi_to_lo(),
 | 
				
			||||||
                InputChannelPolarity::LoToHi => w.mode().event().polarity().lo_to_hi(),
 | 
					                InputChannelPolarity::LoToHi => w.mode().event().polarity().lo_to_hi(),
 | 
				
			||||||
@ -196,38 +159,52 @@ impl<C: ChannelID, T> InputChannel<C, T> {
 | 
				
			|||||||
                InputChannelPolarity::Toggle => w.mode().event().polarity().toggle(),
 | 
					                InputChannelPolarity::Toggle => w.mode().event().polarity().toggle(),
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            #[cfg(any(feature = "52833", feature = "52840"))]
 | 
					            #[cfg(any(feature = "52833", feature = "52840"))]
 | 
				
			||||||
            w.port().bit(match pin.port() {
 | 
					            w.port().bit(match pin.pin.port() {
 | 
				
			||||||
                Port::Port0 => false,
 | 
					                Port::Port0 => false,
 | 
				
			||||||
                Port::Port1 => true,
 | 
					                Port::Port1 => true,
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            unsafe { w.psel().bits(pin.pin()) }
 | 
					            unsafe { w.psel().bits(pin.pin.pin()) }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        CHANNEL_WAKERS[index].reset();
 | 
					        g.events_in[num].reset();
 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Enable interrupt
 | 
					 | 
				
			||||||
        g.intenset.write(|w| unsafe { w.bits(1 << index) });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        InputChannel { ch, pin }
 | 
					        InputChannel { ch, pin }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn free(self) -> (C, GpioPin<Input<T>>) {
 | 
					 | 
				
			||||||
        let m = ManuallyDrop::new(self);
 | 
					 | 
				
			||||||
        let ch = unsafe { ptr::read(&m.ch) };
 | 
					 | 
				
			||||||
        let pin = unsafe { ptr::read(&m.pin) };
 | 
					 | 
				
			||||||
        (ch, pin)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub async fn wait(&self) {
 | 
					    pub async fn wait(&self) {
 | 
				
			||||||
        let index = self.ch.number();
 | 
					        let g = unsafe { &*pac::GPIOTE::ptr() };
 | 
				
			||||||
        CHANNEL_WAKERS[index].wait().await;
 | 
					        let num = self.ch.number() as usize;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn pin(&self) -> &GpioPin<Input<T>> {
 | 
					        // Enable interrupt
 | 
				
			||||||
        &self.pin
 | 
					        g.events_in[num].reset();
 | 
				
			||||||
 | 
					        g.intenset.write(|w| unsafe { w.bits(1 << num) });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        poll_fn(|cx| {
 | 
				
			||||||
 | 
					            CHANNEL_WAKERS[num].register(cx.waker());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if g.events_in[num].read().bits() != 0 {
 | 
				
			||||||
 | 
					                Poll::Ready(())
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                Poll::Pending
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .await;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<'d, C: Channel, T: GpioPin> InputPin for InputChannel<'d, C, 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()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
pub struct OutputChannel<C: ChannelID, T> {
 | 
					pub struct OutputChannel<C: ChannelID, T> {
 | 
				
			||||||
    ch: C,
 | 
					    ch: C,
 | 
				
			||||||
    pin: GpioPin<Output<T>>,
 | 
					    pin: GpioPin<Output<T>>,
 | 
				
			||||||
@ -414,3 +391,48 @@ impl<'a> Future for PortInputFuture<'a> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mod sealed {
 | 
				
			||||||
 | 
					    pub trait Channel {
 | 
				
			||||||
 | 
					        fn number(&self) -> u8;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub trait Channel: sealed::Channel + Sized {
 | 
				
			||||||
 | 
					    fn degrade(self) -> AnyChannel {
 | 
				
			||||||
 | 
					        AnyChannel {
 | 
				
			||||||
 | 
					            number: self.number(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct AnyChannel {
 | 
				
			||||||
 | 
					    number: u8,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					impl_unborrow!(AnyChannel);
 | 
				
			||||||
 | 
					impl Channel for AnyChannel {}
 | 
				
			||||||
 | 
					impl sealed::Channel for AnyChannel {
 | 
				
			||||||
 | 
					    fn number(&self) -> u8 {
 | 
				
			||||||
 | 
					        self.number
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					macro_rules! impl_channel {
 | 
				
			||||||
 | 
					    ($type:ident, $number:expr) => {
 | 
				
			||||||
 | 
					        impl sealed::Channel for peripherals::$type {
 | 
				
			||||||
 | 
					            fn number(&self) -> u8 {
 | 
				
			||||||
 | 
					                $number
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        impl Channel for peripherals::$type {}
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl_channel!(GPIOTE_CH0, 0);
 | 
				
			||||||
 | 
					impl_channel!(GPIOTE_CH1, 1);
 | 
				
			||||||
 | 
					impl_channel!(GPIOTE_CH2, 2);
 | 
				
			||||||
 | 
					impl_channel!(GPIOTE_CH3, 3);
 | 
				
			||||||
 | 
					impl_channel!(GPIOTE_CH4, 4);
 | 
				
			||||||
 | 
					impl_channel!(GPIOTE_CH5, 5);
 | 
				
			||||||
 | 
					impl_channel!(GPIOTE_CH6, 6);
 | 
				
			||||||
 | 
					impl_channel!(GPIOTE_CH7, 7);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user