aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2020-11-08 18:59:31 +0100
committerDario Nieuwenhuis <[email protected]>2020-11-08 18:59:31 +0100
commitfc0fe842ee0c9a39b23a0b82847580bd596b6e82 (patch)
treef12e68892e8cd55804f7c5a5518bc46e2c71a54d
parenta2735a716c72ec9098297a4ef3120a8e12b5e61d (diff)
Add support for GPIOTE Port event.
-rw-r--r--embassy-nrf/src/gpiote.rs226
1 files changed, 219 insertions, 7 deletions
diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs
index ffea98f2e..1980e8746 100644
--- a/embassy-nrf/src/gpiote.rs
+++ b/embassy-nrf/src/gpiote.rs
@@ -1,4 +1,4 @@
1use anyfmt::*; 1use anyfmt::{panic, *};
2use core::cell::Cell; 2use core::cell::Cell;
3use core::ptr; 3use core::ptr;
4use embassy::util::Signal; 4use embassy::util::Signal;
@@ -7,19 +7,32 @@ use crate::hal::gpio::{Input, Level, Output, Pin, Port};
7use crate::interrupt; 7use crate::interrupt;
8use crate::pac::generic::Reg; 8use crate::pac::generic::Reg;
9use crate::pac::gpiote::_TASKS_OUT; 9use crate::pac::gpiote::_TASKS_OUT;
10use crate::pac::GPIOTE; 10use crate::pac::{p0 as gpio, GPIOTE, P0, P1};
11 11
12#[cfg(not(feature = "51"))] 12#[cfg(not(feature = "51"))]
13use crate::pac::gpiote::{_TASKS_CLR, _TASKS_SET}; 13use crate::pac::gpiote::{_TASKS_CLR, _TASKS_SET};
14 14
15pub const CHANNEL_COUNT: usize = 8;
16
17#[cfg(any(feature = "52833", feature = "52840"))]
18pub const PIN_COUNT: usize = 48;
19#[cfg(not(any(feature = "52833", feature = "52840")))]
20pub const PIN_COUNT: usize = 32;
21
15pub struct Gpiote { 22pub struct Gpiote {
16 inner: GPIOTE, 23 inner: GPIOTE,
17 free_channels: Cell<u8>, // 0 = used, 1 = free. 8 bits for 8 channelself. 24 free_channels: Cell<u8>, // 0 = used, 1 = free. 8 bits for 8 channelself.
18 signals: [Signal<()>; 8], 25 channel_signals: [Signal<()>; CHANNEL_COUNT],
26 port_signals: [Signal<()>; PIN_COUNT],
19} 27}
20 28
21static mut INSTANCE: *const Gpiote = ptr::null_mut(); 29static mut INSTANCE: *const Gpiote = ptr::null_mut();
22 30
31pub enum PortInputPolarity {
32 High,
33 Low,
34}
35
23pub enum InputChannelPolarity { 36pub enum InputChannelPolarity {
24 None, 37 None,
25 HiToLo, 38 HiToLo,
@@ -42,13 +55,115 @@ pub enum NewChannelError {
42 55
43impl Gpiote { 56impl Gpiote {
44 pub fn new(gpiote: GPIOTE) -> Self { 57 pub fn new(gpiote: GPIOTE) -> Self {
58 #[cfg(any(feature = "52833", feature = "52840"))]
59 let ports = unsafe { &[&*P0::ptr(), &*P1::ptr()] };
60 #[cfg(not(any(feature = "52833", feature = "52840")))]
61 let ports = unsafe { &[&*P0::ptr()] };
62
63 for &p in ports {
64 // Enable latched detection
65 p.detectmode.write(|w| w.detectmode().ldetect());
66 // Clear latch
67 p.latch.write(|w| unsafe { w.bits(0xFFFFFFFF) })
68 }
69
70 // Enable interrupts
71 gpiote.events_port.write(|w| w);
72 gpiote.intenset.write(|w| w.port().set());
45 interrupt::unpend(interrupt::GPIOTE); 73 interrupt::unpend(interrupt::GPIOTE);
46 interrupt::enable(interrupt::GPIOTE); 74 interrupt::enable(interrupt::GPIOTE);
47 75
48 Self { 76 Self {
49 inner: gpiote, 77 inner: gpiote,
50 free_channels: Cell::new(0xFF), // all 8 channels free 78 free_channels: Cell::new(0xFF), // all 8 channels free
51 signals: [ 79 channel_signals: [
80 Signal::new(),
81 Signal::new(),
82 Signal::new(),
83 Signal::new(),
84 Signal::new(),
85 Signal::new(),
86 Signal::new(),
87 Signal::new(),
88 ],
89 // This is just horrible
90 #[cfg(any(feature = "52833", feature = "52840"))]
91 port_signals: [
92 Signal::new(),
93 Signal::new(),
94 Signal::new(),
95 Signal::new(),
96 Signal::new(),
97 Signal::new(),
98 Signal::new(),
99 Signal::new(),
100 Signal::new(),
101 Signal::new(),
102 Signal::new(),
103 Signal::new(),
104 Signal::new(),
105 Signal::new(),
106 Signal::new(),
107 Signal::new(),
108 Signal::new(),
109 Signal::new(),
110 Signal::new(),
111 Signal::new(),
112 Signal::new(),
113 Signal::new(),
114 Signal::new(),
115 Signal::new(),
116 Signal::new(),
117 Signal::new(),
118 Signal::new(),
119 Signal::new(),
120 Signal::new(),
121 Signal::new(),
122 Signal::new(),
123 Signal::new(),
124 Signal::new(),
125 Signal::new(),
126 Signal::new(),
127 Signal::new(),
128 Signal::new(),
129 Signal::new(),
130 Signal::new(),
131 Signal::new(),
132 Signal::new(),
133 Signal::new(),
134 Signal::new(),
135 Signal::new(),
136 Signal::new(),
137 Signal::new(),
138 Signal::new(),
139 Signal::new(),
140 ],
141 #[cfg(not(any(feature = "52833", feature = "52840")))]
142 port_signals: [
143 Signal::new(),
144 Signal::new(),
145 Signal::new(),
146 Signal::new(),
147 Signal::new(),
148 Signal::new(),
149 Signal::new(),
150 Signal::new(),
151 Signal::new(),
152 Signal::new(),
153 Signal::new(),
154 Signal::new(),
155 Signal::new(),
156 Signal::new(),
157 Signal::new(),
158 Signal::new(),
159 Signal::new(),
160 Signal::new(),
161 Signal::new(),
162 Signal::new(),
163 Signal::new(),
164 Signal::new(),
165 Signal::new(),
166 Signal::new(),
52 Signal::new(), 167 Signal::new(),
53 Signal::new(), 168 Signal::new(),
54 Signal::new(), 169 Signal::new(),
@@ -84,6 +199,13 @@ impl Gpiote {
84 }) 199 })
85 } 200 }
86 201
202 pub fn new_port_input<'a, T>(&'a self, pin: Pin<Input<T>>) -> PortInput<'a, T> {
203 interrupt::free(|_| {
204 unsafe { INSTANCE = self };
205 PortInput { gpiote: self, pin }
206 })
207 }
208
87 pub fn new_input_channel<'a, T>( 209 pub fn new_input_channel<'a, T>(
88 &'a self, 210 &'a self,
89 pin: Pin<Input<T>>, 211 pin: Pin<Input<T>>,
@@ -161,6 +283,56 @@ impl Gpiote {
161 } 283 }
162} 284}
163 285
286pub struct PortInput<'a, T> {
287 gpiote: &'a Gpiote,
288 pin: Pin<Input<T>>,
289}
290
291impl<'a, T> Drop for PortInput<'a, T> {
292 fn drop(&mut self) {
293 pin_conf(&self.pin).modify(|_, w| w.sense().disabled());
294 self.gpiote.port_signals[pin_num(&self.pin)].reset();
295 }
296}
297
298impl<'a, T> PortInput<'a, T> {
299 pub async fn wait(&self, polarity: PortInputPolarity) {
300 pin_conf(&self.pin).modify(|_, w| match polarity {
301 PortInputPolarity::Low => w.sense().low(),
302 PortInputPolarity::High => w.sense().high(),
303 });
304 self.gpiote.port_signals[pin_num(&self.pin)].wait().await;
305 }
306
307 pub fn pin(&self) -> &Pin<Input<T>> {
308 &self.pin
309 }
310}
311
312fn pin_num<T>(pin: &Pin<T>) -> usize {
313 let port = match pin.port() {
314 Port::Port0 => 0,
315 #[cfg(any(feature = "52833", feature = "52840"))]
316 Port::Port1 => 32,
317 };
318
319 port + pin.pin() as usize
320}
321
322fn pin_block<T>(pin: &Pin<T>) -> &gpio::RegisterBlock {
323 let ptr = match pin.port() {
324 Port::Port0 => P0::ptr(),
325 #[cfg(any(feature = "52833", feature = "52840"))]
326 Port::Port1 => P1::ptr(),
327 };
328
329 unsafe { &*ptr }
330}
331
332fn pin_conf<T>(pin: &Pin<T>) -> &gpio::PIN_CNF {
333 &pin_block(pin).pin_cnf[pin.pin() as usize]
334}
335
164pub struct InputChannel<'a, T> { 336pub struct InputChannel<'a, T> {
165 gpiote: &'a Gpiote, 337 gpiote: &'a Gpiote,
166 pin: Pin<Input<T>>, 338 pin: Pin<Input<T>>,
@@ -174,8 +346,10 @@ impl<'a, T> Drop for InputChannel<'a, T> {
174} 346}
175 347
176impl<'a, T> InputChannel<'a, T> { 348impl<'a, T> InputChannel<'a, T> {
177 pub async fn wait(&self) -> () { 349 pub async fn wait(&self) {
178 self.gpiote.signals[self.index as usize].wait().await; 350 self.gpiote.channel_signals[self.index as usize]
351 .wait()
352 .await;
179 } 353 }
180 354
181 pub fn pin(&self) -> &Pin<Input<T>> { 355 pub fn pin(&self) -> &Pin<Input<T>> {
@@ -235,7 +409,45 @@ unsafe fn GPIOTE() {
235 for i in 0..8 { 409 for i in 0..8 {
236 if s.inner.events_in[i].read().bits() != 0 { 410 if s.inner.events_in[i].read().bits() != 0 {
237 s.inner.events_in[i].write(|w| w); 411 s.inner.events_in[i].write(|w| w);
238 s.signals[i].signal(()); 412 s.channel_signals[i].signal(());
413 }
414 }
415
416 if s.inner.events_port.read().bits() != 0 {
417 s.inner.events_port.write(|w| w);
418
419 #[cfg(any(feature = "52833", feature = "52840"))]
420 let ports = &[&*P0::ptr(), &*P1::ptr()];
421 #[cfg(not(any(feature = "52833", feature = "52840")))]
422 let ports = &[&*P0::ptr()];
423
424 let mut work = true;
425 while work {
426 work = false;
427 for (port, &p) in ports.iter().enumerate() {
428 for pin in BitIter(p.latch.read().bits()) {
429 work = true;
430 p.pin_cnf[pin as usize].modify(|_, w| w.sense().disabled());
431 p.latch.write(|w| w.bits(1 << pin));
432 s.port_signals[port * 32 + pin as usize].signal(());
433 }
434 }
435 }
436 }
437}
438
439struct BitIter(u32);
440
441impl Iterator for BitIter {
442 type Item = u32;
443
444 fn next(&mut self) -> Option<Self::Item> {
445 match self.0.trailing_zeros() {
446 32 => None,
447 b => {
448 self.0 &= !(1 << b);
449 Some(b)
450 }
239 } 451 }
240 } 452 }
241} 453}