aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-03-20 03:09:42 +0100
committerDario Nieuwenhuis <[email protected]>2021-03-29 00:58:57 +0200
commitba7b3974bb0092f0a9d3bf5e02fb5d4c41c53083 (patch)
treeb9704aae9834c41ed81b4e45b70e317de642d947
parent3d3e770b8dca9adb50b02f14d0087fe40ee1ce35 (diff)
nrf/gpiote: update to new gpio
-rw-r--r--embassy-nrf-examples/src/bin/gpiote_port.rs19
-rw-r--r--embassy-nrf/src/gpio.rs8
-rw-r--r--embassy-nrf/src/gpiote.rs281
3 files changed, 137 insertions, 171 deletions
diff --git a/embassy-nrf-examples/src/bin/gpiote_port.rs b/embassy-nrf-examples/src/bin/gpiote_port.rs
index 36ee1c8ea..273cd124d 100644
--- a/embassy-nrf-examples/src/bin/gpiote_port.rs
+++ b/embassy-nrf-examples/src/bin/gpiote_port.rs
@@ -6,7 +6,9 @@
6 6
7#[path = "../example_common.rs"] 7#[path = "../example_common.rs"]
8mod example_common; 8mod example_common;
9use embassy_nrf::gpio::{AnyPin, Input, Pin as _, Pull};
9use example_common::*; 10use example_common::*;
11use gpiote::GpioteInput;
10 12
11use core::pin::Pin; 13use core::pin::Pin;
12use cortex_m_rt::entry; 14use cortex_m_rt::entry;
@@ -16,10 +18,10 @@ use nrf52840_hal::gpio;
16use embassy::executor::{task, Executor}; 18use embassy::executor::{task, Executor};
17use embassy::traits::gpio::{WaitForHigh, WaitForLow}; 19use embassy::traits::gpio::{WaitForHigh, WaitForLow};
18use embassy::util::Forever; 20use embassy::util::Forever;
19use embassy_nrf::gpiote::{Gpiote, GpiotePin}; 21use embassy_nrf::gpiote;
20use embassy_nrf::interrupt; 22use embassy_nrf::interrupt;
21 23
22async fn button(n: usize, mut pin: GpiotePin<gpio::PullUp>) { 24async fn button(n: usize, mut pin: GpioteInput<AnyPin>) {
23 loop { 25 loop {
24 Pin::new(&mut pin).wait_for_low().await; 26 Pin::new(&mut pin).wait_for_low().await;
25 info!("Button {:?} pressed!", n); 27 info!("Button {:?} pressed!", n);
@@ -30,26 +32,25 @@ async fn button(n: usize, mut pin: GpiotePin<gpio::PullUp>) {
30 32
31#[task] 33#[task]
32async fn run() { 34async fn run() {
33 let p = unwrap!(embassy_nrf::pac::Peripherals::take()); 35 let p = unsafe { embassy_nrf::peripherals::Peripherals::steal() };
34 let port0 = gpio::p0::Parts::new(p.P0);
35 36
36 let (g, _) = Gpiote::new(p.GPIOTE, interrupt::take!(GPIOTE)); 37 let g = gpiote::initialize(p.gpiote, interrupt::take!(GPIOTE));
37 38
38 let button1 = button( 39 let button1 = button(
39 1, 40 1,
40 GpiotePin::new(g, port0.p0_11.into_pullup_input().degrade()), 41 GpioteInput::new(g, Input::new(p.p0_11.degrade(), Pull::Up)),
41 ); 42 );
42 let button2 = button( 43 let button2 = button(
43 2, 44 2,
44 GpiotePin::new(g, port0.p0_12.into_pullup_input().degrade()), 45 GpioteInput::new(g, Input::new(p.p0_12.degrade(), Pull::Up)),
45 ); 46 );
46 let button3 = button( 47 let button3 = button(
47 3, 48 3,
48 GpiotePin::new(g, port0.p0_24.into_pullup_input().degrade()), 49 GpioteInput::new(g, Input::new(p.p0_24.degrade(), Pull::Up)),
49 ); 50 );
50 let button4 = button( 51 let button4 = button(
51 4, 52 4,
52 GpiotePin::new(g, port0.p0_25.into_pullup_input().degrade()), 53 GpioteInput::new(g, Input::new(p.p0_25.degrade(), Pull::Up)),
53 ); 54 );
54 futures::join!(button1, button2, button3, button4); 55 futures::join!(button1, button2, button3, button4);
55} 56}
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs
index 52cb57319..dd334c633 100644
--- a/embassy-nrf/src/gpio.rs
+++ b/embassy-nrf/src/gpio.rs
@@ -30,7 +30,7 @@ pub enum Pull {
30 30
31/// GPIO input driver. 31/// GPIO input driver.
32pub struct Input<T: Pin> { 32pub struct Input<T: Pin> {
33 pin: T, 33 pub(crate) pin: T,
34} 34}
35 35
36impl<T: Pin> Input<T> { 36impl<T: Pin> Input<T> {
@@ -273,10 +273,8 @@ pub struct AnyPin {
273} 273}
274 274
275impl AnyPin { 275impl AnyPin {
276 pub unsafe fn steal_from_psel_bits(psel_bits: u32) -> Self { 276 pub unsafe fn steal(pin_port: u8) -> Self {
277 Self { 277 Self { pin_port }
278 pin_port: psel_bits as u8,
279 }
280 } 278 }
281} 279}
282 280
diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs
index 5dc80a639..2b603c4c1 100644
--- a/embassy-nrf/src/gpiote.rs
+++ b/embassy-nrf/src/gpiote.rs
@@ -1,19 +1,24 @@
1use core::convert::Infallible;
1use core::future::Future; 2use core::future::Future;
2use core::mem::ManuallyDrop; 3use core::intrinsics::transmute;
4use core::marker::PhantomData;
5use core::mem::{self, ManuallyDrop};
3use core::ops::Deref; 6use core::ops::Deref;
4use core::pin::Pin; 7use core::pin::Pin;
5use core::ptr; 8use core::ptr;
6use core::task::{Context, Poll}; 9use core::task::{Context, Poll};
7use embassy::interrupt::InterruptExt; 10use embassy::interrupt::InterruptExt;
8use embassy::traits::gpio::{WaitForHigh, WaitForLow}; 11use embassy::traits::gpio::{WaitForHigh, WaitForLow};
9use embassy::util::Signal; 12use embassy::util::{AtomicWakerRegistration, Signal};
13use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
10 14
11use crate::hal::gpio::{Input, Level, Output, Pin as GpioPin, Port}; 15use crate::gpio::sealed::Pin as _;
12use crate::interrupt; 16use crate::gpio::{AnyPin, Input, Pin as GpioPin, Pull};
13use crate::pac; 17use crate::pac;
14use crate::pac::generic::Reg; 18use crate::pac::generic::Reg;
15use crate::pac::gpiote::_TASKS_OUT; 19use crate::pac::gpiote::_TASKS_OUT;
16use crate::pac::{p0 as pac_gpio, GPIOTE}; 20use crate::pac::p0 as pac_gpio;
21use crate::{interrupt, peripherals};
17 22
18#[cfg(not(feature = "51"))] 23#[cfg(not(feature = "51"))]
19use crate::pac::gpiote::{_TASKS_CLR, _TASKS_SET}; 24use crate::pac::gpiote::{_TASKS_CLR, _TASKS_SET};
@@ -63,12 +68,9 @@ impl ChannelID for ChAny {
63 } 68 }
64} 69}
65 70
66#[derive(Clone, Copy)] 71const NEW_AWR: AtomicWakerRegistration = AtomicWakerRegistration::new();
67pub struct Gpiote(()); 72static CHANNEL_WAKERS: [AtomicWakerRegistration; CHANNEL_COUNT] = [NEW_AWR; CHANNEL_COUNT];
68 73static PORT_WAKERS: [AtomicWakerRegistration; PIN_COUNT] = [NEW_AWR; PIN_COUNT];
69const NEW_SIGNAL: Signal<()> = Signal::new();
70static CHANNEL_SIGNALS: [Signal<()>; CHANNEL_COUNT] = [NEW_SIGNAL; CHANNEL_COUNT];
71static PORT_SIGNALS: [Signal<()>; PIN_COUNT] = [NEW_SIGNAL; PIN_COUNT];
72 74
73pub enum InputChannelPolarity { 75pub enum InputChannelPolarity {
74 None, 76 None,
@@ -84,117 +86,84 @@ pub enum OutputChannelPolarity {
84 Toggle, 86 Toggle,
85} 87}
86 88
87#[derive(Debug, Copy, Clone, Eq, PartialEq)] 89/// Token indicating GPIOTE has been correctly initialized.
88#[cfg_attr(feature = "defmt", derive(defmt::Format))] 90///
89pub enum NewChannelError { 91/// This is not an owned singleton, it is Copy. Drivers that make use of GPIOTE require it.
90 NoFreeChannels, 92#[derive(Clone, Copy)]
93pub struct Initialized {
94 _private: (),
91} 95}
92 96
93pub struct Channels { 97pub fn initialize(gpiote: peripherals::GPIOTE, irq: interrupt::GPIOTE) -> Initialized {
94 pub ch0: Ch0, 98 #[cfg(any(feature = "52833", feature = "52840"))]
95 pub ch1: Ch1, 99 let ports = unsafe { &[&*pac::P0::ptr(), &*pac::P1::ptr()] };
96 pub ch2: Ch2, 100 #[cfg(not(any(feature = "52833", feature = "52840")))]
97 pub ch3: Ch3, 101 let ports = unsafe { &[&*pac::P0::ptr()] };
98 pub ch4: Ch4, 102
99 pub ch5: Ch5, 103 for &p in ports {
100 pub ch6: Ch6, 104 // Enable latched detection
101 pub ch7: Ch7, 105 p.detectmode.write(|w| w.detectmode().ldetect());
106 // Clear latch
107 p.latch.write(|w| unsafe { w.bits(0xFFFFFFFF) })
108 }
109
110 // Enable interrupts
111 let g = unsafe { &*pac::GPIOTE::ptr() };
112 g.events_port.write(|w| w);
113 g.intenset.write(|w| w.port().set());
114 irq.set_handler(on_irq);
115 irq.unpend();
116 irq.enable();
117
118 Initialized { _private: () }
102} 119}
103 120
104impl Gpiote { 121unsafe fn on_irq(_ctx: *mut ()) {
105 pub fn new(gpiote: GPIOTE, irq: interrupt::GPIOTE) -> (Self, Channels) { 122 let g = &*pac::GPIOTE::ptr();
106 #[cfg(any(feature = "52833", feature = "52840"))]
107 let ports = unsafe { &[&*pac::P0::ptr(), &*pac::P1::ptr()] };
108 #[cfg(not(any(feature = "52833", feature = "52840")))]
109 let ports = unsafe { &[&*pac::P0::ptr()] };
110 123
111 for &p in ports { 124 for i in 0..CHANNEL_COUNT {
112 // Enable latched detection 125 if g.events_in[i].read().bits() != 0 {
113 p.detectmode.write(|w| w.detectmode().ldetect()); 126 g.events_in[i].write(|w| w);
114 // Clear latch 127 CHANNEL_WAKERS[i].wake();
115 p.latch.write(|w| unsafe { w.bits(0xFFFFFFFF) })
116 } 128 }
117
118 // Enable interrupts
119 gpiote.events_port.write(|w| w);
120 gpiote.intenset.write(|w| w.port().set());
121 irq.set_handler(Self::on_irq);
122 irq.unpend();
123 irq.enable();
124
125 (
126 Self(()),
127 Channels {
128 ch0: Ch0(()),
129 ch1: Ch1(()),
130 ch2: Ch2(()),
131 ch3: Ch3(()),
132 ch4: Ch4(()),
133 ch5: Ch5(()),
134 ch6: Ch6(()),
135 ch7: Ch7(()),
136 },
137 )
138 } 129 }
139 130
140 unsafe fn on_irq(_ctx: *mut ()) { 131 if g.events_port.read().bits() != 0 {
141 let g = &*GPIOTE::ptr(); 132 g.events_port.write(|w| w);
142 133
143 for (event_in, signal) in g.events_in.iter().zip(CHANNEL_SIGNALS.iter()) { 134 #[cfg(any(feature = "52833", feature = "52840"))]
144 if event_in.read().bits() != 0 { 135 let ports = &[&*pac::P0::ptr(), &*pac::P1::ptr()];
145 event_in.write(|w| w); 136 #[cfg(not(any(feature = "52833", feature = "52840")))]
146 signal.signal(()); 137 let ports = &[&*pac::P0::ptr()];
147 }
148 }
149
150 if g.events_port.read().bits() != 0 {
151 g.events_port.write(|w| w);
152 138
153 #[cfg(any(feature = "52833", feature = "52840"))] 139 for (port, &p) in ports.iter().enumerate() {
154 let ports = &[&*pac::P0::ptr(), &*pac::P1::ptr()]; 140 let bits = p.latch.read().bits();
155 #[cfg(not(any(feature = "52833", feature = "52840")))] 141 for pin in BitIter(bits) {
156 let ports = &[&*pac::P0::ptr()]; 142 p.pin_cnf[pin as usize].modify(|_, w| w.sense().disabled());
157 143 PORT_WAKERS[port * 32 + pin as usize].wake();
158 let mut work = true;
159 while work {
160 work = false;
161 for (port, &p) in ports.iter().enumerate() {
162 for pin in BitIter(p.latch.read().bits()) {
163 work = true;
164 p.pin_cnf[pin as usize].modify(|_, w| w.sense().disabled());
165 p.latch.write(|w| w.bits(1 << pin));
166 PORT_SIGNALS[port * 32 + pin as usize].signal(());
167 }
168 }
169 } 144 }
145 p.latch.write(|w| w.bits(bits));
170 } 146 }
171 } 147 }
172} 148}
173 149
174fn pin_num<T>(pin: &GpioPin<T>) -> usize { 150struct BitIter(u32);
175 let port = match pin.port() {
176 Port::Port0 => 0,
177 #[cfg(any(feature = "52833", feature = "52840"))]
178 Port::Port1 => 32,
179 };
180
181 port + pin.pin() as usize
182}
183
184fn pin_block<T>(pin: &GpioPin<T>) -> &pac_gpio::RegisterBlock {
185 let ptr = match pin.port() {
186 Port::Port0 => pac::P0::ptr(),
187 #[cfg(any(feature = "52833", feature = "52840"))]
188 Port::Port1 => pac::P1::ptr(),
189 };
190 151
191 unsafe { &*ptr } 152impl Iterator for BitIter {
192} 153 type Item = u32;
193 154
194fn pin_conf<T>(pin: &GpioPin<T>) -> &pac_gpio::PIN_CNF { 155 fn next(&mut self) -> Option<Self::Item> {
195 &pin_block(pin).pin_cnf[pin.pin() as usize] 156 match self.0.trailing_zeros() {
157 32 => None,
158 b => {
159 self.0 &= !(1 << b);
160 Some(b)
161 }
162 }
163 }
196} 164}
197 165
166/*
198pub struct InputChannel<C: ChannelID, T> { 167pub struct InputChannel<C: ChannelID, T> {
199 ch: C, 168 ch: C,
200 pin: GpioPin<Input<T>>, 169 pin: GpioPin<Input<T>>,
@@ -211,7 +180,7 @@ impl<C: ChannelID, T> Drop for InputChannel<C, T> {
211 180
212impl<C: ChannelID, T> InputChannel<C, T> { 181impl<C: ChannelID, T> InputChannel<C, T> {
213 pub fn new( 182 pub fn new(
214 _gpiote: Gpiote, 183 _init: Initialized,
215 ch: C, 184 ch: C,
216 pin: GpioPin<Input<T>>, 185 pin: GpioPin<Input<T>>,
217 polarity: InputChannelPolarity, 186 polarity: InputChannelPolarity,
@@ -234,7 +203,7 @@ impl<C: ChannelID, T> InputChannel<C, T> {
234 unsafe { w.psel().bits(pin.pin()) } 203 unsafe { w.psel().bits(pin.pin()) }
235 }); 204 });
236 205
237 CHANNEL_SIGNALS[index].reset(); 206 CHANNEL_WAKERS[index].reset();
238 207
239 // Enable interrupt 208 // Enable interrupt
240 g.intenset.write(|w| unsafe { w.bits(1 << index) }); 209 g.intenset.write(|w| unsafe { w.bits(1 << index) });
@@ -251,7 +220,7 @@ impl<C: ChannelID, T> InputChannel<C, T> {
251 220
252 pub async fn wait(&self) { 221 pub async fn wait(&self) {
253 let index = self.ch.number(); 222 let index = self.ch.number();
254 CHANNEL_SIGNALS[index].wait().await; 223 CHANNEL_WAKERS[index].wait().await;
255 } 224 }
256 225
257 pub fn pin(&self) -> &GpioPin<Input<T>> { 226 pub fn pin(&self) -> &GpioPin<Input<T>> {
@@ -366,89 +335,87 @@ impl<C: ChannelID, T> OutputChannel<C, T> {
366 &g.tasks_set[index] 335 &g.tasks_set[index]
367 } 336 }
368} 337}
338 */
369 339
370struct BitIter(u32); 340/// GPIO input driver with support
371 341pub struct GpioteInput<T: GpioPin> {
372impl Iterator for BitIter { 342 pin: Input<T>,
373 type Item = u32; 343}
344impl<T: GpioPin> Unpin for GpioteInput<T> {}
374 345
375 fn next(&mut self) -> Option<Self::Item> { 346impl<T: GpioPin> GpioteInput<T> {
376 match self.0.trailing_zeros() { 347 pub fn new(_init: Initialized, pin: Input<T>) -> Self {
377 32 => None, 348 Self { pin }
378 b => {
379 self.0 &= !(1 << b);
380 Some(b)
381 }
382 }
383 } 349 }
384} 350}
385 351
386pub struct GpiotePin<T> { 352impl<T: GpioPin> InputPin for GpioteInput<T> {
387 pin: GpioPin<Input<T>>, 353 type Error = Infallible;
388}
389 354
390impl<T> Unpin for GpiotePin<T> {} 355 fn is_high(&self) -> Result<bool, Self::Error> {
356 self.pin.is_high()
357 }
391 358
392impl<T> GpiotePin<T> { 359 fn is_low(&self) -> Result<bool, Self::Error> {
393 pub fn new(_gpiote: Gpiote, pin: GpioPin<Input<T>>) -> Self { 360 self.pin.is_low()
394 Self { pin }
395 } 361 }
396} 362}
397 363
398impl<T: 'static> WaitForHigh for GpiotePin<T> { 364impl<T: GpioPin> WaitForHigh for GpioteInput<T> {
399 type Future<'a> = PortInputFuture<'a, T>; 365 type Future<'a> = PortInputFuture<'a>;
400 366
401 fn wait_for_high<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> { 367 fn wait_for_high<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> {
368 self.pin.pin.conf().modify(|_, w| w.sense().high());
369
402 PortInputFuture { 370 PortInputFuture {
403 pin: &self.get_mut().pin, 371 pin_port: self.pin.pin.pin_port(),
404 polarity: PortInputPolarity::High, 372 phantom: PhantomData,
405 } 373 }
406 } 374 }
407} 375}
408 376
409impl<T: 'static> WaitForLow for GpiotePin<T> { 377impl<T: GpioPin> WaitForLow for GpioteInput<T> {
410 type Future<'a> = PortInputFuture<'a, T>; 378 type Future<'a> = PortInputFuture<'a>;
411 379
412 fn wait_for_low<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> { 380 fn wait_for_low<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> {
381 self.pin.pin.conf().modify(|_, w| w.sense().low());
382
413 PortInputFuture { 383 PortInputFuture {
414 pin: &self.get_mut().pin, 384 pin_port: self.pin.pin.pin_port(),
415 polarity: PortInputPolarity::Low, 385 phantom: PhantomData,
416 } 386 }
417 } 387 }
418} 388}
419 389
420impl<T> Deref for GpiotePin<T> { 390pub struct PortInputFuture<'a> {
421 type Target = GpioPin<Input<T>>; 391 pin_port: u8,
422 fn deref(&self) -> &Self::Target { 392 phantom: PhantomData<&'a mut AnyPin>,
423 &self.pin
424 }
425}
426
427enum PortInputPolarity {
428 High,
429 Low,
430}
431
432pub struct PortInputFuture<'a, T> {
433 pin: &'a GpioPin<Input<T>>,
434 polarity: PortInputPolarity,
435} 393}
436 394
437impl<'a, T> Drop for PortInputFuture<'a, T> { 395impl<'a> Drop for PortInputFuture<'a> {
438 fn drop(&mut self) { 396 fn drop(&mut self) {
439 pin_conf(&self.pin).modify(|_, w| w.sense().disabled()); 397 unsafe { AnyPin::steal(self.pin_port) }
440 PORT_SIGNALS[pin_num(&self.pin)].reset(); 398 .conf()
399 .modify(|_, w| w.sense().disabled());
441 } 400 }
442} 401}
443 402
444impl<'a, T> Future for PortInputFuture<'a, T> { 403impl<'a> Future for PortInputFuture<'a> {
445 type Output = (); 404 type Output = ();
446 405
447 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 406 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
448 pin_conf(&self.pin).modify(|_, w| match self.polarity { 407 let dis = unsafe { AnyPin::steal(self.pin_port) }
449 PortInputPolarity::Low => w.sense().low(), 408 .conf()
450 PortInputPolarity::High => w.sense().high(), 409 .read()
451 }); 410 .sense()
452 PORT_SIGNALS[pin_num(&self.pin)].poll_wait(cx) 411 .is_disabled();
412
413 if dis {
414 return Poll::Ready(());
415 }
416
417 PORT_WAKERS[self.pin_port as usize].register(cx.waker());
418
419 Poll::Pending
453 } 420 }
454} 421}