aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-03-27 03:50:18 +0100
committerDario Nieuwenhuis <[email protected]>2021-03-29 00:58:58 +0200
commit2bd9323f28537da035692e48820ce8687e627c9e (patch)
tree945934f7590590e2430a6c3bc61f191c82609d2d
parenta338841797e52e5a2032246ac63d29080014d16c (diff)
nrf/gpiote: update input channel to new API
-rw-r--r--embassy-nrf-examples/src/bin/gpiote_channel.rs45
-rw-r--r--embassy-nrf/src/gpiote.rs160
2 files changed, 120 insertions, 85 deletions
diff --git a/embassy-nrf-examples/src/bin/gpiote_channel.rs b/embassy-nrf-examples/src/bin/gpiote_channel.rs
index 599882a90..d223df7a3 100644
--- a/embassy-nrf-examples/src/bin/gpiote_channel.rs
+++ b/embassy-nrf-examples/src/bin/gpiote_channel.rs
@@ -11,31 +11,44 @@ use example_common::*;
11 11
12use cortex_m_rt::entry; 12use cortex_m_rt::entry;
13use defmt::panic; 13use defmt::panic;
14use nrf52840_hal::gpio;
15 14
16use embassy::executor::{task, Executor}; 15use embassy::executor::{task, Executor};
17use embassy::util::Forever; 16use embassy::util::Forever;
18use embassy_nrf::gpiote::{Gpiote, InputChannel, InputChannelPolarity}; 17use embassy_nrf::gpio::{Input, Pull};
19use embassy_nrf::interrupt; 18use embassy_nrf::gpiote::{self, InputChannel, InputChannelPolarity};
19use embassy_nrf::{interrupt, Peripherals};
20 20
21#[task] 21#[task]
22async fn run() { 22async fn run() {
23 let p = unwrap!(embassy_nrf::pac::Peripherals::take()); 23 let p = Peripherals::take().unwrap();
24 let port0 = gpio::p0::Parts::new(p.P0); 24 let g = gpiote::initialize(p.GPIOTE, interrupt::take!(GPIOTE));
25
26 let (g, chs) = Gpiote::new(p.GPIOTE, interrupt::take!(GPIOTE));
27 25
28 info!("Starting!"); 26 info!("Starting!");
29 27
30 let pin1 = port0.p0_11.into_pullup_input().degrade(); 28 let ch1 = InputChannel::new(
31 let pin2 = port0.p0_12.into_pullup_input().degrade(); 29 g,
32 let pin3 = port0.p0_24.into_pullup_input().degrade(); 30 p.GPIOTE_CH0,
33 let pin4 = port0.p0_25.into_pullup_input().degrade(); 31 Input::new(p.P0_11, Pull::Up),
34 32 InputChannelPolarity::HiToLo,
35 let ch1 = InputChannel::new(g, chs.ch0, pin1, InputChannelPolarity::HiToLo); 33 );
36 let ch2 = InputChannel::new(g, chs.ch1, pin2, InputChannelPolarity::LoToHi); 34 let ch2 = InputChannel::new(
37 let ch3 = InputChannel::new(g, chs.ch2, pin3, InputChannelPolarity::Toggle); 35 g,
38 let ch4 = InputChannel::new(g, chs.ch3, pin4, InputChannelPolarity::Toggle); 36 p.GPIOTE_CH1,
37 Input::new(p.P0_12, Pull::Up),
38 InputChannelPolarity::LoToHi,
39 );
40 let ch3 = InputChannel::new(
41 g,
42 p.GPIOTE_CH2,
43 Input::new(p.P0_24, Pull::Up),
44 InputChannelPolarity::Toggle,
45 );
46 let ch4 = InputChannel::new(
47 g,
48 p.GPIOTE_CH3,
49 Input::new(p.P0_25, Pull::Up),
50 InputChannelPolarity::Toggle,
51 );
39 52
40 let button1 = async { 53 let button1 = async {
41 loop { 54 loop {
diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs
index 9ea008f01..95e49324d 100644
--- a/embassy-nrf/src/gpiote.rs
+++ b/embassy-nrf/src/gpiote.rs
@@ -10,10 +10,12 @@ use core::task::{Context, Poll};
10use embassy::interrupt::InterruptExt; 10use embassy::interrupt::InterruptExt;
11use embassy::traits::gpio::{WaitForHigh, WaitForLow}; 11use embassy::traits::gpio::{WaitForHigh, WaitForLow};
12use embassy::util::{AtomicWaker, PeripheralBorrow, Signal}; 12use embassy::util::{AtomicWaker, PeripheralBorrow, Signal};
13use embassy_extras::impl_unborrow;
13use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin}; 14use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
15use futures::future::poll_fn;
14 16
15use crate::gpio::sealed::Pin as _; 17use crate::gpio::sealed::Pin as _;
16use crate::gpio::{AnyPin, Input, Pin as GpioPin, Pull}; 18use crate::gpio::{AnyPin, Input, Pin as GpioPin, Port, Pull};
17use crate::pac; 19use crate::pac;
18use crate::pac::generic::Reg; 20use crate::pac::generic::Reg;
19use crate::pac::gpiote::_TASKS_OUT; 21use crate::pac::gpiote::_TASKS_OUT;
@@ -30,44 +32,6 @@ pub const PIN_COUNT: usize = 48;
30#[cfg(not(any(feature = "52833", feature = "52840")))] 32#[cfg(not(any(feature = "52833", feature = "52840")))]
31pub const PIN_COUNT: usize = 32; 33pub const PIN_COUNT: usize = 32;
32 34
33pub trait ChannelID {
34 fn number(&self) -> usize;
35}
36
37macro_rules! impl_channel {
38 ($ChX:ident, $n:expr) => {
39 pub struct $ChX(());
40 impl $ChX {
41 pub fn degrade(self) -> ChAny {
42 ChAny($n)
43 }
44 }
45
46 impl ChannelID for $ChX {
47 fn number(&self) -> usize {
48 $n
49 }
50 }
51 };
52}
53
54impl_channel!(Ch0, 0);
55impl_channel!(Ch1, 1);
56impl_channel!(Ch2, 2);
57impl_channel!(Ch3, 3);
58impl_channel!(Ch4, 4);
59impl_channel!(Ch5, 5);
60impl_channel!(Ch6, 6);
61impl_channel!(Ch7, 7);
62
63pub struct ChAny(u8);
64
65impl ChannelID for ChAny {
66 fn number(&self) -> usize {
67 self.0 as usize
68 }
69}
70
71const NEW_AWR: AtomicWaker = AtomicWaker::new(); 35const NEW_AWR: AtomicWaker = AtomicWaker::new();
72static CHANNEL_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [NEW_AWR; CHANNEL_COUNT]; 36static CHANNEL_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [NEW_AWR; CHANNEL_COUNT];
73static PORT_WAKERS: [AtomicWaker; PIN_COUNT] = [NEW_AWR; PIN_COUNT]; 37static PORT_WAKERS: [AtomicWaker; PIN_COUNT] = [NEW_AWR; PIN_COUNT];
@@ -123,7 +87,7 @@ unsafe fn on_irq(_ctx: *mut ()) {
123 87
124 for i in 0..CHANNEL_COUNT { 88 for i in 0..CHANNEL_COUNT {
125 if g.events_in[i].read().bits() != 0 { 89 if g.events_in[i].read().bits() != 0 {
126 g.events_in[i].write(|w| w); 90 g.intenclr.write(|w| unsafe { w.bits(1 << i) });
127 CHANNEL_WAKERS[i].wake(); 91 CHANNEL_WAKERS[i].wake();
128 } 92 }
129 } 93 }
@@ -163,32 +127,31 @@ impl Iterator for BitIter {
163 } 127 }
164} 128}
165 129
166/* 130pub struct InputChannel<'d, C: Channel, T: GpioPin> {
167pub struct InputChannel<C: ChannelID, T> {
168 ch: C, 131 ch: C,
169 pin: GpioPin<Input<T>>, 132 pin: Input<'d, T>,
170} 133}
171 134
172impl<C: ChannelID, T> Drop for InputChannel<C, T> { 135impl<'d, C: Channel, T: GpioPin> Drop for InputChannel<'d, C, T> {
173 fn drop(&mut self) { 136 fn drop(&mut self) {
174 let g = unsafe { &*GPIOTE::ptr() }; 137 let g = unsafe { &*pac::GPIOTE::ptr() };
175 let index = self.ch.number(); 138 let num = self.ch.number() as usize;
176 g.config[index].write(|w| w.mode().disabled()); 139 g.config[num].write(|w| w.mode().disabled());
177 g.intenclr.write(|w| unsafe { w.bits(1 << index) }); 140 g.intenclr.write(|w| unsafe { w.bits(1 << num) });
178 } 141 }
179} 142}
180 143
181impl<C: ChannelID, T> InputChannel<C, T> { 144impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> {
182 pub fn new( 145 pub fn new(
183 _init: Initialized, 146 _init: Initialized,
184 ch: C, 147 ch: C,
185 pin: GpioPin<Input<T>>, 148 pin: Input<'d, T>,
186 polarity: InputChannelPolarity, 149 polarity: InputChannelPolarity,
187 ) -> Self { 150 ) -> Self {
188 let g = unsafe { &*GPIOTE::ptr() }; 151 let g = unsafe { &*pac::GPIOTE::ptr() };
189 let index = ch.number(); 152 let num = ch.number() as usize;
190 153
191 g.config[index].write(|w| { 154 g.config[num].write(|w| {
192 match polarity { 155 match polarity {
193 InputChannelPolarity::HiToLo => w.mode().event().polarity().hi_to_lo(), 156 InputChannelPolarity::HiToLo => w.mode().event().polarity().hi_to_lo(),
194 InputChannelPolarity::LoToHi => w.mode().event().polarity().lo_to_hi(), 157 InputChannelPolarity::LoToHi => w.mode().event().polarity().lo_to_hi(),
@@ -196,38 +159,52 @@ impl<C: ChannelID, T> InputChannel<C, T> {
196 InputChannelPolarity::Toggle => w.mode().event().polarity().toggle(), 159 InputChannelPolarity::Toggle => w.mode().event().polarity().toggle(),
197 }; 160 };
198 #[cfg(any(feature = "52833", feature = "52840"))] 161 #[cfg(any(feature = "52833", feature = "52840"))]
199 w.port().bit(match pin.port() { 162 w.port().bit(match pin.pin.port() {
200 Port::Port0 => false, 163 Port::Port0 => false,
201 Port::Port1 => true, 164 Port::Port1 => true,
202 }); 165 });
203 unsafe { w.psel().bits(pin.pin()) } 166 unsafe { w.psel().bits(pin.pin.pin()) }
204 }); 167 });
205 168
206 CHANNEL_WAKERS[index].reset(); 169 g.events_in[num].reset();
207
208 // Enable interrupt
209 g.intenset.write(|w| unsafe { w.bits(1 << index) });
210 170
211 InputChannel { ch, pin } 171 InputChannel { ch, pin }
212 } 172 }
213 173
214 pub fn free(self) -> (C, GpioPin<Input<T>>) { 174 pub async fn wait(&self) {
215 let m = ManuallyDrop::new(self); 175 let g = unsafe { &*pac::GPIOTE::ptr() };
216 let ch = unsafe { ptr::read(&m.ch) }; 176 let num = self.ch.number() as usize;
217 let pin = unsafe { ptr::read(&m.pin) }; 177
218 (ch, pin) 178 // Enable interrupt
179 g.events_in[num].reset();
180 g.intenset.write(|w| unsafe { w.bits(1 << num) });
181
182 poll_fn(|cx| {
183 CHANNEL_WAKERS[num].register(cx.waker());
184
185 if g.events_in[num].read().bits() != 0 {
186 Poll::Ready(())
187 } else {
188 Poll::Pending
189 }
190 })
191 .await;
219 } 192 }
193}
220 194
221 pub async fn wait(&self) { 195impl<'d, C: Channel, T: GpioPin> InputPin for InputChannel<'d, C, T> {
222 let index = self.ch.number(); 196 type Error = Infallible;
223 CHANNEL_WAKERS[index].wait().await; 197
198 fn is_high(&self) -> Result<bool, Self::Error> {
199 self.pin.is_high()
224 } 200 }
225 201
226 pub fn pin(&self) -> &GpioPin<Input<T>> { 202 fn is_low(&self) -> Result<bool, Self::Error> {
227 &self.pin 203 self.pin.is_low()
228 } 204 }
229} 205}
230 206
207/*
231pub struct OutputChannel<C: ChannelID, T> { 208pub struct OutputChannel<C: ChannelID, T> {
232 ch: C, 209 ch: C,
233 pin: GpioPin<Output<T>>, 210 pin: GpioPin<Output<T>>,
@@ -414,3 +391,48 @@ impl<'a> Future for PortInputFuture<'a> {
414 } 391 }
415 } 392 }
416} 393}
394
395mod sealed {
396 pub trait Channel {
397 fn number(&self) -> u8;
398 }
399}
400
401pub trait Channel: sealed::Channel + Sized {
402 fn degrade(self) -> AnyChannel {
403 AnyChannel {
404 number: self.number(),
405 }
406 }
407}
408
409pub struct AnyChannel {
410 number: u8,
411}
412impl_unborrow!(AnyChannel);
413impl Channel for AnyChannel {}
414impl sealed::Channel for AnyChannel {
415 fn number(&self) -> u8 {
416 self.number
417 }
418}
419
420macro_rules! impl_channel {
421 ($type:ident, $number:expr) => {
422 impl sealed::Channel for peripherals::$type {
423 fn number(&self) -> u8 {
424 $number
425 }
426 }
427 impl Channel for peripherals::$type {}
428 };
429}
430
431impl_channel!(GPIOTE_CH0, 0);
432impl_channel!(GPIOTE_CH1, 1);
433impl_channel!(GPIOTE_CH2, 2);
434impl_channel!(GPIOTE_CH3, 3);
435impl_channel!(GPIOTE_CH4, 4);
436impl_channel!(GPIOTE_CH5, 5);
437impl_channel!(GPIOTE_CH6, 6);
438impl_channel!(GPIOTE_CH7, 7);