aboutsummaryrefslogtreecommitdiff
path: root/embassy-nrf/src
diff options
context:
space:
mode:
authorUlf Lilleengen <[email protected]>2025-10-28 13:52:53 +0000
committerGitHub <[email protected]>2025-10-28 13:52:53 +0000
commitafe9defe31c79444d3bf8eca5e2f0d4161fd96f9 (patch)
treeac3273028c11098689a5d0f637d905974b35aa09 /embassy-nrf/src
parent41ff72bbce343c1e3c5efa2939e08a73b9122552 (diff)
parent83deef3672c651ac86e7ad497eccc52119b3a27f (diff)
Merge pull request #4793 from embassy-rs/nrf54-new-pac
feat: improve nrf54 support using new nrf-pac
Diffstat (limited to 'embassy-nrf/src')
-rw-r--r--embassy-nrf/src/buffered_uarte/mod.rs14
-rw-r--r--embassy-nrf/src/buffered_uarte/v1.rs (renamed from embassy-nrf/src/buffered_uarte.rs)58
-rw-r--r--embassy-nrf/src/buffered_uarte/v2.rs687
-rw-r--r--embassy-nrf/src/chips/nrf51.rs5
-rw-r--r--embassy-nrf/src/chips/nrf52805.rs51
-rw-r--r--embassy-nrf/src/chips/nrf52810.rs71
-rw-r--r--embassy-nrf/src/chips/nrf52811.rs71
-rw-r--r--embassy-nrf/src/chips/nrf52820.rs71
-rw-r--r--embassy-nrf/src/chips/nrf52832.rs71
-rw-r--r--embassy-nrf/src/chips/nrf52833.rs71
-rw-r--r--embassy-nrf/src/chips/nrf52840.rs71
-rw-r--r--embassy-nrf/src/chips/nrf5340_app.rs71
-rw-r--r--embassy-nrf/src/chips/nrf5340_net.rs71
-rw-r--r--embassy-nrf/src/chips/nrf54l15_app.rs229
-rw-r--r--embassy-nrf/src/chips/nrf9120.rs39
-rw-r--r--embassy-nrf/src/chips/nrf9160.rs39
-rw-r--r--embassy-nrf/src/gpio.rs2
-rw-r--r--embassy-nrf/src/gpiote.rs431
-rw-r--r--embassy-nrf/src/lib.rs12
-rw-r--r--embassy-nrf/src/ppi/dppi.rs11
-rw-r--r--embassy-nrf/src/ppi/mod.rs119
-rw-r--r--embassy-nrf/src/pwm.rs59
-rw-r--r--embassy-nrf/src/saadc.rs247
-rw-r--r--embassy-nrf/src/spim.rs163
-rw-r--r--embassy-nrf/src/spis.rs16
-rw-r--r--embassy-nrf/src/twim.rs44
-rw-r--r--embassy-nrf/src/twis.rs44
-rw-r--r--embassy-nrf/src/uarte.rs162
28 files changed, 2374 insertions, 626 deletions
diff --git a/embassy-nrf/src/buffered_uarte/mod.rs b/embassy-nrf/src/buffered_uarte/mod.rs
new file mode 100644
index 000000000..75d84baac
--- /dev/null
+++ b/embassy-nrf/src/buffered_uarte/mod.rs
@@ -0,0 +1,14 @@
1//! Async buffered UART driver.
2//!
3//! Note that discarding a future from a read or write operation may lead to losing
4//! data. For example, when using `futures_util::future::select` and completion occurs
5//! on the "other" future, you should capture the incomplete future and continue to use
6//! it for the next read or write. This pattern is a consideration for all IO, and not
7//! just serial communications.
8//!
9//! Please also see [crate::uarte] to understand when [BufferedUarte] should be used.
10#[cfg_attr(not(feature = "_nrf54l"), path = "v1.rs")]
11#[cfg_attr(feature = "_nrf54l", path = "v2.rs")]
12mod _version;
13
14pub use _version::*;
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte/v1.rs
index b1eb5c81a..07de22717 100644
--- a/embassy-nrf/src/buffered_uarte.rs
+++ b/embassy-nrf/src/buffered_uarte/v1.rs
@@ -102,25 +102,25 @@ impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for Interrupt
102 ss.rx_waker.wake(); 102 ss.rx_waker.wake();
103 } 103 }
104 104
105 if r.events_endrx().read() != 0 { 105 if r.events_dma().rx().end().read() != 0 {
106 //trace!(" irq_rx: endrx"); 106 //trace!(" irq_rx: endrx");
107 r.events_endrx().write_value(0); 107 r.events_dma().rx().end().write_value(0);
108 108
109 let val = s.rx_ended_count.load(Ordering::Relaxed); 109 let val = s.rx_ended_count.load(Ordering::Relaxed);
110 s.rx_ended_count.store(val.wrapping_add(1), Ordering::Relaxed); 110 s.rx_ended_count.store(val.wrapping_add(1), Ordering::Relaxed);
111 } 111 }
112 112
113 if r.events_rxstarted().read() != 0 || !s.rx_started.load(Ordering::Relaxed) { 113 if r.events_dma().rx().ready().read() != 0 || !s.rx_started.load(Ordering::Relaxed) {
114 //trace!(" irq_rx: rxstarted"); 114 //trace!(" irq_rx: rxstarted");
115 let (ptr, len) = rx.push_buf(); 115 let (ptr, len) = rx.push_buf();
116 if len >= half_len { 116 if len >= half_len {
117 r.events_rxstarted().write_value(0); 117 r.events_dma().rx().ready().write_value(0);
118 118
119 //trace!(" irq_rx: starting second {:?}", half_len); 119 //trace!(" irq_rx: starting second {:?}", half_len);
120 120
121 // Set up the DMA read 121 // Set up the DMA read
122 r.rxd().ptr().write_value(ptr as u32); 122 r.dma().rx().ptr().write_value(ptr as u32);
123 r.rxd().maxcnt().write(|w| w.set_maxcnt(half_len as _)); 123 r.dma().rx().maxcnt().write(|w| w.set_maxcnt(half_len as _));
124 124
125 let chn = s.rx_ppi_ch.load(Ordering::Relaxed); 125 let chn = s.rx_ppi_ch.load(Ordering::Relaxed);
126 126
@@ -133,9 +133,9 @@ impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for Interrupt
133 // and manually start. 133 // and manually start.
134 134
135 // check again in case endrx has happened between the last check and now. 135 // check again in case endrx has happened between the last check and now.
136 if r.events_endrx().read() != 0 { 136 if r.events_dma().rx().end().read() != 0 {
137 //trace!(" irq_rx: endrx"); 137 //trace!(" irq_rx: endrx");
138 r.events_endrx().write_value(0); 138 r.events_dma().rx().end().write_value(0);
139 139
140 let val = s.rx_ended_count.load(Ordering::Relaxed); 140 let val = s.rx_ended_count.load(Ordering::Relaxed);
141 s.rx_ended_count.store(val.wrapping_add(1), Ordering::Relaxed); 141 s.rx_ended_count.store(val.wrapping_add(1), Ordering::Relaxed);
@@ -161,7 +161,7 @@ impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for Interrupt
161 ppi::regs().chenclr().write(|w| w.set_ch(chn as _, true)); 161 ppi::regs().chenclr().write(|w| w.set_ch(chn as _, true));
162 162
163 // manually start 163 // manually start
164 r.tasks_startrx().write_value(1); 164 r.tasks_dma().rx().start().write_value(1);
165 } 165 }
166 166
167 rx.push_done(half_len); 167 rx.push_done(half_len);
@@ -170,7 +170,7 @@ impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for Interrupt
170 s.rx_started.store(true, Ordering::Relaxed); 170 s.rx_started.store(true, Ordering::Relaxed);
171 } else { 171 } else {
172 //trace!(" irq_rx: rxstarted no buf"); 172 //trace!(" irq_rx: rxstarted no buf");
173 r.intenclr().write(|w| w.set_rxstarted(true)); 173 r.intenclr().write(|w| w.set_dmarxready(true));
174 } 174 }
175 } 175 }
176 } 176 }
@@ -179,8 +179,8 @@ impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for Interrupt
179 179
180 if let Some(mut tx) = unsafe { s.tx_buf.try_reader() } { 180 if let Some(mut tx) = unsafe { s.tx_buf.try_reader() } {
181 // TX end 181 // TX end
182 if r.events_endtx().read() != 0 { 182 if r.events_dma().tx().end().read() != 0 {
183 r.events_endtx().write_value(0); 183 r.events_dma().tx().end().write_value(0);
184 184
185 let n = s.tx_count.load(Ordering::Relaxed); 185 let n = s.tx_count.load(Ordering::Relaxed);
186 //trace!(" irq_tx: endtx {:?}", n); 186 //trace!(" irq_tx: endtx {:?}", n);
@@ -198,11 +198,11 @@ impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for Interrupt
198 s.tx_count.store(len, Ordering::Relaxed); 198 s.tx_count.store(len, Ordering::Relaxed);
199 199
200 // Set up the DMA write 200 // Set up the DMA write
201 r.txd().ptr().write_value(ptr as u32); 201 r.dma().tx().ptr().write_value(ptr as u32);
202 r.txd().maxcnt().write(|w| w.set_maxcnt(len as _)); 202 r.dma().tx().maxcnt().write(|w| w.set_maxcnt(len as _));
203 203
204 // Start UARTE Transmit transaction 204 // Start UARTE Transmit transaction
205 r.tasks_starttx().write_value(1); 205 r.tasks_dma().tx().start().write_value(1);
206 } 206 }
207 } 207 }
208 } 208 }
@@ -456,11 +456,11 @@ impl<'d> BufferedUarteTx<'d> {
456 let len = tx_buffer.len(); 456 let len = tx_buffer.len();
457 unsafe { buffered_state.tx_buf.init(tx_buffer.as_mut_ptr(), len) }; 457 unsafe { buffered_state.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
458 458
459 r.events_txstarted().write_value(0); 459 r.events_dma().tx().ready().write_value(0);
460 460
461 // Enable interrupts 461 // Enable interrupts
462 r.intenset().write(|w| { 462 r.intenset().write(|w| {
463 w.set_endtx(true); 463 w.set_dmatxend(true);
464 }); 464 });
465 465
466 Self { 466 Self {
@@ -551,11 +551,11 @@ impl<'a> Drop for BufferedUarteTx<'a> {
551 551
552 r.intenclr().write(|w| { 552 r.intenclr().write(|w| {
553 w.set_txdrdy(true); 553 w.set_txdrdy(true);
554 w.set_txstarted(true); 554 w.set_dmatxready(true);
555 w.set_txstopped(true); 555 w.set_txstopped(true);
556 }); 556 });
557 r.events_txstopped().write_value(0); 557 r.events_txstopped().write_value(0);
558 r.tasks_stoptx().write_value(1); 558 r.tasks_dma().tx().stop().write_value(1);
559 while r.events_txstopped().read() == 0 {} 559 while r.events_txstopped().read() == 0 {}
560 560
561 let s = self.buffered_state; 561 let s = self.buffered_state;
@@ -701,16 +701,16 @@ impl<'d> BufferedUarteRx<'d> {
701 let errors = r.errorsrc().read(); 701 let errors = r.errorsrc().read();
702 r.errorsrc().write_value(errors); 702 r.errorsrc().write_value(errors);
703 703
704 r.events_rxstarted().write_value(0); 704 r.events_dma().rx().ready().write_value(0);
705 r.events_error().write_value(0); 705 r.events_error().write_value(0);
706 r.events_endrx().write_value(0); 706 r.events_dma().rx().end().write_value(0);
707 707
708 // Enable interrupts 708 // Enable interrupts
709 r.intenset().write(|w| { 709 r.intenset().write(|w| {
710 w.set_endtx(true); 710 w.set_dmatxend(true);
711 w.set_rxstarted(true); 711 w.set_dmarxready(true);
712 w.set_error(true); 712 w.set_error(true);
713 w.set_endrx(true); 713 w.set_dmarxend(true);
714 }); 714 });
715 715
716 // Configure byte counter. 716 // Configure byte counter.
@@ -729,8 +729,8 @@ impl<'d> BufferedUarteRx<'d> {
729 let mut ppi_group = PpiGroup::new(ppi_group); 729 let mut ppi_group = PpiGroup::new(ppi_group);
730 let mut ppi_ch2 = Ppi::new_one_to_two( 730 let mut ppi_ch2 = Ppi::new_one_to_two(
731 ppi_ch2, 731 ppi_ch2,
732 Event::from_reg(r.events_endrx()), 732 Event::from_reg(r.events_dma().rx().end()),
733 Task::from_reg(r.tasks_startrx()), 733 Task::from_reg(r.tasks_dma().rx().start()),
734 ppi_group.task_disable_all(), 734 ppi_group.task_disable_all(),
735 ); 735 );
736 ppi_ch2.disable(); 736 ppi_ch2.disable();
@@ -823,7 +823,7 @@ impl<'d> BufferedUarteRx<'d> {
823 let s = self.buffered_state; 823 let s = self.buffered_state;
824 let mut rx = unsafe { s.rx_buf.reader() }; 824 let mut rx = unsafe { s.rx_buf.reader() };
825 rx.pop_done(amt); 825 rx.pop_done(amt);
826 self.r.intenset().write(|w| w.set_rxstarted(true)); 826 self.r.intenset().write(|w| w.set_dmarxready(true));
827 } 827 }
828 828
829 /// we are ready to read if there is data in the buffer 829 /// we are ready to read if there is data in the buffer
@@ -846,11 +846,11 @@ impl<'a> Drop for BufferedUarteRx<'a> {
846 846
847 r.intenclr().write(|w| { 847 r.intenclr().write(|w| {
848 w.set_rxdrdy(true); 848 w.set_rxdrdy(true);
849 w.set_rxstarted(true); 849 w.set_dmarxready(true);
850 w.set_rxto(true); 850 w.set_rxto(true);
851 }); 851 });
852 r.events_rxto().write_value(0); 852 r.events_rxto().write_value(0);
853 r.tasks_stoprx().write_value(1); 853 r.tasks_dma().rx().stop().write_value(1);
854 while r.events_rxto().read() == 0 {} 854 while r.events_rxto().read() == 0 {}
855 855
856 let s = self.buffered_state; 856 let s = self.buffered_state;
diff --git a/embassy-nrf/src/buffered_uarte/v2.rs b/embassy-nrf/src/buffered_uarte/v2.rs
new file mode 100644
index 000000000..d0d2d97d1
--- /dev/null
+++ b/embassy-nrf/src/buffered_uarte/v2.rs
@@ -0,0 +1,687 @@
1//! Async buffered UART driver.
2//!
3//! Note that discarding a future from a read or write operation may lead to losing
4//! data. For example, when using `futures_util::future::select` and completion occurs
5//! on the "other" future, you should capture the incomplete future and continue to use
6//! it for the next read or write. This pattern is a consideration for all IO, and not
7//! just serial communications.
8//!
9//! Please also see [crate::uarte] to understand when [BufferedUarte] should be used.
10//!
11//! The code is based on the generic buffered_uarte implementation but uses the nrf54l
12//! frame timeout event to correctly determine the size of transferred data.
13//! Counting of rxrdy events, used in the generic implementation, cannot be applied
14//! to nrf54l chips, as they buffer up to 4 bytes in a single DMA transaction.
15//! The only reliable way to find the number of bytes received is to stop the transfer,
16//! wait for the DMA stopped event, and read the value in the rx.dma.amount register.
17//! This also flushes all in-flight data to RAM.
18
19use core::cmp::min;
20use core::future::{Future, poll_fn};
21use core::marker::PhantomData;
22use core::slice;
23use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering, compiler_fence};
24use core::task::Poll;
25
26use embassy_hal_internal::Peri;
27use embassy_hal_internal::atomic_ring_buffer::RingBuffer;
28use pac::uarte::vals;
29// Re-export SVD variants to allow user to directly set values
30pub use pac::uarte::vals::{Baudrate, ConfigParity as Parity};
31
32use crate::gpio::{AnyPin, Pin as GpioPin};
33use crate::interrupt::typelevel::Interrupt;
34use crate::uarte::{Config, Instance as UarteInstance, configure, configure_rx_pins, configure_tx_pins, drop_tx_rx};
35use crate::{EASY_DMA_SIZE, interrupt, pac};
36
37pub(crate) struct State {
38 tx_buf: RingBuffer,
39 tx_count: AtomicUsize,
40
41 rx_buf: RingBuffer,
42 rx_started: AtomicBool,
43}
44
45/// UART error.
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47#[cfg_attr(feature = "defmt", derive(defmt::Format))]
48#[non_exhaustive]
49pub enum Error {
50 // No errors for now
51}
52
53impl State {
54 pub(crate) const fn new() -> Self {
55 Self {
56 tx_buf: RingBuffer::new(),
57 tx_count: AtomicUsize::new(0),
58
59 rx_buf: RingBuffer::new(),
60 rx_started: AtomicBool::new(false),
61 }
62 }
63}
64
65/// Interrupt handler.
66pub struct InterruptHandler<U: UarteInstance> {
67 _phantom: PhantomData<U>,
68}
69
70impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for InterruptHandler<U> {
71 unsafe fn on_interrupt() {
72 info!("irq: start");
73 let r = U::regs();
74 let ss = U::state();
75 let s = U::buffered_state();
76
77 if let Some(mut rx) = unsafe { s.rx_buf.try_writer() } {
78 let buf_len = s.rx_buf.len();
79 let half_len = buf_len / 2;
80
81 if r.events_error().read() != 0 {
82 r.events_error().write_value(0);
83 let errs = r.errorsrc().read();
84 r.errorsrc().write_value(errs);
85
86 if errs.overrun() {
87 panic!("BufferedUarte UART overrun");
88 }
89 }
90
91 let first_run = !s.rx_started.swap(true, Ordering::Relaxed);
92 if r.events_dma().rx().end().read() != 0 || first_run {
93 //trace!(" irq_rx: endrx");
94 r.events_dma().rx().end().write_value(0);
95
96 if !first_run {
97 // Received some bytes, wake task.
98 let rxed = r.dma().rx().amount().read().amount() as usize;
99 rx.push_done(rxed);
100 ss.rx_waker.wake();
101 }
102
103 let (ptr, len) = rx.push_buf();
104 if len == 0 {
105 panic!("BufferedUarte buffer overrun");
106 }
107
108 let len = if len > half_len { half_len } else { len };
109
110 // Set up the DMA read
111 r.dma().rx().ptr().write_value(ptr as u32);
112 r.dma().rx().maxcnt().write(|w| w.set_maxcnt(len as _));
113
114 // manually start
115 r.tasks_dma().rx().start().write_value(1);
116 }
117 }
118
119 // =============================
120
121 if let Some(mut tx) = unsafe { s.tx_buf.try_reader() } {
122 // TX end
123 if r.events_dma().tx().end().read() != 0 {
124 r.events_dma().tx().end().write_value(0);
125
126 let n = s.tx_count.load(Ordering::Relaxed);
127 //trace!(" irq_tx: endtx {:?}", n);
128 tx.pop_done(n);
129 ss.tx_waker.wake();
130 s.tx_count.store(0, Ordering::Relaxed);
131 }
132
133 // If not TXing, start.
134 if s.tx_count.load(Ordering::Relaxed) == 0 {
135 let (ptr, len) = tx.pop_buf();
136 let len = len.min(EASY_DMA_SIZE);
137 if len != 0 {
138 //trace!(" irq_tx: starting {:?}", len);
139 s.tx_count.store(len, Ordering::Relaxed);
140
141 // Set up the DMA write
142 r.dma().tx().ptr().write_value(ptr as u32);
143 r.dma().tx().maxcnt().write(|w| w.set_maxcnt(len as _));
144
145 // Start UARTE Transmit transaction
146 r.tasks_dma().tx().start().write_value(1);
147 }
148 }
149 }
150
151 //trace!("irq: end");
152 }
153}
154
155/// Buffered UARTE driver.
156pub struct BufferedUarte<'d, U: UarteInstance> {
157 tx: BufferedUarteTx<'d, U>,
158 rx: BufferedUarteRx<'d, U>,
159}
160
161impl<'d, U: UarteInstance> Unpin for BufferedUarte<'d, U> {}
162
163impl<'d, U: UarteInstance> BufferedUarte<'d, U> {
164 /// Create a new BufferedUarte without hardware flow control.
165 #[allow(clippy::too_many_arguments)]
166 pub fn new(
167 uarte: Peri<'d, U>,
168 rxd: Peri<'d, impl GpioPin>,
169 txd: Peri<'d, impl GpioPin>,
170 _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
171 config: Config,
172 rx_buffer: &'d mut [u8],
173 tx_buffer: &'d mut [u8],
174 ) -> Self {
175 Self::new_inner(uarte, rxd.into(), txd.into(), None, None, config, rx_buffer, tx_buffer)
176 }
177
178 /// Create a new BufferedUarte with hardware flow control (RTS/CTS)
179 #[allow(clippy::too_many_arguments)]
180 pub fn new_with_rtscts(
181 uarte: Peri<'d, U>,
182 rxd: Peri<'d, impl GpioPin>,
183 txd: Peri<'d, impl GpioPin>,
184 cts: Peri<'d, impl GpioPin>,
185 rts: Peri<'d, impl GpioPin>,
186 _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
187 config: Config,
188 rx_buffer: &'d mut [u8],
189 tx_buffer: &'d mut [u8],
190 ) -> Self {
191 Self::new_inner(
192 uarte,
193 rxd.into(),
194 txd.into(),
195 Some(cts.into()),
196 Some(rts.into()),
197 config,
198 rx_buffer,
199 tx_buffer,
200 )
201 }
202
203 #[allow(clippy::too_many_arguments)]
204 fn new_inner(
205 peri: Peri<'d, U>,
206 rxd: Peri<'d, AnyPin>,
207 txd: Peri<'d, AnyPin>,
208 cts: Option<Peri<'d, AnyPin>>,
209 rts: Option<Peri<'d, AnyPin>>,
210 config: Config,
211 rx_buffer: &'d mut [u8],
212 tx_buffer: &'d mut [u8],
213 ) -> Self {
214 configure(U::regs(), config, cts.is_some());
215
216 let tx = BufferedUarteTx::new_innerer(unsafe { peri.clone_unchecked() }, txd, cts, tx_buffer);
217 let rx = BufferedUarteRx::new_innerer(peri, rxd, rts, rx_buffer);
218
219 U::regs().enable().write(|w| w.set_enable(vals::Enable::ENABLED));
220 U::Interrupt::pend();
221 unsafe { U::Interrupt::enable() };
222
223 U::state().tx_rx_refcount.store(2, Ordering::Relaxed);
224
225 Self { tx, rx }
226 }
227
228 /// Adjust the baud rate to the provided value.
229 pub fn set_baudrate(&mut self, baudrate: Baudrate) {
230 let r = U::regs();
231 r.baudrate().write(|w| w.set_baudrate(baudrate));
232 }
233
234 /// Split the UART in reader and writer parts.
235 ///
236 /// This allows reading and writing concurrently from independent tasks.
237 pub fn split(self) -> (BufferedUarteRx<'d, U>, BufferedUarteTx<'d, U>) {
238 (self.rx, self.tx)
239 }
240
241 /// Split the UART in reader and writer parts, by reference.
242 ///
243 /// The returned halves borrow from `self`, so you can drop them and go back to using
244 /// the "un-split" `self`. This allows temporarily splitting the UART.
245 pub fn split_by_ref(&mut self) -> (&mut BufferedUarteRx<'d, U>, &mut BufferedUarteTx<'d, U>) {
246 (&mut self.rx, &mut self.tx)
247 }
248
249 /// Pull some bytes from this source into the specified buffer, returning how many bytes were read.
250 pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
251 self.rx.read(buf).await
252 }
253
254 /// Return the contents of the internal buffer, filling it with more data from the inner reader if it is empty.
255 pub async fn fill_buf(&mut self) -> Result<&[u8], Error> {
256 self.rx.fill_buf().await
257 }
258
259 /// Tell this buffer that `amt` bytes have been consumed from the buffer, so they should no longer be returned in calls to `fill_buf`.
260 pub fn consume(&mut self, amt: usize) {
261 self.rx.consume(amt)
262 }
263
264 /// Write a buffer into this writer, returning how many bytes were written.
265 pub async fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
266 self.tx.write(buf).await
267 }
268
269 /// Try writing a buffer without waiting, returning how many bytes were written.
270 pub fn try_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
271 self.tx.try_write(buf)
272 }
273
274 /// Flush this output stream, ensuring that all intermediately buffered contents reach their destination.
275 pub async fn flush(&mut self) -> Result<(), Error> {
276 self.tx.flush().await
277 }
278}
279
280/// Reader part of the buffered UARTE driver.
281pub struct BufferedUarteTx<'d, U: UarteInstance> {
282 _peri: Peri<'d, U>,
283}
284
285impl<'d, U: UarteInstance> BufferedUarteTx<'d, U> {
286 /// Create a new BufferedUarteTx without hardware flow control.
287 pub fn new(
288 uarte: Peri<'d, U>,
289 txd: Peri<'d, impl GpioPin>,
290 _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
291 config: Config,
292 tx_buffer: &'d mut [u8],
293 ) -> Self {
294 Self::new_inner(uarte, txd.into(), None, config, tx_buffer)
295 }
296
297 /// Create a new BufferedUarte with hardware flow control (RTS/CTS)
298 pub fn new_with_cts(
299 uarte: Peri<'d, U>,
300 txd: Peri<'d, impl GpioPin>,
301 cts: Peri<'d, impl GpioPin>,
302 _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
303 config: Config,
304 tx_buffer: &'d mut [u8],
305 ) -> Self {
306 Self::new_inner(uarte, txd.into(), Some(cts.into()), config, tx_buffer)
307 }
308
309 fn new_inner(
310 peri: Peri<'d, U>,
311 txd: Peri<'d, AnyPin>,
312 cts: Option<Peri<'d, AnyPin>>,
313 config: Config,
314 tx_buffer: &'d mut [u8],
315 ) -> Self {
316 configure(U::regs(), config, cts.is_some());
317
318 let this = Self::new_innerer(peri, txd, cts, tx_buffer);
319
320 U::regs().enable().write(|w| w.set_enable(vals::Enable::ENABLED));
321 U::Interrupt::pend();
322 unsafe { U::Interrupt::enable() };
323
324 U::state().tx_rx_refcount.store(1, Ordering::Relaxed);
325
326 this
327 }
328
329 fn new_innerer(
330 peri: Peri<'d, U>,
331 txd: Peri<'d, AnyPin>,
332 cts: Option<Peri<'d, AnyPin>>,
333 tx_buffer: &'d mut [u8],
334 ) -> Self {
335 let r = U::regs();
336
337 configure_tx_pins(r, txd, cts);
338
339 // Initialize state
340 let s = U::buffered_state();
341 s.tx_count.store(0, Ordering::Relaxed);
342 let len = tx_buffer.len();
343 unsafe { s.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
344
345 r.events_dma().tx().ready().write_value(0);
346
347 // Enable interrupts
348 r.intenset().write(|w| {
349 w.set_dmatxend(true);
350 });
351
352 Self { _peri: peri }
353 }
354
355 /// Write a buffer into this writer, returning how many bytes were written.
356 pub fn write<'a>(&'a mut self, buf: &'a [u8]) -> impl Future<Output = Result<usize, Error>> + 'a {
357 poll_fn(move |cx| {
358 //trace!("poll_write: {:?}", buf.len());
359 let ss = U::state();
360 let s = U::buffered_state();
361 let mut tx = unsafe { s.tx_buf.writer() };
362
363 let tx_buf = tx.push_slice();
364 if tx_buf.is_empty() {
365 //trace!("poll_write: pending");
366 ss.tx_waker.register(cx.waker());
367 return Poll::Pending;
368 }
369
370 let n = min(tx_buf.len(), buf.len());
371 tx_buf[..n].copy_from_slice(&buf[..n]);
372 tx.push_done(n);
373
374 //trace!("poll_write: queued {:?}", n);
375
376 compiler_fence(Ordering::SeqCst);
377 U::Interrupt::pend();
378
379 Poll::Ready(Ok(n))
380 })
381 }
382
383 /// Try writing a buffer without waiting, returning how many bytes were written.
384 pub fn try_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
385 //trace!("poll_write: {:?}", buf.len());
386 let s = U::buffered_state();
387 let mut tx = unsafe { s.tx_buf.writer() };
388
389 let tx_buf = tx.push_slice();
390 if tx_buf.is_empty() {
391 return Ok(0);
392 }
393
394 let n = min(tx_buf.len(), buf.len());
395 tx_buf[..n].copy_from_slice(&buf[..n]);
396 tx.push_done(n);
397
398 //trace!("poll_write: queued {:?}", n);
399
400 compiler_fence(Ordering::SeqCst);
401 U::Interrupt::pend();
402
403 Ok(n)
404 }
405
406 /// Flush this output stream, ensuring that all intermediately buffered contents reach their destination.
407 pub fn flush(&mut self) -> impl Future<Output = Result<(), Error>> + '_ {
408 poll_fn(move |cx| {
409 //trace!("poll_flush");
410 let ss = U::state();
411 let s = U::buffered_state();
412 if !s.tx_buf.is_empty() {
413 //trace!("poll_flush: pending");
414 ss.tx_waker.register(cx.waker());
415 return Poll::Pending;
416 }
417
418 Poll::Ready(Ok(()))
419 })
420 }
421}
422
423impl<'a, U: UarteInstance> Drop for BufferedUarteTx<'a, U> {
424 fn drop(&mut self) {
425 let r = U::regs();
426
427 r.intenclr().write(|w| {
428 w.set_txdrdy(true);
429 w.set_dmatxready(true);
430 w.set_txstopped(true);
431 });
432 r.events_txstopped().write_value(0);
433 r.tasks_dma().tx().stop().write_value(1);
434 while r.events_txstopped().read() == 0 {}
435
436 let s = U::buffered_state();
437 unsafe { s.tx_buf.deinit() }
438
439 let s = U::state();
440 drop_tx_rx(r, s);
441 }
442}
443
444/// Reader part of the buffered UARTE driver.
445pub struct BufferedUarteRx<'d, U: UarteInstance> {
446 _peri: Peri<'d, U>,
447}
448
449impl<'d, U: UarteInstance> BufferedUarteRx<'d, U> {
450 /// Create a new BufferedUarte without hardware flow control.
451 #[allow(clippy::too_many_arguments)]
452 pub fn new(
453 uarte: Peri<'d, U>,
454 _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
455 rxd: Peri<'d, impl GpioPin>,
456 config: Config,
457 rx_buffer: &'d mut [u8],
458 ) -> Self {
459 Self::new_inner(uarte, rxd.into(), None, config, rx_buffer)
460 }
461
462 /// Create a new BufferedUarte with hardware flow control (RTS/CTS)
463 #[allow(clippy::too_many_arguments)]
464 pub fn new_with_rts(
465 uarte: Peri<'d, U>,
466 rxd: Peri<'d, impl GpioPin>,
467 rts: Peri<'d, impl GpioPin>,
468 _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
469 config: Config,
470 rx_buffer: &'d mut [u8],
471 ) -> Self {
472 Self::new_inner(uarte, rxd.into(), Some(rts.into()), config, rx_buffer)
473 }
474
475 #[allow(clippy::too_many_arguments)]
476 fn new_inner(
477 peri: Peri<'d, U>,
478 rxd: Peri<'d, AnyPin>,
479 rts: Option<Peri<'d, AnyPin>>,
480 config: Config,
481 rx_buffer: &'d mut [u8],
482 ) -> Self {
483 configure(U::regs(), config, rts.is_some());
484
485 let this = Self::new_innerer(peri, rxd, rts, rx_buffer);
486
487 U::regs().enable().write(|w| w.set_enable(vals::Enable::ENABLED));
488 U::Interrupt::pend();
489 unsafe { U::Interrupt::enable() };
490
491 U::state().tx_rx_refcount.store(1, Ordering::Relaxed);
492
493 this
494 }
495
496 #[allow(clippy::too_many_arguments)]
497 fn new_innerer(
498 peri: Peri<'d, U>,
499 rxd: Peri<'d, AnyPin>,
500 rts: Option<Peri<'d, AnyPin>>,
501 rx_buffer: &'d mut [u8],
502 ) -> Self {
503 let r = U::regs();
504
505 configure_rx_pins(r, rxd, rts);
506
507 // Initialize state
508 let s = U::buffered_state();
509 let rx_len = rx_buffer.len().min(EASY_DMA_SIZE * 2);
510 let rx_ptr = rx_buffer.as_mut_ptr();
511 unsafe { s.rx_buf.init(rx_ptr, rx_len) };
512
513 // clear errors
514 let errors = r.errorsrc().read();
515 r.errorsrc().write_value(errors);
516
517 r.events_error().write_value(0);
518 r.events_dma().rx().end().write_value(0);
519
520 // set timeout-to-stop short
521 r.shorts().write(|w| {
522 w.set_frametimeout_dma_rx_stop(true);
523 });
524
525 // set default timeout
526 r.frametimeout().write_value(pac::uarte::regs::Frametimeout(0x10));
527
528 // Enable interrupts
529 r.intenset().write(|w| {
530 w.set_dmatxend(true);
531 w.set_error(true);
532 w.set_dmarxend(true);
533 });
534
535 Self { _peri: peri }
536 }
537
538 /// Pull some bytes from this source into the specified buffer, returning how many bytes were read.
539 pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
540 let data = self.fill_buf().await?;
541 let n = data.len().min(buf.len());
542 buf[..n].copy_from_slice(&data[..n]);
543 self.consume(n);
544 Ok(n)
545 }
546
547 /// Return the contents of the internal buffer, filling it with more data from the inner reader if it is empty.
548 pub fn fill_buf(&mut self) -> impl Future<Output = Result<&'_ [u8], Error>> {
549 poll_fn(move |cx| {
550 compiler_fence(Ordering::SeqCst);
551 //trace!("poll_read");
552
553 let s = U::buffered_state();
554 let ss = U::state();
555 let mut rx = unsafe { s.rx_buf.reader() };
556
557 let (ptr, n) = rx.pop_buf();
558 if n == 0 {
559 //trace!(" empty");
560 ss.rx_waker.register(cx.waker());
561 Poll::Pending
562 } else {
563 Poll::Ready(Ok(unsafe { slice::from_raw_parts(ptr, n) }))
564 }
565 })
566 }
567
568 /// Tell this buffer that `amt` bytes have been consumed from the buffer, so they should no longer be returned in calls to `fill_buf`.
569 pub fn consume(&mut self, amt: usize) {
570 if amt == 0 {
571 return;
572 }
573
574 let s = U::buffered_state();
575 let mut rx = unsafe { s.rx_buf.reader() };
576 rx.pop_done(amt);
577 }
578
579 /// we are ready to read if there is data in the buffer
580 fn read_ready() -> Result<bool, Error> {
581 let state = U::buffered_state();
582 Ok(!state.rx_buf.is_empty())
583 }
584}
585
586impl<'a, U: UarteInstance> Drop for BufferedUarteRx<'a, U> {
587 fn drop(&mut self) {
588 let r = U::regs();
589
590 r.intenclr().write(|w| {
591 w.set_rxto(true);
592 });
593 r.events_rxto().write_value(0);
594
595 let s = U::buffered_state();
596 unsafe { s.rx_buf.deinit() }
597
598 let s = U::state();
599 drop_tx_rx(r, s);
600 }
601}
602
603mod _embedded_io {
604 use super::*;
605
606 impl embedded_io_async::Error for Error {
607 fn kind(&self) -> embedded_io_async::ErrorKind {
608 match *self {}
609 }
610 }
611
612 impl<'d, U: UarteInstance> embedded_io_async::ErrorType for BufferedUarte<'d, U> {
613 type Error = Error;
614 }
615
616 impl<'d, U: UarteInstance> embedded_io_async::ErrorType for BufferedUarteRx<'d, U> {
617 type Error = Error;
618 }
619
620 impl<'d, U: UarteInstance> embedded_io_async::ErrorType for BufferedUarteTx<'d, U> {
621 type Error = Error;
622 }
623
624 impl<'d, U: UarteInstance> embedded_io_async::Read for BufferedUarte<'d, U> {
625 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
626 self.read(buf).await
627 }
628 }
629
630 impl<'d: 'd, U: UarteInstance> embedded_io_async::Read for BufferedUarteRx<'d, U> {
631 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
632 self.read(buf).await
633 }
634 }
635
636 impl<'d, U: UarteInstance> embedded_io_async::ReadReady for BufferedUarte<'d, U> {
637 fn read_ready(&mut self) -> Result<bool, Self::Error> {
638 BufferedUarteRx::<'d, U>::read_ready()
639 }
640 }
641
642 impl<'d, U: UarteInstance> embedded_io_async::ReadReady for BufferedUarteRx<'d, U> {
643 fn read_ready(&mut self) -> Result<bool, Self::Error> {
644 Self::read_ready()
645 }
646 }
647
648 impl<'d, U: UarteInstance> embedded_io_async::BufRead for BufferedUarte<'d, U> {
649 async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
650 self.fill_buf().await
651 }
652
653 fn consume(&mut self, amt: usize) {
654 self.consume(amt)
655 }
656 }
657
658 impl<'d: 'd, U: UarteInstance> embedded_io_async::BufRead for BufferedUarteRx<'d, U> {
659 async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
660 self.fill_buf().await
661 }
662
663 fn consume(&mut self, amt: usize) {
664 self.consume(amt)
665 }
666 }
667
668 impl<'d, U: UarteInstance> embedded_io_async::Write for BufferedUarte<'d, U> {
669 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
670 self.write(buf).await
671 }
672
673 async fn flush(&mut self) -> Result<(), Self::Error> {
674 self.flush().await
675 }
676 }
677
678 impl<'d: 'd, U: UarteInstance> embedded_io_async::Write for BufferedUarteTx<'d, U> {
679 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
680 self.write(buf).await
681 }
682
683 async fn flush(&mut self) -> Result<(), Self::Error> {
684 self.flush().await
685 }
686 }
687}
diff --git a/embassy-nrf/src/chips/nrf51.rs b/embassy-nrf/src/chips/nrf51.rs
index 3976e8ff0..1184c4409 100644
--- a/embassy-nrf/src/chips/nrf51.rs
+++ b/embassy-nrf/src/chips/nrf51.rs
@@ -115,6 +115,11 @@ impl_rtc!(RTC0, RTC0, RTC0);
115#[cfg(not(feature = "time-driver-rtc1"))] 115#[cfg(not(feature = "time-driver-rtc1"))]
116impl_rtc!(RTC1, RTC1, RTC1); 116impl_rtc!(RTC1, RTC1, RTC1);
117 117
118impl_ppi_group!(PPI_GROUP0, PPI, 0);
119impl_ppi_group!(PPI_GROUP1, PPI, 1);
120impl_ppi_group!(PPI_GROUP2, PPI, 2);
121impl_ppi_group!(PPI_GROUP3, PPI, 3);
122
118impl_pin!(P0_00, 0, 0); 123impl_pin!(P0_00, 0, 0);
119impl_pin!(P0_01, 0, 1); 124impl_pin!(P0_01, 0, 1);
120impl_pin!(P0_02, 0, 2); 125impl_pin!(P0_02, 0, 2);
diff --git a/embassy-nrf/src/chips/nrf52805.rs b/embassy-nrf/src/chips/nrf52805.rs
index 63ba6999a..dd2e66927 100644
--- a/embassy-nrf/src/chips/nrf52805.rs
+++ b/embassy-nrf/src/chips/nrf52805.rs
@@ -195,28 +195,35 @@ impl_pin!(P0_29, 0, 29);
195impl_pin!(P0_30, 0, 30); 195impl_pin!(P0_30, 0, 30);
196impl_pin!(P0_31, 0, 31); 196impl_pin!(P0_31, 0, 31);
197 197
198impl_ppi_channel!(PPI_CH0, 0 => configurable); 198impl_ppi_channel!(PPI_CH0, PPI, 0 => configurable);
199impl_ppi_channel!(PPI_CH1, 1 => configurable); 199impl_ppi_channel!(PPI_CH1, PPI, 1 => configurable);
200impl_ppi_channel!(PPI_CH2, 2 => configurable); 200impl_ppi_channel!(PPI_CH2, PPI, 2 => configurable);
201impl_ppi_channel!(PPI_CH3, 3 => configurable); 201impl_ppi_channel!(PPI_CH3, PPI, 3 => configurable);
202impl_ppi_channel!(PPI_CH4, 4 => configurable); 202impl_ppi_channel!(PPI_CH4, PPI, 4 => configurable);
203impl_ppi_channel!(PPI_CH5, 5 => configurable); 203impl_ppi_channel!(PPI_CH5, PPI, 5 => configurable);
204impl_ppi_channel!(PPI_CH6, 6 => configurable); 204impl_ppi_channel!(PPI_CH6, PPI, 6 => configurable);
205impl_ppi_channel!(PPI_CH7, 7 => configurable); 205impl_ppi_channel!(PPI_CH7, PPI, 7 => configurable);
206impl_ppi_channel!(PPI_CH8, 8 => configurable); 206impl_ppi_channel!(PPI_CH8, PPI, 8 => configurable);
207impl_ppi_channel!(PPI_CH9, 9 => configurable); 207impl_ppi_channel!(PPI_CH9, PPI, 9 => configurable);
208impl_ppi_channel!(PPI_CH20, 20 => static); 208impl_ppi_channel!(PPI_CH20, PPI, 20 => static);
209impl_ppi_channel!(PPI_CH21, 21 => static); 209impl_ppi_channel!(PPI_CH21, PPI, 21 => static);
210impl_ppi_channel!(PPI_CH22, 22 => static); 210impl_ppi_channel!(PPI_CH22, PPI, 22 => static);
211impl_ppi_channel!(PPI_CH23, 23 => static); 211impl_ppi_channel!(PPI_CH23, PPI, 23 => static);
212impl_ppi_channel!(PPI_CH24, 24 => static); 212impl_ppi_channel!(PPI_CH24, PPI, 24 => static);
213impl_ppi_channel!(PPI_CH25, 25 => static); 213impl_ppi_channel!(PPI_CH25, PPI, 25 => static);
214impl_ppi_channel!(PPI_CH26, 26 => static); 214impl_ppi_channel!(PPI_CH26, PPI, 26 => static);
215impl_ppi_channel!(PPI_CH27, 27 => static); 215impl_ppi_channel!(PPI_CH27, PPI, 27 => static);
216impl_ppi_channel!(PPI_CH28, 28 => static); 216impl_ppi_channel!(PPI_CH28, PPI, 28 => static);
217impl_ppi_channel!(PPI_CH29, 29 => static); 217impl_ppi_channel!(PPI_CH29, PPI, 29 => static);
218impl_ppi_channel!(PPI_CH30, 30 => static); 218impl_ppi_channel!(PPI_CH30, PPI, 30 => static);
219impl_ppi_channel!(PPI_CH31, 31 => static); 219impl_ppi_channel!(PPI_CH31, PPI, 31 => static);
220
221impl_ppi_group!(PPI_GROUP0, PPI, 0);
222impl_ppi_group!(PPI_GROUP1, PPI, 1);
223impl_ppi_group!(PPI_GROUP2, PPI, 2);
224impl_ppi_group!(PPI_GROUP3, PPI, 3);
225impl_ppi_group!(PPI_GROUP4, PPI, 4);
226impl_ppi_group!(PPI_GROUP5, PPI, 5);
220 227
221impl_saadc_input!(P0_04, ANALOG_INPUT2); 228impl_saadc_input!(P0_04, ANALOG_INPUT2);
222impl_saadc_input!(P0_05, ANALOG_INPUT3); 229impl_saadc_input!(P0_05, ANALOG_INPUT3);
diff --git a/embassy-nrf/src/chips/nrf52810.rs b/embassy-nrf/src/chips/nrf52810.rs
index 7f744f9fb..7acb53a03 100644
--- a/embassy-nrf/src/chips/nrf52810.rs
+++ b/embassy-nrf/src/chips/nrf52810.rs
@@ -205,38 +205,45 @@ impl_pin!(P0_29, 0, 29);
205impl_pin!(P0_30, 0, 30); 205impl_pin!(P0_30, 0, 30);
206impl_pin!(P0_31, 0, 31); 206impl_pin!(P0_31, 0, 31);
207 207
208impl_ppi_channel!(PPI_CH0, 0 => configurable); 208impl_ppi_channel!(PPI_CH0, PPI, 0 => configurable);
209impl_ppi_channel!(PPI_CH1, 1 => configurable); 209impl_ppi_channel!(PPI_CH1, PPI, 1 => configurable);
210impl_ppi_channel!(PPI_CH2, 2 => configurable); 210impl_ppi_channel!(PPI_CH2, PPI, 2 => configurable);
211impl_ppi_channel!(PPI_CH3, 3 => configurable); 211impl_ppi_channel!(PPI_CH3, PPI, 3 => configurable);
212impl_ppi_channel!(PPI_CH4, 4 => configurable); 212impl_ppi_channel!(PPI_CH4, PPI, 4 => configurable);
213impl_ppi_channel!(PPI_CH5, 5 => configurable); 213impl_ppi_channel!(PPI_CH5, PPI, 5 => configurable);
214impl_ppi_channel!(PPI_CH6, 6 => configurable); 214impl_ppi_channel!(PPI_CH6, PPI, 6 => configurable);
215impl_ppi_channel!(PPI_CH7, 7 => configurable); 215impl_ppi_channel!(PPI_CH7, PPI, 7 => configurable);
216impl_ppi_channel!(PPI_CH8, 8 => configurable); 216impl_ppi_channel!(PPI_CH8, PPI, 8 => configurable);
217impl_ppi_channel!(PPI_CH9, 9 => configurable); 217impl_ppi_channel!(PPI_CH9, PPI, 9 => configurable);
218impl_ppi_channel!(PPI_CH10, 10 => configurable); 218impl_ppi_channel!(PPI_CH10, PPI, 10 => configurable);
219impl_ppi_channel!(PPI_CH11, 11 => configurable); 219impl_ppi_channel!(PPI_CH11, PPI, 11 => configurable);
220impl_ppi_channel!(PPI_CH12, 12 => configurable); 220impl_ppi_channel!(PPI_CH12, PPI, 12 => configurable);
221impl_ppi_channel!(PPI_CH13, 13 => configurable); 221impl_ppi_channel!(PPI_CH13, PPI, 13 => configurable);
222impl_ppi_channel!(PPI_CH14, 14 => configurable); 222impl_ppi_channel!(PPI_CH14, PPI, 14 => configurable);
223impl_ppi_channel!(PPI_CH15, 15 => configurable); 223impl_ppi_channel!(PPI_CH15, PPI, 15 => configurable);
224impl_ppi_channel!(PPI_CH16, 16 => configurable); 224impl_ppi_channel!(PPI_CH16, PPI, 16 => configurable);
225impl_ppi_channel!(PPI_CH17, 17 => configurable); 225impl_ppi_channel!(PPI_CH17, PPI, 17 => configurable);
226impl_ppi_channel!(PPI_CH18, 18 => configurable); 226impl_ppi_channel!(PPI_CH18, PPI, 18 => configurable);
227impl_ppi_channel!(PPI_CH19, 19 => configurable); 227impl_ppi_channel!(PPI_CH19, PPI, 19 => configurable);
228impl_ppi_channel!(PPI_CH20, 20 => static); 228impl_ppi_channel!(PPI_CH20, PPI, 20 => static);
229impl_ppi_channel!(PPI_CH21, 21 => static); 229impl_ppi_channel!(PPI_CH21, PPI, 21 => static);
230impl_ppi_channel!(PPI_CH22, 22 => static); 230impl_ppi_channel!(PPI_CH22, PPI, 22 => static);
231impl_ppi_channel!(PPI_CH23, 23 => static); 231impl_ppi_channel!(PPI_CH23, PPI, 23 => static);
232impl_ppi_channel!(PPI_CH24, 24 => static); 232impl_ppi_channel!(PPI_CH24, PPI, 24 => static);
233impl_ppi_channel!(PPI_CH25, 25 => static); 233impl_ppi_channel!(PPI_CH25, PPI, 25 => static);
234impl_ppi_channel!(PPI_CH26, 26 => static); 234impl_ppi_channel!(PPI_CH26, PPI, 26 => static);
235impl_ppi_channel!(PPI_CH27, 27 => static); 235impl_ppi_channel!(PPI_CH27, PPI, 27 => static);
236impl_ppi_channel!(PPI_CH28, 28 => static); 236impl_ppi_channel!(PPI_CH28, PPI, 28 => static);
237impl_ppi_channel!(PPI_CH29, 29 => static); 237impl_ppi_channel!(PPI_CH29, PPI, 29 => static);
238impl_ppi_channel!(PPI_CH30, 30 => static); 238impl_ppi_channel!(PPI_CH30, PPI, 30 => static);
239impl_ppi_channel!(PPI_CH31, 31 => static); 239impl_ppi_channel!(PPI_CH31, PPI, 31 => static);
240
241impl_ppi_group!(PPI_GROUP0, PPI, 0);
242impl_ppi_group!(PPI_GROUP1, PPI, 1);
243impl_ppi_group!(PPI_GROUP2, PPI, 2);
244impl_ppi_group!(PPI_GROUP3, PPI, 3);
245impl_ppi_group!(PPI_GROUP4, PPI, 4);
246impl_ppi_group!(PPI_GROUP5, PPI, 5);
240 247
241impl_saadc_input!(P0_02, ANALOG_INPUT0); 248impl_saadc_input!(P0_02, ANALOG_INPUT0);
242impl_saadc_input!(P0_03, ANALOG_INPUT1); 249impl_saadc_input!(P0_03, ANALOG_INPUT1);
diff --git a/embassy-nrf/src/chips/nrf52811.rs b/embassy-nrf/src/chips/nrf52811.rs
index 908167e31..4178ef6cd 100644
--- a/embassy-nrf/src/chips/nrf52811.rs
+++ b/embassy-nrf/src/chips/nrf52811.rs
@@ -207,38 +207,45 @@ impl_pin!(P0_29, 0, 29);
207impl_pin!(P0_30, 0, 30); 207impl_pin!(P0_30, 0, 30);
208impl_pin!(P0_31, 0, 31); 208impl_pin!(P0_31, 0, 31);
209 209
210impl_ppi_channel!(PPI_CH0, 0 => configurable); 210impl_ppi_channel!(PPI_CH0, PPI, 0 => configurable);
211impl_ppi_channel!(PPI_CH1, 1 => configurable); 211impl_ppi_channel!(PPI_CH1, PPI, 1 => configurable);
212impl_ppi_channel!(PPI_CH2, 2 => configurable); 212impl_ppi_channel!(PPI_CH2, PPI, 2 => configurable);
213impl_ppi_channel!(PPI_CH3, 3 => configurable); 213impl_ppi_channel!(PPI_CH3, PPI, 3 => configurable);
214impl_ppi_channel!(PPI_CH4, 4 => configurable); 214impl_ppi_channel!(PPI_CH4, PPI, 4 => configurable);
215impl_ppi_channel!(PPI_CH5, 5 => configurable); 215impl_ppi_channel!(PPI_CH5, PPI, 5 => configurable);
216impl_ppi_channel!(PPI_CH6, 6 => configurable); 216impl_ppi_channel!(PPI_CH6, PPI, 6 => configurable);
217impl_ppi_channel!(PPI_CH7, 7 => configurable); 217impl_ppi_channel!(PPI_CH7, PPI, 7 => configurable);
218impl_ppi_channel!(PPI_CH8, 8 => configurable); 218impl_ppi_channel!(PPI_CH8, PPI, 8 => configurable);
219impl_ppi_channel!(PPI_CH9, 9 => configurable); 219impl_ppi_channel!(PPI_CH9, PPI, 9 => configurable);
220impl_ppi_channel!(PPI_CH10, 10 => configurable); 220impl_ppi_channel!(PPI_CH10, PPI, 10 => configurable);
221impl_ppi_channel!(PPI_CH11, 11 => configurable); 221impl_ppi_channel!(PPI_CH11, PPI, 11 => configurable);
222impl_ppi_channel!(PPI_CH12, 12 => configurable); 222impl_ppi_channel!(PPI_CH12, PPI, 12 => configurable);
223impl_ppi_channel!(PPI_CH13, 13 => configurable); 223impl_ppi_channel!(PPI_CH13, PPI, 13 => configurable);
224impl_ppi_channel!(PPI_CH14, 14 => configurable); 224impl_ppi_channel!(PPI_CH14, PPI, 14 => configurable);
225impl_ppi_channel!(PPI_CH15, 15 => configurable); 225impl_ppi_channel!(PPI_CH15, PPI, 15 => configurable);
226impl_ppi_channel!(PPI_CH16, 16 => configurable); 226impl_ppi_channel!(PPI_CH16, PPI, 16 => configurable);
227impl_ppi_channel!(PPI_CH17, 17 => configurable); 227impl_ppi_channel!(PPI_CH17, PPI, 17 => configurable);
228impl_ppi_channel!(PPI_CH18, 18 => configurable); 228impl_ppi_channel!(PPI_CH18, PPI, 18 => configurable);
229impl_ppi_channel!(PPI_CH19, 19 => configurable); 229impl_ppi_channel!(PPI_CH19, PPI, 19 => configurable);
230impl_ppi_channel!(PPI_CH20, 20 => static); 230impl_ppi_channel!(PPI_CH20, PPI, 20 => static);
231impl_ppi_channel!(PPI_CH21, 21 => static); 231impl_ppi_channel!(PPI_CH21, PPI, 21 => static);
232impl_ppi_channel!(PPI_CH22, 22 => static); 232impl_ppi_channel!(PPI_CH22, PPI, 22 => static);
233impl_ppi_channel!(PPI_CH23, 23 => static); 233impl_ppi_channel!(PPI_CH23, PPI, 23 => static);
234impl_ppi_channel!(PPI_CH24, 24 => static); 234impl_ppi_channel!(PPI_CH24, PPI, 24 => static);
235impl_ppi_channel!(PPI_CH25, 25 => static); 235impl_ppi_channel!(PPI_CH25, PPI, 25 => static);
236impl_ppi_channel!(PPI_CH26, 26 => static); 236impl_ppi_channel!(PPI_CH26, PPI, 26 => static);
237impl_ppi_channel!(PPI_CH27, 27 => static); 237impl_ppi_channel!(PPI_CH27, PPI, 27 => static);
238impl_ppi_channel!(PPI_CH28, 28 => static); 238impl_ppi_channel!(PPI_CH28, PPI, 28 => static);
239impl_ppi_channel!(PPI_CH29, 29 => static); 239impl_ppi_channel!(PPI_CH29, PPI, 29 => static);
240impl_ppi_channel!(PPI_CH30, 30 => static); 240impl_ppi_channel!(PPI_CH30, PPI, 30 => static);
241impl_ppi_channel!(PPI_CH31, 31 => static); 241impl_ppi_channel!(PPI_CH31, PPI, 31 => static);
242
243impl_ppi_group!(PPI_GROUP0, PPI, 0);
244impl_ppi_group!(PPI_GROUP1, PPI, 1);
245impl_ppi_group!(PPI_GROUP2, PPI, 2);
246impl_ppi_group!(PPI_GROUP3, PPI, 3);
247impl_ppi_group!(PPI_GROUP4, PPI, 4);
248impl_ppi_group!(PPI_GROUP5, PPI, 5);
242 249
243impl_saadc_input!(P0_02, ANALOG_INPUT0); 250impl_saadc_input!(P0_02, ANALOG_INPUT0);
244impl_saadc_input!(P0_03, ANALOG_INPUT1); 251impl_saadc_input!(P0_03, ANALOG_INPUT1);
diff --git a/embassy-nrf/src/chips/nrf52820.rs b/embassy-nrf/src/chips/nrf52820.rs
index 22360575b..32304b3ea 100644
--- a/embassy-nrf/src/chips/nrf52820.rs
+++ b/embassy-nrf/src/chips/nrf52820.rs
@@ -207,38 +207,45 @@ impl_pin!(P0_29, 0, 29);
207impl_pin!(P0_30, 0, 30); 207impl_pin!(P0_30, 0, 30);
208impl_pin!(P0_31, 0, 31); 208impl_pin!(P0_31, 0, 31);
209 209
210impl_ppi_channel!(PPI_CH0, 0 => configurable); 210impl_ppi_channel!(PPI_CH0, PPI, 0 => configurable);
211impl_ppi_channel!(PPI_CH1, 1 => configurable); 211impl_ppi_channel!(PPI_CH1, PPI, 1 => configurable);
212impl_ppi_channel!(PPI_CH2, 2 => configurable); 212impl_ppi_channel!(PPI_CH2, PPI, 2 => configurable);
213impl_ppi_channel!(PPI_CH3, 3 => configurable); 213impl_ppi_channel!(PPI_CH3, PPI, 3 => configurable);
214impl_ppi_channel!(PPI_CH4, 4 => configurable); 214impl_ppi_channel!(PPI_CH4, PPI, 4 => configurable);
215impl_ppi_channel!(PPI_CH5, 5 => configurable); 215impl_ppi_channel!(PPI_CH5, PPI, 5 => configurable);
216impl_ppi_channel!(PPI_CH6, 6 => configurable); 216impl_ppi_channel!(PPI_CH6, PPI, 6 => configurable);
217impl_ppi_channel!(PPI_CH7, 7 => configurable); 217impl_ppi_channel!(PPI_CH7, PPI, 7 => configurable);
218impl_ppi_channel!(PPI_CH8, 8 => configurable); 218impl_ppi_channel!(PPI_CH8, PPI, 8 => configurable);
219impl_ppi_channel!(PPI_CH9, 9 => configurable); 219impl_ppi_channel!(PPI_CH9, PPI, 9 => configurable);
220impl_ppi_channel!(PPI_CH10, 10 => configurable); 220impl_ppi_channel!(PPI_CH10, PPI, 10 => configurable);
221impl_ppi_channel!(PPI_CH11, 11 => configurable); 221impl_ppi_channel!(PPI_CH11, PPI, 11 => configurable);
222impl_ppi_channel!(PPI_CH12, 12 => configurable); 222impl_ppi_channel!(PPI_CH12, PPI, 12 => configurable);
223impl_ppi_channel!(PPI_CH13, 13 => configurable); 223impl_ppi_channel!(PPI_CH13, PPI, 13 => configurable);
224impl_ppi_channel!(PPI_CH14, 14 => configurable); 224impl_ppi_channel!(PPI_CH14, PPI, 14 => configurable);
225impl_ppi_channel!(PPI_CH15, 15 => configurable); 225impl_ppi_channel!(PPI_CH15, PPI, 15 => configurable);
226impl_ppi_channel!(PPI_CH16, 16 => configurable); 226impl_ppi_channel!(PPI_CH16, PPI, 16 => configurable);
227impl_ppi_channel!(PPI_CH17, 17 => configurable); 227impl_ppi_channel!(PPI_CH17, PPI, 17 => configurable);
228impl_ppi_channel!(PPI_CH18, 18 => configurable); 228impl_ppi_channel!(PPI_CH18, PPI, 18 => configurable);
229impl_ppi_channel!(PPI_CH19, 19 => configurable); 229impl_ppi_channel!(PPI_CH19, PPI, 19 => configurable);
230impl_ppi_channel!(PPI_CH20, 20 => static); 230impl_ppi_channel!(PPI_CH20, PPI, 20 => static);
231impl_ppi_channel!(PPI_CH21, 21 => static); 231impl_ppi_channel!(PPI_CH21, PPI, 21 => static);
232impl_ppi_channel!(PPI_CH22, 22 => static); 232impl_ppi_channel!(PPI_CH22, PPI, 22 => static);
233impl_ppi_channel!(PPI_CH23, 23 => static); 233impl_ppi_channel!(PPI_CH23, PPI, 23 => static);
234impl_ppi_channel!(PPI_CH24, 24 => static); 234impl_ppi_channel!(PPI_CH24, PPI, 24 => static);
235impl_ppi_channel!(PPI_CH25, 25 => static); 235impl_ppi_channel!(PPI_CH25, PPI, 25 => static);
236impl_ppi_channel!(PPI_CH26, 26 => static); 236impl_ppi_channel!(PPI_CH26, PPI, 26 => static);
237impl_ppi_channel!(PPI_CH27, 27 => static); 237impl_ppi_channel!(PPI_CH27, PPI, 27 => static);
238impl_ppi_channel!(PPI_CH28, 28 => static); 238impl_ppi_channel!(PPI_CH28, PPI, 28 => static);
239impl_ppi_channel!(PPI_CH29, 29 => static); 239impl_ppi_channel!(PPI_CH29, PPI, 29 => static);
240impl_ppi_channel!(PPI_CH30, 30 => static); 240impl_ppi_channel!(PPI_CH30, PPI, 30 => static);
241impl_ppi_channel!(PPI_CH31, 31 => static); 241impl_ppi_channel!(PPI_CH31, PPI, 31 => static);
242
243impl_ppi_group!(PPI_GROUP0, PPI, 0);
244impl_ppi_group!(PPI_GROUP1, PPI, 1);
245impl_ppi_group!(PPI_GROUP2, PPI, 2);
246impl_ppi_group!(PPI_GROUP3, PPI, 3);
247impl_ppi_group!(PPI_GROUP4, PPI, 4);
248impl_ppi_group!(PPI_GROUP5, PPI, 5);
242 249
243impl_radio!(RADIO, RADIO, RADIO); 250impl_radio!(RADIO, RADIO, RADIO);
244 251
diff --git a/embassy-nrf/src/chips/nrf52832.rs b/embassy-nrf/src/chips/nrf52832.rs
index 1598df3fe..06363a467 100644
--- a/embassy-nrf/src/chips/nrf52832.rs
+++ b/embassy-nrf/src/chips/nrf52832.rs
@@ -240,38 +240,45 @@ impl_pin!(P0_29, 0, 29);
240impl_pin!(P0_30, 0, 30); 240impl_pin!(P0_30, 0, 30);
241impl_pin!(P0_31, 0, 31); 241impl_pin!(P0_31, 0, 31);
242 242
243impl_ppi_channel!(PPI_CH0, 0 => configurable); 243impl_ppi_channel!(PPI_CH0, PPI, 0 => configurable);
244impl_ppi_channel!(PPI_CH1, 1 => configurable); 244impl_ppi_channel!(PPI_CH1, PPI, 1 => configurable);
245impl_ppi_channel!(PPI_CH2, 2 => configurable); 245impl_ppi_channel!(PPI_CH2, PPI, 2 => configurable);
246impl_ppi_channel!(PPI_CH3, 3 => configurable); 246impl_ppi_channel!(PPI_CH3, PPI, 3 => configurable);
247impl_ppi_channel!(PPI_CH4, 4 => configurable); 247impl_ppi_channel!(PPI_CH4, PPI, 4 => configurable);
248impl_ppi_channel!(PPI_CH5, 5 => configurable); 248impl_ppi_channel!(PPI_CH5, PPI, 5 => configurable);
249impl_ppi_channel!(PPI_CH6, 6 => configurable); 249impl_ppi_channel!(PPI_CH6, PPI, 6 => configurable);
250impl_ppi_channel!(PPI_CH7, 7 => configurable); 250impl_ppi_channel!(PPI_CH7, PPI, 7 => configurable);
251impl_ppi_channel!(PPI_CH8, 8 => configurable); 251impl_ppi_channel!(PPI_CH8, PPI, 8 => configurable);
252impl_ppi_channel!(PPI_CH9, 9 => configurable); 252impl_ppi_channel!(PPI_CH9, PPI, 9 => configurable);
253impl_ppi_channel!(PPI_CH10, 10 => configurable); 253impl_ppi_channel!(PPI_CH10, PPI, 10 => configurable);
254impl_ppi_channel!(PPI_CH11, 11 => configurable); 254impl_ppi_channel!(PPI_CH11, PPI, 11 => configurable);
255impl_ppi_channel!(PPI_CH12, 12 => configurable); 255impl_ppi_channel!(PPI_CH12, PPI, 12 => configurable);
256impl_ppi_channel!(PPI_CH13, 13 => configurable); 256impl_ppi_channel!(PPI_CH13, PPI, 13 => configurable);
257impl_ppi_channel!(PPI_CH14, 14 => configurable); 257impl_ppi_channel!(PPI_CH14, PPI, 14 => configurable);
258impl_ppi_channel!(PPI_CH15, 15 => configurable); 258impl_ppi_channel!(PPI_CH15, PPI, 15 => configurable);
259impl_ppi_channel!(PPI_CH16, 16 => configurable); 259impl_ppi_channel!(PPI_CH16, PPI, 16 => configurable);
260impl_ppi_channel!(PPI_CH17, 17 => configurable); 260impl_ppi_channel!(PPI_CH17, PPI, 17 => configurable);
261impl_ppi_channel!(PPI_CH18, 18 => configurable); 261impl_ppi_channel!(PPI_CH18, PPI, 18 => configurable);
262impl_ppi_channel!(PPI_CH19, 19 => configurable); 262impl_ppi_channel!(PPI_CH19, PPI, 19 => configurable);
263impl_ppi_channel!(PPI_CH20, 20 => static); 263impl_ppi_channel!(PPI_CH20, PPI, 20 => static);
264impl_ppi_channel!(PPI_CH21, 21 => static); 264impl_ppi_channel!(PPI_CH21, PPI, 21 => static);
265impl_ppi_channel!(PPI_CH22, 22 => static); 265impl_ppi_channel!(PPI_CH22, PPI, 22 => static);
266impl_ppi_channel!(PPI_CH23, 23 => static); 266impl_ppi_channel!(PPI_CH23, PPI, 23 => static);
267impl_ppi_channel!(PPI_CH24, 24 => static); 267impl_ppi_channel!(PPI_CH24, PPI, 24 => static);
268impl_ppi_channel!(PPI_CH25, 25 => static); 268impl_ppi_channel!(PPI_CH25, PPI, 25 => static);
269impl_ppi_channel!(PPI_CH26, 26 => static); 269impl_ppi_channel!(PPI_CH26, PPI, 26 => static);
270impl_ppi_channel!(PPI_CH27, 27 => static); 270impl_ppi_channel!(PPI_CH27, PPI, 27 => static);
271impl_ppi_channel!(PPI_CH28, 28 => static); 271impl_ppi_channel!(PPI_CH28, PPI, 28 => static);
272impl_ppi_channel!(PPI_CH29, 29 => static); 272impl_ppi_channel!(PPI_CH29, PPI, 29 => static);
273impl_ppi_channel!(PPI_CH30, 30 => static); 273impl_ppi_channel!(PPI_CH30, PPI, 30 => static);
274impl_ppi_channel!(PPI_CH31, 31 => static); 274impl_ppi_channel!(PPI_CH31, PPI, 31 => static);
275
276impl_ppi_group!(PPI_GROUP0, PPI, 0);
277impl_ppi_group!(PPI_GROUP1, PPI, 1);
278impl_ppi_group!(PPI_GROUP2, PPI, 2);
279impl_ppi_group!(PPI_GROUP3, PPI, 3);
280impl_ppi_group!(PPI_GROUP4, PPI, 4);
281impl_ppi_group!(PPI_GROUP5, PPI, 5);
275 282
276impl_saadc_input!(P0_02, ANALOG_INPUT0); 283impl_saadc_input!(P0_02, ANALOG_INPUT0);
277impl_saadc_input!(P0_03, ANALOG_INPUT1); 284impl_saadc_input!(P0_03, ANALOG_INPUT1);
diff --git a/embassy-nrf/src/chips/nrf52833.rs b/embassy-nrf/src/chips/nrf52833.rs
index 6931fb064..754943d33 100644
--- a/embassy-nrf/src/chips/nrf52833.rs
+++ b/embassy-nrf/src/chips/nrf52833.rs
@@ -282,38 +282,45 @@ impl_pin!(P1_13, 1, 13);
282impl_pin!(P1_14, 1, 14); 282impl_pin!(P1_14, 1, 14);
283impl_pin!(P1_15, 1, 15); 283impl_pin!(P1_15, 1, 15);
284 284
285impl_ppi_channel!(PPI_CH0, 0 => configurable); 285impl_ppi_channel!(PPI_CH0, PPI, 0 => configurable);
286impl_ppi_channel!(PPI_CH1, 1 => configurable); 286impl_ppi_channel!(PPI_CH1, PPI, 1 => configurable);
287impl_ppi_channel!(PPI_CH2, 2 => configurable); 287impl_ppi_channel!(PPI_CH2, PPI, 2 => configurable);
288impl_ppi_channel!(PPI_CH3, 3 => configurable); 288impl_ppi_channel!(PPI_CH3, PPI, 3 => configurable);
289impl_ppi_channel!(PPI_CH4, 4 => configurable); 289impl_ppi_channel!(PPI_CH4, PPI, 4 => configurable);
290impl_ppi_channel!(PPI_CH5, 5 => configurable); 290impl_ppi_channel!(PPI_CH5, PPI, 5 => configurable);
291impl_ppi_channel!(PPI_CH6, 6 => configurable); 291impl_ppi_channel!(PPI_CH6, PPI, 6 => configurable);
292impl_ppi_channel!(PPI_CH7, 7 => configurable); 292impl_ppi_channel!(PPI_CH7, PPI, 7 => configurable);
293impl_ppi_channel!(PPI_CH8, 8 => configurable); 293impl_ppi_channel!(PPI_CH8, PPI, 8 => configurable);
294impl_ppi_channel!(PPI_CH9, 9 => configurable); 294impl_ppi_channel!(PPI_CH9, PPI, 9 => configurable);
295impl_ppi_channel!(PPI_CH10, 10 => configurable); 295impl_ppi_channel!(PPI_CH10, PPI, 10 => configurable);
296impl_ppi_channel!(PPI_CH11, 11 => configurable); 296impl_ppi_channel!(PPI_CH11, PPI, 11 => configurable);
297impl_ppi_channel!(PPI_CH12, 12 => configurable); 297impl_ppi_channel!(PPI_CH12, PPI, 12 => configurable);
298impl_ppi_channel!(PPI_CH13, 13 => configurable); 298impl_ppi_channel!(PPI_CH13, PPI, 13 => configurable);
299impl_ppi_channel!(PPI_CH14, 14 => configurable); 299impl_ppi_channel!(PPI_CH14, PPI, 14 => configurable);
300impl_ppi_channel!(PPI_CH15, 15 => configurable); 300impl_ppi_channel!(PPI_CH15, PPI, 15 => configurable);
301impl_ppi_channel!(PPI_CH16, 16 => configurable); 301impl_ppi_channel!(PPI_CH16, PPI, 16 => configurable);
302impl_ppi_channel!(PPI_CH17, 17 => configurable); 302impl_ppi_channel!(PPI_CH17, PPI, 17 => configurable);
303impl_ppi_channel!(PPI_CH18, 18 => configurable); 303impl_ppi_channel!(PPI_CH18, PPI, 18 => configurable);
304impl_ppi_channel!(PPI_CH19, 19 => configurable); 304impl_ppi_channel!(PPI_CH19, PPI, 19 => configurable);
305impl_ppi_channel!(PPI_CH20, 20 => static); 305impl_ppi_channel!(PPI_CH20, PPI, 20 => static);
306impl_ppi_channel!(PPI_CH21, 21 => static); 306impl_ppi_channel!(PPI_CH21, PPI, 21 => static);
307impl_ppi_channel!(PPI_CH22, 22 => static); 307impl_ppi_channel!(PPI_CH22, PPI, 22 => static);
308impl_ppi_channel!(PPI_CH23, 23 => static); 308impl_ppi_channel!(PPI_CH23, PPI, 23 => static);
309impl_ppi_channel!(PPI_CH24, 24 => static); 309impl_ppi_channel!(PPI_CH24, PPI, 24 => static);
310impl_ppi_channel!(PPI_CH25, 25 => static); 310impl_ppi_channel!(PPI_CH25, PPI, 25 => static);
311impl_ppi_channel!(PPI_CH26, 26 => static); 311impl_ppi_channel!(PPI_CH26, PPI, 26 => static);
312impl_ppi_channel!(PPI_CH27, 27 => static); 312impl_ppi_channel!(PPI_CH27, PPI, 27 => static);
313impl_ppi_channel!(PPI_CH28, 28 => static); 313impl_ppi_channel!(PPI_CH28, PPI, 28 => static);
314impl_ppi_channel!(PPI_CH29, 29 => static); 314impl_ppi_channel!(PPI_CH29, PPI, 29 => static);
315impl_ppi_channel!(PPI_CH30, 30 => static); 315impl_ppi_channel!(PPI_CH30, PPI, 30 => static);
316impl_ppi_channel!(PPI_CH31, 31 => static); 316impl_ppi_channel!(PPI_CH31, PPI, 31 => static);
317
318impl_ppi_group!(PPI_GROUP0, PPI, 0);
319impl_ppi_group!(PPI_GROUP1, PPI, 1);
320impl_ppi_group!(PPI_GROUP2, PPI, 2);
321impl_ppi_group!(PPI_GROUP3, PPI, 3);
322impl_ppi_group!(PPI_GROUP4, PPI, 4);
323impl_ppi_group!(PPI_GROUP5, PPI, 5);
317 324
318impl_saadc_input!(P0_02, ANALOG_INPUT0); 325impl_saadc_input!(P0_02, ANALOG_INPUT0);
319impl_saadc_input!(P0_03, ANALOG_INPUT1); 326impl_saadc_input!(P0_03, ANALOG_INPUT1);
diff --git a/embassy-nrf/src/chips/nrf52840.rs b/embassy-nrf/src/chips/nrf52840.rs
index 5fa521aae..ac07cd820 100644
--- a/embassy-nrf/src/chips/nrf52840.rs
+++ b/embassy-nrf/src/chips/nrf52840.rs
@@ -287,38 +287,45 @@ impl_pin!(P1_13, 1, 13);
287impl_pin!(P1_14, 1, 14); 287impl_pin!(P1_14, 1, 14);
288impl_pin!(P1_15, 1, 15); 288impl_pin!(P1_15, 1, 15);
289 289
290impl_ppi_channel!(PPI_CH0, 0 => configurable); 290impl_ppi_channel!(PPI_CH0, PPI, 0 => configurable);
291impl_ppi_channel!(PPI_CH1, 1 => configurable); 291impl_ppi_channel!(PPI_CH1, PPI, 1 => configurable);
292impl_ppi_channel!(PPI_CH2, 2 => configurable); 292impl_ppi_channel!(PPI_CH2, PPI, 2 => configurable);
293impl_ppi_channel!(PPI_CH3, 3 => configurable); 293impl_ppi_channel!(PPI_CH3, PPI, 3 => configurable);
294impl_ppi_channel!(PPI_CH4, 4 => configurable); 294impl_ppi_channel!(PPI_CH4, PPI, 4 => configurable);
295impl_ppi_channel!(PPI_CH5, 5 => configurable); 295impl_ppi_channel!(PPI_CH5, PPI, 5 => configurable);
296impl_ppi_channel!(PPI_CH6, 6 => configurable); 296impl_ppi_channel!(PPI_CH6, PPI, 6 => configurable);
297impl_ppi_channel!(PPI_CH7, 7 => configurable); 297impl_ppi_channel!(PPI_CH7, PPI, 7 => configurable);
298impl_ppi_channel!(PPI_CH8, 8 => configurable); 298impl_ppi_channel!(PPI_CH8, PPI, 8 => configurable);
299impl_ppi_channel!(PPI_CH9, 9 => configurable); 299impl_ppi_channel!(PPI_CH9, PPI, 9 => configurable);
300impl_ppi_channel!(PPI_CH10, 10 => configurable); 300impl_ppi_channel!(PPI_CH10, PPI, 10 => configurable);
301impl_ppi_channel!(PPI_CH11, 11 => configurable); 301impl_ppi_channel!(PPI_CH11, PPI, 11 => configurable);
302impl_ppi_channel!(PPI_CH12, 12 => configurable); 302impl_ppi_channel!(PPI_CH12, PPI, 12 => configurable);
303impl_ppi_channel!(PPI_CH13, 13 => configurable); 303impl_ppi_channel!(PPI_CH13, PPI, 13 => configurable);
304impl_ppi_channel!(PPI_CH14, 14 => configurable); 304impl_ppi_channel!(PPI_CH14, PPI, 14 => configurable);
305impl_ppi_channel!(PPI_CH15, 15 => configurable); 305impl_ppi_channel!(PPI_CH15, PPI, 15 => configurable);
306impl_ppi_channel!(PPI_CH16, 16 => configurable); 306impl_ppi_channel!(PPI_CH16, PPI, 16 => configurable);
307impl_ppi_channel!(PPI_CH17, 17 => configurable); 307impl_ppi_channel!(PPI_CH17, PPI, 17 => configurable);
308impl_ppi_channel!(PPI_CH18, 18 => configurable); 308impl_ppi_channel!(PPI_CH18, PPI, 18 => configurable);
309impl_ppi_channel!(PPI_CH19, 19 => configurable); 309impl_ppi_channel!(PPI_CH19, PPI, 19 => configurable);
310impl_ppi_channel!(PPI_CH20, 20 => static); 310impl_ppi_channel!(PPI_CH20, PPI, 20 => static);
311impl_ppi_channel!(PPI_CH21, 21 => static); 311impl_ppi_channel!(PPI_CH21, PPI, 21 => static);
312impl_ppi_channel!(PPI_CH22, 22 => static); 312impl_ppi_channel!(PPI_CH22, PPI, 22 => static);
313impl_ppi_channel!(PPI_CH23, 23 => static); 313impl_ppi_channel!(PPI_CH23, PPI, 23 => static);
314impl_ppi_channel!(PPI_CH24, 24 => static); 314impl_ppi_channel!(PPI_CH24, PPI, 24 => static);
315impl_ppi_channel!(PPI_CH25, 25 => static); 315impl_ppi_channel!(PPI_CH25, PPI, 25 => static);
316impl_ppi_channel!(PPI_CH26, 26 => static); 316impl_ppi_channel!(PPI_CH26, PPI, 26 => static);
317impl_ppi_channel!(PPI_CH27, 27 => static); 317impl_ppi_channel!(PPI_CH27, PPI, 27 => static);
318impl_ppi_channel!(PPI_CH28, 28 => static); 318impl_ppi_channel!(PPI_CH28, PPI, 28 => static);
319impl_ppi_channel!(PPI_CH29, 29 => static); 319impl_ppi_channel!(PPI_CH29, PPI, 29 => static);
320impl_ppi_channel!(PPI_CH30, 30 => static); 320impl_ppi_channel!(PPI_CH30, PPI, 30 => static);
321impl_ppi_channel!(PPI_CH31, 31 => static); 321impl_ppi_channel!(PPI_CH31, PPI, 31 => static);
322
323impl_ppi_group!(PPI_GROUP0, PPI, 0);
324impl_ppi_group!(PPI_GROUP1, PPI, 1);
325impl_ppi_group!(PPI_GROUP2, PPI, 2);
326impl_ppi_group!(PPI_GROUP3, PPI, 3);
327impl_ppi_group!(PPI_GROUP4, PPI, 4);
328impl_ppi_group!(PPI_GROUP5, PPI, 5);
322 329
323impl_saadc_input!(P0_02, ANALOG_INPUT0); 330impl_saadc_input!(P0_02, ANALOG_INPUT0);
324impl_saadc_input!(P0_03, ANALOG_INPUT1); 331impl_saadc_input!(P0_03, ANALOG_INPUT1);
diff --git a/embassy-nrf/src/chips/nrf5340_app.rs b/embassy-nrf/src/chips/nrf5340_app.rs
index 730c9842d..aa51527fb 100644
--- a/embassy-nrf/src/chips/nrf5340_app.rs
+++ b/embassy-nrf/src/chips/nrf5340_app.rs
@@ -435,38 +435,45 @@ impl_pin!(P1_13, 1, 13);
435impl_pin!(P1_14, 1, 14); 435impl_pin!(P1_14, 1, 14);
436impl_pin!(P1_15, 1, 15); 436impl_pin!(P1_15, 1, 15);
437 437
438impl_ppi_channel!(PPI_CH0, 0 => configurable); 438impl_ppi_channel!(PPI_CH0, DPPIC, 0 => configurable);
439impl_ppi_channel!(PPI_CH1, 1 => configurable); 439impl_ppi_channel!(PPI_CH1, DPPIC, 1 => configurable);
440impl_ppi_channel!(PPI_CH2, 2 => configurable); 440impl_ppi_channel!(PPI_CH2, DPPIC, 2 => configurable);
441impl_ppi_channel!(PPI_CH3, 3 => configurable); 441impl_ppi_channel!(PPI_CH3, DPPIC, 3 => configurable);
442impl_ppi_channel!(PPI_CH4, 4 => configurable); 442impl_ppi_channel!(PPI_CH4, DPPIC, 4 => configurable);
443impl_ppi_channel!(PPI_CH5, 5 => configurable); 443impl_ppi_channel!(PPI_CH5, DPPIC, 5 => configurable);
444impl_ppi_channel!(PPI_CH6, 6 => configurable); 444impl_ppi_channel!(PPI_CH6, DPPIC, 6 => configurable);
445impl_ppi_channel!(PPI_CH7, 7 => configurable); 445impl_ppi_channel!(PPI_CH7, DPPIC, 7 => configurable);
446impl_ppi_channel!(PPI_CH8, 8 => configurable); 446impl_ppi_channel!(PPI_CH8, DPPIC, 8 => configurable);
447impl_ppi_channel!(PPI_CH9, 9 => configurable); 447impl_ppi_channel!(PPI_CH9, DPPIC, 9 => configurable);
448impl_ppi_channel!(PPI_CH10, 10 => configurable); 448impl_ppi_channel!(PPI_CH10, DPPIC, 10 => configurable);
449impl_ppi_channel!(PPI_CH11, 11 => configurable); 449impl_ppi_channel!(PPI_CH11, DPPIC, 11 => configurable);
450impl_ppi_channel!(PPI_CH12, 12 => configurable); 450impl_ppi_channel!(PPI_CH12, DPPIC, 12 => configurable);
451impl_ppi_channel!(PPI_CH13, 13 => configurable); 451impl_ppi_channel!(PPI_CH13, DPPIC, 13 => configurable);
452impl_ppi_channel!(PPI_CH14, 14 => configurable); 452impl_ppi_channel!(PPI_CH14, DPPIC, 14 => configurable);
453impl_ppi_channel!(PPI_CH15, 15 => configurable); 453impl_ppi_channel!(PPI_CH15, DPPIC, 15 => configurable);
454impl_ppi_channel!(PPI_CH16, 16 => configurable); 454impl_ppi_channel!(PPI_CH16, DPPIC, 16 => configurable);
455impl_ppi_channel!(PPI_CH17, 17 => configurable); 455impl_ppi_channel!(PPI_CH17, DPPIC, 17 => configurable);
456impl_ppi_channel!(PPI_CH18, 18 => configurable); 456impl_ppi_channel!(PPI_CH18, DPPIC, 18 => configurable);
457impl_ppi_channel!(PPI_CH19, 19 => configurable); 457impl_ppi_channel!(PPI_CH19, DPPIC, 19 => configurable);
458impl_ppi_channel!(PPI_CH20, 20 => configurable); 458impl_ppi_channel!(PPI_CH20, DPPIC, 20 => configurable);
459impl_ppi_channel!(PPI_CH21, 21 => configurable); 459impl_ppi_channel!(PPI_CH21, DPPIC, 21 => configurable);
460impl_ppi_channel!(PPI_CH22, 22 => configurable); 460impl_ppi_channel!(PPI_CH22, DPPIC, 22 => configurable);
461impl_ppi_channel!(PPI_CH23, 23 => configurable); 461impl_ppi_channel!(PPI_CH23, DPPIC, 23 => configurable);
462impl_ppi_channel!(PPI_CH24, 24 => configurable); 462impl_ppi_channel!(PPI_CH24, DPPIC, 24 => configurable);
463impl_ppi_channel!(PPI_CH25, 25 => configurable); 463impl_ppi_channel!(PPI_CH25, DPPIC, 25 => configurable);
464impl_ppi_channel!(PPI_CH26, 26 => configurable); 464impl_ppi_channel!(PPI_CH26, DPPIC, 26 => configurable);
465impl_ppi_channel!(PPI_CH27, 27 => configurable); 465impl_ppi_channel!(PPI_CH27, DPPIC, 27 => configurable);
466impl_ppi_channel!(PPI_CH28, 28 => configurable); 466impl_ppi_channel!(PPI_CH28, DPPIC, 28 => configurable);
467impl_ppi_channel!(PPI_CH29, 29 => configurable); 467impl_ppi_channel!(PPI_CH29, DPPIC, 29 => configurable);
468impl_ppi_channel!(PPI_CH30, 30 => configurable); 468impl_ppi_channel!(PPI_CH30, DPPIC, 30 => configurable);
469impl_ppi_channel!(PPI_CH31, 31 => configurable); 469impl_ppi_channel!(PPI_CH31, DPPIC, 31 => configurable);
470
471impl_ppi_group!(PPI_GROUP0, DPPIC, 0);
472impl_ppi_group!(PPI_GROUP1, DPPIC, 1);
473impl_ppi_group!(PPI_GROUP2, DPPIC, 2);
474impl_ppi_group!(PPI_GROUP3, DPPIC, 3);
475impl_ppi_group!(PPI_GROUP4, DPPIC, 4);
476impl_ppi_group!(PPI_GROUP5, DPPIC, 5);
470 477
471impl_saadc_input!(P0_04, ANALOG_INPUT0); 478impl_saadc_input!(P0_04, ANALOG_INPUT0);
472impl_saadc_input!(P0_05, ANALOG_INPUT1); 479impl_saadc_input!(P0_05, ANALOG_INPUT1);
diff --git a/embassy-nrf/src/chips/nrf5340_net.rs b/embassy-nrf/src/chips/nrf5340_net.rs
index 413afc5c5..2207e7bda 100644
--- a/embassy-nrf/src/chips/nrf5340_net.rs
+++ b/embassy-nrf/src/chips/nrf5340_net.rs
@@ -275,38 +275,45 @@ impl_pin!(P1_13, 1, 13);
275impl_pin!(P1_14, 1, 14); 275impl_pin!(P1_14, 1, 14);
276impl_pin!(P1_15, 1, 15); 276impl_pin!(P1_15, 1, 15);
277 277
278impl_ppi_channel!(PPI_CH0, 0 => configurable); 278impl_ppi_channel!(PPI_CH0, DPPIC, 0 => configurable);
279impl_ppi_channel!(PPI_CH1, 1 => configurable); 279impl_ppi_channel!(PPI_CH1, DPPIC, 1 => configurable);
280impl_ppi_channel!(PPI_CH2, 2 => configurable); 280impl_ppi_channel!(PPI_CH2, DPPIC, 2 => configurable);
281impl_ppi_channel!(PPI_CH3, 3 => configurable); 281impl_ppi_channel!(PPI_CH3, DPPIC, 3 => configurable);
282impl_ppi_channel!(PPI_CH4, 4 => configurable); 282impl_ppi_channel!(PPI_CH4, DPPIC, 4 => configurable);
283impl_ppi_channel!(PPI_CH5, 5 => configurable); 283impl_ppi_channel!(PPI_CH5, DPPIC, 5 => configurable);
284impl_ppi_channel!(PPI_CH6, 6 => configurable); 284impl_ppi_channel!(PPI_CH6, DPPIC, 6 => configurable);
285impl_ppi_channel!(PPI_CH7, 7 => configurable); 285impl_ppi_channel!(PPI_CH7, DPPIC, 7 => configurable);
286impl_ppi_channel!(PPI_CH8, 8 => configurable); 286impl_ppi_channel!(PPI_CH8, DPPIC, 8 => configurable);
287impl_ppi_channel!(PPI_CH9, 9 => configurable); 287impl_ppi_channel!(PPI_CH9, DPPIC, 9 => configurable);
288impl_ppi_channel!(PPI_CH10, 10 => configurable); 288impl_ppi_channel!(PPI_CH10, DPPIC, 10 => configurable);
289impl_ppi_channel!(PPI_CH11, 11 => configurable); 289impl_ppi_channel!(PPI_CH11, DPPIC, 11 => configurable);
290impl_ppi_channel!(PPI_CH12, 12 => configurable); 290impl_ppi_channel!(PPI_CH12, DPPIC, 12 => configurable);
291impl_ppi_channel!(PPI_CH13, 13 => configurable); 291impl_ppi_channel!(PPI_CH13, DPPIC, 13 => configurable);
292impl_ppi_channel!(PPI_CH14, 14 => configurable); 292impl_ppi_channel!(PPI_CH14, DPPIC, 14 => configurable);
293impl_ppi_channel!(PPI_CH15, 15 => configurable); 293impl_ppi_channel!(PPI_CH15, DPPIC, 15 => configurable);
294impl_ppi_channel!(PPI_CH16, 16 => configurable); 294impl_ppi_channel!(PPI_CH16, DPPIC, 16 => configurable);
295impl_ppi_channel!(PPI_CH17, 17 => configurable); 295impl_ppi_channel!(PPI_CH17, DPPIC, 17 => configurable);
296impl_ppi_channel!(PPI_CH18, 18 => configurable); 296impl_ppi_channel!(PPI_CH18, DPPIC, 18 => configurable);
297impl_ppi_channel!(PPI_CH19, 19 => configurable); 297impl_ppi_channel!(PPI_CH19, DPPIC, 19 => configurable);
298impl_ppi_channel!(PPI_CH20, 20 => configurable); 298impl_ppi_channel!(PPI_CH20, DPPIC, 20 => configurable);
299impl_ppi_channel!(PPI_CH21, 21 => configurable); 299impl_ppi_channel!(PPI_CH21, DPPIC, 21 => configurable);
300impl_ppi_channel!(PPI_CH22, 22 => configurable); 300impl_ppi_channel!(PPI_CH22, DPPIC, 22 => configurable);
301impl_ppi_channel!(PPI_CH23, 23 => configurable); 301impl_ppi_channel!(PPI_CH23, DPPIC, 23 => configurable);
302impl_ppi_channel!(PPI_CH24, 24 => configurable); 302impl_ppi_channel!(PPI_CH24, DPPIC, 24 => configurable);
303impl_ppi_channel!(PPI_CH25, 25 => configurable); 303impl_ppi_channel!(PPI_CH25, DPPIC, 25 => configurable);
304impl_ppi_channel!(PPI_CH26, 26 => configurable); 304impl_ppi_channel!(PPI_CH26, DPPIC, 26 => configurable);
305impl_ppi_channel!(PPI_CH27, 27 => configurable); 305impl_ppi_channel!(PPI_CH27, DPPIC, 27 => configurable);
306impl_ppi_channel!(PPI_CH28, 28 => configurable); 306impl_ppi_channel!(PPI_CH28, DPPIC, 28 => configurable);
307impl_ppi_channel!(PPI_CH29, 29 => configurable); 307impl_ppi_channel!(PPI_CH29, DPPIC, 29 => configurable);
308impl_ppi_channel!(PPI_CH30, 30 => configurable); 308impl_ppi_channel!(PPI_CH30, DPPIC, 30 => configurable);
309impl_ppi_channel!(PPI_CH31, 31 => configurable); 309impl_ppi_channel!(PPI_CH31, DPPIC, 31 => configurable);
310
311impl_ppi_group!(PPI_GROUP0, DPPIC, 0);
312impl_ppi_group!(PPI_GROUP1, DPPIC, 1);
313impl_ppi_group!(PPI_GROUP2, DPPIC, 2);
314impl_ppi_group!(PPI_GROUP3, DPPIC, 3);
315impl_ppi_group!(PPI_GROUP4, DPPIC, 4);
316impl_ppi_group!(PPI_GROUP5, DPPIC, 5);
310 317
311impl_radio!(RADIO, RADIO, RADIO); 318impl_radio!(RADIO, RADIO, RADIO);
312 319
diff --git a/embassy-nrf/src/chips/nrf54l15_app.rs b/embassy-nrf/src/chips/nrf54l15_app.rs
index 901c5e7fc..f58a74825 100644
--- a/embassy-nrf/src/chips/nrf54l15_app.rs
+++ b/embassy-nrf/src/chips/nrf54l15_app.rs
@@ -200,13 +200,67 @@ pub mod pac {
200 200
201/// The maximum buffer size that the EasyDMA can send/recv in one operation. 201/// The maximum buffer size that the EasyDMA can send/recv in one operation.
202pub const EASY_DMA_SIZE: usize = (1 << 16) - 1; 202pub const EASY_DMA_SIZE: usize = (1 << 16) - 1;
203//pub const FORCE_COPY_BUFFER_SIZE: usize = 1024; 203pub const FORCE_COPY_BUFFER_SIZE: usize = 1024;
204 204
205// 1.5 MB NVM 205// 1.5 MB NVM
206#[allow(unused)] 206#[allow(unused)]
207pub const FLASH_SIZE: usize = 1536 * 1024; 207pub const FLASH_SIZE: usize = 1536 * 1024;
208 208
209embassy_hal_internal::peripherals! { 209embassy_hal_internal::peripherals! {
210 // PPI
211 PPI00_CH0,
212 PPI00_CH1,
213 PPI00_CH2,
214 PPI00_CH3,
215 PPI00_CH4,
216 PPI00_CH5,
217 PPI00_CH6,
218 PPI00_CH7,
219
220 PPI20_CH0,
221 PPI20_CH1,
222 PPI20_CH2,
223 PPI20_CH3,
224 PPI20_CH4,
225 PPI20_CH5,
226 PPI20_CH6,
227 PPI20_CH7,
228 PPI20_CH8,
229 PPI20_CH9,
230 PPI20_CH10,
231 PPI20_CH11,
232 PPI20_CH12,
233 PPI20_CH13,
234 PPI20_CH14,
235 PPI20_CH15,
236
237 PPI30_CH0,
238 PPI30_CH1,
239 PPI30_CH2,
240 PPI30_CH3,
241
242 PPI00_GROUP0,
243 PPI00_GROUP1,
244
245 PPI20_GROUP0,
246 PPI20_GROUP1,
247 PPI20_GROUP2,
248 PPI20_GROUP3,
249 PPI20_GROUP4,
250 PPI20_GROUP5,
251
252 PPI30_GROUP0,
253 PPI30_GROUP1,
254
255 // Timers
256 TIMER00,
257 TIMER10,
258 TIMER20,
259 TIMER21,
260 TIMER22,
261 TIMER23,
262 TIMER24,
263
210 // GPIO port 0 264 // GPIO port 0
211 P0_00, 265 P0_00,
212 P0_01, 266 P0_01,
@@ -253,6 +307,11 @@ embassy_hal_internal::peripherals! {
253 RTC10, 307 RTC10,
254 RTC30, 308 RTC30,
255 309
310 // PWM
311 PWM20,
312 PWM21,
313 PWM22,
314
256 // SERIAL 315 // SERIAL
257 SERIAL00, 316 SERIAL00,
258 SERIAL20, 317 SERIAL20,
@@ -266,11 +325,6 @@ embassy_hal_internal::peripherals! {
266 // RADIO 325 // RADIO
267 RADIO, 326 RADIO,
268 327
269 // TIMER
270 TIMER00,
271 TIMER10,
272 TIMER20,
273
274 // PPI BRIDGE 328 // PPI BRIDGE
275 PPIB00, 329 PPIB00,
276 PPIB01, 330 PPIB01,
@@ -281,10 +335,24 @@ embassy_hal_internal::peripherals! {
281 PPIB22, 335 PPIB22,
282 PPIB30, 336 PPIB30,
283 337
284 // GPIOTE 338 // GPIOTE instances
285 GPIOTE20, 339 GPIOTE20,
286 GPIOTE30, 340 GPIOTE30,
287 341
342 // GPIOTE channels
343 GPIOTE20_CH0,
344 GPIOTE20_CH1,
345 GPIOTE20_CH2,
346 GPIOTE20_CH3,
347 GPIOTE20_CH4,
348 GPIOTE20_CH5,
349 GPIOTE20_CH6,
350 GPIOTE20_CH7,
351 GPIOTE30_CH0,
352 GPIOTE30_CH1,
353 GPIOTE30_CH2,
354 GPIOTE30_CH3,
355
288 // CRACEN 356 // CRACEN
289 CRACEN, 357 CRACEN,
290 358
@@ -311,6 +379,13 @@ impl_pin!(P0_03, 0, 3);
311impl_pin!(P0_04, 0, 4); 379impl_pin!(P0_04, 0, 4);
312impl_pin!(P0_05, 0, 5); 380impl_pin!(P0_05, 0, 5);
313impl_pin!(P0_06, 0, 6); 381impl_pin!(P0_06, 0, 6);
382impl_gpiote_pin!(P0_00, GPIOTE30);
383impl_gpiote_pin!(P0_01, GPIOTE30);
384impl_gpiote_pin!(P0_02, GPIOTE30);
385impl_gpiote_pin!(P0_03, GPIOTE30);
386impl_gpiote_pin!(P0_04, GPIOTE30);
387impl_gpiote_pin!(P0_05, GPIOTE30);
388impl_gpiote_pin!(P0_06, GPIOTE30);
314 389
315impl_pin!(P1_00, 1, 0); 390impl_pin!(P1_00, 1, 0);
316impl_pin!(P1_01, 1, 1); 391impl_pin!(P1_01, 1, 1);
@@ -330,6 +405,24 @@ impl_pin!(P1_14, 1, 14);
330impl_pin!(P1_15, 1, 15); 405impl_pin!(P1_15, 1, 15);
331impl_pin!(P1_16, 1, 16); 406impl_pin!(P1_16, 1, 16);
332 407
408impl_gpiote_pin!(P1_00, GPIOTE20);
409impl_gpiote_pin!(P1_01, GPIOTE20);
410impl_gpiote_pin!(P1_02, GPIOTE20);
411impl_gpiote_pin!(P1_03, GPIOTE20);
412impl_gpiote_pin!(P1_04, GPIOTE20);
413impl_gpiote_pin!(P1_05, GPIOTE20);
414impl_gpiote_pin!(P1_06, GPIOTE20);
415impl_gpiote_pin!(P1_07, GPIOTE20);
416impl_gpiote_pin!(P1_08, GPIOTE20);
417impl_gpiote_pin!(P1_09, GPIOTE20);
418impl_gpiote_pin!(P1_10, GPIOTE20);
419impl_gpiote_pin!(P1_11, GPIOTE20);
420impl_gpiote_pin!(P1_12, GPIOTE20);
421impl_gpiote_pin!(P1_13, GPIOTE20);
422impl_gpiote_pin!(P1_14, GPIOTE20);
423impl_gpiote_pin!(P1_15, GPIOTE20);
424impl_gpiote_pin!(P1_16, GPIOTE20);
425
333impl_pin!(P2_00, 2, 0); 426impl_pin!(P2_00, 2, 0);
334impl_pin!(P2_01, 2, 1); 427impl_pin!(P2_01, 2, 1);
335impl_pin!(P2_02, 2, 2); 428impl_pin!(P2_02, 2, 2);
@@ -351,6 +444,128 @@ impl_wdt!(WDT, WDT31, WDT31, 0);
351impl_wdt!(WDT0, WDT31, WDT31, 0); 444impl_wdt!(WDT0, WDT31, WDT31, 0);
352#[cfg(feature = "_s")] 445#[cfg(feature = "_s")]
353impl_wdt!(WDT1, WDT30, WDT30, 1); 446impl_wdt!(WDT1, WDT30, WDT30, 1);
447// DPPI00 channels
448impl_ppi_channel!(PPI00_CH0, DPPIC00, 0 => configurable);
449impl_ppi_channel!(PPI00_CH1, DPPIC00, 1 => configurable);
450impl_ppi_channel!(PPI00_CH2, DPPIC00, 2 => configurable);
451impl_ppi_channel!(PPI00_CH3, DPPIC00, 3 => configurable);
452impl_ppi_channel!(PPI00_CH4, DPPIC00, 4 => configurable);
453impl_ppi_channel!(PPI00_CH5, DPPIC00, 5 => configurable);
454impl_ppi_channel!(PPI00_CH6, DPPIC00, 6 => configurable);
455impl_ppi_channel!(PPI00_CH7, DPPIC00, 7 => configurable);
456
457// DPPI20 channels
458impl_ppi_channel!(PPI20_CH0, DPPIC20, 0 => configurable);
459impl_ppi_channel!(PPI20_CH1, DPPIC20, 1 => configurable);
460impl_ppi_channel!(PPI20_CH2, DPPIC20, 2 => configurable);
461impl_ppi_channel!(PPI20_CH3, DPPIC20, 3 => configurable);
462impl_ppi_channel!(PPI20_CH4, DPPIC20, 4 => configurable);
463impl_ppi_channel!(PPI20_CH5, DPPIC20, 5 => configurable);
464impl_ppi_channel!(PPI20_CH6, DPPIC20, 6 => configurable);
465impl_ppi_channel!(PPI20_CH7, DPPIC20, 7 => configurable);
466impl_ppi_channel!(PPI20_CH8, DPPIC20, 8 => configurable);
467impl_ppi_channel!(PPI20_CH9, DPPIC20, 9 => configurable);
468impl_ppi_channel!(PPI20_CH10, DPPIC20, 10 => configurable);
469impl_ppi_channel!(PPI20_CH11, DPPIC20, 11 => configurable);
470impl_ppi_channel!(PPI20_CH12, DPPIC20, 12 => configurable);
471impl_ppi_channel!(PPI20_CH13, DPPIC20, 13 => configurable);
472impl_ppi_channel!(PPI20_CH14, DPPIC20, 14 => configurable);
473impl_ppi_channel!(PPI20_CH15, DPPIC20, 15 => configurable);
474
475// DPPI30 channels
476impl_ppi_channel!(PPI30_CH0, DPPIC30, 0 => configurable);
477impl_ppi_channel!(PPI30_CH1, DPPIC30, 1 => configurable);
478impl_ppi_channel!(PPI30_CH2, DPPIC30, 2 => configurable);
479impl_ppi_channel!(PPI30_CH3, DPPIC30, 3 => configurable);
480
481// DPPI00 groups
482impl_ppi_group!(PPI00_GROUP0, DPPIC00, 0);
483impl_ppi_group!(PPI00_GROUP1, DPPIC00, 1);
484
485// DPPI20 groups
486impl_ppi_group!(PPI20_GROUP0, DPPIC20, 0);
487impl_ppi_group!(PPI20_GROUP1, DPPIC20, 1);
488impl_ppi_group!(PPI20_GROUP2, DPPIC20, 2);
489impl_ppi_group!(PPI20_GROUP3, DPPIC20, 3);
490impl_ppi_group!(PPI20_GROUP4, DPPIC20, 4);
491impl_ppi_group!(PPI20_GROUP5, DPPIC20, 5);
492
493// DPPI30 groups
494impl_ppi_group!(PPI30_GROUP0, DPPIC30, 0);
495impl_ppi_group!(PPI30_GROUP1, DPPIC30, 1);
496
497// impl_ppi_channel!(PPI10_CH0, pac::DPPIC10, 0 => static);
498// impl_ppi_group!(PPI10_GROUP0, pac::DPPIC10, 0);
499
500impl_timer!(TIMER00, TIMER00, TIMER00);
501impl_timer!(TIMER10, TIMER10, TIMER10);
502impl_timer!(TIMER20, TIMER20, TIMER20);
503impl_timer!(TIMER21, TIMER21, TIMER21);
504impl_timer!(TIMER22, TIMER22, TIMER22);
505impl_timer!(TIMER23, TIMER23, TIMER23);
506impl_timer!(TIMER24, TIMER24, TIMER24);
507
508impl_twim!(SERIAL20, TWIM20, SERIAL20);
509impl_twim!(SERIAL21, TWIM21, SERIAL21);
510impl_twim!(SERIAL22, TWIM22, SERIAL22);
511impl_twim!(SERIAL30, TWIM30, SERIAL30);
512
513impl_twis!(SERIAL20, TWIS20, SERIAL20);
514impl_twis!(SERIAL21, TWIS21, SERIAL21);
515impl_twis!(SERIAL22, TWIS22, SERIAL22);
516impl_twis!(SERIAL30, TWIS30, SERIAL30);
517
518impl_pwm!(PWM20, PWM20, PWM20);
519impl_pwm!(PWM21, PWM21, PWM21);
520impl_pwm!(PWM22, PWM22, PWM22);
521
522#[cfg(feature = "_s")]
523impl_spim!(
524 SERIAL00,
525 SPIM00,
526 SERIAL00,
527 match pac::OSCILLATORS_S.pll().currentfreq().read().currentfreq() {
528 pac::oscillators::vals::Currentfreq::CK128M => 128_000_000,
529 pac::oscillators::vals::Currentfreq::CK64M => 64_000_000,
530 _ => unreachable!(),
531 }
532);
533#[cfg(feature = "_ns")]
534impl_spim!(
535 SERIAL00,
536 SPIM00,
537 SERIAL00,
538 match pac::OSCILLATORS_NS.pll().currentfreq().read().currentfreq() {
539 pac::oscillators::vals::Currentfreq::CK128M => 128_000_000,
540 pac::oscillators::vals::Currentfreq::CK64M => 64_000_000,
541 _ => unreachable!(),
542 }
543);
544impl_spim!(SERIAL20, SPIM20, SERIAL20, 16_000_000);
545impl_spim!(SERIAL21, SPIM21, SERIAL21, 16_000_000);
546impl_spim!(SERIAL22, SPIM22, SERIAL22, 16_000_000);
547impl_spim!(SERIAL30, SPIM30, SERIAL30, 16_000_000);
548
549impl_spis!(SERIAL20, SPIS20, SERIAL20);
550impl_spis!(SERIAL21, SPIS21, SERIAL21);
551impl_spis!(SERIAL22, SPIS22, SERIAL22);
552impl_spis!(SERIAL30, SPIS30, SERIAL30);
553
554impl_uarte!(SERIAL00, UARTE00, SERIAL00);
555impl_uarte!(SERIAL20, UARTE20, SERIAL20);
556impl_uarte!(SERIAL21, UARTE21, SERIAL21);
557impl_uarte!(SERIAL22, UARTE22, SERIAL22);
558impl_uarte!(SERIAL30, UARTE30, SERIAL30);
559
560// NB: SAADC uses "pin" abstraction, not "AIN"
561impl_saadc_input!(P1_04, 1, 4);
562impl_saadc_input!(P1_05, 1, 5);
563impl_saadc_input!(P1_06, 1, 6);
564impl_saadc_input!(P1_07, 1, 7);
565impl_saadc_input!(P1_11, 1, 11);
566impl_saadc_input!(P1_12, 1, 12);
567impl_saadc_input!(P1_13, 1, 13);
568impl_saadc_input!(P1_14, 1, 14);
354 569
355embassy_hal_internal::interrupt_mod!( 570embassy_hal_internal::interrupt_mod!(
356 SWI00, 571 SWI00,
diff --git a/embassy-nrf/src/chips/nrf9120.rs b/embassy-nrf/src/chips/nrf9120.rs
index 5aee19d97..e9f313fef 100644
--- a/embassy-nrf/src/chips/nrf9120.rs
+++ b/embassy-nrf/src/chips/nrf9120.rs
@@ -314,22 +314,29 @@ impl_pin!(P0_29, 0, 29);
314impl_pin!(P0_30, 0, 30); 314impl_pin!(P0_30, 0, 30);
315impl_pin!(P0_31, 0, 31); 315impl_pin!(P0_31, 0, 31);
316 316
317impl_ppi_channel!(PPI_CH0, 0 => configurable); 317impl_ppi_channel!(PPI_CH0, DPPIC, 0 => configurable);
318impl_ppi_channel!(PPI_CH1, 1 => configurable); 318impl_ppi_channel!(PPI_CH1, DPPIC, 1 => configurable);
319impl_ppi_channel!(PPI_CH2, 2 => configurable); 319impl_ppi_channel!(PPI_CH2, DPPIC, 2 => configurable);
320impl_ppi_channel!(PPI_CH3, 3 => configurable); 320impl_ppi_channel!(PPI_CH3, DPPIC, 3 => configurable);
321impl_ppi_channel!(PPI_CH4, 4 => configurable); 321impl_ppi_channel!(PPI_CH4, DPPIC, 4 => configurable);
322impl_ppi_channel!(PPI_CH5, 5 => configurable); 322impl_ppi_channel!(PPI_CH5, DPPIC, 5 => configurable);
323impl_ppi_channel!(PPI_CH6, 6 => configurable); 323impl_ppi_channel!(PPI_CH6, DPPIC, 6 => configurable);
324impl_ppi_channel!(PPI_CH7, 7 => configurable); 324impl_ppi_channel!(PPI_CH7, DPPIC, 7 => configurable);
325impl_ppi_channel!(PPI_CH8, 8 => configurable); 325impl_ppi_channel!(PPI_CH8, DPPIC, 8 => configurable);
326impl_ppi_channel!(PPI_CH9, 9 => configurable); 326impl_ppi_channel!(PPI_CH9, DPPIC, 9 => configurable);
327impl_ppi_channel!(PPI_CH10, 10 => configurable); 327impl_ppi_channel!(PPI_CH10, DPPIC, 10 => configurable);
328impl_ppi_channel!(PPI_CH11, 11 => configurable); 328impl_ppi_channel!(PPI_CH11, DPPIC, 11 => configurable);
329impl_ppi_channel!(PPI_CH12, 12 => configurable); 329impl_ppi_channel!(PPI_CH12, DPPIC, 12 => configurable);
330impl_ppi_channel!(PPI_CH13, 13 => configurable); 330impl_ppi_channel!(PPI_CH13, DPPIC, 13 => configurable);
331impl_ppi_channel!(PPI_CH14, 14 => configurable); 331impl_ppi_channel!(PPI_CH14, DPPIC, 14 => configurable);
332impl_ppi_channel!(PPI_CH15, 15 => configurable); 332impl_ppi_channel!(PPI_CH15, DPPIC, 15 => configurable);
333
334impl_ppi_group!(PPI_GROUP0, DPPIC, 0);
335impl_ppi_group!(PPI_GROUP1, DPPIC, 1);
336impl_ppi_group!(PPI_GROUP2, DPPIC, 2);
337impl_ppi_group!(PPI_GROUP3, DPPIC, 3);
338impl_ppi_group!(PPI_GROUP4, DPPIC, 4);
339impl_ppi_group!(PPI_GROUP5, DPPIC, 5);
333 340
334impl_saadc_input!(P0_13, ANALOG_INPUT0); 341impl_saadc_input!(P0_13, ANALOG_INPUT0);
335impl_saadc_input!(P0_14, ANALOG_INPUT1); 342impl_saadc_input!(P0_14, ANALOG_INPUT1);
diff --git a/embassy-nrf/src/chips/nrf9160.rs b/embassy-nrf/src/chips/nrf9160.rs
index 64aec217c..4c6f055dd 100644
--- a/embassy-nrf/src/chips/nrf9160.rs
+++ b/embassy-nrf/src/chips/nrf9160.rs
@@ -314,22 +314,29 @@ impl_pin!(P0_29, 0, 29);
314impl_pin!(P0_30, 0, 30); 314impl_pin!(P0_30, 0, 30);
315impl_pin!(P0_31, 0, 31); 315impl_pin!(P0_31, 0, 31);
316 316
317impl_ppi_channel!(PPI_CH0, 0 => configurable); 317impl_ppi_channel!(PPI_CH0, DPPIC, 0 => configurable);
318impl_ppi_channel!(PPI_CH1, 1 => configurable); 318impl_ppi_channel!(PPI_CH1, DPPIC, 1 => configurable);
319impl_ppi_channel!(PPI_CH2, 2 => configurable); 319impl_ppi_channel!(PPI_CH2, DPPIC, 2 => configurable);
320impl_ppi_channel!(PPI_CH3, 3 => configurable); 320impl_ppi_channel!(PPI_CH3, DPPIC, 3 => configurable);
321impl_ppi_channel!(PPI_CH4, 4 => configurable); 321impl_ppi_channel!(PPI_CH4, DPPIC, 4 => configurable);
322impl_ppi_channel!(PPI_CH5, 5 => configurable); 322impl_ppi_channel!(PPI_CH5, DPPIC, 5 => configurable);
323impl_ppi_channel!(PPI_CH6, 6 => configurable); 323impl_ppi_channel!(PPI_CH6, DPPIC, 6 => configurable);
324impl_ppi_channel!(PPI_CH7, 7 => configurable); 324impl_ppi_channel!(PPI_CH7, DPPIC, 7 => configurable);
325impl_ppi_channel!(PPI_CH8, 8 => configurable); 325impl_ppi_channel!(PPI_CH8, DPPIC, 8 => configurable);
326impl_ppi_channel!(PPI_CH9, 9 => configurable); 326impl_ppi_channel!(PPI_CH9, DPPIC, 9 => configurable);
327impl_ppi_channel!(PPI_CH10, 10 => configurable); 327impl_ppi_channel!(PPI_CH10, DPPIC, 10 => configurable);
328impl_ppi_channel!(PPI_CH11, 11 => configurable); 328impl_ppi_channel!(PPI_CH11, DPPIC, 11 => configurable);
329impl_ppi_channel!(PPI_CH12, 12 => configurable); 329impl_ppi_channel!(PPI_CH12, DPPIC, 12 => configurable);
330impl_ppi_channel!(PPI_CH13, 13 => configurable); 330impl_ppi_channel!(PPI_CH13, DPPIC, 13 => configurable);
331impl_ppi_channel!(PPI_CH14, 14 => configurable); 331impl_ppi_channel!(PPI_CH14, DPPIC, 14 => configurable);
332impl_ppi_channel!(PPI_CH15, 15 => configurable); 332impl_ppi_channel!(PPI_CH15, DPPIC, 15 => configurable);
333
334impl_ppi_group!(PPI_GROUP0, DPPIC, 0);
335impl_ppi_group!(PPI_GROUP1, DPPIC, 1);
336impl_ppi_group!(PPI_GROUP2, DPPIC, 2);
337impl_ppi_group!(PPI_GROUP3, DPPIC, 3);
338impl_ppi_group!(PPI_GROUP4, DPPIC, 4);
339impl_ppi_group!(PPI_GROUP5, DPPIC, 5);
333 340
334impl_saadc_input!(P0_13, ANALOG_INPUT0); 341impl_saadc_input!(P0_13, ANALOG_INPUT0);
335impl_saadc_input!(P0_14, ANALOG_INPUT1); 342impl_saadc_input!(P0_14, ANALOG_INPUT1);
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs
index 7ed3a7927..43d1b9cb2 100644
--- a/embassy-nrf/src/gpio.rs
+++ b/embassy-nrf/src/gpio.rs
@@ -585,7 +585,6 @@ impl SealedPin for AnyPin {
585// ==================== 585// ====================
586 586
587#[cfg(not(feature = "_nrf51"))] 587#[cfg(not(feature = "_nrf51"))]
588#[cfg_attr(feature = "_nrf54l", allow(unused))] // TODO
589pub(crate) trait PselBits { 588pub(crate) trait PselBits {
590 fn psel_bits(&self) -> pac::shared::regs::Psel; 589 fn psel_bits(&self) -> pac::shared::regs::Psel;
591} 590}
@@ -602,7 +601,6 @@ impl<'a, P: Pin> PselBits for Option<Peri<'a, P>> {
602} 601}
603 602
604#[cfg(not(feature = "_nrf51"))] 603#[cfg(not(feature = "_nrf51"))]
605#[cfg_attr(feature = "_nrf54l", allow(unused))] // TODO
606pub(crate) const DISCONNECTED: Psel = Psel(1 << 31); 604pub(crate) const DISCONNECTED: Psel = Psel(1 << 31);
607 605
608#[cfg(not(feature = "_nrf51"))] 606#[cfg(not(feature = "_nrf51"))]
diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs
index 3658657c0..060950132 100644
--- a/embassy-nrf/src/gpiote.rs
+++ b/embassy-nrf/src/gpiote.rs
@@ -1,4 +1,5 @@
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::{Future, poll_fn}; 5use core::future::{Future, poll_fn};
@@ -7,7 +8,7 @@ use core::task::{Context, Poll};
7use embassy_hal_internal::{Peri, PeripheralType, impl_peripheral}; 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,28 @@ 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 = "_nrf54l"
37))]
27const PIN_COUNT: usize = 48; 38const PIN_COUNT: usize = 48;
28#[cfg(not(any(feature = "nrf52833", feature = "nrf52840", feature = "_nrf5340")))] 39#[cfg(not(any(
40 feature = "nrf52833",
41 feature = "nrf52840",
42 feature = "_nrf5340",
43 feature = "_nrf54l"
44)))]
29const PIN_COUNT: usize = 32; 45const PIN_COUNT: usize = 32;
30 46
31#[allow(clippy::declare_interior_mutable_const)] 47#[allow(clippy::declare_interior_mutable_const)]
@@ -54,18 +70,6 @@ pub enum OutputChannelPolarity {
54 Toggle, 70 Toggle,
55} 71}
56 72
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) { 73pub(crate) fn init(irq_prio: crate::interrupt::Priority) {
70 // no latched GPIO detect in nrf51. 74 // no latched GPIO detect in nrf51.
71 #[cfg(not(feature = "_nrf51"))] 75 #[cfg(not(feature = "_nrf51"))]
@@ -77,9 +81,9 @@ pub(crate) fn init(irq_prio: crate::interrupt::Priority) {
77 81
78 for &p in ports { 82 for &p in ports {
79 // Enable latched detection 83 // Enable latched detection
80 #[cfg(feature = "_s")] 84 #[cfg(all(feature = "_s", not(feature = "_nrf54l")))]
81 p.detectmode_sec().write(|w| w.set_detectmode(Detectmode::LDETECT)); 85 p.detectmode_sec().write(|w| w.set_detectmode(Detectmode::LDETECT));
82 #[cfg(not(feature = "_s"))] 86 #[cfg(any(not(feature = "_s"), all(feature = "_s", feature = "_nrf54l")))]
83 p.detectmode().write(|w| w.set_detectmode(Detectmode::LDETECT)); 87 p.detectmode().write(|w| w.set_detectmode(Detectmode::LDETECT));
84 // Clear latch 88 // Clear latch
85 p.latch().write(|w| w.0 = 0xFFFFFFFF) 89 p.latch().write(|w| w.0 = 0xFFFFFFFF)
@@ -88,57 +92,136 @@ pub(crate) fn init(irq_prio: crate::interrupt::Priority) {
88 92
89 // Enable interrupts 93 // Enable interrupts
90 #[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s", feature = "nrf9120-s"))] 94 #[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s", feature = "nrf9120-s"))]
91 let irq = interrupt::GPIOTE0; 95 let irqs = &[(pac::GPIOTE0, interrupt::GPIOTE0)];
92 #[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns", feature = "nrf9120-ns"))] 96 #[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns", feature = "nrf9120-ns"))]
93 let irq = interrupt::GPIOTE1; 97 let irqs = &[(pac::GPIOTE1, interrupt::GPIOTE1)];
94 #[cfg(any(feature = "_nrf51", feature = "_nrf52", feature = "nrf5340-net"))] 98 #[cfg(any(feature = "_nrf51", feature = "_nrf52", feature = "nrf5340-net"))]
95 let irq = interrupt::GPIOTE; 99 let irqs = &[(pac::GPIOTE, interrupt::GPIOTE)];
100 #[cfg(any(feature = "_nrf54l"))]
101 let irqs = &[
102 #[cfg(feature = "_s")]
103 (pac::GPIOTE20, interrupt::GPIOTE20_0),
104 #[cfg(feature = "_s")]
105 (pac::GPIOTE30, interrupt::GPIOTE30_0),
106 #[cfg(feature = "_ns")]
107 (pac::GPIOTE20, interrupt::GPIOTE20_1),
108 #[cfg(feature = "_ns")]
109 (pac::GPIOTE30, interrupt::GPIOTE30_1),
110 ];
111
112 for (inst, irq) in irqs {
113 irq.unpend();
114 irq.set_priority(irq_prio);
115 unsafe { irq.enable() };
96 116
97 irq.unpend(); 117 let g = inst;
98 irq.set_priority(irq_prio); 118 #[cfg(not(feature = "_nrf54l"))]
99 unsafe { irq.enable() }; 119 g.intenset(INTNUM).write(|w| w.set_port(true));
100 120
101 let g = regs(); 121 #[cfg(all(feature = "_nrf54l", feature = "_ns"))]
102 g.intenset().write(|w| w.set_port(true)); 122 g.intenset(INTNUM).write(|w| w.set_port0nonsecure(true));
123
124 #[cfg(all(feature = "_nrf54l", feature = "_s"))]
125 g.intenset(INTNUM).write(|w| w.set_port0secure(true));
126 }
103} 127}
104 128
129#[cfg(all(feature = "_nrf54l", feature = "_ns"))]
130const INTNUM: usize = 1;
131
132#[cfg(any(not(feature = "_nrf54l"), feature = "_s"))]
133const INTNUM: usize = 0;
134
105#[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s", feature = "nrf9120-s"))] 135#[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s", feature = "nrf9120-s"))]
106#[cfg(feature = "rt")] 136#[cfg(feature = "rt")]
107#[interrupt] 137#[interrupt]
108fn GPIOTE0() { 138fn GPIOTE0() {
109 unsafe { handle_gpiote_interrupt() }; 139 unsafe { handle_gpiote_interrupt(pac::GPIOTE0) };
110} 140}
111 141
112#[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns", feature = "nrf9120-ns"))] 142#[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns", feature = "nrf9120-ns"))]
113#[cfg(feature = "rt")] 143#[cfg(feature = "rt")]
114#[interrupt] 144#[interrupt]
115fn GPIOTE1() { 145fn GPIOTE1() {
116 unsafe { handle_gpiote_interrupt() }; 146 unsafe { handle_gpiote_interrupt(pac::GPIOTE1) };
117} 147}
118 148
119#[cfg(any(feature = "_nrf51", feature = "_nrf52", feature = "nrf5340-net"))] 149#[cfg(any(feature = "_nrf51", feature = "_nrf52", feature = "nrf5340-net"))]
120#[cfg(feature = "rt")] 150#[cfg(feature = "rt")]
121#[interrupt] 151#[interrupt]
122fn GPIOTE() { 152fn GPIOTE() {
123 unsafe { handle_gpiote_interrupt() }; 153 info!("GPIOTE!");
154 unsafe { handle_gpiote_interrupt(pac::GPIOTE) };
124} 155}
125 156
126unsafe fn handle_gpiote_interrupt() { 157#[cfg(all(feature = "_nrf54l", feature = "_s"))]
127 let g = regs(); 158#[cfg(feature = "rt")]
159#[interrupt]
160fn GPIOTE20_0() {
161 info!("GPIOTE20_0!");
162 unsafe { handle_gpiote_interrupt(pac::GPIOTE20) };
163}
128 164
129 for i in 0..CHANNEL_COUNT { 165#[cfg(all(feature = "_nrf54l", feature = "_s"))]
166#[cfg(feature = "rt")]
167#[interrupt]
168fn GPIOTE30_0() {
169 info!("GPIOTE30_0!");
170 unsafe { handle_gpiote_interrupt(pac::GPIOTE30) };
171}
172
173#[cfg(all(feature = "_nrf54l", feature = "_ns"))]
174#[cfg(feature = "rt")]
175#[interrupt]
176fn GPIOTE20_1() {
177 info!("GPIOTE20_1!");
178 unsafe { handle_gpiote_interrupt(pac::GPIOTE20) };
179}
180
181#[cfg(all(feature = "_nrf54l", feature = "_ns"))]
182#[cfg(feature = "rt")]
183#[interrupt]
184fn GPIOTE30_1() {
185 info!("GPIOTE30_1!");
186 unsafe { handle_gpiote_interrupt(pac::GPIOTE30) };
187}
188
189unsafe fn handle_gpiote_interrupt(g: pac::gpiote::Gpiote) {
190 for c in 0..CHANNEL_COUNT {
191 let i = c % CHANNELS_PER_PORT;
130 if g.events_in(i).read() != 0 { 192 if g.events_in(i).read() != 0 {
131 g.intenclr().write(|w| w.0 = 1 << i); 193 info!("Clear IRQ {} waker {}", INTNUM, c);
132 CHANNEL_WAKERS[i].wake(); 194 g.intenclr(INTNUM).write(|w| w.0 = 1 << i);
195 CHANNEL_WAKERS[c].wake();
133 } 196 }
134 } 197 }
135 198
136 if g.events_port().read() != 0 { 199 #[cfg(not(feature = "_nrf54l"))]
137 g.events_port().write_value(0); 200 let eport = g.events_port(0);
138 201
139 #[cfg(any(feature = "nrf52833", feature = "nrf52840", feature = "_nrf5340"))] 202 #[cfg(all(feature = "_nrf54l", feature = "_ns"))]
203 let eport = g.events_port(0).nonsecure();
204
205 #[cfg(all(feature = "_nrf54l", feature = "_s"))]
206 let eport = g.events_port(0).secure();
207
208 if eport.read() != 0 {
209 eport.write_value(0);
210
211 #[cfg(any(
212 feature = "nrf52833",
213 feature = "nrf52840",
214 feature = "_nrf5340",
215 feature = "_nrf54l"
216 ))]
140 let ports = &[pac::P0, pac::P1]; 217 let ports = &[pac::P0, pac::P1];
141 #[cfg(not(any(feature = "_nrf51", feature = "nrf52833", feature = "nrf52840", feature = "_nrf5340")))] 218 #[cfg(not(any(
219 feature = "_nrf51",
220 feature = "nrf52833",
221 feature = "nrf52840",
222 feature = "_nrf5340",
223 feature = "_nrf54l"
224 )))]
142 let ports = &[pac::P0]; 225 let ports = &[pac::P0];
143 #[cfg(feature = "_nrf51")] 226 #[cfg(feature = "_nrf51")]
144 let ports = &[pac::GPIO]; 227 let ports = &[pac::GPIO];
@@ -162,9 +245,14 @@ unsafe fn handle_gpiote_interrupt() {
162 245
163 #[cfg(not(feature = "_nrf51"))] 246 #[cfg(not(feature = "_nrf51"))]
164 for (port, &p) in ports.iter().enumerate() { 247 for (port, &p) in ports.iter().enumerate() {
248 info!("Interrupt port {}", port);
165 let bits = p.latch().read().0; 249 let bits = p.latch().read().0;
166 for pin in BitIter(bits) { 250 for pin in BitIter(bits) {
167 p.pin_cnf(pin as usize).modify(|w| w.set_sense(Sense::DISABLED)); 251 p.pin_cnf(pin as usize).modify(|w| w.set_sense(Sense::DISABLED));
252
253 let w = port * 32 + pin as usize;
254
255 info!("Interrupt pin {}, waker {}", pin as usize, w);
168 PORT_WAKERS[port * 32 + pin as usize].wake(); 256 PORT_WAKERS[port * 32 + pin as usize].wake();
169 } 257 }
170 p.latch().write(|w| w.0 = bits); 258 p.latch().write(|w| w.0 = bits);
@@ -207,19 +295,43 @@ impl InputChannel<'static> {
207 295
208impl<'d> Drop for InputChannel<'d> { 296impl<'d> Drop for InputChannel<'d> {
209 fn drop(&mut self) { 297 fn drop(&mut self) {
210 let g = regs(); 298 let g = self.ch.regs();
211 let num = self.ch.number(); 299 let num = self.ch.number();
212 g.config(num).write(|w| w.set_mode(Mode::DISABLED)); 300 g.config(num).write(|w| w.set_mode(Mode::DISABLED));
213 g.intenclr().write(|w| w.0 = 1 << num); 301 g.intenclr(INTNUM).write(|w| w.0 = 1 << num);
214 } 302 }
215} 303}
216 304
217impl<'d> InputChannel<'d> { 305impl<'d> InputChannel<'d> {
218 /// Create a new GPIOTE input channel driver. 306 /// Create a new GPIOTE input channel driver.
219 pub fn new(ch: Peri<'d, impl Channel>, pin: Input<'d>, polarity: InputChannelPolarity) -> Self { 307 #[cfg(feature = "_nrf54l")]
220 let g = regs(); 308 pub fn new<C: Channel, T: GpiotePin<Instance = C::Instance>>(
221 let num = ch.number(); 309 ch: Peri<'d, C>,
310 pin: Peri<'d, T>,
311 pull: Pull,
312 polarity: InputChannelPolarity,
313 ) -> Self {
314 let pin = Input::new(pin, pull);
315 let ch = ch.into();
316 Self::new_inner(ch, pin, polarity)
317 }
222 318
319 /// Create a new GPIOTE output channel driver.
320 #[cfg(not(feature = "_nrf54l"))]
321 pub fn new<C: Channel, T: GpioPin>(
322 ch: Peri<'d, C>,
323 pin: Peri<'d, T>,
324 pull: Pull,
325 polarity: InputChannelPolarity,
326 ) -> Self {
327 let pin = Input::new(pin, pull);
328 let ch = ch.into();
329 Self::new_inner(ch, pin, polarity)
330 }
331
332 fn new_inner(ch: Peri<'d, AnyChannel>, pin: Input<'d>, polarity: InputChannelPolarity) -> Self {
333 let g = ch.regs();
334 let num = ch.number();
223 g.config(num).write(|w| { 335 g.config(num).write(|w| {
224 w.set_mode(Mode::EVENT); 336 w.set_mode(Mode::EVENT);
225 match polarity { 337 match polarity {
@@ -228,30 +340,38 @@ impl<'d> InputChannel<'d> {
228 InputChannelPolarity::None => w.set_polarity(Polarity::NONE), 340 InputChannelPolarity::None => w.set_polarity(Polarity::NONE),
229 InputChannelPolarity::Toggle => w.set_polarity(Polarity::TOGGLE), 341 InputChannelPolarity::Toggle => w.set_polarity(Polarity::TOGGLE),
230 }; 342 };
231 #[cfg(any(feature = "nrf52833", feature = "nrf52840", feature = "_nrf5340"))] 343 #[cfg(any(feature = "nrf52833", feature = "nrf52840", feature = "_nrf5340",))]
232 w.set_port(match pin.pin.pin.port() { 344 w.set_port(match pin.pin.pin.port() {
233 crate::gpio::Port::Port0 => false, 345 crate::gpio::Port::Port0 => false,
234 crate::gpio::Port::Port1 => true, 346 crate::gpio::Port::Port1 => true,
235 }); 347 });
348 #[cfg(any(feature = "_nrf54l"))]
349 w.set_port(match pin.pin.pin.port() {
350 crate::gpio::Port::Port0 => 0,
351 crate::gpio::Port::Port1 => 1,
352 crate::gpio::Port::Port2 => 2,
353 });
236 w.set_psel(pin.pin.pin.pin()); 354 w.set_psel(pin.pin.pin.pin());
237 }); 355 });
238 356
239 g.events_in(num).write_value(0); 357 g.events_in(num).write_value(0);
240 358
241 InputChannel { ch: ch.into(), pin } 359 InputChannel { ch, pin }
242 } 360 }
243 361
244 /// Asynchronously wait for an event in this channel. 362 /// Asynchronously wait for an event in this channel.
245 pub async fn wait(&self) { 363 pub async fn wait(&self) {
246 let g = regs(); 364 let g = self.ch.regs();
247 let num = self.ch.number(); 365 let num = self.ch.number();
366 let waker = self.ch.waker();
248 367
249 // Enable interrupt 368 // Enable interrupt
250 g.events_in(num).write_value(0); 369 g.events_in(num).write_value(0);
251 g.intenset().write(|w| w.0 = 1 << num); 370 g.intenset(INTNUM).write(|w| w.0 = 1 << num);
252 371
253 poll_fn(|cx| { 372 poll_fn(|cx| {
254 CHANNEL_WAKERS[num].register(cx.waker()); 373 info!("Waiting for channel waker {}", num);
374 CHANNEL_WAKERS[waker].register(cx.waker());
255 375
256 if g.events_in(num).read() != 0 { 376 if g.events_in(num).read() != 0 {
257 Poll::Ready(()) 377 Poll::Ready(())
@@ -269,7 +389,7 @@ impl<'d> InputChannel<'d> {
269 389
270 /// Returns the IN event, for use with PPI. 390 /// Returns the IN event, for use with PPI.
271 pub fn event_in(&self) -> Event<'d> { 391 pub fn event_in(&self) -> Event<'d> {
272 let g = regs(); 392 let g = self.ch.regs();
273 Event::from_reg(g.events_in(self.ch.number())) 393 Event::from_reg(g.events_in(self.ch.number()))
274 } 394 }
275} 395}
@@ -291,17 +411,44 @@ impl OutputChannel<'static> {
291 411
292impl<'d> Drop for OutputChannel<'d> { 412impl<'d> Drop for OutputChannel<'d> {
293 fn drop(&mut self) { 413 fn drop(&mut self) {
294 let g = regs(); 414 let g = self.ch.regs();
295 let num = self.ch.number(); 415 let num = self.ch.number();
296 g.config(num).write(|w| w.set_mode(Mode::DISABLED)); 416 g.config(num).write(|w| w.set_mode(Mode::DISABLED));
297 g.intenclr().write(|w| w.0 = 1 << num); 417 g.intenclr(INTNUM).write(|w| w.0 = 1 << num);
298 } 418 }
299} 419}
300 420
301impl<'d> OutputChannel<'d> { 421impl<'d> OutputChannel<'d> {
302 /// Create a new GPIOTE output channel driver. 422 /// Create a new GPIOTE output channel driver.
303 pub fn new(ch: Peri<'d, impl Channel>, pin: Output<'d>, polarity: OutputChannelPolarity) -> Self { 423 #[cfg(feature = "_nrf54l")]
304 let g = regs(); 424 pub fn new<C: Channel, T: GpiotePin<Instance = C::Instance>>(
425 ch: Peri<'d, C>,
426 pin: Peri<'d, T>,
427 initial_output: Level,
428 drive: OutputDrive,
429 polarity: OutputChannelPolarity,
430 ) -> Self {
431 let pin = Output::new(pin, initial_output, drive);
432 let ch = ch.into();
433 Self::new_inner(ch, pin, polarity)
434 }
435
436 /// Create a new GPIOTE output channel driver.
437 #[cfg(not(feature = "_nrf54l"))]
438 pub fn new<C: Channel, T: GpioPin>(
439 ch: Peri<'d, C>,
440 pin: Peri<'d, T>,
441 initial_output: Level,
442 drive: OutputDrive,
443 polarity: OutputChannelPolarity,
444 ) -> Self {
445 let pin = Output::new(pin, initial_output, drive);
446 let ch = ch.into();
447 Self::new_inner(ch, pin, polarity)
448 }
449
450 fn new_inner(ch: Peri<'d, AnyChannel>, pin: Output<'d>, polarity: OutputChannelPolarity) -> Self {
451 let g = ch.regs();
305 let num = ch.number(); 452 let num = ch.number();
306 453
307 g.config(num).write(|w| { 454 g.config(num).write(|w| {
@@ -320,52 +467,55 @@ impl<'d> OutputChannel<'d> {
320 crate::gpio::Port::Port0 => false, 467 crate::gpio::Port::Port0 => false,
321 crate::gpio::Port::Port1 => true, 468 crate::gpio::Port::Port1 => true,
322 }); 469 });
470 #[cfg(any(feature = "_nrf54l"))]
471 w.set_port(match pin.pin.pin.port() {
472 crate::gpio::Port::Port0 => 0,
473 crate::gpio::Port::Port1 => 1,
474 crate::gpio::Port::Port2 => 2,
475 });
323 w.set_psel(pin.pin.pin.pin()); 476 w.set_psel(pin.pin.pin.pin());
324 }); 477 });
325 478
326 OutputChannel { 479 OutputChannel { ch, _pin: pin }
327 ch: ch.into(),
328 _pin: pin,
329 }
330 } 480 }
331 481
332 /// Triggers the OUT task (does the action as configured with task_out_polarity, defaults to Toggle). 482 /// Triggers the OUT task (does the action as configured with task_out_polarity, defaults to Toggle).
333 pub fn out(&self) { 483 pub fn out(&self) {
334 let g = regs(); 484 let g = self.ch.regs();
335 g.tasks_out(self.ch.number()).write_value(1); 485 g.tasks_out(self.ch.number()).write_value(1);
336 } 486 }
337 487
338 /// Triggers the SET task (set associated pin high). 488 /// Triggers the SET task (set associated pin high).
339 #[cfg(not(feature = "_nrf51"))] 489 #[cfg(not(feature = "_nrf51"))]
340 pub fn set(&self) { 490 pub fn set(&self) {
341 let g = regs(); 491 let g = self.ch.regs();
342 g.tasks_set(self.ch.number()).write_value(1); 492 g.tasks_set(self.ch.number()).write_value(1);
343 } 493 }
344 494
345 /// Triggers the CLEAR task (set associated pin low). 495 /// Triggers the CLEAR task (set associated pin low).
346 #[cfg(not(feature = "_nrf51"))] 496 #[cfg(not(feature = "_nrf51"))]
347 pub fn clear(&self) { 497 pub fn clear(&self) {
348 let g = regs(); 498 let g = self.ch.regs();
349 g.tasks_clr(self.ch.number()).write_value(1); 499 g.tasks_clr(self.ch.number()).write_value(1);
350 } 500 }
351 501
352 /// Returns the OUT task, for use with PPI. 502 /// Returns the OUT task, for use with PPI.
353 pub fn task_out(&self) -> Task<'d> { 503 pub fn task_out(&self) -> Task<'d> {
354 let g = regs(); 504 let g = self.ch.regs();
355 Task::from_reg(g.tasks_out(self.ch.number())) 505 Task::from_reg(g.tasks_out(self.ch.number()))
356 } 506 }
357 507
358 /// Returns the CLR task, for use with PPI. 508 /// Returns the CLR task, for use with PPI.
359 #[cfg(not(feature = "_nrf51"))] 509 #[cfg(not(feature = "_nrf51"))]
360 pub fn task_clr(&self) -> Task<'d> { 510 pub fn task_clr(&self) -> Task<'d> {
361 let g = regs(); 511 let g = self.ch.regs();
362 Task::from_reg(g.tasks_clr(self.ch.number())) 512 Task::from_reg(g.tasks_clr(self.ch.number()))
363 } 513 }
364 514
365 /// Returns the SET task, for use with PPI. 515 /// Returns the SET task, for use with PPI.
366 #[cfg(not(feature = "_nrf51"))] 516 #[cfg(not(feature = "_nrf51"))]
367 pub fn task_set(&self) -> Task<'d> { 517 pub fn task_set(&self) -> Task<'d> {
368 let g = regs(); 518 let g = self.ch.regs();
369 Task::from_reg(g.tasks_set(self.ch.number())) 519 Task::from_reg(g.tasks_set(self.ch.number()))
370 } 520 }
371} 521}
@@ -395,6 +545,7 @@ impl<'a> Future for PortInputFuture<'a> {
395 type Output = (); 545 type Output = ();
396 546
397 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 547 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
548 info!("register waker on {}", self.pin.port() as usize);
398 PORT_WAKERS[self.pin.pin_port() as usize].register(cx.waker()); 549 PORT_WAKERS[self.pin.pin_port() as usize].register(cx.waker());
399 550
400 if self.pin.conf().read().sense() == Sense::DISABLED { 551 if self.pin.conf().read().sense() == Sense::DISABLED {
@@ -467,31 +618,52 @@ impl<'d> Flex<'d> {
467 PortInputFuture::new(self.pin.reborrow()).await 618 PortInputFuture::new(self.pin.reborrow()).await
468 } 619 }
469} 620}
470
471// ======================= 621// =======================
622//
472 623
473trait SealedChannel {} 624trait SealedChannel {
625 fn waker(&self) -> usize;
626 fn regs(&self) -> pac::gpiote::Gpiote;
627}
474 628
475/// GPIOTE channel trait. 629/// GPIOTE channel trait.
476/// 630///
477/// Implemented by all GPIOTE channels. 631/// Implemented by all GPIOTE channels.
478#[allow(private_bounds)] 632#[allow(private_bounds)]
479pub trait Channel: PeripheralType + SealedChannel + Into<AnyChannel> + Sized + 'static { 633pub trait Channel: PeripheralType + SealedChannel + Into<AnyChannel> + Sized + 'static {
634 #[cfg(feature = "_nrf54l")]
635 /// GPIOTE instance this channel belongs to.
636 type Instance: GpioteInstance;
480 /// Get the channel number. 637 /// Get the channel number.
481 fn number(&self) -> usize; 638 fn number(&self) -> usize;
482} 639}
483 640
484/// Type-erased channel. 641struct AnyChannel {
485///
486/// Obtained by calling `Channel::into()`.
487///
488/// This allows using several channels in situations that might require
489/// them to be the same type, like putting them in an array.
490pub struct AnyChannel {
491 number: u8, 642 number: u8,
643 regs: pac::gpiote::Gpiote,
644 waker: u8,
492} 645}
646
493impl_peripheral!(AnyChannel); 647impl_peripheral!(AnyChannel);
494impl SealedChannel for AnyChannel {} 648
649impl SealedChannel for AnyChannel {
650 fn waker(&self) -> usize {
651 self.waker as usize
652 }
653
654 fn regs(&self) -> pac::gpiote::Gpiote {
655 self.regs
656 }
657}
658
659#[cfg(feature = "_nrf54l")]
660impl AnyChannel {
661 fn number(&self) -> usize {
662 self.number as usize
663 }
664}
665
666#[cfg(not(feature = "_nrf54l"))]
495impl Channel for AnyChannel { 667impl Channel for AnyChannel {
496 fn number(&self) -> usize { 668 fn number(&self) -> usize {
497 self.number as usize 669 self.number as usize
@@ -499,9 +671,19 @@ impl Channel for AnyChannel {
499} 671}
500 672
501macro_rules! impl_channel { 673macro_rules! impl_channel {
502 ($type:ident, $number:expr) => { 674 ($type:ident, $inst:ident, $number:expr, $waker:expr) => {
503 impl SealedChannel for peripherals::$type {} 675 impl SealedChannel for peripherals::$type {
676 fn waker(&self) -> usize {
677 $waker as usize
678 }
679
680 fn regs(&self) -> pac::gpiote::Gpiote {
681 pac::$inst
682 }
683 }
504 impl Channel for peripherals::$type { 684 impl Channel for peripherals::$type {
685 #[cfg(feature = "_nrf54l")]
686 type Instance = peripherals::$inst;
505 fn number(&self) -> usize { 687 fn number(&self) -> usize {
506 $number as usize 688 $number as usize
507 } 689 }
@@ -511,24 +693,97 @@ macro_rules! impl_channel {
511 fn from(val: peripherals::$type) -> Self { 693 fn from(val: peripherals::$type) -> Self {
512 Self { 694 Self {
513 number: val.number() as u8, 695 number: val.number() as u8,
696 waker: val.waker() as u8,
697 regs: val.regs(),
514 } 698 }
515 } 699 }
516 } 700 }
517 }; 701 };
518} 702}
519 703
520impl_channel!(GPIOTE_CH0, 0); 704cfg_if::cfg_if! {
521impl_channel!(GPIOTE_CH1, 1); 705 if #[cfg(feature = "_nrf54l")] {
522impl_channel!(GPIOTE_CH2, 2); 706 trait SealedGpioteInstance {}
523impl_channel!(GPIOTE_CH3, 3); 707 /// Represents a GPIOTE instance.
524#[cfg(not(feature = "_nrf51"))] 708 #[allow(private_bounds)]
525impl_channel!(GPIOTE_CH4, 4); 709 pub trait GpioteInstance: PeripheralType + SealedGpioteInstance + Sized + 'static {}
526#[cfg(not(feature = "_nrf51"))] 710
527impl_channel!(GPIOTE_CH5, 5); 711 macro_rules! impl_gpiote {
528#[cfg(not(feature = "_nrf51"))] 712 ($type:ident) => {
529impl_channel!(GPIOTE_CH6, 6); 713 impl SealedGpioteInstance for peripherals::$type {}
530#[cfg(not(feature = "_nrf51"))] 714 impl GpioteInstance for peripherals::$type {}
531impl_channel!(GPIOTE_CH7, 7); 715 };
716 }
717
718 pub(crate) trait SealedGpiotePin {}
719
720 /// Represents a GPIO pin that can be used with GPIOTE.
721 #[allow(private_bounds)]
722 pub trait GpiotePin: GpioPin + SealedGpiotePin {
723 /// The GPIOTE instance this pin belongs to.
724 type Instance: GpioteInstance;
725 }
726
727 macro_rules! impl_gpiote_pin {
728 ($type:ident, $inst:ident) => {
729 #[cfg(feature = "gpiote")]
730 impl crate::gpiote::SealedGpiotePin for peripherals::$type {}
731 #[cfg(feature = "gpiote")]
732 impl crate::gpiote::GpiotePin for peripherals::$type {
733 type Instance = peripherals::$inst;
734 }
735 };
736 }
737
738 impl_gpiote!(GPIOTE20);
739 impl_gpiote!(GPIOTE30);
740 impl_channel!(GPIOTE20_CH0, GPIOTE20, 0, 0);
741 impl_channel!(GPIOTE20_CH1, GPIOTE20, 1, 1);
742 impl_channel!(GPIOTE20_CH2, GPIOTE20, 2, 2);
743 impl_channel!(GPIOTE20_CH3, GPIOTE20, 3, 3);
744 impl_channel!(GPIOTE20_CH4, GPIOTE20, 4, 4);
745 impl_channel!(GPIOTE20_CH5, GPIOTE20, 5, 5);
746 impl_channel!(GPIOTE20_CH6, GPIOTE20, 6, 6);
747 impl_channel!(GPIOTE20_CH7, GPIOTE20, 7, 7);
748
749 impl_channel!(GPIOTE30_CH0, GPIOTE30, 0, 8);
750 impl_channel!(GPIOTE30_CH1, GPIOTE30, 1, 9);
751 impl_channel!(GPIOTE30_CH2, GPIOTE30, 2, 10);
752 impl_channel!(GPIOTE30_CH3, GPIOTE30, 3, 11);
753 } else if #[cfg(feature = "_nrf51")] {
754 impl_channel!(GPIOTE_CH0, GPIOTE, 0, 0);
755 impl_channel!(GPIOTE_CH1, GPIOTE, 1, 1);
756 impl_channel!(GPIOTE_CH2, GPIOTE, 2, 2);
757 impl_channel!(GPIOTE_CH3, GPIOTE, 3, 3);
758 } else if #[cfg(all(feature = "_s", any(feature = "_nrf91", feature = "_nrf5340")))] {
759 impl_channel!(GPIOTE_CH0, GPIOTE0, 0, 0);
760 impl_channel!(GPIOTE_CH1, GPIOTE0, 1, 1);
761 impl_channel!(GPIOTE_CH2, GPIOTE0, 2, 2);
762 impl_channel!(GPIOTE_CH3, GPIOTE0, 3, 3);
763 impl_channel!(GPIOTE_CH4, GPIOTE0, 4, 4);
764 impl_channel!(GPIOTE_CH5, GPIOTE0, 5, 5);
765 impl_channel!(GPIOTE_CH6, GPIOTE0, 6, 6);
766 impl_channel!(GPIOTE_CH7, GPIOTE0, 7, 7);
767 } else if #[cfg(all(feature = "_ns", any(feature = "_nrf91", feature = "_nrf5340")))] {
768 impl_channel!(GPIOTE_CH0, GPIOTE1, 0, 0);
769 impl_channel!(GPIOTE_CH1, GPIOTE1, 1, 1);
770 impl_channel!(GPIOTE_CH2, GPIOTE1, 2, 2);
771 impl_channel!(GPIOTE_CH3, GPIOTE1, 3, 3);
772 impl_channel!(GPIOTE_CH4, GPIOTE1, 4, 4);
773 impl_channel!(GPIOTE_CH5, GPIOTE1, 5, 5);
774 impl_channel!(GPIOTE_CH6, GPIOTE1, 6, 6);
775 impl_channel!(GPIOTE_CH7, GPIOTE1, 7, 7);
776 } else {
777 impl_channel!(GPIOTE_CH0, GPIOTE, 0, 0);
778 impl_channel!(GPIOTE_CH1, GPIOTE, 1, 1);
779 impl_channel!(GPIOTE_CH2, GPIOTE, 2, 2);
780 impl_channel!(GPIOTE_CH3, GPIOTE, 3, 3);
781 impl_channel!(GPIOTE_CH4, GPIOTE, 4, 4);
782 impl_channel!(GPIOTE_CH5, GPIOTE, 5, 5);
783 impl_channel!(GPIOTE_CH6, GPIOTE, 6, 6);
784 impl_channel!(GPIOTE_CH7, GPIOTE, 7, 7);
785 }
786}
532 787
533// ==================== 788// ====================
534 789
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 705c77453..2f7505746 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -76,14 +76,12 @@ pub(crate) mod util;
76#[cfg(feature = "_time-driver")] 76#[cfg(feature = "_time-driver")]
77mod time_driver; 77mod time_driver;
78 78
79#[cfg(not(feature = "_nrf54l"))] // TODO
80#[cfg(not(feature = "_nrf51"))] 79#[cfg(not(feature = "_nrf51"))]
81pub mod buffered_uarte; 80pub mod buffered_uarte;
82#[cfg(not(feature = "_nrf54l"))] // TODO 81#[cfg(not(feature = "_nrf54l"))] // TODO
83#[cfg(not(feature = "_nrf51"))] 82#[cfg(not(feature = "_nrf51"))]
84pub mod egu; 83pub mod egu;
85pub mod gpio; 84pub mod gpio;
86#[cfg(not(feature = "_nrf54l"))] // TODO
87#[cfg(feature = "gpiote")] 85#[cfg(feature = "gpiote")]
88pub mod gpiote; 86pub mod gpiote;
89#[cfg(not(feature = "_nrf54l"))] // TODO 87#[cfg(not(feature = "_nrf54l"))] // TODO
@@ -119,9 +117,7 @@ pub mod pdm;
119#[cfg(not(feature = "_nrf54l"))] // TODO 117#[cfg(not(feature = "_nrf54l"))] // TODO
120#[cfg(any(feature = "nrf52840", feature = "nrf9160-s", feature = "nrf9160-ns"))] 118#[cfg(any(feature = "nrf52840", feature = "nrf9160-s", feature = "nrf9160-ns"))]
121pub mod power; 119pub mod power;
122#[cfg(not(feature = "_nrf54l"))] // TODO
123pub mod ppi; 120pub mod ppi;
124#[cfg(not(feature = "_nrf54l"))] // TODO
125#[cfg(not(any( 121#[cfg(not(any(
126 feature = "_nrf51", 122 feature = "_nrf51",
127 feature = "nrf52805", 123 feature = "nrf52805",
@@ -156,26 +152,19 @@ pub mod reset;
156#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf91")))] 152#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf91")))]
157pub mod rng; 153pub mod rng;
158pub mod rtc; 154pub mod rtc;
159#[cfg(not(feature = "_nrf54l"))] // TODO
160#[cfg(not(any(feature = "_nrf51", feature = "nrf52820", feature = "_nrf5340-net")))] 155#[cfg(not(any(feature = "_nrf51", feature = "nrf52820", feature = "_nrf5340-net")))]
161pub mod saadc; 156pub mod saadc;
162#[cfg(not(feature = "_nrf54l"))] // TODO
163#[cfg(not(feature = "_nrf51"))] 157#[cfg(not(feature = "_nrf51"))]
164pub mod spim; 158pub mod spim;
165#[cfg(not(feature = "_nrf54l"))] // TODO
166#[cfg(not(feature = "_nrf51"))] 159#[cfg(not(feature = "_nrf51"))]
167pub mod spis; 160pub mod spis;
168#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf91")))] 161#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf91")))]
169pub mod temp; 162pub mod temp;
170#[cfg(not(feature = "_nrf54l"))] // TODO
171pub mod timer; 163pub mod timer;
172#[cfg(not(feature = "_nrf54l"))] // TODO
173#[cfg(not(feature = "_nrf51"))] 164#[cfg(not(feature = "_nrf51"))]
174pub mod twim; 165pub mod twim;
175#[cfg(not(feature = "_nrf54l"))] // TODO
176#[cfg(not(feature = "_nrf51"))] 166#[cfg(not(feature = "_nrf51"))]
177pub mod twis; 167pub mod twis;
178#[cfg(not(feature = "_nrf54l"))] // TODO
179#[cfg(not(feature = "_nrf51"))] 168#[cfg(not(feature = "_nrf51"))]
180pub mod uarte; 169pub mod uarte;
181#[cfg(not(feature = "_nrf54l"))] // TODO 170#[cfg(not(feature = "_nrf54l"))] // TODO
@@ -1153,7 +1142,6 @@ pub fn init(config: config::Config) -> Peripherals {
1153 } 1142 }
1154 1143
1155 // Init GPIOTE 1144 // Init GPIOTE
1156 #[cfg(not(feature = "_nrf54l"))] // TODO
1157 #[cfg(feature = "gpiote")] 1145 #[cfg(feature = "gpiote")]
1158 gpiote::init(config.gpiote_interrupt_priority); 1146 gpiote::init(config.gpiote_interrupt_priority);
1159 1147
diff --git a/embassy-nrf/src/ppi/dppi.rs b/embassy-nrf/src/ppi/dppi.rs
index 168647be3..d43a25c4e 100644
--- a/embassy-nrf/src/ppi/dppi.rs
+++ b/embassy-nrf/src/ppi/dppi.rs
@@ -1,11 +1,12 @@
1use super::{Channel, ConfigurableChannel, Event, Ppi, Task}; 1use super::{Channel, ConfigurableChannel, Event, Ppi, Task};
2use crate::{Peri, pac}; 2use crate::Peri;
3 3
4const DPPI_ENABLE_BIT: u32 = 0x8000_0000; 4const DPPI_ENABLE_BIT: u32 = 0x8000_0000;
5const DPPI_CHANNEL_MASK: u32 = 0x0000_00FF; 5const DPPI_CHANNEL_MASK: u32 = 0x0000_00FF;
6 6
7pub(crate) fn regs() -> pac::dppic::Dppic { 7#[cfg(not(feature = "_nrf54l"))]
8 pac::DPPIC 8pub(crate) fn regs() -> crate::pac::dppic::Dppic {
9 crate::pac::DPPIC
9} 10}
10 11
11impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> { 12impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> {
@@ -49,13 +50,13 @@ impl<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> Ppi<'d,
49 /// Enables the channel. 50 /// Enables the channel.
50 pub fn enable(&mut self) { 51 pub fn enable(&mut self) {
51 let n = self.ch.number(); 52 let n = self.ch.number();
52 regs().chenset().write(|w| w.0 = 1 << n); 53 self.ch.regs().chenset().write(|w| w.0 = 1 << n);
53 } 54 }
54 55
55 /// Disables the channel. 56 /// Disables the channel.
56 pub fn disable(&mut self) { 57 pub fn disable(&mut self) {
57 let n = self.ch.number(); 58 let n = self.ch.number();
58 regs().chenclr().write(|w| w.0 = 1 << n); 59 self.ch.regs().chenclr().write(|w| w.0 = 1 << n);
59 } 60 }
60} 61}
61 62
diff --git a/embassy-nrf/src/ppi/mod.rs b/embassy-nrf/src/ppi/mod.rs
index f30c2218d..a880d3188 100644
--- a/embassy-nrf/src/ppi/mod.rs
+++ b/embassy-nrf/src/ppi/mod.rs
@@ -21,11 +21,13 @@ use core::ptr::NonNull;
21use embassy_hal_internal::{Peri, PeripheralType, impl_peripheral}; 21use embassy_hal_internal::{Peri, PeripheralType, impl_peripheral};
22 22
23use crate::pac::common::{RW, Reg, W}; 23use crate::pac::common::{RW, Reg, W};
24use crate::peripherals; 24use crate::pac::{self};
25 25
26#[cfg_attr(feature = "_dppi", path = "dppi.rs")] 26#[cfg_attr(feature = "_dppi", path = "dppi.rs")]
27#[cfg_attr(feature = "_ppi", path = "ppi.rs")] 27#[cfg_attr(feature = "_ppi", path = "ppi.rs")]
28mod _version; 28mod _version;
29
30#[allow(unused_imports)]
29pub(crate) use _version::*; 31pub(crate) use _version::*;
30 32
31/// PPI channel driver. 33/// PPI channel driver.
@@ -47,7 +49,7 @@ impl<'d, G: Group> PpiGroup<'d, G> {
47 /// 49 ///
48 /// The group is initialized as containing no channels. 50 /// The group is initialized as containing no channels.
49 pub fn new(g: Peri<'d, G>) -> Self { 51 pub fn new(g: Peri<'d, G>) -> Self {
50 let r = regs(); 52 let r = g.regs();
51 let n = g.number(); 53 let n = g.number();
52 r.chg(n).write(|_| ()); 54 r.chg(n).write(|_| ());
53 55
@@ -61,7 +63,7 @@ impl<'d, G: Group> PpiGroup<'d, G> {
61 &mut self, 63 &mut self,
62 ch: &Ppi<'_, C, EVENT_COUNT, TASK_COUNT>, 64 ch: &Ppi<'_, C, EVENT_COUNT, TASK_COUNT>,
63 ) { 65 ) {
64 let r = regs(); 66 let r = self.g.regs();
65 let ng = self.g.number(); 67 let ng = self.g.number();
66 let nc = ch.ch.number(); 68 let nc = ch.ch.number();
67 r.chg(ng).modify(|w| w.set_ch(nc, true)); 69 r.chg(ng).modify(|w| w.set_ch(nc, true));
@@ -74,7 +76,7 @@ impl<'d, G: Group> PpiGroup<'d, G> {
74 &mut self, 76 &mut self,
75 ch: &Ppi<'_, C, EVENT_COUNT, TASK_COUNT>, 77 ch: &Ppi<'_, C, EVENT_COUNT, TASK_COUNT>,
76 ) { 78 ) {
77 let r = regs(); 79 let r = self.g.regs();
78 let ng = self.g.number(); 80 let ng = self.g.number();
79 let nc = ch.ch.number(); 81 let nc = ch.ch.number();
80 r.chg(ng).modify(|w| w.set_ch(nc, false)); 82 r.chg(ng).modify(|w| w.set_ch(nc, false));
@@ -83,13 +85,13 @@ impl<'d, G: Group> PpiGroup<'d, G> {
83 /// Enable all the channels in this group. 85 /// Enable all the channels in this group.
84 pub fn enable_all(&mut self) { 86 pub fn enable_all(&mut self) {
85 let n = self.g.number(); 87 let n = self.g.number();
86 regs().tasks_chg(n).en().write_value(1); 88 self.g.regs().tasks_chg(n).en().write_value(1);
87 } 89 }
88 90
89 /// Disable all the channels in this group. 91 /// Disable all the channels in this group.
90 pub fn disable_all(&mut self) { 92 pub fn disable_all(&mut self) {
91 let n = self.g.number(); 93 let n = self.g.number();
92 regs().tasks_chg(n).dis().write_value(1); 94 self.g.regs().tasks_chg(n).dis().write_value(1);
93 } 95 }
94 96
95 /// Get a reference to the "enable all" task. 97 /// Get a reference to the "enable all" task.
@@ -97,7 +99,7 @@ impl<'d, G: Group> PpiGroup<'d, G> {
97 /// When triggered, it will enable all the channels in this group. 99 /// When triggered, it will enable all the channels in this group.
98 pub fn task_enable_all(&self) -> Task<'d> { 100 pub fn task_enable_all(&self) -> Task<'d> {
99 let n = self.g.number(); 101 let n = self.g.number();
100 Task::from_reg(regs().tasks_chg(n).en()) 102 Task::from_reg(self.g.regs().tasks_chg(n).en())
101 } 103 }
102 104
103 /// Get a reference to the "disable all" task. 105 /// Get a reference to the "disable all" task.
@@ -105,7 +107,7 @@ impl<'d, G: Group> PpiGroup<'d, G> {
105 /// When triggered, it will disable all the channels in this group. 107 /// When triggered, it will disable all the channels in this group.
106 pub fn task_disable_all(&self) -> Task<'d> { 108 pub fn task_disable_all(&self) -> Task<'d> {
107 let n = self.g.number(); 109 let n = self.g.number();
108 Task::from_reg(regs().tasks_chg(n).dis()) 110 Task::from_reg(self.g.regs().tasks_chg(n).dis())
109 } 111 }
110} 112}
111impl<G: Group> PpiGroup<'static, G> { 113impl<G: Group> PpiGroup<'static, G> {
@@ -119,7 +121,7 @@ impl<G: Group> PpiGroup<'static, G> {
119 121
120impl<'d, G: Group> Drop for PpiGroup<'d, G> { 122impl<'d, G: Group> Drop for PpiGroup<'d, G> {
121 fn drop(&mut self) { 123 fn drop(&mut self) {
122 let r = regs(); 124 let r = self.g.regs();
123 let n = self.g.number(); 125 let n = self.g.number();
124 r.chg(n).write(|_| ()); 126 r.chg(n).write(|_| ());
125 } 127 }
@@ -211,8 +213,16 @@ unsafe impl Send for Event<'_> {}
211// ====================== 213// ======================
212// traits 214// traits
213 215
214pub(crate) trait SealedChannel {} 216pub(crate) trait SealedChannel {
215pub(crate) trait SealedGroup {} 217 #[cfg(feature = "_dppi")]
218 fn regs(&self) -> pac::dppic::Dppic;
219}
220pub(crate) trait SealedGroup {
221 #[cfg(feature = "_dppi")]
222 fn regs(&self) -> pac::dppic::Dppic;
223 #[cfg(not(feature = "_dppi"))]
224 fn regs(&self) -> pac::ppi::Ppi;
225}
216 226
217/// Interface for PPI channels. 227/// Interface for PPI channels.
218#[allow(private_bounds)] 228#[allow(private_bounds)]
@@ -241,9 +251,16 @@ pub trait Group: SealedGroup + PeripheralType + Into<AnyGroup> + Sized + 'static
241/// This can be used to have fewer generic parameters in some places. 251/// This can be used to have fewer generic parameters in some places.
242pub struct AnyStaticChannel { 252pub struct AnyStaticChannel {
243 pub(crate) number: u8, 253 pub(crate) number: u8,
254 #[cfg(feature = "_dppi")]
255 pub(crate) regs: pac::dppic::Dppic,
244} 256}
245impl_peripheral!(AnyStaticChannel); 257impl_peripheral!(AnyStaticChannel);
246impl SealedChannel for AnyStaticChannel {} 258impl SealedChannel for AnyStaticChannel {
259 #[cfg(feature = "_dppi")]
260 fn regs(&self) -> pac::dppic::Dppic {
261 self.regs
262 }
263}
247impl Channel for AnyStaticChannel { 264impl Channel for AnyStaticChannel {
248 fn number(&self) -> usize { 265 fn number(&self) -> usize {
249 self.number as usize 266 self.number as usize
@@ -255,9 +272,16 @@ impl StaticChannel for AnyStaticChannel {}
255/// This can be used to have fewer generic parameters in some places. 272/// This can be used to have fewer generic parameters in some places.
256pub struct AnyConfigurableChannel { 273pub struct AnyConfigurableChannel {
257 pub(crate) number: u8, 274 pub(crate) number: u8,
275 #[cfg(feature = "_dppi")]
276 pub(crate) regs: pac::dppic::Dppic,
258} 277}
259impl_peripheral!(AnyConfigurableChannel); 278impl_peripheral!(AnyConfigurableChannel);
260impl SealedChannel for AnyConfigurableChannel {} 279impl SealedChannel for AnyConfigurableChannel {
280 #[cfg(feature = "_dppi")]
281 fn regs(&self) -> pac::dppic::Dppic {
282 self.regs
283 }
284}
261impl Channel for AnyConfigurableChannel { 285impl Channel for AnyConfigurableChannel {
262 fn number(&self) -> usize { 286 fn number(&self) -> usize {
263 self.number as usize 287 self.number as usize
@@ -267,32 +291,41 @@ impl ConfigurableChannel for AnyConfigurableChannel {}
267 291
268#[cfg(not(feature = "_nrf51"))] 292#[cfg(not(feature = "_nrf51"))]
269macro_rules! impl_ppi_channel { 293macro_rules! impl_ppi_channel {
270 ($type:ident, $number:expr) => { 294 ($type:ident, $inst:ident, $number:expr) => {
271 impl crate::ppi::SealedChannel for peripherals::$type {} 295 impl crate::ppi::SealedChannel for peripherals::$type {
296 #[cfg(feature = "_dppi")]
297 fn regs(&self) -> pac::dppic::Dppic {
298 pac::$inst
299 }
300 }
272 impl crate::ppi::Channel for peripherals::$type { 301 impl crate::ppi::Channel for peripherals::$type {
273 fn number(&self) -> usize { 302 fn number(&self) -> usize {
274 $number 303 $number
275 } 304 }
276 } 305 }
277 }; 306 };
278 ($type:ident, $number:expr => static) => { 307 ($type:ident, $inst:ident, $number:expr => static) => {
279 impl_ppi_channel!($type, $number); 308 impl_ppi_channel!($type, $inst, $number);
280 impl crate::ppi::StaticChannel for peripherals::$type {} 309 impl crate::ppi::StaticChannel for peripherals::$type {}
281 impl From<peripherals::$type> for crate::ppi::AnyStaticChannel { 310 impl From<peripherals::$type> for crate::ppi::AnyStaticChannel {
282 fn from(val: peripherals::$type) -> Self { 311 fn from(val: peripherals::$type) -> Self {
283 Self { 312 Self {
284 number: crate::ppi::Channel::number(&val) as u8, 313 number: crate::ppi::Channel::number(&val) as u8,
314 #[cfg(feature = "_dppi")]
315 regs: pac::$inst,
285 } 316 }
286 } 317 }
287 } 318 }
288 }; 319 };
289 ($type:ident, $number:expr => configurable) => { 320 ($type:ident, $inst:ident, $number:expr => configurable) => {
290 impl_ppi_channel!($type, $number); 321 impl_ppi_channel!($type, $inst, $number);
291 impl crate::ppi::ConfigurableChannel for peripherals::$type {} 322 impl crate::ppi::ConfigurableChannel for peripherals::$type {}
292 impl From<peripherals::$type> for crate::ppi::AnyConfigurableChannel { 323 impl From<peripherals::$type> for crate::ppi::AnyConfigurableChannel {
293 fn from(val: peripherals::$type) -> Self { 324 fn from(val: peripherals::$type) -> Self {
294 Self { 325 Self {
295 number: crate::ppi::Channel::number(&val) as u8, 326 number: crate::ppi::Channel::number(&val) as u8,
327 #[cfg(feature = "_dppi")]
328 regs: pac::$inst,
296 } 329 }
297 } 330 }
298 } 331 }
@@ -304,40 +337,54 @@ macro_rules! impl_ppi_channel {
304 337
305/// A type erased PPI group. 338/// A type erased PPI group.
306pub struct AnyGroup { 339pub struct AnyGroup {
307 number: u8, 340 pub(crate) number: u8,
341 #[cfg(feature = "_dppi")]
342 pub(crate) regs: pac::dppic::Dppic,
343 #[cfg(not(feature = "_dppi"))]
344 pub(crate) regs: pac::ppi::Ppi,
308} 345}
309impl_peripheral!(AnyGroup); 346impl_peripheral!(AnyGroup);
310impl SealedGroup for AnyGroup {} 347impl SealedGroup for AnyGroup {
348 #[cfg(feature = "_dppi")]
349 fn regs(&self) -> pac::dppic::Dppic {
350 self.regs
351 }
352 #[cfg(not(feature = "_dppi"))]
353 fn regs(&self) -> pac::ppi::Ppi {
354 self.regs
355 }
356}
311impl Group for AnyGroup { 357impl Group for AnyGroup {
312 fn number(&self) -> usize { 358 fn number(&self) -> usize {
313 self.number as usize 359 self.number as usize
314 } 360 }
315} 361}
316 362
317macro_rules! impl_group { 363macro_rules! impl_ppi_group {
318 ($type:ident, $number:expr) => { 364 ($type:ident, $inst:ident, $number:expr) => {
319 impl SealedGroup for peripherals::$type {} 365 impl crate::ppi::SealedGroup for crate::peripherals::$type {
320 impl Group for peripherals::$type { 366 #[cfg(feature = "_dppi")]
367 fn regs(&self) -> pac::dppic::Dppic {
368 pac::$inst
369 }
370 #[cfg(not(feature = "_dppi"))]
371 fn regs(&self) -> pac::ppi::Ppi {
372 pac::$inst
373 }
374 }
375 impl crate::ppi::Group for crate::peripherals::$type {
321 fn number(&self) -> usize { 376 fn number(&self) -> usize {
322 $number 377 $number
323 } 378 }
324 } 379 }
325 380
326 impl From<peripherals::$type> for crate::ppi::AnyGroup { 381 impl From<crate::peripherals::$type> for crate::ppi::AnyGroup {
327 fn from(val: peripherals::$type) -> Self { 382 fn from(val: crate::peripherals::$type) -> Self {
328 Self { 383 Self {
329 number: crate::ppi::Group::number(&val) as u8, 384 number: crate::ppi::Group::number(&val) as u8,
385 regs: pac::$inst,
330 } 386 }
331 } 387 }
332 } 388 }
333 }; 389 };
334} 390}
335
336impl_group!(PPI_GROUP0, 0);
337impl_group!(PPI_GROUP1, 1);
338impl_group!(PPI_GROUP2, 2);
339impl_group!(PPI_GROUP3, 3);
340#[cfg(not(feature = "_nrf51"))]
341impl_group!(PPI_GROUP4, 4);
342#[cfg(not(feature = "_nrf51"))]
343impl_group!(PPI_GROUP5, 5);
diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs
index 00b3278c7..04eb14a77 100644
--- a/embassy-nrf/src/pwm.rs
+++ b/embassy-nrf/src/pwm.rs
@@ -203,7 +203,7 @@ impl<'d> SequencePwm<'d> {
203 /// Interacting with the sequence while it runs puts it in an unknown state 203 /// Interacting with the sequence while it runs puts it in an unknown state
204 #[inline(always)] 204 #[inline(always)]
205 pub unsafe fn task_start_seq0(&self) -> Task<'d> { 205 pub unsafe fn task_start_seq0(&self) -> Task<'d> {
206 Task::from_reg(self.r.tasks_seqstart(0)) 206 Task::from_reg(self.r.tasks_dma().seq(0).start())
207 } 207 }
208 208
209 /// Returns reference to `Seq1 Started` task endpoint for PPI. 209 /// Returns reference to `Seq1 Started` task endpoint for PPI.
@@ -212,7 +212,7 @@ impl<'d> SequencePwm<'d> {
212 /// Interacting with the sequence while it runs puts it in an unknown state 212 /// Interacting with the sequence while it runs puts it in an unknown state
213 #[inline(always)] 213 #[inline(always)]
214 pub unsafe fn task_start_seq1(&self) -> Task<'d> { 214 pub unsafe fn task_start_seq1(&self) -> Task<'d> {
215 Task::from_reg(self.r.tasks_seqstart(1)) 215 Task::from_reg(self.r.tasks_dma().seq(1).start())
216 } 216 }
217 217
218 /// Returns reference to `NextStep` task endpoint for PPI. 218 /// Returns reference to `NextStep` task endpoint for PPI.
@@ -444,6 +444,21 @@ pub struct Sequencer<'d, 's> {
444 sequence1: Option<Sequence<'s>>, 444 sequence1: Option<Sequence<'s>>,
445} 445}
446 446
447#[cfg(feature = "_nrf54l")]
448fn pwmseq(r: pac::pwm::Pwm, n: usize) -> pac::pwm::PwmSeq {
449 r.seq(n)
450}
451
452#[cfg(not(feature = "_nrf54l"))]
453fn pwmseq(r: pac::pwm::Pwm, n: usize) -> pac::pwm::DmaSeq {
454 r.dma().seq(n)
455}
456
457#[cfg(feature = "_nrf54l")]
458const CNT_UNIT: u32 = 2;
459#[cfg(not(feature = "_nrf54l"))]
460const CNT_UNIT: u32 = 1;
461
447impl<'d, 's> Sequencer<'d, 's> { 462impl<'d, 's> Sequencer<'d, 's> {
448 /// Create a new double sequence. In the absence of sequence 1, sequence 0 463 /// Create a new double sequence. In the absence of sequence 1, sequence 0
449 /// will be used twice in the one loop. 464 /// will be used twice in the one loop.
@@ -476,15 +491,21 @@ impl<'d, 's> Sequencer<'d, 's> {
476 491
477 let r = self._pwm.r; 492 let r = self._pwm.r;
478 493
479 r.seq(0).refresh().write(|w| w.0 = sequence0.config.refresh); 494 pwmseq(r, 0).refresh().write(|w| w.0 = sequence0.config.refresh);
480 r.seq(0).enddelay().write(|w| w.0 = sequence0.config.end_delay); 495 pwmseq(r, 0).enddelay().write(|w| w.0 = sequence0.config.end_delay);
481 r.seq(0).ptr().write_value(sequence0.words.as_ptr() as u32); 496 r.dma().seq(0).ptr().write_value(sequence0.words.as_ptr() as u32);
482 r.seq(0).cnt().write(|w| w.0 = sequence0.words.len() as u32); 497 r.dma()
483 498 .seq(0)
484 r.seq(1).refresh().write(|w| w.0 = alt_sequence.config.refresh); 499 .maxcnt()
485 r.seq(1).enddelay().write(|w| w.0 = alt_sequence.config.end_delay); 500 .write(|w| w.0 = sequence0.words.len() as u32 * CNT_UNIT);
486 r.seq(1).ptr().write_value(alt_sequence.words.as_ptr() as u32); 501
487 r.seq(1).cnt().write(|w| w.0 = alt_sequence.words.len() as u32); 502 pwmseq(r, 1).refresh().write(|w| w.0 = alt_sequence.config.refresh);
503 pwmseq(r, 1).enddelay().write(|w| w.0 = alt_sequence.config.end_delay);
504 r.dma().seq(1).ptr().write_value(alt_sequence.words.as_ptr() as u32);
505 r.dma()
506 .seq(1)
507 .maxcnt()
508 .write(|w| w.0 = alt_sequence.words.len() as u32 * CNT_UNIT);
488 509
489 r.enable().write(|w| w.set_enable(true)); 510 r.enable().write(|w| w.set_enable(true));
490 511
@@ -500,11 +521,11 @@ impl<'d, 's> Sequencer<'d, 's> {
500 // to play infinitely, repeat the sequence one time, then have loops done self trigger seq0 again 521 // to play infinitely, repeat the sequence one time, then have loops done self trigger seq0 again
501 SequenceMode::Infinite => { 522 SequenceMode::Infinite => {
502 r.loop_().write(|w| w.set_cnt(vals::LoopCnt::from_bits(1))); 523 r.loop_().write(|w| w.set_cnt(vals::LoopCnt::from_bits(1)));
503 r.shorts().write(|w| w.set_loopsdone_seqstart0(true)); 524 r.shorts().write(|w| w.set_loopsdone_dma_seq0_start(true));
504 } 525 }
505 } 526 }
506 527
507 r.tasks_seqstart(seqstart_index).write_value(1); 528 r.tasks_dma().seq(seqstart_index).start().write_value(1);
508 529
509 Ok(()) 530 Ok(())
510 } 531 }
@@ -781,10 +802,10 @@ impl<'d> SimplePwm<'d> {
781 // Enable 802 // Enable
782 r.enable().write(|w| w.set_enable(true)); 803 r.enable().write(|w| w.set_enable(true));
783 804
784 r.seq(0).ptr().write_value((pwm.duty).as_ptr() as u32); 805 r.dma().seq(0).ptr().write_value((pwm.duty).as_ptr() as u32);
785 r.seq(0).cnt().write(|w| w.0 = 4); 806 r.dma().seq(0).maxcnt().write(|w| w.0 = 4 * CNT_UNIT);
786 r.seq(0).refresh().write(|w| w.0 = 0); 807 pwmseq(r, 0).refresh().write(|w| w.0 = 0);
787 r.seq(0).enddelay().write(|w| w.0 = 0); 808 pwmseq(r, 0).enddelay().write(|w| w.0 = 0);
788 809
789 r.decoder().write(|w| { 810 r.decoder().write(|w| {
790 w.set_load(vals::Load::INDIVIDUAL); 811 w.set_load(vals::Load::INDIVIDUAL);
@@ -846,7 +867,7 @@ impl<'d> SimplePwm<'d> {
846 /// Transfer the duty cycles from `self` to the peripheral. 867 /// Transfer the duty cycles from `self` to the peripheral.
847 fn sync_duty_cyles_to_peripheral(&self) { 868 fn sync_duty_cyles_to_peripheral(&self) {
848 // reload ptr in case self was moved 869 // reload ptr in case self was moved
849 self.r.seq(0).ptr().write_value((self.duty).as_ptr() as u32); 870 self.r.dma().seq(0).ptr().write_value((self.duty).as_ptr() as u32);
850 871
851 // defensive before seqstart 872 // defensive before seqstart
852 compiler_fence(Ordering::SeqCst); 873 compiler_fence(Ordering::SeqCst);
@@ -854,7 +875,7 @@ impl<'d> SimplePwm<'d> {
854 self.r.events_seqend(0).write_value(0); 875 self.r.events_seqend(0).write_value(0);
855 876
856 // tasks_seqstart() doesn't exist in all svds so write its bit instead 877 // tasks_seqstart() doesn't exist in all svds so write its bit instead
857 self.r.tasks_seqstart(0).write_value(1); 878 self.r.tasks_dma().seq(0).start().write_value(1);
858 879
859 // defensive wait until waveform is loaded after seqstart so set_duty 880 // defensive wait until waveform is loaded after seqstart so set_duty
860 // can't be called again while dma is still reading 881 // can't be called again while dma is still reading
diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs
index a199c1c4d..ca8cbd73e 100644
--- a/embassy-nrf/src/saadc.rs
+++ b/embassy-nrf/src/saadc.rs
@@ -10,6 +10,7 @@ use core::task::Poll;
10use embassy_hal_internal::drop::OnDrop; 10use embassy_hal_internal::drop::OnDrop;
11use embassy_hal_internal::{Peri, impl_peripheral}; 11use embassy_hal_internal::{Peri, impl_peripheral};
12use embassy_sync::waitqueue::AtomicWaker; 12use embassy_sync::waitqueue::AtomicWaker;
13#[cfg(not(feature = "_nrf54l"))]
13pub(crate) use vals::Psel as InputChannel; 14pub(crate) use vals::Psel as InputChannel;
14 15
15use crate::interrupt::InterruptExt; 16use crate::interrupt::InterruptExt;
@@ -84,6 +85,7 @@ pub struct ChannelConfig<'d> {
84 /// Gain used to control the effective input range of the SAADC. 85 /// Gain used to control the effective input range of the SAADC.
85 pub gain: Gain, 86 pub gain: Gain,
86 /// Positive channel resistor control. 87 /// Positive channel resistor control.
88 #[cfg(not(feature = "_nrf54l"))]
87 pub resistor: Resistor, 89 pub resistor: Resistor,
88 /// Acquisition time in microseconds. 90 /// Acquisition time in microseconds.
89 pub time: Time, 91 pub time: Time,
@@ -98,7 +100,11 @@ impl<'d> ChannelConfig<'d> {
98 pub fn single_ended(input: impl Input + 'd) -> Self { 100 pub fn single_ended(input: impl Input + 'd) -> Self {
99 Self { 101 Self {
100 reference: Reference::INTERNAL, 102 reference: Reference::INTERNAL,
103 #[cfg(not(feature = "_nrf54l"))]
101 gain: Gain::GAIN1_6, 104 gain: Gain::GAIN1_6,
105 #[cfg(feature = "_nrf54l")]
106 gain: Gain::GAIN2_8,
107 #[cfg(not(feature = "_nrf54l"))]
102 resistor: Resistor::BYPASS, 108 resistor: Resistor::BYPASS,
103 time: Time::_10US, 109 time: Time::_10US,
104 p_channel: input.degrade_saadc(), 110 p_channel: input.degrade_saadc(),
@@ -109,7 +115,11 @@ impl<'d> ChannelConfig<'d> {
109 pub fn differential(p_input: impl Input + 'd, n_input: impl Input + 'd) -> Self { 115 pub fn differential(p_input: impl Input + 'd, n_input: impl Input + 'd) -> Self {
110 Self { 116 Self {
111 reference: Reference::INTERNAL, 117 reference: Reference::INTERNAL,
118 #[cfg(not(feature = "_nrf54l"))]
112 gain: Gain::GAIN1_6, 119 gain: Gain::GAIN1_6,
120 #[cfg(feature = "_nrf54l")]
121 gain: Gain::GAIN2_8,
122 #[cfg(not(feature = "_nrf54l"))]
113 resistor: Resistor::BYPASS, 123 resistor: Resistor::BYPASS,
114 time: Time::_10US, 124 time: Time::_10US,
115 p_channel: p_input.degrade_saadc(), 125 p_channel: p_input.degrade_saadc(),
@@ -118,6 +128,8 @@ impl<'d> ChannelConfig<'d> {
118 } 128 }
119} 129}
120 130
131const CNT_UNIT: usize = if cfg!(feature = "_nrf54l") { 2 } else { 1 };
132
121/// Value returned by the SAADC callback, deciding what happens next. 133/// Value returned by the SAADC callback, deciding what happens next.
122#[derive(PartialEq)] 134#[derive(PartialEq)]
123pub enum CallbackResult { 135pub enum CallbackResult {
@@ -150,19 +162,38 @@ impl<'d, const N: usize> Saadc<'d, N> {
150 r.oversample().write(|w| w.set_oversample(oversample.into())); 162 r.oversample().write(|w| w.set_oversample(oversample.into()));
151 163
152 for (i, cc) in channel_configs.iter().enumerate() { 164 for (i, cc) in channel_configs.iter().enumerate() {
165 #[cfg(not(feature = "_nrf54l"))]
153 r.ch(i).pselp().write(|w| w.set_pselp(cc.p_channel.channel())); 166 r.ch(i).pselp().write(|w| w.set_pselp(cc.p_channel.channel()));
167 #[cfg(feature = "_nrf54l")]
168 r.ch(i).pselp().write(|w| {
169 w.set_port(cc.p_channel.port());
170 w.set_pin(cc.p_channel.pin());
171 w.set_internal(cc.p_channel.internal());
172 w.set_connect(cc.p_channel.connect());
173 });
154 if let Some(n_channel) = &cc.n_channel { 174 if let Some(n_channel) = &cc.n_channel {
175 #[cfg(not(feature = "_nrf54l"))]
155 r.ch(i).pseln().write(|w| w.set_pseln(n_channel.channel())); 176 r.ch(i).pseln().write(|w| w.set_pseln(n_channel.channel()));
177 #[cfg(feature = "_nrf54l")]
178 r.ch(i).pseln().write(|w| {
179 w.set_port(n_channel.port());
180 w.set_pin(n_channel.pin());
181 w.set_connect(n_channel.connect().to_bits().into());
182 });
156 } 183 }
157 r.ch(i).config().write(|w| { 184 r.ch(i).config().write(|w| {
158 w.set_refsel(cc.reference.into()); 185 w.set_refsel(cc.reference.into());
159 w.set_gain(cc.gain.into()); 186 w.set_gain(cc.gain.into());
160 w.set_tacq(cc.time.into()); 187 w.set_tacq(cc.time.into());
188 #[cfg(feature = "_nrf54l")]
189 w.set_tconv(7); // 7 is the default from the Nordic C driver
161 w.set_mode(match cc.n_channel { 190 w.set_mode(match cc.n_channel {
162 None => vals::ConfigMode::SE, 191 None => vals::ConfigMode::SE,
163 Some(_) => vals::ConfigMode::DIFF, 192 Some(_) => vals::ConfigMode::DIFF,
164 }); 193 });
194 #[cfg(not(feature = "_nrf54l"))]
165 w.set_resp(cc.resistor.into()); 195 w.set_resp(cc.resistor.into());
196 #[cfg(not(feature = "_nrf54l"))]
166 w.set_resn(vals::Resn::BYPASS); 197 w.set_resn(vals::Resn::BYPASS);
167 w.set_burst(!matches!(oversample, Oversample::BYPASS)); 198 w.set_burst(!matches!(oversample, Oversample::BYPASS));
168 }); 199 });
@@ -222,7 +253,7 @@ impl<'d, const N: usize> Saadc<'d, N> {
222 253
223 // Set up the DMA 254 // Set up the DMA
224 r.result().ptr().write_value(buf.as_mut_ptr() as u32); 255 r.result().ptr().write_value(buf.as_mut_ptr() as u32);
225 r.result().maxcnt().write(|w| w.set_maxcnt(N as _)); 256 r.result().maxcnt().write(|w| w.set_maxcnt((N * CNT_UNIT) as _));
226 257
227 // Reset and enable the end event 258 // Reset and enable the end event
228 r.events_end().write_value(0); 259 r.events_end().write_value(0);
@@ -354,7 +385,7 @@ impl<'d, const N: usize> Saadc<'d, N> {
354 385
355 // Set up the initial DMA 386 // Set up the initial DMA
356 r.result().ptr().write_value(bufs[0].as_mut_ptr() as u32); 387 r.result().ptr().write_value(bufs[0].as_mut_ptr() as u32);
357 r.result().maxcnt().write(|w| w.set_maxcnt((N0 * N) as _)); 388 r.result().maxcnt().write(|w| w.set_maxcnt((N0 * N * CNT_UNIT) as _));
358 389
359 // Reset and enable the events 390 // Reset and enable the events
360 r.events_end().write_value(0); 391 r.events_end().write_value(0);
@@ -473,12 +504,21 @@ impl<'d, const N: usize> Drop for Saadc<'d, N> {
473 let r = Self::regs(); 504 let r = Self::regs();
474 r.enable().write(|w| w.set_enable(false)); 505 r.enable().write(|w| w.set_enable(false));
475 for i in 0..N { 506 for i in 0..N {
476 r.ch(i).pselp().write(|w| w.set_pselp(InputChannel::NC)); 507 #[cfg(not(feature = "_nrf54l"))]
477 r.ch(i).pseln().write(|w| w.set_pseln(InputChannel::NC)); 508 {
509 r.ch(i).pselp().write(|w| w.set_pselp(InputChannel::NC));
510 r.ch(i).pseln().write(|w| w.set_pseln(InputChannel::NC));
511 }
512 #[cfg(feature = "_nrf54l")]
513 {
514 r.ch(i).pselp().write(|w| w.set_connect(vals::PselpConnect::NC));
515 r.ch(i).pseln().write(|w| w.set_connect(vals::PselnConnect::NC));
516 }
478 } 517 }
479 } 518 }
480} 519}
481 520
521#[cfg(not(feature = "_nrf54l"))]
482impl From<Gain> for vals::Gain { 522impl From<Gain> for vals::Gain {
483 fn from(gain: Gain) -> Self { 523 fn from(gain: Gain) -> Self {
484 match gain { 524 match gain {
@@ -494,7 +534,24 @@ impl From<Gain> for vals::Gain {
494 } 534 }
495} 535}
496 536
537#[cfg(feature = "_nrf54l")]
538impl From<Gain> for vals::Gain {
539 fn from(gain: Gain) -> Self {
540 match gain {
541 Gain::GAIN2_8 => vals::Gain::GAIN2_8,
542 Gain::GAIN2_7 => vals::Gain::GAIN2_7,
543 Gain::GAIN2_6 => vals::Gain::GAIN2_6,
544 Gain::GAIN2_5 => vals::Gain::GAIN2_5,
545 Gain::GAIN2_4 => vals::Gain::GAIN2_4,
546 Gain::GAIN2_3 => vals::Gain::GAIN2_3,
547 Gain::GAIN1 => vals::Gain::GAIN1,
548 Gain::GAIN2 => vals::Gain::GAIN2,
549 }
550 }
551}
552
497/// Gain control 553/// Gain control
554#[cfg(not(feature = "_nrf54l"))]
498#[non_exhaustive] 555#[non_exhaustive]
499#[derive(Clone, Copy)] 556#[derive(Clone, Copy)]
500pub enum Gain { 557pub enum Gain {
@@ -516,11 +573,37 @@ pub enum Gain {
516 GAIN4 = 7, 573 GAIN4 = 7,
517} 574}
518 575
576/// Gain control
577#[cfg(feature = "_nrf54l")]
578#[non_exhaustive]
579#[derive(Clone, Copy)]
580pub enum Gain {
581 /// 2/8
582 GAIN2_8 = 0,
583 /// 2/7
584 GAIN2_7 = 1,
585 /// 2/6
586 GAIN2_6 = 2,
587 /// 2/5
588 GAIN2_5 = 3,
589 /// 2/4
590 GAIN2_4 = 4,
591 /// 2/3
592 GAIN2_3 = 5,
593 /// 1
594 GAIN1 = 6,
595 /// 2
596 GAIN2 = 7,
597}
598
519impl From<Reference> for vals::Refsel { 599impl From<Reference> for vals::Refsel {
520 fn from(reference: Reference) -> Self { 600 fn from(reference: Reference) -> Self {
521 match reference { 601 match reference {
522 Reference::INTERNAL => vals::Refsel::INTERNAL, 602 Reference::INTERNAL => vals::Refsel::INTERNAL,
603 #[cfg(not(feature = "_nrf54l"))]
523 Reference::VDD1_4 => vals::Refsel::VDD1_4, 604 Reference::VDD1_4 => vals::Refsel::VDD1_4,
605 #[cfg(feature = "_nrf54l")]
606 Reference::EXTERNAL => vals::Refsel::EXTERNAL,
524 } 607 }
525 } 608 }
526} 609}
@@ -531,10 +614,15 @@ impl From<Reference> for vals::Refsel {
531pub enum Reference { 614pub enum Reference {
532 /// Internal reference (0.6 V) 615 /// Internal reference (0.6 V)
533 INTERNAL = 0, 616 INTERNAL = 0,
617 #[cfg(not(feature = "_nrf54l"))]
534 /// VDD/4 as reference 618 /// VDD/4 as reference
535 VDD1_4 = 1, 619 VDD1_4 = 1,
620 /// PADC_EXT_REF_1V2 as reference
621 #[cfg(feature = "_nrf54l")]
622 EXTERNAL = 1,
536} 623}
537 624
625#[cfg(not(feature = "_nrf54l"))]
538impl From<Resistor> for vals::Resp { 626impl From<Resistor> for vals::Resp {
539 fn from(resistor: Resistor) -> Self { 627 fn from(resistor: Resistor) -> Self {
540 match resistor { 628 match resistor {
@@ -549,6 +637,7 @@ impl From<Resistor> for vals::Resp {
549/// Positive channel resistor control 637/// Positive channel resistor control
550#[non_exhaustive] 638#[non_exhaustive]
551#[derive(Clone, Copy)] 639#[derive(Clone, Copy)]
640#[cfg(not(feature = "_nrf54l"))]
552pub enum Resistor { 641pub enum Resistor {
553 /// Bypass resistor ladder 642 /// Bypass resistor ladder
554 BYPASS = 0, 643 BYPASS = 0,
@@ -560,6 +649,7 @@ pub enum Resistor {
560 VDD1_2 = 3, 649 VDD1_2 = 3,
561} 650}
562 651
652#[cfg(not(feature = "_nrf54l"))]
563impl From<Time> for vals::Tacq { 653impl From<Time> for vals::Tacq {
564 fn from(time: Time) -> Self { 654 fn from(time: Time) -> Self {
565 match time { 655 match time {
@@ -573,6 +663,20 @@ impl From<Time> for vals::Tacq {
573 } 663 }
574} 664}
575 665
666#[cfg(feature = "_nrf54l")]
667impl From<Time> for u16 {
668 fn from(time: Time) -> Self {
669 match time {
670 Time::_3US => (3000 / 125) - 1,
671 Time::_5US => (5000 / 125) - 1,
672 Time::_10US => (10000 / 125) - 1,
673 Time::_15US => (15000 / 125) - 1,
674 Time::_20US => (20000 / 125) - 1,
675 Time::_40US => (40000 / 125) - 1,
676 }
677 }
678}
679
576/// Acquisition time, the time the SAADC uses to sample the input voltage 680/// Acquisition time, the time the SAADC uses to sample the input voltage
577#[non_exhaustive] 681#[non_exhaustive]
578#[derive(Clone, Copy)] 682#[derive(Clone, Copy)]
@@ -657,7 +761,20 @@ pub enum Resolution {
657} 761}
658 762
659pub(crate) trait SealedInput { 763pub(crate) trait SealedInput {
764 #[cfg(not(feature = "_nrf54l"))]
660 fn channel(&self) -> InputChannel; 765 fn channel(&self) -> InputChannel;
766
767 #[cfg(feature = "_nrf54l")]
768 fn pin(&self) -> u8;
769
770 #[cfg(feature = "_nrf54l")]
771 fn port(&self) -> u8;
772
773 #[cfg(feature = "_nrf54l")]
774 fn internal(&self) -> vals::Internal;
775
776 #[cfg(feature = "_nrf54l")]
777 fn connect(&self) -> vals::PselpConnect;
661} 778}
662 779
663/// An input that can be used as either or negative end of a ADC differential in the SAADC periperhal. 780/// An input that can be used as either or negative end of a ADC differential in the SAADC periperhal.
@@ -667,6 +784,7 @@ pub trait Input: SealedInput + Sized {
667 /// 784 ///
668 /// This allows using several inputs in situations that might require 785 /// This allows using several inputs in situations that might require
669 /// them to be the same type, like putting them in an array. 786 /// them to be the same type, like putting them in an array.
787 #[cfg(not(feature = "_nrf54l"))]
670 fn degrade_saadc<'a>(self) -> AnyInput<'a> 788 fn degrade_saadc<'a>(self) -> AnyInput<'a>
671 where 789 where
672 Self: 'a, 790 Self: 'a,
@@ -676,17 +794,49 @@ pub trait Input: SealedInput + Sized {
676 _phantom: core::marker::PhantomData, 794 _phantom: core::marker::PhantomData,
677 } 795 }
678 } 796 }
797
798 /// Convert this SAADC input to a type-erased `AnyInput`.
799 ///
800 /// This allows using several inputs in situations that might require
801 /// them to be the same type, like putting them in an array.
802 #[cfg(feature = "_nrf54l")]
803 fn degrade_saadc<'a>(self) -> AnyInput<'a>
804 where
805 Self: 'a,
806 {
807 AnyInput {
808 pin: self.pin(),
809 port: self.port(),
810 internal: self.internal(),
811 connect: self.connect(),
812 _phantom: core::marker::PhantomData,
813 }
814 }
679} 815}
680 816
681/// A type-erased SAADC input. 817/// A type-erased SAADC input.
682/// 818///
683/// This allows using several inputs in situations that might require 819/// This allows using several inputs in situations that might require
684/// them to be the same type, like putting them in an array. 820/// them to be the same type, like putting them in an array.
821#[cfg(not(feature = "_nrf54l"))]
685pub struct AnyInput<'a> { 822pub struct AnyInput<'a> {
686 channel: InputChannel, 823 channel: InputChannel,
687 _phantom: PhantomData<&'a ()>, 824 _phantom: PhantomData<&'a ()>,
688} 825}
689 826
827/// A type-erased SAADC input.
828///
829/// This allows using several inputs in situations that might require
830/// them to be the same type, like putting them in an array.
831#[cfg(feature = "_nrf54l")]
832pub struct AnyInput<'a> {
833 pin: u8,
834 port: u8,
835 internal: vals::Internal,
836 connect: vals::PselpConnect,
837 _phantom: PhantomData<&'a ()>,
838}
839
690impl<'a> AnyInput<'a> { 840impl<'a> AnyInput<'a> {
691 /// Reborrow into a "child" AnyInput. 841 /// Reborrow into a "child" AnyInput.
692 /// 842 ///
@@ -694,21 +844,56 @@ impl<'a> AnyInput<'a> {
694 pub fn reborrow(&mut self) -> AnyInput<'_> { 844 pub fn reborrow(&mut self) -> AnyInput<'_> {
695 // safety: we're returning the clone inside a new Peripheral that borrows 845 // safety: we're returning the clone inside a new Peripheral that borrows
696 // self, so user code can't use both at the same time. 846 // self, so user code can't use both at the same time.
697 Self { 847 #[cfg(not(feature = "_nrf54l"))]
698 channel: self.channel, 848 {
699 _phantom: PhantomData, 849 Self {
850 channel: self.channel,
851 _phantom: PhantomData,
852 }
853 }
854 #[cfg(feature = "_nrf54l")]
855 {
856 Self {
857 pin: self.pin,
858 port: self.port,
859 internal: self.internal,
860 connect: self.connect,
861 _phantom: PhantomData,
862 }
700 } 863 }
701 } 864 }
702} 865}
703 866
704impl SealedInput for AnyInput<'_> { 867impl SealedInput for AnyInput<'_> {
868 #[cfg(not(feature = "_nrf54l"))]
705 fn channel(&self) -> InputChannel { 869 fn channel(&self) -> InputChannel {
706 self.channel 870 self.channel
707 } 871 }
872
873 #[cfg(feature = "_nrf54l")]
874 fn pin(&self) -> u8 {
875 self.pin
876 }
877
878 #[cfg(feature = "_nrf54l")]
879 fn port(&self) -> u8 {
880 self.port
881 }
882
883 #[cfg(feature = "_nrf54l")]
884 fn internal(&self) -> vals::Internal {
885 self.internal
886 }
887
888 #[cfg(feature = "_nrf54l")]
889 fn connect(&self) -> vals::PselpConnect {
890 self.connect
891 }
708} 892}
709 893
710impl Input for AnyInput<'_> {} 894impl Input for AnyInput<'_> {}
711 895
896#[cfg(not(feature = "_nrf54l"))]
712macro_rules! impl_saadc_input { 897macro_rules! impl_saadc_input {
713 ($pin:ident, $ch:ident) => { 898 ($pin:ident, $ch:ident) => {
714 impl_saadc_input!(@local, crate::Peri<'_, crate::peripherals::$pin>, $ch); 899 impl_saadc_input!(@local, crate::Peri<'_, crate::peripherals::$pin>, $ch);
@@ -723,15 +908,45 @@ macro_rules! impl_saadc_input {
723 }; 908 };
724} 909}
725 910
911#[cfg(feature = "_nrf54l")]
912macro_rules! impl_saadc_input {
913 ($pin:ident, $port:expr, $ain:expr) => {
914 impl_saadc_input!(@local, crate::Peri<'_, crate::peripherals::$pin>, $port, $ain, AVDD, ANALOG_INPUT);
915 };
916 (@local, $pin:ty, $port:expr, $ain:expr, $internal:ident, $connect:ident) => {
917 impl crate::saadc::SealedInput for $pin {
918 fn pin(&self) -> u8 {
919 $ain
920 }
921
922 fn port(&self) -> u8 {
923 $port
924 }
925
926 fn internal(&self) -> crate::pac::saadc::vals::Internal {
927 crate::pac::saadc::vals::Internal::$internal
928 }
929
930 fn connect(&self) -> crate::pac::saadc::vals::PselpConnect {
931 crate::pac::saadc::vals::PselpConnect::$connect
932 }
933 }
934 impl crate::saadc::Input for $pin {}
935 };
936}
937
726/// A dummy `Input` pin implementation for SAADC peripheral sampling from the 938/// A dummy `Input` pin implementation for SAADC peripheral sampling from the
727/// internal voltage. 939/// internal voltage.
728pub struct VddInput; 940pub struct VddInput;
729 941
730impl_peripheral!(VddInput); 942impl_peripheral!(VddInput);
943#[cfg(not(feature = "_nrf54l"))]
731#[cfg(not(feature = "_nrf91"))] 944#[cfg(not(feature = "_nrf91"))]
732impl_saadc_input!(@local, VddInput, VDD); 945impl_saadc_input!(@local, VddInput, VDD);
733#[cfg(feature = "_nrf91")] 946#[cfg(feature = "_nrf91")]
734impl_saadc_input!(@local, VddInput, VDD_GPIO); 947impl_saadc_input!(@local, VddInput, VDD_GPIO);
948#[cfg(feature = "_nrf54l")]
949impl_saadc_input!(@local, VddInput, 0, 0, VDD, INTERNAL);
735 950
736/// A dummy `Input` pin implementation for SAADC peripheral sampling from the 951/// A dummy `Input` pin implementation for SAADC peripheral sampling from the
737/// VDDH / 5 voltage. 952/// VDDH / 5 voltage.
@@ -743,3 +958,21 @@ impl_peripheral!(VddhDiv5Input);
743 958
744#[cfg(any(feature = "_nrf5340-app", feature = "nrf52833", feature = "nrf52840"))] 959#[cfg(any(feature = "_nrf5340-app", feature = "nrf52833", feature = "nrf52840"))]
745impl_saadc_input!(@local, VddhDiv5Input, VDDHDIV5); 960impl_saadc_input!(@local, VddhDiv5Input, VDDHDIV5);
961
962/// A dummy `Input` pin implementation for SAADC peripheral sampling from the
963/// AVDD internal voltage of the nrf54l chip family.
964#[cfg(feature = "_nrf54l")]
965pub struct AVddInput;
966#[cfg(feature = "_nrf54l")]
967embassy_hal_internal::impl_peripheral!(AVddInput);
968#[cfg(feature = "_nrf54l")]
969impl_saadc_input!(@local, AVddInput, 0, 0, AVDD, INTERNAL);
970
971/// A dummy `Input` pin implementation for SAADC peripheral sampling from the
972/// DVDD internal voltage of the nrf54l chip family.
973#[cfg(feature = "_nrf54l")]
974pub struct DVddInput;
975#[cfg(feature = "_nrf54l")]
976embassy_hal_internal::impl_peripheral!(DVddInput);
977#[cfg(feature = "_nrf54l")]
978impl_saadc_input!(@local, DVddInput, 0, 0, DVDD, INTERNAL);
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs
index ce994dbc9..34485609b 100644
--- a/embassy-nrf/src/spim.rs
+++ b/embassy-nrf/src/spim.rs
@@ -13,7 +13,7 @@ use embassy_embedded_hal::SetConfig;
13use embassy_hal_internal::{Peri, PeripheralType}; 13use embassy_hal_internal::{Peri, PeripheralType};
14use embassy_sync::waitqueue::AtomicWaker; 14use embassy_sync::waitqueue::AtomicWaker;
15pub use embedded_hal_02::spi::{MODE_0, MODE_1, MODE_2, MODE_3, Mode, Phase, Polarity}; 15pub use embedded_hal_02::spi::{MODE_0, MODE_1, MODE_2, MODE_3, Mode, Phase, Polarity};
16pub use pac::spim::vals::{Frequency, Order as BitOrder}; 16pub use pac::spim::vals::Order as BitOrder;
17 17
18use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; 18use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
19use crate::gpio::{self, AnyPin, OutputDrive, Pin as GpioPin, PselBits, SealedPin as _, convert_drive}; 19use crate::gpio::{self, AnyPin, OutputDrive, Pin as GpioPin, PselBits, SealedPin as _, convert_drive};
@@ -23,6 +23,110 @@ use crate::pac::spim::vals;
23use crate::util::slice_in_ram_or; 23use crate::util::slice_in_ram_or;
24use crate::{interrupt, pac}; 24use crate::{interrupt, pac};
25 25
26/// SPI frequencies.
27#[repr(transparent)]
28#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
29pub struct Frequency(u32);
30impl Frequency {
31 #[doc = "125 kbps"]
32 pub const K125: Self = Self(0x0200_0000);
33 #[doc = "250 kbps"]
34 pub const K250: Self = Self(0x0400_0000);
35 #[doc = "500 kbps"]
36 pub const K500: Self = Self(0x0800_0000);
37 #[doc = "1 Mbps"]
38 pub const M1: Self = Self(0x1000_0000);
39 #[doc = "2 Mbps"]
40 pub const M2: Self = Self(0x2000_0000);
41 #[doc = "4 Mbps"]
42 pub const M4: Self = Self(0x4000_0000);
43 #[doc = "8 Mbps"]
44 pub const M8: Self = Self(0x8000_0000);
45 #[cfg(not(feature = "_spi-v1"))]
46 #[doc = "16 Mbps"]
47 pub const M16: Self = Self(0x0a00_0000);
48 #[cfg(not(feature = "_spi-v1"))]
49 #[doc = "32 Mbps"]
50 pub const M32: Self = Self(0x1400_0000);
51}
52
53impl Frequency {
54 #[cfg(feature = "_nrf54l")]
55 fn to_divisor(&self, clk: u32) -> u8 {
56 let frequency = match *self {
57 #[cfg(not(feature = "_spi-v1"))]
58 Self::M32 => 32_000_000,
59 #[cfg(not(feature = "_spi-v1"))]
60 Self::M16 => 16_000_000,
61 Self::M8 => 8_000_000,
62 Self::M4 => 4_000_000,
63 Self::M2 => 2_000_000,
64 Self::M1 => 1_000_000,
65 Self::K500 => 500_000,
66 Self::K250 => 250_000,
67 Self::K125 => 125_000,
68 _ => unreachable!(),
69 };
70 let divisor = (clk / frequency) as u8;
71 divisor
72 }
73}
74impl core::fmt::Debug for Frequency {
75 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
76 match self.0 {
77 0x0200_0000 => f.write_str("K125"),
78 0x0400_0000 => f.write_str("K250"),
79 0x0800_0000 => f.write_str("K500"),
80 0x0a00_0000 => f.write_str("M16"),
81 0x1000_0000 => f.write_str("M1"),
82 0x1400_0000 => f.write_str("M32"),
83 0x2000_0000 => f.write_str("M2"),
84 0x4000_0000 => f.write_str("M4"),
85 0x8000_0000 => f.write_str("M8"),
86 other => core::write!(f, "0x{:02X}", other),
87 }
88 }
89}
90
91#[cfg(feature = "defmt")]
92impl defmt::Format for Frequency {
93 fn format(&self, f: defmt::Formatter) {
94 match self.0 {
95 0x0200_0000 => defmt::write!(f, "K125"),
96 0x0400_0000 => defmt::write!(f, "K250"),
97 0x0800_0000 => defmt::write!(f, "K500"),
98 0x0a00_0000 => defmt::write!(f, "M16"),
99 0x1000_0000 => defmt::write!(f, "M1"),
100 0x1400_0000 => defmt::write!(f, "M32"),
101 0x2000_0000 => defmt::write!(f, "M2"),
102 0x4000_0000 => defmt::write!(f, "M4"),
103 0x8000_0000 => defmt::write!(f, "M8"),
104 other => defmt::write!(f, "0x{:02X}", other),
105 }
106 }
107}
108
109#[cfg(not(feature = "_nrf54l"))]
110impl Into<pac::spim::vals::Frequency> for Frequency {
111 fn into(self) -> pac::spim::vals::Frequency {
112 use pac::spim::vals::Frequency as Freq;
113 match self {
114 #[cfg(not(feature = "_spi-v1"))]
115 Self::M32 => Freq::M32,
116 #[cfg(not(feature = "_spi-v1"))]
117 Self::M16 => Freq::M16,
118 Self::M8 => Freq::M8,
119 Self::M4 => Freq::M4,
120 Self::M2 => Freq::M2,
121 Self::M1 => Freq::M1,
122 Self::K500 => Freq::K500,
123 Self::K250 => Freq::K250,
124 Self::K125 => Freq::K125,
125 _ => unreachable!(),
126 }
127 }
128}
129
26/// SPIM error 130/// SPIM error
27#[derive(Debug, Clone, Copy, PartialEq, Eq)] 131#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28#[cfg_attr(feature = "defmt", derive(defmt::Format))] 132#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -103,6 +207,8 @@ pub struct Spim<'d> {
103 r: pac::spim::Spim, 207 r: pac::spim::Spim,
104 irq: interrupt::Interrupt, 208 irq: interrupt::Interrupt,
105 state: &'static State, 209 state: &'static State,
210 #[cfg(feature = "_nrf54l")]
211 clk: u32,
106 _p: PhantomData<&'d ()>, 212 _p: PhantomData<&'d ()>,
107} 213}
108 214
@@ -208,6 +314,8 @@ impl<'d> Spim<'d> {
208 r: T::regs(), 314 r: T::regs(),
209 irq: T::Interrupt::IRQ, 315 irq: T::Interrupt::IRQ,
210 state: T::state(), 316 state: T::state(),
317 #[cfg(feature = "_nrf54l")]
318 clk: T::clk(),
211 _p: PhantomData {}, 319 _p: PhantomData {},
212 }; 320 };
213 321
@@ -238,13 +346,13 @@ impl<'d> Spim<'d> {
238 346
239 // Set up the DMA read. 347 // Set up the DMA read.
240 let (rx_ptr, rx_len) = xfer_params(rx as *mut u8 as _, rx.len() as _, offset, length); 348 let (rx_ptr, rx_len) = xfer_params(rx as *mut u8 as _, rx.len() as _, offset, length);
241 r.rxd().ptr().write_value(rx_ptr); 349 r.dma().rx().ptr().write_value(rx_ptr);
242 r.rxd().maxcnt().write(|w| w.set_maxcnt(rx_len as _)); 350 r.dma().rx().maxcnt().write(|w| w.set_maxcnt(rx_len as _));
243 351
244 // Set up the DMA write. 352 // Set up the DMA write.
245 let (tx_ptr, tx_len) = xfer_params(tx as *const u8 as _, tx.len() as _, offset, length); 353 let (tx_ptr, tx_len) = xfer_params(tx as *const u8 as _, tx.len() as _, offset, length);
246 r.txd().ptr().write_value(tx_ptr); 354 r.dma().tx().ptr().write_value(tx_ptr);
247 r.txd().maxcnt().write(|w| w.set_maxcnt(tx_len as _)); 355 r.dma().tx().maxcnt().write(|w| w.set_maxcnt(tx_len as _));
248 356
249 /* 357 /*
250 trace!("XFER: offset: {}, length: {}", offset, length); 358 trace!("XFER: offset: {}, length: {}", offset, length);
@@ -259,8 +367,8 @@ impl<'d> Spim<'d> {
259 r.events_started().write_value(0); 367 r.events_started().write_value(0);
260 368
261 // Set rx/tx buffer lengths to 0... 369 // Set rx/tx buffer lengths to 0...
262 r.txd().maxcnt().write(|_| ()); 370 r.dma().tx().maxcnt().write(|_| ());
263 r.rxd().maxcnt().write(|_| ()); 371 r.dma().rx().maxcnt().write(|_| ());
264 372
265 // ...and keep track of original buffer lengths... 373 // ...and keep track of original buffer lengths...
266 s.tx.store(tx_len as _, Ordering::Relaxed); 374 s.tx.store(tx_len as _, Ordering::Relaxed);
@@ -447,8 +555,14 @@ impl<'d> Spim<'d> {
447 r.events_end().write_value(0); 555 r.events_end().write_value(0);
448 556
449 // Update DMA registers with correct rx/tx buffer sizes 557 // Update DMA registers with correct rx/tx buffer sizes
450 r.rxd().maxcnt().write(|w| w.set_maxcnt(s.rx.load(Ordering::Relaxed))); 558 r.dma()
451 r.txd().maxcnt().write(|w| w.set_maxcnt(s.tx.load(Ordering::Relaxed))); 559 .rx()
560 .maxcnt()
561 .write(|w| w.set_maxcnt(s.rx.load(Ordering::Relaxed)));
562 r.dma()
563 .tx()
564 .maxcnt()
565 .write(|w| w.set_maxcnt(s.tx.load(Ordering::Relaxed)));
452 566
453 r.intenset().write(|w| w.set_end(true)); 567 r.intenset().write(|w| w.set_end(true));
454 // ... and start actual, hopefully glitch-free transmission 568 // ... and start actual, hopefully glitch-free transmission
@@ -503,6 +617,8 @@ impl State {
503pub(crate) trait SealedInstance { 617pub(crate) trait SealedInstance {
504 fn regs() -> pac::spim::Spim; 618 fn regs() -> pac::spim::Spim;
505 fn state() -> &'static State; 619 fn state() -> &'static State;
620 #[cfg(feature = "_nrf54l")]
621 fn clk() -> u32;
506} 622}
507 623
508/// SPIM peripheral instance 624/// SPIM peripheral instance
@@ -512,6 +628,28 @@ pub trait Instance: SealedInstance + PeripheralType + 'static {
512 type Interrupt: interrupt::typelevel::Interrupt; 628 type Interrupt: interrupt::typelevel::Interrupt;
513} 629}
514 630
631#[cfg(feature = "_nrf54l")]
632macro_rules! impl_spim {
633 ($type:ident, $pac_type:ident, $irq:ident, $clk:expr) => {
634 impl crate::spim::SealedInstance for peripherals::$type {
635 fn regs() -> pac::spim::Spim {
636 pac::$pac_type
637 }
638 fn state() -> &'static crate::spim::State {
639 static STATE: crate::spim::State = crate::spim::State::new();
640 &STATE
641 }
642 fn clk() -> u32 {
643 $clk
644 }
645 }
646 impl crate::spim::Instance for peripherals::$type {
647 type Interrupt = crate::interrupt::typelevel::$irq;
648 }
649 };
650}
651
652#[cfg(not(feature = "_nrf54l"))]
515macro_rules! impl_spim { 653macro_rules! impl_spim {
516 ($type:ident, $pac_type:ident, $irq:ident) => { 654 ($type:ident, $pac_type:ident, $irq:ident) => {
517 impl crate::spim::SealedInstance for peripherals::$type { 655 impl crate::spim::SealedInstance for peripherals::$type {
@@ -638,7 +776,12 @@ impl<'d> SetConfig for Spim<'d> {
638 776
639 // Configure frequency. 777 // Configure frequency.
640 let frequency = config.frequency; 778 let frequency = config.frequency;
641 r.frequency().write(|w| w.set_frequency(frequency)); 779 #[cfg(not(feature = "_nrf54l"))]
780 r.frequency().write(|w| w.set_frequency(frequency.into()));
781 #[cfg(feature = "_nrf54l")]
782 {
783 r.prescaler().write(|w| w.set_divisor(frequency.to_divisor(self.clk)));
784 }
642 785
643 // Set over-read character 786 // Set over-read character
644 let orc = config.orc; 787 let orc = config.orc;
diff --git a/embassy-nrf/src/spis.rs b/embassy-nrf/src/spis.rs
index 885821146..96a9c0ae0 100644
--- a/embassy-nrf/src/spis.rs
+++ b/embassy-nrf/src/spis.rs
@@ -224,15 +224,15 @@ impl<'d> Spis<'d> {
224 if tx.len() > EASY_DMA_SIZE { 224 if tx.len() > EASY_DMA_SIZE {
225 return Err(Error::TxBufferTooLong); 225 return Err(Error::TxBufferTooLong);
226 } 226 }
227 r.txd().ptr().write_value(tx as *const u8 as _); 227 r.dma().tx().ptr().write_value(tx as *const u8 as _);
228 r.txd().maxcnt().write(|w| w.set_maxcnt(tx.len() as _)); 228 r.dma().tx().maxcnt().write(|w| w.set_maxcnt(tx.len() as _));
229 229
230 // Set up the DMA read. 230 // Set up the DMA read.
231 if rx.len() > EASY_DMA_SIZE { 231 if rx.len() > EASY_DMA_SIZE {
232 return Err(Error::RxBufferTooLong); 232 return Err(Error::RxBufferTooLong);
233 } 233 }
234 r.rxd().ptr().write_value(rx as *mut u8 as _); 234 r.dma().rx().ptr().write_value(rx as *mut u8 as _);
235 r.rxd().maxcnt().write(|w| w.set_maxcnt(rx.len() as _)); 235 r.dma().rx().maxcnt().write(|w| w.set_maxcnt(rx.len() as _));
236 236
237 // Reset end event. 237 // Reset end event.
238 r.events_end().write_value(0); 238 r.events_end().write_value(0);
@@ -260,8 +260,8 @@ impl<'d> Spis<'d> {
260 // Wait for 'end' event. 260 // Wait for 'end' event.
261 while r.events_end().read() == 0 {} 261 while r.events_end().read() == 0 {}
262 262
263 let n_rx = r.rxd().amount().read().0 as usize; 263 let n_rx = r.dma().rx().amount().read().0 as usize;
264 let n_tx = r.txd().amount().read().0 as usize; 264 let n_tx = r.dma().tx().amount().read().0 as usize;
265 265
266 compiler_fence(Ordering::SeqCst); 266 compiler_fence(Ordering::SeqCst);
267 267
@@ -326,8 +326,8 @@ impl<'d> Spis<'d> {
326 }) 326 })
327 .await; 327 .await;
328 328
329 let n_rx = r.rxd().amount().read().0 as usize; 329 let n_rx = r.dma().rx().amount().read().0 as usize;
330 let n_tx = r.txd().amount().read().0 as usize; 330 let n_tx = r.dma().tx().amount().read().0 as usize;
331 331
332 compiler_fence(Ordering::SeqCst); 332 compiler_fence(Ordering::SeqCst);
333 333
diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs
index 93255c832..abf9a923f 100644
--- a/embassy-nrf/src/twim.rs
+++ b/embassy-nrf/src/twim.rs
@@ -141,10 +141,19 @@ impl<'d> Twim<'d> {
141 sda.conf().write(|w| { 141 sda.conf().write(|w| {
142 w.set_dir(gpiovals::Dir::OUTPUT); 142 w.set_dir(gpiovals::Dir::OUTPUT);
143 w.set_input(gpiovals::Input::CONNECT); 143 w.set_input(gpiovals::Input::CONNECT);
144 #[cfg(not(feature = "_nrf54l"))]
144 w.set_drive(match config.sda_high_drive { 145 w.set_drive(match config.sda_high_drive {
145 true => gpiovals::Drive::H0D1, 146 true => gpiovals::Drive::H0D1,
146 false => gpiovals::Drive::S0D1, 147 false => gpiovals::Drive::S0D1,
147 }); 148 });
149 #[cfg(feature = "_nrf54l")]
150 {
151 w.set_drive0(match config.sda_high_drive {
152 true => gpiovals::Drive::H,
153 false => gpiovals::Drive::S,
154 });
155 w.set_drive1(gpiovals::Drive::D);
156 }
148 if config.sda_pullup { 157 if config.sda_pullup {
149 w.set_pull(gpiovals::Pull::PULLUP); 158 w.set_pull(gpiovals::Pull::PULLUP);
150 } 159 }
@@ -152,10 +161,19 @@ impl<'d> Twim<'d> {
152 scl.conf().write(|w| { 161 scl.conf().write(|w| {
153 w.set_dir(gpiovals::Dir::OUTPUT); 162 w.set_dir(gpiovals::Dir::OUTPUT);
154 w.set_input(gpiovals::Input::CONNECT); 163 w.set_input(gpiovals::Input::CONNECT);
164 #[cfg(not(feature = "_nrf54l"))]
155 w.set_drive(match config.scl_high_drive { 165 w.set_drive(match config.scl_high_drive {
156 true => gpiovals::Drive::H0D1, 166 true => gpiovals::Drive::H0D1,
157 false => gpiovals::Drive::S0D1, 167 false => gpiovals::Drive::S0D1,
158 }); 168 });
169 #[cfg(feature = "_nrf54l")]
170 {
171 w.set_drive0(match config.scl_high_drive {
172 true => gpiovals::Drive::H,
173 false => gpiovals::Drive::S,
174 });
175 w.set_drive1(gpiovals::Drive::D);
176 }
159 if config.sda_pullup { 177 if config.sda_pullup {
160 w.set_pull(gpiovals::Pull::PULLUP); 178 w.set_pull(gpiovals::Pull::PULLUP);
161 } 179 }
@@ -210,8 +228,8 @@ impl<'d> Twim<'d> {
210 // We're giving the register a pointer to the stack. Since we're 228 // We're giving the register a pointer to the stack. Since we're
211 // waiting for the I2C transaction to end before this stack pointer 229 // waiting for the I2C transaction to end before this stack pointer
212 // becomes invalid, there's nothing wrong here. 230 // becomes invalid, there's nothing wrong here.
213 r.txd().ptr().write_value(buffer.as_ptr() as u32); 231 r.dma().tx().ptr().write_value(buffer.as_ptr() as u32);
214 r.txd().maxcnt().write(|w| 232 r.dma().tx().maxcnt().write(|w|
215 // We're giving it the length of the buffer, so no danger of 233 // We're giving it the length of the buffer, so no danger of
216 // accessing invalid memory. We have verified that the length of the 234 // accessing invalid memory. We have verified that the length of the
217 // buffer fits in an `u8`, so the cast to `u8` is also fine. 235 // buffer fits in an `u8`, so the cast to `u8` is also fine.
@@ -237,8 +255,8 @@ impl<'d> Twim<'d> {
237 // We're giving the register a pointer to the stack. Since we're 255 // We're giving the register a pointer to the stack. Since we're
238 // waiting for the I2C transaction to end before this stack pointer 256 // waiting for the I2C transaction to end before this stack pointer
239 // becomes invalid, there's nothing wrong here. 257 // becomes invalid, there's nothing wrong here.
240 r.rxd().ptr().write_value(buffer.as_mut_ptr() as u32); 258 r.dma().rx().ptr().write_value(buffer.as_mut_ptr() as u32);
241 r.rxd().maxcnt().write(|w| 259 r.dma().rx().maxcnt().write(|w|
242 // We're giving it the length of the buffer, so no danger of 260 // We're giving it the length of the buffer, so no danger of
243 // accessing invalid memory. We have verified that the length of the 261 // accessing invalid memory. We have verified that the length of the
244 // buffer fits in an `u8`, so the cast to the type of maxcnt 262 // buffer fits in an `u8`, so the cast to the type of maxcnt
@@ -281,7 +299,7 @@ impl<'d> Twim<'d> {
281 299
282 fn check_rx(&self, len: usize) -> Result<(), Error> { 300 fn check_rx(&self, len: usize) -> Result<(), Error> {
283 let r = self.r; 301 let r = self.r;
284 if r.rxd().amount().read().0 != len as u32 { 302 if r.dma().rx().amount().read().0 != len as u32 {
285 Err(Error::Receive) 303 Err(Error::Receive)
286 } else { 304 } else {
287 Ok(()) 305 Ok(())
@@ -290,7 +308,7 @@ impl<'d> Twim<'d> {
290 308
291 fn check_tx(&self, len: usize) -> Result<(), Error> { 309 fn check_tx(&self, len: usize) -> Result<(), Error> {
292 let r = self.r; 310 let r = self.r;
293 if r.txd().amount().read().0 != len as u32 { 311 if r.dma().tx().amount().read().0 != len as u32 {
294 Err(Error::Transmit) 312 Err(Error::Transmit)
295 } else { 313 } else {
296 Ok(()) 314 Ok(())
@@ -412,7 +430,7 @@ impl<'d> Twim<'d> {
412 } 430 }
413 431
414 r.shorts().write(|w| { 432 r.shorts().write(|w| {
415 w.set_lastrx_starttx(true); 433 w.set_lastrx_dma_tx_start(true);
416 if stop { 434 if stop {
417 w.set_lasttx_stop(true); 435 w.set_lasttx_stop(true);
418 } else { 436 } else {
@@ -421,7 +439,7 @@ impl<'d> Twim<'d> {
421 }); 439 });
422 440
423 // Start read+write operation. 441 // Start read+write operation.
424 r.tasks_startrx().write_value(1); 442 r.tasks_dma().rx().start().write_value(1);
425 if last_op.is_some() { 443 if last_op.is_some() {
426 r.tasks_resume().write_value(1); 444 r.tasks_resume().write_value(1);
427 } 445 }
@@ -429,7 +447,7 @@ impl<'d> Twim<'d> {
429 // TODO: Handle empty write buffer 447 // TODO: Handle empty write buffer
430 if rd_buffer.is_empty() { 448 if rd_buffer.is_empty() {
431 // With a zero-length buffer, LASTRX doesn't fire (because there's no last byte!), so do the STARTTX ourselves. 449 // With a zero-length buffer, LASTRX doesn't fire (because there's no last byte!), so do the STARTTX ourselves.
432 r.tasks_starttx().write_value(1); 450 r.tasks_dma().tx().start().write_value(1);
433 } 451 }
434 452
435 Ok(2) 453 Ok(2)
@@ -443,7 +461,7 @@ impl<'d> Twim<'d> {
443 r.shorts().write(|w| w.set_lastrx_stop(true)); 461 r.shorts().write(|w| w.set_lastrx_stop(true));
444 462
445 // Start read operation. 463 // Start read operation.
446 r.tasks_startrx().write_value(1); 464 r.tasks_dma().rx().start().write_value(1);
447 if last_op.is_some() { 465 if last_op.is_some() {
448 r.tasks_resume().write_value(1); 466 r.tasks_resume().write_value(1);
449 } 467 }
@@ -466,11 +484,11 @@ impl<'d> Twim<'d> {
466 484
467 // Start write+read operation. 485 // Start write+read operation.
468 r.shorts().write(|w| { 486 r.shorts().write(|w| {
469 w.set_lasttx_startrx(true); 487 w.set_lasttx_dma_rx_start(true);
470 w.set_lastrx_stop(true); 488 w.set_lastrx_stop(true);
471 }); 489 });
472 490
473 r.tasks_starttx().write_value(1); 491 r.tasks_dma().tx().start().write_value(1);
474 if last_op.is_some() { 492 if last_op.is_some() {
475 r.tasks_resume().write_value(1); 493 r.tasks_resume().write_value(1);
476 } 494 }
@@ -494,7 +512,7 @@ impl<'d> Twim<'d> {
494 } 512 }
495 }); 513 });
496 514
497 r.tasks_starttx().write_value(1); 515 r.tasks_dma().tx().start().write_value(1);
498 if last_op.is_some() { 516 if last_op.is_some() {
499 r.tasks_resume().write_value(1); 517 r.tasks_resume().write_value(1);
500 } 518 }
diff --git a/embassy-nrf/src/twis.rs b/embassy-nrf/src/twis.rs
index 2bc0a5c13..b3a699f71 100644
--- a/embassy-nrf/src/twis.rs
+++ b/embassy-nrf/src/twis.rs
@@ -161,10 +161,19 @@ impl<'d> Twis<'d> {
161 sda.conf().write(|w| { 161 sda.conf().write(|w| {
162 w.set_dir(gpiovals::Dir::INPUT); 162 w.set_dir(gpiovals::Dir::INPUT);
163 w.set_input(gpiovals::Input::CONNECT); 163 w.set_input(gpiovals::Input::CONNECT);
164 #[cfg(not(feature = "_nrf54l"))]
164 w.set_drive(match config.sda_high_drive { 165 w.set_drive(match config.sda_high_drive {
165 true => gpiovals::Drive::H0D1, 166 true => gpiovals::Drive::H0D1,
166 false => gpiovals::Drive::S0D1, 167 false => gpiovals::Drive::S0D1,
167 }); 168 });
169 #[cfg(feature = "_nrf54l")]
170 {
171 w.set_drive0(match config.sda_high_drive {
172 true => gpiovals::Drive::H,
173 false => gpiovals::Drive::S,
174 });
175 w.set_drive1(gpiovals::Drive::D);
176 }
168 if config.sda_pullup { 177 if config.sda_pullup {
169 w.set_pull(gpiovals::Pull::PULLUP); 178 w.set_pull(gpiovals::Pull::PULLUP);
170 } 179 }
@@ -172,10 +181,19 @@ impl<'d> Twis<'d> {
172 scl.conf().write(|w| { 181 scl.conf().write(|w| {
173 w.set_dir(gpiovals::Dir::INPUT); 182 w.set_dir(gpiovals::Dir::INPUT);
174 w.set_input(gpiovals::Input::CONNECT); 183 w.set_input(gpiovals::Input::CONNECT);
184 #[cfg(not(feature = "_nrf54l"))]
175 w.set_drive(match config.scl_high_drive { 185 w.set_drive(match config.scl_high_drive {
176 true => gpiovals::Drive::H0D1, 186 true => gpiovals::Drive::H0D1,
177 false => gpiovals::Drive::S0D1, 187 false => gpiovals::Drive::S0D1,
178 }); 188 });
189 #[cfg(feature = "_nrf54l")]
190 {
191 w.set_drive0(match config.scl_high_drive {
192 true => gpiovals::Drive::H,
193 false => gpiovals::Drive::S,
194 });
195 w.set_drive1(gpiovals::Drive::D);
196 }
179 if config.sda_pullup { 197 if config.sda_pullup {
180 w.set_pull(gpiovals::Pull::PULLUP); 198 w.set_pull(gpiovals::Pull::PULLUP);
181 } 199 }
@@ -228,8 +246,8 @@ impl<'d> Twis<'d> {
228 // We're giving the register a pointer to the stack. Since we're 246 // We're giving the register a pointer to the stack. Since we're
229 // waiting for the I2C transaction to end before this stack pointer 247 // waiting for the I2C transaction to end before this stack pointer
230 // becomes invalid, there's nothing wrong here. 248 // becomes invalid, there's nothing wrong here.
231 r.txd().ptr().write_value(buffer.as_ptr() as u32); 249 r.dma().tx().ptr().write_value(buffer.as_ptr() as u32);
232 r.txd().maxcnt().write(|w| 250 r.dma().tx().maxcnt().write(|w|
233 // We're giving it the length of the buffer, so no danger of 251 // We're giving it the length of the buffer, so no danger of
234 // accessing invalid memory. We have verified that the length of the 252 // accessing invalid memory. We have verified that the length of the
235 // buffer fits in an `u8`, so the cast to `u8` is also fine. 253 // buffer fits in an `u8`, so the cast to `u8` is also fine.
@@ -255,8 +273,8 @@ impl<'d> Twis<'d> {
255 // We're giving the register a pointer to the stack. Since we're 273 // We're giving the register a pointer to the stack. Since we're
256 // waiting for the I2C transaction to end before this stack pointer 274 // waiting for the I2C transaction to end before this stack pointer
257 // becomes invalid, there's nothing wrong here. 275 // becomes invalid, there's nothing wrong here.
258 r.rxd().ptr().write_value(buffer.as_mut_ptr() as u32); 276 r.dma().rx().ptr().write_value(buffer.as_mut_ptr() as u32);
259 r.rxd().maxcnt().write(|w| 277 r.dma().rx().maxcnt().write(|w|
260 // We're giving it the length of the buffer, so no danger of 278 // We're giving it the length of the buffer, so no danger of
261 // accessing invalid memory. We have verified that the length of the 279 // accessing invalid memory. We have verified that the length of the
262 // buffer fits in an `u8`, so the cast to the type of maxcnt 280 // buffer fits in an `u8`, so the cast to the type of maxcnt
@@ -330,13 +348,13 @@ impl<'d> Twis<'d> {
330 return match status { 348 return match status {
331 Status::Read => Ok(Command::Read), 349 Status::Read => Ok(Command::Read),
332 Status::Write => { 350 Status::Write => {
333 let n = r.rxd().amount().read().0 as usize; 351 let n = r.dma().rx().amount().read().0 as usize;
334 Ok(Command::Write(n)) 352 Ok(Command::Write(n))
335 } 353 }
336 }; 354 };
337 } else if r.events_read().read() != 0 { 355 } else if r.events_read().read() != 0 {
338 r.events_read().write_value(0); 356 r.events_read().write_value(0);
339 let n = r.rxd().amount().read().0 as usize; 357 let n = r.dma().rx().amount().read().0 as usize;
340 return Ok(Command::WriteRead(n)); 358 return Ok(Command::WriteRead(n));
341 } 359 }
342 } 360 }
@@ -360,7 +378,7 @@ impl<'d> Twis<'d> {
360 } 378 }
361 } else if r.events_stopped().read() != 0 { 379 } else if r.events_stopped().read() != 0 {
362 r.events_stopped().write_value(0); 380 r.events_stopped().write_value(0);
363 let n = r.txd().amount().read().0 as usize; 381 let n = r.dma().tx().amount().read().0 as usize;
364 return Ok(n); 382 return Ok(n);
365 } 383 }
366 } 384 }
@@ -386,7 +404,7 @@ impl<'d> Twis<'d> {
386 } 404 }
387 } else if r.events_stopped().read() != 0 { 405 } else if r.events_stopped().read() != 0 {
388 r.events_stopped().write_value(0); 406 r.events_stopped().write_value(0);
389 let n = r.txd().amount().read().0 as usize; 407 let n = r.dma().tx().amount().read().0 as usize;
390 return Ok(n); 408 return Ok(n);
391 } else if Instant::now() > deadline { 409 } else if Instant::now() > deadline {
392 r.tasks_stop().write_value(1); 410 r.tasks_stop().write_value(1);
@@ -442,13 +460,13 @@ impl<'d> Twis<'d> {
442 return match status { 460 return match status {
443 Status::Read => Ok(Command::Read), 461 Status::Read => Ok(Command::Read),
444 Status::Write => { 462 Status::Write => {
445 let n = r.rxd().amount().read().0 as usize; 463 let n = r.dma().rx().amount().read().0 as usize;
446 Ok(Command::Write(n)) 464 Ok(Command::Write(n))
447 } 465 }
448 }; 466 };
449 } else if r.events_read().read() != 0 { 467 } else if r.events_read().read() != 0 {
450 r.events_read().write_value(0); 468 r.events_read().write_value(0);
451 let n = r.rxd().amount().read().0 as usize; 469 let n = r.dma().rx().amount().read().0 as usize;
452 return Ok(Command::WriteRead(n)); 470 return Ok(Command::WriteRead(n));
453 } else if Instant::now() > deadline { 471 } else if Instant::now() > deadline {
454 r.tasks_stop().write_value(1); 472 r.tasks_stop().write_value(1);
@@ -478,7 +496,7 @@ impl<'d> Twis<'d> {
478 } 496 }
479 } else if r.events_stopped().read() != 0 { 497 } else if r.events_stopped().read() != 0 {
480 r.events_stopped().write_value(0); 498 r.events_stopped().write_value(0);
481 let n = r.txd().amount().read().0 as usize; 499 let n = r.dma().tx().amount().read().0 as usize;
482 return Poll::Ready(Ok(n)); 500 return Poll::Ready(Ok(n));
483 } 501 }
484 502
@@ -529,13 +547,13 @@ impl<'d> Twis<'d> {
529 return match status { 547 return match status {
530 Status::Read => Poll::Ready(Ok(Command::Read)), 548 Status::Read => Poll::Ready(Ok(Command::Read)),
531 Status::Write => { 549 Status::Write => {
532 let n = r.rxd().amount().read().0 as usize; 550 let n = r.dma().rx().amount().read().0 as usize;
533 Poll::Ready(Ok(Command::Write(n))) 551 Poll::Ready(Ok(Command::Write(n)))
534 } 552 }
535 }; 553 };
536 } else if r.events_read().read() != 0 { 554 } else if r.events_read().read() != 0 {
537 r.events_read().write_value(0); 555 r.events_read().write_value(0);
538 let n = r.rxd().amount().read().0 as usize; 556 let n = r.dma().rx().amount().read().0 as usize;
539 return Poll::Ready(Ok(Command::WriteRead(n))); 557 return Poll::Ready(Ok(Command::WriteRead(n)));
540 } 558 }
541 Poll::Pending 559 Poll::Pending
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs
index 1ee452173..bf3b73f58 100644
--- a/embassy-nrf/src/uarte.rs
+++ b/embassy-nrf/src/uarte.rs
@@ -113,20 +113,20 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
113 let r = T::regs(); 113 let r = T::regs();
114 let s = T::state(); 114 let s = T::state();
115 115
116 let endrx = r.events_endrx().read(); 116 let endrx = r.events_dma().rx().end().read();
117 let error = r.events_error().read(); 117 let error = r.events_error().read();
118 if endrx != 0 || error != 0 { 118 if endrx != 0 || error != 0 {
119 s.rx_waker.wake(); 119 s.rx_waker.wake();
120 if endrx != 0 { 120 if endrx != 0 {
121 r.intenclr().write(|w| w.set_endrx(true)); 121 r.intenclr().write(|w| w.set_dmarxend(true));
122 } 122 }
123 if error != 0 { 123 if error != 0 {
124 r.intenclr().write(|w| w.set_error(true)); 124 r.intenclr().write(|w| w.set_error(true));
125 } 125 }
126 } 126 }
127 if r.events_endtx().read() != 0 { 127 if r.events_dma().tx().end().read() != 0 {
128 s.tx_waker.wake(); 128 s.tx_waker.wake();
129 r.intenclr().write(|w| w.set_endtx(true)); 129 r.intenclr().write(|w| w.set_dmatxend(true));
130 } 130 }
131 } 131 }
132} 132}
@@ -257,7 +257,7 @@ impl<'d> Uarte<'d> {
257 /// Return the endtx event for use with PPI 257 /// Return the endtx event for use with PPI
258 pub fn event_endtx(&self) -> Event<'_> { 258 pub fn event_endtx(&self) -> Event<'_> {
259 let r = self.tx.r; 259 let r = self.tx.r;
260 Event::from_reg(r.events_endtx()) 260 Event::from_reg(r.events_dma().tx().end())
261 } 261 }
262 262
263 /// Read bytes until the buffer is filled. 263 /// Read bytes until the buffer is filled.
@@ -296,7 +296,13 @@ pub(crate) fn configure_tx_pins(r: pac::uarte::Uarte, txd: Peri<'_, AnyPin>, cts
296 txd.conf().write(|w| { 296 txd.conf().write(|w| {
297 w.set_dir(gpiovals::Dir::OUTPUT); 297 w.set_dir(gpiovals::Dir::OUTPUT);
298 w.set_input(gpiovals::Input::DISCONNECT); 298 w.set_input(gpiovals::Input::DISCONNECT);
299 #[cfg(not(feature = "_nrf54l"))]
299 w.set_drive(gpiovals::Drive::H0H1); 300 w.set_drive(gpiovals::Drive::H0H1);
301 #[cfg(feature = "_nrf54l")]
302 {
303 w.set_drive0(gpiovals::Drive::H);
304 w.set_drive1(gpiovals::Drive::H);
305 }
300 }); 306 });
301 r.psel().txd().write_value(txd.psel_bits()); 307 r.psel().txd().write_value(txd.psel_bits());
302 308
@@ -304,7 +310,13 @@ pub(crate) fn configure_tx_pins(r: pac::uarte::Uarte, txd: Peri<'_, AnyPin>, cts
304 pin.conf().write(|w| { 310 pin.conf().write(|w| {
305 w.set_dir(gpiovals::Dir::INPUT); 311 w.set_dir(gpiovals::Dir::INPUT);
306 w.set_input(gpiovals::Input::CONNECT); 312 w.set_input(gpiovals::Input::CONNECT);
313 #[cfg(not(feature = "_nrf54l"))]
307 w.set_drive(gpiovals::Drive::H0H1); 314 w.set_drive(gpiovals::Drive::H0H1);
315 #[cfg(feature = "_nrf54l")]
316 {
317 w.set_drive0(gpiovals::Drive::H);
318 w.set_drive1(gpiovals::Drive::H);
319 }
308 }); 320 });
309 } 321 }
310 r.psel().cts().write_value(cts.psel_bits()); 322 r.psel().cts().write_value(cts.psel_bits());
@@ -314,7 +326,13 @@ pub(crate) fn configure_rx_pins(r: pac::uarte::Uarte, rxd: Peri<'_, AnyPin>, rts
314 rxd.conf().write(|w| { 326 rxd.conf().write(|w| {
315 w.set_dir(gpiovals::Dir::INPUT); 327 w.set_dir(gpiovals::Dir::INPUT);
316 w.set_input(gpiovals::Input::CONNECT); 328 w.set_input(gpiovals::Input::CONNECT);
329 #[cfg(not(feature = "_nrf54l"))]
317 w.set_drive(gpiovals::Drive::H0H1); 330 w.set_drive(gpiovals::Drive::H0H1);
331 #[cfg(feature = "_nrf54l")]
332 {
333 w.set_drive0(gpiovals::Drive::H);
334 w.set_drive1(gpiovals::Drive::H);
335 }
318 }); 336 });
319 r.psel().rxd().write_value(rxd.psel_bits()); 337 r.psel().rxd().write_value(rxd.psel_bits());
320 338
@@ -323,7 +341,13 @@ pub(crate) fn configure_rx_pins(r: pac::uarte::Uarte, rxd: Peri<'_, AnyPin>, rts
323 pin.conf().write(|w| { 341 pin.conf().write(|w| {
324 w.set_dir(gpiovals::Dir::OUTPUT); 342 w.set_dir(gpiovals::Dir::OUTPUT);
325 w.set_input(gpiovals::Input::DISCONNECT); 343 w.set_input(gpiovals::Input::DISCONNECT);
344 #[cfg(not(feature = "_nrf54l"))]
326 w.set_drive(gpiovals::Drive::H0H1); 345 w.set_drive(gpiovals::Drive::H0H1);
346 #[cfg(feature = "_nrf54l")]
347 {
348 w.set_drive0(gpiovals::Drive::H);
349 w.set_drive1(gpiovals::Drive::H);
350 }
327 }); 351 });
328 } 352 }
329 r.psel().rts().write_value(rts.psel_bits()); 353 r.psel().rts().write_value(rts.psel_bits());
@@ -333,6 +357,10 @@ pub(crate) fn configure(r: pac::uarte::Uarte, config: Config, hardware_flow_cont
333 r.config().write(|w| { 357 r.config().write(|w| {
334 w.set_hwfc(hardware_flow_control); 358 w.set_hwfc(hardware_flow_control);
335 w.set_parity(config.parity); 359 w.set_parity(config.parity);
360 #[cfg(feature = "_nrf54l")]
361 w.set_framesize(vals::Framesize::_8BIT);
362 #[cfg(feature = "_nrf54l")]
363 w.set_frametimeout(true);
336 }); 364 });
337 r.baudrate().write(|w| w.set_baudrate(config.baudrate)); 365 r.baudrate().write(|w| w.set_baudrate(config.baudrate));
338 366
@@ -341,8 +369,8 @@ pub(crate) fn configure(r: pac::uarte::Uarte, config: Config, hardware_flow_cont
341 369
342 // Reset rxstarted, txstarted. These are used by drop to know whether a transfer was 370 // Reset rxstarted, txstarted. These are used by drop to know whether a transfer was
343 // stopped midway or not. 371 // stopped midway or not.
344 r.events_rxstarted().write_value(0); 372 r.events_dma().rx().ready().write_value(0);
345 r.events_txstarted().write_value(0); 373 r.events_dma().tx().ready().write_value(0);
346 374
347 // reset all pins 375 // reset all pins
348 r.psel().txd().write_value(DISCONNECTED); 376 r.psel().txd().write_value(DISCONNECTED);
@@ -434,29 +462,29 @@ impl<'d> UarteTx<'d> {
434 let drop = OnDrop::new(move || { 462 let drop = OnDrop::new(move || {
435 trace!("write drop: stopping"); 463 trace!("write drop: stopping");
436 464
437 r.intenclr().write(|w| w.set_endtx(true)); 465 r.intenclr().write(|w| w.set_dmatxend(true));
438 r.events_txstopped().write_value(0); 466 r.events_txstopped().write_value(0);
439 r.tasks_stoptx().write_value(1); 467 r.tasks_dma().tx().stop().write_value(1);
440 468
441 // TX is stopped almost instantly, spinning is fine. 469 // TX is stopped almost instantly, spinning is fine.
442 while r.events_endtx().read() == 0 {} 470 while r.events_dma().tx().end().read() == 0 {}
443 trace!("write drop: stopped"); 471 trace!("write drop: stopped");
444 }); 472 });
445 473
446 r.txd().ptr().write_value(ptr as u32); 474 r.dma().tx().ptr().write_value(ptr as u32);
447 r.txd().maxcnt().write(|w| w.set_maxcnt(len as _)); 475 r.dma().tx().maxcnt().write(|w| w.set_maxcnt(len as _));
448 476
449 r.events_endtx().write_value(0); 477 r.events_dma().tx().end().write_value(0);
450 r.intenset().write(|w| w.set_endtx(true)); 478 r.intenset().write(|w| w.set_dmatxend(true));
451 479
452 compiler_fence(Ordering::SeqCst); 480 compiler_fence(Ordering::SeqCst);
453 481
454 trace!("starttx"); 482 trace!("starttx");
455 r.tasks_starttx().write_value(1); 483 r.tasks_dma().tx().start().write_value(1);
456 484
457 poll_fn(|cx| { 485 poll_fn(|cx| {
458 s.tx_waker.register(cx.waker()); 486 s.tx_waker.register(cx.waker());
459 if r.events_endtx().read() != 0 { 487 if r.events_dma().tx().end().read() != 0 {
460 return Poll::Ready(()); 488 return Poll::Ready(());
461 } 489 }
462 Poll::Pending 490 Poll::Pending
@@ -464,7 +492,7 @@ impl<'d> UarteTx<'d> {
464 .await; 492 .await;
465 493
466 compiler_fence(Ordering::SeqCst); 494 compiler_fence(Ordering::SeqCst);
467 r.events_txstarted().write_value(0); 495 r.events_dma().tx().ready().write_value(0);
468 drop.defuse(); 496 drop.defuse();
469 497
470 Ok(()) 498 Ok(())
@@ -500,21 +528,21 @@ impl<'d> UarteTx<'d> {
500 528
501 let r = self.r; 529 let r = self.r;
502 530
503 r.txd().ptr().write_value(ptr as u32); 531 r.dma().tx().ptr().write_value(ptr as u32);
504 r.txd().maxcnt().write(|w| w.set_maxcnt(len as _)); 532 r.dma().tx().maxcnt().write(|w| w.set_maxcnt(len as _));
505 533
506 r.events_endtx().write_value(0); 534 r.events_dma().tx().end().write_value(0);
507 r.intenclr().write(|w| w.set_endtx(true)); 535 r.intenclr().write(|w| w.set_dmatxend(true));
508 536
509 compiler_fence(Ordering::SeqCst); 537 compiler_fence(Ordering::SeqCst);
510 538
511 trace!("starttx"); 539 trace!("starttx");
512 r.tasks_starttx().write_value(1); 540 r.tasks_dma().tx().start().write_value(1);
513 541
514 while r.events_endtx().read() == 0 {} 542 while r.events_dma().tx().end().read() == 0 {}
515 543
516 compiler_fence(Ordering::SeqCst); 544 compiler_fence(Ordering::SeqCst);
517 r.events_txstarted().write_value(0); 545 r.events_dma().tx().ready().write_value(0);
518 546
519 Ok(()) 547 Ok(())
520 } 548 }
@@ -526,7 +554,7 @@ impl<'a> Drop for UarteTx<'a> {
526 554
527 let r = self.r; 555 let r = self.r;
528 556
529 let did_stoptx = r.events_txstarted().read() != 0; 557 let did_stoptx = r.events_dma().tx().ready().read() != 0;
530 trace!("did_stoptx {}", did_stoptx); 558 trace!("did_stoptx {}", did_stoptx);
531 559
532 // Wait for txstopped, if needed. 560 // Wait for txstopped, if needed.
@@ -629,7 +657,7 @@ impl<'d> UarteRx<'d> {
629 let mut ppi_ch2 = Ppi::new_one_to_one( 657 let mut ppi_ch2 = Ppi::new_one_to_one(
630 ppi_ch2.into(), 658 ppi_ch2.into(),
631 timer.cc(0).event_compare(), 659 timer.cc(0).event_compare(),
632 Task::from_reg(r.tasks_stoprx()), 660 Task::from_reg(r.tasks_dma().rx().stop()),
633 ); 661 );
634 ppi_ch2.enable(); 662 ppi_ch2.enable();
635 663
@@ -664,41 +692,41 @@ impl<'d> UarteRx<'d> {
664 trace!("read drop: stopping"); 692 trace!("read drop: stopping");
665 693
666 r.intenclr().write(|w| { 694 r.intenclr().write(|w| {
667 w.set_endrx(true); 695 w.set_dmarxend(true);
668 w.set_error(true); 696 w.set_error(true);
669 }); 697 });
670 r.events_rxto().write_value(0); 698 r.events_rxto().write_value(0);
671 r.events_error().write_value(0); 699 r.events_error().write_value(0);
672 r.tasks_stoprx().write_value(1); 700 r.tasks_dma().rx().stop().write_value(1);
673 701
674 while r.events_endrx().read() == 0 {} 702 while r.events_dma().rx().end().read() == 0 {}
675 703
676 trace!("read drop: stopped"); 704 trace!("read drop: stopped");
677 }); 705 });
678 706
679 r.rxd().ptr().write_value(ptr as u32); 707 r.dma().rx().ptr().write_value(ptr as u32);
680 r.rxd().maxcnt().write(|w| w.set_maxcnt(len as _)); 708 r.dma().rx().maxcnt().write(|w| w.set_maxcnt(len as _));
681 709
682 r.events_endrx().write_value(0); 710 r.events_dma().rx().end().write_value(0);
683 r.events_error().write_value(0); 711 r.events_error().write_value(0);
684 r.intenset().write(|w| { 712 r.intenset().write(|w| {
685 w.set_endrx(true); 713 w.set_dmarxend(true);
686 w.set_error(true); 714 w.set_error(true);
687 }); 715 });
688 716
689 compiler_fence(Ordering::SeqCst); 717 compiler_fence(Ordering::SeqCst);
690 718
691 trace!("startrx"); 719 trace!("startrx");
692 r.tasks_startrx().write_value(1); 720 r.tasks_dma().rx().start().write_value(1);
693 721
694 let result = poll_fn(|cx| { 722 let result = poll_fn(|cx| {
695 s.rx_waker.register(cx.waker()); 723 s.rx_waker.register(cx.waker());
696 724
697 if let Err(e) = self.check_and_clear_errors() { 725 if let Err(e) = self.check_and_clear_errors() {
698 r.tasks_stoprx().write_value(1); 726 r.tasks_dma().rx().stop().write_value(1);
699 return Poll::Ready(Err(e)); 727 return Poll::Ready(Err(e));
700 } 728 }
701 if r.events_endrx().read() != 0 { 729 if r.events_dma().rx().end().read() != 0 {
702 return Poll::Ready(Ok(())); 730 return Poll::Ready(Ok(()));
703 } 731 }
704 Poll::Pending 732 Poll::Pending
@@ -706,7 +734,7 @@ impl<'d> UarteRx<'d> {
706 .await; 734 .await;
707 735
708 compiler_fence(Ordering::SeqCst); 736 compiler_fence(Ordering::SeqCst);
709 r.events_rxstarted().write_value(0); 737 r.events_dma().rx().ready().write_value(0);
710 drop.defuse(); 738 drop.defuse();
711 739
712 result 740 result
@@ -726,25 +754,25 @@ impl<'d> UarteRx<'d> {
726 754
727 let r = self.r; 755 let r = self.r;
728 756
729 r.rxd().ptr().write_value(ptr as u32); 757 r.dma().rx().ptr().write_value(ptr as u32);
730 r.rxd().maxcnt().write(|w| w.set_maxcnt(len as _)); 758 r.dma().rx().maxcnt().write(|w| w.set_maxcnt(len as _));
731 759
732 r.events_endrx().write_value(0); 760 r.events_dma().rx().end().write_value(0);
733 r.events_error().write_value(0); 761 r.events_error().write_value(0);
734 r.intenclr().write(|w| { 762 r.intenclr().write(|w| {
735 w.set_endrx(true); 763 w.set_dmarxend(true);
736 w.set_error(true); 764 w.set_error(true);
737 }); 765 });
738 766
739 compiler_fence(Ordering::SeqCst); 767 compiler_fence(Ordering::SeqCst);
740 768
741 trace!("startrx"); 769 trace!("startrx");
742 r.tasks_startrx().write_value(1); 770 r.tasks_dma().rx().start().write_value(1);
743 771
744 while r.events_endrx().read() == 0 && r.events_error().read() == 0 {} 772 while r.events_dma().rx().end().read() == 0 && r.events_error().read() == 0 {}
745 773
746 compiler_fence(Ordering::SeqCst); 774 compiler_fence(Ordering::SeqCst);
747 r.events_rxstarted().write_value(0); 775 r.events_dma().rx().ready().write_value(0);
748 776
749 self.check_and_clear_errors() 777 self.check_and_clear_errors()
750 } 778 }
@@ -756,7 +784,7 @@ impl<'a> Drop for UarteRx<'a> {
756 784
757 let r = self.r; 785 let r = self.r;
758 786
759 let did_stoprx = r.events_rxstarted().read() != 0; 787 let did_stoprx = r.events_dma().rx().ready().read() != 0;
760 trace!("did_stoprx {}", did_stoprx); 788 trace!("did_stoprx {}", did_stoprx);
761 789
762 // Wait for rxto, if needed. 790 // Wait for rxto, if needed.
@@ -816,38 +844,38 @@ impl<'d> UarteRxWithIdle<'d> {
816 self.timer.stop(); 844 self.timer.stop();
817 845
818 r.intenclr().write(|w| { 846 r.intenclr().write(|w| {
819 w.set_endrx(true); 847 w.set_dmarxend(true);
820 w.set_error(true); 848 w.set_error(true);
821 }); 849 });
822 r.events_rxto().write_value(0); 850 r.events_rxto().write_value(0);
823 r.events_error().write_value(0); 851 r.events_error().write_value(0);
824 r.tasks_stoprx().write_value(1); 852 r.tasks_dma().rx().stop().write_value(1);
825 853
826 while r.events_endrx().read() == 0 {} 854 while r.events_dma().rx().end().read() == 0 {}
827 }); 855 });
828 856
829 r.rxd().ptr().write_value(ptr as u32); 857 r.dma().rx().ptr().write_value(ptr as u32);
830 r.rxd().maxcnt().write(|w| w.set_maxcnt(len as _)); 858 r.dma().rx().maxcnt().write(|w| w.set_maxcnt(len as _));
831 859
832 r.events_endrx().write_value(0); 860 r.events_dma().rx().end().write_value(0);
833 r.events_error().write_value(0); 861 r.events_error().write_value(0);
834 r.intenset().write(|w| { 862 r.intenset().write(|w| {
835 w.set_endrx(true); 863 w.set_dmarxend(true);
836 w.set_error(true); 864 w.set_error(true);
837 }); 865 });
838 866
839 compiler_fence(Ordering::SeqCst); 867 compiler_fence(Ordering::SeqCst);
840 868
841 r.tasks_startrx().write_value(1); 869 r.tasks_dma().rx().start().write_value(1);
842 870
843 let result = poll_fn(|cx| { 871 let result = poll_fn(|cx| {
844 s.rx_waker.register(cx.waker()); 872 s.rx_waker.register(cx.waker());
845 873
846 if let Err(e) = self.rx.check_and_clear_errors() { 874 if let Err(e) = self.rx.check_and_clear_errors() {
847 r.tasks_stoprx().write_value(1); 875 r.tasks_dma().rx().stop().write_value(1);
848 return Poll::Ready(Err(e)); 876 return Poll::Ready(Err(e));
849 } 877 }
850 if r.events_endrx().read() != 0 { 878 if r.events_dma().rx().end().read() != 0 {
851 return Poll::Ready(Ok(())); 879 return Poll::Ready(Ok(()));
852 } 880 }
853 881
@@ -856,10 +884,10 @@ impl<'d> UarteRxWithIdle<'d> {
856 .await; 884 .await;
857 885
858 compiler_fence(Ordering::SeqCst); 886 compiler_fence(Ordering::SeqCst);
859 let n = r.rxd().amount().read().0 as usize; 887 let n = r.dma().rx().amount().read().0 as usize;
860 888
861 self.timer.stop(); 889 self.timer.stop();
862 r.events_rxstarted().write_value(0); 890 r.events_dma().rx().ready().write_value(0);
863 891
864 drop.defuse(); 892 drop.defuse();
865 893
@@ -884,27 +912,27 @@ impl<'d> UarteRxWithIdle<'d> {
884 912
885 self.ppi_ch1.enable(); 913 self.ppi_ch1.enable();
886 914
887 r.rxd().ptr().write_value(ptr as u32); 915 r.dma().rx().ptr().write_value(ptr as u32);
888 r.rxd().maxcnt().write(|w| w.set_maxcnt(len as _)); 916 r.dma().rx().maxcnt().write(|w| w.set_maxcnt(len as _));
889 917
890 r.events_endrx().write_value(0); 918 r.events_dma().rx().end().write_value(0);
891 r.events_error().write_value(0); 919 r.events_error().write_value(0);
892 r.intenclr().write(|w| { 920 r.intenclr().write(|w| {
893 w.set_endrx(true); 921 w.set_dmarxend(true);
894 w.set_error(true); 922 w.set_error(true);
895 }); 923 });
896 924
897 compiler_fence(Ordering::SeqCst); 925 compiler_fence(Ordering::SeqCst);
898 926
899 r.tasks_startrx().write_value(1); 927 r.tasks_dma().rx().start().write_value(1);
900 928
901 while r.events_endrx().read() == 0 && r.events_error().read() == 0 {} 929 while r.events_dma().rx().end().read() == 0 && r.events_error().read() == 0 {}
902 930
903 compiler_fence(Ordering::SeqCst); 931 compiler_fence(Ordering::SeqCst);
904 let n = r.rxd().amount().read().0 as usize; 932 let n = r.dma().rx().amount().read().0 as usize;
905 933
906 self.timer.stop(); 934 self.timer.stop();
907 r.events_rxstarted().write_value(0); 935 r.events_dma().rx().ready().write_value(0);
908 936
909 self.rx.check_and_clear_errors().map(|_| n) 937 self.rx.check_and_clear_errors().map(|_| n)
910 } 938 }
@@ -927,14 +955,14 @@ pub(crate) fn apply_workaround_for_enable_anomaly(r: pac::uarte::Uarte) {
927 // NB Safety: This is taken from Nordic's driver - 955 // NB Safety: This is taken from Nordic's driver -
928 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197 956 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
929 if unsafe { core::ptr::read_volatile(txenable_reg) } == 1 { 957 if unsafe { core::ptr::read_volatile(txenable_reg) } == 1 {
930 r.tasks_stoptx().write_value(1); 958 r.tasks_dma().tx().stop().write_value(1);
931 } 959 }
932 960
933 // NB Safety: This is taken from Nordic's driver - 961 // NB Safety: This is taken from Nordic's driver -
934 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197 962 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
935 if unsafe { core::ptr::read_volatile(rxenable_reg) } == 1 { 963 if unsafe { core::ptr::read_volatile(rxenable_reg) } == 1 {
936 r.enable().write(|w| w.set_enable(vals::Enable::ENABLED)); 964 r.enable().write(|w| w.set_enable(vals::Enable::ENABLED));
937 r.tasks_stoprx().write_value(1); 965 r.tasks_dma().rx().stop().write_value(1);
938 966
939 let mut workaround_succeded = false; 967 let mut workaround_succeded = false;
940 // The UARTE is able to receive up to four bytes after the STOPRX task has been triggered. 968 // The UARTE is able to receive up to four bytes after the STOPRX task has been triggered.