aboutsummaryrefslogtreecommitdiff
path: root/embassy-nrf/src/gpiote.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-nrf/src/gpiote.rs')
-rw-r--r--embassy-nrf/src/gpiote.rs492
1 files changed, 400 insertions, 92 deletions
diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs
index 43e43f0bf..1f6000b13 100644
--- a/embassy-nrf/src/gpiote.rs
+++ b/embassy-nrf/src/gpiote.rs
@@ -1,13 +1,14 @@
1//! GPIO task/event (GPIOTE) driver. 1//! GPIO task/event (GPIOTE) driver.
2#![macro_use]
2 3
3use core::convert::Infallible; 4use core::convert::Infallible;
4use core::future::{poll_fn, Future}; 5use core::future::{Future, poll_fn};
5use core::task::{Context, Poll}; 6use core::task::{Context, Poll};
6 7
7use embassy_hal_internal::{impl_peripheral, Peri, PeripheralType}; 8use embassy_hal_internal::{Peri, PeripheralType, impl_peripheral};
8use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
9 10
10use crate::gpio::{AnyPin, Flex, Input, Output, Pin as GpioPin, SealedPin as _}; 11use crate::gpio::{AnyPin, Flex, Input, Level, Output, OutputDrive, Pin as GpioPin, Pull, SealedPin as _};
11use crate::interrupt::InterruptExt; 12use crate::interrupt::InterruptExt;
12#[cfg(not(feature = "_nrf51"))] 13#[cfg(not(feature = "_nrf51"))]
13use crate::pac::gpio::vals::Detectmode; 14use crate::pac::gpio::vals::Detectmode;
@@ -19,13 +20,32 @@ use crate::{interrupt, pac, peripherals};
19#[cfg(feature = "_nrf51")] 20#[cfg(feature = "_nrf51")]
20/// Amount of GPIOTE channels in the chip. 21/// Amount of GPIOTE channels in the chip.
21const CHANNEL_COUNT: usize = 4; 22const CHANNEL_COUNT: usize = 4;
22#[cfg(not(feature = "_nrf51"))] 23#[cfg(not(any(feature = "_nrf51", feature = "_nrf54l")))]
23/// Amount of GPIOTE channels in the chip. 24/// Amount of GPIOTE channels in the chip.
24const CHANNEL_COUNT: usize = 8; 25const CHANNEL_COUNT: usize = 8;
25 26#[cfg(any(feature = "_nrf54l"))]
26#[cfg(any(feature = "nrf52833", feature = "nrf52840", feature = "_nrf5340"))] 27/// Amount of GPIOTE channels in the chip.
28const CHANNEL_COUNT: usize = 12;
29/// Max channels per port
30const CHANNELS_PER_PORT: usize = 8;
31
32#[cfg(any(
33 feature = "nrf52833",
34 feature = "nrf52840",
35 feature = "_nrf5340",
36 feature = "_nrf54l15",
37 feature = "_nrf54l10",
38 feature = "_nrf54l05"
39))]
27const PIN_COUNT: usize = 48; 40const PIN_COUNT: usize = 48;
28#[cfg(not(any(feature = "nrf52833", feature = "nrf52840", feature = "_nrf5340")))] 41#[cfg(feature = "_nrf54lm20")]
42const PIN_COUNT: usize = 66;
43#[cfg(not(any(
44 feature = "nrf52833",
45 feature = "nrf52840",
46 feature = "_nrf5340",
47 feature = "_nrf54l",
48)))]
29const PIN_COUNT: usize = 32; 49const PIN_COUNT: usize = 32;
30 50
31#[allow(clippy::declare_interior_mutable_const)] 51#[allow(clippy::declare_interior_mutable_const)]
@@ -54,18 +74,6 @@ pub enum OutputChannelPolarity {
54 Toggle, 74 Toggle,
55} 75}
56 76
57fn regs() -> pac::gpiote::Gpiote {
58 cfg_if::cfg_if! {
59 if #[cfg(any(feature="nrf5340-app-s", feature="nrf9160-s", feature="nrf9120-s"))] {
60 pac::GPIOTE0
61 } else if #[cfg(any(feature="nrf5340-app-ns", feature="nrf9160-ns", feature="nrf9120-ns"))] {
62 pac::GPIOTE1
63 } else {
64 pac::GPIOTE
65 }
66 }
67}
68
69pub(crate) fn init(irq_prio: crate::interrupt::Priority) { 77pub(crate) fn init(irq_prio: crate::interrupt::Priority) {
70 // no latched GPIO detect in nrf51. 78 // no latched GPIO detect in nrf51.
71 #[cfg(not(feature = "_nrf51"))] 79 #[cfg(not(feature = "_nrf51"))]
@@ -77,6 +85,9 @@ pub(crate) fn init(irq_prio: crate::interrupt::Priority) {
77 85
78 for &p in ports { 86 for &p in ports {
79 // Enable latched detection 87 // Enable latched detection
88 #[cfg(all(feature = "_s", not(feature = "_nrf54l")))]
89 p.detectmode_sec().write(|w| w.set_detectmode(Detectmode::LDETECT));
90 #[cfg(any(not(feature = "_s"), all(feature = "_s", feature = "_nrf54l")))]
80 p.detectmode().write(|w| w.set_detectmode(Detectmode::LDETECT)); 91 p.detectmode().write(|w| w.set_detectmode(Detectmode::LDETECT));
81 // Clear latch 92 // Clear latch
82 p.latch().write(|w| w.0 = 0xFFFFFFFF) 93 p.latch().write(|w| w.0 = 0xFFFFFFFF)
@@ -85,57 +96,130 @@ pub(crate) fn init(irq_prio: crate::interrupt::Priority) {
85 96
86 // Enable interrupts 97 // Enable interrupts
87 #[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s", feature = "nrf9120-s"))] 98 #[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s", feature = "nrf9120-s"))]
88 let irq = interrupt::GPIOTE0; 99 let irqs = &[(pac::GPIOTE0, interrupt::GPIOTE0)];
89 #[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns", feature = "nrf9120-ns"))] 100 #[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns", feature = "nrf9120-ns"))]
90 let irq = interrupt::GPIOTE1; 101 let irqs = &[(pac::GPIOTE1, interrupt::GPIOTE1)];
91 #[cfg(any(feature = "_nrf51", feature = "_nrf52", feature = "nrf5340-net"))] 102 #[cfg(any(feature = "_nrf51", feature = "_nrf52", feature = "nrf5340-net"))]
92 let irq = interrupt::GPIOTE; 103 let irqs = &[(pac::GPIOTE, interrupt::GPIOTE)];
104 #[cfg(any(feature = "_nrf54l"))]
105 let irqs = &[
106 #[cfg(feature = "_s")]
107 (pac::GPIOTE20, interrupt::GPIOTE20_0),
108 #[cfg(feature = "_s")]
109 (pac::GPIOTE30, interrupt::GPIOTE30_0),
110 #[cfg(feature = "_ns")]
111 (pac::GPIOTE20, interrupt::GPIOTE20_1),
112 #[cfg(feature = "_ns")]
113 (pac::GPIOTE30, interrupt::GPIOTE30_1),
114 ];
115
116 for (inst, irq) in irqs {
117 irq.unpend();
118 irq.set_priority(irq_prio);
119 unsafe { irq.enable() };
93 120
94 irq.unpend(); 121 let g = inst;
95 irq.set_priority(irq_prio); 122 #[cfg(not(feature = "_nrf54l"))]
96 unsafe { irq.enable() }; 123 g.intenset(INTNUM).write(|w| w.set_port(true));
97 124
98 let g = regs(); 125 #[cfg(all(feature = "_nrf54l", feature = "_ns"))]
99 g.intenset().write(|w| w.set_port(true)); 126 g.intenset(INTNUM).write(|w| w.set_port0nonsecure(true));
127
128 #[cfg(all(feature = "_nrf54l", feature = "_s"))]
129 g.intenset(INTNUM).write(|w| w.set_port0secure(true));
130 }
100} 131}
101 132
133#[cfg(all(feature = "_nrf54l", feature = "_ns"))]
134const INTNUM: usize = 1;
135
136#[cfg(any(not(feature = "_nrf54l"), feature = "_s"))]
137const INTNUM: usize = 0;
138
102#[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s", feature = "nrf9120-s"))] 139#[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s", feature = "nrf9120-s"))]
103#[cfg(feature = "rt")] 140#[cfg(feature = "rt")]
104#[interrupt] 141#[interrupt]
105fn GPIOTE0() { 142fn GPIOTE0() {
106 unsafe { handle_gpiote_interrupt() }; 143 unsafe { handle_gpiote_interrupt(pac::GPIOTE0) };
107} 144}
108 145
109#[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns", feature = "nrf9120-ns"))] 146#[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns", feature = "nrf9120-ns"))]
110#[cfg(feature = "rt")] 147#[cfg(feature = "rt")]
111#[interrupt] 148#[interrupt]
112fn GPIOTE1() { 149fn GPIOTE1() {
113 unsafe { handle_gpiote_interrupt() }; 150 unsafe { handle_gpiote_interrupt(pac::GPIOTE1) };
114} 151}
115 152
116#[cfg(any(feature = "_nrf51", feature = "_nrf52", feature = "nrf5340-net"))] 153#[cfg(any(feature = "_nrf51", feature = "_nrf52", feature = "nrf5340-net"))]
117#[cfg(feature = "rt")] 154#[cfg(feature = "rt")]
118#[interrupt] 155#[interrupt]
119fn GPIOTE() { 156fn GPIOTE() {
120 unsafe { handle_gpiote_interrupt() }; 157 unsafe { handle_gpiote_interrupt(pac::GPIOTE) };
158}
159
160#[cfg(all(feature = "_nrf54l", feature = "_s"))]
161#[cfg(feature = "rt")]
162#[interrupt]
163fn GPIOTE20_0() {
164 unsafe { handle_gpiote_interrupt(pac::GPIOTE20) };
165}
166
167#[cfg(all(feature = "_nrf54l", feature = "_s"))]
168#[cfg(feature = "rt")]
169#[interrupt]
170fn GPIOTE30_0() {
171 unsafe { handle_gpiote_interrupt(pac::GPIOTE30) };
172}
173
174#[cfg(all(feature = "_nrf54l", feature = "_ns"))]
175#[cfg(feature = "rt")]
176#[interrupt]
177fn GPIOTE20_1() {
178 unsafe { handle_gpiote_interrupt(pac::GPIOTE20) };
121} 179}
122 180
123unsafe fn handle_gpiote_interrupt() { 181#[cfg(all(feature = "_nrf54l", feature = "_ns"))]
124 let g = regs(); 182#[cfg(feature = "rt")]
183#[interrupt]
184fn GPIOTE30_1() {
185 unsafe { handle_gpiote_interrupt(pac::GPIOTE30) };
186}
125 187
126 for i in 0..CHANNEL_COUNT { 188unsafe fn handle_gpiote_interrupt(g: pac::gpiote::Gpiote) {
189 for c in 0..CHANNEL_COUNT {
190 let i = c % CHANNELS_PER_PORT;
127 if g.events_in(i).read() != 0 { 191 if g.events_in(i).read() != 0 {
128 g.intenclr().write(|w| w.0 = 1 << i); 192 g.intenclr(INTNUM).write(|w| w.0 = 1 << i);
129 CHANNEL_WAKERS[i].wake(); 193 CHANNEL_WAKERS[c].wake();
130 } 194 }
131 } 195 }
132 196
133 if g.events_port().read() != 0 { 197 #[cfg(not(feature = "_nrf54l"))]
134 g.events_port().write_value(0); 198 let eport = g.events_port(0);
135 199
136 #[cfg(any(feature = "nrf52833", feature = "nrf52840", feature = "_nrf5340"))] 200 #[cfg(all(feature = "_nrf54l", feature = "_ns"))]
201 let eport = g.events_port(0).nonsecure();
202
203 #[cfg(all(feature = "_nrf54l", feature = "_s"))]
204 let eport = g.events_port(0).secure();
205
206 if eport.read() != 0 {
207 eport.write_value(0);
208
209 #[cfg(any(
210 feature = "nrf52833",
211 feature = "nrf52840",
212 feature = "_nrf5340",
213 feature = "_nrf54l"
214 ))]
137 let ports = &[pac::P0, pac::P1]; 215 let ports = &[pac::P0, pac::P1];
138 #[cfg(not(any(feature = "_nrf51", feature = "nrf52833", feature = "nrf52840", feature = "_nrf5340")))] 216 #[cfg(not(any(
217 feature = "_nrf51",
218 feature = "nrf52833",
219 feature = "nrf52840",
220 feature = "_nrf5340",
221 feature = "_nrf54l"
222 )))]
139 let ports = &[pac::P0]; 223 let ports = &[pac::P0];
140 #[cfg(feature = "_nrf51")] 224 #[cfg(feature = "_nrf51")]
141 let ports = &[pac::GPIO]; 225 let ports = &[pac::GPIO];
@@ -204,19 +288,43 @@ impl InputChannel<'static> {
204 288
205impl<'d> Drop for InputChannel<'d> { 289impl<'d> Drop for InputChannel<'d> {
206 fn drop(&mut self) { 290 fn drop(&mut self) {
207 let g = regs(); 291 let g = self.ch.regs();
208 let num = self.ch.number(); 292 let num = self.ch.number();
209 g.config(num).write(|w| w.set_mode(Mode::DISABLED)); 293 g.config(num).write(|w| w.set_mode(Mode::DISABLED));
210 g.intenclr().write(|w| w.0 = 1 << num); 294 g.intenclr(INTNUM).write(|w| w.0 = 1 << num);
211 } 295 }
212} 296}
213 297
214impl<'d> InputChannel<'d> { 298impl<'d> InputChannel<'d> {
215 /// Create a new GPIOTE input channel driver. 299 /// Create a new GPIOTE input channel driver.
216 pub fn new(ch: Peri<'d, impl Channel>, pin: Input<'d>, polarity: InputChannelPolarity) -> Self { 300 #[cfg(feature = "_nrf54l")]
217 let g = regs(); 301 pub fn new<C: Channel, T: GpiotePin<Instance = C::Instance>>(
218 let num = ch.number(); 302 ch: Peri<'d, C>,
303 pin: Peri<'d, T>,
304 pull: Pull,
305 polarity: InputChannelPolarity,
306 ) -> Self {
307 let pin = Input::new(pin, pull);
308 let ch = ch.into();
309 Self::new_inner(ch, pin, polarity)
310 }
219 311
312 /// Create a new GPIOTE output channel driver.
313 #[cfg(not(feature = "_nrf54l"))]
314 pub fn new<C: Channel, T: GpioPin>(
315 ch: Peri<'d, C>,
316 pin: Peri<'d, T>,
317 pull: Pull,
318 polarity: InputChannelPolarity,
319 ) -> Self {
320 let pin = Input::new(pin, pull);
321 let ch = ch.into();
322 Self::new_inner(ch, pin, polarity)
323 }
324
325 fn new_inner(ch: Peri<'d, AnyChannel>, pin: Input<'d>, polarity: InputChannelPolarity) -> Self {
326 let g = ch.regs();
327 let num = ch.number();
220 g.config(num).write(|w| { 328 g.config(num).write(|w| {
221 w.set_mode(Mode::EVENT); 329 w.set_mode(Mode::EVENT);
222 match polarity { 330 match polarity {
@@ -225,30 +333,94 @@ impl<'d> InputChannel<'d> {
225 InputChannelPolarity::None => w.set_polarity(Polarity::NONE), 333 InputChannelPolarity::None => w.set_polarity(Polarity::NONE),
226 InputChannelPolarity::Toggle => w.set_polarity(Polarity::TOGGLE), 334 InputChannelPolarity::Toggle => w.set_polarity(Polarity::TOGGLE),
227 }; 335 };
228 #[cfg(any(feature = "nrf52833", feature = "nrf52840", feature = "_nrf5340"))] 336 #[cfg(any(feature = "nrf52833", feature = "nrf52840", feature = "_nrf5340",))]
229 w.set_port(match pin.pin.pin.port() { 337 w.set_port(match pin.pin.pin.port() {
230 crate::gpio::Port::Port0 => false, 338 crate::gpio::Port::Port0 => false,
231 crate::gpio::Port::Port1 => true, 339 crate::gpio::Port::Port1 => true,
232 }); 340 });
341 #[cfg(any(feature = "_nrf54l"))]
342 w.set_port(match pin.pin.pin.port() {
343 crate::gpio::Port::Port0 => 0,
344 crate::gpio::Port::Port1 => 1,
345 crate::gpio::Port::Port2 => 2,
346 });
233 w.set_psel(pin.pin.pin.pin()); 347 w.set_psel(pin.pin.pin.pin());
234 }); 348 });
235 349
236 g.events_in(num).write_value(0); 350 g.events_in(num).write_value(0);
237 351
238 InputChannel { ch: ch.into(), pin } 352 InputChannel { ch, pin }
239 } 353 }
240 354
241 /// Asynchronously wait for an event in this channel. 355 /// Asynchronously wait for an event in this channel.
242 pub async fn wait(&self) { 356 ///
243 let g = regs(); 357 /// It is possible to call this function and await the returned future later.
244 let num = self.ch.number(); 358 /// If an even occurs in the mean time, the future will immediately report ready.
359 pub fn wait(&mut self) -> impl Future<Output = ()> {
360 // NOTE: This is `-> impl Future` and not an `async fn` on purpose.
361 // Otherwise, events will only be detected starting at the first poll of the returned future.
362 Self::wait_internal(&mut self.ch)
363 }
364
365 /// Asynchronously wait for the pin to become high.
366 ///
367 /// The channel must be configured with [`InputChannelPolarity::LoToHi`] or [`InputChannelPolarity::Toggle`].
368 /// If the channel is not configured to detect rising edges, it is unspecified when the returned future completes.
369 ///
370 /// It is possible to call this function and await the returned future later.
371 /// If an even occurs in the mean time, the future will immediately report ready.
372 pub fn wait_for_high(&mut self) -> impl Future<Output = ()> {
373 // NOTE: This is `-> impl Future` and not an `async fn` on purpose.
374 // Otherwise, events will only be detected starting at the first poll of the returned future.
375
376 // Subscribe to the event before checking the pin level.
377 let wait = Self::wait_internal(&mut self.ch);
378 let pin = &self.pin;
379 async move {
380 if pin.is_high() {
381 return;
382 }
383 wait.await;
384 }
385 }
386
387 /// Asynchronously wait for the pin to become low.
388 ///
389 /// The channel must be configured with [`InputChannelPolarity::HiToLo`] or [`InputChannelPolarity::Toggle`].
390 /// If the channel is not configured to detect falling edges, it is unspecified when the returned future completes.
391 ///
392 /// It is possible to call this function and await the returned future later.
393 /// If an even occurs in the mean time, the future will immediately report ready.
394 pub fn wait_for_low(&mut self) -> impl Future<Output = ()> {
395 // NOTE: This is `-> impl Future` and not an `async fn` on purpose.
396 // Otherwise, events will only be detected starting at the first poll of the returned future.
397
398 // Subscribe to the event before checking the pin level.
399 let wait = Self::wait_internal(&mut self.ch);
400 let pin = &self.pin;
401 async move {
402 if pin.is_low() {
403 return;
404 }
405 wait.await;
406 }
407 }
408
409 /// Internal implementation for `wait()` and friends.
410 fn wait_internal(channel: &mut Peri<'_, AnyChannel>) -> impl Future<Output = ()> {
411 // NOTE: This is `-> impl Future` and not an `async fn` on purpose.
412 // Otherwise, events will only be detected starting at the first poll of the returned future.
413
414 let g = channel.regs();
415 let num = channel.number();
416 let waker = channel.waker();
245 417
246 // Enable interrupt 418 // Enable interrupt
247 g.events_in(num).write_value(0); 419 g.events_in(num).write_value(0);
248 g.intenset().write(|w| w.0 = 1 << num); 420 g.intenset(INTNUM).write(|w| w.0 = 1 << num);
249 421
250 poll_fn(|cx| { 422 poll_fn(move |cx| {
251 CHANNEL_WAKERS[num].register(cx.waker()); 423 CHANNEL_WAKERS[waker].register(cx.waker());
252 424
253 if g.events_in(num).read() != 0 { 425 if g.events_in(num).read() != 0 {
254 Poll::Ready(()) 426 Poll::Ready(())
@@ -256,12 +428,16 @@ impl<'d> InputChannel<'d> {
256 Poll::Pending 428 Poll::Pending
257 } 429 }
258 }) 430 })
259 .await; 431 }
432
433 /// Get the associated input pin.
434 pub fn pin(&self) -> &Input<'_> {
435 &self.pin
260 } 436 }
261 437
262 /// Returns the IN event, for use with PPI. 438 /// Returns the IN event, for use with PPI.
263 pub fn event_in(&self) -> Event<'d> { 439 pub fn event_in(&self) -> Event<'d> {
264 let g = regs(); 440 let g = self.ch.regs();
265 Event::from_reg(g.events_in(self.ch.number())) 441 Event::from_reg(g.events_in(self.ch.number()))
266 } 442 }
267} 443}
@@ -283,17 +459,44 @@ impl OutputChannel<'static> {
283 459
284impl<'d> Drop for OutputChannel<'d> { 460impl<'d> Drop for OutputChannel<'d> {
285 fn drop(&mut self) { 461 fn drop(&mut self) {
286 let g = regs(); 462 let g = self.ch.regs();
287 let num = self.ch.number(); 463 let num = self.ch.number();
288 g.config(num).write(|w| w.set_mode(Mode::DISABLED)); 464 g.config(num).write(|w| w.set_mode(Mode::DISABLED));
289 g.intenclr().write(|w| w.0 = 1 << num); 465 g.intenclr(INTNUM).write(|w| w.0 = 1 << num);
290 } 466 }
291} 467}
292 468
293impl<'d> OutputChannel<'d> { 469impl<'d> OutputChannel<'d> {
294 /// Create a new GPIOTE output channel driver. 470 /// Create a new GPIOTE output channel driver.
295 pub fn new(ch: Peri<'d, impl Channel>, pin: Output<'d>, polarity: OutputChannelPolarity) -> Self { 471 #[cfg(feature = "_nrf54l")]
296 let g = regs(); 472 pub fn new<C: Channel, T: GpiotePin<Instance = C::Instance>>(
473 ch: Peri<'d, C>,
474 pin: Peri<'d, T>,
475 initial_output: Level,
476 drive: OutputDrive,
477 polarity: OutputChannelPolarity,
478 ) -> Self {
479 let pin = Output::new(pin, initial_output, drive);
480 let ch = ch.into();
481 Self::new_inner(ch, pin, polarity)
482 }
483
484 /// Create a new GPIOTE output channel driver.
485 #[cfg(not(feature = "_nrf54l"))]
486 pub fn new<C: Channel, T: GpioPin>(
487 ch: Peri<'d, C>,
488 pin: Peri<'d, T>,
489 initial_output: Level,
490 drive: OutputDrive,
491 polarity: OutputChannelPolarity,
492 ) -> Self {
493 let pin = Output::new(pin, initial_output, drive);
494 let ch = ch.into();
495 Self::new_inner(ch, pin, polarity)
496 }
497
498 fn new_inner(ch: Peri<'d, AnyChannel>, pin: Output<'d>, polarity: OutputChannelPolarity) -> Self {
499 let g = ch.regs();
297 let num = ch.number(); 500 let num = ch.number();
298 501
299 g.config(num).write(|w| { 502 g.config(num).write(|w| {
@@ -312,52 +515,55 @@ impl<'d> OutputChannel<'d> {
312 crate::gpio::Port::Port0 => false, 515 crate::gpio::Port::Port0 => false,
313 crate::gpio::Port::Port1 => true, 516 crate::gpio::Port::Port1 => true,
314 }); 517 });
518 #[cfg(any(feature = "_nrf54l"))]
519 w.set_port(match pin.pin.pin.port() {
520 crate::gpio::Port::Port0 => 0,
521 crate::gpio::Port::Port1 => 1,
522 crate::gpio::Port::Port2 => 2,
523 });
315 w.set_psel(pin.pin.pin.pin()); 524 w.set_psel(pin.pin.pin.pin());
316 }); 525 });
317 526
318 OutputChannel { 527 OutputChannel { ch, _pin: pin }
319 ch: ch.into(),
320 _pin: pin,
321 }
322 } 528 }
323 529
324 /// Triggers the OUT task (does the action as configured with task_out_polarity, defaults to Toggle). 530 /// Triggers the OUT task (does the action as configured with task_out_polarity, defaults to Toggle).
325 pub fn out(&self) { 531 pub fn out(&self) {
326 let g = regs(); 532 let g = self.ch.regs();
327 g.tasks_out(self.ch.number()).write_value(1); 533 g.tasks_out(self.ch.number()).write_value(1);
328 } 534 }
329 535
330 /// Triggers the SET task (set associated pin high). 536 /// Triggers the SET task (set associated pin high).
331 #[cfg(not(feature = "_nrf51"))] 537 #[cfg(not(feature = "_nrf51"))]
332 pub fn set(&self) { 538 pub fn set(&self) {
333 let g = regs(); 539 let g = self.ch.regs();
334 g.tasks_set(self.ch.number()).write_value(1); 540 g.tasks_set(self.ch.number()).write_value(1);
335 } 541 }
336 542
337 /// Triggers the CLEAR task (set associated pin low). 543 /// Triggers the CLEAR task (set associated pin low).
338 #[cfg(not(feature = "_nrf51"))] 544 #[cfg(not(feature = "_nrf51"))]
339 pub fn clear(&self) { 545 pub fn clear(&self) {
340 let g = regs(); 546 let g = self.ch.regs();
341 g.tasks_clr(self.ch.number()).write_value(1); 547 g.tasks_clr(self.ch.number()).write_value(1);
342 } 548 }
343 549
344 /// Returns the OUT task, for use with PPI. 550 /// Returns the OUT task, for use with PPI.
345 pub fn task_out(&self) -> Task<'d> { 551 pub fn task_out(&self) -> Task<'d> {
346 let g = regs(); 552 let g = self.ch.regs();
347 Task::from_reg(g.tasks_out(self.ch.number())) 553 Task::from_reg(g.tasks_out(self.ch.number()))
348 } 554 }
349 555
350 /// Returns the CLR task, for use with PPI. 556 /// Returns the CLR task, for use with PPI.
351 #[cfg(not(feature = "_nrf51"))] 557 #[cfg(not(feature = "_nrf51"))]
352 pub fn task_clr(&self) -> Task<'d> { 558 pub fn task_clr(&self) -> Task<'d> {
353 let g = regs(); 559 let g = self.ch.regs();
354 Task::from_reg(g.tasks_clr(self.ch.number())) 560 Task::from_reg(g.tasks_clr(self.ch.number()))
355 } 561 }
356 562
357 /// Returns the SET task, for use with PPI. 563 /// Returns the SET task, for use with PPI.
358 #[cfg(not(feature = "_nrf51"))] 564 #[cfg(not(feature = "_nrf51"))]
359 pub fn task_set(&self) -> Task<'d> { 565 pub fn task_set(&self) -> Task<'d> {
360 let g = regs(); 566 let g = self.ch.regs();
361 Task::from_reg(g.tasks_set(self.ch.number())) 567 Task::from_reg(g.tasks_set(self.ch.number()))
362 } 568 }
363} 569}
@@ -459,31 +665,52 @@ impl<'d> Flex<'d> {
459 PortInputFuture::new(self.pin.reborrow()).await 665 PortInputFuture::new(self.pin.reborrow()).await
460 } 666 }
461} 667}
462
463// ======================= 668// =======================
669//
464 670
465trait SealedChannel {} 671trait SealedChannel {
672 fn waker(&self) -> usize;
673 fn regs(&self) -> pac::gpiote::Gpiote;
674}
466 675
467/// GPIOTE channel trait. 676/// GPIOTE channel trait.
468/// 677///
469/// Implemented by all GPIOTE channels. 678/// Implemented by all GPIOTE channels.
470#[allow(private_bounds)] 679#[allow(private_bounds)]
471pub trait Channel: PeripheralType + SealedChannel + Into<AnyChannel> + Sized + 'static { 680pub trait Channel: PeripheralType + SealedChannel + Into<AnyChannel> + Sized + 'static {
681 #[cfg(feature = "_nrf54l")]
682 /// GPIOTE instance this channel belongs to.
683 type Instance: GpioteInstance;
472 /// Get the channel number. 684 /// Get the channel number.
473 fn number(&self) -> usize; 685 fn number(&self) -> usize;
474} 686}
475 687
476/// Type-erased channel. 688struct AnyChannel {
477///
478/// Obtained by calling `Channel::into()`.
479///
480/// This allows using several channels in situations that might require
481/// them to be the same type, like putting them in an array.
482pub struct AnyChannel {
483 number: u8, 689 number: u8,
690 regs: pac::gpiote::Gpiote,
691 waker: u8,
484} 692}
693
485impl_peripheral!(AnyChannel); 694impl_peripheral!(AnyChannel);
486impl SealedChannel for AnyChannel {} 695
696impl SealedChannel for AnyChannel {
697 fn waker(&self) -> usize {
698 self.waker as usize
699 }
700
701 fn regs(&self) -> pac::gpiote::Gpiote {
702 self.regs
703 }
704}
705
706#[cfg(feature = "_nrf54l")]
707impl AnyChannel {
708 fn number(&self) -> usize {
709 self.number as usize
710 }
711}
712
713#[cfg(not(feature = "_nrf54l"))]
487impl Channel for AnyChannel { 714impl Channel for AnyChannel {
488 fn number(&self) -> usize { 715 fn number(&self) -> usize {
489 self.number as usize 716 self.number as usize
@@ -491,9 +718,19 @@ impl Channel for AnyChannel {
491} 718}
492 719
493macro_rules! impl_channel { 720macro_rules! impl_channel {
494 ($type:ident, $number:expr) => { 721 ($type:ident, $inst:ident, $number:expr, $waker:expr) => {
495 impl SealedChannel for peripherals::$type {} 722 impl SealedChannel for peripherals::$type {
723 fn waker(&self) -> usize {
724 $waker as usize
725 }
726
727 fn regs(&self) -> pac::gpiote::Gpiote {
728 pac::$inst
729 }
730 }
496 impl Channel for peripherals::$type { 731 impl Channel for peripherals::$type {
732 #[cfg(feature = "_nrf54l")]
733 type Instance = peripherals::$inst;
497 fn number(&self) -> usize { 734 fn number(&self) -> usize {
498 $number as usize 735 $number as usize
499 } 736 }
@@ -503,24 +740,95 @@ macro_rules! impl_channel {
503 fn from(val: peripherals::$type) -> Self { 740 fn from(val: peripherals::$type) -> Self {
504 Self { 741 Self {
505 number: val.number() as u8, 742 number: val.number() as u8,
743 waker: val.waker() as u8,
744 regs: val.regs(),
506 } 745 }
507 } 746 }
508 } 747 }
509 }; 748 };
510} 749}
511 750
512impl_channel!(GPIOTE_CH0, 0); 751cfg_if::cfg_if! {
513impl_channel!(GPIOTE_CH1, 1); 752 if #[cfg(feature = "_nrf54l")] {
514impl_channel!(GPIOTE_CH2, 2); 753 trait SealedGpioteInstance {}
515impl_channel!(GPIOTE_CH3, 3); 754 /// Represents a GPIOTE instance.
516#[cfg(not(feature = "_nrf51"))] 755 #[allow(private_bounds)]
517impl_channel!(GPIOTE_CH4, 4); 756 pub trait GpioteInstance: PeripheralType + SealedGpioteInstance + Sized + 'static {}
518#[cfg(not(feature = "_nrf51"))] 757
519impl_channel!(GPIOTE_CH5, 5); 758 macro_rules! impl_gpiote {
520#[cfg(not(feature = "_nrf51"))] 759 ($type:ident) => {
521impl_channel!(GPIOTE_CH6, 6); 760 impl SealedGpioteInstance for peripherals::$type {}
522#[cfg(not(feature = "_nrf51"))] 761 impl GpioteInstance for peripherals::$type {}
523impl_channel!(GPIOTE_CH7, 7); 762 };
763 }
764
765 pub(crate) trait SealedGpiotePin {}
766
767 /// Represents a GPIO pin that can be used with GPIOTE.
768 #[allow(private_bounds)]
769 pub trait GpiotePin: GpioPin + SealedGpiotePin {
770 /// The GPIOTE instance this pin belongs to.
771 type Instance: GpioteInstance;
772 }
773
774 macro_rules! impl_gpiote_pin {
775 ($type:ident, $inst:ident) => {
776 impl crate::gpiote::SealedGpiotePin for peripherals::$type {}
777 impl crate::gpiote::GpiotePin for peripherals::$type {
778 type Instance = peripherals::$inst;
779 }
780 };
781 }
782
783 impl_gpiote!(GPIOTE20);
784 impl_gpiote!(GPIOTE30);
785 impl_channel!(GPIOTE20_CH0, GPIOTE20, 0, 0);
786 impl_channel!(GPIOTE20_CH1, GPIOTE20, 1, 1);
787 impl_channel!(GPIOTE20_CH2, GPIOTE20, 2, 2);
788 impl_channel!(GPIOTE20_CH3, GPIOTE20, 3, 3);
789 impl_channel!(GPIOTE20_CH4, GPIOTE20, 4, 4);
790 impl_channel!(GPIOTE20_CH5, GPIOTE20, 5, 5);
791 impl_channel!(GPIOTE20_CH6, GPIOTE20, 6, 6);
792 impl_channel!(GPIOTE20_CH7, GPIOTE20, 7, 7);
793
794 impl_channel!(GPIOTE30_CH0, GPIOTE30, 0, 8);
795 impl_channel!(GPIOTE30_CH1, GPIOTE30, 1, 9);
796 impl_channel!(GPIOTE30_CH2, GPIOTE30, 2, 10);
797 impl_channel!(GPIOTE30_CH3, GPIOTE30, 3, 11);
798 } else if #[cfg(feature = "_nrf51")] {
799 impl_channel!(GPIOTE_CH0, GPIOTE, 0, 0);
800 impl_channel!(GPIOTE_CH1, GPIOTE, 1, 1);
801 impl_channel!(GPIOTE_CH2, GPIOTE, 2, 2);
802 impl_channel!(GPIOTE_CH3, GPIOTE, 3, 3);
803 } else if #[cfg(all(feature = "_s", any(feature = "_nrf91", feature = "_nrf5340")))] {
804 impl_channel!(GPIOTE_CH0, GPIOTE0, 0, 0);
805 impl_channel!(GPIOTE_CH1, GPIOTE0, 1, 1);
806 impl_channel!(GPIOTE_CH2, GPIOTE0, 2, 2);
807 impl_channel!(GPIOTE_CH3, GPIOTE0, 3, 3);
808 impl_channel!(GPIOTE_CH4, GPIOTE0, 4, 4);
809 impl_channel!(GPIOTE_CH5, GPIOTE0, 5, 5);
810 impl_channel!(GPIOTE_CH6, GPIOTE0, 6, 6);
811 impl_channel!(GPIOTE_CH7, GPIOTE0, 7, 7);
812 } else if #[cfg(all(feature = "_ns", any(feature = "_nrf91", feature = "_nrf5340")))] {
813 impl_channel!(GPIOTE_CH0, GPIOTE1, 0, 0);
814 impl_channel!(GPIOTE_CH1, GPIOTE1, 1, 1);
815 impl_channel!(GPIOTE_CH2, GPIOTE1, 2, 2);
816 impl_channel!(GPIOTE_CH3, GPIOTE1, 3, 3);
817 impl_channel!(GPIOTE_CH4, GPIOTE1, 4, 4);
818 impl_channel!(GPIOTE_CH5, GPIOTE1, 5, 5);
819 impl_channel!(GPIOTE_CH6, GPIOTE1, 6, 6);
820 impl_channel!(GPIOTE_CH7, GPIOTE1, 7, 7);
821 } else {
822 impl_channel!(GPIOTE_CH0, GPIOTE, 0, 0);
823 impl_channel!(GPIOTE_CH1, GPIOTE, 1, 1);
824 impl_channel!(GPIOTE_CH2, GPIOTE, 2, 2);
825 impl_channel!(GPIOTE_CH3, GPIOTE, 3, 3);
826 impl_channel!(GPIOTE_CH4, GPIOTE, 4, 4);
827 impl_channel!(GPIOTE_CH5, GPIOTE, 5, 5);
828 impl_channel!(GPIOTE_CH6, GPIOTE, 6, 6);
829 impl_channel!(GPIOTE_CH7, GPIOTE, 7, 7);
830 }
831}
524 832
525// ==================== 833// ====================
526 834