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…
Reference in New Issue
Block a user