aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-02-04 23:56:17 +0100
committerDario Nieuwenhuis <[email protected]>2021-02-04 23:56:17 +0100
commita7797a918d3a42f9244a853d2a47aced0ceb900a (patch)
tree4ef025641efec64892caf82a710782bb88e84095
parent18797031533c11ace18160c5917d5131709397ce (diff)
nrf/gpiote: new api: switch to owned structs, implement WaitForHigh/WaitForLow.
-rw-r--r--embassy-nrf-examples/src/bin/gpiote_channel.rs (renamed from embassy-nrf-examples/src/bin/gpiote.rs)32
-rw-r--r--embassy-nrf-examples/src/bin/gpiote_port.rs39
-rw-r--r--embassy-nrf/src/gpiote.rs580
3 files changed, 323 insertions, 328 deletions
diff --git a/embassy-nrf-examples/src/bin/gpiote.rs b/embassy-nrf-examples/src/bin/gpiote_channel.rs
index f5315d6a6..5470c47cd 100644
--- a/embassy-nrf-examples/src/bin/gpiote.rs
+++ b/embassy-nrf-examples/src/bin/gpiote_channel.rs
@@ -12,7 +12,7 @@ use nrf52840_hal::gpio;
12 12
13use embassy::executor::{task, Executor}; 13use embassy::executor::{task, Executor};
14use embassy::util::Forever; 14use embassy::util::Forever;
15use embassy_nrf::gpiote; 15use embassy_nrf::gpiote::{Channels, Gpiote, InputChannel, InputChannelPolarity};
16use embassy_nrf::interrupt; 16use embassy_nrf::interrupt;
17 17
18#[task] 18#[task]
@@ -20,46 +20,44 @@ async fn run() {
20 let p = unwrap!(embassy_nrf::pac::Peripherals::take()); 20 let p = unwrap!(embassy_nrf::pac::Peripherals::take());
21 let port0 = gpio::p0::Parts::new(p.P0); 21 let port0 = gpio::p0::Parts::new(p.P0);
22 22
23 let g = gpiote::Gpiote::new(p.GPIOTE, interrupt::take!(GPIOTE)); 23 let (g, chs) = Gpiote::new(p.GPIOTE, interrupt::take!(GPIOTE));
24 24
25 info!("Starting!"); 25 info!("Starting!");
26 26
27 let pin1 = port0.p0_11.into_pullup_input().degrade(); 27 let pin1 = port0.p0_11.into_pullup_input().degrade();
28 let button1 = async { 28 let pin2 = port0.p0_12.into_pullup_input().degrade();
29 let ch = unwrap!(g.new_input_channel(pin1, gpiote::InputChannelPolarity::HiToLo)); 29 let pin3 = port0.p0_24.into_pullup_input().degrade();
30 let pin4 = port0.p0_25.into_pullup_input().degrade();
31
32 let ch1 = InputChannel::new(g, chs.ch0, pin1, InputChannelPolarity::HiToLo);
33 let ch2 = InputChannel::new(g, chs.ch1, pin2, InputChannelPolarity::LoToHi);
34 let ch3 = InputChannel::new(g, chs.ch2, pin3, InputChannelPolarity::Toggle);
35 let ch4 = InputChannel::new(g, chs.ch3, pin4, InputChannelPolarity::Toggle);
30 36
37 let button1 = async {
31 loop { 38 loop {
32 ch.wait().await; 39 ch1.wait().await;
33 info!("Button 1 pressed") 40 info!("Button 1 pressed")
34 } 41 }
35 }; 42 };
36 43
37 let pin2 = port0.p0_12.into_pullup_input().degrade();
38 let button2 = async { 44 let button2 = async {
39 let ch = unwrap!(g.new_input_channel(pin2, gpiote::InputChannelPolarity::LoToHi));
40
41 loop { 45 loop {
42 ch.wait().await; 46 ch2.wait().await;
43 info!("Button 2 released") 47 info!("Button 2 released")
44 } 48 }
45 }; 49 };
46 50
47 let pin3 = port0.p0_24.into_pullup_input().degrade();
48 let button3 = async { 51 let button3 = async {
49 let ch = unwrap!(g.new_input_channel(pin3, gpiote::InputChannelPolarity::Toggle));
50
51 loop { 52 loop {
52 ch.wait().await; 53 ch3.wait().await;
53 info!("Button 3 toggled") 54 info!("Button 3 toggled")
54 } 55 }
55 }; 56 };
56 57
57 let pin4 = port0.p0_25.into_pullup_input().degrade();
58 let button4 = async { 58 let button4 = async {
59 let ch = unwrap!(g.new_input_channel(pin4, gpiote::InputChannelPolarity::Toggle));
60
61 loop { 59 loop {
62 ch.wait().await; 60 ch4.wait().await;
63 info!("Button 4 toggled") 61 info!("Button 4 toggled")
64 } 62 }
65 }; 63 };
diff --git a/embassy-nrf-examples/src/bin/gpiote_port.rs b/embassy-nrf-examples/src/bin/gpiote_port.rs
index 833096f3a..9d999f951 100644
--- a/embassy-nrf-examples/src/bin/gpiote_port.rs
+++ b/embassy-nrf-examples/src/bin/gpiote_port.rs
@@ -7,20 +7,22 @@ mod example_common;
7use example_common::*; 7use example_common::*;
8 8
9use core::mem; 9use core::mem;
10use core::pin::Pin;
10use cortex_m_rt::entry; 11use cortex_m_rt::entry;
11use defmt::panic; 12use defmt::panic;
12use nrf52840_hal::gpio; 13use nrf52840_hal::gpio;
13 14
14use embassy::executor::{task, Executor}; 15use embassy::executor::{task, Executor};
16use embassy::gpio::{WaitForHigh, WaitForLow};
15use embassy::util::Forever; 17use embassy::util::Forever;
16use embassy_nrf::gpiote::{Gpiote, PortInputPolarity}; 18use embassy_nrf::gpiote::{Gpiote, GpiotePin};
17use embassy_nrf::interrupt; 19use embassy_nrf::interrupt;
18 20
19async fn button(g: &Gpiote, n: usize, pin: gpio::Pin<gpio::Input<gpio::PullUp>>) { 21async fn button(n: usize, mut pin: GpiotePin<gpio::PullUp>) {
20 loop { 22 loop {
21 g.wait_port_input(&pin, PortInputPolarity::Low).await; 23 Pin::new(&mut pin).wait_for_low().await;
22 info!("Button {:?} pressed!", n); 24 info!("Button {:?} pressed!", n);
23 g.wait_port_input(&pin, PortInputPolarity::High).await; 25 Pin::new(&mut pin).wait_for_high().await;
24 info!("Button {:?} released!", n); 26 info!("Button {:?} released!", n);
25 } 27 }
26} 28}
@@ -30,19 +32,24 @@ async fn run() {
30 let p = unwrap!(embassy_nrf::pac::Peripherals::take()); 32 let p = unwrap!(embassy_nrf::pac::Peripherals::take());
31 let port0 = gpio::p0::Parts::new(p.P0); 33 let port0 = gpio::p0::Parts::new(p.P0);
32 34
33 let g = Gpiote::new(p.GPIOTE, interrupt::take!(GPIOTE)); 35 let (g, _) = Gpiote::new(p.GPIOTE, interrupt::take!(GPIOTE));
34 info!(
35 "sizeof Signal<()> = {:usize}",
36 mem::size_of::<embassy::util::Signal<()>>()
37 );
38 info!("sizeof gpiote = {:usize}", mem::size_of::<Gpiote>());
39
40 info!("Starting!");
41 36
42 let button1 = button(&g, 1, port0.p0_11.into_pullup_input().degrade()); 37 let button1 = button(
43 let button2 = button(&g, 2, port0.p0_12.into_pullup_input().degrade()); 38 1,
44 let button3 = button(&g, 3, port0.p0_24.into_pullup_input().degrade()); 39 GpiotePin::new(g, port0.p0_11.into_pullup_input().degrade()),
45 let button4 = button(&g, 4, port0.p0_25.into_pullup_input().degrade()); 40 );
41 let button2 = button(
42 2,
43 GpiotePin::new(g, port0.p0_12.into_pullup_input().degrade()),
44 );
45 let button3 = button(
46 3,
47 GpiotePin::new(g, port0.p0_24.into_pullup_input().degrade()),
48 );
49 let button4 = button(
50 4,
51 GpiotePin::new(g, port0.p0_25.into_pullup_input().degrade()),
52 );
46 futures::join!(button1, button2, button3, button4); 53 futures::join!(button1, button2, button3, button4);
47} 54}
48 55
diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs
index 65a584c78..89aab5bc6 100644
--- a/embassy-nrf/src/gpiote.rs
+++ b/embassy-nrf/src/gpiote.rs
@@ -1,18 +1,20 @@
1use crate::fmt::{panic, *};
2use core::cell::Cell;
3use core::future::Future; 1use core::future::Future;
2use core::mem::ManuallyDrop;
3use core::ops::Deref;
4use core::pin::Pin;
4use core::ptr; 5use core::ptr;
5use core::task::{Context, Poll}; 6use core::task::{Context, Poll};
7use embassy::gpio::{WaitForHigh, WaitForLow};
6use embassy::util::Signal; 8use embassy::util::Signal;
7 9
8use crate::hal::gpio::{Input, Level, Output, Pin, Port}; 10use crate::fmt::{panic, *};
11use crate::hal::gpio::{Input, Level, Output, Pin as GpioPin, Port};
9use crate::interrupt; 12use crate::interrupt;
10use crate::interrupt::OwnedInterrupt; 13use crate::interrupt::OwnedInterrupt;
14use crate::pac;
11use crate::pac::generic::Reg; 15use crate::pac::generic::Reg;
12use crate::pac::gpiote::_TASKS_OUT; 16use crate::pac::gpiote::_TASKS_OUT;
13#[cfg(any(feature = "52833", feature = "52840"))] 17use crate::pac::{p0 as pac_gpio, GPIOTE};
14use crate::pac::P1;
15use crate::pac::{p0 as gpio, GPIOTE, P0};
16 18
17#[cfg(not(feature = "51"))] 19#[cfg(not(feature = "51"))]
18use crate::pac::gpiote::{_TASKS_CLR, _TASKS_SET}; 20use crate::pac::gpiote::{_TASKS_CLR, _TASKS_SET};
@@ -24,20 +26,51 @@ pub const PIN_COUNT: usize = 48;
24#[cfg(not(any(feature = "52833", feature = "52840")))] 26#[cfg(not(any(feature = "52833", feature = "52840")))]
25pub const PIN_COUNT: usize = 32; 27pub const PIN_COUNT: usize = 32;
26 28
27pub struct Gpiote { 29pub trait ChannelID {
28 inner: GPIOTE, 30 fn number(&self) -> usize;
29 free_channels: Cell<u8>, // 0 = used, 1 = free. 8 bits for 8 channelself.
30 channel_signals: [Signal<()>; CHANNEL_COUNT],
31 port_signals: [Signal<()>; PIN_COUNT],
32} 31}
33 32
34static mut INSTANCE: *const Gpiote = ptr::null_mut(); 33macro_rules! impl_channel {
34 ($ChX:ident, $n:expr) => {
35 pub struct $ChX(());
36 impl $ChX {
37 pub fn degrade(self) -> ChAny {
38 ChAny($n)
39 }
40 }
35 41
36pub enum PortInputPolarity { 42 impl ChannelID for $ChX {
37 High, 43 fn number(&self) -> usize {
38 Low, 44 $n
45 }
46 }
47 };
39} 48}
40 49
50impl_channel!(Ch0, 0);
51impl_channel!(Ch1, 1);
52impl_channel!(Ch2, 2);
53impl_channel!(Ch3, 3);
54impl_channel!(Ch4, 4);
55impl_channel!(Ch5, 5);
56impl_channel!(Ch6, 6);
57impl_channel!(Ch7, 7);
58
59pub struct ChAny(u8);
60
61impl ChannelID for ChAny {
62 fn number(&self) -> usize {
63 self.0 as usize
64 }
65}
66
67#[derive(Clone, Copy)]
68pub struct Gpiote(());
69
70const NEW_SIGNAL: Signal<()> = Signal::new();
71static CHANNEL_SIGNALS: [Signal<()>; CHANNEL_COUNT] = [NEW_SIGNAL; CHANNEL_COUNT];
72static PORT_SIGNALS: [Signal<()>; PIN_COUNT] = [NEW_SIGNAL; PIN_COUNT];
73
41pub enum InputChannelPolarity { 74pub enum InputChannelPolarity {
42 None, 75 None,
43 HiToLo, 76 HiToLo,
@@ -58,12 +91,23 @@ pub enum NewChannelError {
58 NoFreeChannels, 91 NoFreeChannels,
59} 92}
60 93
94pub struct Channels {
95 pub ch0: Ch0,
96 pub ch1: Ch1,
97 pub ch2: Ch2,
98 pub ch3: Ch3,
99 pub ch4: Ch4,
100 pub ch5: Ch5,
101 pub ch6: Ch6,
102 pub ch7: Ch7,
103}
104
61impl Gpiote { 105impl Gpiote {
62 pub fn new(gpiote: GPIOTE, irq: interrupt::GPIOTEInterrupt) -> Self { 106 pub fn new(gpiote: GPIOTE, irq: interrupt::GPIOTEInterrupt) -> (Self, Channels) {
63 #[cfg(any(feature = "52833", feature = "52840"))] 107 #[cfg(any(feature = "52833", feature = "52840"))]
64 let ports = unsafe { &[&*P0::ptr(), &*P1::ptr()] }; 108 let ports = unsafe { &[&*pac::P0::ptr(), &*pac::P1::ptr()] };
65 #[cfg(not(any(feature = "52833", feature = "52840")))] 109 #[cfg(not(any(feature = "52833", feature = "52840")))]
66 let ports = unsafe { &[&*P0::ptr()] }; 110 let ports = unsafe { &[&*pac::P0::ptr()] };
67 111
68 for &p in ports { 112 for &p in ports {
69 // Enable latched detection 113 // Enable latched detection
@@ -79,240 +123,38 @@ impl Gpiote {
79 irq.unpend(); 123 irq.unpend();
80 irq.enable(); 124 irq.enable();
81 125
82 Self { 126 (
83 inner: gpiote, 127 Self(()),
84 free_channels: Cell::new(0xFF), // all 8 channels free 128 Channels {
85 channel_signals: [ 129 ch0: Ch0(()),
86 Signal::new(), 130 ch1: Ch1(()),
87 Signal::new(), 131 ch2: Ch2(()),
88 Signal::new(), 132 ch3: Ch3(()),
89 Signal::new(), 133 ch4: Ch4(()),
90 Signal::new(), 134 ch5: Ch5(()),
91 Signal::new(), 135 ch6: Ch6(()),
92 Signal::new(), 136 ch7: Ch7(()),
93 Signal::new(), 137 },
94 ], 138 )
95 // This is just horrible
96 #[cfg(any(feature = "52833", feature = "52840"))]
97 port_signals: [
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 Signal::new(),
141 Signal::new(),
142 Signal::new(),
143 Signal::new(),
144 Signal::new(),
145 Signal::new(),
146 ],
147 #[cfg(not(any(feature = "52833", feature = "52840")))]
148 port_signals: [
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(),
167 Signal::new(),
168 Signal::new(),
169 Signal::new(),
170 Signal::new(),
171 Signal::new(),
172 Signal::new(),
173 Signal::new(),
174 Signal::new(),
175 Signal::new(),
176 Signal::new(),
177 Signal::new(),
178 Signal::new(),
179 Signal::new(),
180 Signal::new(),
181 ],
182 }
183 }
184
185 fn allocate_channel(&self) -> Result<u8, NewChannelError> {
186 interrupt::free(|_| {
187 let chs = self.free_channels.get();
188 let index = chs.trailing_zeros() as usize;
189 if index == 8 {
190 return Err(NewChannelError::NoFreeChannels);
191 }
192 self.free_channels.set(chs & !(1 << index));
193 Ok(index as u8)
194 })
195 }
196
197 fn free_channel(&self, index: u8) {
198 interrupt::free(|_| {
199 self.inner.config[index as usize].write(|w| w.mode().disabled());
200 self.inner.intenclr.write(|w| unsafe { w.bits(1 << index) });
201
202 self.free_channels
203 .set(self.free_channels.get() | 1 << index);
204 trace!("freed ch {:?}", index);
205 })
206 }
207
208 pub fn wait_port_input<'a, T>(
209 &'a self,
210 pin: &'a Pin<Input<T>>,
211 polarity: PortInputPolarity,
212 ) -> PortInputFuture<'a, T> {
213 interrupt::free(|_| {
214 unsafe { INSTANCE = self };
215 PortInputFuture {
216 gpiote: self,
217 pin,
218 polarity,
219 }
220 })
221 }
222
223 pub fn new_input_channel<'a, T>(
224 &'a self,
225 pin: Pin<Input<T>>,
226 polarity: InputChannelPolarity,
227 ) -> Result<InputChannel<'a, T>, NewChannelError> {
228 interrupt::free(|_| {
229 unsafe { INSTANCE = self };
230 let index = self.allocate_channel()?;
231 trace!("allocated in ch {:?}", index as u8);
232
233 self.inner.config[index as usize].write(|w| {
234 match polarity {
235 InputChannelPolarity::HiToLo => w.mode().event().polarity().hi_to_lo(),
236 InputChannelPolarity::LoToHi => w.mode().event().polarity().lo_to_hi(),
237 InputChannelPolarity::None => w.mode().event().polarity().none(),
238 InputChannelPolarity::Toggle => w.mode().event().polarity().toggle(),
239 };
240 #[cfg(any(feature = "52833", feature = "52840"))]
241 w.port().bit(match pin.port() {
242 Port::Port0 => false,
243 Port::Port1 => true,
244 });
245 unsafe { w.psel().bits(pin.pin()) }
246 });
247
248 // Enable interrupt
249 self.inner.intenset.write(|w| unsafe { w.bits(1 << index) });
250
251 Ok(InputChannel {
252 gpiote: self,
253 index,
254 pin,
255 })
256 })
257 }
258
259 pub fn new_output_channel<'a, T>(
260 &'a self,
261 pin: Pin<Output<T>>,
262 level: Level,
263 polarity: OutputChannelPolarity,
264 ) -> Result<OutputChannel<'a>, NewChannelError> {
265 interrupt::free(|_| {
266 unsafe { INSTANCE = self };
267 let index = self.allocate_channel()?;
268 trace!("allocated out ch {:?}", index);
269
270 self.inner.config[index as usize].write(|w| {
271 w.mode().task();
272 match level {
273 Level::High => w.outinit().high(),
274 Level::Low => w.outinit().low(),
275 };
276 match polarity {
277 OutputChannelPolarity::Set => w.polarity().lo_to_hi(),
278 OutputChannelPolarity::Clear => w.polarity().hi_to_lo(),
279 OutputChannelPolarity::Toggle => w.polarity().toggle(),
280 };
281 #[cfg(any(feature = "52833", feature = "52840"))]
282 w.port().bit(match pin.port() {
283 Port::Port0 => false,
284 Port::Port1 => true,
285 });
286 unsafe { w.psel().bits(pin.pin()) }
287 });
288
289 // Enable interrupt
290 self.inner.intenset.write(|w| unsafe { w.bits(1 << index) });
291
292 Ok(OutputChannel {
293 gpiote: self,
294 index,
295 })
296 })
297 } 139 }
298 140
299 unsafe fn on_irq(_ctx: *mut ()) { 141 unsafe fn on_irq(_ctx: *mut ()) {
300 let s = &(*INSTANCE); 142 let g = &*GPIOTE::ptr();
301 143
302 for i in 0..8 { 144 for i in 0..8 {
303 if s.inner.events_in[i].read().bits() != 0 { 145 if g.events_in[i].read().bits() != 0 {
304 s.inner.events_in[i].write(|w| w); 146 g.events_in[i].write(|w| w);
305 s.channel_signals[i].signal(()); 147 CHANNEL_SIGNALS[i].signal(());
306 } 148 }
307 } 149 }
308 150
309 if s.inner.events_port.read().bits() != 0 { 151 if g.events_port.read().bits() != 0 {
310 s.inner.events_port.write(|w| w); 152 g.events_port.write(|w| w);
311 153
312 #[cfg(any(feature = "52833", feature = "52840"))] 154 #[cfg(any(feature = "52833", feature = "52840"))]
313 let ports = &[&*P0::ptr(), &*P1::ptr()]; 155 let ports = &[&*pac::P0::ptr(), &*pac::P1::ptr()];
314 #[cfg(not(any(feature = "52833", feature = "52840")))] 156 #[cfg(not(any(feature = "52833", feature = "52840")))]
315 let ports = &[&*P0::ptr()]; 157 let ports = &[&*pac::P0::ptr()];
316 158
317 let mut work = true; 159 let mut work = true;
318 while work { 160 while work {
@@ -322,7 +164,7 @@ impl Gpiote {
322 work = true; 164 work = true;
323 p.pin_cnf[pin as usize].modify(|_, w| w.sense().disabled()); 165 p.pin_cnf[pin as usize].modify(|_, w| w.sense().disabled());
324 p.latch.write(|w| w.bits(1 << pin)); 166 p.latch.write(|w| w.bits(1 << pin));
325 s.port_signals[port * 32 + pin as usize].signal(()); 167 PORT_SIGNALS[port * 32 + pin as usize].signal(());
326 } 168 }
327 } 169 }
328 } 170 }
@@ -330,32 +172,7 @@ impl Gpiote {
330 } 172 }
331} 173}
332 174
333pub struct PortInputFuture<'a, T> { 175fn pin_num<T>(pin: &GpioPin<T>) -> usize {
334 gpiote: &'a Gpiote,
335 pin: &'a Pin<Input<T>>,
336 polarity: PortInputPolarity,
337}
338
339impl<'a, T> Drop for PortInputFuture<'a, T> {
340 fn drop(&mut self) {
341 pin_conf(&self.pin).modify(|_, w| w.sense().disabled());
342 self.gpiote.port_signals[pin_num(&self.pin)].reset();
343 }
344}
345
346impl<'a, T> Future for PortInputFuture<'a, T> {
347 type Output = ();
348
349 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
350 pin_conf(&self.pin).modify(|_, w| match self.polarity {
351 PortInputPolarity::Low => w.sense().low(),
352 PortInputPolarity::High => w.sense().high(),
353 });
354 self.gpiote.port_signals[pin_num(&self.pin)].poll_wait(cx)
355 }
356}
357
358fn pin_num<T>(pin: &Pin<T>) -> usize {
359 let port = match pin.port() { 176 let port = match pin.port() {
360 Port::Port0 => 0, 177 Port::Port0 => 0,
361 #[cfg(any(feature = "52833", feature = "52840"))] 178 #[cfg(any(feature = "52833", feature = "52840"))]
@@ -365,86 +182,189 @@ fn pin_num<T>(pin: &Pin<T>) -> usize {
365 port + pin.pin() as usize 182 port + pin.pin() as usize
366} 183}
367 184
368fn pin_block<T>(pin: &Pin<T>) -> &gpio::RegisterBlock { 185fn pin_block<T>(pin: &GpioPin<T>) -> &pac_gpio::RegisterBlock {
369 let ptr = match pin.port() { 186 let ptr = match pin.port() {
370 Port::Port0 => P0::ptr(), 187 Port::Port0 => pac::P0::ptr(),
371 #[cfg(any(feature = "52833", feature = "52840"))] 188 #[cfg(any(feature = "52833", feature = "52840"))]
372 Port::Port1 => P1::ptr(), 189 Port::Port1 => pac::P1::ptr(),
373 }; 190 };
374 191
375 unsafe { &*ptr } 192 unsafe { &*ptr }
376} 193}
377 194
378fn pin_conf<T>(pin: &Pin<T>) -> &gpio::PIN_CNF { 195fn pin_conf<T>(pin: &GpioPin<T>) -> &pac_gpio::PIN_CNF {
379 &pin_block(pin).pin_cnf[pin.pin() as usize] 196 &pin_block(pin).pin_cnf[pin.pin() as usize]
380} 197}
381 198
382pub struct InputChannel<'a, T> { 199pub struct InputChannel<C: ChannelID, T> {
383 gpiote: &'a Gpiote, 200 ch: C,
384 pin: Pin<Input<T>>, 201 pin: GpioPin<Input<T>>,
385 index: u8,
386} 202}
387 203
388impl<'a, T> Drop for InputChannel<'a, T> { 204impl<C: ChannelID, T> Drop for InputChannel<C, T> {
389 fn drop(&mut self) { 205 fn drop(&mut self) {
390 self.gpiote.free_channel(self.index); 206 let g = unsafe { &*GPIOTE::ptr() };
207 let index = self.ch.number();
208 g.config[index].write(|w| w.mode().disabled());
209 g.intenclr.write(|w| unsafe { w.bits(1 << index) });
391 } 210 }
392} 211}
393 212
394impl<'a, T> InputChannel<'a, T> { 213impl<C: ChannelID, T> InputChannel<C, T> {
214 pub fn new(
215 _gpiote: Gpiote,
216 ch: C,
217 pin: GpioPin<Input<T>>,
218 polarity: InputChannelPolarity,
219 ) -> Self {
220 let g = unsafe { &*GPIOTE::ptr() };
221 let index = ch.number();
222
223 g.config[index].write(|w| {
224 match polarity {
225 InputChannelPolarity::HiToLo => w.mode().event().polarity().hi_to_lo(),
226 InputChannelPolarity::LoToHi => w.mode().event().polarity().lo_to_hi(),
227 InputChannelPolarity::None => w.mode().event().polarity().none(),
228 InputChannelPolarity::Toggle => w.mode().event().polarity().toggle(),
229 };
230 #[cfg(any(feature = "52833", feature = "52840"))]
231 w.port().bit(match pin.port() {
232 Port::Port0 => false,
233 Port::Port1 => true,
234 });
235 unsafe { w.psel().bits(pin.pin()) }
236 });
237
238 CHANNEL_SIGNALS[index].reset();
239
240 // Enable interrupt
241 g.intenset.write(|w| unsafe { w.bits(1 << index) });
242
243 InputChannel { ch, pin }
244 }
245
246 pub fn free(self) -> (C, GpioPin<Input<T>>) {
247 let m = ManuallyDrop::new(self);
248 let ch = unsafe { ptr::read(&m.ch) };
249 let pin = unsafe { ptr::read(&m.pin) };
250 (ch, pin)
251 }
252
395 pub async fn wait(&self) { 253 pub async fn wait(&self) {
396 self.gpiote.channel_signals[self.index as usize] 254 let index = self.ch.number();
397 .wait() 255 CHANNEL_SIGNALS[index].wait().await;
398 .await;
399 } 256 }
400 257
401 pub fn pin(&self) -> &Pin<Input<T>> { 258 pub fn pin(&self) -> &GpioPin<Input<T>> {
402 &self.pin 259 &self.pin
403 } 260 }
404} 261}
405 262
406pub struct OutputChannel<'a> { 263pub struct OutputChannel<C: ChannelID, T> {
407 gpiote: &'a Gpiote, 264 ch: C,
408 index: u8, 265 pin: GpioPin<Output<T>>,
409} 266}
410 267
411impl<'a> Drop for OutputChannel<'a> { 268impl<C: ChannelID, T> Drop for OutputChannel<C, T> {
412 fn drop(&mut self) { 269 fn drop(&mut self) {
413 self.gpiote.free_channel(self.index); 270 let g = unsafe { &*GPIOTE::ptr() };
271 let index = self.ch.number();
272 g.config[index].write(|w| w.mode().disabled());
273 g.intenclr.write(|w| unsafe { w.bits(1 << index) });
414 } 274 }
415} 275}
416 276
417impl<'a> OutputChannel<'a> { 277impl<C: ChannelID, T> OutputChannel<C, T> {
278 pub fn new(
279 _gpiote: Gpiote,
280 ch: C,
281 pin: GpioPin<Output<T>>,
282 level: Level,
283 polarity: OutputChannelPolarity,
284 ) -> Self {
285 let g = unsafe { &*GPIOTE::ptr() };
286 let index = ch.number();
287
288 g.config[index].write(|w| {
289 w.mode().task();
290 match level {
291 Level::High => w.outinit().high(),
292 Level::Low => w.outinit().low(),
293 };
294 match polarity {
295 OutputChannelPolarity::Set => w.polarity().lo_to_hi(),
296 OutputChannelPolarity::Clear => w.polarity().hi_to_lo(),
297 OutputChannelPolarity::Toggle => w.polarity().toggle(),
298 };
299 #[cfg(any(feature = "52833", feature = "52840"))]
300 w.port().bit(match pin.port() {
301 Port::Port0 => false,
302 Port::Port1 => true,
303 });
304 unsafe { w.psel().bits(pin.pin()) }
305 });
306
307 // Enable interrupt
308 g.intenset.write(|w| unsafe { w.bits(1 << index) });
309
310 OutputChannel { ch, pin }
311 }
312
313 pub fn free(self) -> (C, GpioPin<Output<T>>) {
314 let m = ManuallyDrop::new(self);
315 let ch = unsafe { ptr::read(&m.ch) };
316 let pin = unsafe { ptr::read(&m.pin) };
317 (ch, pin)
318 }
319
418 /// Triggers `task out` (as configured with task_out_polarity, defaults to Toggle). 320 /// Triggers `task out` (as configured with task_out_polarity, defaults to Toggle).
419 pub fn out(&self) { 321 pub fn out(&self) {
420 self.gpiote.inner.tasks_out[self.index as usize].write(|w| unsafe { w.bits(1) }); 322 let g = unsafe { &*GPIOTE::ptr() };
323 let index = self.ch.number();
324
325 g.tasks_out[index].write(|w| unsafe { w.bits(1) });
421 } 326 }
422 /// Triggers `task set` (set associated pin high). 327 /// Triggers `task set` (set associated pin high).
423 #[cfg(not(feature = "51"))] 328 #[cfg(not(feature = "51"))]
424 pub fn set(&self) { 329 pub fn set(&self) {
425 self.gpiote.inner.tasks_set[self.index as usize].write(|w| unsafe { w.bits(1) }); 330 let g = unsafe { &*GPIOTE::ptr() };
331 let index = self.ch.number();
332
333 g.tasks_set[index].write(|w| unsafe { w.bits(1) });
426 } 334 }
427 /// Triggers `task clear` (set associated pin low). 335 /// Triggers `task clear` (set associated pin low).
428 #[cfg(not(feature = "51"))] 336 #[cfg(not(feature = "51"))]
429 pub fn clear(&self) { 337 pub fn clear(&self) {
430 self.gpiote.inner.tasks_clr[self.index as usize].write(|w| unsafe { w.bits(1) }); 338 let g = unsafe { &*GPIOTE::ptr() };
339 let index = self.ch.number();
340
341 g.tasks_clr[index].write(|w| unsafe { w.bits(1) });
431 } 342 }
432 343
433 /// Returns reference to task_out endpoint for PPI. 344 /// Returns reference to task_out endpoint for PPI.
434 pub fn task_out(&self) -> &Reg<u32, _TASKS_OUT> { 345 pub fn task_out(&self) -> &Reg<u32, _TASKS_OUT> {
435 &self.gpiote.inner.tasks_out[self.index as usize] 346 let g = unsafe { &*GPIOTE::ptr() };
347 let index = self.ch.number();
348
349 &g.tasks_out[index]
436 } 350 }
437 351
438 /// Returns reference to task_clr endpoint for PPI. 352 /// Returns reference to task_clr endpoint for PPI.
439 #[cfg(not(feature = "51"))] 353 #[cfg(not(feature = "51"))]
440 pub fn task_clr(&self) -> &Reg<u32, _TASKS_CLR> { 354 pub fn task_clr(&self) -> &Reg<u32, _TASKS_CLR> {
441 &self.gpiote.inner.tasks_clr[self.index as usize] 355 let g = unsafe { &*GPIOTE::ptr() };
356 let index = self.ch.number();
357
358 &g.tasks_clr[index]
442 } 359 }
443 360
444 /// Returns reference to task_set endpoint for PPI. 361 /// Returns reference to task_set endpoint for PPI.
445 #[cfg(not(feature = "51"))] 362 #[cfg(not(feature = "51"))]
446 pub fn task_set(&self) -> &Reg<u32, _TASKS_SET> { 363 pub fn task_set(&self) -> &Reg<u32, _TASKS_SET> {
447 &self.gpiote.inner.tasks_set[self.index as usize] 364 let g = unsafe { &*GPIOTE::ptr() };
365 let index = self.ch.number();
366
367 &g.tasks_set[index]
448 } 368 }
449} 369}
450 370
@@ -463,3 +383,73 @@ impl Iterator for BitIter {
463 } 383 }
464 } 384 }
465} 385}
386
387pub struct GpiotePin<T> {
388 pin: GpioPin<Input<T>>,
389}
390
391impl<T> Unpin for GpiotePin<T> {}
392
393impl<T> GpiotePin<T> {
394 pub fn new(_gpiote: Gpiote, pin: GpioPin<Input<T>>) -> Self {
395 Self { pin }
396 }
397}
398
399impl<T: 'static> WaitForHigh for GpiotePin<T> {
400 type Future<'a> = PortInputFuture<'a, T>;
401
402 fn wait_for_high<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> {
403 PortInputFuture {
404 pin: &self.get_mut().pin,
405 polarity: PortInputPolarity::High,
406 }
407 }
408}
409
410impl<T: 'static> WaitForLow for GpiotePin<T> {
411 type Future<'a> = PortInputFuture<'a, T>;
412
413 fn wait_for_low<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> {
414 PortInputFuture {
415 pin: &self.get_mut().pin,
416 polarity: PortInputPolarity::Low,
417 }
418 }
419}
420
421impl<T> Deref for GpiotePin<T> {
422 type Target = GpioPin<Input<T>>;
423 fn deref(&self) -> &Self::Target {
424 &self.pin
425 }
426}
427
428enum PortInputPolarity {
429 High,
430 Low,
431}
432
433pub struct PortInputFuture<'a, T> {
434 pin: &'a GpioPin<Input<T>>,
435 polarity: PortInputPolarity,
436}
437
438impl<'a, T> Drop for PortInputFuture<'a, T> {
439 fn drop(&mut self) {
440 pin_conf(&self.pin).modify(|_, w| w.sense().disabled());
441 PORT_SIGNALS[pin_num(&self.pin)].reset();
442 }
443}
444
445impl<'a, T> Future for PortInputFuture<'a, T> {
446 type Output = ();
447
448 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
449 pin_conf(&self.pin).modify(|_, w| match self.polarity {
450 PortInputPolarity::Low => w.sense().low(),
451 PortInputPolarity::High => w.sense().high(),
452 });
453 PORT_SIGNALS[pin_num(&self.pin)].poll_wait(cx)
454 }
455}