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 defmt::panic;
|
||||
use nrf52840_hal::gpio;
|
||||
|
||||
use embassy::executor::{task, Executor};
|
||||
use embassy::util::Forever;
|
||||
use embassy_nrf::gpiote::{Gpiote, InputChannel, InputChannelPolarity};
|
||||
use embassy_nrf::interrupt;
|
||||
use embassy_nrf::gpio::{Input, Pull};
|
||||
use embassy_nrf::gpiote::{self, InputChannel, InputChannelPolarity};
|
||||
use embassy_nrf::{interrupt, Peripherals};
|
||||
|
||||
#[task]
|
||||
async fn run() {
|
||||
let p = unwrap!(embassy_nrf::pac::Peripherals::take());
|
||||
let port0 = gpio::p0::Parts::new(p.P0);
|
||||
|
||||
let (g, chs) = Gpiote::new(p.GPIOTE, interrupt::take!(GPIOTE));
|
||||
let p = Peripherals::take().unwrap();
|
||||
let g = gpiote::initialize(p.GPIOTE, interrupt::take!(GPIOTE));
|
||||
|
||||
info!("Starting!");
|
||||
|
||||
let pin1 = port0.p0_11.into_pullup_input().degrade();
|
||||
let pin2 = port0.p0_12.into_pullup_input().degrade();
|
||||
let pin3 = port0.p0_24.into_pullup_input().degrade();
|
||||
let pin4 = port0.p0_25.into_pullup_input().degrade();
|
||||
|
||||
let ch1 = InputChannel::new(g, chs.ch0, pin1, InputChannelPolarity::HiToLo);
|
||||
let ch2 = InputChannel::new(g, chs.ch1, pin2, InputChannelPolarity::LoToHi);
|
||||
let ch3 = InputChannel::new(g, chs.ch2, pin3, InputChannelPolarity::Toggle);
|
||||
let ch4 = InputChannel::new(g, chs.ch3, pin4, InputChannelPolarity::Toggle);
|
||||
let ch1 = InputChannel::new(
|
||||
g,
|
||||
p.GPIOTE_CH0,
|
||||
Input::new(p.P0_11, Pull::Up),
|
||||
InputChannelPolarity::HiToLo,
|
||||
);
|
||||
let ch2 = InputChannel::new(
|
||||
g,
|
||||
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 {
|
||||
loop {
|
||||
|
@ -10,10 +10,12 @@ use core::task::{Context, Poll};
|
||||
use embassy::interrupt::InterruptExt;
|
||||
use embassy::traits::gpio::{WaitForHigh, WaitForLow};
|
||||
use embassy::util::{AtomicWaker, PeripheralBorrow, Signal};
|
||||
use embassy_extras::impl_unborrow;
|
||||
use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
|
||||
use futures::future::poll_fn;
|
||||
|
||||
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::generic::Reg;
|
||||
use crate::pac::gpiote::_TASKS_OUT;
|
||||
@ -30,44 +32,6 @@ pub const PIN_COUNT: usize = 48;
|
||||
#[cfg(not(any(feature = "52833", feature = "52840")))]
|
||||
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();
|
||||
static CHANNEL_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [NEW_AWR; CHANNEL_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 {
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -163,32 +127,31 @@ impl Iterator for BitIter {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
pub struct InputChannel<C: ChannelID, T> {
|
||||
pub struct InputChannel<'d, C: Channel, T: GpioPin> {
|
||||
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) {
|
||||
let g = unsafe { &*GPIOTE::ptr() };
|
||||
let index = self.ch.number();
|
||||
g.config[index].write(|w| w.mode().disabled());
|
||||
g.intenclr.write(|w| unsafe { w.bits(1 << index) });
|
||||
let g = unsafe { &*pac::GPIOTE::ptr() };
|
||||
let num = self.ch.number() as usize;
|
||||
g.config[num].write(|w| w.mode().disabled());
|
||||
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(
|
||||
_init: Initialized,
|
||||
ch: C,
|
||||
pin: GpioPin<Input<T>>,
|
||||
pin: Input<'d, T>,
|
||||
polarity: InputChannelPolarity,
|
||||
) -> Self {
|
||||
let g = unsafe { &*GPIOTE::ptr() };
|
||||
let index = ch.number();
|
||||
let g = unsafe { &*pac::GPIOTE::ptr() };
|
||||
let num = ch.number() as usize;
|
||||
|
||||
g.config[index].write(|w| {
|
||||
g.config[num].write(|w| {
|
||||
match polarity {
|
||||
InputChannelPolarity::HiToLo => w.mode().event().polarity().hi_to_lo(),
|
||||
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(),
|
||||
};
|
||||
#[cfg(any(feature = "52833", feature = "52840"))]
|
||||
w.port().bit(match pin.port() {
|
||||
w.port().bit(match pin.pin.port() {
|
||||
Port::Port0 => false,
|
||||
Port::Port1 => true,
|
||||
});
|
||||
unsafe { w.psel().bits(pin.pin()) }
|
||||
unsafe { w.psel().bits(pin.pin.pin()) }
|
||||
});
|
||||
|
||||
CHANNEL_WAKERS[index].reset();
|
||||
|
||||
// Enable interrupt
|
||||
g.intenset.write(|w| unsafe { w.bits(1 << index) });
|
||||
g.events_in[num].reset();
|
||||
|
||||
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) {
|
||||
let index = self.ch.number();
|
||||
CHANNEL_WAKERS[index].wait().await;
|
||||
}
|
||||
let g = unsafe { &*pac::GPIOTE::ptr() };
|
||||
let num = self.ch.number() as usize;
|
||||
|
||||
pub fn pin(&self) -> &GpioPin<Input<T>> {
|
||||
&self.pin
|
||||
// Enable interrupt
|
||||
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> {
|
||||
ch: C,
|
||||
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…
Reference in New Issue
Block a user