aboutsummaryrefslogtreecommitdiff
path: root/embassy-nrf/src
diff options
context:
space:
mode:
authorQuentin Smith <[email protected]>2023-07-17 21:31:43 -0400
committerQuentin Smith <[email protected]>2023-07-17 21:31:43 -0400
commit6f02403184eb7fb7990fb88fc9df9c4328a690a3 (patch)
tree748f510e190bb2724750507a6e69ed1a8e08cb20 /embassy-nrf/src
parentd896f80405aa8963877049ed999e4aba25d6e2bb (diff)
parent6b5df4523aa1c4902f02e803450ae4b418e0e3ca (diff)
Merge remote-tracking branch 'origin/main' into nrf-pdm
Diffstat (limited to 'embassy-nrf/src')
-rw-r--r--embassy-nrf/src/buffered_uarte.rs873
-rw-r--r--embassy-nrf/src/chips/nrf52805.rs74
-rw-r--r--embassy-nrf/src/chips/nrf52810.rs94
-rw-r--r--embassy-nrf/src/chips/nrf52811.rs95
-rw-r--r--embassy-nrf/src/chips/nrf52820.rs74
-rw-r--r--embassy-nrf/src/chips/nrf52832.rs126
-rw-r--r--embassy-nrf/src/chips/nrf52833.rs134
-rw-r--r--embassy-nrf/src/chips/nrf52840.rs138
-rw-r--r--embassy-nrf/src/chips/nrf5340_app.rs183
-rw-r--r--embassy-nrf/src/chips/nrf5340_net.rs77
-rw-r--r--embassy-nrf/src/chips/nrf9160.rs141
-rw-r--r--embassy-nrf/src/gpio.rs22
-rw-r--r--embassy-nrf/src/gpiote.rs224
-rw-r--r--embassy-nrf/src/i2s.rs1194
-rw-r--r--embassy-nrf/src/lib.rs407
-rw-r--r--embassy-nrf/src/nvmc.rs71
-rw-r--r--embassy-nrf/src/pdm.rs447
-rw-r--r--embassy-nrf/src/ppi/dppi.rs13
-rw-r--r--embassy-nrf/src/ppi/mod.rs154
-rw-r--r--embassy-nrf/src/ppi/ppi.rs12
-rw-r--r--embassy-nrf/src/pwm.rs51
-rw-r--r--embassy-nrf/src/qdec.rs165
-rw-r--r--embassy-nrf/src/qspi.rs374
-rw-r--r--embassy-nrf/src/rng.rs202
-rw-r--r--embassy-nrf/src/saadc.rs161
-rw-r--r--embassy-nrf/src/spim.rs155
-rw-r--r--embassy-nrf/src/spis.rs550
-rw-r--r--embassy-nrf/src/temp.rs54
-rw-r--r--embassy-nrf/src/time_driver.rs29
-rw-r--r--embassy-nrf/src/timer.rs176
-rw-r--r--embassy-nrf/src/twim.rs212
-rw-r--r--embassy-nrf/src/twis.rs799
-rw-r--r--embassy-nrf/src/uarte.rs645
-rw-r--r--embassy-nrf/src/usb/mod.rs (renamed from embassy-nrf/src/usb.rs)639
-rw-r--r--embassy-nrf/src/usb/vbus_detect.rs177
-rw-r--r--embassy-nrf/src/wdt.rs32
36 files changed, 6329 insertions, 2645 deletions
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs
index 62af544ae..9bc1c1e7a 100644
--- a/embassy-nrf/src/buffered_uarte.rs
+++ b/embassy-nrf/src/buffered_uarte.rs
@@ -1,9 +1,4 @@
1//! Async buffered UART 1//! Async buffered UART driver.
2//!
3//! WARNING!!! The functionality provided here is intended to be used only
4//! in situations where hardware flow control are available i.e. CTS and RTS.
5//! This is a problem that should be addressed at a later stage and can be
6//! fully explained at <https://github.com/embassy-rs/embassy/issues/536>.
7//! 2//!
8//! Note that discarding a future from a read or write operation may lead to losing 3//! Note that discarding a future from a read or write operation may lead to losing
9//! data. For example, when using `futures_util::future::select` and completion occurs 4//! data. For example, when using `futures_util::future::select` and completion occurs
@@ -14,82 +9,234 @@
14//! Please also see [crate::uarte] to understand when [BufferedUarte] should be used. 9//! Please also see [crate::uarte] to understand when [BufferedUarte] should be used.
15 10
16use core::cmp::min; 11use core::cmp::min;
17use core::future::Future; 12use core::future::poll_fn;
18use core::sync::atomic::{compiler_fence, Ordering}; 13use core::marker::PhantomData;
14use core::slice;
15use core::sync::atomic::{compiler_fence, AtomicU8, AtomicUsize, Ordering};
19use core::task::Poll; 16use core::task::Poll;
20 17
21use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; 18use embassy_hal_common::atomic_ring_buffer::RingBuffer;
22use embassy_hal_common::ring_buffer::RingBuffer;
23use embassy_hal_common::{into_ref, PeripheralRef}; 19use embassy_hal_common::{into_ref, PeripheralRef};
24use embassy_sync::waitqueue::WakerRegistration; 20use embassy_sync::waitqueue::AtomicWaker;
25use futures::future::poll_fn;
26// Re-export SVD variants to allow user to directly set values 21// Re-export SVD variants to allow user to directly set values
27pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; 22pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
28 23
29use crate::gpio::Pin as GpioPin; 24use crate::gpio::sealed::Pin;
30use crate::interrupt::InterruptExt; 25use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits};
31use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; 26use crate::interrupt::typelevel::Interrupt;
32use crate::timer::{Frequency, Instance as TimerInstance, Timer}; 27use crate::ppi::{
28 self, AnyConfigurableChannel, AnyGroup, Channel, ConfigurableChannel, Event, Group, Ppi, PpiGroup, Task,
29};
30use crate::timer::{Instance as TimerInstance, Timer};
33use crate::uarte::{apply_workaround_for_enable_anomaly, Config, Instance as UarteInstance}; 31use crate::uarte::{apply_workaround_for_enable_anomaly, Config, Instance as UarteInstance};
34use crate::{pac, Peripheral}; 32use crate::{interrupt, pac, Peripheral};
33
34mod sealed {
35 use super::*;
36
37 pub struct State {
38 pub tx_waker: AtomicWaker,
39 pub tx_buf: RingBuffer,
40 pub tx_count: AtomicUsize,
35 41
36#[derive(Copy, Clone, Debug, PartialEq)] 42 pub rx_waker: AtomicWaker,
37enum RxState { 43 pub rx_buf: RingBuffer,
38 Idle, 44 pub rx_bufs: AtomicU8,
39 Receiving, 45 pub rx_ppi_ch: AtomicU8,
46 }
40} 47}
41 48
42#[derive(Copy, Clone, Debug, PartialEq)] 49/// UART error.
43enum TxState { 50#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44 Idle, 51#[cfg_attr(feature = "defmt", derive(defmt::Format))]
45 Transmitting(usize), 52#[non_exhaustive]
53pub enum Error {
54 // No errors for now
46} 55}
47 56
48/// A type for storing the state of the UARTE peripheral that can be stored in a static. 57pub(crate) use sealed::State;
49pub struct State<'d, U: UarteInstance, T: TimerInstance>(StateStorage<StateInner<'d, U, T>>); 58
50impl<'d, U: UarteInstance, T: TimerInstance> State<'d, U, T> { 59impl State {
51 /// Create an instance for storing UARTE peripheral state. 60 pub(crate) const fn new() -> Self {
52 pub fn new() -> Self { 61 Self {
53 Self(StateStorage::new()) 62 tx_waker: AtomicWaker::new(),
63 tx_buf: RingBuffer::new(),
64 tx_count: AtomicUsize::new(0),
65
66 rx_waker: AtomicWaker::new(),
67 rx_buf: RingBuffer::new(),
68 rx_bufs: AtomicU8::new(0),
69 rx_ppi_ch: AtomicU8::new(0),
70 }
54 } 71 }
55} 72}
56 73
57struct StateInner<'d, U: UarteInstance, T: TimerInstance> { 74/// Interrupt handler.
58 _peri: PeripheralRef<'d, U>, 75pub struct InterruptHandler<U: UarteInstance> {
59 timer: Timer<'d, T>, 76 _phantom: PhantomData<U>,
60 _ppi_ch1: Ppi<'d, AnyConfigurableChannel, 1, 2>, 77}
61 _ppi_ch2: Ppi<'d, AnyConfigurableChannel, 1, 1>, 78
79impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for InterruptHandler<U> {
80 unsafe fn on_interrupt() {
81 //trace!("irq: start");
82 let r = U::regs();
83 let s = U::buffered_state();
84
85 let buf_len = s.rx_buf.len();
86 let half_len = buf_len / 2;
87 let mut tx = unsafe { s.tx_buf.reader() };
88 let mut rx = unsafe { s.rx_buf.writer() };
89
90 if r.events_error.read().bits() != 0 {
91 r.events_error.reset();
92 let errs = r.errorsrc.read();
93 r.errorsrc.write(|w| unsafe { w.bits(errs.bits()) });
94
95 if errs.overrun().bit() {
96 panic!("BufferedUarte overrun");
97 }
98 }
99
100 // Received some bytes, wake task.
101 if r.inten.read().rxdrdy().bit_is_set() && r.events_rxdrdy.read().bits() != 0 {
102 r.intenclr.write(|w| w.rxdrdy().clear());
103 r.events_rxdrdy.reset();
104 s.rx_waker.wake();
105 }
106
107 // If not RXing, start.
108 if s.rx_bufs.load(Ordering::Relaxed) == 0 {
109 let (ptr, len) = rx.push_buf();
110 if len >= half_len {
111 //trace!(" irq_rx: starting {:?}", half_len);
112 s.rx_bufs.store(1, Ordering::Relaxed);
113
114 // Set up the DMA read
115 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
116 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(half_len as _) });
117
118 // Start UARTE Receive transaction
119 r.tasks_startrx.write(|w| unsafe { w.bits(1) });
120 rx.push_done(half_len);
121 r.intenset.write(|w| w.rxstarted().set());
122 }
123 }
62 124
63 rx: RingBuffer<'d>, 125 if r.events_rxstarted.read().bits() != 0 {
64 rx_state: RxState, 126 //trace!(" irq_rx: rxstarted");
65 rx_waker: WakerRegistration, 127 let (ptr, len) = rx.push_buf();
128 if len >= half_len {
129 //trace!(" irq_rx: starting second {:?}", half_len);
66 130
67 tx: RingBuffer<'d>, 131 // Set up the DMA read
68 tx_state: TxState, 132 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
69 tx_waker: WakerRegistration, 133 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(half_len as _) });
134
135 let chn = s.rx_ppi_ch.load(Ordering::Relaxed);
136
137 ppi::regs().chenset.write(|w| unsafe { w.bits(1 << chn) });
138
139 rx.push_done(half_len);
140
141 r.events_rxstarted.reset();
142 } else {
143 //trace!(" irq_rx: rxstarted no buf");
144 r.intenclr.write(|w| w.rxstarted().clear());
145 }
146 }
147
148 // =============================
149
150 // TX end
151 if r.events_endtx.read().bits() != 0 {
152 r.events_endtx.reset();
153
154 let n = s.tx_count.load(Ordering::Relaxed);
155 //trace!(" irq_tx: endtx {:?}", n);
156 tx.pop_done(n);
157 s.tx_waker.wake();
158 s.tx_count.store(0, Ordering::Relaxed);
159 }
160
161 // If not TXing, start.
162 if s.tx_count.load(Ordering::Relaxed) == 0 {
163 let (ptr, len) = tx.pop_buf();
164 if len != 0 {
165 //trace!(" irq_tx: starting {:?}", len);
166 s.tx_count.store(len, Ordering::Relaxed);
167
168 // Set up the DMA write
169 r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
170 r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
171
172 // Start UARTE Transmit transaction
173 r.tasks_starttx.write(|w| unsafe { w.bits(1) });
174 }
175 }
176
177 //trace!("irq: end");
178 }
70} 179}
71 180
72/// Interface to a UARTE instance 181/// Buffered UARTE driver.
73pub struct BufferedUarte<'d, U: UarteInstance, T: TimerInstance> { 182pub struct BufferedUarte<'d, U: UarteInstance, T: TimerInstance> {
74 inner: PeripheralMutex<'d, StateInner<'d, U, T>>, 183 _peri: PeripheralRef<'d, U>,
184 timer: Timer<'d, T>,
185 _ppi_ch1: Ppi<'d, AnyConfigurableChannel, 1, 1>,
186 _ppi_ch2: Ppi<'d, AnyConfigurableChannel, 1, 2>,
187 _ppi_group: PpiGroup<'d, AnyGroup>,
75} 188}
76 189
77impl<'d, U: UarteInstance, T: TimerInstance> Unpin for BufferedUarte<'d, U, T> {} 190impl<'d, U: UarteInstance, T: TimerInstance> Unpin for BufferedUarte<'d, U, T> {}
78 191
79impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { 192impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
80 /// Create a new instance of a BufferedUarte. 193 /// Create a new BufferedUarte without hardware flow control.
81 /// 194 ///
82 /// See the [module documentation](crate::buffered_uarte) for more details about the intended use. 195 /// # Panics
83 /// 196 ///
84 /// The BufferedUarte uses the provided state to store the buffers and peripheral state. The timer and ppi channels are used to 'emulate' idle line detection so that read operations 197 /// Panics if `rx_buffer.len()` is odd.
85 /// can return early if there is no data to receive.
86 pub fn new( 198 pub fn new(
87 state: &'d mut State<'d, U, T>, 199 uarte: impl Peripheral<P = U> + 'd,
88 peri: impl Peripheral<P = U> + 'd,
89 timer: impl Peripheral<P = T> + 'd, 200 timer: impl Peripheral<P = T> + 'd,
90 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd, 201 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd,
91 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd, 202 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd,
92 irq: impl Peripheral<P = U::Interrupt> + 'd, 203 ppi_group: impl Peripheral<P = impl Group> + 'd,
204 _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
205 rxd: impl Peripheral<P = impl GpioPin> + 'd,
206 txd: impl Peripheral<P = impl GpioPin> + 'd,
207 config: Config,
208 rx_buffer: &'d mut [u8],
209 tx_buffer: &'d mut [u8],
210 ) -> Self {
211 into_ref!(rxd, txd, ppi_ch1, ppi_ch2, ppi_group);
212 Self::new_inner(
213 uarte,
214 timer,
215 ppi_ch1.map_into(),
216 ppi_ch2.map_into(),
217 ppi_group.map_into(),
218 rxd.map_into(),
219 txd.map_into(),
220 None,
221 None,
222 config,
223 rx_buffer,
224 tx_buffer,
225 )
226 }
227
228 /// Create a new BufferedUarte with hardware flow control (RTS/CTS)
229 ///
230 /// # Panics
231 ///
232 /// Panics if `rx_buffer.len()` is odd.
233 pub fn new_with_rtscts(
234 uarte: impl Peripheral<P = U> + 'd,
235 timer: impl Peripheral<P = T> + 'd,
236 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd,
237 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd,
238 ppi_group: impl Peripheral<P = impl Group> + 'd,
239 _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
93 rxd: impl Peripheral<P = impl GpioPin> + 'd, 240 rxd: impl Peripheral<P = impl GpioPin> + 'd,
94 txd: impl Peripheral<P = impl GpioPin> + 'd, 241 txd: impl Peripheral<P = impl GpioPin> + 'd,
95 cts: impl Peripheral<P = impl GpioPin> + 'd, 242 cts: impl Peripheral<P = impl GpioPin> + 'd,
@@ -98,11 +245,42 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
98 rx_buffer: &'d mut [u8], 245 rx_buffer: &'d mut [u8],
99 tx_buffer: &'d mut [u8], 246 tx_buffer: &'d mut [u8],
100 ) -> Self { 247 ) -> Self {
101 into_ref!(peri, ppi_ch1, ppi_ch2, irq, rxd, txd, cts, rts); 248 into_ref!(rxd, txd, cts, rts, ppi_ch1, ppi_ch2, ppi_group);
249 Self::new_inner(
250 uarte,
251 timer,
252 ppi_ch1.map_into(),
253 ppi_ch2.map_into(),
254 ppi_group.map_into(),
255 rxd.map_into(),
256 txd.map_into(),
257 Some(cts.map_into()),
258 Some(rts.map_into()),
259 config,
260 rx_buffer,
261 tx_buffer,
262 )
263 }
102 264
103 let r = U::regs(); 265 fn new_inner(
266 peri: impl Peripheral<P = U> + 'd,
267 timer: impl Peripheral<P = T> + 'd,
268 ppi_ch1: PeripheralRef<'d, AnyConfigurableChannel>,
269 ppi_ch2: PeripheralRef<'d, AnyConfigurableChannel>,
270 ppi_group: PeripheralRef<'d, AnyGroup>,
271 rxd: PeripheralRef<'d, AnyPin>,
272 txd: PeripheralRef<'d, AnyPin>,
273 cts: Option<PeripheralRef<'d, AnyPin>>,
274 rts: Option<PeripheralRef<'d, AnyPin>>,
275 config: Config,
276 rx_buffer: &'d mut [u8],
277 tx_buffer: &'d mut [u8],
278 ) -> Self {
279 into_ref!(peri, timer);
280
281 assert!(rx_buffer.len() % 2 == 0);
104 282
105 let mut timer = Timer::new(timer); 283 let r = U::regs();
106 284
107 rxd.conf().write(|w| w.input().connect().drive().h0h1()); 285 rxd.conf().write(|w| w.input().connect().drive().h0h1());
108 r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) }); 286 r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) });
@@ -111,361 +289,388 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
111 txd.conf().write(|w| w.dir().output().drive().h0h1()); 289 txd.conf().write(|w| w.dir().output().drive().h0h1());
112 r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) }); 290 r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) });
113 291
114 cts.conf().write(|w| w.input().connect().drive().h0h1()); 292 if let Some(pin) = &cts {
293 pin.conf().write(|w| w.input().connect().drive().h0h1());
294 }
115 r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) }); 295 r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) });
116 296
117 rts.set_high(); 297 if let Some(pin) = &rts {
118 rts.conf().write(|w| w.dir().output().drive().h0h1()); 298 pin.set_high();
299 pin.conf().write(|w| w.dir().output().drive().h0h1());
300 }
119 r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) }); 301 r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) });
120 302
121 r.baudrate.write(|w| w.baudrate().variant(config.baudrate)); 303 // Initialize state
122 r.config.write(|w| w.parity().variant(config.parity)); 304 let s = U::buffered_state();
305 s.tx_count.store(0, Ordering::Relaxed);
306 s.rx_bufs.store(0, Ordering::Relaxed);
307 let len = tx_buffer.len();
308 unsafe { s.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
309 let len = rx_buffer.len();
310 unsafe { s.rx_buf.init(rx_buffer.as_mut_ptr(), len) };
123 311
124 // Configure 312 // Configure
125 r.config.write(|w| { 313 r.config.write(|w| {
126 w.hwfc().bit(true); 314 w.hwfc().bit(false);
127 w.parity().variant(config.parity); 315 w.parity().variant(config.parity);
128 w 316 w
129 }); 317 });
130 r.baudrate.write(|w| w.baudrate().variant(config.baudrate)); 318 r.baudrate.write(|w| w.baudrate().variant(config.baudrate));
131 319
132 // Enable interrupts 320 // clear errors
133 r.intenset.write(|w| w.endrx().set().endtx().set()); 321 let errors = r.errorsrc.read().bits();
322 r.errorsrc.write(|w| unsafe { w.bits(errors) });
323
324 r.events_rxstarted.reset();
325 r.events_txstarted.reset();
326 r.events_error.reset();
327 r.events_endrx.reset();
328 r.events_endtx.reset();
134 329
135 // Disable the irq, let the Registration enable it when everything is set up. 330 // Enable interrupts
136 irq.disable(); 331 r.intenclr.write(|w| unsafe { w.bits(!0) });
137 irq.pend(); 332 r.intenset.write(|w| {
333 w.endtx().set();
334 w.rxstarted().set();
335 w.error().set();
336 w
337 });
138 338
139 // Enable UARTE instance 339 // Enable UARTE instance
140 apply_workaround_for_enable_anomaly(&r); 340 apply_workaround_for_enable_anomaly(&r);
141 r.enable.write(|w| w.enable().enabled()); 341 r.enable.write(|w| w.enable().enabled());
142 342
143 // BAUDRATE register values are `baudrate * 2^32 / 16000000` 343 // Configure byte counter.
144 // source: https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values 344 let timer = Timer::new_counter(timer);
145 // 345 timer.cc(1).write(rx_buffer.len() as u32 * 2);
146 // We want to stop RX if line is idle for 2 bytes worth of time 346 timer.cc(1).short_compare_clear();
147 // That is 20 bits (each byte is 1 start bit + 8 data bits + 1 stop bit) 347 timer.clear();
148 // This gives us the amount of 16M ticks for 20 bits. 348 timer.start();
149 let timeout = 0x8000_0000 / (config.baudrate as u32 / 40);
150 349
151 timer.set_frequency(Frequency::F16MHz); 350 let mut ppi_ch1 = Ppi::new_one_to_one(ppi_ch1, Event::from_reg(&r.events_rxdrdy), timer.task_count());
152 timer.cc(0).write(timeout);
153 timer.cc(0).short_compare_clear();
154 timer.cc(0).short_compare_stop();
155
156 let mut ppi_ch1 = Ppi::new_one_to_two(
157 ppi_ch1.map_into(),
158 Event::from_reg(&r.events_rxdrdy),
159 timer.task_clear(),
160 timer.task_start(),
161 );
162 ppi_ch1.enable(); 351 ppi_ch1.enable();
163 352
164 let mut ppi_ch2 = Ppi::new_one_to_one( 353 s.rx_ppi_ch.store(ppi_ch2.number() as u8, Ordering::Relaxed);
165 ppi_ch2.map_into(), 354 let mut ppi_group = PpiGroup::new(ppi_group);
166 timer.cc(0).event_compare(), 355 let mut ppi_ch2 = Ppi::new_one_to_two(
167 Task::from_reg(&r.tasks_stoprx), 356 ppi_ch2,
357 Event::from_reg(&r.events_endrx),
358 Task::from_reg(&r.tasks_startrx),
359 ppi_group.task_disable_all(),
168 ); 360 );
169 ppi_ch2.enable(); 361 ppi_ch2.disable();
362 ppi_group.add_channel(&ppi_ch2);
363
364 U::Interrupt::pend();
365 unsafe { U::Interrupt::enable() };
170 366
171 Self { 367 Self {
172 inner: PeripheralMutex::new(irq, &mut state.0, move || StateInner { 368 _peri: peri,
173 _peri: peri, 369 timer,
174 timer, 370 _ppi_ch1: ppi_ch1,
175 _ppi_ch1: ppi_ch1, 371 _ppi_ch2: ppi_ch2,
176 _ppi_ch2: ppi_ch2, 372 _ppi_group: ppi_group,
177
178 rx: RingBuffer::new(rx_buffer),
179 rx_state: RxState::Idle,
180 rx_waker: WakerRegistration::new(),
181
182 tx: RingBuffer::new(tx_buffer),
183 tx_state: TxState::Idle,
184 tx_waker: WakerRegistration::new(),
185 }),
186 } 373 }
187 } 374 }
188 375
376 fn pend_irq() {
377 U::Interrupt::pend()
378 }
379
189 /// Adjust the baud rate to the provided value. 380 /// Adjust the baud rate to the provided value.
190 pub fn set_baudrate(&mut self, baudrate: Baudrate) { 381 pub fn set_baudrate(&mut self, baudrate: Baudrate) {
191 self.inner.with(|state| { 382 let r = U::regs();
192 let r = U::regs(); 383 r.baudrate.write(|w| w.baudrate().variant(baudrate));
384 }
193 385
194 let timeout = 0x8000_0000 / (baudrate as u32 / 40); 386 /// Split the UART in reader and writer parts.
195 state.timer.cc(0).write(timeout); 387 ///
196 state.timer.clear(); 388 /// This allows reading and writing concurrently from independent tasks.
389 pub fn split<'u>(&'u mut self) -> (BufferedUarteRx<'u, 'd, U, T>, BufferedUarteTx<'u, 'd, U, T>) {
390 (BufferedUarteRx { inner: self }, BufferedUarteTx { inner: self })
391 }
197 392
198 r.baudrate.write(|w| w.baudrate().variant(baudrate)); 393 async fn inner_read(&self, buf: &mut [u8]) -> Result<usize, Error> {
199 }); 394 let data = self.inner_fill_buf().await?;
395 let n = data.len().min(buf.len());
396 buf[..n].copy_from_slice(&data[..n]);
397 self.inner_consume(n);
398 Ok(n)
200 } 399 }
201}
202 400
203impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::Io for BufferedUarte<'d, U, T> { 401 async fn inner_write<'a>(&'a self, buf: &'a [u8]) -> Result<usize, Error> {
204 type Error = core::convert::Infallible; 402 poll_fn(move |cx| {
205} 403 //trace!("poll_write: {:?}", buf.len());
404 let s = U::buffered_state();
405 let mut tx = unsafe { s.tx_buf.writer() };
406
407 let tx_buf = tx.push_slice();
408 if tx_buf.is_empty() {
409 //trace!("poll_write: pending");
410 s.tx_waker.register(cx.waker());
411 return Poll::Pending;
412 }
413
414 let n = min(tx_buf.len(), buf.len());
415 tx_buf[..n].copy_from_slice(&buf[..n]);
416 tx.push_done(n);
417
418 //trace!("poll_write: queued {:?}", n);
206 419
207impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Read for BufferedUarte<'d, U, T> { 420 compiler_fence(Ordering::SeqCst);
208 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 421 Self::pend_irq();
209 where
210 Self: 'a;
211 422
212 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { 423 Poll::Ready(Ok(n))
424 })
425 .await
426 }
427
428 async fn inner_flush<'a>(&'a self) -> Result<(), Error> {
213 poll_fn(move |cx| { 429 poll_fn(move |cx| {
214 let mut do_pend = false; 430 //trace!("poll_flush");
215 let res = self.inner.with(|state| { 431 let s = U::buffered_state();
216 compiler_fence(Ordering::SeqCst); 432 if !s.tx_buf.is_empty() {
217 trace!("poll_read"); 433 //trace!("poll_flush: pending");
218 434 s.tx_waker.register(cx.waker());
219 // We have data ready in buffer? Return it. 435 return Poll::Pending;
220 let data = state.rx.pop_buf();
221 if !data.is_empty() {
222 trace!(" got {:?} {:?}", data.as_ptr() as u32, data.len());
223 let len = data.len().min(buf.len());
224 buf[..len].copy_from_slice(&data[..len]);
225 state.rx.pop(len);
226 do_pend = true;
227 return Poll::Ready(Ok(len));
228 }
229
230 trace!(" empty");
231 state.rx_waker.register(cx.waker());
232 Poll::Pending
233 });
234 if do_pend {
235 self.inner.pend();
236 } 436 }
237 437
238 res 438 Poll::Ready(Ok(()))
239 }) 439 })
440 .await
240 } 441 }
241}
242
243impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::BufRead for BufferedUarte<'d, U, T> {
244 type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>>
245 where
246 Self: 'a;
247 442
248 fn fill_buf<'a>(&'a mut self) -> Self::FillBufFuture<'a> { 443 async fn inner_fill_buf<'a>(&'a self) -> Result<&'a [u8], Error> {
249 poll_fn(move |cx| { 444 poll_fn(move |cx| {
250 self.inner.with(|state| { 445 compiler_fence(Ordering::SeqCst);
251 compiler_fence(Ordering::SeqCst); 446 //trace!("poll_read");
252 trace!("fill_buf"); 447
253 448 let r = U::regs();
254 // We have data ready in buffer? Return it. 449 let s = U::buffered_state();
255 let buf = state.rx.pop_buf(); 450
256 if !buf.is_empty() { 451 // Read the RXDRDY counter.
257 trace!(" got {:?} {:?}", buf.as_ptr() as u32, buf.len()); 452 T::regs().tasks_capture[0].write(|w| unsafe { w.bits(1) });
258 let buf: &[u8] = buf; 453 let mut end = T::regs().cc[0].read().bits() as usize;
259 // Safety: buffer lives as long as uart 454 //trace!(" rxdrdy count = {:?}", end);
260 let buf: &[u8] = unsafe { core::mem::transmute(buf) }; 455
261 return Poll::Ready(Ok(buf)); 456 // We've set a compare channel that resets the counter to 0 when it reaches `len*2`.
262 } 457 // However, it's unclear if that's instant, or there's a small window where you can
263 458 // still read `len()*2`.
264 trace!(" empty"); 459 // This could happen if in one clock cycle the counter is updated, and in the next the
265 state.rx_waker.register(cx.waker()); 460 // clear takes effect. The docs are very sparse, they just say "Task delays: After TIMER
266 Poll::<Result<&[u8], Self::Error>>::Pending 461 // is started, the CLEAR, COUNT, and STOP tasks are guaranteed to take effect within one
267 }) 462 // clock cycle of the PCLK16M." :shrug:
463 // So, we wrap the counter ourselves, just in case.
464 if end > s.rx_buf.len() * 2 {
465 end = 0
466 }
467
468 // This logic mirrors `atomic_ring_buffer::Reader::pop_buf()`
469 let mut start = s.rx_buf.start.load(Ordering::Relaxed);
470 let len = s.rx_buf.len();
471 if start == end {
472 //trace!(" empty");
473 s.rx_waker.register(cx.waker());
474 r.intenset.write(|w| w.rxdrdy().set_bit());
475 return Poll::Pending;
476 }
477
478 if start >= len {
479 start -= len
480 }
481 if end >= len {
482 end -= len
483 }
484
485 let n = if end > start { end - start } else { len - start };
486 assert!(n != 0);
487 //trace!(" uarte ringbuf: pop_buf {:?}..{:?}", start, start + n);
488
489 let buf = s.rx_buf.buf.load(Ordering::Relaxed);
490 Poll::Ready(Ok(unsafe { slice::from_raw_parts(buf.add(start), n) }))
268 }) 491 })
492 .await
269 } 493 }
270 494
271 fn consume(&mut self, amt: usize) { 495 fn inner_consume(&self, amt: usize) {
272 let signal = self.inner.with(|state| { 496 if amt == 0 {
273 let full = state.rx.is_full(); 497 return;
274 state.rx.pop(amt);
275 full
276 });
277 if signal {
278 self.inner.pend();
279 } 498 }
280 }
281}
282 499
283impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Write for BufferedUarte<'d, U, T> { 500 let s = U::buffered_state();
284 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 501 let mut rx = unsafe { s.rx_buf.reader() };
285 where 502 rx.pop_done(amt);
286 Self: 'a; 503 U::regs().intenset.write(|w| w.rxstarted().set());
504 }
287 505
288 fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { 506 /// Pull some bytes from this source into the specified buffer, returning how many bytes were read.
289 poll_fn(move |cx| { 507 pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
290 let res = self.inner.with(|state| { 508 self.inner_read(buf).await
291 trace!("poll_write: {:?}", buf.len()); 509 }
292 510
293 let tx_buf = state.tx.push_buf(); 511 /// Return the contents of the internal buffer, filling it with more data from the inner reader if it is empty.
294 if tx_buf.is_empty() { 512 pub async fn fill_buf(&mut self) -> Result<&[u8], Error> {
295 trace!("poll_write: pending"); 513 self.inner_fill_buf().await
296 state.tx_waker.register(cx.waker()); 514 }
297 return Poll::Pending;
298 }
299 515
300 let n = min(tx_buf.len(), buf.len()); 516 /// Tell this buffer that `amt` bytes have been consumed from the buffer, so they should no longer be returned in calls to `fill_buf`.
301 tx_buf[..n].copy_from_slice(&buf[..n]); 517 pub fn consume(&mut self, amt: usize) {
302 state.tx.push(n); 518 self.inner_consume(amt)
519 }
303 520
304 trace!("poll_write: queued {:?}", n); 521 /// Write a buffer into this writer, returning how many bytes were written.
522 pub async fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
523 self.inner_write(buf).await
524 }
305 525
306 compiler_fence(Ordering::SeqCst); 526 /// Flush this output stream, ensuring that all intermediately buffered contents reach their destination.
527 pub async fn flush(&mut self) -> Result<(), Error> {
528 self.inner_flush().await
529 }
530}
307 531
308 Poll::Ready(Ok(n)) 532/// Reader part of the buffered UARTE driver.
309 }); 533pub struct BufferedUarteTx<'u, 'd, U: UarteInstance, T: TimerInstance> {
534 inner: &'u BufferedUarte<'d, U, T>,
535}
310 536
311 self.inner.pend(); 537impl<'u, 'd, U: UarteInstance, T: TimerInstance> BufferedUarteTx<'u, 'd, U, T> {
538 /// Write a buffer into this writer, returning how many bytes were written.
539 pub async fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
540 self.inner.inner_write(buf).await
541 }
312 542
313 res 543 /// Flush this output stream, ensuring that all intermediately buffered contents reach their destination.
314 }) 544 pub async fn flush(&mut self) -> Result<(), Error> {
545 self.inner.inner_flush().await
315 } 546 }
547}
316 548
317 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> 549/// Writer part of the buffered UARTE driver.
318 where 550pub struct BufferedUarteRx<'u, 'd, U: UarteInstance, T: TimerInstance> {
319 Self: 'a; 551 inner: &'u BufferedUarte<'d, U, T>,
552}
320 553
321 fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { 554impl<'u, 'd, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'u, 'd, U, T> {
322 poll_fn(move |cx| { 555 /// Pull some bytes from this source into the specified buffer, returning how many bytes were read.
323 self.inner.with(|state| { 556 pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
324 trace!("poll_flush"); 557 self.inner.inner_read(buf).await
558 }
325 559
326 if !state.tx.is_empty() { 560 /// Return the contents of the internal buffer, filling it with more data from the inner reader if it is empty.
327 trace!("poll_flush: pending"); 561 pub async fn fill_buf(&mut self) -> Result<&[u8], Error> {
328 state.tx_waker.register(cx.waker()); 562 self.inner.inner_fill_buf().await
329 return Poll::Pending; 563 }
330 }
331 564
332 Poll::Ready(Ok(())) 565 /// Tell this buffer that `amt` bytes have been consumed from the buffer, so they should no longer be returned in calls to `fill_buf`.
333 }) 566 pub fn consume(&mut self, amt: usize) {
334 }) 567 self.inner.inner_consume(amt)
335 } 568 }
336} 569}
337 570
338impl<'a, U: UarteInstance, T: TimerInstance> Drop for StateInner<'a, U, T> { 571#[cfg(feature = "nightly")]
339 fn drop(&mut self) { 572mod _embedded_io {
340 let r = U::regs(); 573 use super::*;
341 574
342 // TODO this probably deadlocks. do like Uarte instead. 575 impl embedded_io::Error for Error {
576 fn kind(&self) -> embedded_io::ErrorKind {
577 match *self {}
578 }
579 }
343 580
344 self.timer.stop(); 581 impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::Io for BufferedUarte<'d, U, T> {
345 if let RxState::Receiving = self.rx_state { 582 type Error = Error;
346 r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); 583 }
584
585 impl<'u, 'd, U: UarteInstance, T: TimerInstance> embedded_io::Io for BufferedUarteRx<'u, 'd, U, T> {
586 type Error = Error;
587 }
588
589 impl<'u, 'd, U: UarteInstance, T: TimerInstance> embedded_io::Io for BufferedUarteTx<'u, 'd, U, T> {
590 type Error = Error;
591 }
592
593 impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Read for BufferedUarte<'d, U, T> {
594 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
595 self.inner_read(buf).await
347 } 596 }
348 if let TxState::Transmitting(_) = self.tx_state { 597 }
349 r.tasks_stoptx.write(|w| unsafe { w.bits(1) }); 598
599 impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Read for BufferedUarteRx<'u, 'd, U, T> {
600 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
601 self.inner.inner_read(buf).await
350 } 602 }
351 if let RxState::Receiving = self.rx_state { 603 }
352 low_power_wait_until(|| r.events_endrx.read().bits() == 1); 604
605 impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::BufRead for BufferedUarte<'d, U, T> {
606 async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
607 self.inner_fill_buf().await
353 } 608 }
354 if let TxState::Transmitting(_) = self.tx_state { 609
355 low_power_wait_until(|| r.events_endtx.read().bits() == 1); 610 fn consume(&mut self, amt: usize) {
611 self.inner_consume(amt)
356 } 612 }
357 } 613 }
358}
359 614
360impl<'a, U: UarteInstance, T: TimerInstance> PeripheralState for StateInner<'a, U, T> { 615 impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::BufRead for BufferedUarteRx<'u, 'd, U, T> {
361 type Interrupt = U::Interrupt; 616 async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
362 fn on_interrupt(&mut self) { 617 self.inner.inner_fill_buf().await
363 trace!("irq: start"); 618 }
364 let r = U::regs();
365 619
366 loop { 620 fn consume(&mut self, amt: usize) {
367 match self.rx_state { 621 self.inner.inner_consume(amt)
368 RxState::Idle => {
369 trace!(" irq_rx: in state idle");
370
371 let buf = self.rx.push_buf();
372 if !buf.is_empty() {
373 trace!(" irq_rx: starting {:?}", buf.len());
374 self.rx_state = RxState::Receiving;
375
376 // Set up the DMA read
377 r.rxd.ptr.write(|w|
378 // The PTR field is a full 32 bits wide and accepts the full range
379 // of values.
380 unsafe { w.ptr().bits(buf.as_ptr() as u32) });
381 r.rxd.maxcnt.write(|w|
382 // We're giving it the length of the buffer, so no danger of
383 // accessing invalid memory. We have verified that the length of the
384 // buffer fits in an `u8`, so the cast to `u8` is also fine.
385 //
386 // The MAXCNT field is at least 8 bits wide and accepts the full
387 // range of values.
388 unsafe { w.maxcnt().bits(buf.len() as _) });
389 trace!(" irq_rx: buf {:?} {:?}", buf.as_ptr() as u32, buf.len());
390
391 // Start UARTE Receive transaction
392 r.tasks_startrx.write(|w| unsafe { w.bits(1) });
393 }
394 break;
395 }
396 RxState::Receiving => {
397 trace!(" irq_rx: in state receiving");
398 if r.events_endrx.read().bits() != 0 {
399 self.timer.stop();
400
401 let n: usize = r.rxd.amount.read().amount().bits() as usize;
402 trace!(" irq_rx: endrx {:?}", n);
403 self.rx.push(n);
404
405 r.events_endrx.reset();
406
407 self.rx_waker.wake();
408 self.rx_state = RxState::Idle;
409 } else {
410 break;
411 }
412 }
413 }
414 } 622 }
623 }
415 624
416 loop { 625 impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Write for BufferedUarte<'d, U, T> {
417 match self.tx_state { 626 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
418 TxState::Idle => { 627 self.inner_write(buf).await
419 trace!(" irq_tx: in state Idle"); 628 }
420 let buf = self.tx.pop_buf(); 629
421 if !buf.is_empty() { 630 async fn flush(&mut self) -> Result<(), Self::Error> {
422 trace!(" irq_tx: starting {:?}", buf.len()); 631 self.inner_flush().await
423 self.tx_state = TxState::Transmitting(buf.len()); 632 }
424 633 }
425 // Set up the DMA write 634
426 r.txd.ptr.write(|w| 635 impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Write for BufferedUarteTx<'u, 'd, U, T> {
427 // The PTR field is a full 32 bits wide and accepts the full range 636 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
428 // of values. 637 self.inner.inner_write(buf).await
429 unsafe { w.ptr().bits(buf.as_ptr() as u32) }); 638 }
430 r.txd.maxcnt.write(|w| 639
431 // We're giving it the length of the buffer, so no danger of 640 async fn flush(&mut self) -> Result<(), Self::Error> {
432 // accessing invalid memory. We have verified that the length of the 641 self.inner.inner_flush().await
433 // buffer fits in an `u8`, so the cast to `u8` is also fine.
434 //
435 // The MAXCNT field is 8 bits wide and accepts the full range of
436 // values.
437 unsafe { w.maxcnt().bits(buf.len() as _) });
438
439 // Start UARTE Transmit transaction
440 r.tasks_starttx.write(|w| unsafe { w.bits(1) });
441 }
442 break;
443 }
444 TxState::Transmitting(n) => {
445 trace!(" irq_tx: in state Transmitting");
446 if r.events_endtx.read().bits() != 0 {
447 r.events_endtx.reset();
448
449 trace!(" irq_tx: endtx {:?}", n);
450 self.tx.pop(n);
451 self.tx_waker.wake();
452 self.tx_state = TxState::Idle;
453 } else {
454 break;
455 }
456 }
457 }
458 } 642 }
459 trace!("irq: end");
460 } 643 }
461} 644}
462 645
463/// Low power blocking wait loop using WFE/SEV. 646impl<'a, U: UarteInstance, T: TimerInstance> Drop for BufferedUarte<'a, U, T> {
464fn low_power_wait_until(mut condition: impl FnMut() -> bool) { 647 fn drop(&mut self) {
465 while !condition() { 648 self._ppi_group.disable_all();
466 // WFE might "eat" an event that would have otherwise woken the executor. 649
467 cortex_m::asm::wfe(); 650 let r = U::regs();
651
652 self.timer.stop();
653
654 r.inten.reset();
655 r.events_rxto.reset();
656 r.tasks_stoprx.write(|w| unsafe { w.bits(1) });
657 r.events_txstopped.reset();
658 r.tasks_stoptx.write(|w| unsafe { w.bits(1) });
659
660 while r.events_txstopped.read().bits() == 0 {}
661 while r.events_rxto.read().bits() == 0 {}
662
663 r.enable.write(|w| w.enable().disabled());
664
665 gpio::deconfigure_pin(r.psel.rxd.read().bits());
666 gpio::deconfigure_pin(r.psel.txd.read().bits());
667 gpio::deconfigure_pin(r.psel.rts.read().bits());
668 gpio::deconfigure_pin(r.psel.cts.read().bits());
669
670 let s = U::buffered_state();
671 unsafe {
672 s.rx_buf.deinit();
673 s.tx_buf.deinit();
674 }
468 } 675 }
469 // Retrigger an event to be transparent to the executor.
470 cortex_m::asm::sev();
471} 676}
diff --git a/embassy-nrf/src/chips/nrf52805.rs b/embassy-nrf/src/chips/nrf52805.rs
index d078fa0ad..8776000c8 100644
--- a/embassy-nrf/src/chips/nrf52805.rs
+++ b/embassy-nrf/src/chips/nrf52805.rs
@@ -6,6 +6,8 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 256;
6 6
7pub const FLASH_SIZE: usize = 192 * 1024; 7pub const FLASH_SIZE: usize = 192 * 1024;
8 8
9pub const RESET_PIN: u32 = 21;
10
9embassy_hal_common::peripherals! { 11embassy_hal_common::peripherals! {
10 // RTC 12 // RTC
11 RTC0, 13 RTC0,
@@ -108,6 +110,7 @@ embassy_hal_common::peripherals! {
108 P0_18, 110 P0_18,
109 P0_19, 111 P0_19,
110 P0_20, 112 P0_20,
113 #[cfg(feature="reset-pin-as-gpio")]
111 P0_21, 114 P0_21,
112 P0_22, 115 P0_22,
113 P0_23, 116 P0_23,
@@ -131,8 +134,16 @@ impl_uarte!(UARTE0, UARTE0, UARTE0_UART0);
131 134
132impl_spim!(SPI0, SPIM0, SPIM0_SPIS0_SPI0); 135impl_spim!(SPI0, SPIM0, SPIM0_SPIS0_SPI0);
133 136
137impl_spis!(SPI0, SPIS0, SPIM0_SPIS0_SPI0);
138
134impl_twim!(TWI0, TWIM0, TWIM0_TWIS0_TWI0); 139impl_twim!(TWI0, TWIM0, TWIM0_TWIS0_TWI0);
135 140
141impl_twis!(TWI0, TWIS0, TWIM0_TWIS0_TWI0);
142
143impl_qdec!(QDEC, QDEC, QDEC);
144
145impl_rng!(RNG, RNG, RNG);
146
136impl_timer!(TIMER0, TIMER0, TIMER0); 147impl_timer!(TIMER0, TIMER0, TIMER0);
137impl_timer!(TIMER1, TIMER1, TIMER1); 148impl_timer!(TIMER1, TIMER1, TIMER1);
138impl_timer!(TIMER2, TIMER2, TIMER2); 149impl_timer!(TIMER2, TIMER2, TIMER2);
@@ -158,6 +169,7 @@ impl_pin!(P0_17, 0, 17);
158impl_pin!(P0_18, 0, 18); 169impl_pin!(P0_18, 0, 18);
159impl_pin!(P0_19, 0, 19); 170impl_pin!(P0_19, 0, 19);
160impl_pin!(P0_20, 0, 20); 171impl_pin!(P0_20, 0, 20);
172#[cfg(feature = "reset-pin-as-gpio")]
161impl_pin!(P0_21, 0, 21); 173impl_pin!(P0_21, 0, 21);
162impl_pin!(P0_22, 0, 22); 174impl_pin!(P0_22, 0, 22);
163impl_pin!(P0_23, 0, 23); 175impl_pin!(P0_23, 0, 23);
@@ -193,36 +205,32 @@ impl_ppi_channel!(PPI_CH29, 29 => static);
193impl_ppi_channel!(PPI_CH30, 30 => static); 205impl_ppi_channel!(PPI_CH30, 30 => static);
194impl_ppi_channel!(PPI_CH31, 31 => static); 206impl_ppi_channel!(PPI_CH31, 31 => static);
195 207
196impl_saadc_input!(P0_04, ANALOGINPUT2); 208impl_saadc_input!(P0_04, ANALOG_INPUT2);
197impl_saadc_input!(P0_05, ANALOGINPUT3); 209impl_saadc_input!(P0_05, ANALOG_INPUT3);
198 210
199pub mod irqs { 211embassy_hal_common::interrupt_mod!(
200 use embassy_cortex_m::interrupt::_export::declare; 212 POWER_CLOCK,
201 213 RADIO,
202 use crate::pac::Interrupt as InterruptEnum; 214 UARTE0_UART0,
203 215 TWIM0_TWIS0_TWI0,
204 declare!(POWER_CLOCK); 216 SPIM0_SPIS0_SPI0,
205 declare!(RADIO); 217 GPIOTE,
206 declare!(UARTE0_UART0); 218 SAADC,
207 declare!(TWIM0_TWIS0_TWI0); 219 TIMER0,
208 declare!(SPIM0_SPIS0_SPI0); 220 TIMER1,
209 declare!(GPIOTE); 221 TIMER2,
210 declare!(SAADC); 222 RTC0,
211 declare!(TIMER0); 223 TEMP,
212 declare!(TIMER1); 224 RNG,
213 declare!(TIMER2); 225 ECB,
214 declare!(RTC0); 226 CCM_AAR,
215 declare!(TEMP); 227 WDT,
216 declare!(RNG); 228 RTC1,
217 declare!(ECB); 229 QDEC,
218 declare!(CCM_AAR); 230 SWI0_EGU0,
219 declare!(WDT); 231 SWI1_EGU1,
220 declare!(RTC1); 232 SWI2,
221 declare!(QDEC); 233 SWI3,
222 declare!(SWI0_EGU0); 234 SWI4,
223 declare!(SWI1_EGU1); 235 SWI5,
224 declare!(SWI2); 236);
225 declare!(SWI3);
226 declare!(SWI4);
227 declare!(SWI5);
228}
diff --git a/embassy-nrf/src/chips/nrf52810.rs b/embassy-nrf/src/chips/nrf52810.rs
index 3e500098c..5519e8953 100644
--- a/embassy-nrf/src/chips/nrf52810.rs
+++ b/embassy-nrf/src/chips/nrf52810.rs
@@ -6,6 +6,8 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 256;
6 6
7pub const FLASH_SIZE: usize = 192 * 1024; 7pub const FLASH_SIZE: usize = 192 * 1024;
8 8
9pub const RESET_PIN: u32 = 21;
10
9embassy_hal_common::peripherals! { 11embassy_hal_common::peripherals! {
10 // RTC 12 // RTC
11 RTC0, 13 RTC0,
@@ -111,6 +113,7 @@ embassy_hal_common::peripherals! {
111 P0_18, 113 P0_18,
112 P0_19, 114 P0_19,
113 P0_20, 115 P0_20,
116 #[cfg(feature="reset-pin-as-gpio")]
114 P0_21, 117 P0_21,
115 P0_22, 118 P0_22,
116 P0_23, 119 P0_23,
@@ -137,10 +140,20 @@ impl_uarte!(UARTE0, UARTE0, UARTE0_UART0);
137 140
138impl_spim!(SPI0, SPIM0, SPIM0_SPIS0_SPI0); 141impl_spim!(SPI0, SPIM0, SPIM0_SPIS0_SPI0);
139 142
143impl_spis!(SPI0, SPIS0, SPIM0_SPIS0_SPI0);
144
140impl_twim!(TWI0, TWIM0, TWIM0_TWIS0_TWI0); 145impl_twim!(TWI0, TWIM0, TWIM0_TWIS0_TWI0);
141 146
147impl_twis!(TWI0, TWIS0, TWIM0_TWIS0_TWI0);
148
142impl_pwm!(PWM0, PWM0, PWM0); 149impl_pwm!(PWM0, PWM0, PWM0);
143 150
151impl_pdm!(PDM, PDM, PDM);
152
153impl_qdec!(QDEC, QDEC, QDEC);
154
155impl_rng!(RNG, RNG, RNG);
156
144impl_timer!(TIMER0, TIMER0, TIMER0); 157impl_timer!(TIMER0, TIMER0, TIMER0);
145impl_timer!(TIMER1, TIMER1, TIMER1); 158impl_timer!(TIMER1, TIMER1, TIMER1);
146impl_timer!(TIMER2, TIMER2, TIMER2); 159impl_timer!(TIMER2, TIMER2, TIMER2);
@@ -166,6 +179,7 @@ impl_pin!(P0_17, 0, 17);
166impl_pin!(P0_18, 0, 18); 179impl_pin!(P0_18, 0, 18);
167impl_pin!(P0_19, 0, 19); 180impl_pin!(P0_19, 0, 19);
168impl_pin!(P0_20, 0, 20); 181impl_pin!(P0_20, 0, 20);
182#[cfg(feature = "reset-pin-as-gpio")]
169impl_pin!(P0_21, 0, 21); 183impl_pin!(P0_21, 0, 21);
170impl_pin!(P0_22, 0, 22); 184impl_pin!(P0_22, 0, 22);
171impl_pin!(P0_23, 0, 23); 185impl_pin!(P0_23, 0, 23);
@@ -211,45 +225,41 @@ impl_ppi_channel!(PPI_CH29, 29 => static);
211impl_ppi_channel!(PPI_CH30, 30 => static); 225impl_ppi_channel!(PPI_CH30, 30 => static);
212impl_ppi_channel!(PPI_CH31, 31 => static); 226impl_ppi_channel!(PPI_CH31, 31 => static);
213 227
214impl_saadc_input!(P0_02, ANALOGINPUT0); 228impl_saadc_input!(P0_02, ANALOG_INPUT0);
215impl_saadc_input!(P0_03, ANALOGINPUT1); 229impl_saadc_input!(P0_03, ANALOG_INPUT1);
216impl_saadc_input!(P0_04, ANALOGINPUT2); 230impl_saadc_input!(P0_04, ANALOG_INPUT2);
217impl_saadc_input!(P0_05, ANALOGINPUT3); 231impl_saadc_input!(P0_05, ANALOG_INPUT3);
218impl_saadc_input!(P0_28, ANALOGINPUT4); 232impl_saadc_input!(P0_28, ANALOG_INPUT4);
219impl_saadc_input!(P0_29, ANALOGINPUT5); 233impl_saadc_input!(P0_29, ANALOG_INPUT5);
220impl_saadc_input!(P0_30, ANALOGINPUT6); 234impl_saadc_input!(P0_30, ANALOG_INPUT6);
221impl_saadc_input!(P0_31, ANALOGINPUT7); 235impl_saadc_input!(P0_31, ANALOG_INPUT7);
222 236
223pub mod irqs { 237embassy_hal_common::interrupt_mod!(
224 use embassy_cortex_m::interrupt::_export::declare; 238 POWER_CLOCK,
225 239 RADIO,
226 use crate::pac::Interrupt as InterruptEnum; 240 UARTE0_UART0,
227 241 TWIM0_TWIS0_TWI0,
228 declare!(POWER_CLOCK); 242 SPIM0_SPIS0_SPI0,
229 declare!(RADIO); 243 GPIOTE,
230 declare!(UARTE0_UART0); 244 SAADC,
231 declare!(TWIM0_TWIS0_TWI0); 245 TIMER0,
232 declare!(SPIM0_SPIS0_SPI0); 246 TIMER1,
233 declare!(GPIOTE); 247 TIMER2,
234 declare!(SAADC); 248 RTC0,
235 declare!(TIMER0); 249 TEMP,
236 declare!(TIMER1); 250 RNG,
237 declare!(TIMER2); 251 ECB,
238 declare!(RTC0); 252 CCM_AAR,
239 declare!(TEMP); 253 WDT,
240 declare!(RNG); 254 RTC1,
241 declare!(ECB); 255 QDEC,
242 declare!(CCM_AAR); 256 COMP,
243 declare!(WDT); 257 SWI0_EGU0,
244 declare!(RTC1); 258 SWI1_EGU1,
245 declare!(QDEC); 259 SWI2,
246 declare!(COMP); 260 SWI3,
247 declare!(SWI0_EGU0); 261 SWI4,
248 declare!(SWI1_EGU1); 262 SWI5,
249 declare!(SWI2); 263 PWM0,
250 declare!(SWI3); 264 PDM,
251 declare!(SWI4); 265);
252 declare!(SWI5);
253 declare!(PWM0);
254 declare!(PDM);
255}
diff --git a/embassy-nrf/src/chips/nrf52811.rs b/embassy-nrf/src/chips/nrf52811.rs
index 25c7c0d91..d5367c59a 100644
--- a/embassy-nrf/src/chips/nrf52811.rs
+++ b/embassy-nrf/src/chips/nrf52811.rs
@@ -6,6 +6,8 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 256;
6 6
7pub const FLASH_SIZE: usize = 192 * 1024; 7pub const FLASH_SIZE: usize = 192 * 1024;
8 8
9pub const RESET_PIN: u32 = 21;
10
9embassy_hal_common::peripherals! { 11embassy_hal_common::peripherals! {
10 // RTC 12 // RTC
11 RTC0, 13 RTC0,
@@ -111,6 +113,7 @@ embassy_hal_common::peripherals! {
111 P0_18, 113 P0_18,
112 P0_19, 114 P0_19,
113 P0_20, 115 P0_20,
116 #[cfg(feature="reset-pin-as-gpio")]
114 P0_21, 117 P0_21,
115 P0_22, 118 P0_22,
116 P0_23, 119 P0_23,
@@ -138,10 +141,21 @@ impl_uarte!(UARTE0, UARTE0, UARTE0_UART0);
138impl_spim!(TWISPI0, SPIM0, TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0); 141impl_spim!(TWISPI0, SPIM0, TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0);
139impl_spim!(SPI1, SPIM1, SPIM1_SPIS1_SPI1); 142impl_spim!(SPI1, SPIM1, SPIM1_SPIS1_SPI1);
140 143
144impl_spis!(TWISPI0, SPIS0, TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0);
145impl_spis!(SPI1, SPIS1, SPIM1_SPIS1_SPI1);
146
141impl_twim!(TWISPI0, TWIM0, TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0); 147impl_twim!(TWISPI0, TWIM0, TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0);
142 148
149impl_twis!(TWISPI0, TWIS0, TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0);
150
143impl_pwm!(PWM0, PWM0, PWM0); 151impl_pwm!(PWM0, PWM0, PWM0);
144 152
153impl_pdm!(PDM, PDM, PDM);
154
155impl_qdec!(QDEC, QDEC, QDEC);
156
157impl_rng!(RNG, RNG, RNG);
158
145impl_timer!(TIMER0, TIMER0, TIMER0); 159impl_timer!(TIMER0, TIMER0, TIMER0);
146impl_timer!(TIMER1, TIMER1, TIMER1); 160impl_timer!(TIMER1, TIMER1, TIMER1);
147impl_timer!(TIMER2, TIMER2, TIMER2); 161impl_timer!(TIMER2, TIMER2, TIMER2);
@@ -167,6 +181,7 @@ impl_pin!(P0_17, 0, 17);
167impl_pin!(P0_18, 0, 18); 181impl_pin!(P0_18, 0, 18);
168impl_pin!(P0_19, 0, 19); 182impl_pin!(P0_19, 0, 19);
169impl_pin!(P0_20, 0, 20); 183impl_pin!(P0_20, 0, 20);
184#[cfg(feature = "reset-pin-as-gpio")]
170impl_pin!(P0_21, 0, 21); 185impl_pin!(P0_21, 0, 21);
171impl_pin!(P0_22, 0, 22); 186impl_pin!(P0_22, 0, 22);
172impl_pin!(P0_23, 0, 23); 187impl_pin!(P0_23, 0, 23);
@@ -212,45 +227,41 @@ impl_ppi_channel!(PPI_CH29, 29 => static);
212impl_ppi_channel!(PPI_CH30, 30 => static); 227impl_ppi_channel!(PPI_CH30, 30 => static);
213impl_ppi_channel!(PPI_CH31, 31 => static); 228impl_ppi_channel!(PPI_CH31, 31 => static);
214 229
215impl_saadc_input!(P0_02, ANALOGINPUT0); 230impl_saadc_input!(P0_02, ANALOG_INPUT0);
216impl_saadc_input!(P0_03, ANALOGINPUT1); 231impl_saadc_input!(P0_03, ANALOG_INPUT1);
217impl_saadc_input!(P0_04, ANALOGINPUT2); 232impl_saadc_input!(P0_04, ANALOG_INPUT2);
218impl_saadc_input!(P0_05, ANALOGINPUT3); 233impl_saadc_input!(P0_05, ANALOG_INPUT3);
219impl_saadc_input!(P0_28, ANALOGINPUT4); 234impl_saadc_input!(P0_28, ANALOG_INPUT4);
220impl_saadc_input!(P0_29, ANALOGINPUT5); 235impl_saadc_input!(P0_29, ANALOG_INPUT5);
221impl_saadc_input!(P0_30, ANALOGINPUT6); 236impl_saadc_input!(P0_30, ANALOG_INPUT6);
222impl_saadc_input!(P0_31, ANALOGINPUT7); 237impl_saadc_input!(P0_31, ANALOG_INPUT7);
223 238
224pub mod irqs { 239embassy_hal_common::interrupt_mod!(
225 use embassy_cortex_m::interrupt::_export::declare; 240 POWER_CLOCK,
226 241 RADIO,
227 use crate::pac::Interrupt as InterruptEnum; 242 UARTE0_UART0,
228 243 TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0,
229 declare!(POWER_CLOCK); 244 SPIM1_SPIS1_SPI1,
230 declare!(RADIO); 245 GPIOTE,
231 declare!(UARTE0_UART0); 246 SAADC,
232 declare!(TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0); 247 TIMER0,
233 declare!(SPIM1_SPIS1_SPI1); 248 TIMER1,
234 declare!(GPIOTE); 249 TIMER2,
235 declare!(SAADC); 250 RTC0,
236 declare!(TIMER0); 251 TEMP,
237 declare!(TIMER1); 252 RNG,
238 declare!(TIMER2); 253 ECB,
239 declare!(RTC0); 254 CCM_AAR,
240 declare!(TEMP); 255 WDT,
241 declare!(RNG); 256 RTC1,
242 declare!(ECB); 257 QDEC,
243 declare!(CCM_AAR); 258 COMP,
244 declare!(WDT); 259 SWI0_EGU0,
245 declare!(RTC1); 260 SWI1_EGU1,
246 declare!(QDEC); 261 SWI2,
247 declare!(COMP); 262 SWI3,
248 declare!(SWI0_EGU0); 263 SWI4,
249 declare!(SWI1_EGU1); 264 SWI5,
250 declare!(SWI2); 265 PWM0,
251 declare!(SWI3); 266 PDM,
252 declare!(SWI4); 267);
253 declare!(SWI5);
254 declare!(PWM0);
255 declare!(PDM);
256}
diff --git a/embassy-nrf/src/chips/nrf52820.rs b/embassy-nrf/src/chips/nrf52820.rs
index dba033b0f..785170447 100644
--- a/embassy-nrf/src/chips/nrf52820.rs
+++ b/embassy-nrf/src/chips/nrf52820.rs
@@ -6,6 +6,8 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 512;
6 6
7pub const FLASH_SIZE: usize = 256 * 1024; 7pub const FLASH_SIZE: usize = 256 * 1024;
8 8
9pub const RESET_PIN: u32 = 18;
10
9embassy_hal_common::peripherals! { 11embassy_hal_common::peripherals! {
10 // USB 12 // USB
11 USBD, 13 USBD,
@@ -106,6 +108,7 @@ embassy_hal_common::peripherals! {
106 P0_15, 108 P0_15,
107 P0_16, 109 P0_16,
108 P0_17, 110 P0_17,
111 #[cfg(feature="reset-pin-as-gpio")]
109 P0_18, 112 P0_18,
110 P0_19, 113 P0_19,
111 P0_20, 114 P0_20,
@@ -136,14 +139,24 @@ impl_uarte!(UARTE0, UARTE0, UARTE0_UART0);
136impl_spim!(TWISPI0, SPIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); 139impl_spim!(TWISPI0, SPIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
137impl_spim!(TWISPI1, SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); 140impl_spim!(TWISPI1, SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
138 141
142impl_spis!(TWISPI0, SPIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
143impl_spis!(TWISPI1, SPIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
144
139impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); 145impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
140impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); 146impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
141 147
148impl_twis!(TWISPI0, TWIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
149impl_twis!(TWISPI1, TWIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
150
142impl_timer!(TIMER0, TIMER0, TIMER0); 151impl_timer!(TIMER0, TIMER0, TIMER0);
143impl_timer!(TIMER1, TIMER1, TIMER1); 152impl_timer!(TIMER1, TIMER1, TIMER1);
144impl_timer!(TIMER2, TIMER2, TIMER2); 153impl_timer!(TIMER2, TIMER2, TIMER2);
145impl_timer!(TIMER3, TIMER3, TIMER3, extended); 154impl_timer!(TIMER3, TIMER3, TIMER3, extended);
146 155
156impl_qdec!(QDEC, QDEC, QDEC);
157
158impl_rng!(RNG, RNG, RNG);
159
147impl_pin!(P0_00, 0, 0); 160impl_pin!(P0_00, 0, 0);
148impl_pin!(P0_01, 0, 1); 161impl_pin!(P0_01, 0, 1);
149impl_pin!(P0_02, 0, 2); 162impl_pin!(P0_02, 0, 2);
@@ -162,6 +175,7 @@ impl_pin!(P0_14, 0, 14);
162impl_pin!(P0_15, 0, 15); 175impl_pin!(P0_15, 0, 15);
163impl_pin!(P0_16, 0, 16); 176impl_pin!(P0_16, 0, 16);
164impl_pin!(P0_17, 0, 17); 177impl_pin!(P0_17, 0, 17);
178#[cfg(feature = "reset-pin-as-gpio")]
165impl_pin!(P0_18, 0, 18); 179impl_pin!(P0_18, 0, 18);
166impl_pin!(P0_19, 0, 19); 180impl_pin!(P0_19, 0, 19);
167impl_pin!(P0_20, 0, 20); 181impl_pin!(P0_20, 0, 20);
@@ -210,35 +224,31 @@ impl_ppi_channel!(PPI_CH29, 29 => static);
210impl_ppi_channel!(PPI_CH30, 30 => static); 224impl_ppi_channel!(PPI_CH30, 30 => static);
211impl_ppi_channel!(PPI_CH31, 31 => static); 225impl_ppi_channel!(PPI_CH31, 31 => static);
212 226
213pub mod irqs { 227embassy_hal_common::interrupt_mod!(
214 use embassy_cortex_m::interrupt::_export::declare; 228 POWER_CLOCK,
215 229 RADIO,
216 use crate::pac::Interrupt as InterruptEnum; 230 UARTE0_UART0,
217 231 SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0,
218 declare!(POWER_CLOCK); 232 SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1,
219 declare!(RADIO); 233 GPIOTE,
220 declare!(UARTE0_UART0); 234 TIMER0,
221 declare!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); 235 TIMER1,
222 declare!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); 236 TIMER2,
223 declare!(GPIOTE); 237 RTC0,
224 declare!(TIMER0); 238 TEMP,
225 declare!(TIMER1); 239 RNG,
226 declare!(TIMER2); 240 ECB,
227 declare!(RTC0); 241 CCM_AAR,
228 declare!(TEMP); 242 WDT,
229 declare!(RNG); 243 RTC1,
230 declare!(ECB); 244 QDEC,
231 declare!(CCM_AAR); 245 COMP,
232 declare!(WDT); 246 SWI0_EGU0,
233 declare!(RTC1); 247 SWI1_EGU1,
234 declare!(QDEC); 248 SWI2_EGU2,
235 declare!(COMP); 249 SWI3_EGU3,
236 declare!(SWI0_EGU0); 250 SWI4_EGU4,
237 declare!(SWI1_EGU1); 251 SWI5_EGU5,
238 declare!(SWI2_EGU2); 252 TIMER3,
239 declare!(SWI3_EGU3); 253 USBD,
240 declare!(SWI4_EGU4); 254);
241 declare!(SWI5_EGU5);
242 declare!(TIMER3);
243 declare!(USBD);
244}
diff --git a/embassy-nrf/src/chips/nrf52832.rs b/embassy-nrf/src/chips/nrf52832.rs
index 2c6276d4a..b77564a5c 100644
--- a/embassy-nrf/src/chips/nrf52832.rs
+++ b/embassy-nrf/src/chips/nrf52832.rs
@@ -10,6 +10,8 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 255;
10// nrf52832xxAB = 256kb 10// nrf52832xxAB = 256kb
11pub const FLASH_SIZE: usize = 512 * 1024; 11pub const FLASH_SIZE: usize = 512 * 1024;
12 12
13pub const RESET_PIN: u32 = 21;
14
13embassy_hal_common::peripherals! { 15embassy_hal_common::peripherals! {
14 // RTC 16 // RTC
15 RTC0, 17 RTC0,
@@ -109,7 +111,9 @@ embassy_hal_common::peripherals! {
109 P0_06, 111 P0_06,
110 P0_07, 112 P0_07,
111 P0_08, 113 P0_08,
114 #[cfg(feature = "nfc-pins-as-gpio")]
112 P0_09, 115 P0_09,
116 #[cfg(feature = "nfc-pins-as-gpio")]
113 P0_10, 117 P0_10,
114 P0_11, 118 P0_11,
115 P0_12, 119 P0_12,
@@ -121,6 +125,7 @@ embassy_hal_common::peripherals! {
121 P0_18, 125 P0_18,
122 P0_19, 126 P0_19,
123 P0_20, 127 P0_20,
128 #[cfg(feature="reset-pin-as-gpio")]
124 P0_21, 129 P0_21,
125 P0_22, 130 P0_22,
126 P0_23, 131 P0_23,
@@ -139,6 +144,9 @@ embassy_hal_common::peripherals! {
139 // QDEC 144 // QDEC
140 QDEC, 145 QDEC,
141 146
147 // I2S
148 I2S,
149
142 // PDM 150 // PDM
143 PDM, 151 PDM,
144} 152}
@@ -149,13 +157,26 @@ impl_spim!(TWISPI0, SPIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
149impl_spim!(TWISPI1, SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); 157impl_spim!(TWISPI1, SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
150impl_spim!(SPI2, SPIM2, SPIM2_SPIS2_SPI2); 158impl_spim!(SPI2, SPIM2, SPIM2_SPIS2_SPI2);
151 159
160impl_spis!(TWISPI0, SPIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
161impl_spis!(TWISPI1, SPIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
162impl_spis!(SPI2, SPIS2, SPIM2_SPIS2_SPI2);
163
152impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); 164impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
153impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); 165impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
154 166
167impl_twis!(TWISPI0, TWIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
168impl_twis!(TWISPI1, TWIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
169
155impl_pwm!(PWM0, PWM0, PWM0); 170impl_pwm!(PWM0, PWM0, PWM0);
156impl_pwm!(PWM1, PWM1, PWM1); 171impl_pwm!(PWM1, PWM1, PWM1);
157impl_pwm!(PWM2, PWM2, PWM2); 172impl_pwm!(PWM2, PWM2, PWM2);
158 173
174impl_pdm!(PDM, PDM, PDM);
175
176impl_qdec!(QDEC, QDEC, QDEC);
177
178impl_rng!(RNG, RNG, RNG);
179
159impl_timer!(TIMER0, TIMER0, TIMER0); 180impl_timer!(TIMER0, TIMER0, TIMER0);
160impl_timer!(TIMER1, TIMER1, TIMER1); 181impl_timer!(TIMER1, TIMER1, TIMER1);
161impl_timer!(TIMER2, TIMER2, TIMER2); 182impl_timer!(TIMER2, TIMER2, TIMER2);
@@ -171,7 +192,9 @@ impl_pin!(P0_05, 0, 5);
171impl_pin!(P0_06, 0, 6); 192impl_pin!(P0_06, 0, 6);
172impl_pin!(P0_07, 0, 7); 193impl_pin!(P0_07, 0, 7);
173impl_pin!(P0_08, 0, 8); 194impl_pin!(P0_08, 0, 8);
195#[cfg(feature = "nfc-pins-as-gpio")]
174impl_pin!(P0_09, 0, 9); 196impl_pin!(P0_09, 0, 9);
197#[cfg(feature = "nfc-pins-as-gpio")]
175impl_pin!(P0_10, 0, 10); 198impl_pin!(P0_10, 0, 10);
176impl_pin!(P0_11, 0, 11); 199impl_pin!(P0_11, 0, 11);
177impl_pin!(P0_12, 0, 12); 200impl_pin!(P0_12, 0, 12);
@@ -183,6 +206,7 @@ impl_pin!(P0_17, 0, 17);
183impl_pin!(P0_18, 0, 18); 206impl_pin!(P0_18, 0, 18);
184impl_pin!(P0_19, 0, 19); 207impl_pin!(P0_19, 0, 19);
185impl_pin!(P0_20, 0, 20); 208impl_pin!(P0_20, 0, 20);
209#[cfg(feature = "reset-pin-as-gpio")]
186impl_pin!(P0_21, 0, 21); 210impl_pin!(P0_21, 0, 21);
187impl_pin!(P0_22, 0, 22); 211impl_pin!(P0_22, 0, 22);
188impl_pin!(P0_23, 0, 23); 212impl_pin!(P0_23, 0, 23);
@@ -228,55 +252,53 @@ impl_ppi_channel!(PPI_CH29, 29 => static);
228impl_ppi_channel!(PPI_CH30, 30 => static); 252impl_ppi_channel!(PPI_CH30, 30 => static);
229impl_ppi_channel!(PPI_CH31, 31 => static); 253impl_ppi_channel!(PPI_CH31, 31 => static);
230 254
231impl_saadc_input!(P0_02, ANALOGINPUT0); 255impl_saadc_input!(P0_02, ANALOG_INPUT0);
232impl_saadc_input!(P0_03, ANALOGINPUT1); 256impl_saadc_input!(P0_03, ANALOG_INPUT1);
233impl_saadc_input!(P0_04, ANALOGINPUT2); 257impl_saadc_input!(P0_04, ANALOG_INPUT2);
234impl_saadc_input!(P0_05, ANALOGINPUT3); 258impl_saadc_input!(P0_05, ANALOG_INPUT3);
235impl_saadc_input!(P0_28, ANALOGINPUT4); 259impl_saadc_input!(P0_28, ANALOG_INPUT4);
236impl_saadc_input!(P0_29, ANALOGINPUT5); 260impl_saadc_input!(P0_29, ANALOG_INPUT5);
237impl_saadc_input!(P0_30, ANALOGINPUT6); 261impl_saadc_input!(P0_30, ANALOG_INPUT6);
238impl_saadc_input!(P0_31, ANALOGINPUT7); 262impl_saadc_input!(P0_31, ANALOG_INPUT7);
239 263
240pub mod irqs { 264impl_i2s!(I2S, I2S, I2S);
241 use embassy_cortex_m::interrupt::_export::declare; 265
242 266embassy_hal_common::interrupt_mod!(
243 use crate::pac::Interrupt as InterruptEnum; 267 POWER_CLOCK,
244 268 RADIO,
245 declare!(POWER_CLOCK); 269 UARTE0_UART0,
246 declare!(RADIO); 270 SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0,
247 declare!(UARTE0_UART0); 271 SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1,
248 declare!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); 272 NFCT,
249 declare!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); 273 GPIOTE,
250 declare!(NFCT); 274 SAADC,
251 declare!(GPIOTE); 275 TIMER0,
252 declare!(SAADC); 276 TIMER1,
253 declare!(TIMER0); 277 TIMER2,
254 declare!(TIMER1); 278 RTC0,
255 declare!(TIMER2); 279 TEMP,
256 declare!(RTC0); 280 RNG,
257 declare!(TEMP); 281 ECB,
258 declare!(RNG); 282 CCM_AAR,
259 declare!(ECB); 283 WDT,
260 declare!(CCM_AAR); 284 RTC1,
261 declare!(WDT); 285 QDEC,
262 declare!(RTC1); 286 COMP_LPCOMP,
263 declare!(QDEC); 287 SWI0_EGU0,
264 declare!(COMP_LPCOMP); 288 SWI1_EGU1,
265 declare!(SWI0_EGU0); 289 SWI2_EGU2,
266 declare!(SWI1_EGU1); 290 SWI3_EGU3,
267 declare!(SWI2_EGU2); 291 SWI4_EGU4,
268 declare!(SWI3_EGU3); 292 SWI5_EGU5,
269 declare!(SWI4_EGU4); 293 TIMER3,
270 declare!(SWI5_EGU5); 294 TIMER4,
271 declare!(TIMER3); 295 PWM0,
272 declare!(TIMER4); 296 PDM,
273 declare!(PWM0); 297 MWU,
274 declare!(PDM); 298 PWM1,
275 declare!(MWU); 299 PWM2,
276 declare!(PWM1); 300 SPIM2_SPIS2_SPI2,
277 declare!(PWM2); 301 RTC2,
278 declare!(SPIM2_SPIS2_SPI2); 302 FPU,
279 declare!(RTC2); 303 I2S,
280 declare!(I2S); 304);
281 declare!(FPU);
282}
diff --git a/embassy-nrf/src/chips/nrf52833.rs b/embassy-nrf/src/chips/nrf52833.rs
index 3b33907d2..bff7f4ebb 100644
--- a/embassy-nrf/src/chips/nrf52833.rs
+++ b/embassy-nrf/src/chips/nrf52833.rs
@@ -6,6 +6,8 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 512;
6 6
7pub const FLASH_SIZE: usize = 512 * 1024; 7pub const FLASH_SIZE: usize = 512 * 1024;
8 8
9pub const RESET_PIN: u32 = 18;
10
9embassy_hal_common::peripherals! { 11embassy_hal_common::peripherals! {
10 // USB 12 // USB
11 USBD, 13 USBD,
@@ -111,7 +113,9 @@ embassy_hal_common::peripherals! {
111 P0_06, 113 P0_06,
112 P0_07, 114 P0_07,
113 P0_08, 115 P0_08,
116 #[cfg(feature = "nfc-pins-as-gpio")]
114 P0_09, 117 P0_09,
118 #[cfg(feature = "nfc-pins-as-gpio")]
115 P0_10, 119 P0_10,
116 P0_11, 120 P0_11,
117 P0_12, 121 P0_12,
@@ -120,6 +124,7 @@ embassy_hal_common::peripherals! {
120 P0_15, 124 P0_15,
121 P0_16, 125 P0_16,
122 P0_17, 126 P0_17,
127 #[cfg(feature="reset-pin-as-gpio")]
123 P0_18, 128 P0_18,
124 P0_19, 129 P0_19,
125 P0_20, 130 P0_20,
@@ -161,6 +166,9 @@ embassy_hal_common::peripherals! {
161 166
162 // PDM 167 // PDM
163 PDM, 168 PDM,
169
170 // I2S
171 I2S,
164} 172}
165 173
166#[cfg(feature = "nightly")] 174#[cfg(feature = "nightly")]
@@ -174,14 +182,27 @@ impl_spim!(TWISPI1, SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
174impl_spim!(SPI2, SPIM2, SPIM2_SPIS2_SPI2); 182impl_spim!(SPI2, SPIM2, SPIM2_SPIS2_SPI2);
175impl_spim!(SPI3, SPIM3, SPIM3); 183impl_spim!(SPI3, SPIM3, SPIM3);
176 184
185impl_spis!(TWISPI0, SPIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
186impl_spis!(TWISPI1, SPIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
187impl_spis!(SPI2, SPIS2, SPIM2_SPIS2_SPI2);
188
177impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); 189impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
178impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); 190impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
179 191
192impl_twis!(TWISPI0, TWIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
193impl_twis!(TWISPI1, TWIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
194
180impl_pwm!(PWM0, PWM0, PWM0); 195impl_pwm!(PWM0, PWM0, PWM0);
181impl_pwm!(PWM1, PWM1, PWM1); 196impl_pwm!(PWM1, PWM1, PWM1);
182impl_pwm!(PWM2, PWM2, PWM2); 197impl_pwm!(PWM2, PWM2, PWM2);
183impl_pwm!(PWM3, PWM3, PWM3); 198impl_pwm!(PWM3, PWM3, PWM3);
184 199
200impl_pdm!(PDM, PDM, PDM);
201
202impl_qdec!(QDEC, QDEC, QDEC);
203
204impl_rng!(RNG, RNG, RNG);
205
185impl_timer!(TIMER0, TIMER0, TIMER0); 206impl_timer!(TIMER0, TIMER0, TIMER0);
186impl_timer!(TIMER1, TIMER1, TIMER1); 207impl_timer!(TIMER1, TIMER1, TIMER1);
187impl_timer!(TIMER2, TIMER2, TIMER2); 208impl_timer!(TIMER2, TIMER2, TIMER2);
@@ -197,7 +218,9 @@ impl_pin!(P0_05, 0, 5);
197impl_pin!(P0_06, 0, 6); 218impl_pin!(P0_06, 0, 6);
198impl_pin!(P0_07, 0, 7); 219impl_pin!(P0_07, 0, 7);
199impl_pin!(P0_08, 0, 8); 220impl_pin!(P0_08, 0, 8);
221#[cfg(feature = "nfc-pins-as-gpio")]
200impl_pin!(P0_09, 0, 9); 222impl_pin!(P0_09, 0, 9);
223#[cfg(feature = "nfc-pins-as-gpio")]
201impl_pin!(P0_10, 0, 10); 224impl_pin!(P0_10, 0, 10);
202impl_pin!(P0_11, 0, 11); 225impl_pin!(P0_11, 0, 11);
203impl_pin!(P0_12, 0, 12); 226impl_pin!(P0_12, 0, 12);
@@ -206,6 +229,7 @@ impl_pin!(P0_14, 0, 14);
206impl_pin!(P0_15, 0, 15); 229impl_pin!(P0_15, 0, 15);
207impl_pin!(P0_16, 0, 16); 230impl_pin!(P0_16, 0, 16);
208impl_pin!(P0_17, 0, 17); 231impl_pin!(P0_17, 0, 17);
232#[cfg(feature = "reset-pin-as-gpio")]
209impl_pin!(P0_18, 0, 18); 233impl_pin!(P0_18, 0, 18);
210impl_pin!(P0_19, 0, 19); 234impl_pin!(P0_19, 0, 19);
211impl_pin!(P0_20, 0, 20); 235impl_pin!(P0_20, 0, 20);
@@ -271,59 +295,57 @@ impl_ppi_channel!(PPI_CH29, 29 => static);
271impl_ppi_channel!(PPI_CH30, 30 => static); 295impl_ppi_channel!(PPI_CH30, 30 => static);
272impl_ppi_channel!(PPI_CH31, 31 => static); 296impl_ppi_channel!(PPI_CH31, 31 => static);
273 297
274impl_saadc_input!(P0_02, ANALOGINPUT0); 298impl_saadc_input!(P0_02, ANALOG_INPUT0);
275impl_saadc_input!(P0_03, ANALOGINPUT1); 299impl_saadc_input!(P0_03, ANALOG_INPUT1);
276impl_saadc_input!(P0_04, ANALOGINPUT2); 300impl_saadc_input!(P0_04, ANALOG_INPUT2);
277impl_saadc_input!(P0_05, ANALOGINPUT3); 301impl_saadc_input!(P0_05, ANALOG_INPUT3);
278impl_saadc_input!(P0_28, ANALOGINPUT4); 302impl_saadc_input!(P0_28, ANALOG_INPUT4);
279impl_saadc_input!(P0_29, ANALOGINPUT5); 303impl_saadc_input!(P0_29, ANALOG_INPUT5);
280impl_saadc_input!(P0_30, ANALOGINPUT6); 304impl_saadc_input!(P0_30, ANALOG_INPUT6);
281impl_saadc_input!(P0_31, ANALOGINPUT7); 305impl_saadc_input!(P0_31, ANALOG_INPUT7);
282 306
283pub mod irqs { 307impl_i2s!(I2S, I2S, I2S);
284 use embassy_cortex_m::interrupt::_export::declare; 308
285 309embassy_hal_common::interrupt_mod!(
286 use crate::pac::Interrupt as InterruptEnum; 310 POWER_CLOCK,
287 311 RADIO,
288 declare!(POWER_CLOCK); 312 UARTE0_UART0,
289 declare!(RADIO); 313 SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0,
290 declare!(UARTE0_UART0); 314 SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1,
291 declare!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); 315 NFCT,
292 declare!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); 316 GPIOTE,
293 declare!(NFCT); 317 SAADC,
294 declare!(GPIOTE); 318 TIMER0,
295 declare!(SAADC); 319 TIMER1,
296 declare!(TIMER0); 320 TIMER2,
297 declare!(TIMER1); 321 RTC0,
298 declare!(TIMER2); 322 TEMP,
299 declare!(RTC0); 323 RNG,
300 declare!(TEMP); 324 ECB,
301 declare!(RNG); 325 CCM_AAR,
302 declare!(ECB); 326 WDT,
303 declare!(CCM_AAR); 327 RTC1,
304 declare!(WDT); 328 QDEC,
305 declare!(RTC1); 329 COMP_LPCOMP,
306 declare!(QDEC); 330 SWI0_EGU0,
307 declare!(COMP_LPCOMP); 331 SWI1_EGU1,
308 declare!(SWI0_EGU0); 332 SWI2_EGU2,
309 declare!(SWI1_EGU1); 333 SWI3_EGU3,
310 declare!(SWI2_EGU2); 334 SWI4_EGU4,
311 declare!(SWI3_EGU3); 335 SWI5_EGU5,
312 declare!(SWI4_EGU4); 336 TIMER3,
313 declare!(SWI5_EGU5); 337 TIMER4,
314 declare!(TIMER3); 338 PWM0,
315 declare!(TIMER4); 339 PDM,
316 declare!(PWM0); 340 MWU,
317 declare!(PDM); 341 PWM1,
318 declare!(MWU); 342 PWM2,
319 declare!(PWM1); 343 SPIM2_SPIS2_SPI2,
320 declare!(PWM2); 344 RTC2,
321 declare!(SPIM2_SPIS2_SPI2); 345 FPU,
322 declare!(RTC2); 346 USBD,
323 declare!(I2S); 347 UARTE1,
324 declare!(FPU); 348 PWM3,
325 declare!(USBD); 349 SPIM3,
326 declare!(UARTE1); 350 I2S,
327 declare!(PWM3); 351);
328 declare!(SPIM3);
329}
diff --git a/embassy-nrf/src/chips/nrf52840.rs b/embassy-nrf/src/chips/nrf52840.rs
index ae59f8b25..9b0050823 100644
--- a/embassy-nrf/src/chips/nrf52840.rs
+++ b/embassy-nrf/src/chips/nrf52840.rs
@@ -6,6 +6,8 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 512;
6 6
7pub const FLASH_SIZE: usize = 1024 * 1024; 7pub const FLASH_SIZE: usize = 1024 * 1024;
8 8
9pub const RESET_PIN: u32 = 18;
10
9embassy_hal_common::peripherals! { 11embassy_hal_common::peripherals! {
10 // USB 12 // USB
11 USBD, 13 USBD,
@@ -117,7 +119,9 @@ embassy_hal_common::peripherals! {
117 P0_06, 119 P0_06,
118 P0_07, 120 P0_07,
119 P0_08, 121 P0_08,
122 #[cfg(feature = "nfc-pins-as-gpio")]
120 P0_09, 123 P0_09,
124 #[cfg(feature = "nfc-pins-as-gpio")]
121 P0_10, 125 P0_10,
122 P0_11, 126 P0_11,
123 P0_12, 127 P0_12,
@@ -126,6 +130,7 @@ embassy_hal_common::peripherals! {
126 P0_15, 130 P0_15,
127 P0_16, 131 P0_16,
128 P0_17, 132 P0_17,
133 #[cfg(feature="reset-pin-as-gpio")]
129 P0_18, 134 P0_18,
130 P0_19, 135 P0_19,
131 P0_20, 136 P0_20,
@@ -164,6 +169,9 @@ embassy_hal_common::peripherals! {
164 169
165 // PDM 170 // PDM
166 PDM, 171 PDM,
172
173 // I2S
174 I2S,
167} 175}
168 176
169#[cfg(feature = "nightly")] 177#[cfg(feature = "nightly")]
@@ -177,9 +185,16 @@ impl_spim!(TWISPI1, SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
177impl_spim!(SPI2, SPIM2, SPIM2_SPIS2_SPI2); 185impl_spim!(SPI2, SPIM2, SPIM2_SPIS2_SPI2);
178impl_spim!(SPI3, SPIM3, SPIM3); 186impl_spim!(SPI3, SPIM3, SPIM3);
179 187
188impl_spis!(TWISPI0, SPIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
189impl_spis!(TWISPI1, SPIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
190impl_spis!(SPI2, SPIS2, SPIM2_SPIS2_SPI2);
191
180impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); 192impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
181impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); 193impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
182 194
195impl_twis!(TWISPI0, TWIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
196impl_twis!(TWISPI1, TWIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
197
183impl_pwm!(PWM0, PWM0, PWM0); 198impl_pwm!(PWM0, PWM0, PWM0);
184impl_pwm!(PWM1, PWM1, PWM1); 199impl_pwm!(PWM1, PWM1, PWM1);
185impl_pwm!(PWM2, PWM2, PWM2); 200impl_pwm!(PWM2, PWM2, PWM2);
@@ -193,6 +208,12 @@ impl_timer!(TIMER4, TIMER4, TIMER4, extended);
193 208
194impl_qspi!(QSPI, QSPI, QSPI); 209impl_qspi!(QSPI, QSPI, QSPI);
195 210
211impl_pdm!(PDM, PDM, PDM);
212
213impl_qdec!(QDEC, QDEC, QDEC);
214
215impl_rng!(RNG, RNG, RNG);
216
196impl_pin!(P0_00, 0, 0); 217impl_pin!(P0_00, 0, 0);
197impl_pin!(P0_01, 0, 1); 218impl_pin!(P0_01, 0, 1);
198impl_pin!(P0_02, 0, 2); 219impl_pin!(P0_02, 0, 2);
@@ -202,7 +223,9 @@ impl_pin!(P0_05, 0, 5);
202impl_pin!(P0_06, 0, 6); 223impl_pin!(P0_06, 0, 6);
203impl_pin!(P0_07, 0, 7); 224impl_pin!(P0_07, 0, 7);
204impl_pin!(P0_08, 0, 8); 225impl_pin!(P0_08, 0, 8);
226#[cfg(feature = "nfc-pins-as-gpio")]
205impl_pin!(P0_09, 0, 9); 227impl_pin!(P0_09, 0, 9);
228#[cfg(feature = "nfc-pins-as-gpio")]
206impl_pin!(P0_10, 0, 10); 229impl_pin!(P0_10, 0, 10);
207impl_pin!(P0_11, 0, 11); 230impl_pin!(P0_11, 0, 11);
208impl_pin!(P0_12, 0, 12); 231impl_pin!(P0_12, 0, 12);
@@ -211,6 +234,7 @@ impl_pin!(P0_14, 0, 14);
211impl_pin!(P0_15, 0, 15); 234impl_pin!(P0_15, 0, 15);
212impl_pin!(P0_16, 0, 16); 235impl_pin!(P0_16, 0, 16);
213impl_pin!(P0_17, 0, 17); 236impl_pin!(P0_17, 0, 17);
237#[cfg(feature = "reset-pin-as-gpio")]
214impl_pin!(P0_18, 0, 18); 238impl_pin!(P0_18, 0, 18);
215impl_pin!(P0_19, 0, 19); 239impl_pin!(P0_19, 0, 19);
216impl_pin!(P0_20, 0, 20); 240impl_pin!(P0_20, 0, 20);
@@ -276,61 +300,59 @@ impl_ppi_channel!(PPI_CH29, 29 => static);
276impl_ppi_channel!(PPI_CH30, 30 => static); 300impl_ppi_channel!(PPI_CH30, 30 => static);
277impl_ppi_channel!(PPI_CH31, 31 => static); 301impl_ppi_channel!(PPI_CH31, 31 => static);
278 302
279impl_saadc_input!(P0_02, ANALOGINPUT0); 303impl_saadc_input!(P0_02, ANALOG_INPUT0);
280impl_saadc_input!(P0_03, ANALOGINPUT1); 304impl_saadc_input!(P0_03, ANALOG_INPUT1);
281impl_saadc_input!(P0_04, ANALOGINPUT2); 305impl_saadc_input!(P0_04, ANALOG_INPUT2);
282impl_saadc_input!(P0_05, ANALOGINPUT3); 306impl_saadc_input!(P0_05, ANALOG_INPUT3);
283impl_saadc_input!(P0_28, ANALOGINPUT4); 307impl_saadc_input!(P0_28, ANALOG_INPUT4);
284impl_saadc_input!(P0_29, ANALOGINPUT5); 308impl_saadc_input!(P0_29, ANALOG_INPUT5);
285impl_saadc_input!(P0_30, ANALOGINPUT6); 309impl_saadc_input!(P0_30, ANALOG_INPUT6);
286impl_saadc_input!(P0_31, ANALOGINPUT7); 310impl_saadc_input!(P0_31, ANALOG_INPUT7);
287 311
288pub mod irqs { 312impl_i2s!(I2S, I2S, I2S);
289 use embassy_cortex_m::interrupt::_export::declare; 313
290 314embassy_hal_common::interrupt_mod!(
291 use crate::pac::Interrupt as InterruptEnum; 315 POWER_CLOCK,
292 316 RADIO,
293 declare!(POWER_CLOCK); 317 UARTE0_UART0,
294 declare!(RADIO); 318 SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0,
295 declare!(UARTE0_UART0); 319 SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1,
296 declare!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); 320 NFCT,
297 declare!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); 321 GPIOTE,
298 declare!(NFCT); 322 SAADC,
299 declare!(GPIOTE); 323 TIMER0,
300 declare!(SAADC); 324 TIMER1,
301 declare!(TIMER0); 325 TIMER2,
302 declare!(TIMER1); 326 RTC0,
303 declare!(TIMER2); 327 TEMP,
304 declare!(RTC0); 328 RNG,
305 declare!(TEMP); 329 ECB,
306 declare!(RNG); 330 CCM_AAR,
307 declare!(ECB); 331 WDT,
308 declare!(CCM_AAR); 332 RTC1,
309 declare!(WDT); 333 QDEC,
310 declare!(RTC1); 334 COMP_LPCOMP,
311 declare!(QDEC); 335 SWI0_EGU0,
312 declare!(COMP_LPCOMP); 336 SWI1_EGU1,
313 declare!(SWI0_EGU0); 337 SWI2_EGU2,
314 declare!(SWI1_EGU1); 338 SWI3_EGU3,
315 declare!(SWI2_EGU2); 339 SWI4_EGU4,
316 declare!(SWI3_EGU3); 340 SWI5_EGU5,
317 declare!(SWI4_EGU4); 341 TIMER3,
318 declare!(SWI5_EGU5); 342 TIMER4,
319 declare!(TIMER3); 343 PWM0,
320 declare!(TIMER4); 344 PDM,
321 declare!(PWM0); 345 MWU,
322 declare!(PDM); 346 PWM1,
323 declare!(MWU); 347 PWM2,
324 declare!(PWM1); 348 SPIM2_SPIS2_SPI2,
325 declare!(PWM2); 349 RTC2,
326 declare!(SPIM2_SPIS2_SPI2); 350 FPU,
327 declare!(RTC2); 351 USBD,
328 declare!(I2S); 352 UARTE1,
329 declare!(FPU); 353 QSPI,
330 declare!(USBD); 354 CRYPTOCELL,
331 declare!(UARTE1); 355 PWM3,
332 declare!(QSPI); 356 SPIM3,
333 declare!(CRYPTOCELL); 357 I2S,
334 declare!(PWM3); 358);
335 declare!(SPIM3);
336}
diff --git a/embassy-nrf/src/chips/nrf5340_app.rs b/embassy-nrf/src/chips/nrf5340_app.rs
index edf800ef3..410ae921c 100644
--- a/embassy-nrf/src/chips/nrf5340_app.rs
+++ b/embassy-nrf/src/chips/nrf5340_app.rs
@@ -1,9 +1,12 @@
1/// Peripheral Access Crate
1#[allow(unused_imports)] 2#[allow(unused_imports)]
2#[rustfmt::skip] 3#[rustfmt::skip]
3pub mod pac { 4pub mod pac {
4 // The nRF5340 has a secure and non-secure (NS) mode. 5 // The nRF5340 has a secure and non-secure (NS) mode.
5 // To avoid cfg spam, we remove _ns or _s suffixes here. 6 // To avoid cfg spam, we remove _ns or _s suffixes here.
6 7
8 pub use nrf5340_app_pac::NVIC_PRIO_BITS;
9
7 #[doc(no_inline)] 10 #[doc(no_inline)]
8 pub use nrf5340_app_pac::{ 11 pub use nrf5340_app_pac::{
9 interrupt, 12 interrupt,
@@ -33,10 +36,10 @@ pub mod pac {
33 nvmc_ns as nvmc, 36 nvmc_ns as nvmc,
34 oscillators_ns as oscillators, 37 oscillators_ns as oscillators,
35 p0_ns as p0, 38 p0_ns as p0,
36 pdm0_ns as pdm0, 39 pdm0_ns as pdm,
37 power_ns as power, 40 power_ns as power,
38 pwm0_ns as pwm0, 41 pwm0_ns as pwm0,
39 qdec0_ns as qdec0, 42 qdec0_ns as qdec,
40 qspi_ns as qspi, 43 qspi_ns as qspi,
41 regulators_ns as regulators, 44 regulators_ns as regulators,
42 reset_ns as reset, 45 reset_ns as reset,
@@ -213,6 +216,8 @@ pub mod pac {
213pub const EASY_DMA_SIZE: usize = (1 << 16) - 1; 216pub const EASY_DMA_SIZE: usize = (1 << 16) - 1;
214pub const FORCE_COPY_BUFFER_SIZE: usize = 1024; 217pub const FORCE_COPY_BUFFER_SIZE: usize = 1024;
215 218
219pub const FLASH_SIZE: usize = 1024 * 1024;
220
216embassy_hal_common::peripherals! { 221embassy_hal_common::peripherals! {
217 // USB 222 // USB
218 USBD, 223 USBD,
@@ -224,11 +229,14 @@ embassy_hal_common::peripherals! {
224 // WDT 229 // WDT
225 WDT, 230 WDT,
226 231
232 // NVMC
233 NVMC,
234
227 // UARTE, TWI & SPI 235 // UARTE, TWI & SPI
228 UARTETWISPI0, 236 SERIAL0,
229 UARTETWISPI1, 237 SERIAL1,
230 UARTETWISPI2, 238 SERIAL2,
231 UARTETWISPI3, 239 SERIAL3,
232 240
233 // SAADC 241 // SAADC
234 SAADC, 242 SAADC,
@@ -244,6 +252,16 @@ embassy_hal_common::peripherals! {
244 TIMER1, 252 TIMER1,
245 TIMER2, 253 TIMER2,
246 254
255 // QSPI
256 QSPI,
257
258 // PDM
259 PDM0,
260
261 // QDEC
262 QDEC0,
263 QDEC1,
264
247 // GPIOTE 265 // GPIOTE
248 GPIOTE_CH0, 266 GPIOTE_CH0,
249 GPIOTE_CH1, 267 GPIOTE_CH1,
@@ -298,7 +316,9 @@ embassy_hal_common::peripherals! {
298 // GPIO port 0 316 // GPIO port 0
299 P0_00, 317 P0_00,
300 P0_01, 318 P0_01,
319 #[cfg(feature = "nfc-pins-as-gpio")]
301 P0_02, 320 P0_02,
321 #[cfg(feature = "nfc-pins-as-gpio")]
302 P0_03, 322 P0_03,
303 P0_04, 323 P0_04,
304 P0_05, 324 P0_05,
@@ -351,20 +371,30 @@ embassy_hal_common::peripherals! {
351#[cfg(feature = "nightly")] 371#[cfg(feature = "nightly")]
352impl_usb!(USBD, USBD, USBD); 372impl_usb!(USBD, USBD, USBD);
353 373
354impl_uarte!(UARTETWISPI0, UARTE0, SERIAL0); 374impl_uarte!(SERIAL0, UARTE0, SERIAL0);
355impl_uarte!(UARTETWISPI1, UARTE1, SERIAL1); 375impl_uarte!(SERIAL1, UARTE1, SERIAL1);
356impl_uarte!(UARTETWISPI2, UARTE2, SERIAL2); 376impl_uarte!(SERIAL2, UARTE2, SERIAL2);
357impl_uarte!(UARTETWISPI3, UARTE3, SERIAL3); 377impl_uarte!(SERIAL3, UARTE3, SERIAL3);
358 378
359impl_spim!(UARTETWISPI0, SPIM0, SERIAL0); 379impl_spim!(SERIAL0, SPIM0, SERIAL0);
360impl_spim!(UARTETWISPI1, SPIM1, SERIAL1); 380impl_spim!(SERIAL1, SPIM1, SERIAL1);
361impl_spim!(UARTETWISPI2, SPIM2, SERIAL2); 381impl_spim!(SERIAL2, SPIM2, SERIAL2);
362impl_spim!(UARTETWISPI3, SPIM3, SERIAL3); 382impl_spim!(SERIAL3, SPIM3, SERIAL3);
363 383
364impl_twim!(UARTETWISPI0, TWIM0, SERIAL0); 384impl_spis!(SERIAL0, SPIS0, SERIAL0);
365impl_twim!(UARTETWISPI1, TWIM1, SERIAL1); 385impl_spis!(SERIAL1, SPIS1, SERIAL1);
366impl_twim!(UARTETWISPI2, TWIM2, SERIAL2); 386impl_spis!(SERIAL2, SPIS2, SERIAL2);
367impl_twim!(UARTETWISPI3, TWIM3, SERIAL3); 387impl_spis!(SERIAL3, SPIS3, SERIAL3);
388
389impl_twim!(SERIAL0, TWIM0, SERIAL0);
390impl_twim!(SERIAL1, TWIM1, SERIAL1);
391impl_twim!(SERIAL2, TWIM2, SERIAL2);
392impl_twim!(SERIAL3, TWIM3, SERIAL3);
393
394impl_twis!(SERIAL0, TWIS0, SERIAL0);
395impl_twis!(SERIAL1, TWIS1, SERIAL1);
396impl_twis!(SERIAL2, TWIS2, SERIAL2);
397impl_twis!(SERIAL3, TWIS3, SERIAL3);
368 398
369impl_pwm!(PWM0, PWM0, PWM0); 399impl_pwm!(PWM0, PWM0, PWM0);
370impl_pwm!(PWM1, PWM1, PWM1); 400impl_pwm!(PWM1, PWM1, PWM1);
@@ -375,9 +405,18 @@ impl_timer!(TIMER0, TIMER0, TIMER0);
375impl_timer!(TIMER1, TIMER1, TIMER1); 405impl_timer!(TIMER1, TIMER1, TIMER1);
376impl_timer!(TIMER2, TIMER2, TIMER2); 406impl_timer!(TIMER2, TIMER2, TIMER2);
377 407
408impl_qspi!(QSPI, QSPI, QSPI);
409
410impl_pdm!(PDM0, PDM0, PDM0);
411
412impl_qdec!(QDEC0, QDEC0, QDEC0);
413impl_qdec!(QDEC1, QDEC1, QDEC1);
414
378impl_pin!(P0_00, 0, 0); 415impl_pin!(P0_00, 0, 0);
379impl_pin!(P0_01, 0, 1); 416impl_pin!(P0_01, 0, 1);
417#[cfg(feature = "nfc-pins-as-gpio")]
380impl_pin!(P0_02, 0, 2); 418impl_pin!(P0_02, 0, 2);
419#[cfg(feature = "nfc-pins-as-gpio")]
381impl_pin!(P0_03, 0, 3); 420impl_pin!(P0_03, 0, 3);
382impl_pin!(P0_04, 0, 4); 421impl_pin!(P0_04, 0, 4);
383impl_pin!(P0_05, 0, 5); 422impl_pin!(P0_05, 0, 5);
@@ -458,59 +497,55 @@ impl_ppi_channel!(PPI_CH29, 29 => configurable);
458impl_ppi_channel!(PPI_CH30, 30 => configurable); 497impl_ppi_channel!(PPI_CH30, 30 => configurable);
459impl_ppi_channel!(PPI_CH31, 31 => configurable); 498impl_ppi_channel!(PPI_CH31, 31 => configurable);
460 499
461impl_saadc_input!(P0_13, ANALOGINPUT0); 500impl_saadc_input!(P0_13, ANALOG_INPUT0);
462impl_saadc_input!(P0_14, ANALOGINPUT1); 501impl_saadc_input!(P0_14, ANALOG_INPUT1);
463impl_saadc_input!(P0_15, ANALOGINPUT2); 502impl_saadc_input!(P0_15, ANALOG_INPUT2);
464impl_saadc_input!(P0_16, ANALOGINPUT3); 503impl_saadc_input!(P0_16, ANALOG_INPUT3);
465impl_saadc_input!(P0_17, ANALOGINPUT4); 504impl_saadc_input!(P0_17, ANALOG_INPUT4);
466impl_saadc_input!(P0_18, ANALOGINPUT5); 505impl_saadc_input!(P0_18, ANALOG_INPUT5);
467impl_saadc_input!(P0_19, ANALOGINPUT6); 506impl_saadc_input!(P0_19, ANALOG_INPUT6);
468impl_saadc_input!(P0_20, ANALOGINPUT7); 507impl_saadc_input!(P0_20, ANALOG_INPUT7);
469 508
470pub mod irqs { 509embassy_hal_common::interrupt_mod!(
471 use embassy_cortex_m::interrupt::_export::declare; 510 FPU,
472 511 CACHE,
473 use crate::pac::Interrupt as InterruptEnum; 512 SPU,
474 513 CLOCK_POWER,
475 declare!(FPU); 514 SERIAL0,
476 declare!(CACHE); 515 SERIAL1,
477 declare!(SPU); 516 SPIM4,
478 declare!(CLOCK_POWER); 517 SERIAL2,
479 declare!(SERIAL0); 518 SERIAL3,
480 declare!(SERIAL1); 519 GPIOTE0,
481 declare!(SPIM4); 520 SAADC,
482 declare!(SERIAL2); 521 TIMER0,
483 declare!(SERIAL3); 522 TIMER1,
484 declare!(GPIOTE0); 523 TIMER2,
485 declare!(SAADC); 524 RTC0,
486 declare!(TIMER0); 525 RTC1,
487 declare!(TIMER1); 526 WDT0,
488 declare!(TIMER2); 527 WDT1,
489 declare!(RTC0); 528 COMP_LPCOMP,
490 declare!(RTC1); 529 EGU0,
491 declare!(WDT0); 530 EGU1,
492 declare!(WDT1); 531 EGU2,
493 declare!(COMP_LPCOMP); 532 EGU3,
494 declare!(EGU0); 533 EGU4,
495 declare!(EGU1); 534 EGU5,
496 declare!(EGU2); 535 PWM0,
497 declare!(EGU3); 536 PWM1,
498 declare!(EGU4); 537 PWM2,
499 declare!(EGU5); 538 PWM3,
500 declare!(PWM0); 539 PDM0,
501 declare!(PWM1); 540 I2S0,
502 declare!(PWM2); 541 IPC,
503 declare!(PWM3); 542 QSPI,
504 declare!(PDM0); 543 NFCT,
505 declare!(I2S0); 544 GPIOTE1,
506 declare!(IPC); 545 QDEC0,
507 declare!(QSPI); 546 QDEC1,
508 declare!(NFCT); 547 USBD,
509 declare!(GPIOTE1); 548 USBREGULATOR,
510 declare!(QDEC0); 549 KMU,
511 declare!(QDEC1); 550 CRYPTOCELL,
512 declare!(USBD); 551);
513 declare!(USBREGULATOR);
514 declare!(KMU);
515 declare!(CRYPTOCELL);
516}
diff --git a/embassy-nrf/src/chips/nrf5340_net.rs b/embassy-nrf/src/chips/nrf5340_net.rs
index ae136e09d..6ac783085 100644
--- a/embassy-nrf/src/chips/nrf5340_net.rs
+++ b/embassy-nrf/src/chips/nrf5340_net.rs
@@ -1,9 +1,12 @@
1/// Peripheral Access Crate
1#[allow(unused_imports)] 2#[allow(unused_imports)]
2#[rustfmt::skip] 3#[rustfmt::skip]
3pub mod pac { 4pub mod pac {
4 // The nRF5340 has a secure and non-secure (NS) mode. 5 // The nRF5340 has a secure and non-secure (NS) mode.
5 // To avoid cfg spam, we remove _ns or _s suffixes here. 6 // To avoid cfg spam, we remove _ns or _s suffixes here.
6 7
8 pub use nrf5340_net_pac::NVIC_PRIO_BITS;
9
7 #[doc(no_inline)] 10 #[doc(no_inline)]
8 pub use nrf5340_net_pac::{ 11 pub use nrf5340_net_pac::{
9 interrupt, 12 interrupt,
@@ -104,6 +107,8 @@ pub mod pac {
104pub const EASY_DMA_SIZE: usize = (1 << 16) - 1; 107pub const EASY_DMA_SIZE: usize = (1 << 16) - 1;
105pub const FORCE_COPY_BUFFER_SIZE: usize = 1024; 108pub const FORCE_COPY_BUFFER_SIZE: usize = 1024;
106 109
110pub const FLASH_SIZE: usize = 256 * 1024;
111
107embassy_hal_common::peripherals! { 112embassy_hal_common::peripherals! {
108 // RTC 113 // RTC
109 RTC0, 114 RTC0,
@@ -112,15 +117,21 @@ embassy_hal_common::peripherals! {
112 // WDT 117 // WDT
113 WDT, 118 WDT,
114 119
120 // NVMC
121 NVMC,
122
115 // UARTE, TWI & SPI 123 // UARTE, TWI & SPI
116 UARTETWISPI0, 124 SERIAL0,
117 UARTETWISPI1, 125 SERIAL1,
118 UARTETWISPI2, 126 SERIAL2,
119 UARTETWISPI3, 127 SERIAL3,
120 128
121 // SAADC 129 // SAADC
122 SAADC, 130 SAADC,
123 131
132 // RNG
133 RNG,
134
124 // PWM 135 // PWM
125 PWM0, 136 PWM0,
126 PWM1, 137 PWM1,
@@ -236,14 +247,18 @@ embassy_hal_common::peripherals! {
236 P1_15, 247 P1_15,
237} 248}
238 249
239impl_uarte!(UARTETWISPI0, UARTE0, SERIAL0); 250impl_uarte!(SERIAL0, UARTE0, SERIAL0);
240impl_spim!(UARTETWISPI0, SPIM0, SERIAL0); 251impl_spim!(SERIAL0, SPIM0, SERIAL0);
241impl_twim!(UARTETWISPI0, TWIM0, SERIAL0); 252impl_spis!(SERIAL0, SPIS0, SERIAL0);
253impl_twim!(SERIAL0, TWIM0, SERIAL0);
254impl_twis!(SERIAL0, TWIS0, SERIAL0);
242 255
243impl_timer!(TIMER0, TIMER0, TIMER0); 256impl_timer!(TIMER0, TIMER0, TIMER0);
244impl_timer!(TIMER1, TIMER1, TIMER1); 257impl_timer!(TIMER1, TIMER1, TIMER1);
245impl_timer!(TIMER2, TIMER2, TIMER2); 258impl_timer!(TIMER2, TIMER2, TIMER2);
246 259
260impl_rng!(RNG, RNG, RNG);
261
247impl_pin!(P0_00, 0, 0); 262impl_pin!(P0_00, 0, 0);
248impl_pin!(P0_01, 0, 1); 263impl_pin!(P0_01, 0, 1);
249impl_pin!(P0_02, 0, 2); 264impl_pin!(P0_02, 0, 2);
@@ -327,29 +342,25 @@ impl_ppi_channel!(PPI_CH29, 29 => configurable);
327impl_ppi_channel!(PPI_CH30, 30 => configurable); 342impl_ppi_channel!(PPI_CH30, 30 => configurable);
328impl_ppi_channel!(PPI_CH31, 31 => configurable); 343impl_ppi_channel!(PPI_CH31, 31 => configurable);
329 344
330pub mod irqs { 345embassy_hal_common::interrupt_mod!(
331 use embassy_cortex_m::interrupt::_export::declare; 346 CLOCK_POWER,
332 347 RADIO,
333 use crate::pac::Interrupt as InterruptEnum; 348 RNG,
334 349 GPIOTE,
335 declare!(CLOCK_POWER); 350 WDT,
336 declare!(RADIO); 351 TIMER0,
337 declare!(RNG); 352 ECB,
338 declare!(GPIOTE); 353 AAR_CCM,
339 declare!(WDT); 354 TEMP,
340 declare!(TIMER0); 355 RTC0,
341 declare!(ECB); 356 IPC,
342 declare!(AAR_CCM); 357 SERIAL0,
343 declare!(TEMP); 358 EGU0,
344 declare!(RTC0); 359 RTC1,
345 declare!(IPC); 360 TIMER1,
346 declare!(SERIAL0); 361 TIMER2,
347 declare!(EGU0); 362 SWI0,
348 declare!(RTC1); 363 SWI1,
349 declare!(TIMER1); 364 SWI2,
350 declare!(TIMER2); 365 SWI3,
351 declare!(SWI0); 366);
352 declare!(SWI1);
353 declare!(SWI2);
354 declare!(SWI3);
355}
diff --git a/embassy-nrf/src/chips/nrf9160.rs b/embassy-nrf/src/chips/nrf9160.rs
index a4be8564e..67ea032ff 100644
--- a/embassy-nrf/src/chips/nrf9160.rs
+++ b/embassy-nrf/src/chips/nrf9160.rs
@@ -1,9 +1,12 @@
1/// Peripheral Access Crate
1#[allow(unused_imports)] 2#[allow(unused_imports)]
2#[rustfmt::skip] 3#[rustfmt::skip]
3pub mod pac { 4pub mod pac {
4 // The nRF9160 has a secure and non-secure (NS) mode. 5 // The nRF9160 has a secure and non-secure (NS) mode.
5 // To avoid cfg spam, we remove _ns or _s suffixes here. 6 // To avoid cfg spam, we remove _ns or _s suffixes here.
6 7
8 pub use nrf9160_pac::NVIC_PRIO_BITS;
9
7 #[doc(no_inline)] 10 #[doc(no_inline)]
8 pub use nrf9160_pac::{ 11 pub use nrf9160_pac::{
9 interrupt, 12 interrupt,
@@ -164,6 +167,8 @@ pub mod pac {
164pub const EASY_DMA_SIZE: usize = (1 << 13) - 1; 167pub const EASY_DMA_SIZE: usize = (1 << 13) - 1;
165pub const FORCE_COPY_BUFFER_SIZE: usize = 1024; 168pub const FORCE_COPY_BUFFER_SIZE: usize = 1024;
166 169
170pub const FLASH_SIZE: usize = 1024 * 1024;
171
167embassy_hal_common::peripherals! { 172embassy_hal_common::peripherals! {
168 // RTC 173 // RTC
169 RTC0, 174 RTC0,
@@ -172,11 +177,14 @@ embassy_hal_common::peripherals! {
172 // WDT 177 // WDT
173 WDT, 178 WDT,
174 179
180 // NVMC
181 NVMC,
182
175 // UARTE, TWI & SPI 183 // UARTE, TWI & SPI
176 UARTETWISPI0, 184 SERIAL0,
177 UARTETWISPI1, 185 SERIAL1,
178 UARTETWISPI2, 186 SERIAL2,
179 UARTETWISPI3, 187 SERIAL3,
180 188
181 // SAADC 189 // SAADC
182 SAADC, 190 SAADC,
@@ -260,28 +268,43 @@ embassy_hal_common::peripherals! {
260 P0_29, 268 P0_29,
261 P0_30, 269 P0_30,
262 P0_31, 270 P0_31,
271
272 // PDM
273 PDM,
263} 274}
264 275
265impl_uarte!(UARTETWISPI0, UARTE0, UARTE0_SPIM0_SPIS0_TWIM0_TWIS0); 276impl_uarte!(SERIAL0, UARTE0, UARTE0_SPIM0_SPIS0_TWIM0_TWIS0);
266impl_uarte!(UARTETWISPI1, UARTE1, UARTE1_SPIM1_SPIS1_TWIM1_TWIS1); 277impl_uarte!(SERIAL1, UARTE1, UARTE1_SPIM1_SPIS1_TWIM1_TWIS1);
267impl_uarte!(UARTETWISPI2, UARTE2, UARTE2_SPIM2_SPIS2_TWIM2_TWIS2); 278impl_uarte!(SERIAL2, UARTE2, UARTE2_SPIM2_SPIS2_TWIM2_TWIS2);
268impl_uarte!(UARTETWISPI3, UARTE3, UARTE3_SPIM3_SPIS3_TWIM3_TWIS3); 279impl_uarte!(SERIAL3, UARTE3, UARTE3_SPIM3_SPIS3_TWIM3_TWIS3);
280
281impl_spim!(SERIAL0, SPIM0, UARTE0_SPIM0_SPIS0_TWIM0_TWIS0);
282impl_spim!(SERIAL1, SPIM1, UARTE1_SPIM1_SPIS1_TWIM1_TWIS1);
283impl_spim!(SERIAL2, SPIM2, UARTE2_SPIM2_SPIS2_TWIM2_TWIS2);
284impl_spim!(SERIAL3, SPIM3, UARTE3_SPIM3_SPIS3_TWIM3_TWIS3);
285
286impl_spis!(SERIAL0, SPIS0, UARTE0_SPIM0_SPIS0_TWIM0_TWIS0);
287impl_spis!(SERIAL1, SPIS1, UARTE1_SPIM1_SPIS1_TWIM1_TWIS1);
288impl_spis!(SERIAL2, SPIS2, UARTE2_SPIM2_SPIS2_TWIM2_TWIS2);
289impl_spis!(SERIAL3, SPIS3, UARTE3_SPIM3_SPIS3_TWIM3_TWIS3);
269 290
270impl_spim!(UARTETWISPI0, SPIM0, UARTE0_SPIM0_SPIS0_TWIM0_TWIS0); 291impl_twim!(SERIAL0, TWIM0, UARTE0_SPIM0_SPIS0_TWIM0_TWIS0);
271impl_spim!(UARTETWISPI1, SPIM1, UARTE1_SPIM1_SPIS1_TWIM1_TWIS1); 292impl_twim!(SERIAL1, TWIM1, UARTE1_SPIM1_SPIS1_TWIM1_TWIS1);
272impl_spim!(UARTETWISPI2, SPIM2, UARTE2_SPIM2_SPIS2_TWIM2_TWIS2); 293impl_twim!(SERIAL2, TWIM2, UARTE2_SPIM2_SPIS2_TWIM2_TWIS2);
273impl_spim!(UARTETWISPI3, SPIM3, UARTE3_SPIM3_SPIS3_TWIM3_TWIS3); 294impl_twim!(SERIAL3, TWIM3, UARTE3_SPIM3_SPIS3_TWIM3_TWIS3);
274 295
275impl_twim!(UARTETWISPI0, TWIM0, UARTE0_SPIM0_SPIS0_TWIM0_TWIS0); 296impl_twis!(SERIAL0, TWIS0, UARTE0_SPIM0_SPIS0_TWIM0_TWIS0);
276impl_twim!(UARTETWISPI1, TWIM1, UARTE1_SPIM1_SPIS1_TWIM1_TWIS1); 297impl_twis!(SERIAL1, TWIS1, UARTE1_SPIM1_SPIS1_TWIM1_TWIS1);
277impl_twim!(UARTETWISPI2, TWIM2, UARTE2_SPIM2_SPIS2_TWIM2_TWIS2); 298impl_twis!(SERIAL2, TWIS2, UARTE2_SPIM2_SPIS2_TWIM2_TWIS2);
278impl_twim!(UARTETWISPI3, TWIM3, UARTE3_SPIM3_SPIS3_TWIM3_TWIS3); 299impl_twis!(SERIAL3, TWIS3, UARTE3_SPIM3_SPIS3_TWIM3_TWIS3);
279 300
280impl_pwm!(PWM0, PWM0, PWM0); 301impl_pwm!(PWM0, PWM0, PWM0);
281impl_pwm!(PWM1, PWM1, PWM1); 302impl_pwm!(PWM1, PWM1, PWM1);
282impl_pwm!(PWM2, PWM2, PWM2); 303impl_pwm!(PWM2, PWM2, PWM2);
283impl_pwm!(PWM3, PWM3, PWM3); 304impl_pwm!(PWM3, PWM3, PWM3);
284 305
306impl_pdm!(PDM, PDM, PDM);
307
285impl_timer!(TIMER0, TIMER0, TIMER0); 308impl_timer!(TIMER0, TIMER0, TIMER0);
286impl_timer!(TIMER1, TIMER1, TIMER1); 309impl_timer!(TIMER1, TIMER1, TIMER1);
287impl_timer!(TIMER2, TIMER2, TIMER2); 310impl_timer!(TIMER2, TIMER2, TIMER2);
@@ -336,49 +359,45 @@ impl_ppi_channel!(PPI_CH13, 13 => configurable);
336impl_ppi_channel!(PPI_CH14, 14 => configurable); 359impl_ppi_channel!(PPI_CH14, 14 => configurable);
337impl_ppi_channel!(PPI_CH15, 15 => configurable); 360impl_ppi_channel!(PPI_CH15, 15 => configurable);
338 361
339impl_saadc_input!(P0_13, ANALOGINPUT0); 362impl_saadc_input!(P0_13, ANALOG_INPUT0);
340impl_saadc_input!(P0_14, ANALOGINPUT1); 363impl_saadc_input!(P0_14, ANALOG_INPUT1);
341impl_saadc_input!(P0_15, ANALOGINPUT2); 364impl_saadc_input!(P0_15, ANALOG_INPUT2);
342impl_saadc_input!(P0_16, ANALOGINPUT3); 365impl_saadc_input!(P0_16, ANALOG_INPUT3);
343impl_saadc_input!(P0_17, ANALOGINPUT4); 366impl_saadc_input!(P0_17, ANALOG_INPUT4);
344impl_saadc_input!(P0_18, ANALOGINPUT5); 367impl_saadc_input!(P0_18, ANALOG_INPUT5);
345impl_saadc_input!(P0_19, ANALOGINPUT6); 368impl_saadc_input!(P0_19, ANALOG_INPUT6);
346impl_saadc_input!(P0_20, ANALOGINPUT7); 369impl_saadc_input!(P0_20, ANALOG_INPUT7);
347
348pub mod irqs {
349 use embassy_cortex_m::interrupt::_export::declare;
350
351 use crate::pac::Interrupt as InterruptEnum;
352 370
353 declare!(SPU); 371embassy_hal_common::interrupt_mod!(
354 declare!(CLOCK_POWER); 372 SPU,
355 declare!(UARTE0_SPIM0_SPIS0_TWIM0_TWIS0); 373 CLOCK_POWER,
356 declare!(UARTE1_SPIM1_SPIS1_TWIM1_TWIS1); 374 UARTE0_SPIM0_SPIS0_TWIM0_TWIS0,
357 declare!(UARTE2_SPIM2_SPIS2_TWIM2_TWIS2); 375 UARTE1_SPIM1_SPIS1_TWIM1_TWIS1,
358 declare!(UARTE3_SPIM3_SPIS3_TWIM3_TWIS3); 376 UARTE2_SPIM2_SPIS2_TWIM2_TWIS2,
359 declare!(GPIOTE0); 377 UARTE3_SPIM3_SPIS3_TWIM3_TWIS3,
360 declare!(SAADC); 378 GPIOTE0,
361 declare!(TIMER0); 379 SAADC,
362 declare!(TIMER1); 380 TIMER0,
363 declare!(TIMER2); 381 TIMER1,
364 declare!(RTC0); 382 TIMER2,
365 declare!(RTC1); 383 RTC0,
366 declare!(WDT); 384 RTC1,
367 declare!(EGU0); 385 WDT,
368 declare!(EGU1); 386 EGU0,
369 declare!(EGU2); 387 EGU1,
370 declare!(EGU3); 388 EGU2,
371 declare!(EGU4); 389 EGU3,
372 declare!(EGU5); 390 EGU4,
373 declare!(PWM0); 391 EGU5,
374 declare!(PWM1); 392 PWM0,
375 declare!(PWM2); 393 PWM1,
376 declare!(PDM); 394 PWM2,
377 declare!(PWM3); 395 PDM,
378 declare!(I2S); 396 PWM3,
379 declare!(IPC); 397 I2S,
380 declare!(FPU); 398 IPC,
381 declare!(GPIOTE1); 399 FPU,
382 declare!(KMU); 400 GPIOTE1,
383 declare!(CRYPTOCELL); 401 KMU,
384} 402 CRYPTOCELL,
403);
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs
index 924629908..895ab9340 100644
--- a/embassy-nrf/src/gpio.rs
+++ b/embassy-nrf/src/gpio.rs
@@ -1,4 +1,4 @@
1//! General purpose input/output for nRF. 1//! General purpose input/output (GPIO) driver.
2#![macro_use] 2#![macro_use]
3 3
4use core::convert::Infallible; 4use core::convert::Infallible;
@@ -70,7 +70,7 @@ impl<'d, T: Pin> Input<'d, T> {
70} 70}
71 71
72/// Digital input or output level. 72/// Digital input or output level.
73#[derive(Debug, Eq, PartialEq)] 73#[derive(Clone, Copy, Debug, Eq, PartialEq)]
74#[cfg_attr(feature = "defmt", derive(defmt::Format))] 74#[cfg_attr(feature = "defmt", derive(defmt::Format))]
75pub enum Level { 75pub enum Level {
76 /// Logical low. 76 /// Logical low.
@@ -88,9 +88,9 @@ impl From<bool> for Level {
88 } 88 }
89} 89}
90 90
91impl Into<bool> for Level { 91impl From<Level> for bool {
92 fn into(self) -> bool { 92 fn from(level: Level) -> bool {
93 match self { 93 match level {
94 Level::Low => false, 94 Level::Low => false,
95 Level::High => true, 95 Level::High => true,
96 } 96 }
@@ -574,7 +574,7 @@ mod eh1 {
574 type Error = Infallible; 574 type Error = Infallible;
575 } 575 }
576 576
577 impl<'d, T: Pin> embedded_hal_1::digital::blocking::InputPin for Input<'d, T> { 577 impl<'d, T: Pin> embedded_hal_1::digital::InputPin for Input<'d, T> {
578 fn is_high(&self) -> Result<bool, Self::Error> { 578 fn is_high(&self) -> Result<bool, Self::Error> {
579 Ok(self.is_high()) 579 Ok(self.is_high())
580 } 580 }
@@ -588,7 +588,7 @@ mod eh1 {
588 type Error = Infallible; 588 type Error = Infallible;
589 } 589 }
590 590
591 impl<'d, T: Pin> embedded_hal_1::digital::blocking::OutputPin for Output<'d, T> { 591 impl<'d, T: Pin> embedded_hal_1::digital::OutputPin for Output<'d, T> {
592 fn set_high(&mut self) -> Result<(), Self::Error> { 592 fn set_high(&mut self) -> Result<(), Self::Error> {
593 Ok(self.set_high()) 593 Ok(self.set_high())
594 } 594 }
@@ -598,7 +598,7 @@ mod eh1 {
598 } 598 }
599 } 599 }
600 600
601 impl<'d, T: Pin> embedded_hal_1::digital::blocking::StatefulOutputPin for Output<'d, T> { 601 impl<'d, T: Pin> embedded_hal_1::digital::StatefulOutputPin for Output<'d, T> {
602 fn is_set_high(&self) -> Result<bool, Self::Error> { 602 fn is_set_high(&self) -> Result<bool, Self::Error> {
603 Ok(self.is_set_high()) 603 Ok(self.is_set_high())
604 } 604 }
@@ -615,7 +615,7 @@ mod eh1 {
615 /// Implement [`InputPin`] for [`Flex`]; 615 /// Implement [`InputPin`] for [`Flex`];
616 /// 616 ///
617 /// If the pin is not in input mode the result is unspecified. 617 /// If the pin is not in input mode the result is unspecified.
618 impl<'d, T: Pin> embedded_hal_1::digital::blocking::InputPin for Flex<'d, T> { 618 impl<'d, T: Pin> embedded_hal_1::digital::InputPin for Flex<'d, T> {
619 fn is_high(&self) -> Result<bool, Self::Error> { 619 fn is_high(&self) -> Result<bool, Self::Error> {
620 Ok(self.is_high()) 620 Ok(self.is_high())
621 } 621 }
@@ -625,7 +625,7 @@ mod eh1 {
625 } 625 }
626 } 626 }
627 627
628 impl<'d, T: Pin> embedded_hal_1::digital::blocking::OutputPin for Flex<'d, T> { 628 impl<'d, T: Pin> embedded_hal_1::digital::OutputPin for Flex<'d, T> {
629 fn set_high(&mut self) -> Result<(), Self::Error> { 629 fn set_high(&mut self) -> Result<(), Self::Error> {
630 Ok(self.set_high()) 630 Ok(self.set_high())
631 } 631 }
@@ -635,7 +635,7 @@ mod eh1 {
635 } 635 }
636 } 636 }
637 637
638 impl<'d, T: Pin> embedded_hal_1::digital::blocking::StatefulOutputPin for Flex<'d, T> { 638 impl<'d, T: Pin> embedded_hal_1::digital::StatefulOutputPin for Flex<'d, T> {
639 fn is_set_high(&self) -> Result<bool, Self::Error> { 639 fn is_set_high(&self) -> Result<bool, Self::Error> {
640 Ok(self.is_set_high()) 640 Ok(self.is_set_high())
641 } 641 }
diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs
index b52035705..6550f2abd 100644
--- a/embassy-nrf/src/gpiote.rs
+++ b/embassy-nrf/src/gpiote.rs
@@ -1,40 +1,50 @@
1//! GPIO task/event (GPIOTE) driver.
2
1use core::convert::Infallible; 3use core::convert::Infallible;
2use core::future::Future; 4use core::future::{poll_fn, Future};
3use core::task::{Context, Poll}; 5use core::task::{Context, Poll};
4 6
5use embassy_hal_common::{impl_peripheral, Peripheral, PeripheralRef}; 7use embassy_hal_common::{impl_peripheral, into_ref, Peripheral, PeripheralRef};
6use embassy_sync::waitqueue::AtomicWaker; 8use embassy_sync::waitqueue::AtomicWaker;
7use futures::future::poll_fn;
8 9
9use crate::gpio::sealed::Pin as _; 10use crate::gpio::sealed::Pin as _;
10use crate::gpio::{AnyPin, Flex, Input, Output, Pin as GpioPin}; 11use crate::gpio::{AnyPin, Flex, Input, Output, Pin as GpioPin};
11use crate::interrupt::{Interrupt, InterruptExt}; 12use crate::interrupt::InterruptExt;
12use crate::ppi::{Event, Task}; 13use crate::ppi::{Event, Task};
13use crate::{interrupt, pac, peripherals}; 14use crate::{interrupt, pac, peripherals};
14 15
15pub const CHANNEL_COUNT: usize = 8; 16/// Amount of GPIOTE channels in the chip.
17const CHANNEL_COUNT: usize = 8;
16 18
17#[cfg(any(feature = "nrf52833", feature = "nrf52840"))] 19#[cfg(any(feature = "nrf52833", feature = "nrf52840"))]
18pub const PIN_COUNT: usize = 48; 20const PIN_COUNT: usize = 48;
19#[cfg(not(any(feature = "nrf52833", feature = "nrf52840")))] 21#[cfg(not(any(feature = "nrf52833", feature = "nrf52840")))]
20pub const PIN_COUNT: usize = 32; 22const PIN_COUNT: usize = 32;
21 23
22#[allow(clippy::declare_interior_mutable_const)] 24#[allow(clippy::declare_interior_mutable_const)]
23const NEW_AW: AtomicWaker = AtomicWaker::new(); 25const NEW_AW: AtomicWaker = AtomicWaker::new();
24static CHANNEL_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [NEW_AW; CHANNEL_COUNT]; 26static CHANNEL_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [NEW_AW; CHANNEL_COUNT];
25static PORT_WAKERS: [AtomicWaker; PIN_COUNT] = [NEW_AW; PIN_COUNT]; 27static PORT_WAKERS: [AtomicWaker; PIN_COUNT] = [NEW_AW; PIN_COUNT];
26 28
29/// Polarity for listening to events for GPIOTE input channels.
27pub enum InputChannelPolarity { 30pub enum InputChannelPolarity {
31 /// Don't listen for any pin changes.
28 None, 32 None,
33 /// Listen for high to low changes.
29 HiToLo, 34 HiToLo,
35 /// Listen for low to high changes.
30 LoToHi, 36 LoToHi,
37 /// Listen for any change, either low to high or high to low.
31 Toggle, 38 Toggle,
32} 39}
33 40
34/// Polarity of the `task out` operation. 41/// Polarity of the OUT task operation for GPIOTE output channels.
35pub enum OutputChannelPolarity { 42pub enum OutputChannelPolarity {
43 /// Set the pin high.
36 Set, 44 Set,
45 /// Set the pin low.
37 Clear, 46 Clear,
47 /// Toggle the pin.
38 Toggle, 48 Toggle,
39} 49}
40 50
@@ -64,42 +74,41 @@ pub(crate) fn init(irq_prio: crate::interrupt::Priority) {
64 } 74 }
65 75
66 // Enable interrupts 76 // Enable interrupts
67 cfg_if::cfg_if! { 77 #[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s"))]
68 if #[cfg(any(feature="nrf5340-app-s", feature="nrf9160-s"))] { 78 let irq = interrupt::GPIOTE0;
69 let irq = unsafe { interrupt::GPIOTE0::steal() }; 79 #[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns"))]
70 } else if #[cfg(any(feature="nrf5340-app-ns", feature="nrf9160-ns"))] { 80 let irq = interrupt::GPIOTE1;
71 let irq = unsafe { interrupt::GPIOTE1::steal() }; 81 #[cfg(any(feature = "_nrf52", feature = "nrf5340-net"))]
72 } else { 82 let irq = interrupt::GPIOTE;
73 let irq = unsafe { interrupt::GPIOTE::steal() };
74 }
75 }
76 83
77 irq.unpend(); 84 irq.unpend();
78 irq.set_priority(irq_prio); 85 irq.set_priority(irq_prio);
79 irq.enable(); 86 unsafe { irq.enable() };
80 87
81 let g = regs(); 88 let g = regs();
82 g.events_port.write(|w| w); 89 g.events_port.write(|w| w);
83 g.intenset.write(|w| w.port().set()); 90 g.intenset.write(|w| w.port().set());
84} 91}
85 92
86cfg_if::cfg_if! { 93#[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s"))]
87 if #[cfg(any(feature="nrf5340-app-s", feature="nrf9160-s"))] { 94#[cfg(feature = "rt")]
88 #[interrupt] 95#[interrupt]
89 fn GPIOTE0() { 96fn GPIOTE0() {
90 unsafe { handle_gpiote_interrupt() }; 97 unsafe { handle_gpiote_interrupt() };
91 } 98}
92 } else if #[cfg(any(feature="nrf5340-app-ns", feature="nrf9160-ns"))] { 99
93 #[interrupt] 100#[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns"))]
94 fn GPIOTE1() { 101#[cfg(feature = "rt")]
95 unsafe { handle_gpiote_interrupt() }; 102#[interrupt]
96 } 103fn GPIOTE1() {
97 } else { 104 unsafe { handle_gpiote_interrupt() };
98 #[interrupt] 105}
99 fn GPIOTE() { 106
100 unsafe { handle_gpiote_interrupt() }; 107#[cfg(any(feature = "_nrf52", feature = "nrf5340-net"))]
101 } 108#[cfg(feature = "rt")]
102 } 109#[interrupt]
110fn GPIOTE() {
111 unsafe { handle_gpiote_interrupt() };
103} 112}
104 113
105unsafe fn handle_gpiote_interrupt() { 114unsafe fn handle_gpiote_interrupt() {
@@ -149,7 +158,7 @@ impl Iterator for BitIter {
149 158
150/// GPIOTE channel driver in input mode 159/// GPIOTE channel driver in input mode
151pub struct InputChannel<'d, C: Channel, T: GpioPin> { 160pub struct InputChannel<'d, C: Channel, T: GpioPin> {
152 ch: C, 161 ch: PeripheralRef<'d, C>,
153 pin: Input<'d, T>, 162 pin: Input<'d, T>,
154} 163}
155 164
@@ -163,7 +172,10 @@ impl<'d, C: Channel, T: GpioPin> Drop for InputChannel<'d, C, T> {
163} 172}
164 173
165impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> { 174impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> {
166 pub fn new(ch: C, pin: Input<'d, T>, polarity: InputChannelPolarity) -> Self { 175 /// Create a new GPIOTE input channel driver.
176 pub fn new(ch: impl Peripheral<P = C> + 'd, pin: Input<'d, T>, polarity: InputChannelPolarity) -> Self {
177 into_ref!(ch);
178
167 let g = regs(); 179 let g = regs();
168 let num = ch.number(); 180 let num = ch.number();
169 181
@@ -187,6 +199,7 @@ impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> {
187 InputChannel { ch, pin } 199 InputChannel { ch, pin }
188 } 200 }
189 201
202 /// Asynchronously wait for an event in this channel.
190 pub async fn wait(&self) { 203 pub async fn wait(&self) {
191 let g = regs(); 204 let g = regs();
192 let num = self.ch.number(); 205 let num = self.ch.number();
@@ -208,7 +221,7 @@ impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> {
208 } 221 }
209 222
210 /// Returns the IN event, for use with PPI. 223 /// Returns the IN event, for use with PPI.
211 pub fn event_in(&self) -> Event { 224 pub fn event_in(&self) -> Event<'d> {
212 let g = regs(); 225 let g = regs();
213 Event::from_reg(&g.events_in[self.ch.number()]) 226 Event::from_reg(&g.events_in[self.ch.number()])
214 } 227 }
@@ -216,7 +229,7 @@ impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> {
216 229
217/// GPIOTE channel driver in output mode 230/// GPIOTE channel driver in output mode
218pub struct OutputChannel<'d, C: Channel, T: GpioPin> { 231pub struct OutputChannel<'d, C: Channel, T: GpioPin> {
219 ch: C, 232 ch: PeripheralRef<'d, C>,
220 _pin: Output<'d, T>, 233 _pin: Output<'d, T>,
221} 234}
222 235
@@ -230,7 +243,9 @@ impl<'d, C: Channel, T: GpioPin> Drop for OutputChannel<'d, C, T> {
230} 243}
231 244
232impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> { 245impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> {
233 pub fn new(ch: C, pin: Output<'d, T>, polarity: OutputChannelPolarity) -> Self { 246 /// Create a new GPIOTE output channel driver.
247 pub fn new(ch: impl Peripheral<P = C> + 'd, pin: Output<'d, T>, polarity: OutputChannelPolarity) -> Self {
248 into_ref!(ch);
234 let g = regs(); 249 let g = regs();
235 let num = ch.number(); 250 let num = ch.number();
236 251
@@ -256,20 +271,20 @@ impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> {
256 OutputChannel { ch, _pin: pin } 271 OutputChannel { ch, _pin: pin }
257 } 272 }
258 273
259 /// Triggers `task out` (as configured with task_out_polarity, defaults to Toggle). 274 /// Triggers the OUT task (does the action as configured with task_out_polarity, defaults to Toggle).
260 pub fn out(&self) { 275 pub fn out(&self) {
261 let g = regs(); 276 let g = regs();
262 g.tasks_out[self.ch.number()].write(|w| unsafe { w.bits(1) }); 277 g.tasks_out[self.ch.number()].write(|w| unsafe { w.bits(1) });
263 } 278 }
264 279
265 /// Triggers `task set` (set associated pin high). 280 /// Triggers the SET task (set associated pin high).
266 #[cfg(not(feature = "nrf51"))] 281 #[cfg(not(feature = "nrf51"))]
267 pub fn set(&self) { 282 pub fn set(&self) {
268 let g = regs(); 283 let g = regs();
269 g.tasks_set[self.ch.number()].write(|w| unsafe { w.bits(1) }); 284 g.tasks_set[self.ch.number()].write(|w| unsafe { w.bits(1) });
270 } 285 }
271 286
272 /// Triggers `task clear` (set associated pin low). 287 /// Triggers the CLEAR task (set associated pin low).
273 #[cfg(not(feature = "nrf51"))] 288 #[cfg(not(feature = "nrf51"))]
274 pub fn clear(&self) { 289 pub fn clear(&self) {
275 let g = regs(); 290 let g = regs();
@@ -277,21 +292,21 @@ impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> {
277 } 292 }
278 293
279 /// Returns the OUT task, for use with PPI. 294 /// Returns the OUT task, for use with PPI.
280 pub fn task_out(&self) -> Task { 295 pub fn task_out(&self) -> Task<'d> {
281 let g = regs(); 296 let g = regs();
282 Task::from_reg(&g.tasks_out[self.ch.number()]) 297 Task::from_reg(&g.tasks_out[self.ch.number()])
283 } 298 }
284 299
285 /// Returns the CLR task, for use with PPI. 300 /// Returns the CLR task, for use with PPI.
286 #[cfg(not(feature = "nrf51"))] 301 #[cfg(not(feature = "nrf51"))]
287 pub fn task_clr(&self) -> Task { 302 pub fn task_clr(&self) -> Task<'d> {
288 let g = regs(); 303 let g = regs();
289 Task::from_reg(&g.tasks_clr[self.ch.number()]) 304 Task::from_reg(&g.tasks_clr[self.ch.number()])
290 } 305 }
291 306
292 /// Returns the SET task, for use with PPI. 307 /// Returns the SET task, for use with PPI.
293 #[cfg(not(feature = "nrf51"))] 308 #[cfg(not(feature = "nrf51"))]
294 pub fn task_set(&self) -> Task { 309 pub fn task_set(&self) -> Task<'d> {
295 let g = regs(); 310 let g = regs();
296 Task::from_reg(&g.tasks_set[self.ch.number()]) 311 Task::from_reg(&g.tasks_set[self.ch.number()])
297 } 312 }
@@ -299,6 +314,7 @@ impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> {
299 314
300// ======================= 315// =======================
301 316
317#[must_use = "futures do nothing unless you `.await` or poll them"]
302pub(crate) struct PortInputFuture<'a> { 318pub(crate) struct PortInputFuture<'a> {
303 pin: PeripheralRef<'a, AnyPin>, 319 pin: PeripheralRef<'a, AnyPin>,
304} 320}
@@ -334,48 +350,58 @@ impl<'a> Future for PortInputFuture<'a> {
334} 350}
335 351
336impl<'d, T: GpioPin> Input<'d, T> { 352impl<'d, T: GpioPin> Input<'d, T> {
353 /// Wait until the pin is high. If it is already high, return immediately.
337 pub async fn wait_for_high(&mut self) { 354 pub async fn wait_for_high(&mut self) {
338 self.pin.wait_for_high().await 355 self.pin.wait_for_high().await
339 } 356 }
340 357
358 /// Wait until the pin is low. If it is already low, return immediately.
341 pub async fn wait_for_low(&mut self) { 359 pub async fn wait_for_low(&mut self) {
342 self.pin.wait_for_low().await 360 self.pin.wait_for_low().await
343 } 361 }
344 362
363 /// Wait for the pin to undergo a transition from low to high.
345 pub async fn wait_for_rising_edge(&mut self) { 364 pub async fn wait_for_rising_edge(&mut self) {
346 self.pin.wait_for_rising_edge().await 365 self.pin.wait_for_rising_edge().await
347 } 366 }
348 367
368 /// Wait for the pin to undergo a transition from high to low.
349 pub async fn wait_for_falling_edge(&mut self) { 369 pub async fn wait_for_falling_edge(&mut self) {
350 self.pin.wait_for_falling_edge().await 370 self.pin.wait_for_falling_edge().await
351 } 371 }
352 372
373 /// Wait for the pin to undergo any transition, i.e low to high OR high to low.
353 pub async fn wait_for_any_edge(&mut self) { 374 pub async fn wait_for_any_edge(&mut self) {
354 self.pin.wait_for_any_edge().await 375 self.pin.wait_for_any_edge().await
355 } 376 }
356} 377}
357 378
358impl<'d, T: GpioPin> Flex<'d, T> { 379impl<'d, T: GpioPin> Flex<'d, T> {
380 /// Wait until the pin is high. If it is already high, return immediately.
359 pub async fn wait_for_high(&mut self) { 381 pub async fn wait_for_high(&mut self) {
360 self.pin.conf().modify(|_, w| w.sense().high()); 382 self.pin.conf().modify(|_, w| w.sense().high());
361 PortInputFuture::new(&mut self.pin).await 383 PortInputFuture::new(&mut self.pin).await
362 } 384 }
363 385
386 /// Wait until the pin is low. If it is already low, return immediately.
364 pub async fn wait_for_low(&mut self) { 387 pub async fn wait_for_low(&mut self) {
365 self.pin.conf().modify(|_, w| w.sense().low()); 388 self.pin.conf().modify(|_, w| w.sense().low());
366 PortInputFuture::new(&mut self.pin).await 389 PortInputFuture::new(&mut self.pin).await
367 } 390 }
368 391
392 /// Wait for the pin to undergo a transition from low to high.
369 pub async fn wait_for_rising_edge(&mut self) { 393 pub async fn wait_for_rising_edge(&mut self) {
370 self.wait_for_low().await; 394 self.wait_for_low().await;
371 self.wait_for_high().await; 395 self.wait_for_high().await;
372 } 396 }
373 397
398 /// Wait for the pin to undergo a transition from high to low.
374 pub async fn wait_for_falling_edge(&mut self) { 399 pub async fn wait_for_falling_edge(&mut self) {
375 self.wait_for_high().await; 400 self.wait_for_high().await;
376 self.wait_for_low().await; 401 self.wait_for_low().await;
377 } 402 }
378 403
404 /// Wait for the pin to undergo any transition, i.e low to high OR high to low.
379 pub async fn wait_for_any_edge(&mut self) { 405 pub async fn wait_for_any_edge(&mut self) {
380 if self.is_high() { 406 if self.is_high() {
381 self.pin.conf().modify(|_, w| w.sense().low()); 407 self.pin.conf().modify(|_, w| w.sense().low());
@@ -392,8 +418,17 @@ mod sealed {
392 pub trait Channel {} 418 pub trait Channel {}
393} 419}
394 420
421/// GPIOTE channel trait.
422///
423/// Implemented by all GPIOTE channels.
395pub trait Channel: sealed::Channel + Sized { 424pub trait Channel: sealed::Channel + Sized {
425 /// Get the channel number.
396 fn number(&self) -> usize; 426 fn number(&self) -> usize;
427
428 /// Convert this channel to a type-erased `AnyChannel`.
429 ///
430 /// This allows using several channels in situations that might require
431 /// them to be the same type, like putting them in an array.
397 fn degrade(self) -> AnyChannel { 432 fn degrade(self) -> AnyChannel {
398 AnyChannel { 433 AnyChannel {
399 number: self.number() as u8, 434 number: self.number() as u8,
@@ -401,6 +436,12 @@ pub trait Channel: sealed::Channel + Sized {
401 } 436 }
402} 437}
403 438
439/// Type-erased channel.
440///
441/// Obtained by calling `Channel::degrade`.
442///
443/// This allows using several channels in situations that might require
444/// them to be the same type, like putting them in an array.
404pub struct AnyChannel { 445pub struct AnyChannel {
405 number: u8, 446 number: u8,
406} 447}
@@ -458,7 +499,7 @@ mod eh1 {
458 type Error = Infallible; 499 type Error = Infallible;
459 } 500 }
460 501
461 impl<'d, C: Channel, T: GpioPin> embedded_hal_1::digital::blocking::InputPin for InputChannel<'d, C, T> { 502 impl<'d, C: Channel, T: GpioPin> embedded_hal_1::digital::InputPin for InputChannel<'d, C, T> {
462 fn is_high(&self) -> Result<bool, Self::Error> { 503 fn is_high(&self) -> Result<bool, Self::Error> {
463 Ok(self.pin.is_high()) 504 Ok(self.pin.is_high())
464 } 505 }
@@ -469,72 +510,51 @@ mod eh1 {
469 } 510 }
470} 511}
471 512
472cfg_if::cfg_if! { 513#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
473 if #[cfg(all(feature = "unstable-traits", feature = "nightly"))] { 514mod eha {
474 use futures::FutureExt; 515 use super::*;
475
476 impl<'d, T: GpioPin> embedded_hal_async::digital::Wait for Input<'d, T> {
477 type WaitForHighFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
478
479 fn wait_for_high<'a>(&'a mut self) -> Self::WaitForHighFuture<'a> {
480 self.wait_for_high().map(Ok)
481 }
482
483 type WaitForLowFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
484
485 fn wait_for_low<'a>(&'a mut self) -> Self::WaitForLowFuture<'a> {
486 self.wait_for_low().map(Ok)
487 }
488
489 type WaitForRisingEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
490
491 fn wait_for_rising_edge<'a>(&'a mut self) -> Self::WaitForRisingEdgeFuture<'a> {
492 self.wait_for_rising_edge().map(Ok)
493 }
494
495 type WaitForFallingEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
496
497 fn wait_for_falling_edge<'a>(&'a mut self) -> Self::WaitForFallingEdgeFuture<'a> {
498 self.wait_for_falling_edge().map(Ok)
499 }
500
501 type WaitForAnyEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
502 516
503 fn wait_for_any_edge<'a>(&'a mut self) -> Self::WaitForAnyEdgeFuture<'a> { 517 impl<'d, T: GpioPin> embedded_hal_async::digital::Wait for Input<'d, T> {
504 self.wait_for_any_edge().map(Ok) 518 async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
505 } 519 Ok(self.wait_for_high().await)
506 } 520 }
507 521
508 impl<'d, T: GpioPin> embedded_hal_async::digital::Wait for Flex<'d, T> { 522 async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
509 type WaitForHighFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; 523 Ok(self.wait_for_low().await)
510 524 }
511 fn wait_for_high<'a>(&'a mut self) -> Self::WaitForHighFuture<'a> {
512 self.wait_for_high().map(Ok)
513 }
514 525
515 type WaitForLowFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; 526 async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
527 Ok(self.wait_for_rising_edge().await)
528 }
516 529
517 fn wait_for_low<'a>(&'a mut self) -> Self::WaitForLowFuture<'a> { 530 async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
518 self.wait_for_low().map(Ok) 531 Ok(self.wait_for_falling_edge().await)
519 } 532 }
520 533
521 type WaitForRisingEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; 534 async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
535 Ok(self.wait_for_any_edge().await)
536 }
537 }
522 538
523 fn wait_for_rising_edge<'a>(&'a mut self) -> Self::WaitForRisingEdgeFuture<'a> { 539 impl<'d, T: GpioPin> embedded_hal_async::digital::Wait for Flex<'d, T> {
524 self.wait_for_rising_edge().map(Ok) 540 async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
525 } 541 Ok(self.wait_for_high().await)
542 }
526 543
527 type WaitForFallingEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; 544 async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
545 Ok(self.wait_for_low().await)
546 }
528 547
529 fn wait_for_falling_edge<'a>(&'a mut self) -> Self::WaitForFallingEdgeFuture<'a> { 548 async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
530 self.wait_for_falling_edge().map(Ok) 549 Ok(self.wait_for_rising_edge().await)
531 } 550 }
532 551
533 type WaitForAnyEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; 552 async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
553 Ok(self.wait_for_falling_edge().await)
554 }
534 555
535 fn wait_for_any_edge<'a>(&'a mut self) -> Self::WaitForAnyEdgeFuture<'a> { 556 async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
536 self.wait_for_any_edge().map(Ok) 557 Ok(self.wait_for_any_edge().await)
537 }
538 } 558 }
539 } 559 }
540} 560}
diff --git a/embassy-nrf/src/i2s.rs b/embassy-nrf/src/i2s.rs
new file mode 100644
index 000000000..fea38c4c0
--- /dev/null
+++ b/embassy-nrf/src/i2s.rs
@@ -0,0 +1,1194 @@
1//! Inter-IC Sound (I2S) driver.
2
3#![macro_use]
4
5use core::future::poll_fn;
6use core::marker::PhantomData;
7use core::mem::size_of;
8use core::ops::{Deref, DerefMut};
9use core::sync::atomic::{compiler_fence, Ordering};
10use core::task::Poll;
11
12use embassy_hal_common::drop::OnDrop;
13use embassy_hal_common::{into_ref, PeripheralRef};
14
15use crate::gpio::{AnyPin, Pin as GpioPin};
16use crate::interrupt::typelevel::Interrupt;
17use crate::pac::i2s::RegisterBlock;
18use crate::util::{slice_in_ram_or, slice_ptr_parts};
19use crate::{interrupt, Peripheral, EASY_DMA_SIZE};
20
21/// Type alias for `MultiBuffering` with 2 buffers.
22pub type DoubleBuffering<S, const NS: usize> = MultiBuffering<S, 2, NS>;
23
24/// I2S transfer error.
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26#[cfg_attr(feature = "defmt", derive(defmt::Format))]
27#[non_exhaustive]
28pub enum Error {
29 /// The buffer is too long.
30 BufferTooLong,
31 /// The buffer is empty.
32 BufferZeroLength,
33 /// The buffer is not in data RAM. It's most likely in flash, and nRF's DMA cannot access flash.
34 BufferNotInRAM,
35 /// The buffer address is not aligned.
36 BufferMisaligned,
37 /// The buffer length is not a multiple of the alignment.
38 BufferLengthMisaligned,
39}
40
41/// I2S configuration.
42#[derive(Clone)]
43#[non_exhaustive]
44pub struct Config {
45 /// Sample width
46 pub sample_width: SampleWidth,
47 /// Alignment
48 pub align: Align,
49 /// Sample format
50 pub format: Format,
51 /// Channel configuration.
52 pub channels: Channels,
53}
54
55impl Default for Config {
56 fn default() -> Self {
57 Self {
58 sample_width: SampleWidth::_16bit,
59 align: Align::Left,
60 format: Format::I2S,
61 channels: Channels::Stereo,
62 }
63 }
64}
65
66/// I2S clock configuration.
67#[derive(Debug, Eq, PartialEq, Clone, Copy)]
68pub struct MasterClock {
69 freq: MckFreq,
70 ratio: Ratio,
71}
72
73impl MasterClock {
74 /// Create a new `MasterClock`.
75 pub fn new(freq: MckFreq, ratio: Ratio) -> Self {
76 Self { freq, ratio }
77 }
78}
79
80impl MasterClock {
81 /// Get the sample rate for this clock configuration.
82 pub fn sample_rate(&self) -> u32 {
83 self.freq.to_frequency() / self.ratio.to_divisor()
84 }
85}
86
87/// Master clock generator frequency.
88#[derive(Debug, Eq, PartialEq, Clone, Copy)]
89pub enum MckFreq {
90 /// 32 Mhz / 8 = 4000.00 kHz
91 _32MDiv8,
92 /// 32 Mhz / 10 = 3200.00 kHz
93 _32MDiv10,
94 /// 32 Mhz / 11 = 2909.09 kHz
95 _32MDiv11,
96 /// 32 Mhz / 15 = 2133.33 kHz
97 _32MDiv15,
98 /// 32 Mhz / 16 = 2000.00 kHz
99 _32MDiv16,
100 /// 32 Mhz / 21 = 1523.81 kHz
101 _32MDiv21,
102 /// 32 Mhz / 23 = 1391.30 kHz
103 _32MDiv23,
104 /// 32 Mhz / 30 = 1066.67 kHz
105 _32MDiv30,
106 /// 32 Mhz / 31 = 1032.26 kHz
107 _32MDiv31,
108 /// 32 Mhz / 32 = 1000.00 kHz
109 _32MDiv32,
110 /// 32 Mhz / 42 = 761.90 kHz
111 _32MDiv42,
112 /// 32 Mhz / 63 = 507.94 kHz
113 _32MDiv63,
114 /// 32 Mhz / 125 = 256.00 kHz
115 _32MDiv125,
116}
117
118impl MckFreq {
119 const REGISTER_VALUES: &'static [u32] = &[
120 0x20000000, 0x18000000, 0x16000000, 0x11000000, 0x10000000, 0x0C000000, 0x0B000000, 0x08800000, 0x08400000,
121 0x08000000, 0x06000000, 0x04100000, 0x020C0000,
122 ];
123
124 const FREQUENCIES: &'static [u32] = &[
125 4000000, 3200000, 2909090, 2133333, 2000000, 1523809, 1391304, 1066666, 1032258, 1000000, 761904, 507936,
126 256000,
127 ];
128
129 /// Return the value that needs to be written to the register.
130 pub fn to_register_value(&self) -> u32 {
131 Self::REGISTER_VALUES[usize::from(*self)]
132 }
133
134 /// Return the master clock frequency.
135 pub fn to_frequency(&self) -> u32 {
136 Self::FREQUENCIES[usize::from(*self)]
137 }
138}
139
140impl From<MckFreq> for usize {
141 fn from(variant: MckFreq) -> Self {
142 variant as _
143 }
144}
145
146/// Master clock frequency ratio
147///
148/// Sample Rate = LRCK = MCK / Ratio
149///
150#[derive(Debug, Eq, PartialEq, Clone, Copy)]
151pub enum Ratio {
152 /// Divide by 32
153 _32x,
154 /// Divide by 48
155 _48x,
156 /// Divide by 64
157 _64x,
158 /// Divide by 96
159 _96x,
160 /// Divide by 128
161 _128x,
162 /// Divide by 192
163 _192x,
164 /// Divide by 256
165 _256x,
166 /// Divide by 384
167 _384x,
168 /// Divide by 512
169 _512x,
170}
171
172impl Ratio {
173 const RATIOS: &'static [u32] = &[32, 48, 64, 96, 128, 192, 256, 384, 512];
174
175 /// Return the value that needs to be written to the register.
176 pub fn to_register_value(&self) -> u8 {
177 usize::from(*self) as u8
178 }
179
180 /// Return the divisor for this ratio
181 pub fn to_divisor(&self) -> u32 {
182 Self::RATIOS[usize::from(*self)]
183 }
184}
185
186impl From<Ratio> for usize {
187 fn from(variant: Ratio) -> Self {
188 variant as _
189 }
190}
191
192/// Approximate sample rates.
193///
194/// Those are common sample rates that can not be configured without an small error.
195///
196/// For custom master clock configuration, please refer to [MasterClock].
197#[derive(Clone, Copy)]
198pub enum ApproxSampleRate {
199 /// 11025 Hz
200 _11025,
201 /// 16000 Hz
202 _16000,
203 /// 22050 Hz
204 _22050,
205 /// 32000 Hz
206 _32000,
207 /// 44100 Hz
208 _44100,
209 /// 48000 Hz
210 _48000,
211}
212
213impl From<ApproxSampleRate> for MasterClock {
214 fn from(value: ApproxSampleRate) -> Self {
215 match value {
216 // error = 86
217 ApproxSampleRate::_11025 => MasterClock::new(MckFreq::_32MDiv15, Ratio::_192x),
218 // error = 127
219 ApproxSampleRate::_16000 => MasterClock::new(MckFreq::_32MDiv21, Ratio::_96x),
220 // error = 172
221 ApproxSampleRate::_22050 => MasterClock::new(MckFreq::_32MDiv15, Ratio::_96x),
222 // error = 254
223 ApproxSampleRate::_32000 => MasterClock::new(MckFreq::_32MDiv21, Ratio::_48x),
224 // error = 344
225 ApproxSampleRate::_44100 => MasterClock::new(MckFreq::_32MDiv15, Ratio::_48x),
226 // error = 381
227 ApproxSampleRate::_48000 => MasterClock::new(MckFreq::_32MDiv21, Ratio::_32x),
228 }
229 }
230}
231
232impl ApproxSampleRate {
233 /// Get the sample rate as an integer.
234 pub fn sample_rate(&self) -> u32 {
235 MasterClock::from(*self).sample_rate()
236 }
237}
238
239/// Exact sample rates.
240///
241/// Those are non standard sample rates that can be configured without error.
242///
243/// For custom master clock configuration, please refer to [Mode].
244#[derive(Clone, Copy)]
245pub enum ExactSampleRate {
246 /// 8000 Hz
247 _8000,
248 /// 10582 Hz
249 _10582,
250 /// 12500 Hz
251 _12500,
252 /// 15625 Hz
253 _15625,
254 /// 15873 Hz
255 _15873,
256 /// 25000 Hz
257 _25000,
258 /// 31250 Hz
259 _31250,
260 /// 50000 Hz
261 _50000,
262 /// 62500 Hz
263 _62500,
264 /// 100000 Hz
265 _100000,
266 /// 125000 Hz
267 _125000,
268}
269
270impl ExactSampleRate {
271 /// Get the sample rate as an integer.
272 pub fn sample_rate(&self) -> u32 {
273 MasterClock::from(*self).sample_rate()
274 }
275}
276
277impl From<ExactSampleRate> for MasterClock {
278 fn from(value: ExactSampleRate) -> Self {
279 match value {
280 ExactSampleRate::_8000 => MasterClock::new(MckFreq::_32MDiv125, Ratio::_32x),
281 ExactSampleRate::_10582 => MasterClock::new(MckFreq::_32MDiv63, Ratio::_48x),
282 ExactSampleRate::_12500 => MasterClock::new(MckFreq::_32MDiv10, Ratio::_256x),
283 ExactSampleRate::_15625 => MasterClock::new(MckFreq::_32MDiv32, Ratio::_64x),
284 ExactSampleRate::_15873 => MasterClock::new(MckFreq::_32MDiv63, Ratio::_32x),
285 ExactSampleRate::_25000 => MasterClock::new(MckFreq::_32MDiv10, Ratio::_128x),
286 ExactSampleRate::_31250 => MasterClock::new(MckFreq::_32MDiv32, Ratio::_32x),
287 ExactSampleRate::_50000 => MasterClock::new(MckFreq::_32MDiv10, Ratio::_64x),
288 ExactSampleRate::_62500 => MasterClock::new(MckFreq::_32MDiv16, Ratio::_32x),
289 ExactSampleRate::_100000 => MasterClock::new(MckFreq::_32MDiv10, Ratio::_32x),
290 ExactSampleRate::_125000 => MasterClock::new(MckFreq::_32MDiv8, Ratio::_32x),
291 }
292 }
293}
294
295/// Sample width.
296#[derive(Debug, Eq, PartialEq, Clone, Copy)]
297pub enum SampleWidth {
298 /// 8 bit samples.
299 _8bit,
300 /// 16 bit samples.
301 _16bit,
302 /// 24 bit samples.
303 _24bit,
304}
305
306impl From<SampleWidth> for u8 {
307 fn from(variant: SampleWidth) -> Self {
308 variant as _
309 }
310}
311
312/// Channel used for the most significant sample value in a frame.
313#[derive(Debug, Eq, PartialEq, Clone, Copy)]
314pub enum Align {
315 /// Left-align samples.
316 Left,
317 /// Right-align samples.
318 Right,
319}
320
321impl From<Align> for bool {
322 fn from(variant: Align) -> Self {
323 match variant {
324 Align::Left => false,
325 Align::Right => true,
326 }
327 }
328}
329
330/// Frame format.
331#[derive(Debug, Eq, PartialEq, Clone, Copy)]
332pub enum Format {
333 /// I2S frame format
334 I2S,
335 /// Aligned frame format
336 Aligned,
337}
338
339impl From<Format> for bool {
340 fn from(variant: Format) -> Self {
341 match variant {
342 Format::I2S => false,
343 Format::Aligned => true,
344 }
345 }
346}
347
348/// Channels
349#[derive(Debug, Eq, PartialEq, Clone, Copy)]
350pub enum Channels {
351 /// Stereo (2 channels).
352 Stereo,
353 /// Mono, left channel only.
354 MonoLeft,
355 /// Mono, right channel only.
356 MonoRight,
357}
358
359impl From<Channels> for u8 {
360 fn from(variant: Channels) -> Self {
361 variant as _
362 }
363}
364
365/// Interrupt handler.
366pub struct InterruptHandler<T: Instance> {
367 _phantom: PhantomData<T>,
368}
369
370impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
371 unsafe fn on_interrupt() {
372 let device = Device::<T>::new();
373 let s = T::state();
374
375 if device.is_tx_ptr_updated() {
376 trace!("TX INT");
377 s.tx_waker.wake();
378 device.disable_tx_ptr_interrupt();
379 }
380
381 if device.is_rx_ptr_updated() {
382 trace!("RX INT");
383 s.rx_waker.wake();
384 device.disable_rx_ptr_interrupt();
385 }
386
387 if device.is_stopped() {
388 trace!("STOPPED INT");
389 s.stop_waker.wake();
390 device.disable_stopped_interrupt();
391 }
392 }
393}
394
395/// I2S driver.
396pub struct I2S<'d, T: Instance> {
397 i2s: PeripheralRef<'d, T>,
398 mck: Option<PeripheralRef<'d, AnyPin>>,
399 sck: PeripheralRef<'d, AnyPin>,
400 lrck: PeripheralRef<'d, AnyPin>,
401 sdin: Option<PeripheralRef<'d, AnyPin>>,
402 sdout: Option<PeripheralRef<'d, AnyPin>>,
403 master_clock: Option<MasterClock>,
404 config: Config,
405}
406
407impl<'d, T: Instance> I2S<'d, T> {
408 /// Create a new I2S in master mode
409 pub fn new_master(
410 i2s: impl Peripheral<P = T> + 'd,
411 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
412 mck: impl Peripheral<P = impl GpioPin> + 'd,
413 sck: impl Peripheral<P = impl GpioPin> + 'd,
414 lrck: impl Peripheral<P = impl GpioPin> + 'd,
415 master_clock: MasterClock,
416 config: Config,
417 ) -> Self {
418 into_ref!(i2s, mck, sck, lrck);
419 Self {
420 i2s,
421 mck: Some(mck.map_into()),
422 sck: sck.map_into(),
423 lrck: lrck.map_into(),
424 sdin: None,
425 sdout: None,
426 master_clock: Some(master_clock),
427 config,
428 }
429 }
430
431 /// Create a new I2S in slave mode
432 pub fn new_slave(
433 i2s: impl Peripheral<P = T> + 'd,
434 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
435 sck: impl Peripheral<P = impl GpioPin> + 'd,
436 lrck: impl Peripheral<P = impl GpioPin> + 'd,
437 config: Config,
438 ) -> Self {
439 into_ref!(i2s, sck, lrck);
440 Self {
441 i2s,
442 mck: None,
443 sck: sck.map_into(),
444 lrck: lrck.map_into(),
445 sdin: None,
446 sdout: None,
447 master_clock: None,
448 config,
449 }
450 }
451
452 /// I2S output only
453 pub fn output<S: Sample, const NB: usize, const NS: usize>(
454 mut self,
455 sdout: impl Peripheral<P = impl GpioPin> + 'd,
456 buffers: MultiBuffering<S, NB, NS>,
457 ) -> OutputStream<'d, T, S, NB, NS> {
458 self.sdout = Some(sdout.into_ref().map_into());
459 OutputStream {
460 _p: self.build(),
461 buffers,
462 }
463 }
464
465 /// I2S input only
466 pub fn input<S: Sample, const NB: usize, const NS: usize>(
467 mut self,
468 sdin: impl Peripheral<P = impl GpioPin> + 'd,
469 buffers: MultiBuffering<S, NB, NS>,
470 ) -> InputStream<'d, T, S, NB, NS> {
471 self.sdin = Some(sdin.into_ref().map_into());
472 InputStream {
473 _p: self.build(),
474 buffers,
475 }
476 }
477
478 /// I2S full duplex (input and output)
479 pub fn full_duplex<S: Sample, const NB: usize, const NS: usize>(
480 mut self,
481 sdin: impl Peripheral<P = impl GpioPin> + 'd,
482 sdout: impl Peripheral<P = impl GpioPin> + 'd,
483 buffers_out: MultiBuffering<S, NB, NS>,
484 buffers_in: MultiBuffering<S, NB, NS>,
485 ) -> FullDuplexStream<'d, T, S, NB, NS> {
486 self.sdout = Some(sdout.into_ref().map_into());
487 self.sdin = Some(sdin.into_ref().map_into());
488
489 FullDuplexStream {
490 _p: self.build(),
491 buffers_out,
492 buffers_in,
493 }
494 }
495
496 fn build(self) -> PeripheralRef<'d, T> {
497 self.apply_config();
498 self.select_pins();
499 self.setup_interrupt();
500
501 let device = Device::<T>::new();
502 device.enable();
503
504 self.i2s
505 }
506
507 fn apply_config(&self) {
508 let c = &T::regs().config;
509 match &self.master_clock {
510 Some(MasterClock { freq, ratio }) => {
511 c.mode.write(|w| w.mode().master());
512 c.mcken.write(|w| w.mcken().enabled());
513 c.mckfreq
514 .write(|w| unsafe { w.mckfreq().bits(freq.to_register_value()) });
515 c.ratio.write(|w| unsafe { w.ratio().bits(ratio.to_register_value()) });
516 }
517 None => {
518 c.mode.write(|w| w.mode().slave());
519 }
520 };
521
522 c.swidth
523 .write(|w| unsafe { w.swidth().bits(self.config.sample_width.into()) });
524 c.align.write(|w| w.align().bit(self.config.align.into()));
525 c.format.write(|w| w.format().bit(self.config.format.into()));
526 c.channels
527 .write(|w| unsafe { w.channels().bits(self.config.channels.into()) });
528 }
529
530 fn select_pins(&self) {
531 let psel = &T::regs().psel;
532
533 if let Some(mck) = &self.mck {
534 psel.mck.write(|w| {
535 unsafe { w.bits(mck.psel_bits()) };
536 w.connect().connected()
537 });
538 }
539
540 psel.sck.write(|w| {
541 unsafe { w.bits(self.sck.psel_bits()) };
542 w.connect().connected()
543 });
544
545 psel.lrck.write(|w| {
546 unsafe { w.bits(self.lrck.psel_bits()) };
547 w.connect().connected()
548 });
549
550 if let Some(sdin) = &self.sdin {
551 psel.sdin.write(|w| {
552 unsafe { w.bits(sdin.psel_bits()) };
553 w.connect().connected()
554 });
555 }
556
557 if let Some(sdout) = &self.sdout {
558 psel.sdout.write(|w| {
559 unsafe { w.bits(sdout.psel_bits()) };
560 w.connect().connected()
561 });
562 }
563 }
564
565 fn setup_interrupt(&self) {
566 T::Interrupt::unpend();
567 unsafe { T::Interrupt::enable() };
568
569 let device = Device::<T>::new();
570 device.disable_tx_ptr_interrupt();
571 device.disable_rx_ptr_interrupt();
572 device.disable_stopped_interrupt();
573
574 device.reset_tx_ptr_event();
575 device.reset_rx_ptr_event();
576 device.reset_stopped_event();
577
578 device.enable_tx_ptr_interrupt();
579 device.enable_rx_ptr_interrupt();
580 device.enable_stopped_interrupt();
581 }
582
583 async fn stop() {
584 compiler_fence(Ordering::SeqCst);
585
586 let device = Device::<T>::new();
587 device.stop();
588
589 T::state().started.store(false, Ordering::Relaxed);
590
591 poll_fn(|cx| {
592 T::state().stop_waker.register(cx.waker());
593
594 if device.is_stopped() {
595 trace!("STOP: Ready");
596 device.reset_stopped_event();
597 Poll::Ready(())
598 } else {
599 trace!("STOP: Pending");
600 Poll::Pending
601 }
602 })
603 .await;
604
605 device.disable();
606 }
607
608 async fn send_from_ram<S>(buffer_ptr: *const [S]) -> Result<(), Error>
609 where
610 S: Sample,
611 {
612 trace!("SEND: {}", buffer_ptr as *const S as u32);
613
614 slice_in_ram_or(buffer_ptr, Error::BufferNotInRAM)?;
615
616 compiler_fence(Ordering::SeqCst);
617
618 let device = Device::<T>::new();
619
620 device.update_tx(buffer_ptr)?;
621
622 Self::wait_tx_ptr_update().await;
623
624 compiler_fence(Ordering::SeqCst);
625
626 Ok(())
627 }
628
629 async fn wait_tx_ptr_update() {
630 let drop = OnDrop::new(move || {
631 trace!("TX DROP: Stopping");
632
633 let device = Device::<T>::new();
634 device.disable_tx_ptr_interrupt();
635 device.reset_tx_ptr_event();
636 device.disable_tx();
637
638 // TX is stopped almost instantly, spinning is fine.
639 while !device.is_tx_ptr_updated() {}
640
641 trace!("TX DROP: Stopped");
642 });
643
644 poll_fn(|cx| {
645 T::state().tx_waker.register(cx.waker());
646
647 let device = Device::<T>::new();
648 if device.is_tx_ptr_updated() {
649 trace!("TX POLL: Ready");
650 device.reset_tx_ptr_event();
651 device.enable_tx_ptr_interrupt();
652 Poll::Ready(())
653 } else {
654 trace!("TX POLL: Pending");
655 Poll::Pending
656 }
657 })
658 .await;
659
660 drop.defuse();
661 }
662
663 async fn receive_from_ram<S>(buffer_ptr: *mut [S]) -> Result<(), Error>
664 where
665 S: Sample,
666 {
667 trace!("RECEIVE: {}", buffer_ptr as *const S as u32);
668
669 // NOTE: RAM slice check for rx is not necessary, as a mutable
670 // slice can only be built from data located in RAM.
671
672 compiler_fence(Ordering::SeqCst);
673
674 let device = Device::<T>::new();
675
676 device.update_rx(buffer_ptr)?;
677
678 Self::wait_rx_ptr_update().await;
679
680 compiler_fence(Ordering::SeqCst);
681
682 Ok(())
683 }
684
685 async fn wait_rx_ptr_update() {
686 let drop = OnDrop::new(move || {
687 trace!("RX DROP: Stopping");
688
689 let device = Device::<T>::new();
690 device.disable_rx_ptr_interrupt();
691 device.reset_rx_ptr_event();
692 device.disable_rx();
693
694 // TX is stopped almost instantly, spinning is fine.
695 while !device.is_rx_ptr_updated() {}
696
697 trace!("RX DROP: Stopped");
698 });
699
700 poll_fn(|cx| {
701 T::state().rx_waker.register(cx.waker());
702
703 let device = Device::<T>::new();
704 if device.is_rx_ptr_updated() {
705 trace!("RX POLL: Ready");
706 device.reset_rx_ptr_event();
707 device.enable_rx_ptr_interrupt();
708 Poll::Ready(())
709 } else {
710 trace!("RX POLL: Pending");
711 Poll::Pending
712 }
713 })
714 .await;
715
716 drop.defuse();
717 }
718}
719
720/// I2S output
721pub struct OutputStream<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> {
722 _p: PeripheralRef<'d, T>,
723 buffers: MultiBuffering<S, NB, NS>,
724}
725
726impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> OutputStream<'d, T, S, NB, NS> {
727 /// Get a mutable reference to the current buffer.
728 pub fn buffer(&mut self) -> &mut [S] {
729 self.buffers.get_mut()
730 }
731
732 /// Prepare the initial buffer and start the I2S transfer.
733 pub async fn start(&mut self) -> Result<(), Error>
734 where
735 S: Sample,
736 {
737 let device = Device::<T>::new();
738
739 let s = T::state();
740 if s.started.load(Ordering::Relaxed) {
741 self.stop().await;
742 }
743
744 device.enable();
745 device.enable_tx();
746
747 device.update_tx(self.buffers.switch())?;
748
749 s.started.store(true, Ordering::Relaxed);
750
751 device.start();
752
753 I2S::<T>::wait_tx_ptr_update().await;
754
755 Ok(())
756 }
757
758 /// Stops the I2S transfer and waits until it has stopped.
759 #[inline(always)]
760 pub async fn stop(&self) {
761 I2S::<T>::stop().await
762 }
763
764 /// Sends the current buffer for transmission in the DMA.
765 /// Switches to use the next available buffer.
766 pub async fn send(&mut self) -> Result<(), Error>
767 where
768 S: Sample,
769 {
770 I2S::<T>::send_from_ram(self.buffers.switch()).await
771 }
772}
773
774/// I2S input
775pub struct InputStream<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> {
776 _p: PeripheralRef<'d, T>,
777 buffers: MultiBuffering<S, NB, NS>,
778}
779
780impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> InputStream<'d, T, S, NB, NS> {
781 /// Get a mutable reference to the current buffer.
782 pub fn buffer(&mut self) -> &mut [S] {
783 self.buffers.get_mut()
784 }
785
786 /// Prepare the initial buffer and start the I2S transfer.
787 pub async fn start(&mut self) -> Result<(), Error>
788 where
789 S: Sample,
790 {
791 let device = Device::<T>::new();
792
793 let s = T::state();
794 if s.started.load(Ordering::Relaxed) {
795 self.stop().await;
796 }
797
798 device.enable();
799 device.enable_rx();
800
801 device.update_rx(self.buffers.switch())?;
802
803 s.started.store(true, Ordering::Relaxed);
804
805 device.start();
806
807 I2S::<T>::wait_rx_ptr_update().await;
808
809 Ok(())
810 }
811
812 /// Stops the I2S transfer and waits until it has stopped.
813 #[inline(always)]
814 pub async fn stop(&self) {
815 I2S::<T>::stop().await
816 }
817
818 /// Sets the current buffer for reception from the DMA.
819 /// Switches to use the next available buffer.
820 #[allow(unused_mut)]
821 pub async fn receive(&mut self) -> Result<(), Error>
822 where
823 S: Sample,
824 {
825 I2S::<T>::receive_from_ram(self.buffers.switch_mut()).await
826 }
827}
828
829/// I2S full duplex stream (input & output)
830pub struct FullDuplexStream<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> {
831 _p: PeripheralRef<'d, T>,
832 buffers_out: MultiBuffering<S, NB, NS>,
833 buffers_in: MultiBuffering<S, NB, NS>,
834}
835
836impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> FullDuplexStream<'d, T, S, NB, NS> {
837 /// Get the current output and input buffers.
838 pub fn buffers(&mut self) -> (&mut [S], &[S]) {
839 (self.buffers_out.get_mut(), self.buffers_in.get())
840 }
841
842 /// Prepare the initial buffers and start the I2S transfer.
843 pub async fn start(&mut self) -> Result<(), Error>
844 where
845 S: Sample,
846 {
847 let device = Device::<T>::new();
848
849 let s = T::state();
850 if s.started.load(Ordering::Relaxed) {
851 self.stop().await;
852 }
853
854 device.enable();
855 device.enable_tx();
856 device.enable_rx();
857
858 device.update_tx(self.buffers_out.switch())?;
859 device.update_rx(self.buffers_in.switch_mut())?;
860
861 s.started.store(true, Ordering::Relaxed);
862
863 device.start();
864
865 I2S::<T>::wait_tx_ptr_update().await;
866 I2S::<T>::wait_rx_ptr_update().await;
867
868 Ok(())
869 }
870
871 /// Stops the I2S transfer and waits until it has stopped.
872 #[inline(always)]
873 pub async fn stop(&self) {
874 I2S::<T>::stop().await
875 }
876
877 /// Sets the current buffers for output and input for transmission/reception from the DMA.
878 /// Switch to use the next available buffers for output/input.
879 pub async fn send_and_receive(&mut self) -> Result<(), Error>
880 where
881 S: Sample,
882 {
883 I2S::<T>::send_from_ram(self.buffers_out.switch()).await?;
884 I2S::<T>::receive_from_ram(self.buffers_in.switch_mut()).await?;
885 Ok(())
886 }
887}
888
889/// Helper encapsulating common I2S device operations.
890struct Device<T>(&'static RegisterBlock, PhantomData<T>);
891
892impl<T: Instance> Device<T> {
893 fn new() -> Self {
894 Self(T::regs(), PhantomData)
895 }
896
897 #[inline(always)]
898 pub fn enable(&self) {
899 trace!("ENABLED");
900 self.0.enable.write(|w| w.enable().enabled());
901 }
902
903 #[inline(always)]
904 pub fn disable(&self) {
905 trace!("DISABLED");
906 self.0.enable.write(|w| w.enable().disabled());
907 }
908
909 #[inline(always)]
910 fn enable_tx(&self) {
911 trace!("TX ENABLED");
912 self.0.config.txen.write(|w| w.txen().enabled());
913 }
914
915 #[inline(always)]
916 fn disable_tx(&self) {
917 trace!("TX DISABLED");
918 self.0.config.txen.write(|w| w.txen().disabled());
919 }
920
921 #[inline(always)]
922 fn enable_rx(&self) {
923 trace!("RX ENABLED");
924 self.0.config.rxen.write(|w| w.rxen().enabled());
925 }
926
927 #[inline(always)]
928 fn disable_rx(&self) {
929 trace!("RX DISABLED");
930 self.0.config.rxen.write(|w| w.rxen().disabled());
931 }
932
933 #[inline(always)]
934 fn start(&self) {
935 trace!("START");
936 self.0.tasks_start.write(|w| unsafe { w.bits(1) });
937 }
938
939 #[inline(always)]
940 fn stop(&self) {
941 self.0.tasks_stop.write(|w| unsafe { w.bits(1) });
942 }
943
944 #[inline(always)]
945 fn is_stopped(&self) -> bool {
946 self.0.events_stopped.read().bits() != 0
947 }
948
949 #[inline(always)]
950 fn reset_stopped_event(&self) {
951 trace!("STOPPED EVENT: Reset");
952 self.0.events_stopped.reset();
953 }
954
955 #[inline(always)]
956 fn disable_stopped_interrupt(&self) {
957 trace!("STOPPED INTERRUPT: Disabled");
958 self.0.intenclr.write(|w| w.stopped().clear());
959 }
960
961 #[inline(always)]
962 fn enable_stopped_interrupt(&self) {
963 trace!("STOPPED INTERRUPT: Enabled");
964 self.0.intenset.write(|w| w.stopped().set());
965 }
966
967 #[inline(always)]
968 fn reset_tx_ptr_event(&self) {
969 trace!("TX PTR EVENT: Reset");
970 self.0.events_txptrupd.reset();
971 }
972
973 #[inline(always)]
974 fn reset_rx_ptr_event(&self) {
975 trace!("RX PTR EVENT: Reset");
976 self.0.events_rxptrupd.reset();
977 }
978
979 #[inline(always)]
980 fn disable_tx_ptr_interrupt(&self) {
981 trace!("TX PTR INTERRUPT: Disabled");
982 self.0.intenclr.write(|w| w.txptrupd().clear());
983 }
984
985 #[inline(always)]
986 fn disable_rx_ptr_interrupt(&self) {
987 trace!("RX PTR INTERRUPT: Disabled");
988 self.0.intenclr.write(|w| w.rxptrupd().clear());
989 }
990
991 #[inline(always)]
992 fn enable_tx_ptr_interrupt(&self) {
993 trace!("TX PTR INTERRUPT: Enabled");
994 self.0.intenset.write(|w| w.txptrupd().set());
995 }
996
997 #[inline(always)]
998 fn enable_rx_ptr_interrupt(&self) {
999 trace!("RX PTR INTERRUPT: Enabled");
1000 self.0.intenset.write(|w| w.rxptrupd().set());
1001 }
1002
1003 #[inline(always)]
1004 fn is_tx_ptr_updated(&self) -> bool {
1005 self.0.events_txptrupd.read().bits() != 0
1006 }
1007
1008 #[inline(always)]
1009 fn is_rx_ptr_updated(&self) -> bool {
1010 self.0.events_rxptrupd.read().bits() != 0
1011 }
1012
1013 #[inline]
1014 fn update_tx<S>(&self, buffer_ptr: *const [S]) -> Result<(), Error> {
1015 let (ptr, maxcnt) = Self::validated_dma_parts(buffer_ptr)?;
1016 self.0.rxtxd.maxcnt.write(|w| unsafe { w.bits(maxcnt) });
1017 self.0.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr) });
1018 Ok(())
1019 }
1020
1021 #[inline]
1022 fn update_rx<S>(&self, buffer_ptr: *const [S]) -> Result<(), Error> {
1023 let (ptr, maxcnt) = Self::validated_dma_parts(buffer_ptr)?;
1024 self.0.rxtxd.maxcnt.write(|w| unsafe { w.bits(maxcnt) });
1025 self.0.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr) });
1026 Ok(())
1027 }
1028
1029 fn validated_dma_parts<S>(buffer_ptr: *const [S]) -> Result<(u32, u32), Error> {
1030 let (ptr, len) = slice_ptr_parts(buffer_ptr);
1031 let ptr = ptr as u32;
1032 let bytes_len = len * size_of::<S>();
1033 let maxcnt = (bytes_len / size_of::<u32>()) as u32;
1034
1035 trace!("PTR={}, MAXCNT={}", ptr, maxcnt);
1036
1037 if ptr % 4 != 0 {
1038 Err(Error::BufferMisaligned)
1039 } else if bytes_len % 4 != 0 {
1040 Err(Error::BufferLengthMisaligned)
1041 } else if maxcnt as usize > EASY_DMA_SIZE {
1042 Err(Error::BufferTooLong)
1043 } else {
1044 Ok((ptr, maxcnt))
1045 }
1046 }
1047}
1048
1049/// Sample details
1050pub trait Sample: Sized + Copy + Default {
1051 /// Width of this sample type.
1052 const WIDTH: usize;
1053
1054 /// Scale of this sample.
1055 const SCALE: Self;
1056}
1057
1058impl Sample for i8 {
1059 const WIDTH: usize = 8;
1060 const SCALE: Self = 1 << (Self::WIDTH - 1);
1061}
1062
1063impl Sample for i16 {
1064 const WIDTH: usize = 16;
1065 const SCALE: Self = 1 << (Self::WIDTH - 1);
1066}
1067
1068impl Sample for i32 {
1069 const WIDTH: usize = 24;
1070 const SCALE: Self = 1 << (Self::WIDTH - 1);
1071}
1072
1073/// A 4-bytes aligned buffer. Needed for DMA access.
1074#[derive(Clone, Copy)]
1075#[repr(align(4))]
1076pub struct AlignedBuffer<T: Sample, const N: usize>([T; N]);
1077
1078impl<T: Sample, const N: usize> AlignedBuffer<T, N> {
1079 /// Create a new `AlignedBuffer`.
1080 pub fn new(array: [T; N]) -> Self {
1081 Self(array)
1082 }
1083}
1084
1085impl<T: Sample, const N: usize> Default for AlignedBuffer<T, N> {
1086 fn default() -> Self {
1087 Self([T::default(); N])
1088 }
1089}
1090
1091impl<T: Sample, const N: usize> Deref for AlignedBuffer<T, N> {
1092 type Target = [T];
1093 fn deref(&self) -> &Self::Target {
1094 self.0.as_slice()
1095 }
1096}
1097
1098impl<T: Sample, const N: usize> DerefMut for AlignedBuffer<T, N> {
1099 fn deref_mut(&mut self) -> &mut Self::Target {
1100 self.0.as_mut_slice()
1101 }
1102}
1103
1104/// Set of multiple buffers, for multi-buffering transfers.
1105pub struct MultiBuffering<S: Sample, const NB: usize, const NS: usize> {
1106 buffers: [AlignedBuffer<S, NS>; NB],
1107 index: usize,
1108}
1109
1110impl<S: Sample, const NB: usize, const NS: usize> MultiBuffering<S, NB, NS> {
1111 /// Create a new `MultiBuffering`.
1112 pub fn new() -> Self {
1113 assert!(NB > 1);
1114 Self {
1115 buffers: [AlignedBuffer::<S, NS>::default(); NB],
1116 index: 0,
1117 }
1118 }
1119
1120 fn get(&self) -> &[S] {
1121 &self.buffers[self.index]
1122 }
1123
1124 fn get_mut(&mut self) -> &mut [S] {
1125 &mut self.buffers[self.index]
1126 }
1127
1128 /// Advance to use the next buffer and return a non mutable pointer to the previous one.
1129 fn switch(&mut self) -> *const [S] {
1130 let prev_index = self.index;
1131 self.index = (self.index + 1) % NB;
1132 self.buffers[prev_index].deref() as *const [S]
1133 }
1134
1135 /// Advance to use the next buffer and return a mutable pointer to the previous one.
1136 fn switch_mut(&mut self) -> *mut [S] {
1137 let prev_index = self.index;
1138 self.index = (self.index + 1) % NB;
1139 self.buffers[prev_index].deref_mut() as *mut [S]
1140 }
1141}
1142
1143pub(crate) mod sealed {
1144 use core::sync::atomic::AtomicBool;
1145
1146 use embassy_sync::waitqueue::AtomicWaker;
1147
1148 /// Peripheral static state
1149 pub struct State {
1150 pub started: AtomicBool,
1151 pub rx_waker: AtomicWaker,
1152 pub tx_waker: AtomicWaker,
1153 pub stop_waker: AtomicWaker,
1154 }
1155
1156 impl State {
1157 pub const fn new() -> Self {
1158 Self {
1159 started: AtomicBool::new(false),
1160 rx_waker: AtomicWaker::new(),
1161 tx_waker: AtomicWaker::new(),
1162 stop_waker: AtomicWaker::new(),
1163 }
1164 }
1165 }
1166
1167 pub trait Instance {
1168 fn regs() -> &'static crate::pac::i2s::RegisterBlock;
1169 fn state() -> &'static State;
1170 }
1171}
1172
1173/// I2S peripheral instance.
1174pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
1175 /// Interrupt for this peripheral.
1176 type Interrupt: interrupt::typelevel::Interrupt;
1177}
1178
1179macro_rules! impl_i2s {
1180 ($type:ident, $pac_type:ident, $irq:ident) => {
1181 impl crate::i2s::sealed::Instance for peripherals::$type {
1182 fn regs() -> &'static crate::pac::i2s::RegisterBlock {
1183 unsafe { &*pac::$pac_type::ptr() }
1184 }
1185 fn state() -> &'static crate::i2s::sealed::State {
1186 static STATE: crate::i2s::sealed::State = crate::i2s::sealed::State::new();
1187 &STATE
1188 }
1189 }
1190 impl crate::i2s::Instance for peripherals::$type {
1191 type Interrupt = crate::interrupt::typelevel::$irq;
1192 }
1193 };
1194}
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 205891954..d23759f9d 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -1,49 +1,7 @@
1//! # Embassy nRF HAL
2//!
3//! HALs implement safe, idiomatic Rust APIs to use the hardware capabilities, so raw register manipulation is not needed.
4//!
5//! The Embassy nRF HAL targets the Nordic Semiconductor nRF family of hardware. The HAL implements both blocking and async APIs
6//! for many peripherals. The benefit of using the async APIs is that the HAL takes care of waiting for peripherals to
7//! complete operations in low power mod and handling interrupts, so that applications can focus on more important matters.
8//!
9//! ## EasyDMA considerations
10//!
11//! On nRF chips, peripherals can use the so called EasyDMA feature to offload the task of interacting
12//! with peripherals. It takes care of sending/receiving data over a variety of bus protocols (TWI/I2C, UART, SPI).
13//! However, EasyDMA requires the buffers used to transmit and receive data to reside in RAM. Unfortunately, Rust
14//! slices will not always do so. The following example using the SPI peripheral shows a common situation where this might happen:
15//!
16//! ```no_run
17//! // As we pass a slice to the function whose contents will not ever change,
18//! // the compiler writes it into the flash and thus the pointer to it will
19//! // reference static memory. Since EasyDMA requires slices to reside in RAM,
20//! // this function call will fail.
21//! let result = spim.write_from_ram(&[1, 2, 3]);
22//! assert_eq!(result, Err(Error::DMABufferNotInDataMemory));
23//!
24//! // The data is still static and located in flash. However, since we are assigning
25//! // it to a variable, the compiler will load it into memory. Passing a reference to the
26//! // variable will yield a pointer that references dynamic memory, thus making EasyDMA happy.
27//! // This function call succeeds.
28//! let data = [1, 2, 3];
29//! let result = spim.write_from_ram(&data);
30//! assert!(result.is_ok());
31//! ```
32//!
33//! Each peripheral struct which uses EasyDMA ([`Spim`](spim::Spim), [`Uarte`](uarte::Uarte), [`Twim`](twim::Twim)) has two variants of their mutating functions:
34//! - Functions with the suffix (e.g. [`write_from_ram`](spim::Spim::write_from_ram), [`transfer_from_ram`](spim::Spim::transfer_from_ram)) will return an error if the passed slice does not reside in RAM.
35//! - Functions without the suffix (e.g. [`write`](spim::Spim::write), [`transfer`](spim::Spim::transfer)) will check whether the data is in RAM and copy it into memory prior to transmission.
36//!
37//! Since copying incurs a overhead, you are given the option to choose from `_from_ram` variants which will
38//! fail and notify you, or the more convenient versions without the suffix which are potentially a little bit
39//! more inefficient. Be aware that this overhead is not only in terms of instruction count but also in terms of memory usage
40//! as the methods without the suffix will be allocating a statically sized buffer (up to 512 bytes for the nRF52840).
41//!
42//! Note that the methods that read data like [`read`](spim::Spim::read) and [`transfer_in_place`](spim::Spim::transfer_in_place) do not have the corresponding `_from_ram` variants as
43//! mutable slices always reside in RAM.
44
45#![no_std] 1#![no_std]
46#![cfg_attr(feature = "nightly", feature(generic_associated_types, type_alias_impl_trait))] 2#![cfg_attr(feature = "nightly", feature(async_fn_in_trait, impl_trait_projections))]
3#![doc = include_str!("../README.md")]
4#![warn(missing_docs)]
47 5
48#[cfg(not(any( 6#[cfg(not(any(
49 feature = "nrf51", 7 feature = "nrf51",
@@ -62,6 +20,12 @@
62)))] 20)))]
63compile_error!("No chip feature activated. You must activate exactly one of the following features: nrf52810, nrf52811, nrf52832, nrf52833, nrf52840"); 21compile_error!("No chip feature activated. You must activate exactly one of the following features: nrf52810, nrf52811, nrf52832, nrf52833, nrf52840");
64 22
23#[cfg(all(feature = "reset-pin-as-gpio", not(feature = "_nrf52")))]
24compile_error!("feature `reset-pin-as-gpio` is only valid for nRF52 series chips.");
25
26#[cfg(all(feature = "nfc-pins-as-gpio", not(any(feature = "_nrf52", feature = "_nrf5340-app"))))]
27compile_error!("feature `nfc-pins-as-gpio` is only valid for nRF52, or nRF53's application core.");
28
65// This mod MUST go first, so that the others see its macros. 29// This mod MUST go first, so that the others see its macros.
66pub(crate) mod fmt; 30pub(crate) mod fmt;
67pub(crate) mod util; 31pub(crate) mod util;
@@ -69,29 +33,41 @@ pub(crate) mod util;
69#[cfg(feature = "_time-driver")] 33#[cfg(feature = "_time-driver")]
70mod time_driver; 34mod time_driver;
71 35
72#[cfg(feature = "nightly")]
73pub mod buffered_uarte; 36pub mod buffered_uarte;
74pub mod gpio; 37pub mod gpio;
75#[cfg(feature = "gpiote")] 38#[cfg(feature = "gpiote")]
76pub mod gpiote; 39pub mod gpiote;
77#[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] 40#[cfg(any(feature = "nrf52832", feature = "nrf52833", feature = "nrf52840"))]
41pub mod i2s;
78pub mod nvmc; 42pub mod nvmc;
43#[cfg(any(
44 feature = "nrf52810",
45 feature = "nrf52811",
46 feature = "nrf52832",
47 feature = "nrf52833",
48 feature = "nrf52840",
49 feature = "_nrf5340-app",
50 feature = "_nrf9160"
51))]
52pub mod pdm;
79pub mod ppi; 53pub mod ppi;
80#[cfg(not(any(feature = "nrf52805", feature = "nrf52820", feature = "_nrf5340-net")))] 54#[cfg(not(any(feature = "nrf52805", feature = "nrf52820", feature = "_nrf5340-net")))]
81pub mod pwm; 55pub mod pwm;
82#[cfg(not(any(feature = "nrf51", feature = "_nrf9160", feature = "_nrf5340")))] 56#[cfg(not(any(feature = "nrf51", feature = "_nrf9160", feature = "_nrf5340-net")))]
83pub mod qdec; 57pub mod qdec;
84#[cfg(feature = "nrf52840")] 58#[cfg(any(feature = "nrf52840", feature = "_nrf5340-app"))]
85pub mod qspi; 59pub mod qspi;
86#[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] 60#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf9160")))]
87pub mod rng; 61pub mod rng;
88#[cfg(not(any(feature = "nrf52820", feature = "_nrf5340-net")))] 62#[cfg(not(any(feature = "nrf52820", feature = "_nrf5340-net")))]
89pub mod saadc; 63pub mod saadc;
90pub mod spim; 64pub mod spim;
65pub mod spis;
91#[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] 66#[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))]
92pub mod temp; 67pub mod temp;
93pub mod timer; 68pub mod timer;
94pub mod twim; 69pub mod twim;
70pub mod twis;
95pub mod uarte; 71pub mod uarte;
96#[cfg(any( 72#[cfg(any(
97 feature = "_nrf5340-app", 73 feature = "_nrf5340-app",
@@ -103,14 +79,6 @@ pub mod uarte;
103pub mod usb; 79pub mod usb;
104#[cfg(not(feature = "_nrf5340"))] 80#[cfg(not(feature = "_nrf5340"))]
105pub mod wdt; 81pub mod wdt;
106#[cfg(any(
107 feature = "nrf52810",
108 feature = "nrf52811",
109 feature = "nrf52832",
110 feature = "nrf52833",
111 feature = "nrf52840",
112))]
113pub mod pdm;
114 82
115// This mod MUST go last, so that it sees all the `impl_foo!` macros 83// This mod MUST go last, so that it sees all the `impl_foo!` macros
116#[cfg_attr(feature = "nrf52805", path = "chips/nrf52805.rs")] 84#[cfg_attr(feature = "nrf52805", path = "chips/nrf52805.rs")]
@@ -125,15 +93,32 @@ pub mod pdm;
125#[cfg_attr(feature = "_nrf9160", path = "chips/nrf9160.rs")] 93#[cfg_attr(feature = "_nrf9160", path = "chips/nrf9160.rs")]
126mod chip; 94mod chip;
127 95
128pub use chip::EASY_DMA_SIZE; 96/// Macro to bind interrupts to handlers.
97///
98/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`)
99/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to
100/// prove at compile-time that the right interrupts have been bound.
101// developer note: this macro can't be in `embassy-hal-common` due to the use of `$crate`.
102#[macro_export]
103macro_rules! bind_interrupts {
104 ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => {
105 $vis struct $name;
129 106
130pub mod interrupt { 107 $(
131 //! nRF interrupts for cortex-m devices. 108 #[allow(non_snake_case)]
132 pub use cortex_m::interrupt::{CriticalSection, Mutex}; 109 #[no_mangle]
133 pub use embassy_cortex_m::interrupt::*; 110 unsafe extern "C" fn $irq() {
111 $(
112 <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt();
113 )*
114 }
134 115
135 pub use crate::chip::irqs::*; 116 $(
136} 117 unsafe impl $crate::interrupt::typelevel::Binding<$crate::interrupt::typelevel::$irq, $handler> for $name {}
118 )*
119 )*
120 };
121 }
137 122
138// Reexports 123// Reexports
139 124
@@ -141,11 +126,12 @@ pub mod interrupt {
141pub use chip::pac; 126pub use chip::pac;
142#[cfg(not(feature = "unstable-pac"))] 127#[cfg(not(feature = "unstable-pac"))]
143pub(crate) use chip::pac; 128pub(crate) use chip::pac;
144pub use chip::{peripherals, Peripherals}; 129pub use chip::{peripherals, Peripherals, EASY_DMA_SIZE};
145pub use embassy_cortex_m::executor;
146pub use embassy_cortex_m::interrupt::_export::interrupt;
147pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; 130pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
148 131
132pub use crate::chip::interrupt;
133pub use crate::pac::NVIC_PRIO_BITS;
134
149pub mod config { 135pub mod config {
150 //! Configuration options used when initializing the HAL. 136 //! Configuration options used when initializing the HAL.
151 137
@@ -174,6 +160,47 @@ pub mod config {
174 ExternalFullSwing, 160 ExternalFullSwing,
175 } 161 }
176 162
163 /// SWD access port protection setting.
164 #[non_exhaustive]
165 pub enum Debug {
166 /// Debugging is allowed (APPROTECT is disabled). Default.
167 Allowed,
168 /// Debugging is not allowed (APPROTECT is enabled).
169 Disallowed,
170 /// APPROTECT is not configured (neither to enable it or disable it).
171 /// This can be useful if you're already doing it by other means and
172 /// you don't want embassy-nrf to touch UICR.
173 NotConfigured,
174 }
175
176 /// Settings for enabling the built in DCDC converters.
177 #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))]
178 pub struct DcdcConfig {
179 /// Config for the first stage DCDC (VDDH -> VDD), if disabled LDO will be used.
180 #[cfg(feature = "nrf52840")]
181 pub reg0: bool,
182 /// Config for the second stage DCDC (VDD -> DEC4), if disabled LDO will be used.
183 pub reg1: bool,
184 }
185
186 /// Settings for enabling the built in DCDC converters.
187 #[cfg(feature = "_nrf5340-app")]
188 pub struct DcdcConfig {
189 /// Config for the high voltage stage, if disabled LDO will be used.
190 pub regh: bool,
191 /// Config for the main rail, if disabled LDO will be used.
192 pub regmain: bool,
193 /// Config for the radio rail, if disabled LDO will be used.
194 pub regradio: bool,
195 }
196
197 /// Settings for enabling the built in DCDC converter.
198 #[cfg(feature = "_nrf9160")]
199 pub struct DcdcConfig {
200 /// Config for the main rail, if disabled LDO will be used.
201 pub regmain: bool,
202 }
203
177 /// Configuration for peripherals. Default configuration should work on any nRF chip. 204 /// Configuration for peripherals. Default configuration should work on any nRF chip.
178 #[non_exhaustive] 205 #[non_exhaustive]
179 pub struct Config { 206 pub struct Config {
@@ -181,12 +208,17 @@ pub mod config {
181 pub hfclk_source: HfclkSource, 208 pub hfclk_source: HfclkSource,
182 /// Low frequency clock source. 209 /// Low frequency clock source.
183 pub lfclk_source: LfclkSource, 210 pub lfclk_source: LfclkSource,
211 #[cfg(not(feature = "_nrf5340-net"))]
212 /// DCDC configuration.
213 pub dcdc: DcdcConfig,
184 /// GPIOTE interrupt priority. Should be lower priority than softdevice if used. 214 /// GPIOTE interrupt priority. Should be lower priority than softdevice if used.
185 #[cfg(feature = "gpiote")] 215 #[cfg(feature = "gpiote")]
186 pub gpiote_interrupt_priority: crate::interrupt::Priority, 216 pub gpiote_interrupt_priority: crate::interrupt::Priority,
187 /// Time driver interrupt priority. Should be lower priority than softdevice if used. 217 /// Time driver interrupt priority. Should be lower priority than softdevice if used.
188 #[cfg(feature = "_time-driver")] 218 #[cfg(feature = "_time-driver")]
189 pub time_interrupt_priority: crate::interrupt::Priority, 219 pub time_interrupt_priority: crate::interrupt::Priority,
220 /// Enable or disable the debug port.
221 pub debug: Debug,
190 } 222 }
191 223
192 impl Default for Config { 224 impl Default for Config {
@@ -197,21 +229,218 @@ pub mod config {
197 // xtals if they know they have them. 229 // xtals if they know they have them.
198 hfclk_source: HfclkSource::Internal, 230 hfclk_source: HfclkSource::Internal,
199 lfclk_source: LfclkSource::InternalRC, 231 lfclk_source: LfclkSource::InternalRC,
232 #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))]
233 dcdc: DcdcConfig {
234 #[cfg(feature = "nrf52840")]
235 reg0: false,
236 reg1: false,
237 },
238 #[cfg(feature = "_nrf5340-app")]
239 dcdc: DcdcConfig {
240 regh: false,
241 regmain: false,
242 regradio: false,
243 },
244 #[cfg(feature = "_nrf9160")]
245 dcdc: DcdcConfig { regmain: false },
200 #[cfg(feature = "gpiote")] 246 #[cfg(feature = "gpiote")]
201 gpiote_interrupt_priority: crate::interrupt::Priority::P0, 247 gpiote_interrupt_priority: crate::interrupt::Priority::P0,
202 #[cfg(feature = "_time-driver")] 248 #[cfg(feature = "_time-driver")]
203 time_interrupt_priority: crate::interrupt::Priority::P0, 249 time_interrupt_priority: crate::interrupt::Priority::P0,
250
251 // In NS mode, default to NotConfigured, assuming the S firmware will do it.
252 #[cfg(feature = "_ns")]
253 debug: Debug::NotConfigured,
254 #[cfg(not(feature = "_ns"))]
255 debug: Debug::Allowed,
204 } 256 }
205 } 257 }
206 } 258 }
207} 259}
208 260
261#[cfg(feature = "_nrf9160")]
262#[allow(unused)]
263mod consts {
264 pub const UICR_APPROTECT: *mut u32 = 0x00FF8000 as *mut u32;
265 pub const UICR_SECUREAPPROTECT: *mut u32 = 0x00FF802C as *mut u32;
266 pub const APPROTECT_ENABLED: u32 = 0x0000_0000;
267}
268
269#[cfg(feature = "_nrf5340-app")]
270#[allow(unused)]
271mod consts {
272 pub const UICR_APPROTECT: *mut u32 = 0x00FF8000 as *mut u32;
273 pub const UICR_SECUREAPPROTECT: *mut u32 = 0x00FF801C as *mut u32;
274 pub const UICR_NFCPINS: *mut u32 = 0x00FF8028 as *mut u32;
275 pub const APPROTECT_ENABLED: u32 = 0x0000_0000;
276 pub const APPROTECT_DISABLED: u32 = 0x50FA50FA;
277}
278
279#[cfg(feature = "_nrf5340-net")]
280#[allow(unused)]
281mod consts {
282 pub const UICR_APPROTECT: *mut u32 = 0x01FF8000 as *mut u32;
283 pub const APPROTECT_ENABLED: u32 = 0x0000_0000;
284 pub const APPROTECT_DISABLED: u32 = 0x50FA50FA;
285}
286
287#[cfg(feature = "_nrf52")]
288#[allow(unused)]
289mod consts {
290 pub const UICR_PSELRESET1: *mut u32 = 0x10001200 as *mut u32;
291 pub const UICR_PSELRESET2: *mut u32 = 0x10001204 as *mut u32;
292 pub const UICR_NFCPINS: *mut u32 = 0x1000120C as *mut u32;
293 pub const UICR_APPROTECT: *mut u32 = 0x10001208 as *mut u32;
294 pub const APPROTECT_ENABLED: u32 = 0x0000_0000;
295 pub const APPROTECT_DISABLED: u32 = 0x0000_005a;
296}
297
298#[derive(Debug, Copy, Clone, Eq, PartialEq)]
299#[cfg_attr(feature = "defmt", derive(defmt::Format))]
300enum WriteResult {
301 /// Word was written successfully, needs reset.
302 Written,
303 /// Word was already set to the value we wanted to write, nothing was done.
304 Noop,
305 /// Word is already set to something else, we couldn't write the desired value.
306 Failed,
307}
308
309unsafe fn uicr_write(address: *mut u32, value: u32) -> WriteResult {
310 uicr_write_masked(address, value, 0xFFFF_FFFF)
311}
312
313unsafe fn uicr_write_masked(address: *mut u32, value: u32, mask: u32) -> WriteResult {
314 let curr_val = address.read_volatile();
315 if curr_val & mask == value & mask {
316 return WriteResult::Noop;
317 }
318
319 // We can only change `1` bits to `0` bits.
320 if curr_val & value & mask != value & mask {
321 return WriteResult::Failed;
322 }
323
324 let nvmc = &*pac::NVMC::ptr();
325 nvmc.config.write(|w| w.wen().wen());
326 while nvmc.ready.read().ready().is_busy() {}
327 address.write_volatile(value | !mask);
328 while nvmc.ready.read().ready().is_busy() {}
329 nvmc.config.reset();
330 while nvmc.ready.read().ready().is_busy() {}
331
332 WriteResult::Written
333}
334
209/// Initialize peripherals with the provided configuration. This should only be called once at startup. 335/// Initialize peripherals with the provided configuration. This should only be called once at startup.
210pub fn init(config: config::Config) -> Peripherals { 336pub fn init(config: config::Config) -> Peripherals {
211 // Do this first, so that it panics if user is calling `init` a second time 337 // Do this first, so that it panics if user is calling `init` a second time
212 // before doing anything important. 338 // before doing anything important.
213 let peripherals = Peripherals::take(); 339 let peripherals = Peripherals::take();
214 340
341 let mut needs_reset = false;
342
343 // Setup debug protection.
344 match config.debug {
345 config::Debug::Allowed => {
346 #[cfg(feature = "_nrf52")]
347 unsafe {
348 let variant = (0x1000_0104 as *mut u32).read_volatile();
349 // Get the letter for the build code (b'A' .. b'F')
350 let build_code = (variant >> 8) as u8;
351
352 if build_code >= b'F' {
353 // Chips with build code F and higher (revision 3 and higher) have an
354 // improved APPROTECT ("hardware and software controlled access port protection")
355 // which needs explicit action by the firmware to keep it unlocked
356
357 // UICR.APPROTECT = SwDisabled
358 let res = uicr_write(consts::UICR_APPROTECT, consts::APPROTECT_DISABLED);
359 needs_reset |= res == WriteResult::Written;
360 // APPROTECT.DISABLE = SwDisabled
361 (0x4000_0558 as *mut u32).write_volatile(consts::APPROTECT_DISABLED);
362 } else {
363 // nothing to do on older chips, debug is allowed by default.
364 }
365 }
366
367 #[cfg(feature = "_nrf5340")]
368 unsafe {
369 let p = &*pac::CTRLAP::ptr();
370
371 let res = uicr_write(consts::UICR_APPROTECT, consts::APPROTECT_DISABLED);
372 needs_reset |= res == WriteResult::Written;
373 p.approtect.disable.write(|w| w.bits(consts::APPROTECT_DISABLED));
374
375 #[cfg(feature = "_nrf5340-app")]
376 {
377 let res = uicr_write(consts::UICR_SECUREAPPROTECT, consts::APPROTECT_DISABLED);
378 needs_reset |= res == WriteResult::Written;
379 p.secureapprotect.disable.write(|w| w.bits(consts::APPROTECT_DISABLED));
380 }
381 }
382
383 // nothing to do on the nrf9160, debug is allowed by default.
384 }
385 config::Debug::Disallowed => unsafe {
386 // UICR.APPROTECT = Enabled
387 let res = uicr_write(consts::UICR_APPROTECT, consts::APPROTECT_ENABLED);
388 needs_reset |= res == WriteResult::Written;
389 #[cfg(any(feature = "_nrf5340-app", feature = "_nrf9160"))]
390 {
391 let res = uicr_write(consts::UICR_SECUREAPPROTECT, consts::APPROTECT_ENABLED);
392 needs_reset |= res == WriteResult::Written;
393 }
394 },
395 config::Debug::NotConfigured => {}
396 }
397
398 #[cfg(feature = "_nrf52")]
399 unsafe {
400 let value = if cfg!(feature = "reset-pin-as-gpio") {
401 !0
402 } else {
403 chip::RESET_PIN
404 };
405 let res1 = uicr_write(consts::UICR_PSELRESET1, value);
406 let res2 = uicr_write(consts::UICR_PSELRESET2, value);
407 needs_reset |= res1 == WriteResult::Written || res2 == WriteResult::Written;
408 if res1 == WriteResult::Failed || res2 == WriteResult::Failed {
409 #[cfg(not(feature = "reset-pin-as-gpio"))]
410 warn!(
411 "You have requested enabling chip reset functionality on the reset pin, by not enabling the Cargo feature `reset-pin-as-gpio`.\n\
412 However, UICR is already programmed to some other setting, and can't be changed without erasing it.\n\
413 To fix this, erase UICR manually, for example using `probe-rs erase` or `nrfjprog --eraseuicr`."
414 );
415 #[cfg(feature = "reset-pin-as-gpio")]
416 warn!(
417 "You have requested using the reset pin as GPIO, by enabling the Cargo feature `reset-pin-as-gpio`.\n\
418 However, UICR is already programmed to some other setting, and can't be changed without erasing it.\n\
419 To fix this, erase UICR manually, for example using `probe-rs erase` or `nrfjprog --eraseuicr`."
420 );
421 }
422 }
423
424 #[cfg(any(feature = "_nrf52", feature = "_nrf5340-app"))]
425 unsafe {
426 let value = if cfg!(feature = "nfc-pins-as-gpio") { 0 } else { 1 };
427 let res = uicr_write_masked(consts::UICR_NFCPINS, value, 1);
428 needs_reset |= res == WriteResult::Written;
429 if res == WriteResult::Failed {
430 // with nfc-pins-as-gpio, this can never fail because we're writing all zero bits.
431 #[cfg(not(feature = "nfc-pins-as-gpio"))]
432 warn!(
433 "You have requested to use P0.09 and P0.10 pins for NFC, by not enabling the Cargo feature `nfc-pins-as-gpio`.\n\
434 However, UICR is already programmed to some other setting, and can't be changed without erasing it.\n\
435 To fix this, erase UICR manually, for example using `probe-rs erase` or `nrfjprog --eraseuicr`."
436 );
437 }
438 }
439
440 if needs_reset {
441 cortex_m::peripheral::SCB::sys_reset();
442 }
443
215 let r = unsafe { &*pac::CLOCK::ptr() }; 444 let r = unsafe { &*pac::CLOCK::ptr() };
216 445
217 // Start HFCLK. 446 // Start HFCLK.
@@ -259,6 +488,41 @@ pub fn init(config: config::Config) -> Peripherals {
259 r.tasks_lfclkstart.write(|w| unsafe { w.bits(1) }); 488 r.tasks_lfclkstart.write(|w| unsafe { w.bits(1) });
260 while r.events_lfclkstarted.read().bits() == 0 {} 489 while r.events_lfclkstarted.read().bits() == 0 {}
261 490
491 #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))]
492 {
493 // Setup DCDCs.
494 let pwr = unsafe { &*pac::POWER::ptr() };
495 #[cfg(feature = "nrf52840")]
496 if config.dcdc.reg0 {
497 pwr.dcdcen0.write(|w| w.dcdcen().set_bit());
498 }
499 if config.dcdc.reg1 {
500 pwr.dcdcen.write(|w| w.dcdcen().set_bit());
501 }
502 }
503 #[cfg(feature = "_nrf9160")]
504 {
505 // Setup DCDC.
506 let reg = unsafe { &*pac::REGULATORS::ptr() };
507 if config.dcdc.regmain {
508 reg.dcdcen.write(|w| w.dcdcen().set_bit());
509 }
510 }
511 #[cfg(feature = "_nrf5340-app")]
512 {
513 // Setup DCDC.
514 let reg = unsafe { &*pac::REGULATORS::ptr() };
515 if config.dcdc.regh {
516 reg.vregh.dcdcen.write(|w| w.dcdcen().set_bit());
517 }
518 if config.dcdc.regmain {
519 reg.vregmain.dcdcen.write(|w| w.dcdcen().set_bit());
520 }
521 if config.dcdc.regradio {
522 reg.vregradio.dcdcen.write(|w| w.dcdcen().set_bit());
523 }
524 }
525
262 // Init GPIOTE 526 // Init GPIOTE
263 #[cfg(feature = "gpiote")] 527 #[cfg(feature = "gpiote")]
264 gpiote::init(config.gpiote_interrupt_priority); 528 gpiote::init(config.gpiote_interrupt_priority);
@@ -267,5 +531,12 @@ pub fn init(config: config::Config) -> Peripherals {
267 #[cfg(feature = "_time-driver")] 531 #[cfg(feature = "_time-driver")]
268 time_driver::init(config.time_interrupt_priority); 532 time_driver::init(config.time_interrupt_priority);
269 533
534 // Disable UARTE (enabled by default for some reason)
535 #[cfg(feature = "_nrf9160")]
536 unsafe {
537 (*pac::UARTE0::ptr()).enable.write(|w| w.enable().disabled());
538 (*pac::UARTE1::ptr()).enable.write(|w| w.enable().disabled());
539 }
540
270 peripherals 541 peripherals
271} 542}
diff --git a/embassy-nrf/src/nvmc.rs b/embassy-nrf/src/nvmc.rs
index 6f66f7a78..91a5a272f 100644
--- a/embassy-nrf/src/nvmc.rs
+++ b/embassy-nrf/src/nvmc.rs
@@ -1,4 +1,4 @@
1//! Non-Volatile Memory Controller (NVMC) module. 1//! Non-Volatile Memory Controller (NVMC, AKA internal flash) driver.
2 2
3use core::{ptr, slice}; 3use core::{ptr, slice};
4 4
@@ -10,8 +10,12 @@ use embedded_storage::nor_flash::{
10use crate::peripherals::NVMC; 10use crate::peripherals::NVMC;
11use crate::{pac, Peripheral}; 11use crate::{pac, Peripheral};
12 12
13#[cfg(not(feature = "_nrf5340-net"))]
13/// Erase size of NVMC flash in bytes. 14/// Erase size of NVMC flash in bytes.
14pub const PAGE_SIZE: usize = 4096; 15pub const PAGE_SIZE: usize = 4096;
16#[cfg(feature = "_nrf5340-net")]
17/// Erase size of NVMC flash in bytes.
18pub const PAGE_SIZE: usize = 2048;
15 19
16/// Size of NVMC flash in bytes. 20/// Size of NVMC flash in bytes.
17pub const FLASH_SIZE: usize = crate::chip::FLASH_SIZE; 21pub const FLASH_SIZE: usize = crate::chip::FLASH_SIZE;
@@ -20,7 +24,7 @@ pub const FLASH_SIZE: usize = crate::chip::FLASH_SIZE;
20#[derive(Debug, Copy, Clone, PartialEq, Eq)] 24#[derive(Debug, Copy, Clone, PartialEq, Eq)]
21#[cfg_attr(feature = "defmt", derive(defmt::Format))] 25#[cfg_attr(feature = "defmt", derive(defmt::Format))]
22pub enum Error { 26pub enum Error {
23 /// Opration using a location not in flash. 27 /// Operation using a location not in flash.
24 OutOfBounds, 28 OutOfBounds,
25 /// Unaligned operation or using unaligned buffers. 29 /// Unaligned operation or using unaligned buffers.
26 Unaligned, 30 Unaligned,
@@ -55,6 +59,51 @@ impl<'d> Nvmc<'d> {
55 let p = Self::regs(); 59 let p = Self::regs();
56 while p.ready.read().ready().is_busy() {} 60 while p.ready.read().ready().is_busy() {}
57 } 61 }
62
63 #[cfg(not(any(feature = "_nrf9160", feature = "_nrf5340")))]
64 fn wait_ready_write(&mut self) {
65 self.wait_ready();
66 }
67
68 #[cfg(any(feature = "_nrf9160", feature = "_nrf5340"))]
69 fn wait_ready_write(&mut self) {
70 let p = Self::regs();
71 while p.readynext.read().readynext().is_busy() {}
72 }
73
74 #[cfg(not(any(feature = "_nrf9160", feature = "_nrf5340")))]
75 fn erase_page(&mut self, page_addr: u32) {
76 Self::regs().erasepage().write(|w| unsafe { w.bits(page_addr) });
77 }
78
79 #[cfg(any(feature = "_nrf9160", feature = "_nrf5340"))]
80 fn erase_page(&mut self, page_addr: u32) {
81 let first_page_word = page_addr as *mut u32;
82 unsafe {
83 first_page_word.write_volatile(0xFFFF_FFFF);
84 }
85 }
86
87 fn enable_erase(&self) {
88 #[cfg(not(feature = "_ns"))]
89 Self::regs().config.write(|w| w.wen().een());
90 #[cfg(feature = "_ns")]
91 Self::regs().configns.write(|w| w.wen().een());
92 }
93
94 fn enable_read(&self) {
95 #[cfg(not(feature = "_ns"))]
96 Self::regs().config.write(|w| w.wen().ren());
97 #[cfg(feature = "_ns")]
98 Self::regs().configns.write(|w| w.wen().ren());
99 }
100
101 fn enable_write(&self) {
102 #[cfg(not(feature = "_ns"))]
103 Self::regs().config.write(|w| w.wen().wen());
104 #[cfg(feature = "_ns")]
105 Self::regs().configns.write(|w| w.wen().wen());
106 }
58} 107}
59 108
60impl<'d> MultiwriteNorFlash for Nvmc<'d> {} 109impl<'d> MultiwriteNorFlash for Nvmc<'d> {}
@@ -93,17 +142,15 @@ impl<'d> NorFlash for Nvmc<'d> {
93 return Err(Error::Unaligned); 142 return Err(Error::Unaligned);
94 } 143 }
95 144
96 let p = Self::regs(); 145 self.enable_erase();
97
98 p.config.write(|w| w.wen().een());
99 self.wait_ready(); 146 self.wait_ready();
100 147
101 for page in (from..to).step_by(PAGE_SIZE) { 148 for page_addr in (from..to).step_by(PAGE_SIZE) {
102 p.erasepage().write(|w| unsafe { w.bits(page) }); 149 self.erase_page(page_addr);
103 self.wait_ready(); 150 self.wait_ready();
104 } 151 }
105 152
106 p.config.reset(); 153 self.enable_read();
107 self.wait_ready(); 154 self.wait_ready();
108 155
109 Ok(()) 156 Ok(())
@@ -117,9 +164,7 @@ impl<'d> NorFlash for Nvmc<'d> {
117 return Err(Error::Unaligned); 164 return Err(Error::Unaligned);
118 } 165 }
119 166
120 let p = Self::regs(); 167 self.enable_write();
121
122 p.config.write(|w| w.wen().wen());
123 self.wait_ready(); 168 self.wait_ready();
124 169
125 unsafe { 170 unsafe {
@@ -129,11 +174,11 @@ impl<'d> NorFlash for Nvmc<'d> {
129 for i in 0..words { 174 for i in 0..words {
130 let w = ptr::read_unaligned(p_src.add(i)); 175 let w = ptr::read_unaligned(p_src.add(i));
131 ptr::write_volatile(p_dst.add(i), w); 176 ptr::write_volatile(p_dst.add(i), w);
132 self.wait_ready(); 177 self.wait_ready_write();
133 } 178 }
134 } 179 }
135 180
136 p.config.reset(); 181 self.enable_read();
137 self.wait_ready(); 182 self.wait_ready();
138 183
139 Ok(()) 184 Ok(())
diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs
index c2c54fba9..1fc717fd1 100644
--- a/embassy-nrf/src/pdm.rs
+++ b/embassy-nrf/src/pdm.rs
@@ -1,66 +1,71 @@
1//! Pulse Density Modulation (PDM) mirophone driver.
2
1#![macro_use] 3#![macro_use]
2 4
5use core::marker::PhantomData;
3use core::sync::atomic::{compiler_fence, Ordering}; 6use core::sync::atomic::{compiler_fence, Ordering};
4use core::task::Poll; 7use core::task::Poll;
5 8
6use embassy_hal_common::{into_ref, PeripheralRef};
7use embassy_hal_common::drop::OnDrop; 9use embassy_hal_common::drop::OnDrop;
8use embassy_sync::waitqueue::AtomicWaker; 10use embassy_hal_common::{into_ref, PeripheralRef};
9use futures::future::poll_fn; 11use futures::future::poll_fn;
10use pac::{pdm, PDM};
11use pdm::mode::{EDGE_A, OPERATION_A};
12pub use pdm::pdmclkctrl::FREQ_A as Frequency;
13pub use pdm::ratio::RATIO_A as Ratio;
14use fixed::types::I7F1; 12use fixed::types::I7F1;
15 13
16use crate::interrupt::InterruptExt; 14use crate::chip::EASY_DMA_SIZE;
17use crate::gpio::Pin as GpioPin; 15use crate::gpio::sealed::Pin;
18use crate::{interrupt, pac, peripherals, Peripheral}; 16use crate::gpio::{AnyPin, Pin as GpioPin};
17use crate::interrupt::typelevel::Interrupt;
18use crate::{interrupt, Peripheral};
19use crate::pac::pdm::mode::{EDGE_A, OPERATION_A};
20pub use crate::pac::pdm::pdmclkctrl::FREQ_A as Frequency;
21pub use crate::pac::pdm::ratio::RATIO_A as Ratio;
22
23/// Interrupt handler.
24pub struct InterruptHandler<T: Instance> {
25 _phantom: PhantomData<T>,
26}
19 27
20#[derive(Debug, Clone, Copy, PartialEq, Eq)] 28impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
21#[cfg_attr(feature = "defmt", derive(defmt::Format))] 29 unsafe fn on_interrupt() {
22#[non_exhaustive] 30 let r = T::regs();
23pub enum Error {} 31
32 if r.events_end.read().bits() != 0 {
33 r.intenclr.write(|w| w.end().clear());
34 }
24 35
25/// One-shot and continuous PDM. 36 if r.events_started.read().bits() != 0 {
26pub struct Pdm<'d> { 37 r.intenclr.write(|w| w.started().clear());
27 _p: PeripheralRef<'d, peripherals::PDM>, 38 }
39
40 if r.events_stopped.read().bits() != 0 {
41 r.intenclr.write(|w| w.stopped().clear());
42 }
43
44 T::state().waker.wake();
45 }
28} 46}
29 47
30static WAKER: AtomicWaker = AtomicWaker::new(); 48/// PDM microphone interface
49pub struct Pdm<'d, T: Instance> {
50 _peri: PeripheralRef<'d, T>,
51}
31 52
32/// Used to configure the PDM peripheral. 53/// PDM error.
33/// 54#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34/// See the `Default` impl for suitable default values. 55#[cfg_attr(feature = "defmt", derive(defmt::Format))]
35#[non_exhaustive] 56#[non_exhaustive]
36pub struct Config { 57pub enum Error {
37 /// Clock frequency 58 /// Buffer is too long.
38 pub frequency: Frequency, 59 BufferTooLong,
39 /// Clock ratio 60 /// Buffer is empty
40 pub ratio: Ratio, 61 BufferZeroLength,
41 /// Channels 62 /// PDM is not running
42 pub channels: Channels, 63 NotRunning,
43 /// Edge to sample on 64 /// PDM is already running
44 pub left_edge: Edge, 65 AlreadyRunning,
45 /// Gain left in dB
46 pub gain_left: I7F1,
47 /// Gain right in dB
48 pub gain_right: I7F1,
49} 66}
50 67
51impl Default for Config { 68static DUMMY_BUFFER: [i16; 1] = [0; 1];
52 /// Default configuration for single channel sampling.
53 fn default() -> Self {
54 Self {
55 frequency: Frequency::DEFAULT,
56 ratio: Ratio::RATIO80,
57 channels: Channels::Stereo,
58 left_edge: Edge::FallingEdge,
59 gain_left: I7F1::ZERO,
60 gain_right: I7F1::ZERO,
61 }
62 }
63}
64 69
65/// The state of a continuously running sampler. While it reflects 70/// The state of a continuously running sampler. While it reflects
66/// the progress of a sampler, it also signals what should be done 71/// the progress of a sampler, it also signals what should be done
@@ -68,69 +73,66 @@ impl Default for Config {
68/// can then tear down its infrastructure. 73/// can then tear down its infrastructure.
69#[derive(PartialEq)] 74#[derive(PartialEq)]
70pub enum SamplerState { 75pub enum SamplerState {
76 /// The sampler processed the samples and is ready for more.
71 Sampled, 77 Sampled,
78 /// The sampler is done processing samples.
72 Stopped, 79 Stopped,
73} 80}
74 81
75impl<'d> Pdm<'d> { 82impl<'d, T: Instance> Pdm<'d, T> {
83 /// Create PDM driver
76 pub fn new( 84 pub fn new(
77 pdm: impl Peripheral<P = peripherals::PDM> + 'd, 85 pdm: impl Peripheral<P = T> + 'd,
78 irq: impl Peripheral<P = interrupt::PDM> + 'd, 86 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
79 data: impl Peripheral<P = impl GpioPin> + 'd, 87 clk: impl Peripheral<P = impl GpioPin> + 'd,
80 clock: impl Peripheral<P = impl GpioPin> + 'd, 88 din: impl Peripheral<P = impl GpioPin> + 'd,
89 config: Config,
90 ) -> Self {
91 into_ref!(pdm, clk, din);
92 Self::new_inner(pdm, clk.map_into(), din.map_into(), config)
93 }
94
95 fn new_inner(
96 pdm: PeripheralRef<'d, T>,
97 clk: PeripheralRef<'d, AnyPin>,
98 din: PeripheralRef<'d, AnyPin>,
81 config: Config, 99 config: Config,
82 ) -> Self { 100 ) -> Self {
83 into_ref!(pdm, irq, data, clock); 101 into_ref!(pdm);
84 102
85 let r = unsafe { &*PDM::ptr() }; 103 let r = T::regs();
86 104
87 let Config { frequency, ratio, channels, left_edge, gain_left, gain_right } = config; 105 // setup gpio pins
106 din.conf().write(|w| w.input().set_bit());
107 r.psel.din.write(|w| unsafe { w.bits(din.psel_bits()) });
108 clk.set_low();
109 clk.conf().write(|w| w.dir().output());
110 r.psel.clk.write(|w| unsafe { w.bits(clk.psel_bits()) });
88 111
89 // Configure channels 112 // configure
90 r.enable.write(|w| w.enable().enabled()); 113 r.pdmclkctrl.write(|w| w.freq().variant(config.frequency));
91 r.pdmclkctrl.write(|w| w.freq().variant(frequency)); 114 r.ratio.write(|w| w.ratio().variant(config.ratio));
92 r.ratio.write(|w| w.ratio().variant(ratio));
93 r.mode.write(|w| { 115 r.mode.write(|w| {
94 w.operation().variant(channels.into()); 116 w.operation().variant(config.operation_mode.into());
95 w.edge().variant(left_edge.into()); 117 w.edge().variant(config.edge.into());
96 w 118 w
97 }); 119 });
98 120
99 Self::_set_gain(r, gain_left, gain_right); 121 Self::_set_gain(r, config.gain_left, config.gain_right);
100
101 r.psel.din.write(|w| unsafe { w.bits(data.psel_bits()) });
102 r.psel.clk.write(|w| unsafe { w.bits(clock.psel_bits()) });
103 122
104 // Disable all events interrupts 123 // Disable all events interrupts
105 r.intenclr.write(|w| unsafe { w.bits(0x003F_FFFF) }); 124 r.intenclr.write(|w| unsafe { w.bits(0x003F_FFFF) });
106 125
107 irq.set_handler(Self::on_interrupt); 126 // IRQ
108 irq.unpend(); 127 T::Interrupt::unpend();
109 irq.enable(); 128 unsafe { T::Interrupt::enable() };
110
111 Self { _p: pdm }
112 }
113
114 fn on_interrupt(_ctx: *mut ()) {
115 let r = Self::regs();
116
117 if r.events_end.read().bits() != 0 {
118 r.intenclr.write(|w| w.end().clear());
119 WAKER.wake();
120 }
121 129
122 if r.events_started.read().bits() != 0 { 130 r.enable.write(|w| w.enable().set_bit());
123 r.intenclr.write(|w| w.started().clear());
124 WAKER.wake();
125 }
126 131
127 if r.events_stopped.read().bits() != 0 { 132 Self { _peri: pdm }
128 r.intenclr.write(|w| w.stopped().clear());
129 WAKER.wake();
130 }
131 } 133 }
132 134
133 fn _set_gain(r: &pdm::RegisterBlock, gain_left: I7F1, gain_right: I7F1) { 135 fn _set_gain(r: &crate::pac::pdm::RegisterBlock, gain_left: I7F1, gain_right: I7F1) {
134 let gain_left = gain_left.saturating_add(I7F1::from_bits(40)).saturating_to_num::<u8>().clamp(0, 0x50); 136 let gain_left = gain_left.saturating_add(I7F1::from_bits(40)).saturating_to_num::<u8>().clamp(0, 0x50);
135 let gain_right = gain_right.saturating_add(I7F1::from_bits(40)).saturating_to_num::<u8>().clamp(0, 0x50); 137 let gain_right = gain_right.saturating_add(I7F1::from_bits(40)).saturating_to_num::<u8>().clamp(0, 0x50);
136 138
@@ -138,81 +140,111 @@ impl<'d> Pdm<'d> {
138 r.gainr.write(|w| unsafe { w.gainr().bits(gain_right) }); 140 r.gainr.write(|w| unsafe { w.gainr().bits(gain_right) });
139 } 141 }
140 142
143 /// Adjust the gain of the PDM microphone on the fly
141 pub fn set_gain(&mut self, gain_left: I7F1, gain_right: I7F1) { 144 pub fn set_gain(&mut self, gain_left: I7F1, gain_right: I7F1) {
142 Self::_set_gain(Self::regs(), gain_left, gain_right) 145 Self::_set_gain(T::regs(), gain_left, gain_right)
143 } 146 }
144 147
145 fn regs() -> &'static pdm::RegisterBlock { 148 /// Start sampling microphon data into a dummy buffer
146 unsafe { &*PDM::ptr() } 149 /// Usefull to start the microphon and keep it active between recording samples
150 pub async fn start(&mut self) {
151 let r = T::regs();
152
153 // start dummy sampling because microphon needs some setup time
154 r.sample
155 .ptr
156 .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) });
157 r.sample
158 .maxcnt
159 .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) });
160
161 r.tasks_start.write(|w| unsafe { w.bits(1) });
147 } 162 }
148 163
149 /// One shot sampling. If the PDM is configured for multiple channels, the samples will be interleaved. 164 /// Stop sampling microphon data inta a dummy buffer
150 /// The first samples from the PDM peripheral and microphone usually contain garbage data, so the discard parameter sets the number of complete buffers to discard before returning. 165 pub async fn stop(&mut self) {
151 pub async fn sample<const N: usize>(&mut self, mut discard: usize, buf: &mut [i16; N]) { 166 let r = T::regs();
152 let r = Self::regs(); 167 r.tasks_stop.write(|w| unsafe { w.bits(1) });
168 r.events_started.reset();
169 }
153 170
154 // Set up the DMA 171 /// Sample data into the given buffer.
155 r.sample.ptr.write(|w| unsafe { w.sampleptr().bits(buf.as_mut_ptr() as u32) }); 172 pub async fn sample(&mut self, buffer: &mut [i16]) -> Result<(), Error> {
156 r.sample.maxcnt.write(|w| unsafe { w.buffsize().bits(N as _) }); 173 if buffer.len() == 0 {
174 return Err(Error::BufferZeroLength);
175 }
176 if buffer.len() > EASY_DMA_SIZE {
177 return Err(Error::BufferTooLong);
178 }
157 179
158 // Reset and enable the events 180 let r = T::regs();
159 r.events_end.reset();
160 r.events_stopped.reset();
161 r.intenset.write(|w| {
162 w.end().set();
163 w.stopped().set();
164 w
165 });
166 181
167 // Don't reorder the start event before the previous writes. Hopefully self 182 if r.events_started.read().bits() == 0 {
168 // wouldn't happen anyway. 183 return Err(Error::NotRunning);
169 compiler_fence(Ordering::SeqCst); 184 }
170 185
171 r.tasks_start.write(|w| w.tasks_start().set_bit()); 186 let drop = OnDrop::new(move || {
187 r.intenclr.write(|w| w.end().clear());
188 r.events_stopped.reset();
172 189
173 let ondrop = OnDrop::new(|| { 190 // reset to dummy buffer
174 r.tasks_stop.write(|w| w.tasks_stop().set_bit()); 191 r.sample
175 // N.B. It would be better if this were async, but Drop only support sync code. 192 .ptr
176 while r.events_stopped.read().bits() != 0 {} 193 .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) });
194 r.sample
195 .maxcnt
196 .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) });
197
198 while r.events_stopped.read().bits() == 0 {}
177 }); 199 });
178 200
179 // Wait for 'end' event. 201 // setup user buffer
180 poll_fn(|cx| { 202 let ptr = buffer.as_ptr();
181 let r = Self::regs(); 203 let len = buffer.len();
204 r.sample.ptr.write(|w| unsafe { w.sampleptr().bits(ptr as u32) });
205 r.sample.maxcnt.write(|w| unsafe { w.buffsize().bits(len as _) });
182 206
183 WAKER.register(cx.waker()); 207 // wait till the current sample is finished and the user buffer sample is started
208 Self::wait_for_sample().await;
184 209
185 if r.events_end.read().bits() != 0 { 210 // reset the buffer back to the dummy buffer
186 compiler_fence(Ordering::SeqCst); 211 r.sample
187 // END means the whole buffer has been received. 212 .ptr
188 r.events_end.reset(); 213 .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) });
189 r.intenset.write(|w| w.end().set()); 214 r.sample
215 .maxcnt
216 .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) });
190 217
191 if discard > 0 { 218 // wait till the user buffer is sampled
192 discard -= 1; 219 Self::wait_for_sample().await;
193 } else { 220
194 // Note that the beginning of the buffer might be overwritten before the task fully stops :( 221 drop.defuse();
195 r.tasks_stop.write(|w| w.tasks_stop().set_bit()); 222
196 } 223 Ok(())
197 } 224 }
198 if r.events_stopped.read().bits() != 0 { 225
226 async fn wait_for_sample() {
227 let r = T::regs();
228
229 r.events_end.reset();
230 r.intenset.write(|w| w.end().set());
231
232 compiler_fence(Ordering::SeqCst);
233
234 poll_fn(|cx| {
235 T::state().waker.register(cx.waker());
236 if r.events_end.read().bits() != 0 {
199 return Poll::Ready(()); 237 return Poll::Ready(());
200 } 238 }
201
202 Poll::Pending 239 Poll::Pending
203 }) 240 })
204 .await; 241 .await;
205 ondrop.defuse(); 242
243 compiler_fence(Ordering::SeqCst);
206 } 244 }
207 245
208 /// Continuous sampling with double buffers. 246 /// Continuous sampling with double buffers.
209 /// 247 ///
210 /// A TIMER and two PPI peripherals are passed in so that precise sampling
211 /// can be attained. The sampling interval is expressed by selecting a
212 /// timer clock frequency to use along with a counter threshold to be reached.
213 /// For example, 1KHz can be achieved using a frequency of 1MHz and a counter
214 /// threshold of 1000.
215 ///
216 /// A sampler closure is provided that receives the buffer of samples, noting 248 /// A sampler closure is provided that receives the buffer of samples, noting
217 /// that the size of this buffer can be less than the original buffer's size. 249 /// that the size of this buffer can be less than the original buffer's size.
218 /// A command is return from the closure that indicates whether the sampling 250 /// A command is return from the closure that indicates whether the sampling
@@ -226,10 +258,14 @@ impl<'d> Pdm<'d> {
226 &mut self, 258 &mut self,
227 bufs: &mut [[i16; N]; 2], 259 bufs: &mut [[i16; N]; 2],
228 mut sampler: S, 260 mut sampler: S,
229 ) where 261 ) -> Result<(), Error> where
230 S: FnMut(&[i16; N]) -> SamplerState, 262 S: FnMut(&[i16; N]) -> SamplerState,
231 { 263 {
232 let r = Self::regs(); 264 let r = T::regs();
265
266 if r.events_started.read().bits() != 0 {
267 return Err(Error::AlreadyRunning);
268 }
233 269
234 r.sample.ptr.write(|w| unsafe { w.sampleptr().bits(bufs[0].as_mut_ptr() as u32) }); 270 r.sample.ptr.write(|w| unsafe { w.sampleptr().bits(bufs[0].as_mut_ptr() as u32) });
235 r.sample.maxcnt.write(|w| unsafe { w.buffsize().bits(N as _) }); 271 r.sample.maxcnt.write(|w| unsafe { w.buffsize().bits(N as _) });
@@ -255,7 +291,7 @@ impl<'d> Pdm<'d> {
255 291
256 let mut done = false; 292 let mut done = false;
257 293
258 let ondrop = OnDrop::new(|| { 294 let drop = OnDrop::new(|| {
259 r.tasks_stop.write(|w| w.tasks_stop().set_bit()); 295 r.tasks_stop.write(|w| w.tasks_stop().set_bit());
260 // N.B. It would be better if this were async, but Drop only support sync code. 296 // N.B. It would be better if this were async, but Drop only support sync code.
261 while r.events_stopped.read().bits() != 0 {} 297 while r.events_stopped.read().bits() != 0 {}
@@ -263,9 +299,9 @@ impl<'d> Pdm<'d> {
263 299
264 // Wait for events and complete when the sampler indicates it has had enough. 300 // Wait for events and complete when the sampler indicates it has had enough.
265 poll_fn(|cx| { 301 poll_fn(|cx| {
266 let r = Self::regs(); 302 let r = T::regs();
267 303
268 WAKER.register(cx.waker()); 304 T::state().waker.register(cx.waker());
269 305
270 if r.events_end.read().bits() != 0 { 306 if r.events_end.read().bits() != 0 {
271 compiler_fence(Ordering::SeqCst); 307 compiler_fence(Ordering::SeqCst);
@@ -301,43 +337,130 @@ impl<'d> Pdm<'d> {
301 Poll::Pending 337 Poll::Pending
302 }) 338 })
303 .await; 339 .await;
304 ondrop.defuse(); 340 drop.defuse();
341 Ok(())
305 } 342 }
306} 343}
307 344
308impl<'d> Drop for Pdm<'d> { 345/// PDM microphone driver Config
309 fn drop(&mut self) { 346pub struct Config {
310 let r = Self::regs(); 347 /// Use stero or mono operation
311 r.enable.write(|w| w.enable().disabled()); 348 pub operation_mode: OperationMode,
349 /// On which edge the left channel should be samples
350 pub edge: Edge,
351 /// Clock frequency
352 pub frequency: Frequency,
353 /// Clock ratio
354 pub ratio: Ratio,
355 /// Gain left in dB
356 pub gain_left: I7F1,
357 /// Gain right in dB
358 pub gain_right: I7F1,
359}
360
361impl Default for Config {
362 fn default() -> Self {
363 Self {
364 operation_mode: OperationMode::Mono,
365 edge: Edge::LeftFalling,
366 frequency: Frequency::DEFAULT,
367 ratio: Ratio::RATIO80,
368 gain_left: I7F1::ZERO,
369 gain_right: I7F1::ZERO,
370 }
371 }
372}
373
374/// PDM operation mode.
375#[derive(PartialEq)]
376pub enum OperationMode {
377 /// Mono (1 channel)
378 Mono,
379 /// Stereo (2 channels)
380 Stereo,
381}
382
383impl From<OperationMode> for OPERATION_A {
384 fn from(mode: OperationMode) -> Self {
385 match mode {
386 OperationMode::Mono => OPERATION_A::MONO,
387 OperationMode::Stereo => OPERATION_A::STEREO,
388 }
312 } 389 }
313} 390}
314 391
315#[derive(Clone, Copy, PartialEq)] 392/// PDM edge polarity
393#[derive(PartialEq)]
316pub enum Edge { 394pub enum Edge {
317 FallingEdge, 395 /// Left edge is rising
318 RisingEdge, 396 LeftRising,
397 /// Left edge is falling
398 LeftFalling,
319} 399}
320 400
321impl From<Edge> for EDGE_A { 401impl From<Edge> for EDGE_A {
322 fn from(edge: Edge) -> Self { 402 fn from(edge: Edge) -> Self {
323 match edge { 403 match edge {
324 Edge::FallingEdge => EDGE_A::LEFTFALLING, 404 Edge::LeftRising => EDGE_A::LEFT_RISING,
325 Edge::RisingEdge => EDGE_A::LEFTRISING, 405 Edge::LeftFalling => EDGE_A::LEFT_FALLING,
326 } 406 }
327 } 407 }
328} 408}
329 409
330#[derive(Clone, Copy, PartialEq)] 410impl<'d, T: Instance> Drop for Pdm<'d, T> {
331pub enum Channels { 411 fn drop(&mut self) {
332 Stereo, 412 let r = T::regs();
333 Mono, 413
414 r.tasks_stop.write(|w| unsafe { w.bits(1) });
415
416 r.enable.write(|w| w.enable().disabled());
417
418 r.psel.din.reset();
419 r.psel.clk.reset();
420 }
334} 421}
335 422
336impl From<Channels> for OPERATION_A { 423pub(crate) mod sealed {
337 fn from(ch: Channels) -> Self { 424 use embassy_sync::waitqueue::AtomicWaker;
338 match ch { 425
339 Channels::Stereo => OPERATION_A::STEREO, 426 /// Peripheral static state
340 Channels::Mono => OPERATION_A::MONO, 427 pub struct State {
428 pub waker: AtomicWaker,
429 }
430
431 impl State {
432 pub const fn new() -> Self {
433 Self {
434 waker: AtomicWaker::new(),
435 }
341 } 436 }
342 } 437 }
438
439 pub trait Instance {
440 fn regs() -> &'static crate::pac::pdm::RegisterBlock;
441 fn state() -> &'static State;
442 }
443}
444
445/// PDM peripheral instance.
446pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
447 /// Interrupt for this peripheral.
448 type Interrupt: interrupt::typelevel::Interrupt;
449}
450
451macro_rules! impl_pdm {
452 ($type:ident, $pac_type:ident, $irq:ident) => {
453 impl crate::pdm::sealed::Instance for peripherals::$type {
454 fn regs() -> &'static crate::pac::pdm::RegisterBlock {
455 unsafe { &*pac::$pac_type::ptr() }
456 }
457 fn state() -> &'static crate::pdm::sealed::State {
458 static STATE: crate::pdm::sealed::State = crate::pdm::sealed::State::new();
459 &STATE
460 }
461 }
462 impl crate::pdm::Instance for peripherals::$type {
463 type Interrupt = crate::interrupt::typelevel::$irq;
464 }
465 };
343} \ No newline at end of file 466} \ No newline at end of file
diff --git a/embassy-nrf/src/ppi/dppi.rs b/embassy-nrf/src/ppi/dppi.rs
index de856c0ca..40ccb2f09 100644
--- a/embassy-nrf/src/ppi/dppi.rs
+++ b/embassy-nrf/src/ppi/dppi.rs
@@ -6,18 +6,20 @@ use crate::{pac, Peripheral};
6const DPPI_ENABLE_BIT: u32 = 0x8000_0000; 6const DPPI_ENABLE_BIT: u32 = 0x8000_0000;
7const DPPI_CHANNEL_MASK: u32 = 0x0000_00FF; 7const DPPI_CHANNEL_MASK: u32 = 0x0000_00FF;
8 8
9fn regs() -> &'static pac::dppic::RegisterBlock { 9pub(crate) fn regs() -> &'static pac::dppic::RegisterBlock {
10 unsafe { &*pac::DPPIC::ptr() } 10 unsafe { &*pac::DPPIC::ptr() }
11} 11}
12 12
13impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> { 13impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> {
14 pub fn new_one_to_one(ch: impl Peripheral<P = C> + 'd, event: Event, task: Task) -> Self { 14 /// Configure PPI channel to trigger `task` on `event`.
15 pub fn new_one_to_one(ch: impl Peripheral<P = C> + 'd, event: Event<'d>, task: Task<'d>) -> Self {
15 Ppi::new_many_to_many(ch, [event], [task]) 16 Ppi::new_many_to_many(ch, [event], [task])
16 } 17 }
17} 18}
18 19
19impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> { 20impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> {
20 pub fn new_one_to_two(ch: impl Peripheral<P = C> + 'd, event: Event, task1: Task, task2: Task) -> Self { 21 /// Configure PPI channel to trigger both `task1` and `task2` on `event`.
22 pub fn new_one_to_two(ch: impl Peripheral<P = C> + 'd, event: Event<'d>, task1: Task<'d>, task2: Task<'d>) -> Self {
21 Ppi::new_many_to_many(ch, [event], [task1, task2]) 23 Ppi::new_many_to_many(ch, [event], [task1, task2])
22 } 24 }
23} 25}
@@ -25,10 +27,11 @@ impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> {
25impl<'d, C: ConfigurableChannel, const EVENT_COUNT: usize, const TASK_COUNT: usize> 27impl<'d, C: ConfigurableChannel, const EVENT_COUNT: usize, const TASK_COUNT: usize>
26 Ppi<'d, C, EVENT_COUNT, TASK_COUNT> 28 Ppi<'d, C, EVENT_COUNT, TASK_COUNT>
27{ 29{
30 /// Configure a DPPI channel to trigger all `tasks` when any of the `events` fires.
28 pub fn new_many_to_many( 31 pub fn new_many_to_many(
29 ch: impl Peripheral<P = C> + 'd, 32 ch: impl Peripheral<P = C> + 'd,
30 events: [Event; EVENT_COUNT], 33 events: [Event<'d>; EVENT_COUNT],
31 tasks: [Task; TASK_COUNT], 34 tasks: [Task<'d>; TASK_COUNT],
32 ) -> Self { 35 ) -> Self {
33 into_ref!(ch); 36 into_ref!(ch);
34 37
diff --git a/embassy-nrf/src/ppi/mod.rs b/embassy-nrf/src/ppi/mod.rs
index 8f5ed14cd..ff6593bd5 100644
--- a/embassy-nrf/src/ppi/mod.rs
+++ b/embassy-nrf/src/ppi/mod.rs
@@ -1,6 +1,6 @@
1#![macro_use] 1#![macro_use]
2 2
3//! HAL interface for the PPI and DPPI peripheral. 3//! Programmable Peripheral Interconnect (PPI/DPPI) driver.
4//! 4//!
5//! The (Distributed) Programmable Peripheral Interconnect interface allows for an autonomous interoperability 5//! The (Distributed) Programmable Peripheral Interconnect interface allows for an autonomous interoperability
6//! between peripherals through their events and tasks. There are fixed PPI channels and fully 6//! between peripherals through their events and tasks. There are fixed PPI channels and fully
@@ -15,24 +15,107 @@
15//! many tasks and events, but any single task or event can only be coupled with one channel. 15//! many tasks and events, but any single task or event can only be coupled with one channel.
16//! 16//!
17 17
18use core::marker::PhantomData;
18use core::ptr::NonNull; 19use core::ptr::NonNull;
19 20
20use embassy_hal_common::{impl_peripheral, PeripheralRef}; 21use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef};
21 22
22use crate::{peripherals, Peripheral}; 23use crate::{peripherals, Peripheral};
23 24
24#[cfg(feature = "_dppi")] 25#[cfg_attr(feature = "_dppi", path = "dppi.rs")]
25mod dppi; 26#[cfg_attr(feature = "_ppi", path = "ppi.rs")]
26#[cfg(feature = "_ppi")] 27mod _version;
27mod ppi; 28pub(crate) use _version::*;
28 29
29/// An instance of the Programmable peripheral interconnect on nRF devices. 30/// PPI channel driver.
30pub struct Ppi<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> { 31pub struct Ppi<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> {
31 ch: PeripheralRef<'d, C>, 32 ch: PeripheralRef<'d, C>,
32 #[cfg(feature = "_dppi")] 33 #[cfg(feature = "_dppi")]
33 events: [Event; EVENT_COUNT], 34 events: [Event<'d>; EVENT_COUNT],
34 #[cfg(feature = "_dppi")] 35 #[cfg(feature = "_dppi")]
35 tasks: [Task; TASK_COUNT], 36 tasks: [Task<'d>; TASK_COUNT],
37}
38
39/// PPI channel group driver.
40pub struct PpiGroup<'d, G: Group> {
41 g: PeripheralRef<'d, G>,
42}
43
44impl<'d, G: Group> PpiGroup<'d, G> {
45 /// Create a new PPI group driver.
46 ///
47 /// The group is initialized as containing no channels.
48 pub fn new(g: impl Peripheral<P = G> + 'd) -> Self {
49 into_ref!(g);
50
51 let r = regs();
52 let n = g.number();
53 r.chg[n].write(|w| unsafe { w.bits(0) });
54
55 Self { g }
56 }
57
58 /// Add a PPI channel to this group.
59 ///
60 /// If the channel is already in the group, this is a no-op.
61 pub fn add_channel<C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize>(
62 &mut self,
63 ch: &Ppi<'_, C, EVENT_COUNT, TASK_COUNT>,
64 ) {
65 let r = regs();
66 let ng = self.g.number();
67 let nc = ch.ch.number();
68 r.chg[ng].modify(|r, w| unsafe { w.bits(r.bits() | 1 << nc) });
69 }
70
71 /// Remove a PPI channel from this group.
72 ///
73 /// If the channel is already not in the group, this is a no-op.
74 pub fn remove_channel<C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize>(
75 &mut self,
76 ch: &Ppi<'_, C, EVENT_COUNT, TASK_COUNT>,
77 ) {
78 let r = regs();
79 let ng = self.g.number();
80 let nc = ch.ch.number();
81 r.chg[ng].modify(|r, w| unsafe { w.bits(r.bits() & !(1 << nc)) });
82 }
83
84 /// Enable all the channels in this group.
85 pub fn enable_all(&mut self) {
86 let n = self.g.number();
87 regs().tasks_chg[n].en.write(|w| unsafe { w.bits(1) });
88 }
89
90 /// Disable all the channels in this group.
91 pub fn disable_all(&mut self) {
92 let n = self.g.number();
93 regs().tasks_chg[n].dis.write(|w| unsafe { w.bits(1) });
94 }
95
96 /// Get a reference to the "enable all" task.
97 ///
98 /// When triggered, it will enable all the channels in this group.
99 pub fn task_enable_all(&self) -> Task<'d> {
100 let n = self.g.number();
101 Task::from_reg(&regs().tasks_chg[n].en)
102 }
103
104 /// Get a reference to the "disable all" task.
105 ///
106 /// When triggered, it will disable all the channels in this group.
107 pub fn task_disable_all(&self) -> Task<'d> {
108 let n = self.g.number();
109 Task::from_reg(&regs().tasks_chg[n].dis)
110 }
111}
112
113impl<'d, G: Group> Drop for PpiGroup<'d, G> {
114 fn drop(&mut self) {
115 let r = regs();
116 let n = self.g.number();
117 r.chg[n].write(|w| unsafe { w.bits(0) });
118 }
36} 119}
37 120
38#[cfg(feature = "_dppi")] 121#[cfg(feature = "_dppi")]
@@ -43,20 +126,28 @@ const REGISTER_DPPI_CONFIG_OFFSET: usize = 0x80 / core::mem::size_of::<u32>();
43/// When a task is subscribed to a PPI channel, it will run when the channel is triggered by 126/// When a task is subscribed to a PPI channel, it will run when the channel is triggered by
44/// a published event. 127/// a published event.
45#[derive(PartialEq, Eq, Clone, Copy)] 128#[derive(PartialEq, Eq, Clone, Copy)]
46pub struct Task(NonNull<u32>); 129pub struct Task<'d>(NonNull<u32>, PhantomData<&'d ()>);
47 130
48impl Task { 131impl<'d> Task<'d> {
49 /// Create a new `Task` from a task register pointer 132 /// Create a new `Task` from a task register pointer
50 /// 133 ///
51 /// # Safety 134 /// # Safety
52 /// 135 ///
53 /// `ptr` must be a pointer to a valid `TASKS_*` register from an nRF peripheral. 136 /// `ptr` must be a pointer to a valid `TASKS_*` register from an nRF peripheral.
54 pub unsafe fn new_unchecked(ptr: NonNull<u32>) -> Self { 137 pub unsafe fn new_unchecked(ptr: NonNull<u32>) -> Self {
55 Self(ptr) 138 Self(ptr, PhantomData)
139 }
140
141 /// Triggers this task.
142 pub fn trigger(&mut self) {
143 unsafe { self.0.as_ptr().write_volatile(1) };
56 } 144 }
57 145
58 pub(crate) fn from_reg<T>(reg: &T) -> Self { 146 pub(crate) fn from_reg<T>(reg: &T) -> Self {
59 Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) }) 147 Self(
148 unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) },
149 PhantomData,
150 )
60 } 151 }
61 152
62 /// Address of subscription register for this task. 153 /// Address of subscription register for this task.
@@ -69,26 +160,39 @@ impl Task {
69/// # Safety 160/// # Safety
70/// 161///
71/// NonNull is not send, but this event is only allowed to point at registers and those exist in any context on the same core. 162/// NonNull is not send, but this event is only allowed to point at registers and those exist in any context on the same core.
72unsafe impl Send for Task {} 163unsafe impl Send for Task<'_> {}
73 164
74/// Represents an event that a peripheral can publish. 165/// Represents an event that a peripheral can publish.
75/// 166///
76/// An event can be set to publish on a PPI channel when the event happens. 167/// An event can be set to publish on a PPI channel when the event happens.
77#[derive(PartialEq, Eq, Clone, Copy)] 168#[derive(PartialEq, Eq, Clone, Copy)]
78pub struct Event(NonNull<u32>); 169pub struct Event<'d>(NonNull<u32>, PhantomData<&'d ()>);
79 170
80impl Event { 171impl<'d> Event<'d> {
81 /// Create a new `Event` from an event register pointer 172 /// Create a new `Event` from an event register pointer
82 /// 173 ///
83 /// # Safety 174 /// # Safety
84 /// 175 ///
85 /// `ptr` must be a pointer to a valid `EVENTS_*` register from an nRF peripheral. 176 /// `ptr` must be a pointer to a valid `EVENTS_*` register from an nRF peripheral.
86 pub unsafe fn new_unchecked(ptr: NonNull<u32>) -> Self { 177 pub unsafe fn new_unchecked(ptr: NonNull<u32>) -> Self {
87 Self(ptr) 178 Self(ptr, PhantomData)
88 } 179 }
89 180
90 pub(crate) fn from_reg<T>(reg: &T) -> Self { 181 pub(crate) fn from_reg<T>(reg: &'d T) -> Self {
91 Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) }) 182 Self(
183 unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) },
184 PhantomData,
185 )
186 }
187
188 /// Describes whether this Event is currently in a triggered state.
189 pub fn is_triggered(&self) -> bool {
190 unsafe { self.0.as_ptr().read_volatile() == 1 }
191 }
192
193 /// Clear the current register's triggered state, reverting it to 0.
194 pub fn clear(&mut self) {
195 unsafe { self.0.as_ptr().write_volatile(0) };
92 } 196 }
93 197
94 /// Address of publish register for this event. 198 /// Address of publish register for this event.
@@ -101,7 +205,7 @@ impl Event {
101/// # Safety 205/// # Safety
102/// 206///
103/// NonNull is not send, but this event is only allowed to point at registers and those exist in any context on the same core. 207/// NonNull is not send, but this event is only allowed to point at registers and those exist in any context on the same core.
104unsafe impl Send for Event {} 208unsafe impl Send for Event<'_> {}
105 209
106// ====================== 210// ======================
107// traits 211// traits
@@ -112,7 +216,7 @@ pub(crate) mod sealed {
112} 216}
113 217
114/// Interface for PPI channels. 218/// Interface for PPI channels.
115pub trait Channel: sealed::Channel + Peripheral<P = Self> + Sized { 219pub trait Channel: sealed::Channel + Peripheral<P = Self> + Sized + 'static {
116 /// Returns the number of the channel 220 /// Returns the number of the channel
117 fn number(&self) -> usize; 221 fn number(&self) -> usize;
118} 222}
@@ -130,7 +234,7 @@ pub trait StaticChannel: Channel + Into<AnyStaticChannel> {
130} 234}
131 235
132/// Interface for a group of PPI channels. 236/// Interface for a group of PPI channels.
133pub trait Group: sealed::Group + Sized { 237pub trait Group: sealed::Group + Peripheral<P = Self> + Into<AnyGroup> + Sized + 'static {
134 /// Returns the number of the group. 238 /// Returns the number of the group.
135 fn number(&self) -> usize; 239 fn number(&self) -> usize;
136 /// Convert into a type erased group. 240 /// Convert into a type erased group.
@@ -248,6 +352,12 @@ macro_rules! impl_group {
248 $number 352 $number
249 } 353 }
250 } 354 }
355
356 impl From<peripherals::$type> for crate::ppi::AnyGroup {
357 fn from(val: peripherals::$type) -> Self {
358 crate::ppi::Group::degrade(val)
359 }
360 }
251 }; 361 };
252} 362}
253 363
diff --git a/embassy-nrf/src/ppi/ppi.rs b/embassy-nrf/src/ppi/ppi.rs
index 19abc4e18..1fe898625 100644
--- a/embassy-nrf/src/ppi/ppi.rs
+++ b/embassy-nrf/src/ppi/ppi.rs
@@ -3,18 +3,18 @@ use embassy_hal_common::into_ref;
3use super::{Channel, ConfigurableChannel, Event, Ppi, StaticChannel, Task}; 3use super::{Channel, ConfigurableChannel, Event, Ppi, StaticChannel, Task};
4use crate::{pac, Peripheral}; 4use crate::{pac, Peripheral};
5 5
6impl Task { 6impl<'d> Task<'d> {
7 fn reg_val(&self) -> u32 { 7 fn reg_val(&self) -> u32 {
8 self.0.as_ptr() as _ 8 self.0.as_ptr() as _
9 } 9 }
10} 10}
11impl Event { 11impl<'d> Event<'d> {
12 fn reg_val(&self) -> u32 { 12 fn reg_val(&self) -> u32 {
13 self.0.as_ptr() as _ 13 self.0.as_ptr() as _
14 } 14 }
15} 15}
16 16
17fn regs() -> &'static pac::ppi::RegisterBlock { 17pub(crate) fn regs() -> &'static pac::ppi::RegisterBlock {
18 unsafe { &*pac::PPI::ptr() } 18 unsafe { &*pac::PPI::ptr() }
19} 19}
20 20
@@ -34,7 +34,7 @@ impl<'d, C: StaticChannel> Ppi<'d, C, 0, 1> {
34 34
35impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> { 35impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> {
36 /// Configure PPI channel to trigger `task` on `event`. 36 /// Configure PPI channel to trigger `task` on `event`.
37 pub fn new_one_to_one(ch: impl Peripheral<P = C> + 'd, event: Event, task: Task) -> Self { 37 pub fn new_one_to_one(ch: impl Peripheral<P = C> + 'd, event: Event<'d>, task: Task<'d>) -> Self {
38 into_ref!(ch); 38 into_ref!(ch);
39 39
40 let r = regs(); 40 let r = regs();
@@ -48,8 +48,8 @@ impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> {
48 48
49#[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task 49#[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task
50impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> { 50impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> {
51 /// Configure PPI channel to trigger `task1` and `task2` on `event`. 51 /// Configure PPI channel to trigger both `task1` and `task2` on `event`.
52 pub fn new_one_to_two(ch: impl Peripheral<P = C> + 'd, event: Event, task1: Task, task2: Task) -> Self { 52 pub fn new_one_to_two(ch: impl Peripheral<P = C> + 'd, event: Event<'d>, task1: Task<'d>, task2: Task<'d>) -> Self {
53 into_ref!(ch); 53 into_ref!(ch);
54 54
55 let r = regs(); 55 let r = regs();
diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs
index 5f750a91e..c8c81fa01 100644
--- a/embassy-nrf/src/pwm.rs
+++ b/embassy-nrf/src/pwm.rs
@@ -1,3 +1,5 @@
1//! Pulse Width Modulation (PWM) driver.
2
1#![macro_use] 3#![macro_use]
2 4
3use core::sync::atomic::{compiler_fence, Ordering}; 5use core::sync::atomic::{compiler_fence, Ordering};
@@ -6,10 +8,9 @@ use embassy_hal_common::{into_ref, PeripheralRef};
6 8
7use crate::gpio::sealed::Pin as _; 9use crate::gpio::sealed::Pin as _;
8use crate::gpio::{AnyPin, Pin as GpioPin, PselBits}; 10use crate::gpio::{AnyPin, Pin as GpioPin, PselBits};
9use crate::interrupt::Interrupt;
10use crate::ppi::{Event, Task}; 11use crate::ppi::{Event, Task};
11use crate::util::slice_in_ram_or; 12use crate::util::slice_in_ram_or;
12use crate::{pac, Peripheral}; 13use crate::{interrupt, pac, Peripheral};
13 14
14/// SimplePwm is the traditional pwm interface you're probably used to, allowing 15/// SimplePwm is the traditional pwm interface you're probably used to, allowing
15/// to simply set a duty cycle across up to four channels. 16/// to simply set a duty cycle across up to four channels.
@@ -32,6 +33,7 @@ pub struct SequencePwm<'d, T: Instance> {
32 ch3: Option<PeripheralRef<'d, AnyPin>>, 33 ch3: Option<PeripheralRef<'d, AnyPin>>,
33} 34}
34 35
36/// PWM error
35#[derive(Debug, Clone, Copy, PartialEq, Eq)] 37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36#[cfg_attr(feature = "defmt", derive(defmt::Format))] 38#[cfg_attr(feature = "defmt", derive(defmt::Format))]
37#[non_exhaustive] 39#[non_exhaustive]
@@ -41,7 +43,7 @@ pub enum Error {
41 /// Min Sequence count is 1 43 /// Min Sequence count is 1
42 SequenceTimesAtLeastOne, 44 SequenceTimesAtLeastOne,
43 /// EasyDMA can only read from data memory, read only buffers in flash will fail. 45 /// EasyDMA can only read from data memory, read only buffers in flash will fail.
44 DMABufferNotInDataMemory, 46 BufferNotInRAM,
45} 47}
46 48
47const MAX_SEQUENCE_LEN: usize = 32767; 49const MAX_SEQUENCE_LEN: usize = 32767;
@@ -179,7 +181,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
179 181
180 /// Returns reference to `Stopped` event endpoint for PPI. 182 /// Returns reference to `Stopped` event endpoint for PPI.
181 #[inline(always)] 183 #[inline(always)]
182 pub fn event_stopped(&self) -> Event { 184 pub fn event_stopped(&self) -> Event<'d> {
183 let r = T::regs(); 185 let r = T::regs();
184 186
185 Event::from_reg(&r.events_stopped) 187 Event::from_reg(&r.events_stopped)
@@ -187,7 +189,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
187 189
188 /// Returns reference to `LoopsDone` event endpoint for PPI. 190 /// Returns reference to `LoopsDone` event endpoint for PPI.
189 #[inline(always)] 191 #[inline(always)]
190 pub fn event_loops_done(&self) -> Event { 192 pub fn event_loops_done(&self) -> Event<'d> {
191 let r = T::regs(); 193 let r = T::regs();
192 194
193 Event::from_reg(&r.events_loopsdone) 195 Event::from_reg(&r.events_loopsdone)
@@ -195,7 +197,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
195 197
196 /// Returns reference to `PwmPeriodEnd` event endpoint for PPI. 198 /// Returns reference to `PwmPeriodEnd` event endpoint for PPI.
197 #[inline(always)] 199 #[inline(always)]
198 pub fn event_pwm_period_end(&self) -> Event { 200 pub fn event_pwm_period_end(&self) -> Event<'d> {
199 let r = T::regs(); 201 let r = T::regs();
200 202
201 Event::from_reg(&r.events_pwmperiodend) 203 Event::from_reg(&r.events_pwmperiodend)
@@ -203,7 +205,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
203 205
204 /// Returns reference to `Seq0 End` event endpoint for PPI. 206 /// Returns reference to `Seq0 End` event endpoint for PPI.
205 #[inline(always)] 207 #[inline(always)]
206 pub fn event_seq_end(&self) -> Event { 208 pub fn event_seq_end(&self) -> Event<'d> {
207 let r = T::regs(); 209 let r = T::regs();
208 210
209 Event::from_reg(&r.events_seqend[0]) 211 Event::from_reg(&r.events_seqend[0])
@@ -211,7 +213,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
211 213
212 /// Returns reference to `Seq1 End` event endpoint for PPI. 214 /// Returns reference to `Seq1 End` event endpoint for PPI.
213 #[inline(always)] 215 #[inline(always)]
214 pub fn event_seq1_end(&self) -> Event { 216 pub fn event_seq1_end(&self) -> Event<'d> {
215 let r = T::regs(); 217 let r = T::regs();
216 218
217 Event::from_reg(&r.events_seqend[1]) 219 Event::from_reg(&r.events_seqend[1])
@@ -219,7 +221,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
219 221
220 /// Returns reference to `Seq0 Started` event endpoint for PPI. 222 /// Returns reference to `Seq0 Started` event endpoint for PPI.
221 #[inline(always)] 223 #[inline(always)]
222 pub fn event_seq0_started(&self) -> Event { 224 pub fn event_seq0_started(&self) -> Event<'d> {
223 let r = T::regs(); 225 let r = T::regs();
224 226
225 Event::from_reg(&r.events_seqstarted[0]) 227 Event::from_reg(&r.events_seqstarted[0])
@@ -227,7 +229,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
227 229
228 /// Returns reference to `Seq1 Started` event endpoint for PPI. 230 /// Returns reference to `Seq1 Started` event endpoint for PPI.
229 #[inline(always)] 231 #[inline(always)]
230 pub fn event_seq1_started(&self) -> Event { 232 pub fn event_seq1_started(&self) -> Event<'d> {
231 let r = T::regs(); 233 let r = T::regs();
232 234
233 Event::from_reg(&r.events_seqstarted[1]) 235 Event::from_reg(&r.events_seqstarted[1])
@@ -238,7 +240,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
238 /// 240 ///
239 /// Interacting with the sequence while it runs puts it in an unknown state 241 /// Interacting with the sequence while it runs puts it in an unknown state
240 #[inline(always)] 242 #[inline(always)]
241 pub unsafe fn task_start_seq0(&self) -> Task { 243 pub unsafe fn task_start_seq0(&self) -> Task<'d> {
242 let r = T::regs(); 244 let r = T::regs();
243 245
244 Task::from_reg(&r.tasks_seqstart[0]) 246 Task::from_reg(&r.tasks_seqstart[0])
@@ -249,7 +251,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
249 /// 251 ///
250 /// Interacting with the sequence while it runs puts it in an unknown state 252 /// Interacting with the sequence while it runs puts it in an unknown state
251 #[inline(always)] 253 #[inline(always)]
252 pub unsafe fn task_start_seq1(&self) -> Task { 254 pub unsafe fn task_start_seq1(&self) -> Task<'d> {
253 let r = T::regs(); 255 let r = T::regs();
254 256
255 Task::from_reg(&r.tasks_seqstart[1]) 257 Task::from_reg(&r.tasks_seqstart[1])
@@ -260,7 +262,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
260 /// 262 ///
261 /// Interacting with the sequence while it runs puts it in an unknown state 263 /// Interacting with the sequence while it runs puts it in an unknown state
262 #[inline(always)] 264 #[inline(always)]
263 pub unsafe fn task_next_step(&self) -> Task { 265 pub unsafe fn task_next_step(&self) -> Task<'d> {
264 let r = T::regs(); 266 let r = T::regs();
265 267
266 Task::from_reg(&r.tasks_nextstep) 268 Task::from_reg(&r.tasks_nextstep)
@@ -271,7 +273,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
271 /// 273 ///
272 /// Interacting with the sequence while it runs puts it in an unknown state 274 /// Interacting with the sequence while it runs puts it in an unknown state
273 #[inline(always)] 275 #[inline(always)]
274 pub unsafe fn task_stop(&self) -> Task { 276 pub unsafe fn task_stop(&self) -> Task<'d> {
275 let r = T::regs(); 277 let r = T::regs();
276 278
277 Task::from_reg(&r.tasks_stop) 279 Task::from_reg(&r.tasks_stop)
@@ -358,6 +360,7 @@ pub struct Sequence<'s> {
358} 360}
359 361
360impl<'s> Sequence<'s> { 362impl<'s> Sequence<'s> {
363 /// Create a new `Sequence`
361 pub fn new(words: &'s [u16], config: SequenceConfig) -> Self { 364 pub fn new(words: &'s [u16], config: SequenceConfig) -> Self {
362 Self { words, config } 365 Self { words, config }
363 } 366 }
@@ -367,7 +370,7 @@ impl<'s> Sequence<'s> {
367/// Takes at one sequence along with its configuration. 370/// Takes at one sequence along with its configuration.
368#[non_exhaustive] 371#[non_exhaustive]
369pub struct SingleSequencer<'d, 's, T: Instance> { 372pub struct SingleSequencer<'d, 's, T: Instance> {
370 pub sequencer: Sequencer<'d, 's, T>, 373 sequencer: Sequencer<'d, 's, T>,
371} 374}
372 375
373impl<'d, 's, T: Instance> SingleSequencer<'d, 's, T> { 376impl<'d, 's, T: Instance> SingleSequencer<'d, 's, T> {
@@ -428,8 +431,8 @@ impl<'d, 's, T: Instance> Sequencer<'d, 's, T> {
428 let sequence0 = &self.sequence0; 431 let sequence0 = &self.sequence0;
429 let alt_sequence = self.sequence1.as_ref().unwrap_or(&self.sequence0); 432 let alt_sequence = self.sequence1.as_ref().unwrap_or(&self.sequence0);
430 433
431 slice_in_ram_or(sequence0.words, Error::DMABufferNotInDataMemory)?; 434 slice_in_ram_or(sequence0.words, Error::BufferNotInRAM)?;
432 slice_in_ram_or(alt_sequence.words, Error::DMABufferNotInDataMemory)?; 435 slice_in_ram_or(alt_sequence.words, Error::BufferNotInRAM)?;
433 436
434 if sequence0.words.len() > MAX_SEQUENCE_LEN || alt_sequence.words.len() > MAX_SEQUENCE_LEN { 437 if sequence0.words.len() > MAX_SEQUENCE_LEN || alt_sequence.words.len() > MAX_SEQUENCE_LEN {
435 return Err(Error::SequenceTooLong); 438 return Err(Error::SequenceTooLong);
@@ -536,13 +539,21 @@ pub enum SequenceMode {
536/// PWM Base clock is system clock (16MHz) divided by prescaler 539/// PWM Base clock is system clock (16MHz) divided by prescaler
537#[derive(Debug, Eq, PartialEq, Clone, Copy)] 540#[derive(Debug, Eq, PartialEq, Clone, Copy)]
538pub enum Prescaler { 541pub enum Prescaler {
542 /// Divide by 1
539 Div1, 543 Div1,
544 /// Divide by 2
540 Div2, 545 Div2,
546 /// Divide by 4
541 Div4, 547 Div4,
548 /// Divide by 8
542 Div8, 549 Div8,
550 /// Divide by 16
543 Div16, 551 Div16,
552 /// Divide by 32
544 Div32, 553 Div32,
554 /// Divide by 64
545 Div64, 555 Div64,
556 /// Divide by 128
546 Div128, 557 Div128,
547} 558}
548 559
@@ -828,8 +839,10 @@ pub(crate) mod sealed {
828 } 839 }
829} 840}
830 841
842/// PWM peripheral instance.
831pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static { 843pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static {
832 type Interrupt: Interrupt; 844 /// Interrupt for this peripheral.
845 type Interrupt: interrupt::typelevel::Interrupt;
833} 846}
834 847
835macro_rules! impl_pwm { 848macro_rules! impl_pwm {
@@ -840,7 +853,7 @@ macro_rules! impl_pwm {
840 } 853 }
841 } 854 }
842 impl crate::pwm::Instance for peripherals::$type { 855 impl crate::pwm::Instance for peripherals::$type {
843 type Interrupt = crate::interrupt::$irq; 856 type Interrupt = crate::interrupt::typelevel::$irq;
844 } 857 }
845 }; 858 };
846} 859}
diff --git a/embassy-nrf/src/qdec.rs b/embassy-nrf/src/qdec.rs
index 762e09715..8bac87d37 100644
--- a/embassy-nrf/src/qdec.rs
+++ b/embassy-nrf/src/qdec.rs
@@ -1,28 +1,35 @@
1//! Quadrature decoder interface 1//! Quadrature decoder (QDEC) driver.
2 2
3#![macro_use]
4
5use core::future::poll_fn;
6use core::marker::PhantomData;
3use core::task::Poll; 7use core::task::Poll;
4 8
5use embassy_hal_common::{into_ref, PeripheralRef}; 9use embassy_hal_common::{into_ref, PeripheralRef};
6use embassy_sync::waitqueue::AtomicWaker;
7use futures::future::poll_fn;
8 10
9use crate::gpio::sealed::Pin as _; 11use crate::gpio::sealed::Pin as _;
10use crate::gpio::{AnyPin, Pin as GpioPin}; 12use crate::gpio::{AnyPin, Pin as GpioPin};
11use crate::interrupt::InterruptExt; 13use crate::interrupt::typelevel::Interrupt;
12use crate::peripherals::QDEC; 14use crate::{interrupt, Peripheral};
13use crate::{interrupt, pac, Peripheral};
14 15
15/// Quadrature decoder 16/// Quadrature decoder driver.
16pub struct Qdec<'d> { 17pub struct Qdec<'d, T: Instance> {
17 _p: PeripheralRef<'d, QDEC>, 18 _p: PeripheralRef<'d, T>,
18} 19}
19 20
21/// QDEC config
20#[non_exhaustive] 22#[non_exhaustive]
21pub struct Config { 23pub struct Config {
24 /// Number of samples
22 pub num_samples: NumSamples, 25 pub num_samples: NumSamples,
26 /// Sample period
23 pub period: SamplePeriod, 27 pub period: SamplePeriod,
28 /// Set LED output pin polarity
24 pub led_polarity: LedPolarity, 29 pub led_polarity: LedPolarity,
30 /// Enable/disable input debounce filters
25 pub debounce: bool, 31 pub debounce: bool,
32 /// Time period the LED is switched ON prior to sampling (0..511 us).
26 pub led_pre_usecs: u16, 33 pub led_pre_usecs: u16,
27} 34}
28 35
@@ -38,42 +45,52 @@ impl Default for Config {
38 } 45 }
39} 46}
40 47
41static WAKER: AtomicWaker = AtomicWaker::new(); 48/// Interrupt handler.
49pub struct InterruptHandler<T: Instance> {
50 _phantom: PhantomData<T>,
51}
52
53impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
54 unsafe fn on_interrupt() {
55 T::regs().intenclr.write(|w| w.reportrdy().clear());
56 T::state().waker.wake();
57 }
58}
42 59
43impl<'d> Qdec<'d> { 60impl<'d, T: Instance> Qdec<'d, T> {
61 /// Create a new QDEC.
44 pub fn new( 62 pub fn new(
45 qdec: impl Peripheral<P = QDEC> + 'd, 63 qdec: impl Peripheral<P = T> + 'd,
46 irq: impl Peripheral<P = interrupt::QDEC> + 'd, 64 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
47 a: impl Peripheral<P = impl GpioPin> + 'd, 65 a: impl Peripheral<P = impl GpioPin> + 'd,
48 b: impl Peripheral<P = impl GpioPin> + 'd, 66 b: impl Peripheral<P = impl GpioPin> + 'd,
49 config: Config, 67 config: Config,
50 ) -> Self { 68 ) -> Self {
51 into_ref!(a, b); 69 into_ref!(qdec, a, b);
52 Self::new_inner(qdec, irq, a.map_into(), b.map_into(), None, config) 70 Self::new_inner(qdec, a.map_into(), b.map_into(), None, config)
53 } 71 }
54 72
73 /// Create a new QDEC, with a pin for LED output.
55 pub fn new_with_led( 74 pub fn new_with_led(
56 qdec: impl Peripheral<P = QDEC> + 'd, 75 qdec: impl Peripheral<P = T> + 'd,
57 irq: impl Peripheral<P = interrupt::QDEC> + 'd, 76 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
58 a: impl Peripheral<P = impl GpioPin> + 'd, 77 a: impl Peripheral<P = impl GpioPin> + 'd,
59 b: impl Peripheral<P = impl GpioPin> + 'd, 78 b: impl Peripheral<P = impl GpioPin> + 'd,
60 led: impl Peripheral<P = impl GpioPin> + 'd, 79 led: impl Peripheral<P = impl GpioPin> + 'd,
61 config: Config, 80 config: Config,
62 ) -> Self { 81 ) -> Self {
63 into_ref!(a, b, led); 82 into_ref!(qdec, a, b, led);
64 Self::new_inner(qdec, irq, a.map_into(), b.map_into(), Some(led.map_into()), config) 83 Self::new_inner(qdec, a.map_into(), b.map_into(), Some(led.map_into()), config)
65 } 84 }
66 85
67 fn new_inner( 86 fn new_inner(
68 p: impl Peripheral<P = QDEC> + 'd, 87 p: PeripheralRef<'d, T>,
69 irq: impl Peripheral<P = interrupt::QDEC> + 'd,
70 a: PeripheralRef<'d, AnyPin>, 88 a: PeripheralRef<'d, AnyPin>,
71 b: PeripheralRef<'d, AnyPin>, 89 b: PeripheralRef<'d, AnyPin>,
72 led: Option<PeripheralRef<'d, AnyPin>>, 90 led: Option<PeripheralRef<'d, AnyPin>>,
73 config: Config, 91 config: Config,
74 ) -> Self { 92 ) -> Self {
75 into_ref!(p, irq); 93 let r = T::regs();
76 let r = Self::regs();
77 94
78 // Select pins. 95 // Select pins.
79 a.conf().write(|w| w.input().connect().pull().pullup()); 96 a.conf().write(|w| w.input().connect().pull().pullup());
@@ -116,20 +133,15 @@ impl<'d> Qdec<'d> {
116 SamplePeriod::_131ms => w.sampleper()._131ms(), 133 SamplePeriod::_131ms => w.sampleper()._131ms(),
117 }); 134 });
118 135
136 T::Interrupt::unpend();
137 unsafe { T::Interrupt::enable() };
138
119 // Enable peripheral 139 // Enable peripheral
120 r.enable.write(|w| w.enable().set_bit()); 140 r.enable.write(|w| w.enable().set_bit());
121 141
122 // Start sampling 142 // Start sampling
123 unsafe { r.tasks_start.write(|w| w.bits(1)) }; 143 unsafe { r.tasks_start.write(|w| w.bits(1)) };
124 144
125 irq.disable();
126 irq.set_handler(|_| {
127 let r = Self::regs();
128 r.intenclr.write(|w| w.reportrdy().clear());
129 WAKER.wake();
130 });
131 irq.enable();
132
133 Self { _p: p } 145 Self { _p: p }
134 } 146 }
135 147
@@ -141,18 +153,27 @@ impl<'d> Qdec<'d> {
141 /// # Example 153 /// # Example
142 /// 154 ///
143 /// ```no_run 155 /// ```no_run
144 /// let irq = interrupt::take!(QDEC); 156 /// use embassy_nrf::qdec::{self, Qdec};
157 /// use embassy_nrf::{bind_interrupts, peripherals};
158 ///
159 /// bind_interrupts!(struct Irqs {
160 /// QDEC => qdec::InterruptHandler<peripherals::QDEC>;
161 /// });
162 ///
163 /// # async {
164 /// # let p: embassy_nrf::Peripherals = todo!();
145 /// let config = qdec::Config::default(); 165 /// let config = qdec::Config::default();
146 /// let mut q = Qdec::new(p.QDEC, p.P0_31, p.P0_30, config); 166 /// let mut q = Qdec::new(p.QDEC, Irqs, p.P0_31, p.P0_30, config);
147 /// let delta = q.read().await; 167 /// let delta = q.read().await;
168 /// # };
148 /// ``` 169 /// ```
149 pub async fn read(&mut self) -> i16 { 170 pub async fn read(&mut self) -> i16 {
150 let t = Self::regs(); 171 let t = T::regs();
151 t.intenset.write(|w| w.reportrdy().set()); 172 t.intenset.write(|w| w.reportrdy().set());
152 unsafe { t.tasks_readclracc.write(|w| w.bits(1)) }; 173 unsafe { t.tasks_readclracc.write(|w| w.bits(1)) };
153 174
154 let value = poll_fn(|cx| { 175 let value = poll_fn(|cx| {
155 WAKER.register(cx.waker()); 176 T::state().waker.register(cx.waker());
156 if t.events_reportrdy.read().bits() == 0 { 177 if t.events_reportrdy.read().bits() == 0 {
157 return Poll::Pending; 178 return Poll::Pending;
158 } else { 179 } else {
@@ -164,42 +185,108 @@ impl<'d> Qdec<'d> {
164 .await; 185 .await;
165 value 186 value
166 } 187 }
167
168 fn regs() -> &'static pac::qdec::RegisterBlock {
169 unsafe { &*pac::QDEC::ptr() }
170 }
171} 188}
172 189
190/// Sample period
173#[derive(Debug, Eq, PartialEq, Clone, Copy)] 191#[derive(Debug, Eq, PartialEq, Clone, Copy)]
174pub enum SamplePeriod { 192pub enum SamplePeriod {
193 /// 128 us
175 _128us, 194 _128us,
195 /// 256 us
176 _256us, 196 _256us,
197 /// 512 us
177 _512us, 198 _512us,
199 /// 1024 us
178 _1024us, 200 _1024us,
201 /// 2048 us
179 _2048us, 202 _2048us,
203 /// 4096 us
180 _4096us, 204 _4096us,
205 /// 8192 us
181 _8192us, 206 _8192us,
207 /// 16384 us
182 _16384us, 208 _16384us,
209 /// 32 ms
183 _32ms, 210 _32ms,
211 /// 65 ms
184 _65ms, 212 _65ms,
213 /// 131 ms
185 _131ms, 214 _131ms,
186} 215}
187 216
217/// Number of samples taken.
188#[derive(Debug, Eq, PartialEq, Clone, Copy)] 218#[derive(Debug, Eq, PartialEq, Clone, Copy)]
189pub enum NumSamples { 219pub enum NumSamples {
220 /// 10 samples
190 _10smpl, 221 _10smpl,
222 /// 40 samples
191 _40smpl, 223 _40smpl,
224 /// 80 samples
192 _80smpl, 225 _80smpl,
226 /// 120 samples
193 _120smpl, 227 _120smpl,
228 /// 160 samples
194 _160smpl, 229 _160smpl,
230 /// 200 samples
195 _200smpl, 231 _200smpl,
232 /// 240 samples
196 _240smpl, 233 _240smpl,
234 /// 280 samples
197 _280smpl, 235 _280smpl,
236 /// 1 sample
198 _1smpl, 237 _1smpl,
199} 238}
200 239
240/// LED polarity
201#[derive(Debug, Eq, PartialEq, Clone, Copy)] 241#[derive(Debug, Eq, PartialEq, Clone, Copy)]
202pub enum LedPolarity { 242pub enum LedPolarity {
243 /// Active high (a high output turns on the LED).
203 ActiveHigh, 244 ActiveHigh,
245 /// Active low (a low output turns on the LED).
204 ActiveLow, 246 ActiveLow,
205} 247}
248
249pub(crate) mod sealed {
250 use embassy_sync::waitqueue::AtomicWaker;
251
252 /// Peripheral static state
253 pub struct State {
254 pub waker: AtomicWaker,
255 }
256
257 impl State {
258 pub const fn new() -> Self {
259 Self {
260 waker: AtomicWaker::new(),
261 }
262 }
263 }
264
265 pub trait Instance {
266 fn regs() -> &'static crate::pac::qdec::RegisterBlock;
267 fn state() -> &'static State;
268 }
269}
270
271/// qdec peripheral instance.
272pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
273 /// Interrupt for this peripheral.
274 type Interrupt: interrupt::typelevel::Interrupt;
275}
276
277macro_rules! impl_qdec {
278 ($type:ident, $pac_type:ident, $irq:ident) => {
279 impl crate::qdec::sealed::Instance for peripherals::$type {
280 fn regs() -> &'static crate::pac::qdec::RegisterBlock {
281 unsafe { &*pac::$pac_type::ptr() }
282 }
283 fn state() -> &'static crate::qdec::sealed::State {
284 static STATE: crate::qdec::sealed::State = crate::qdec::sealed::State::new();
285 &STATE
286 }
287 }
288 impl crate::qdec::Instance for peripherals::$type {
289 type Interrupt = crate::interrupt::typelevel::$irq;
290 }
291 };
292}
diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs
index c97cb1656..baefc7967 100644
--- a/embassy-nrf/src/qspi.rs
+++ b/embassy-nrf/src/qspi.rs
@@ -1,20 +1,25 @@
1//! Quad Serial Peripheral Interface (QSPI) flash driver.
2
1#![macro_use] 3#![macro_use]
2 4
5use core::future::poll_fn;
6use core::marker::PhantomData;
3use core::ptr; 7use core::ptr;
4use core::task::Poll; 8use core::task::Poll;
5 9
6use embassy_hal_common::drop::DropBomb; 10use embassy_hal_common::drop::OnDrop;
7use embassy_hal_common::{into_ref, PeripheralRef}; 11use embassy_hal_common::{into_ref, PeripheralRef};
8use futures::future::poll_fn; 12use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash};
9 13
10use crate::gpio::{self, Pin as GpioPin}; 14use crate::gpio::{self, Pin as GpioPin};
11use crate::interrupt::{Interrupt, InterruptExt}; 15use crate::interrupt::typelevel::Interrupt;
12pub use crate::pac::qspi::ifconfig0::{ 16pub use crate::pac::qspi::ifconfig0::{
13 ADDRMODE_A as AddressMode, PPSIZE_A as WritePageSize, READOC_A as ReadOpcode, WRITEOC_A as WriteOpcode, 17 ADDRMODE_A as AddressMode, PPSIZE_A as WritePageSize, READOC_A as ReadOpcode, WRITEOC_A as WriteOpcode,
14}; 18};
15pub use crate::pac::qspi::ifconfig1::SPIMODE_A as SpiMode; 19pub use crate::pac::qspi::ifconfig1::SPIMODE_A as SpiMode;
16use crate::{pac, Peripheral}; 20use crate::{interrupt, Peripheral};
17 21
22/// Deep power-down config.
18pub struct DeepPowerDownConfig { 23pub struct DeepPowerDownConfig {
19 /// Time required for entering DPM, in units of 16us 24 /// Time required for entering DPM, in units of 16us
20 pub enter_time: u16, 25 pub enter_time: u16,
@@ -22,38 +27,65 @@ pub struct DeepPowerDownConfig {
22 pub exit_time: u16, 27 pub exit_time: u16,
23} 28}
24 29
30/// QSPI bus frequency.
25pub enum Frequency { 31pub enum Frequency {
32 /// 32 Mhz
26 M32 = 0, 33 M32 = 0,
34 /// 16 Mhz
27 M16 = 1, 35 M16 = 1,
36 /// 10.7 Mhz
28 M10_7 = 2, 37 M10_7 = 2,
38 /// 8 Mhz
29 M8 = 3, 39 M8 = 3,
40 /// 6.4 Mhz
30 M6_4 = 4, 41 M6_4 = 4,
42 /// 5.3 Mhz
31 M5_3 = 5, 43 M5_3 = 5,
44 /// 4.6 Mhz
32 M4_6 = 6, 45 M4_6 = 6,
46 /// 4 Mhz
33 M4 = 7, 47 M4 = 7,
48 /// 3.6 Mhz
34 M3_6 = 8, 49 M3_6 = 8,
50 /// 3.2 Mhz
35 M3_2 = 9, 51 M3_2 = 9,
52 /// 2.9 Mhz
36 M2_9 = 10, 53 M2_9 = 10,
54 /// 2.7 Mhz
37 M2_7 = 11, 55 M2_7 = 11,
56 /// 2.5 Mhz
38 M2_5 = 12, 57 M2_5 = 12,
58 /// 2.3 Mhz
39 M2_3 = 13, 59 M2_3 = 13,
60 /// 2.1 Mhz
40 M2_1 = 14, 61 M2_1 = 14,
62 /// 2 Mhz
41 M2 = 15, 63 M2 = 15,
42} 64}
43 65
66/// QSPI config.
44#[non_exhaustive] 67#[non_exhaustive]
45pub struct Config { 68pub struct Config {
69 /// XIP offset.
46 pub xip_offset: u32, 70 pub xip_offset: u32,
71 /// Opcode used for read operations.
47 pub read_opcode: ReadOpcode, 72 pub read_opcode: ReadOpcode,
73 /// Opcode used for write operations.
48 pub write_opcode: WriteOpcode, 74 pub write_opcode: WriteOpcode,
75 /// Page size for write operations.
49 pub write_page_size: WritePageSize, 76 pub write_page_size: WritePageSize,
77 /// Configuration for deep power down. If None, deep power down is disabled.
50 pub deep_power_down: Option<DeepPowerDownConfig>, 78 pub deep_power_down: Option<DeepPowerDownConfig>,
79 /// QSPI bus frequency.
51 pub frequency: Frequency, 80 pub frequency: Frequency,
52 /// Value is specified in number of 16 MHz periods (62.5 ns) 81 /// Value is specified in number of 16 MHz periods (62.5 ns)
53 pub sck_delay: u8, 82 pub sck_delay: u8,
54 /// Whether data is captured on the clock rising edge and data is output on a falling edge (MODE0) or vice-versa (MODE3) 83 /// Whether data is captured on the clock rising edge and data is output on a falling edge (MODE0) or vice-versa (MODE3)
55 pub spi_mode: SpiMode, 84 pub spi_mode: SpiMode,
85 /// Addressing mode (24-bit or 32-bit)
56 pub address_mode: AddressMode, 86 pub address_mode: AddressMode,
87 /// Flash memory capacity in bytes. This is the value reported by the `embedded-storage` traits.
88 pub capacity: u32,
57} 89}
58 90
59impl Default for Config { 91impl Default for Config {
@@ -68,27 +100,50 @@ impl Default for Config {
68 sck_delay: 80, 100 sck_delay: 80,
69 spi_mode: SpiMode::MODE0, 101 spi_mode: SpiMode::MODE0,
70 address_mode: AddressMode::_24BIT, 102 address_mode: AddressMode::_24BIT,
103 capacity: 0,
71 } 104 }
72 } 105 }
73} 106}
74 107
108/// Error
75#[derive(Debug, Copy, Clone, Eq, PartialEq)] 109#[derive(Debug, Copy, Clone, Eq, PartialEq)]
76#[cfg_attr(feature = "defmt", derive(defmt::Format))] 110#[cfg_attr(feature = "defmt", derive(defmt::Format))]
77#[non_exhaustive] 111#[non_exhaustive]
78pub enum Error { 112pub enum Error {
113 /// Operation address was out of bounds.
79 OutOfBounds, 114 OutOfBounds,
80 // TODO add "not in data memory" error and check for it 115 // TODO add "not in data memory" error and check for it
81} 116}
82 117
83pub struct Qspi<'d, T: Instance, const FLASH_SIZE: usize> { 118/// Interrupt handler.
84 irq: PeripheralRef<'d, T::Interrupt>, 119pub struct InterruptHandler<T: Instance> {
120 _phantom: PhantomData<T>,
121}
122
123impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
124 unsafe fn on_interrupt() {
125 let r = T::regs();
126 let s = T::state();
127
128 if r.events_ready.read().bits() != 0 {
129 s.waker.wake();
130 r.intenclr.write(|w| w.ready().clear());
131 }
132 }
133}
134
135/// QSPI flash driver.
136pub struct Qspi<'d, T: Instance> {
137 _peri: PeripheralRef<'d, T>,
85 dpm_enabled: bool, 138 dpm_enabled: bool,
139 capacity: u32,
86} 140}
87 141
88impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> { 142impl<'d, T: Instance> Qspi<'d, T> {
143 /// Create a new QSPI driver.
89 pub fn new( 144 pub fn new(
90 _qspi: impl Peripheral<P = T> + 'd, 145 qspi: impl Peripheral<P = T> + 'd,
91 irq: impl Peripheral<P = T::Interrupt> + 'd, 146 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
92 sck: impl Peripheral<P = impl GpioPin> + 'd, 147 sck: impl Peripheral<P = impl GpioPin> + 'd,
93 csn: impl Peripheral<P = impl GpioPin> + 'd, 148 csn: impl Peripheral<P = impl GpioPin> + 'd,
94 io0: impl Peripheral<P = impl GpioPin> + 'd, 149 io0: impl Peripheral<P = impl GpioPin> + 'd,
@@ -96,30 +151,31 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> {
96 io2: impl Peripheral<P = impl GpioPin> + 'd, 151 io2: impl Peripheral<P = impl GpioPin> + 'd,
97 io3: impl Peripheral<P = impl GpioPin> + 'd, 152 io3: impl Peripheral<P = impl GpioPin> + 'd,
98 config: Config, 153 config: Config,
99 ) -> Qspi<'d, T, FLASH_SIZE> { 154 ) -> Self {
100 into_ref!(irq, sck, csn, io0, io1, io2, io3); 155 into_ref!(qspi, sck, csn, io0, io1, io2, io3);
101 156
102 let r = T::regs(); 157 let r = T::regs();
103 158
104 sck.set_high(); 159 macro_rules! config_pin {
105 csn.set_high(); 160 ($pin:ident) => {
106 io0.set_high(); 161 $pin.set_high();
107 io1.set_high(); 162 $pin.conf().write(|w| {
108 io2.set_high(); 163 w.dir().output();
109 io3.set_high(); 164 w.drive().h0h1();
110 sck.conf().write(|w| w.dir().output().drive().h0h1()); 165 #[cfg(feature = "_nrf5340-s")]
111 csn.conf().write(|w| w.dir().output().drive().h0h1()); 166 w.mcusel().peripheral();
112 io0.conf().write(|w| w.dir().output().drive().h0h1()); 167 w
113 io1.conf().write(|w| w.dir().output().drive().h0h1()); 168 });
114 io2.conf().write(|w| w.dir().output().drive().h0h1()); 169 r.psel.$pin.write(|w| unsafe { w.bits($pin.psel_bits()) });
115 io3.conf().write(|w| w.dir().output().drive().h0h1()); 170 };
116 171 }
117 r.psel.sck.write(|w| unsafe { w.bits(sck.psel_bits()) }); 172
118 r.psel.csn.write(|w| unsafe { w.bits(csn.psel_bits()) }); 173 config_pin!(sck);
119 r.psel.io0.write(|w| unsafe { w.bits(io0.psel_bits()) }); 174 config_pin!(csn);
120 r.psel.io1.write(|w| unsafe { w.bits(io1.psel_bits()) }); 175 config_pin!(io0);
121 r.psel.io2.write(|w| unsafe { w.bits(io2.psel_bits()) }); 176 config_pin!(io1);
122 r.psel.io3.write(|w| unsafe { w.bits(io3.psel_bits()) }); 177 config_pin!(io2);
178 config_pin!(io3);
123 179
124 r.ifconfig0.write(|w| { 180 r.ifconfig0.write(|w| {
125 w.addrmode().variant(config.address_mode); 181 w.addrmode().variant(config.address_mode);
@@ -151,16 +207,16 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> {
151 w 207 w
152 }); 208 });
153 209
154 irq.set_handler(Self::on_interrupt); 210 T::Interrupt::unpend();
155 irq.unpend(); 211 unsafe { T::Interrupt::enable() };
156 irq.enable();
157 212
158 // Enable it 213 // Enable it
159 r.enable.write(|w| w.enable().enabled()); 214 r.enable.write(|w| w.enable().enabled());
160 215
161 let mut res = Self { 216 let res = Self {
217 _peri: qspi,
162 dpm_enabled: config.deep_power_down.is_some(), 218 dpm_enabled: config.deep_power_down.is_some(),
163 irq, 219 capacity: config.capacity,
164 }; 220 };
165 221
166 r.events_ready.reset(); 222 r.events_ready.reset();
@@ -168,23 +224,14 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> {
168 224
169 r.tasks_activate.write(|w| w.tasks_activate().bit(true)); 225 r.tasks_activate.write(|w| w.tasks_activate().bit(true));
170 226
171 res.blocking_wait_ready(); 227 Self::blocking_wait_ready();
172 228
173 res 229 res
174 } 230 }
175 231
176 fn on_interrupt(_: *mut ()) { 232 /// Do a custom QSPI instruction.
177 let r = T::regs();
178 let s = T::state();
179
180 if r.events_ready.read().bits() != 0 {
181 s.ready_waker.wake();
182 r.intenclr.write(|w| w.ready().clear());
183 }
184 }
185
186 pub async fn custom_instruction(&mut self, opcode: u8, req: &[u8], resp: &mut [u8]) -> Result<(), Error> { 233 pub async fn custom_instruction(&mut self, opcode: u8, req: &[u8], resp: &mut [u8]) -> Result<(), Error> {
187 let bomb = DropBomb::new(); 234 let ondrop = OnDrop::new(Self::blocking_wait_ready);
188 235
189 let len = core::cmp::max(req.len(), resp.len()) as u8; 236 let len = core::cmp::max(req.len(), resp.len()) as u8;
190 self.custom_instruction_start(opcode, req, len)?; 237 self.custom_instruction_start(opcode, req, len)?;
@@ -193,16 +240,17 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> {
193 240
194 self.custom_instruction_finish(resp)?; 241 self.custom_instruction_finish(resp)?;
195 242
196 bomb.defuse(); 243 ondrop.defuse();
197 244
198 Ok(()) 245 Ok(())
199 } 246 }
200 247
248 /// Do a custom QSPI instruction, blocking version.
201 pub fn blocking_custom_instruction(&mut self, opcode: u8, req: &[u8], resp: &mut [u8]) -> Result<(), Error> { 249 pub fn blocking_custom_instruction(&mut self, opcode: u8, req: &[u8], resp: &mut [u8]) -> Result<(), Error> {
202 let len = core::cmp::max(req.len(), resp.len()) as u8; 250 let len = core::cmp::max(req.len(), resp.len()) as u8;
203 self.custom_instruction_start(opcode, req, len)?; 251 self.custom_instruction_start(opcode, req, len)?;
204 252
205 self.blocking_wait_ready(); 253 Self::blocking_wait_ready();
206 254
207 self.custom_instruction_finish(resp)?; 255 self.custom_instruction_finish(resp)?;
208 256
@@ -269,7 +317,7 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> {
269 poll_fn(move |cx| { 317 poll_fn(move |cx| {
270 let r = T::regs(); 318 let r = T::regs();
271 let s = T::state(); 319 let s = T::state();
272 s.ready_waker.register(cx.waker()); 320 s.waker.register(cx.waker());
273 if r.events_ready.read().bits() != 0 { 321 if r.events_ready.read().bits() != 0 {
274 return Poll::Ready(()); 322 return Poll::Ready(());
275 } 323 }
@@ -278,7 +326,7 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> {
278 .await 326 .await
279 } 327 }
280 328
281 fn blocking_wait_ready(&mut self) { 329 fn blocking_wait_ready() {
282 loop { 330 loop {
283 let r = T::regs(); 331 let r = T::regs();
284 if r.events_ready.read().bits() != 0 { 332 if r.events_ready.read().bits() != 0 {
@@ -287,17 +335,15 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> {
287 } 335 }
288 } 336 }
289 337
290 fn start_read(&mut self, address: usize, data: &mut [u8]) -> Result<(), Error> { 338 fn start_read(&mut self, address: u32, data: &mut [u8]) -> Result<(), Error> {
339 // TODO: Return these as errors instead.
291 assert_eq!(data.as_ptr() as u32 % 4, 0); 340 assert_eq!(data.as_ptr() as u32 % 4, 0);
292 assert_eq!(data.len() as u32 % 4, 0); 341 assert_eq!(data.len() as u32 % 4, 0);
293 assert_eq!(address as u32 % 4, 0); 342 assert_eq!(address % 4, 0);
294 if address > FLASH_SIZE {
295 return Err(Error::OutOfBounds);
296 }
297 343
298 let r = T::regs(); 344 let r = T::regs();
299 345
300 r.read.src.write(|w| unsafe { w.src().bits(address as u32) }); 346 r.read.src.write(|w| unsafe { w.src().bits(address) });
301 r.read.dst.write(|w| unsafe { w.dst().bits(data.as_ptr() as u32) }); 347 r.read.dst.write(|w| unsafe { w.dst().bits(data.as_ptr() as u32) });
302 r.read.cnt.write(|w| unsafe { w.cnt().bits(data.len() as u32) }); 348 r.read.cnt.write(|w| unsafe { w.cnt().bits(data.len() as u32) });
303 349
@@ -308,18 +354,15 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> {
308 Ok(()) 354 Ok(())
309 } 355 }
310 356
311 fn start_write(&mut self, address: usize, data: &[u8]) -> Result<(), Error> { 357 fn start_write(&mut self, address: u32, data: &[u8]) -> Result<(), Error> {
358 // TODO: Return these as errors instead.
312 assert_eq!(data.as_ptr() as u32 % 4, 0); 359 assert_eq!(data.as_ptr() as u32 % 4, 0);
313 assert_eq!(data.len() as u32 % 4, 0); 360 assert_eq!(data.len() as u32 % 4, 0);
314 assert_eq!(address as u32 % 4, 0); 361 assert_eq!(address % 4, 0);
315
316 if address > FLASH_SIZE {
317 return Err(Error::OutOfBounds);
318 }
319 362
320 let r = T::regs(); 363 let r = T::regs();
321 r.write.src.write(|w| unsafe { w.src().bits(data.as_ptr() as u32) }); 364 r.write.src.write(|w| unsafe { w.src().bits(data.as_ptr() as u32) });
322 r.write.dst.write(|w| unsafe { w.dst().bits(address as u32) }); 365 r.write.dst.write(|w| unsafe { w.dst().bits(address) });
323 r.write.cnt.write(|w| unsafe { w.cnt().bits(data.len() as u32) }); 366 r.write.cnt.write(|w| unsafe { w.cnt().bits(data.len() as u32) });
324 367
325 r.events_ready.reset(); 368 r.events_ready.reset();
@@ -329,14 +372,12 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> {
329 Ok(()) 372 Ok(())
330 } 373 }
331 374
332 fn start_erase(&mut self, address: usize) -> Result<(), Error> { 375 fn start_erase(&mut self, address: u32) -> Result<(), Error> {
333 assert_eq!(address as u32 % 4096, 0); 376 // TODO: Return these as errors instead.
334 if address > FLASH_SIZE { 377 assert_eq!(address % 4096, 0);
335 return Err(Error::OutOfBounds);
336 }
337 378
338 let r = T::regs(); 379 let r = T::regs();
339 r.erase.ptr.write(|w| unsafe { w.ptr().bits(address as u32) }); 380 r.erase.ptr.write(|w| unsafe { w.ptr().bits(address) });
340 r.erase.len.write(|w| w.len()._4kb()); 381 r.erase.len.write(|w| w.len()._4kb());
341 382
342 r.events_ready.reset(); 383 r.events_ready.reset();
@@ -346,59 +387,122 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> {
346 Ok(()) 387 Ok(())
347 } 388 }
348 389
349 pub async fn read(&mut self, address: usize, data: &mut [u8]) -> Result<(), Error> { 390 /// Raw QSPI read.
350 let bomb = DropBomb::new(); 391 ///
392 /// The difference with `read` is that this does not do bounds checks
393 /// against the flash capacity. It is intended for use when QSPI is used as
394 /// a raw bus, not with flash memory.
395 pub async fn read_raw(&mut self, address: u32, data: &mut [u8]) -> Result<(), Error> {
396 let ondrop = OnDrop::new(Self::blocking_wait_ready);
351 397
352 self.start_read(address, data)?; 398 self.start_read(address, data)?;
353 self.wait_ready().await; 399 self.wait_ready().await;
354 400
355 bomb.defuse(); 401 ondrop.defuse();
356 402
357 Ok(()) 403 Ok(())
358 } 404 }
359 405
360 pub async fn write(&mut self, address: usize, data: &[u8]) -> Result<(), Error> { 406 /// Raw QSPI write.
361 let bomb = DropBomb::new(); 407 ///
408 /// The difference with `write` is that this does not do bounds checks
409 /// against the flash capacity. It is intended for use when QSPI is used as
410 /// a raw bus, not with flash memory.
411 pub async fn write_raw(&mut self, address: u32, data: &[u8]) -> Result<(), Error> {
412 let ondrop = OnDrop::new(Self::blocking_wait_ready);
362 413
363 self.start_write(address, data)?; 414 self.start_write(address, data)?;
364 self.wait_ready().await; 415 self.wait_ready().await;
365 416
366 bomb.defuse(); 417 ondrop.defuse();
367 418
368 Ok(()) 419 Ok(())
369 } 420 }
370 421
371 pub async fn erase(&mut self, address: usize) -> Result<(), Error> { 422 /// Raw QSPI read, blocking version.
372 let bomb = DropBomb::new(); 423 ///
424 /// The difference with `blocking_read` is that this does not do bounds checks
425 /// against the flash capacity. It is intended for use when QSPI is used as
426 /// a raw bus, not with flash memory.
427 pub fn blocking_read_raw(&mut self, address: u32, data: &mut [u8]) -> Result<(), Error> {
428 self.start_read(address, data)?;
429 Self::blocking_wait_ready();
430 Ok(())
431 }
432
433 /// Raw QSPI write, blocking version.
434 ///
435 /// The difference with `blocking_write` is that this does not do bounds checks
436 /// against the flash capacity. It is intended for use when QSPI is used as
437 /// a raw bus, not with flash memory.
438 pub fn blocking_write_raw(&mut self, address: u32, data: &[u8]) -> Result<(), Error> {
439 self.start_write(address, data)?;
440 Self::blocking_wait_ready();
441 Ok(())
442 }
443
444 /// Read data from the flash memory.
445 pub async fn read(&mut self, address: u32, data: &mut [u8]) -> Result<(), Error> {
446 self.bounds_check(address, data.len())?;
447 self.read_raw(address, data).await
448 }
449
450 /// Write data to the flash memory.
451 pub async fn write(&mut self, address: u32, data: &[u8]) -> Result<(), Error> {
452 self.bounds_check(address, data.len())?;
453 self.write_raw(address, data).await
454 }
455
456 /// Erase a sector on the flash memory.
457 pub async fn erase(&mut self, address: u32) -> Result<(), Error> {
458 if address >= self.capacity {
459 return Err(Error::OutOfBounds);
460 }
461
462 let ondrop = OnDrop::new(Self::blocking_wait_ready);
373 463
374 self.start_erase(address)?; 464 self.start_erase(address)?;
375 self.wait_ready().await; 465 self.wait_ready().await;
376 466
377 bomb.defuse(); 467 ondrop.defuse();
378 468
379 Ok(()) 469 Ok(())
380 } 470 }
381 471
382 pub fn blocking_read(&mut self, address: usize, data: &mut [u8]) -> Result<(), Error> { 472 /// Read data from the flash memory, blocking version.
383 self.start_read(address, data)?; 473 pub fn blocking_read(&mut self, address: u32, data: &mut [u8]) -> Result<(), Error> {
384 self.blocking_wait_ready(); 474 self.bounds_check(address, data.len())?;
385 Ok(()) 475 self.blocking_read_raw(address, data)
386 } 476 }
387 477
388 pub fn blocking_write(&mut self, address: usize, data: &[u8]) -> Result<(), Error> { 478 /// Write data to the flash memory, blocking version.
389 self.start_write(address, data)?; 479 pub fn blocking_write(&mut self, address: u32, data: &[u8]) -> Result<(), Error> {
390 self.blocking_wait_ready(); 480 self.bounds_check(address, data.len())?;
391 Ok(()) 481 self.blocking_write_raw(address, data)
392 } 482 }
393 483
394 pub fn blocking_erase(&mut self, address: usize) -> Result<(), Error> { 484 /// Erase a sector on the flash memory, blocking version.
485 pub fn blocking_erase(&mut self, address: u32) -> Result<(), Error> {
486 if address >= self.capacity {
487 return Err(Error::OutOfBounds);
488 }
489
395 self.start_erase(address)?; 490 self.start_erase(address)?;
396 self.blocking_wait_ready(); 491 Self::blocking_wait_ready();
492 Ok(())
493 }
494
495 fn bounds_check(&self, address: u32, len: usize) -> Result<(), Error> {
496 let len_u32: u32 = len.try_into().map_err(|_| Error::OutOfBounds)?;
497 let end_address = address.checked_add(len_u32).ok_or(Error::OutOfBounds)?;
498 if end_address > self.capacity {
499 return Err(Error::OutOfBounds);
500 }
397 Ok(()) 501 Ok(())
398 } 502 }
399} 503}
400 504
401impl<'d, T: Instance, const FLASH_SIZE: usize> Drop for Qspi<'d, T, FLASH_SIZE> { 505impl<'d, T: Instance> Drop for Qspi<'d, T> {
402 fn drop(&mut self) { 506 fn drop(&mut self) {
403 let r = T::regs(); 507 let r = T::regs();
404 508
@@ -428,8 +532,6 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Drop for Qspi<'d, T, FLASH_SIZE>
428 532
429 r.enable.write(|w| w.enable().disabled()); 533 r.enable.write(|w| w.enable().disabled());
430 534
431 self.irq.disable();
432
433 // Note: we do NOT deconfigure CSN here. If DPM is in use and we disconnect CSN, 535 // Note: we do NOT deconfigure CSN here. If DPM is in use and we disconnect CSN,
434 // leaving it floating, the flash chip might read it as zero which would cause it to 536 // leaving it floating, the flash chip might read it as zero which would cause it to
435 // spuriously exit DPM. 537 // spuriously exit DPM.
@@ -443,9 +545,7 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Drop for Qspi<'d, T, FLASH_SIZE>
443 } 545 }
444} 546}
445 547
446use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; 548impl<'d, T: Instance> ErrorType for Qspi<'d, T> {
447
448impl<'d, T: Instance, const FLASH_SIZE: usize> ErrorType for Qspi<'d, T, FLASH_SIZE> {
449 type Error = Error; 549 type Error = Error;
450} 550}
451 551
@@ -455,72 +555,66 @@ impl NorFlashError for Error {
455 } 555 }
456} 556}
457 557
458impl<'d, T: Instance, const FLASH_SIZE: usize> ReadNorFlash for Qspi<'d, T, FLASH_SIZE> { 558impl<'d, T: Instance> ReadNorFlash for Qspi<'d, T> {
459 const READ_SIZE: usize = 4; 559 const READ_SIZE: usize = 4;
460 560
461 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { 561 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
462 self.blocking_read(offset as usize, bytes)?; 562 self.blocking_read(offset, bytes)?;
463 Ok(()) 563 Ok(())
464 } 564 }
465 565
466 fn capacity(&self) -> usize { 566 fn capacity(&self) -> usize {
467 FLASH_SIZE 567 self.capacity as usize
468 } 568 }
469} 569}
470 570
471impl<'d, T: Instance, const FLASH_SIZE: usize> NorFlash for Qspi<'d, T, FLASH_SIZE> { 571impl<'d, T: Instance> NorFlash for Qspi<'d, T> {
472 const WRITE_SIZE: usize = 4; 572 const WRITE_SIZE: usize = 4;
473 const ERASE_SIZE: usize = 4096; 573 const ERASE_SIZE: usize = 4096;
474 574
475 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { 575 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
476 for address in (from as usize..to as usize).step_by(<Self as NorFlash>::ERASE_SIZE) { 576 for address in (from..to).step_by(<Self as NorFlash>::ERASE_SIZE) {
477 self.blocking_erase(address)?; 577 self.blocking_erase(address)?;
478 } 578 }
479 Ok(()) 579 Ok(())
480 } 580 }
481 581
482 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { 582 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
483 self.blocking_write(offset as usize, bytes)?; 583 self.blocking_write(offset, bytes)?;
484 Ok(()) 584 Ok(())
485 } 585 }
486} 586}
487 587
488cfg_if::cfg_if! { 588#[cfg(feature = "nightly")]
489 if #[cfg(feature = "nightly")] 589mod _eh1 {
490 { 590 use embedded_storage_async::nor_flash::{NorFlash as AsyncNorFlash, ReadNorFlash as AsyncReadNorFlash};
491 use embedded_storage_async::nor_flash::{AsyncNorFlash, AsyncReadNorFlash};
492 use core::future::Future;
493 591
494 impl<'d, T: Instance, const FLASH_SIZE: usize> AsyncNorFlash for Qspi<'d, T, FLASH_SIZE> { 592 use super::*;
495 const WRITE_SIZE: usize = <Self as NorFlash>::WRITE_SIZE;
496 const ERASE_SIZE: usize = <Self as NorFlash>::ERASE_SIZE;
497 593
498 type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; 594 impl<'d, T: Instance> AsyncNorFlash for Qspi<'d, T> {
499 fn write<'a>(&'a mut self, offset: u32, data: &'a [u8]) -> Self::WriteFuture<'a> { 595 const WRITE_SIZE: usize = <Self as NorFlash>::WRITE_SIZE;
500 async move { self.write(offset as usize, data).await } 596 const ERASE_SIZE: usize = <Self as NorFlash>::ERASE_SIZE;
501 }
502 597
503 type EraseFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; 598 async fn write(&mut self, offset: u32, data: &[u8]) -> Result<(), Self::Error> {
504 fn erase<'a>(&'a mut self, from: u32, to: u32) -> Self::EraseFuture<'a> { 599 self.write(offset, data).await
505 async move {
506 for address in (from as usize..to as usize).step_by(<Self as AsyncNorFlash>::ERASE_SIZE) {
507 self.erase(address).await?
508 }
509 Ok(())
510 }
511 }
512 } 600 }
513 601
514 impl<'d, T: Instance, const FLASH_SIZE: usize> AsyncReadNorFlash for Qspi<'d, T, FLASH_SIZE> { 602 async fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
515 const READ_SIZE: usize = 4; 603 for address in (from..to).step_by(<Self as AsyncNorFlash>::ERASE_SIZE) {
516 type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; 604 self.erase(address).await?
517 fn read<'a>(&'a mut self, address: u32, data: &'a mut [u8]) -> Self::ReadFuture<'a> {
518 async move { self.read(address as usize, data).await }
519 } 605 }
606 Ok(())
607 }
608 }
520 609
521 fn capacity(&self) -> usize { 610 impl<'d, T: Instance> AsyncReadNorFlash for Qspi<'d, T> {
522 FLASH_SIZE 611 const READ_SIZE: usize = 4;
523 } 612 async fn read(&mut self, address: u32, data: &mut [u8]) -> Result<(), Self::Error> {
613 self.read(address, data).await
614 }
615
616 fn capacity(&self) -> usize {
617 self.capacity as usize
524 } 618 }
525 } 619 }
526} 620}
@@ -528,33 +622,35 @@ cfg_if::cfg_if! {
528pub(crate) mod sealed { 622pub(crate) mod sealed {
529 use embassy_sync::waitqueue::AtomicWaker; 623 use embassy_sync::waitqueue::AtomicWaker;
530 624
531 use super::*; 625 /// Peripheral static state
532
533 pub struct State { 626 pub struct State {
534 pub ready_waker: AtomicWaker, 627 pub waker: AtomicWaker,
535 } 628 }
629
536 impl State { 630 impl State {
537 pub const fn new() -> Self { 631 pub const fn new() -> Self {
538 Self { 632 Self {
539 ready_waker: AtomicWaker::new(), 633 waker: AtomicWaker::new(),
540 } 634 }
541 } 635 }
542 } 636 }
543 637
544 pub trait Instance { 638 pub trait Instance {
545 fn regs() -> &'static pac::qspi::RegisterBlock; 639 fn regs() -> &'static crate::pac::qspi::RegisterBlock;
546 fn state() -> &'static State; 640 fn state() -> &'static State;
547 } 641 }
548} 642}
549 643
550pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static { 644/// QSPI peripheral instance.
551 type Interrupt: Interrupt; 645pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
646 /// Interrupt for this peripheral.
647 type Interrupt: interrupt::typelevel::Interrupt;
552} 648}
553 649
554macro_rules! impl_qspi { 650macro_rules! impl_qspi {
555 ($type:ident, $pac_type:ident, $irq:ident) => { 651 ($type:ident, $pac_type:ident, $irq:ident) => {
556 impl crate::qspi::sealed::Instance for peripherals::$type { 652 impl crate::qspi::sealed::Instance for peripherals::$type {
557 fn regs() -> &'static pac::qspi::RegisterBlock { 653 fn regs() -> &'static crate::pac::qspi::RegisterBlock {
558 unsafe { &*pac::$pac_type::ptr() } 654 unsafe { &*pac::$pac_type::ptr() }
559 } 655 }
560 fn state() -> &'static crate::qspi::sealed::State { 656 fn state() -> &'static crate::qspi::sealed::State {
@@ -563,7 +659,7 @@ macro_rules! impl_qspi {
563 } 659 }
564 } 660 }
565 impl crate::qspi::Instance for peripherals::$type { 661 impl crate::qspi::Instance for peripherals::$type {
566 type Interrupt = crate::interrupt::$irq; 662 type Interrupt = crate::interrupt::typelevel::$irq;
567 } 663 }
568 }; 664 };
569} 665}
diff --git a/embassy-nrf/src/rng.rs b/embassy-nrf/src/rng.rs
index 42da51d0f..923b8b467 100644
--- a/embassy-nrf/src/rng.rs
+++ b/embassy-nrf/src/rng.rs
@@ -1,3 +1,9 @@
1//! Random Number Generator (RNG) driver.
2
3#![macro_use]
4
5use core::future::poll_fn;
6use core::marker::PhantomData;
1use core::ptr; 7use core::ptr;
2use core::sync::atomic::{AtomicPtr, Ordering}; 8use core::sync::atomic::{AtomicPtr, Ordering};
3use core::task::Poll; 9use core::task::Poll;
@@ -5,77 +11,37 @@ use core::task::Poll;
5use embassy_hal_common::drop::OnDrop; 11use embassy_hal_common::drop::OnDrop;
6use embassy_hal_common::{into_ref, PeripheralRef}; 12use embassy_hal_common::{into_ref, PeripheralRef};
7use embassy_sync::waitqueue::AtomicWaker; 13use embassy_sync::waitqueue::AtomicWaker;
8use futures::future::poll_fn;
9 14
10use crate::interrupt::InterruptExt; 15use crate::interrupt::typelevel::Interrupt;
11use crate::peripherals::RNG; 16use crate::{interrupt, Peripheral};
12use crate::{interrupt, pac, Peripheral};
13 17
14impl RNG { 18/// Interrupt handler.
15 fn regs() -> &'static pac::rng::RegisterBlock { 19pub struct InterruptHandler<T: Instance> {
16 unsafe { &*pac::RNG::ptr() } 20 _phantom: PhantomData<T>,
17 }
18} 21}
19 22
20static STATE: State = State { 23impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
21 ptr: AtomicPtr::new(ptr::null_mut()), 24 unsafe fn on_interrupt() {
22 end: AtomicPtr::new(ptr::null_mut()), 25 let s = T::state();
23 waker: AtomicWaker::new(), 26 let r = T::regs();
24};
25
26struct State {
27 ptr: AtomicPtr<u8>,
28 end: AtomicPtr<u8>,
29 waker: AtomicWaker,
30}
31
32/// A wrapper around an nRF RNG peripheral.
33///
34/// It has a non-blocking API, and a blocking api through `rand`.
35pub struct Rng<'d> {
36 irq: PeripheralRef<'d, interrupt::RNG>,
37}
38
39impl<'d> Rng<'d> {
40 /// Creates a new RNG driver from the `RNG` peripheral and interrupt.
41 ///
42 /// SAFETY: The future returned from `fill_bytes` must not have its lifetime end without running its destructor,
43 /// e.g. using `mem::forget`.
44 ///
45 /// The synchronous API is safe.
46 pub fn new(_rng: impl Peripheral<P = RNG> + 'd, irq: impl Peripheral<P = interrupt::RNG> + 'd) -> Self {
47 into_ref!(irq);
48 27
49 let this = Self { irq };
50
51 this.stop();
52 this.disable_irq();
53
54 this.irq.set_handler(Self::on_interrupt);
55 this.irq.unpend();
56 this.irq.enable();
57
58 this
59 }
60
61 fn on_interrupt(_: *mut ()) {
62 // Clear the event. 28 // Clear the event.
63 RNG::regs().events_valrdy.reset(); 29 r.events_valrdy.reset();
64 30
65 // Mutate the slice within a critical section, 31 // Mutate the slice within a critical section,
66 // so that the future isn't dropped in between us loading the pointer and actually dereferencing it. 32 // so that the future isn't dropped in between us loading the pointer and actually dereferencing it.
67 let (ptr, end) = critical_section::with(|_| { 33 let (ptr, end) = critical_section::with(|_| {
68 let ptr = STATE.ptr.load(Ordering::Relaxed); 34 let ptr = s.ptr.load(Ordering::Relaxed);
69 // We need to make sure we haven't already filled the whole slice, 35 // We need to make sure we haven't already filled the whole slice,
70 // in case the interrupt fired again before the executor got back to the future. 36 // in case the interrupt fired again before the executor got back to the future.
71 let end = STATE.end.load(Ordering::Relaxed); 37 let end = s.end.load(Ordering::Relaxed);
72 if !ptr.is_null() && ptr != end { 38 if !ptr.is_null() && ptr != end {
73 // If the future was dropped, the pointer would have been set to null, 39 // If the future was dropped, the pointer would have been set to null,
74 // so we're still good to mutate the slice. 40 // so we're still good to mutate the slice.
75 // The safety contract of `Rng::new` means that the future can't have been dropped 41 // The safety contract of `Rng::new` means that the future can't have been dropped
76 // without calling its destructor. 42 // without calling its destructor.
77 unsafe { 43 unsafe {
78 *ptr = RNG::regs().value.read().value().bits(); 44 *ptr = r.value.read().value().bits();
79 } 45 }
80 } 46 }
81 (ptr, end) 47 (ptr, end)
@@ -88,15 +54,15 @@ impl<'d> Rng<'d> {
88 } 54 }
89 55
90 let new_ptr = unsafe { ptr.add(1) }; 56 let new_ptr = unsafe { ptr.add(1) };
91 match STATE 57 match s
92 .ptr 58 .ptr
93 .compare_exchange(ptr, new_ptr, Ordering::Relaxed, Ordering::Relaxed) 59 .compare_exchange(ptr, new_ptr, Ordering::Relaxed, Ordering::Relaxed)
94 { 60 {
95 Ok(_) => { 61 Ok(_) => {
96 let end = STATE.end.load(Ordering::Relaxed); 62 let end = s.end.load(Ordering::Relaxed);
97 // It doesn't matter if `end` was changed under our feet, because then this will just be false. 63 // It doesn't matter if `end` was changed under our feet, because then this will just be false.
98 if new_ptr == end { 64 if new_ptr == end {
99 STATE.waker.wake(); 65 s.waker.wake();
100 } 66 }
101 } 67 }
102 Err(_) => { 68 Err(_) => {
@@ -105,21 +71,53 @@ impl<'d> Rng<'d> {
105 } 71 }
106 } 72 }
107 } 73 }
74}
75
76/// A wrapper around an nRF RNG peripheral.
77///
78/// It has a non-blocking API, and a blocking api through `rand`.
79pub struct Rng<'d, T: Instance> {
80 _peri: PeripheralRef<'d, T>,
81}
82
83impl<'d, T: Instance> Rng<'d, T> {
84 /// Creates a new RNG driver from the `RNG` peripheral and interrupt.
85 ///
86 /// SAFETY: The future returned from `fill_bytes` must not have its lifetime end without running its destructor,
87 /// e.g. using `mem::forget`.
88 ///
89 /// The synchronous API is safe.
90 pub fn new(
91 rng: impl Peripheral<P = T> + 'd,
92 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
93 ) -> Self {
94 into_ref!(rng);
95
96 let this = Self { _peri: rng };
97
98 this.stop();
99 this.disable_irq();
100
101 T::Interrupt::unpend();
102 unsafe { T::Interrupt::enable() };
103
104 this
105 }
108 106
109 fn stop(&self) { 107 fn stop(&self) {
110 RNG::regs().tasks_stop.write(|w| unsafe { w.bits(1) }) 108 T::regs().tasks_stop.write(|w| unsafe { w.bits(1) })
111 } 109 }
112 110
113 fn start(&self) { 111 fn start(&self) {
114 RNG::regs().tasks_start.write(|w| unsafe { w.bits(1) }) 112 T::regs().tasks_start.write(|w| unsafe { w.bits(1) })
115 } 113 }
116 114
117 fn enable_irq(&self) { 115 fn enable_irq(&self) {
118 RNG::regs().intenset.write(|w| w.valrdy().set()); 116 T::regs().intenset.write(|w| w.valrdy().set());
119 } 117 }
120 118
121 fn disable_irq(&self) { 119 fn disable_irq(&self) {
122 RNG::regs().intenclr.write(|w| w.valrdy().clear()); 120 T::regs().intenclr.write(|w| w.valrdy().clear());
123 } 121 }
124 122
125 /// Enable or disable the RNG's bias correction. 123 /// Enable or disable the RNG's bias correction.
@@ -128,20 +126,23 @@ impl<'d> Rng<'d> {
128 /// However, this makes the generation of numbers slower. 126 /// However, this makes the generation of numbers slower.
129 /// 127 ///
130 /// Defaults to disabled. 128 /// Defaults to disabled.
131 pub fn bias_correction(&self, enable: bool) { 129 pub fn set_bias_correction(&self, enable: bool) {
132 RNG::regs().config.write(|w| w.dercen().bit(enable)) 130 T::regs().config.write(|w| w.dercen().bit(enable))
133 } 131 }
134 132
133 /// Fill the buffer with random bytes.
135 pub async fn fill_bytes(&mut self, dest: &mut [u8]) { 134 pub async fn fill_bytes(&mut self, dest: &mut [u8]) {
136 if dest.len() == 0 { 135 if dest.len() == 0 {
137 return; // Nothing to fill 136 return; // Nothing to fill
138 } 137 }
139 138
139 let s = T::state();
140
140 let range = dest.as_mut_ptr_range(); 141 let range = dest.as_mut_ptr_range();
141 // Even if we've preempted the interrupt, it can't preempt us again, 142 // Even if we've preempted the interrupt, it can't preempt us again,
142 // so we don't need to worry about the order we write these in. 143 // so we don't need to worry about the order we write these in.
143 STATE.ptr.store(range.start, Ordering::Relaxed); 144 s.ptr.store(range.start, Ordering::Relaxed);
144 STATE.end.store(range.end, Ordering::Relaxed); 145 s.end.store(range.end, Ordering::Relaxed);
145 146
146 self.enable_irq(); 147 self.enable_irq();
147 self.start(); 148 self.start();
@@ -151,16 +152,16 @@ impl<'d> Rng<'d> {
151 self.disable_irq(); 152 self.disable_irq();
152 153
153 // The interrupt is now disabled and can't preempt us anymore, so the order doesn't matter here. 154 // The interrupt is now disabled and can't preempt us anymore, so the order doesn't matter here.
154 STATE.ptr.store(ptr::null_mut(), Ordering::Relaxed); 155 s.ptr.store(ptr::null_mut(), Ordering::Relaxed);
155 STATE.end.store(ptr::null_mut(), Ordering::Relaxed); 156 s.end.store(ptr::null_mut(), Ordering::Relaxed);
156 }); 157 });
157 158
158 poll_fn(|cx| { 159 poll_fn(|cx| {
159 STATE.waker.register(cx.waker()); 160 s.waker.register(cx.waker());
160 161
161 // The interrupt will never modify `end`, so load it first and then get the most up-to-date `ptr`. 162 // The interrupt will never modify `end`, so load it first and then get the most up-to-date `ptr`.
162 let end = STATE.end.load(Ordering::Relaxed); 163 let end = s.end.load(Ordering::Relaxed);
163 let ptr = STATE.ptr.load(Ordering::Relaxed); 164 let ptr = s.ptr.load(Ordering::Relaxed);
164 165
165 if ptr == end { 166 if ptr == end {
166 // We're done. 167 // We're done.
@@ -175,11 +176,12 @@ impl<'d> Rng<'d> {
175 drop(on_drop); 176 drop(on_drop);
176 } 177 }
177 178
179 /// Fill the buffer with random bytes, blocking version.
178 pub fn blocking_fill_bytes(&mut self, dest: &mut [u8]) { 180 pub fn blocking_fill_bytes(&mut self, dest: &mut [u8]) {
179 self.start(); 181 self.start();
180 182
181 for byte in dest.iter_mut() { 183 for byte in dest.iter_mut() {
182 let regs = RNG::regs(); 184 let regs = T::regs();
183 while regs.events_valrdy.read().bits() == 0 {} 185 while regs.events_valrdy.read().bits() == 0 {}
184 regs.events_valrdy.reset(); 186 regs.events_valrdy.reset();
185 *byte = regs.value.read().value().bits(); 187 *byte = regs.value.read().value().bits();
@@ -189,13 +191,16 @@ impl<'d> Rng<'d> {
189 } 191 }
190} 192}
191 193
192impl<'d> Drop for Rng<'d> { 194impl<'d, T: Instance> Drop for Rng<'d, T> {
193 fn drop(&mut self) { 195 fn drop(&mut self) {
194 self.irq.disable() 196 self.stop();
197 let s = T::state();
198 s.ptr.store(ptr::null_mut(), Ordering::Relaxed);
199 s.end.store(ptr::null_mut(), Ordering::Relaxed);
195 } 200 }
196} 201}
197 202
198impl<'d> rand_core::RngCore for Rng<'d> { 203impl<'d, T: Instance> rand_core::RngCore for Rng<'d, T> {
199 fn fill_bytes(&mut self, dest: &mut [u8]) { 204 fn fill_bytes(&mut self, dest: &mut [u8]) {
200 self.blocking_fill_bytes(dest); 205 self.blocking_fill_bytes(dest);
201 } 206 }
@@ -219,4 +224,53 @@ impl<'d> rand_core::RngCore for Rng<'d> {
219 } 224 }
220} 225}
221 226
222impl<'d> rand_core::CryptoRng for Rng<'d> {} 227impl<'d, T: Instance> rand_core::CryptoRng for Rng<'d, T> {}
228
229pub(crate) mod sealed {
230 use super::*;
231
232 /// Peripheral static state
233 pub struct State {
234 pub ptr: AtomicPtr<u8>,
235 pub end: AtomicPtr<u8>,
236 pub waker: AtomicWaker,
237 }
238
239 impl State {
240 pub const fn new() -> Self {
241 Self {
242 ptr: AtomicPtr::new(ptr::null_mut()),
243 end: AtomicPtr::new(ptr::null_mut()),
244 waker: AtomicWaker::new(),
245 }
246 }
247 }
248
249 pub trait Instance {
250 fn regs() -> &'static crate::pac::rng::RegisterBlock;
251 fn state() -> &'static State;
252 }
253}
254
255/// RNG peripheral instance.
256pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
257 /// Interrupt for this peripheral.
258 type Interrupt: interrupt::typelevel::Interrupt;
259}
260
261macro_rules! impl_rng {
262 ($type:ident, $pac_type:ident, $irq:ident) => {
263 impl crate::rng::sealed::Instance for peripherals::$type {
264 fn regs() -> &'static crate::pac::rng::RegisterBlock {
265 unsafe { &*pac::$pac_type::ptr() }
266 }
267 fn state() -> &'static crate::rng::sealed::State {
268 static STATE: crate::rng::sealed::State = crate::rng::sealed::State::new();
269 &STATE
270 }
271 }
272 impl crate::rng::Instance for peripherals::$type {
273 type Interrupt = crate::interrupt::typelevel::$irq;
274 }
275 };
276}
diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs
index 7dc66349e..23292924c 100644
--- a/embassy-nrf/src/saadc.rs
+++ b/embassy-nrf/src/saadc.rs
@@ -1,11 +1,14 @@
1//! Successive Approximation Analog-to-Digital Converter (SAADC) driver.
2
1#![macro_use] 3#![macro_use]
2 4
5use core::future::poll_fn;
3use core::sync::atomic::{compiler_fence, Ordering}; 6use core::sync::atomic::{compiler_fence, Ordering};
4use core::task::Poll; 7use core::task::Poll;
5 8
9use embassy_hal_common::drop::OnDrop;
6use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; 10use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef};
7use embassy_sync::waitqueue::AtomicWaker; 11use embassy_sync::waitqueue::AtomicWaker;
8use futures::future::poll_fn;
9use pac::{saadc, SAADC}; 12use pac::{saadc, SAADC};
10use saadc::ch::config::{GAIN_A, REFSEL_A, RESP_A, TACQ_A}; 13use saadc::ch::config::{GAIN_A, REFSEL_A, RESP_A, TACQ_A};
11// We treat the positive and negative channels with the same enum values to keep our type tidy and given they are the same 14// We treat the positive and negative channels with the same enum values to keep our type tidy and given they are the same
@@ -19,14 +22,36 @@ use crate::ppi::{ConfigurableChannel, Event, Ppi, Task};
19use crate::timer::{Frequency, Instance as TimerInstance, Timer}; 22use crate::timer::{Frequency, Instance as TimerInstance, Timer};
20use crate::{interrupt, pac, peripherals, Peripheral}; 23use crate::{interrupt, pac, peripherals, Peripheral};
21 24
25/// SAADC error
22#[derive(Debug, Clone, Copy, PartialEq, Eq)] 26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23#[cfg_attr(feature = "defmt", derive(defmt::Format))] 27#[cfg_attr(feature = "defmt", derive(defmt::Format))]
24#[non_exhaustive] 28#[non_exhaustive]
25pub enum Error {} 29pub enum Error {}
26 30
27/// One-shot and continuous SAADC. 31/// Interrupt handler.
28pub struct Saadc<'d, const N: usize> { 32pub struct InterruptHandler {
29 _p: PeripheralRef<'d, peripherals::SAADC>, 33 _private: (),
34}
35
36impl interrupt::typelevel::Handler<interrupt::typelevel::SAADC> for InterruptHandler {
37 unsafe fn on_interrupt() {
38 let r = unsafe { &*SAADC::ptr() };
39
40 if r.events_calibratedone.read().bits() != 0 {
41 r.intenclr.write(|w| w.calibratedone().clear());
42 WAKER.wake();
43 }
44
45 if r.events_end.read().bits() != 0 {
46 r.intenclr.write(|w| w.end().clear());
47 WAKER.wake();
48 }
49
50 if r.events_started.read().bits() != 0 {
51 r.intenclr.write(|w| w.started().clear());
52 WAKER.wake();
53 }
54 }
30} 55}
31 56
32static WAKER: AtomicWaker = AtomicWaker::new(); 57static WAKER: AtomicWaker = AtomicWaker::new();
@@ -101,24 +126,29 @@ impl<'d> ChannelConfig<'d> {
101 } 126 }
102} 127}
103 128
104/// The state of a continuously running sampler. While it reflects 129/// Value returned by the SAADC callback, deciding what happens next.
105/// the progress of a sampler, it also signals what should be done
106/// next. For example, if the sampler has stopped then the Saadc implementation
107/// can then tear down its infrastructure.
108#[derive(PartialEq)] 130#[derive(PartialEq)]
109pub enum SamplerState { 131pub enum CallbackResult {
110 Sampled, 132 /// The SAADC should keep sampling and calling the callback.
111 Stopped, 133 Continue,
134 /// The SAADC should stop sampling, and return.
135 Stop,
136}
137
138/// One-shot and continuous SAADC.
139pub struct Saadc<'d, const N: usize> {
140 _p: PeripheralRef<'d, peripherals::SAADC>,
112} 141}
113 142
114impl<'d, const N: usize> Saadc<'d, N> { 143impl<'d, const N: usize> Saadc<'d, N> {
144 /// Create a new SAADC driver.
115 pub fn new( 145 pub fn new(
116 saadc: impl Peripheral<P = peripherals::SAADC> + 'd, 146 saadc: impl Peripheral<P = peripherals::SAADC> + 'd,
117 irq: impl Peripheral<P = interrupt::SAADC> + 'd, 147 _irq: impl interrupt::typelevel::Binding<interrupt::typelevel::SAADC, InterruptHandler> + 'd,
118 config: Config, 148 config: Config,
119 channel_configs: [ChannelConfig; N], 149 channel_configs: [ChannelConfig; N],
120 ) -> Self { 150 ) -> Self {
121 into_ref!(saadc, irq); 151 into_ref!(saadc);
122 152
123 let r = unsafe { &*SAADC::ptr() }; 153 let r = unsafe { &*SAADC::ptr() };
124 154
@@ -159,32 +189,12 @@ impl<'d, const N: usize> Saadc<'d, N> {
159 // Disable all events interrupts 189 // Disable all events interrupts
160 r.intenclr.write(|w| unsafe { w.bits(0x003F_FFFF) }); 190 r.intenclr.write(|w| unsafe { w.bits(0x003F_FFFF) });
161 191
162 irq.set_handler(Self::on_interrupt); 192 interrupt::SAADC.unpend();
163 irq.unpend(); 193 unsafe { interrupt::SAADC.enable() };
164 irq.enable();
165 194
166 Self { _p: saadc } 195 Self { _p: saadc }
167 } 196 }
168 197
169 fn on_interrupt(_ctx: *mut ()) {
170 let r = Self::regs();
171
172 if r.events_calibratedone.read().bits() != 0 {
173 r.intenclr.write(|w| w.calibratedone().clear());
174 WAKER.wake();
175 }
176
177 if r.events_end.read().bits() != 0 {
178 r.intenclr.write(|w| w.end().clear());
179 WAKER.wake();
180 }
181
182 if r.events_started.read().bits() != 0 {
183 r.intenclr.write(|w| w.started().clear());
184 WAKER.wake();
185 }
186 }
187
188 fn regs() -> &'static saadc::RegisterBlock { 198 fn regs() -> &'static saadc::RegisterBlock {
189 unsafe { &*SAADC::ptr() } 199 unsafe { &*SAADC::ptr() }
190 } 200 }
@@ -219,7 +229,13 @@ impl<'d, const N: usize> Saadc<'d, N> {
219 } 229 }
220 230
221 /// One shot sampling. The buffer must be the same size as the number of channels configured. 231 /// One shot sampling. The buffer must be the same size as the number of channels configured.
232 /// The sampling is stopped prior to returning in order to reduce power consumption (power
233 /// consumption remains higher if sampling is not stopped explicitly). Cancellation will
234 /// also cause the sampling to be stopped.
222 pub async fn sample(&mut self, buf: &mut [i16; N]) { 235 pub async fn sample(&mut self, buf: &mut [i16; N]) {
236 // In case the future is dropped, stop the task and wait for it to end.
237 let on_drop = OnDrop::new(Self::stop_sampling_immediately);
238
223 let r = Self::regs(); 239 let r = Self::regs();
224 240
225 // Set up the DMA 241 // Set up the DMA
@@ -251,6 +267,8 @@ impl<'d, const N: usize> Saadc<'d, N> {
251 Poll::Pending 267 Poll::Pending
252 }) 268 })
253 .await; 269 .await;
270
271 drop(on_drop);
254 } 272 }
255 273
256 /// Continuous sampling with double buffers. 274 /// Continuous sampling with double buffers.
@@ -270,7 +288,13 @@ impl<'d, const N: usize> Saadc<'d, N> {
270 /// taken to acquire the samples into a single buffer. You should measure the 288 /// taken to acquire the samples into a single buffer. You should measure the
271 /// time taken by the callback and set the sample buffer size accordingly. 289 /// time taken by the callback and set the sample buffer size accordingly.
272 /// Exceeding this time can lead to samples becoming dropped. 290 /// Exceeding this time can lead to samples becoming dropped.
273 pub async fn run_task_sampler<S, T: TimerInstance, const N0: usize>( 291 ///
292 /// The sampling is stopped prior to returning in order to reduce power consumption (power
293 /// consumption remains higher if sampling is not stopped explicitly), and to
294 /// free the buffers from being used by the peripheral. Cancellation will
295 /// also cause the sampling to be stopped.
296
297 pub async fn run_task_sampler<F, T: TimerInstance, const N0: usize>(
274 &mut self, 298 &mut self,
275 timer: &mut T, 299 timer: &mut T,
276 ppi_ch1: &mut impl ConfigurableChannel, 300 ppi_ch1: &mut impl ConfigurableChannel,
@@ -278,9 +302,9 @@ impl<'d, const N: usize> Saadc<'d, N> {
278 frequency: Frequency, 302 frequency: Frequency,
279 sample_counter: u32, 303 sample_counter: u32,
280 bufs: &mut [[[i16; N]; N0]; 2], 304 bufs: &mut [[[i16; N]; N0]; 2],
281 sampler: S, 305 callback: F,
282 ) where 306 ) where
283 S: FnMut(&[[i16; N]]) -> SamplerState, 307 F: FnMut(&[[i16; N]]) -> CallbackResult,
284 { 308 {
285 let r = Self::regs(); 309 let r = Self::regs();
286 310
@@ -291,12 +315,14 @@ impl<'d, const N: usize> Saadc<'d, N> {
291 Ppi::new_one_to_one(ppi_ch1, Event::from_reg(&r.events_end), Task::from_reg(&r.tasks_start)); 315 Ppi::new_one_to_one(ppi_ch1, Event::from_reg(&r.events_end), Task::from_reg(&r.tasks_start));
292 start_ppi.enable(); 316 start_ppi.enable();
293 317
294 let mut timer = Timer::new(timer); 318 let timer = Timer::new(timer);
295 timer.set_frequency(frequency); 319 timer.set_frequency(frequency);
296 timer.cc(0).write(sample_counter); 320 timer.cc(0).write(sample_counter);
297 timer.cc(0).short_compare_clear(); 321 timer.cc(0).short_compare_clear();
298 322
299 let mut sample_ppi = Ppi::new_one_to_one(ppi_ch2, timer.cc(0).event_compare(), Task::from_reg(&r.tasks_sample)); 323 let timer_cc = timer.cc(0);
324
325 let mut sample_ppi = Ppi::new_one_to_one(ppi_ch2, timer_cc.event_compare(), Task::from_reg(&r.tasks_sample));
300 326
301 timer.start(); 327 timer.start();
302 328
@@ -306,21 +332,24 @@ impl<'d, const N: usize> Saadc<'d, N> {
306 || { 332 || {
307 sample_ppi.enable(); 333 sample_ppi.enable();
308 }, 334 },
309 sampler, 335 callback,
310 ) 336 )
311 .await; 337 .await;
312 } 338 }
313 339
314 async fn run_sampler<I, S, const N0: usize>( 340 async fn run_sampler<I, F, const N0: usize>(
315 &mut self, 341 &mut self,
316 bufs: &mut [[[i16; N]; N0]; 2], 342 bufs: &mut [[[i16; N]; N0]; 2],
317 sample_rate_divisor: Option<u16>, 343 sample_rate_divisor: Option<u16>,
318 mut init: I, 344 mut init: I,
319 mut sampler: S, 345 mut callback: F,
320 ) where 346 ) where
321 I: FnMut(), 347 I: FnMut(),
322 S: FnMut(&[[i16; N]]) -> SamplerState, 348 F: FnMut(&[[i16; N]]) -> CallbackResult,
323 { 349 {
350 // In case the future is dropped, stop the task and wait for it to end.
351 let on_drop = OnDrop::new(Self::stop_sampling_immediately);
352
324 let r = Self::regs(); 353 let r = Self::regs();
325 354
326 // Establish mode and sample rate 355 // Establish mode and sample rate
@@ -366,7 +395,7 @@ impl<'d, const N: usize> Saadc<'d, N> {
366 let mut current_buffer = 0; 395 let mut current_buffer = 0;
367 396
368 // Wait for events and complete when the sampler indicates it has had enough. 397 // Wait for events and complete when the sampler indicates it has had enough.
369 poll_fn(|cx| { 398 let r = poll_fn(|cx| {
370 let r = Self::regs(); 399 let r = Self::regs();
371 400
372 WAKER.register(cx.waker()); 401 WAKER.register(cx.waker());
@@ -377,12 +406,15 @@ impl<'d, const N: usize> Saadc<'d, N> {
377 r.events_end.reset(); 406 r.events_end.reset();
378 r.intenset.write(|w| w.end().set()); 407 r.intenset.write(|w| w.end().set());
379 408
380 if sampler(&bufs[current_buffer]) == SamplerState::Sampled { 409 match callback(&bufs[current_buffer]) {
381 let next_buffer = 1 - current_buffer; 410 CallbackResult::Continue => {
382 current_buffer = next_buffer; 411 let next_buffer = 1 - current_buffer;
383 } else { 412 current_buffer = next_buffer;
384 return Poll::Ready(()); 413 }
385 }; 414 CallbackResult::Stop => {
415 return Poll::Ready(());
416 }
417 }
386 } 418 }
387 419
388 if r.events_started.read().bits() != 0 { 420 if r.events_started.read().bits() != 0 {
@@ -403,6 +435,23 @@ impl<'d, const N: usize> Saadc<'d, N> {
403 Poll::Pending 435 Poll::Pending
404 }) 436 })
405 .await; 437 .await;
438
439 drop(on_drop);
440
441 r
442 }
443
444 // Stop sampling and wait for it to stop in a blocking fashion
445 fn stop_sampling_immediately() {
446 let r = Self::regs();
447
448 compiler_fence(Ordering::SeqCst);
449
450 r.events_stopped.reset();
451 r.tasks_stop.write(|w| unsafe { w.bits(1) });
452
453 while r.events_stopped.read().bits() == 0 {}
454 r.events_stopped.reset();
406 } 455 }
407} 456}
408 457
@@ -423,7 +472,7 @@ impl<'d> Saadc<'d, 1> {
423 sample_rate_divisor: u16, 472 sample_rate_divisor: u16,
424 sampler: S, 473 sampler: S,
425 ) where 474 ) where
426 S: FnMut(&[[i16; 1]]) -> SamplerState, 475 S: FnMut(&[[i16; 1]]) -> CallbackResult,
427 { 476 {
428 self.run_sampler(bufs, Some(sample_rate_divisor), || {}, sampler).await; 477 self.run_sampler(bufs, Some(sample_rate_divisor), || {}, sampler).await;
429 } 478 }
@@ -623,6 +672,10 @@ pub(crate) mod sealed {
623 672
624/// An input that can be used as either or negative end of a ADC differential in the SAADC periperhal. 673/// An input that can be used as either or negative end of a ADC differential in the SAADC periperhal.
625pub trait Input: sealed::Input + Into<AnyInput> + Peripheral<P = Self> + Sized + 'static { 674pub trait Input: sealed::Input + Into<AnyInput> + Peripheral<P = Self> + Sized + 'static {
675 /// Convert this SAADC input to a type-erased `AnyInput`.
676 ///
677 /// This allows using several inputs in situations that might require
678 /// them to be the same type, like putting them in an array.
626 fn degrade_saadc(self) -> AnyInput { 679 fn degrade_saadc(self) -> AnyInput {
627 AnyInput { 680 AnyInput {
628 channel: self.channel(), 681 channel: self.channel(),
@@ -630,6 +683,10 @@ pub trait Input: sealed::Input + Into<AnyInput> + Peripheral<P = Self> + Sized +
630 } 683 }
631} 684}
632 685
686/// A type-erased SAADC input.
687///
688/// This allows using several inputs in situations that might require
689/// them to be the same type, like putting them in an array.
633pub struct AnyInput { 690pub struct AnyInput {
634 channel: InputChannel, 691 channel: InputChannel,
635} 692}
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs
index be2fc02fc..b7dc332e9 100644
--- a/embassy-nrf/src/spim.rs
+++ b/embassy-nrf/src/spim.rs
@@ -1,42 +1,50 @@
1//! Serial Peripheral Instance in master mode (SPIM) driver.
2
1#![macro_use] 3#![macro_use]
2 4
5use core::future::poll_fn;
6use core::marker::PhantomData;
3use core::sync::atomic::{compiler_fence, Ordering}; 7use core::sync::atomic::{compiler_fence, Ordering};
4use core::task::Poll; 8use core::task::Poll;
5 9
6use embassy_embedded_hal::SetConfig; 10use embassy_embedded_hal::SetConfig;
7use embassy_hal_common::{into_ref, PeripheralRef}; 11use embassy_hal_common::{into_ref, PeripheralRef};
8pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; 12pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
9use futures::future::poll_fn;
10pub use pac::spim0::frequency::FREQUENCY_A as Frequency; 13pub use pac::spim0::frequency::FREQUENCY_A as Frequency;
11 14
12use crate::chip::FORCE_COPY_BUFFER_SIZE; 15use crate::chip::FORCE_COPY_BUFFER_SIZE;
13use crate::gpio::sealed::Pin as _; 16use crate::gpio::sealed::Pin as _;
14use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; 17use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits};
15use crate::interrupt::{Interrupt, InterruptExt}; 18use crate::interrupt::typelevel::Interrupt;
16use crate::util::{slice_in_ram_or, slice_ptr_parts, slice_ptr_parts_mut}; 19use crate::util::{slice_in_ram_or, slice_ptr_parts, slice_ptr_parts_mut};
17use crate::{pac, Peripheral}; 20use crate::{interrupt, pac, Peripheral};
18 21
22/// SPIM error
19#[derive(Debug, Clone, Copy, PartialEq, Eq)] 23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20#[cfg_attr(feature = "defmt", derive(defmt::Format))] 24#[cfg_attr(feature = "defmt", derive(defmt::Format))]
21#[non_exhaustive] 25#[non_exhaustive]
22pub enum Error { 26pub enum Error {
27 /// TX buffer was too long.
23 TxBufferTooLong, 28 TxBufferTooLong,
29 /// RX buffer was too long.
24 RxBufferTooLong, 30 RxBufferTooLong,
25 /// EasyDMA can only read from data memory, read only buffers in flash will fail. 31 /// EasyDMA can only read from data memory, read only buffers in flash will fail.
26 DMABufferNotInDataMemory, 32 BufferNotInRAM,
27}
28
29/// Interface for the SPIM peripheral using EasyDMA to offload the transmission and reception workload.
30///
31/// For more details about EasyDMA, consult the module documentation.
32pub struct Spim<'d, T: Instance> {
33 _p: PeripheralRef<'d, T>,
34} 33}
35 34
35/// SPIM configuration.
36#[non_exhaustive] 36#[non_exhaustive]
37pub struct Config { 37pub struct Config {
38 /// Frequency
38 pub frequency: Frequency, 39 pub frequency: Frequency,
40
41 /// SPI mode
39 pub mode: Mode, 42 pub mode: Mode,
43
44 /// Overread character.
45 ///
46 /// When doing bidirectional transfers, if the TX buffer is shorter than the RX buffer,
47 /// this byte will be transmitted in the MOSI line for the left-over bytes.
40 pub orc: u8, 48 pub orc: u8,
41} 49}
42 50
@@ -50,10 +58,33 @@ impl Default for Config {
50 } 58 }
51} 59}
52 60
61/// Interrupt handler.
62pub struct InterruptHandler<T: Instance> {
63 _phantom: PhantomData<T>,
64}
65
66impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
67 unsafe fn on_interrupt() {
68 let r = T::regs();
69 let s = T::state();
70
71 if r.events_end.read().bits() != 0 {
72 s.end_waker.wake();
73 r.intenclr.write(|w| w.end().clear());
74 }
75 }
76}
77
78/// SPIM driver.
79pub struct Spim<'d, T: Instance> {
80 _p: PeripheralRef<'d, T>,
81}
82
53impl<'d, T: Instance> Spim<'d, T> { 83impl<'d, T: Instance> Spim<'d, T> {
84 /// Create a new SPIM driver.
54 pub fn new( 85 pub fn new(
55 spim: impl Peripheral<P = T> + 'd, 86 spim: impl Peripheral<P = T> + 'd,
56 irq: impl Peripheral<P = T::Interrupt> + 'd, 87 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
57 sck: impl Peripheral<P = impl GpioPin> + 'd, 88 sck: impl Peripheral<P = impl GpioPin> + 'd,
58 miso: impl Peripheral<P = impl GpioPin> + 'd, 89 miso: impl Peripheral<P = impl GpioPin> + 'd,
59 mosi: impl Peripheral<P = impl GpioPin> + 'd, 90 mosi: impl Peripheral<P = impl GpioPin> + 'd,
@@ -62,7 +93,6 @@ impl<'d, T: Instance> Spim<'d, T> {
62 into_ref!(sck, miso, mosi); 93 into_ref!(sck, miso, mosi);
63 Self::new_inner( 94 Self::new_inner(
64 spim, 95 spim,
65 irq,
66 sck.map_into(), 96 sck.map_into(),
67 Some(miso.map_into()), 97 Some(miso.map_into()),
68 Some(mosi.map_into()), 98 Some(mosi.map_into()),
@@ -70,37 +100,38 @@ impl<'d, T: Instance> Spim<'d, T> {
70 ) 100 )
71 } 101 }
72 102
103 /// Create a new SPIM driver, capable of TX only (MOSI only).
73 pub fn new_txonly( 104 pub fn new_txonly(
74 spim: impl Peripheral<P = T> + 'd, 105 spim: impl Peripheral<P = T> + 'd,
75 irq: impl Peripheral<P = T::Interrupt> + 'd, 106 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
76 sck: impl Peripheral<P = impl GpioPin> + 'd, 107 sck: impl Peripheral<P = impl GpioPin> + 'd,
77 mosi: impl Peripheral<P = impl GpioPin> + 'd, 108 mosi: impl Peripheral<P = impl GpioPin> + 'd,
78 config: Config, 109 config: Config,
79 ) -> Self { 110 ) -> Self {
80 into_ref!(sck, mosi); 111 into_ref!(sck, mosi);
81 Self::new_inner(spim, irq, sck.map_into(), None, Some(mosi.map_into()), config) 112 Self::new_inner(spim, sck.map_into(), None, Some(mosi.map_into()), config)
82 } 113 }
83 114
115 /// Create a new SPIM driver, capable of RX only (MISO only).
84 pub fn new_rxonly( 116 pub fn new_rxonly(
85 spim: impl Peripheral<P = T> + 'd, 117 spim: impl Peripheral<P = T> + 'd,
86 irq: impl Peripheral<P = T::Interrupt> + 'd, 118 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
87 sck: impl Peripheral<P = impl GpioPin> + 'd, 119 sck: impl Peripheral<P = impl GpioPin> + 'd,
88 miso: impl Peripheral<P = impl GpioPin> + 'd, 120 miso: impl Peripheral<P = impl GpioPin> + 'd,
89 config: Config, 121 config: Config,
90 ) -> Self { 122 ) -> Self {
91 into_ref!(sck, miso); 123 into_ref!(sck, miso);
92 Self::new_inner(spim, irq, sck.map_into(), Some(miso.map_into()), None, config) 124 Self::new_inner(spim, sck.map_into(), Some(miso.map_into()), None, config)
93 } 125 }
94 126
95 fn new_inner( 127 fn new_inner(
96 spim: impl Peripheral<P = T> + 'd, 128 spim: impl Peripheral<P = T> + 'd,
97 irq: impl Peripheral<P = T::Interrupt> + 'd,
98 sck: PeripheralRef<'d, AnyPin>, 129 sck: PeripheralRef<'d, AnyPin>,
99 miso: Option<PeripheralRef<'d, AnyPin>>, 130 miso: Option<PeripheralRef<'d, AnyPin>>,
100 mosi: Option<PeripheralRef<'d, AnyPin>>, 131 mosi: Option<PeripheralRef<'d, AnyPin>>,
101 config: Config, 132 config: Config,
102 ) -> Self { 133 ) -> Self {
103 into_ref!(spim, irq); 134 into_ref!(spim);
104 135
105 let r = T::regs(); 136 let r = T::regs();
106 137
@@ -176,25 +207,14 @@ impl<'d, T: Instance> Spim<'d, T> {
176 // Disable all events interrupts 207 // Disable all events interrupts
177 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); 208 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
178 209
179 irq.set_handler(Self::on_interrupt); 210 T::Interrupt::unpend();
180 irq.unpend(); 211 unsafe { T::Interrupt::enable() };
181 irq.enable();
182 212
183 Self { _p: spim } 213 Self { _p: spim }
184 } 214 }
185 215
186 fn on_interrupt(_: *mut ()) {
187 let r = T::regs();
188 let s = T::state();
189
190 if r.events_end.read().bits() != 0 {
191 s.end_waker.wake();
192 r.intenclr.write(|w| w.end().clear());
193 }
194 }
195
196 fn prepare(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { 216 fn prepare(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
197 slice_in_ram_or(tx, Error::DMABufferNotInDataMemory)?; 217 slice_in_ram_or(tx, Error::BufferNotInRAM)?;
198 // NOTE: RAM slice check for rx is not necessary, as a mutable 218 // NOTE: RAM slice check for rx is not necessary, as a mutable
199 // slice can only be built from data located in RAM. 219 // slice can only be built from data located in RAM.
200 220
@@ -236,7 +256,7 @@ impl<'d, T: Instance> Spim<'d, T> {
236 fn blocking_inner(&mut self, rx: &mut [u8], tx: &[u8]) -> Result<(), Error> { 256 fn blocking_inner(&mut self, rx: &mut [u8], tx: &[u8]) -> Result<(), Error> {
237 match self.blocking_inner_from_ram(rx, tx) { 257 match self.blocking_inner_from_ram(rx, tx) {
238 Ok(_) => Ok(()), 258 Ok(_) => Ok(()),
239 Err(Error::DMABufferNotInDataMemory) => { 259 Err(Error::BufferNotInRAM) => {
240 trace!("Copying SPIM tx buffer into RAM for DMA"); 260 trace!("Copying SPIM tx buffer into RAM for DMA");
241 let tx_ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..tx.len()]; 261 let tx_ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..tx.len()];
242 tx_ram_buf.copy_from_slice(tx); 262 tx_ram_buf.copy_from_slice(tx);
@@ -268,7 +288,7 @@ impl<'d, T: Instance> Spim<'d, T> {
268 async fn async_inner(&mut self, rx: &mut [u8], tx: &[u8]) -> Result<(), Error> { 288 async fn async_inner(&mut self, rx: &mut [u8], tx: &[u8]) -> Result<(), Error> {
269 match self.async_inner_from_ram(rx, tx).await { 289 match self.async_inner_from_ram(rx, tx).await {
270 Ok(_) => Ok(()), 290 Ok(_) => Ok(()),
271 Err(Error::DMABufferNotInDataMemory) => { 291 Err(Error::BufferNotInRAM) => {
272 trace!("Copying SPIM tx buffer into RAM for DMA"); 292 trace!("Copying SPIM tx buffer into RAM for DMA");
273 let tx_ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..tx.len()]; 293 let tx_ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..tx.len()];
274 tx_ram_buf.copy_from_slice(tx); 294 tx_ram_buf.copy_from_slice(tx);
@@ -385,8 +405,10 @@ pub(crate) mod sealed {
385 } 405 }
386} 406}
387 407
408/// SPIM peripheral instance
388pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static { 409pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static {
389 type Interrupt: Interrupt; 410 /// Interrupt for this peripheral.
411 type Interrupt: interrupt::typelevel::Interrupt;
390} 412}
391 413
392macro_rules! impl_spim { 414macro_rules! impl_spim {
@@ -401,7 +423,7 @@ macro_rules! impl_spim {
401 } 423 }
402 } 424 }
403 impl crate::spim::Instance for peripherals::$type { 425 impl crate::spim::Instance for peripherals::$type {
404 type Interrupt = crate::interrupt::$irq; 426 type Interrupt = crate::interrupt::typelevel::$irq;
405 } 427 }
406 }; 428 };
407} 429}
@@ -437,7 +459,7 @@ mod eh1 {
437 match *self { 459 match *self {
438 Self::TxBufferTooLong => embedded_hal_1::spi::ErrorKind::Other, 460 Self::TxBufferTooLong => embedded_hal_1::spi::ErrorKind::Other,
439 Self::RxBufferTooLong => embedded_hal_1::spi::ErrorKind::Other, 461 Self::RxBufferTooLong => embedded_hal_1::spi::ErrorKind::Other,
440 Self::DMABufferNotInDataMemory => embedded_hal_1::spi::ErrorKind::Other, 462 Self::BufferNotInRAM => embedded_hal_1::spi::ErrorKind::Other,
441 } 463 }
442 } 464 }
443 } 465 }
@@ -446,25 +468,19 @@ mod eh1 {
446 type Error = Error; 468 type Error = Error;
447 } 469 }
448 470
449 impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBusFlush for Spim<'d, T> { 471 impl<'d, T: Instance> embedded_hal_1::spi::SpiBus<u8> for Spim<'d, T> {
450 fn flush(&mut self) -> Result<(), Self::Error> { 472 fn flush(&mut self) -> Result<(), Self::Error> {
451 Ok(()) 473 Ok(())
452 } 474 }
453 }
454 475
455 impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBusRead<u8> for Spim<'d, T> {
456 fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { 476 fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
457 self.blocking_transfer(words, &[]) 477 self.blocking_transfer(words, &[])
458 } 478 }
459 }
460 479
461 impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBusWrite<u8> for Spim<'d, T> {
462 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { 480 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
463 self.blocking_write(words) 481 self.blocking_write(words)
464 } 482 }
465 }
466 483
467 impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBus<u8> for Spim<'d, T> {
468 fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { 484 fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
469 self.blocking_transfer(read, write) 485 self.blocking_transfer(read, write)
470 } 486 }
@@ -475,49 +491,30 @@ mod eh1 {
475 } 491 }
476} 492}
477 493
478cfg_if::cfg_if! { 494#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
479 if #[cfg(all(feature = "unstable-traits", feature = "nightly"))] { 495mod eha {
480 use core::future::Future;
481 496
482 impl<'d, T: Instance> embedded_hal_async::spi::SpiBusFlush for Spim<'d, T> { 497 use super::*;
483 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
484 498
485 fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { 499 impl<'d, T: Instance> embedded_hal_async::spi::SpiBus<u8> for Spim<'d, T> {
486 async move { Ok(()) } 500 async fn flush(&mut self) -> Result<(), Error> {
487 } 501 Ok(())
488 } 502 }
489 503
490 impl<'d, T: Instance> embedded_hal_async::spi::SpiBusRead<u8> for Spim<'d, T> { 504 async fn read(&mut self, words: &mut [u8]) -> Result<(), Error> {
491 type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; 505 self.read(words).await
492
493 fn read<'a>(&'a mut self, words: &'a mut [u8]) -> Self::ReadFuture<'a> {
494 self.read(words)
495 }
496 } 506 }
497 507
498 impl<'d, T: Instance> embedded_hal_async::spi::SpiBusWrite<u8> for Spim<'d, T> { 508 async fn write(&mut self, data: &[u8]) -> Result<(), Error> {
499 type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; 509 self.write(data).await
500
501 fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> {
502 self.write(data)
503 }
504 } 510 }
505 511
506 impl<'d, T: Instance> embedded_hal_async::spi::SpiBus<u8> for Spim<'d, T> { 512 async fn transfer(&mut self, rx: &mut [u8], tx: &[u8]) -> Result<(), Error> {
507 type TransferFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; 513 self.transfer(rx, tx).await
508 514 }
509 fn transfer<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Self::TransferFuture<'a> {
510 self.transfer(rx, tx)
511 }
512
513 type TransferInPlaceFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
514 515
515 fn transfer_in_place<'a>( 516 async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Error> {
516 &'a mut self, 517 self.transfer_in_place(words).await
517 words: &'a mut [u8],
518 ) -> Self::TransferInPlaceFuture<'a> {
519 self.transfer_in_place(words)
520 }
521 } 518 }
522 } 519 }
523} 520}
diff --git a/embassy-nrf/src/spis.rs b/embassy-nrf/src/spis.rs
new file mode 100644
index 000000000..aa438415a
--- /dev/null
+++ b/embassy-nrf/src/spis.rs
@@ -0,0 +1,550 @@
1//! Serial Peripheral Instance in slave mode (SPIS) driver.
2
3#![macro_use]
4use core::future::poll_fn;
5use core::marker::PhantomData;
6use core::sync::atomic::{compiler_fence, Ordering};
7use core::task::Poll;
8
9use embassy_embedded_hal::SetConfig;
10use embassy_hal_common::{into_ref, PeripheralRef};
11pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
12
13use crate::chip::FORCE_COPY_BUFFER_SIZE;
14use crate::gpio::sealed::Pin as _;
15use crate::gpio::{self, AnyPin, Pin as GpioPin};
16use crate::interrupt::typelevel::Interrupt;
17use crate::util::{slice_in_ram_or, slice_ptr_parts, slice_ptr_parts_mut};
18use crate::{interrupt, pac, Peripheral};
19
20/// SPIS error
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22#[cfg_attr(feature = "defmt", derive(defmt::Format))]
23#[non_exhaustive]
24pub enum Error {
25 /// TX buffer was too long.
26 TxBufferTooLong,
27 /// RX buffer was too long.
28 RxBufferTooLong,
29 /// EasyDMA can only read from data memory, read only buffers in flash will fail.
30 BufferNotInRAM,
31}
32
33/// SPIS configuration.
34#[non_exhaustive]
35pub struct Config {
36 /// SPI mode
37 pub mode: Mode,
38
39 /// Overread character.
40 ///
41 /// If the master keeps clocking the bus after all the bytes in the TX buffer have
42 /// already been transmitted, this byte will be constantly transmitted in the MISO line.
43 pub orc: u8,
44
45 /// Default byte.
46 ///
47 /// This is the byte clocked out in the MISO line for ignored transactions (if the master
48 /// sets CSN low while the semaphore is owned by the firmware)
49 pub def: u8,
50
51 /// Automatically make the firmware side acquire the semaphore on transfer end.
52 pub auto_acquire: bool,
53}
54
55impl Default for Config {
56 fn default() -> Self {
57 Self {
58 mode: MODE_0,
59 orc: 0x00,
60 def: 0x00,
61 auto_acquire: true,
62 }
63 }
64}
65
66/// Interrupt handler.
67pub struct InterruptHandler<T: Instance> {
68 _phantom: PhantomData<T>,
69}
70
71impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
72 unsafe fn on_interrupt() {
73 let r = T::regs();
74 let s = T::state();
75
76 if r.events_end.read().bits() != 0 {
77 s.waker.wake();
78 r.intenclr.write(|w| w.end().clear());
79 }
80
81 if r.events_acquired.read().bits() != 0 {
82 s.waker.wake();
83 r.intenclr.write(|w| w.acquired().clear());
84 }
85 }
86}
87
88/// SPIS driver.
89pub struct Spis<'d, T: Instance> {
90 _p: PeripheralRef<'d, T>,
91}
92
93impl<'d, T: Instance> Spis<'d, T> {
94 /// Create a new SPIS driver.
95 pub fn new(
96 spis: impl Peripheral<P = T> + 'd,
97 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
98 cs: impl Peripheral<P = impl GpioPin> + 'd,
99 sck: impl Peripheral<P = impl GpioPin> + 'd,
100 miso: impl Peripheral<P = impl GpioPin> + 'd,
101 mosi: impl Peripheral<P = impl GpioPin> + 'd,
102 config: Config,
103 ) -> Self {
104 into_ref!(cs, sck, miso, mosi);
105 Self::new_inner(
106 spis,
107 cs.map_into(),
108 sck.map_into(),
109 Some(miso.map_into()),
110 Some(mosi.map_into()),
111 config,
112 )
113 }
114
115 /// Create a new SPIS driver, capable of TX only (MISO only).
116 pub fn new_txonly(
117 spis: impl Peripheral<P = T> + 'd,
118 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
119 cs: impl Peripheral<P = impl GpioPin> + 'd,
120 sck: impl Peripheral<P = impl GpioPin> + 'd,
121 miso: impl Peripheral<P = impl GpioPin> + 'd,
122 config: Config,
123 ) -> Self {
124 into_ref!(cs, sck, miso);
125 Self::new_inner(spis, cs.map_into(), sck.map_into(), Some(miso.map_into()), None, config)
126 }
127
128 /// Create a new SPIS driver, capable of RX only (MOSI only).
129 pub fn new_rxonly(
130 spis: impl Peripheral<P = T> + 'd,
131 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
132 cs: impl Peripheral<P = impl GpioPin> + 'd,
133 sck: impl Peripheral<P = impl GpioPin> + 'd,
134 mosi: impl Peripheral<P = impl GpioPin> + 'd,
135 config: Config,
136 ) -> Self {
137 into_ref!(cs, sck, mosi);
138 Self::new_inner(spis, cs.map_into(), sck.map_into(), None, Some(mosi.map_into()), config)
139 }
140
141 fn new_inner(
142 spis: impl Peripheral<P = T> + 'd,
143 cs: PeripheralRef<'d, AnyPin>,
144 sck: PeripheralRef<'d, AnyPin>,
145 miso: Option<PeripheralRef<'d, AnyPin>>,
146 mosi: Option<PeripheralRef<'d, AnyPin>>,
147 config: Config,
148 ) -> Self {
149 compiler_fence(Ordering::SeqCst);
150
151 into_ref!(spis, cs, sck);
152
153 let r = T::regs();
154
155 // Configure pins.
156 sck.conf().write(|w| w.input().connect().drive().h0h1());
157 r.psel.sck.write(|w| unsafe { w.bits(sck.psel_bits()) });
158 cs.conf().write(|w| w.input().connect().drive().h0h1());
159 r.psel.csn.write(|w| unsafe { w.bits(cs.psel_bits()) });
160 if let Some(mosi) = &mosi {
161 mosi.conf().write(|w| w.input().connect().drive().h0h1());
162 r.psel.mosi.write(|w| unsafe { w.bits(mosi.psel_bits()) });
163 }
164 if let Some(miso) = &miso {
165 miso.conf().write(|w| w.dir().output().drive().h0h1());
166 r.psel.miso.write(|w| unsafe { w.bits(miso.psel_bits()) });
167 }
168
169 // Enable SPIS instance.
170 r.enable.write(|w| w.enable().enabled());
171
172 // Configure mode.
173 let mode = config.mode;
174 r.config.write(|w| {
175 match mode {
176 MODE_0 => {
177 w.order().msb_first();
178 w.cpol().active_high();
179 w.cpha().leading();
180 }
181 MODE_1 => {
182 w.order().msb_first();
183 w.cpol().active_high();
184 w.cpha().trailing();
185 }
186 MODE_2 => {
187 w.order().msb_first();
188 w.cpol().active_low();
189 w.cpha().leading();
190 }
191 MODE_3 => {
192 w.order().msb_first();
193 w.cpol().active_low();
194 w.cpha().trailing();
195 }
196 }
197
198 w
199 });
200
201 // Set over-read character.
202 let orc = config.orc;
203 r.orc.write(|w| unsafe { w.orc().bits(orc) });
204
205 // Set default character.
206 let def = config.def;
207 r.def.write(|w| unsafe { w.def().bits(def) });
208
209 // Configure auto-acquire on 'transfer end' event.
210 if config.auto_acquire {
211 r.shorts.write(|w| w.end_acquire().bit(true));
212 }
213
214 // Disable all events interrupts.
215 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
216
217 T::Interrupt::unpend();
218 unsafe { T::Interrupt::enable() };
219
220 Self { _p: spis }
221 }
222
223 fn prepare(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
224 slice_in_ram_or(tx, Error::BufferNotInRAM)?;
225 // NOTE: RAM slice check for rx is not necessary, as a mutable
226 // slice can only be built from data located in RAM.
227
228 compiler_fence(Ordering::SeqCst);
229
230 let r = T::regs();
231
232 // Set up the DMA write.
233 let (ptr, len) = slice_ptr_parts(tx);
234 r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) });
235 r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
236
237 // Set up the DMA read.
238 let (ptr, len) = slice_ptr_parts_mut(rx);
239 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) });
240 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
241
242 // Reset end event.
243 r.events_end.reset();
244
245 // Release the semaphore.
246 r.tasks_release.write(|w| unsafe { w.bits(1) });
247
248 Ok(())
249 }
250
251 fn blocking_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(usize, usize), Error> {
252 compiler_fence(Ordering::SeqCst);
253 let r = T::regs();
254
255 // Acquire semaphore.
256 if r.semstat.read().bits() != 1 {
257 r.events_acquired.reset();
258 r.tasks_acquire.write(|w| unsafe { w.bits(1) });
259 // Wait until CPU has acquired the semaphore.
260 while r.semstat.read().bits() != 1 {}
261 }
262
263 self.prepare(rx, tx)?;
264
265 // Wait for 'end' event.
266 while r.events_end.read().bits() == 0 {}
267
268 let n_rx = r.rxd.amount.read().bits() as usize;
269 let n_tx = r.txd.amount.read().bits() as usize;
270
271 compiler_fence(Ordering::SeqCst);
272
273 Ok((n_rx, n_tx))
274 }
275
276 fn blocking_inner(&mut self, rx: &mut [u8], tx: &[u8]) -> Result<(usize, usize), Error> {
277 match self.blocking_inner_from_ram(rx, tx) {
278 Ok(n) => Ok(n),
279 Err(Error::BufferNotInRAM) => {
280 trace!("Copying SPIS tx buffer into RAM for DMA");
281 let tx_ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..tx.len()];
282 tx_ram_buf.copy_from_slice(tx);
283 self.blocking_inner_from_ram(rx, tx_ram_buf)
284 }
285 Err(error) => Err(error),
286 }
287 }
288
289 async fn async_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(usize, usize), Error> {
290 let r = T::regs();
291 let s = T::state();
292
293 // Clear status register.
294 r.status.write(|w| w.overflow().clear().overread().clear());
295
296 // Acquire semaphore.
297 if r.semstat.read().bits() != 1 {
298 // Reset and enable the acquire event.
299 r.events_acquired.reset();
300 r.intenset.write(|w| w.acquired().set());
301
302 // Request acquiring the SPIS semaphore.
303 r.tasks_acquire.write(|w| unsafe { w.bits(1) });
304
305 // Wait until CPU has acquired the semaphore.
306 poll_fn(|cx| {
307 s.waker.register(cx.waker());
308 if r.events_acquired.read().bits() == 1 {
309 r.events_acquired.reset();
310 return Poll::Ready(());
311 }
312 Poll::Pending
313 })
314 .await;
315 }
316
317 self.prepare(rx, tx)?;
318
319 // Wait for 'end' event.
320 r.intenset.write(|w| w.end().set());
321 poll_fn(|cx| {
322 s.waker.register(cx.waker());
323 if r.events_end.read().bits() != 0 {
324 r.events_end.reset();
325 return Poll::Ready(());
326 }
327 Poll::Pending
328 })
329 .await;
330
331 let n_rx = r.rxd.amount.read().bits() as usize;
332 let n_tx = r.txd.amount.read().bits() as usize;
333
334 compiler_fence(Ordering::SeqCst);
335
336 Ok((n_rx, n_tx))
337 }
338
339 async fn async_inner(&mut self, rx: &mut [u8], tx: &[u8]) -> Result<(usize, usize), Error> {
340 match self.async_inner_from_ram(rx, tx).await {
341 Ok(n) => Ok(n),
342 Err(Error::BufferNotInRAM) => {
343 trace!("Copying SPIS tx buffer into RAM for DMA");
344 let tx_ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..tx.len()];
345 tx_ram_buf.copy_from_slice(tx);
346 self.async_inner_from_ram(rx, tx_ram_buf).await
347 }
348 Err(error) => Err(error),
349 }
350 }
351
352 /// Reads data from the SPI bus without sending anything. Blocks until `cs` is deasserted.
353 /// Returns number of bytes read.
354 pub fn blocking_read(&mut self, data: &mut [u8]) -> Result<usize, Error> {
355 self.blocking_inner(data, &[]).map(|n| n.0)
356 }
357
358 /// Simultaneously sends and receives data. Blocks until the transmission is completed.
359 /// If necessary, the write buffer will be copied into RAM (see struct description for detail).
360 /// Returns number of bytes transferred `(n_rx, n_tx)`.
361 pub fn blocking_transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(usize, usize), Error> {
362 self.blocking_inner(read, write)
363 }
364
365 /// Same as [`blocking_transfer`](Spis::blocking_transfer) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
366 /// Returns number of bytes transferred `(n_rx, n_tx)`.
367 pub fn blocking_transfer_from_ram(&mut self, read: &mut [u8], write: &[u8]) -> Result<(usize, usize), Error> {
368 self.blocking_inner_from_ram(read, write)
369 }
370
371 /// Simultaneously sends and receives data.
372 /// Places the received data into the same buffer and blocks until the transmission is completed.
373 /// Returns number of bytes transferred.
374 pub fn blocking_transfer_in_place(&mut self, data: &mut [u8]) -> Result<usize, Error> {
375 self.blocking_inner_from_ram(data, data).map(|n| n.0)
376 }
377
378 /// Sends data, discarding any received data. Blocks until the transmission is completed.
379 /// If necessary, the write buffer will be copied into RAM (see struct description for detail).
380 /// Returns number of bytes written.
381 pub fn blocking_write(&mut self, data: &[u8]) -> Result<usize, Error> {
382 self.blocking_inner(&mut [], data).map(|n| n.1)
383 }
384
385 /// Same as [`blocking_write`](Spis::blocking_write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
386 /// Returns number of bytes written.
387 pub fn blocking_write_from_ram(&mut self, data: &[u8]) -> Result<usize, Error> {
388 self.blocking_inner_from_ram(&mut [], data).map(|n| n.1)
389 }
390
391 /// Reads data from the SPI bus without sending anything.
392 /// Returns number of bytes read.
393 pub async fn read(&mut self, data: &mut [u8]) -> Result<usize, Error> {
394 self.async_inner(data, &[]).await.map(|n| n.0)
395 }
396
397 /// Simultaneously sends and receives data.
398 /// If necessary, the write buffer will be copied into RAM (see struct description for detail).
399 /// Returns number of bytes transferred `(n_rx, n_tx)`.
400 pub async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(usize, usize), Error> {
401 self.async_inner(read, write).await
402 }
403
404 /// Same as [`transfer`](Spis::transfer) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
405 /// Returns number of bytes transferred `(n_rx, n_tx)`.
406 pub async fn transfer_from_ram(&mut self, read: &mut [u8], write: &[u8]) -> Result<(usize, usize), Error> {
407 self.async_inner_from_ram(read, write).await
408 }
409
410 /// Simultaneously sends and receives data. Places the received data into the same buffer.
411 /// Returns number of bytes transferred.
412 pub async fn transfer_in_place(&mut self, data: &mut [u8]) -> Result<usize, Error> {
413 self.async_inner_from_ram(data, data).await.map(|n| n.0)
414 }
415
416 /// Sends data, discarding any received data.
417 /// If necessary, the write buffer will be copied into RAM (see struct description for detail).
418 /// Returns number of bytes written.
419 pub async fn write(&mut self, data: &[u8]) -> Result<usize, Error> {
420 self.async_inner(&mut [], data).await.map(|n| n.1)
421 }
422
423 /// Same as [`write`](Spis::write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
424 /// Returns number of bytes written.
425 pub async fn write_from_ram(&mut self, data: &[u8]) -> Result<usize, Error> {
426 self.async_inner_from_ram(&mut [], data).await.map(|n| n.1)
427 }
428
429 /// Checks if last transaction overread.
430 pub fn is_overread(&mut self) -> bool {
431 T::regs().status.read().overread().is_present()
432 }
433
434 /// Checks if last transaction overflowed.
435 pub fn is_overflow(&mut self) -> bool {
436 T::regs().status.read().overflow().is_present()
437 }
438}
439
440impl<'d, T: Instance> Drop for Spis<'d, T> {
441 fn drop(&mut self) {
442 trace!("spis drop");
443
444 // Disable
445 let r = T::regs();
446 r.enable.write(|w| w.enable().disabled());
447
448 gpio::deconfigure_pin(r.psel.sck.read().bits());
449 gpio::deconfigure_pin(r.psel.csn.read().bits());
450 gpio::deconfigure_pin(r.psel.miso.read().bits());
451 gpio::deconfigure_pin(r.psel.mosi.read().bits());
452
453 trace!("spis drop: done");
454 }
455}
456
457pub(crate) mod sealed {
458 use embassy_sync::waitqueue::AtomicWaker;
459
460 use super::*;
461
462 pub struct State {
463 pub waker: AtomicWaker,
464 }
465
466 impl State {
467 pub const fn new() -> Self {
468 Self {
469 waker: AtomicWaker::new(),
470 }
471 }
472 }
473
474 pub trait Instance {
475 fn regs() -> &'static pac::spis0::RegisterBlock;
476 fn state() -> &'static State;
477 }
478}
479
480/// SPIS peripheral instance
481pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static {
482 /// Interrupt for this peripheral.
483 type Interrupt: interrupt::typelevel::Interrupt;
484}
485
486macro_rules! impl_spis {
487 ($type:ident, $pac_type:ident, $irq:ident) => {
488 impl crate::spis::sealed::Instance for peripherals::$type {
489 fn regs() -> &'static pac::spis0::RegisterBlock {
490 unsafe { &*pac::$pac_type::ptr() }
491 }
492 fn state() -> &'static crate::spis::sealed::State {
493 static STATE: crate::spis::sealed::State = crate::spis::sealed::State::new();
494 &STATE
495 }
496 }
497 impl crate::spis::Instance for peripherals::$type {
498 type Interrupt = crate::interrupt::typelevel::$irq;
499 }
500 };
501}
502
503// ====================
504
505impl<'d, T: Instance> SetConfig for Spis<'d, T> {
506 type Config = Config;
507 fn set_config(&mut self, config: &Self::Config) {
508 let r = T::regs();
509 // Configure mode.
510 let mode = config.mode;
511 r.config.write(|w| {
512 match mode {
513 MODE_0 => {
514 w.order().msb_first();
515 w.cpol().active_high();
516 w.cpha().leading();
517 }
518 MODE_1 => {
519 w.order().msb_first();
520 w.cpol().active_high();
521 w.cpha().trailing();
522 }
523 MODE_2 => {
524 w.order().msb_first();
525 w.cpol().active_low();
526 w.cpha().leading();
527 }
528 MODE_3 => {
529 w.order().msb_first();
530 w.cpol().active_low();
531 w.cpha().trailing();
532 }
533 }
534
535 w
536 });
537
538 // Set over-read character.
539 let orc = config.orc;
540 r.orc.write(|w| unsafe { w.orc().bits(orc) });
541
542 // Set default character.
543 let def = config.def;
544 r.def.write(|w| unsafe { w.def().bits(def) });
545
546 // Configure auto-acquire on 'transfer end' event.
547 let auto_acquire = config.auto_acquire;
548 r.shorts.write(|w| w.end_acquire().bit(auto_acquire));
549 }
550}
diff --git a/embassy-nrf/src/temp.rs b/embassy-nrf/src/temp.rs
index d520fd686..491e92c04 100644
--- a/embassy-nrf/src/temp.rs
+++ b/embassy-nrf/src/temp.rs
@@ -1,37 +1,50 @@
1//! Temperature sensor interface. 1//! Builtin temperature sensor driver.
2 2
3use core::future::poll_fn;
3use core::task::Poll; 4use core::task::Poll;
4 5
5use embassy_hal_common::drop::OnDrop; 6use embassy_hal_common::drop::OnDrop;
6use embassy_hal_common::{into_ref, PeripheralRef}; 7use embassy_hal_common::{into_ref, PeripheralRef};
7use embassy_sync::waitqueue::AtomicWaker; 8use embassy_sync::waitqueue::AtomicWaker;
8use fixed::types::I30F2; 9use fixed::types::I30F2;
9use futures::future::poll_fn;
10 10
11use crate::interrupt::InterruptExt; 11use crate::interrupt::InterruptExt;
12use crate::peripherals::TEMP; 12use crate::peripherals::TEMP;
13use crate::{interrupt, pac, Peripheral}; 13use crate::{interrupt, pac, Peripheral};
14 14
15/// Integrated temperature sensor. 15/// Interrupt handler.
16pub struct InterruptHandler {
17 _private: (),
18}
19
20impl interrupt::typelevel::Handler<interrupt::typelevel::TEMP> for InterruptHandler {
21 unsafe fn on_interrupt() {
22 let r = unsafe { &*pac::TEMP::PTR };
23 r.intenclr.write(|w| w.datardy().clear());
24 WAKER.wake();
25 }
26}
27
28/// Builtin temperature sensor driver.
16pub struct Temp<'d> { 29pub struct Temp<'d> {
17 _irq: PeripheralRef<'d, interrupt::TEMP>, 30 _peri: PeripheralRef<'d, TEMP>,
18} 31}
19 32
20static WAKER: AtomicWaker = AtomicWaker::new(); 33static WAKER: AtomicWaker = AtomicWaker::new();
21 34
22impl<'d> Temp<'d> { 35impl<'d> Temp<'d> {
23 pub fn new(_t: impl Peripheral<P = TEMP> + 'd, irq: impl Peripheral<P = interrupt::TEMP> + 'd) -> Self { 36 /// Create a new temperature sensor driver.
24 into_ref!(_t, irq); 37 pub fn new(
38 _peri: impl Peripheral<P = TEMP> + 'd,
39 _irq: impl interrupt::typelevel::Binding<interrupt::typelevel::TEMP, InterruptHandler> + 'd,
40 ) -> Self {
41 into_ref!(_peri);
25 42
26 // Enable interrupt that signals temperature values 43 // Enable interrupt that signals temperature values
27 irq.disable(); 44 interrupt::TEMP.unpend();
28 irq.set_handler(|_| { 45 unsafe { interrupt::TEMP.enable() };
29 let t = Self::regs(); 46
30 t.intenclr.write(|w| w.datardy().clear()); 47 Self { _peri }
31 WAKER.wake();
32 });
33 irq.enable();
34 Self { _irq: irq }
35 } 48 }
36 49
37 /// Perform an asynchronous temperature measurement. The returned future 50 /// Perform an asynchronous temperature measurement. The returned future
@@ -42,8 +55,19 @@ impl<'d> Temp<'d> {
42 /// # Example 55 /// # Example
43 /// 56 ///
44 /// ```no_run 57 /// ```no_run
45 /// let mut t = Temp::new(p.TEMP, interrupt::take!(TEMP)); 58 /// use embassy_nrf::{bind_interrupts, temp};
59 /// use embassy_nrf::temp::Temp;
60 /// use embassy_time::{Duration, Timer};
61 ///
62 /// bind_interrupts!(struct Irqs {
63 /// TEMP => temp::InterruptHandler;
64 /// });
65 ///
66 /// # async {
67 /// # let p: embassy_nrf::Peripherals = todo!();
68 /// let mut t = Temp::new(p.TEMP, Irqs);
46 /// let v: u16 = t.read().await.to_num::<u16>(); 69 /// let v: u16 = t.read().await.to_num::<u16>();
70 /// # };
47 /// ``` 71 /// ```
48 pub async fn read(&mut self) -> I30F2 { 72 pub async fn read(&mut self) -> I30F2 {
49 // In case the future is dropped, stop the task and reset events. 73 // In case the future is dropped, stop the task and reset events.
diff --git a/embassy-nrf/src/time_driver.rs b/embassy-nrf/src/time_driver.rs
index c32a44637..f1ab4f8fd 100644
--- a/embassy-nrf/src/time_driver.rs
+++ b/embassy-nrf/src/time_driver.rs
@@ -7,7 +7,7 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
7use embassy_sync::blocking_mutex::CriticalSectionMutex as Mutex; 7use embassy_sync::blocking_mutex::CriticalSectionMutex as Mutex;
8use embassy_time::driver::{AlarmHandle, Driver}; 8use embassy_time::driver::{AlarmHandle, Driver};
9 9
10use crate::interrupt::{Interrupt, InterruptExt}; 10use crate::interrupt::InterruptExt;
11use crate::{interrupt, pac}; 11use crate::{interrupt, pac};
12 12
13fn rtc() -> &'static pac::rtc0::RegisterBlock { 13fn rtc() -> &'static pac::rtc0::RegisterBlock {
@@ -67,7 +67,7 @@ fn compare_n(n: usize) -> u32 {
67 1 << (n + 16) 67 1 << (n + 16)
68} 68}
69 69
70#[cfg(tests)] 70#[cfg(test)]
71mod test { 71mod test {
72 use super::*; 72 use super::*;
73 73
@@ -142,9 +142,8 @@ impl RtcDriver {
142 // Wait for clear 142 // Wait for clear
143 while r.counter.read().bits() != 0 {} 143 while r.counter.read().bits() != 0 {}
144 144
145 let irq = unsafe { interrupt::RTC1::steal() }; 145 interrupt::RTC1.set_priority(irq_prio);
146 irq.set_priority(irq_prio); 146 unsafe { interrupt::RTC1.enable() };
147 irq.enable();
148 } 147 }
149 148
150 fn on_interrupt(&self) { 149 fn on_interrupt(&self) {
@@ -243,21 +242,24 @@ impl Driver for RtcDriver {
243 }) 242 })
244 } 243 }
245 244
246 fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) { 245 fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) -> bool {
247 critical_section::with(|cs| { 246 critical_section::with(|cs| {
248 let n = alarm.id() as _; 247 let n = alarm.id() as _;
249 let alarm = self.get_alarm(cs, alarm); 248 let alarm = self.get_alarm(cs, alarm);
250 alarm.timestamp.set(timestamp); 249 alarm.timestamp.set(timestamp);
251 250
252 let t = self.now(); 251 let r = rtc();
253 252
254 // If alarm timestamp has passed, trigger it instantly. 253 let t = self.now();
255 if timestamp <= t { 254 if timestamp <= t {
256 self.trigger_alarm(n, cs); 255 // If alarm timestamp has passed the alarm will not fire.
257 return; 256 // Disarm the alarm and return `false` to indicate that.
258 } 257 r.intenclr.write(|w| unsafe { w.bits(compare_n(n)) });
259 258
260 let r = rtc(); 259 alarm.timestamp.set(u64::MAX);
260
261 return false;
262 }
261 263
262 // If it hasn't triggered yet, setup it in the compare channel. 264 // If it hasn't triggered yet, setup it in the compare channel.
263 265
@@ -287,10 +289,13 @@ impl Driver for RtcDriver {
287 // It will be setup later by `next_period`. 289 // It will be setup later by `next_period`.
288 r.intenclr.write(|w| unsafe { w.bits(compare_n(n)) }); 290 r.intenclr.write(|w| unsafe { w.bits(compare_n(n)) });
289 } 291 }
292
293 true
290 }) 294 })
291 } 295 }
292} 296}
293 297
298#[cfg(feature = "rt")]
294#[interrupt] 299#[interrupt]
295fn RTC1() { 300fn RTC1() {
296 DRIVER.on_interrupt() 301 DRIVER.on_interrupt()
diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs
index 3de5a8962..04748238d 100644
--- a/embassy-nrf/src/timer.rs
+++ b/embassy-nrf/src/timer.rs
@@ -1,14 +1,13 @@
1#![macro_use] 1//! Timer driver.
2//!
3//! Important note! This driver is very low level. For most time-related use cases, like
4//! "sleep for X seconds", "do something every X seconds", or measuring time, you should
5//! use [`embassy-time`](https://crates.io/crates/embassy-time) instead!
2 6
3use core::marker::PhantomData; 7#![macro_use]
4use core::task::Poll;
5 8
6use embassy_hal_common::drop::OnDrop;
7use embassy_hal_common::{into_ref, PeripheralRef}; 9use embassy_hal_common::{into_ref, PeripheralRef};
8use embassy_sync::waitqueue::AtomicWaker;
9use futures::future::poll_fn;
10 10
11use crate::interrupt::{Interrupt, InterruptExt};
12use crate::ppi::{Event, Task}; 11use crate::ppi::{Event, Task};
13use crate::{pac, Peripheral}; 12use crate::{pac, Peripheral};
14 13
@@ -20,17 +19,19 @@ pub(crate) mod sealed {
20 /// The number of CC registers this instance has. 19 /// The number of CC registers this instance has.
21 const CCS: usize; 20 const CCS: usize;
22 fn regs() -> &'static pac::timer0::RegisterBlock; 21 fn regs() -> &'static pac::timer0::RegisterBlock;
23 /// Storage for the waker for CC register `n`.
24 fn waker(n: usize) -> &'static AtomicWaker;
25 } 22 }
26 pub trait ExtendedInstance {} 23 pub trait ExtendedInstance {}
27 24
28 pub trait TimerType {} 25 pub trait TimerType {}
29} 26}
30 27
28/// Basic Timer instance.
31pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send { 29pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
32 type Interrupt: Interrupt; 30 /// Interrupt for this peripheral.
31 type Interrupt: crate::interrupt::typelevel::Interrupt;
33} 32}
33
34/// Extended timer instance.
34pub trait ExtendedInstance: Instance + sealed::ExtendedInstance {} 35pub trait ExtendedInstance: Instance + sealed::ExtendedInstance {}
35 36
36macro_rules! impl_timer { 37macro_rules! impl_timer {
@@ -40,15 +41,9 @@ macro_rules! impl_timer {
40 fn regs() -> &'static pac::timer0::RegisterBlock { 41 fn regs() -> &'static pac::timer0::RegisterBlock {
41 unsafe { &*(pac::$pac_type::ptr() as *const pac::timer0::RegisterBlock) } 42 unsafe { &*(pac::$pac_type::ptr() as *const pac::timer0::RegisterBlock) }
42 } 43 }
43 fn waker(n: usize) -> &'static ::embassy_sync::waitqueue::AtomicWaker {
44 use ::embassy_sync::waitqueue::AtomicWaker;
45 const NEW_AW: AtomicWaker = AtomicWaker::new();
46 static WAKERS: [AtomicWaker; $ccs] = [NEW_AW; $ccs];
47 &WAKERS[n]
48 }
49 } 44 }
50 impl crate::timer::Instance for peripherals::$type { 45 impl crate::timer::Instance for peripherals::$type {
51 type Interrupt = crate::interrupt::$irq; 46 type Interrupt = crate::interrupt::typelevel::$irq;
52 } 47 }
53 }; 48 };
54 ($type:ident, $pac_type:ident, $irq:ident) => { 49 ($type:ident, $pac_type:ident, $irq:ident) => {
@@ -61,85 +56,77 @@ macro_rules! impl_timer {
61 }; 56 };
62} 57}
63 58
59/// Timer frequency
64#[repr(u8)] 60#[repr(u8)]
65pub enum Frequency { 61pub enum Frequency {
66 // I'd prefer not to prefix these with `F`, but Rust identifiers can't start with digits. 62 /// 16MHz
67 F16MHz = 0, 63 F16MHz = 0,
64 /// 8MHz
68 F8MHz = 1, 65 F8MHz = 1,
66 /// 4MHz
69 F4MHz = 2, 67 F4MHz = 2,
68 /// 2MHz
70 F2MHz = 3, 69 F2MHz = 3,
70 /// 1MHz
71 F1MHz = 4, 71 F1MHz = 4,
72 /// 500kHz
72 F500kHz = 5, 73 F500kHz = 5,
74 /// 250kHz
73 F250kHz = 6, 75 F250kHz = 6,
76 /// 125kHz
74 F125kHz = 7, 77 F125kHz = 7,
78 /// 62500Hz
75 F62500Hz = 8, 79 F62500Hz = 8,
80 /// 31250Hz
76 F31250Hz = 9, 81 F31250Hz = 9,
77} 82}
78 83
79/// nRF Timer driver. 84/// nRF Timer driver.
80/// 85///
81/// The timer has an internal counter, which is incremented for every tick of the timer. 86/// The timer has an internal counter, which is incremented for every tick of the timer.
82/// The counter is 32-bit, so it wraps back to 0 at 4294967296. 87/// The counter is 32-bit, so it wraps back to 0 when it reaches 2^32.
83/// 88///
84/// It has either 4 or 6 Capture/Compare registers, which can be used to capture the current state of the counter 89/// It has either 4 or 6 Capture/Compare registers, which can be used to capture the current state of the counter
85/// or trigger an event when the counter reaches a certain value. 90/// or trigger an event when the counter reaches a certain value.
86 91
87pub trait TimerType: sealed::TimerType {} 92/// Timer driver.
88 93pub struct Timer<'d, T: Instance> {
89pub enum Awaitable {}
90pub enum NotAwaitable {}
91
92impl sealed::TimerType for Awaitable {}
93impl sealed::TimerType for NotAwaitable {}
94impl TimerType for Awaitable {}
95impl TimerType for NotAwaitable {}
96
97pub struct Timer<'d, T: Instance, I: TimerType = NotAwaitable> {
98 _p: PeripheralRef<'d, T>, 94 _p: PeripheralRef<'d, T>,
99 _i: PhantomData<I>,
100} 95}
101 96
102impl<'d, T: Instance> Timer<'d, T, Awaitable> { 97impl<'d, T: Instance> Timer<'d, T> {
103 pub fn new_awaitable(timer: impl Peripheral<P = T> + 'd, irq: impl Peripheral<P = T::Interrupt> + 'd) -> Self { 98 /// Create a new `Timer` driver.
104 into_ref!(irq);
105
106 irq.set_handler(Self::on_interrupt);
107 irq.unpend();
108 irq.enable();
109
110 Self::new_irqless(timer)
111 }
112}
113impl<'d, T: Instance> Timer<'d, T, NotAwaitable> {
114 /// Create a `Timer` without an interrupt, meaning `Cc::wait` won't work.
115 /// 99 ///
116 /// This can be useful for triggering tasks via PPI 100 /// This can be useful for triggering tasks via PPI
117 /// `Uarte` uses this internally. 101 /// `Uarte` uses this internally.
118 pub fn new(timer: impl Peripheral<P = T> + 'd) -> Self { 102 pub fn new(timer: impl Peripheral<P = T> + 'd) -> Self {
119 Self::new_irqless(timer) 103 Self::new_inner(timer, false)
120 } 104 }
121}
122 105
123impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> { 106 /// Create a new `Timer` driver in counter mode.
124 /// Create a `Timer` without an interrupt, meaning `Cc::wait` won't work.
125 /// 107 ///
126 /// This is used by the public constructors. 108 /// This can be useful for triggering tasks via PPI
127 fn new_irqless(timer: impl Peripheral<P = T> + 'd) -> Self { 109 /// `Uarte` uses this internally.
110 pub fn new_counter(timer: impl Peripheral<P = T> + 'd) -> Self {
111 Self::new_inner(timer, true)
112 }
113
114 fn new_inner(timer: impl Peripheral<P = T> + 'd, is_counter: bool) -> Self {
128 into_ref!(timer); 115 into_ref!(timer);
129 116
130 let regs = T::regs(); 117 let regs = T::regs();
131 118
132 let mut this = Self { 119 let this = Self { _p: timer };
133 _p: timer,
134 _i: PhantomData,
135 };
136 120
137 // Stop the timer before doing anything else, 121 // Stop the timer before doing anything else,
138 // since changing BITMODE while running can cause 'unpredictable behaviour' according to the specification. 122 // since changing BITMODE while running can cause 'unpredictable behaviour' according to the specification.
139 this.stop(); 123 this.stop();
140 124
141 // Set the instance to timer mode. 125 if is_counter {
142 regs.mode.write(|w| w.mode().timer()); 126 regs.mode.write(|w| w.mode().low_power_counter());
127 } else {
128 regs.mode.write(|w| w.mode().timer());
129 }
143 130
144 // Make the counter's max value as high as possible. 131 // Make the counter's max value as high as possible.
145 // TODO: is there a reason someone would want to set this lower? 132 // TODO: is there a reason someone would want to set this lower?
@@ -181,24 +168,32 @@ impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> {
181 /// Returns the START task, for use with PPI. 168 /// Returns the START task, for use with PPI.
182 /// 169 ///
183 /// When triggered, this task starts the timer. 170 /// When triggered, this task starts the timer.
184 pub fn task_start(&self) -> Task { 171 pub fn task_start(&self) -> Task<'d> {
185 Task::from_reg(&T::regs().tasks_start) 172 Task::from_reg(&T::regs().tasks_start)
186 } 173 }
187 174
188 /// Returns the STOP task, for use with PPI. 175 /// Returns the STOP task, for use with PPI.
189 /// 176 ///
190 /// When triggered, this task stops the timer. 177 /// When triggered, this task stops the timer.
191 pub fn task_stop(&self) -> Task { 178 pub fn task_stop(&self) -> Task<'d> {
192 Task::from_reg(&T::regs().tasks_stop) 179 Task::from_reg(&T::regs().tasks_stop)
193 } 180 }
194 181
195 /// Returns the CLEAR task, for use with PPI. 182 /// Returns the CLEAR task, for use with PPI.
196 /// 183 ///
197 /// When triggered, this task resets the timer's counter to 0. 184 /// When triggered, this task resets the timer's counter to 0.
198 pub fn task_clear(&self) -> Task { 185 pub fn task_clear(&self) -> Task<'d> {
199 Task::from_reg(&T::regs().tasks_clear) 186 Task::from_reg(&T::regs().tasks_clear)
200 } 187 }
201 188
189 /// Returns the COUNT task, for use with PPI.
190 ///
191 /// When triggered, this task increments the timer's counter by 1.
192 /// Only works in counter mode.
193 pub fn task_count(&self) -> Task<'d> {
194 Task::from_reg(&T::regs().tasks_count)
195 }
196
202 /// Change the timer's frequency. 197 /// Change the timer's frequency.
203 /// 198 ///
204 /// This will stop the timer if it isn't already stopped, 199 /// This will stop the timer if it isn't already stopped,
@@ -213,31 +208,17 @@ impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> {
213 .write(|w| unsafe { w.prescaler().bits(frequency as u8) }) 208 .write(|w| unsafe { w.prescaler().bits(frequency as u8) })
214 } 209 }
215 210
216 fn on_interrupt(_: *mut ()) {
217 let regs = T::regs();
218 for n in 0..T::CCS {
219 if regs.events_compare[n].read().bits() != 0 {
220 // Clear the interrupt, otherwise the interrupt will be repeatedly raised as soon as the interrupt handler exits.
221 // We can't clear the event, because it's used to poll whether the future is done or still pending.
222 regs.intenclr
223 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << (16 + n))) });
224 T::waker(n).wake();
225 }
226 }
227 }
228
229 /// Returns this timer's `n`th CC register. 211 /// Returns this timer's `n`th CC register.
230 /// 212 ///
231 /// # Panics 213 /// # Panics
232 /// Panics if `n` >= the number of CC registers this timer has (4 for a normal timer, 6 for an extended timer). 214 /// Panics if `n` >= the number of CC registers this timer has (4 for a normal timer, 6 for an extended timer).
233 pub fn cc(&mut self, n: usize) -> Cc<T, I> { 215 pub fn cc(&self, n: usize) -> Cc<'d, T> {
234 if n >= T::CCS { 216 if n >= T::CCS {
235 panic!("Cannot get CC register {} of timer with {} CC registers.", n, T::CCS); 217 panic!("Cannot get CC register {} of timer with {} CC registers.", n, T::CCS);
236 } 218 }
237 Cc { 219 Cc {
238 n, 220 n,
239 _p: self._p.reborrow(), 221 _p: unsafe { self._p.clone_unchecked() },
240 _i: PhantomData,
241 } 222 }
242 } 223 }
243} 224}
@@ -249,49 +230,12 @@ impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> {
249/// 230///
250/// The timer will fire the register's COMPARE event when its counter reaches the value stored in the register. 231/// The timer will fire the register's COMPARE event when its counter reaches the value stored in the register.
251/// When the register's CAPTURE task is triggered, the timer will store the current value of its counter in the register 232/// When the register's CAPTURE task is triggered, the timer will store the current value of its counter in the register
252pub struct Cc<'d, T: Instance, I: TimerType = NotAwaitable> { 233pub struct Cc<'d, T: Instance> {
253 n: usize, 234 n: usize,
254 _p: PeripheralRef<'d, T>, 235 _p: PeripheralRef<'d, T>,
255 _i: PhantomData<I>,
256}
257
258impl<'d, T: Instance> Cc<'d, T, Awaitable> {
259 /// Wait until the timer's counter reaches the value stored in this register.
260 ///
261 /// This requires a mutable reference so that this task's waker cannot be overwritten by a second call to `wait`.
262 pub async fn wait(&mut self) {
263 let regs = T::regs();
264
265 // Enable the interrupt for this CC's COMPARE event.
266 regs.intenset
267 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << (16 + self.n))) });
268
269 // Disable the interrupt if the future is dropped.
270 let on_drop = OnDrop::new(|| {
271 regs.intenclr
272 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << (16 + self.n))) });
273 });
274
275 poll_fn(|cx| {
276 T::waker(self.n).register(cx.waker());
277
278 if regs.events_compare[self.n].read().bits() != 0 {
279 // Reset the register for next time
280 regs.events_compare[self.n].reset();
281 Poll::Ready(())
282 } else {
283 Poll::Pending
284 }
285 })
286 .await;
287
288 // The interrupt was already disabled in the interrupt handler, so there's no need to disable it again.
289 on_drop.defuse();
290 }
291} 236}
292impl<'d, T: Instance> Cc<'d, T, NotAwaitable> {}
293 237
294impl<'d, T: Instance, I: TimerType> Cc<'d, T, I> { 238impl<'d, T: Instance> Cc<'d, T> {
295 /// Get the current value stored in the register. 239 /// Get the current value stored in the register.
296 pub fn read(&self) -> u32 { 240 pub fn read(&self) -> u32 {
297 T::regs().cc[self.n].read().cc().bits() 241 T::regs().cc[self.n].read().cc().bits()
@@ -314,14 +258,14 @@ impl<'d, T: Instance, I: TimerType> Cc<'d, T, I> {
314 /// Returns this CC register's CAPTURE task, for use with PPI. 258 /// Returns this CC register's CAPTURE task, for use with PPI.
315 /// 259 ///
316 /// When triggered, this task will capture the current value of the timer's counter in this register. 260 /// When triggered, this task will capture the current value of the timer's counter in this register.
317 pub fn task_capture(&self) -> Task { 261 pub fn task_capture(&self) -> Task<'d> {
318 Task::from_reg(&T::regs().tasks_capture) 262 Task::from_reg(&T::regs().tasks_capture)
319 } 263 }
320 264
321 /// Returns this CC register's COMPARE event, for use with PPI. 265 /// Returns this CC register's COMPARE event, for use with PPI.
322 /// 266 ///
323 /// This event will fire when the timer's counter reaches the value in this CC register. 267 /// This event will fire when the timer's counter reaches the value in this CC register.
324 pub fn event_compare(&self) -> Event { 268 pub fn event_compare(&self) -> Event<'d> {
325 Event::from_reg(&T::regs().events_compare[self.n]) 269 Event::from_reg(&T::regs().events_compare[self.n])
326 } 270 }
327 271
diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs
index 850f6d0fa..2ad0d19b1 100644
--- a/embassy-nrf/src/twim.rs
+++ b/embassy-nrf/src/twim.rs
@@ -1,12 +1,9 @@
1//! I2C-compatible Two Wire Interface in master mode (TWIM) driver.
2
1#![macro_use] 3#![macro_use]
2 4
3//! HAL interface to the TWIM peripheral. 5use core::future::{poll_fn, Future};
4//! 6use core::marker::PhantomData;
5//! See product specification:
6//!
7//! - nRF52832: Section 33
8//! - nRF52840: Section 6.31
9use core::future::Future;
10use core::sync::atomic::compiler_fence; 7use core::sync::atomic::compiler_fence;
11use core::sync::atomic::Ordering::SeqCst; 8use core::sync::atomic::Ordering::SeqCst;
12use core::task::Poll; 9use core::task::Poll;
@@ -16,30 +13,46 @@ use embassy_hal_common::{into_ref, PeripheralRef};
16use embassy_sync::waitqueue::AtomicWaker; 13use embassy_sync::waitqueue::AtomicWaker;
17#[cfg(feature = "time")] 14#[cfg(feature = "time")]
18use embassy_time::{Duration, Instant}; 15use embassy_time::{Duration, Instant};
19use futures::future::poll_fn;
20 16
21use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; 17use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
22use crate::gpio::Pin as GpioPin; 18use crate::gpio::Pin as GpioPin;
23use crate::interrupt::{Interrupt, InterruptExt}; 19use crate::interrupt::typelevel::Interrupt;
24use crate::util::{slice_in_ram, slice_in_ram_or}; 20use crate::util::{slice_in_ram, slice_in_ram_or};
25use crate::{gpio, pac, Peripheral}; 21use crate::{gpio, interrupt, pac, Peripheral};
26 22
23/// TWI frequency
27#[derive(Clone, Copy)] 24#[derive(Clone, Copy)]
28pub enum Frequency { 25pub enum Frequency {
29 #[doc = "26738688: 100 kbps"] 26 /// 100 kbps
30 K100 = 26738688, 27 K100 = 26738688,
31 #[doc = "67108864: 250 kbps"] 28 /// 250 kbps
32 K250 = 67108864, 29 K250 = 67108864,
33 #[doc = "104857600: 400 kbps"] 30 /// 400 kbps
34 K400 = 104857600, 31 K400 = 104857600,
35} 32}
36 33
34/// TWIM config.
37#[non_exhaustive] 35#[non_exhaustive]
38pub struct Config { 36pub struct Config {
37 /// Frequency
39 pub frequency: Frequency, 38 pub frequency: Frequency,
39
40 /// Enable high drive for the SDA line.
40 pub sda_high_drive: bool, 41 pub sda_high_drive: bool,
42
43 /// Enable internal pullup for the SDA line.
44 ///
45 /// Note that using external pullups is recommended for I2C, and
46 /// most boards already have them.
41 pub sda_pullup: bool, 47 pub sda_pullup: bool,
48
49 /// Enable high drive for the SCL line.
42 pub scl_high_drive: bool, 50 pub scl_high_drive: bool,
51
52 /// Enable internal pullup for the SCL line.
53 ///
54 /// Note that using external pullups is recommended for I2C, and
55 /// most boards already have them.
43 pub scl_pullup: bool, 56 pub scl_pullup: bool,
44} 57}
45 58
@@ -55,37 +68,67 @@ impl Default for Config {
55 } 68 }
56} 69}
57 70
71/// TWI error.
58#[derive(Debug, Copy, Clone, Eq, PartialEq)] 72#[derive(Debug, Copy, Clone, Eq, PartialEq)]
59#[cfg_attr(feature = "defmt", derive(defmt::Format))] 73#[cfg_attr(feature = "defmt", derive(defmt::Format))]
60#[non_exhaustive] 74#[non_exhaustive]
61pub enum Error { 75pub enum Error {
76 /// TX buffer was too long.
62 TxBufferTooLong, 77 TxBufferTooLong,
78 /// RX buffer was too long.
63 RxBufferTooLong, 79 RxBufferTooLong,
80 /// Data transmit failed.
64 Transmit, 81 Transmit,
82 /// Data reception failed.
65 Receive, 83 Receive,
66 DMABufferNotInDataMemory, 84 /// The buffer is not in data RAM. It's most likely in flash, and nRF's DMA cannot access flash.
85 BufferNotInRAM,
86 /// Didn't receive an ACK bit after the address byte. Address might be wrong, or the i2c device chip might not be connected properly.
67 AddressNack, 87 AddressNack,
88 /// Didn't receive an ACK bit after a data byte.
68 DataNack, 89 DataNack,
90 /// Overrun error.
69 Overrun, 91 Overrun,
92 /// Timeout error.
70 Timeout, 93 Timeout,
71} 94}
72 95
73/// Interface to a TWIM instance using EasyDMA to offload the transmission and reception workload. 96/// Interrupt handler.
74/// 97pub struct InterruptHandler<T: Instance> {
75/// For more details about EasyDMA, consult the module documentation. 98 _phantom: PhantomData<T>,
99}
100
101impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
102 unsafe fn on_interrupt() {
103 let r = T::regs();
104 let s = T::state();
105
106 if r.events_stopped.read().bits() != 0 {
107 s.end_waker.wake();
108 r.intenclr.write(|w| w.stopped().clear());
109 }
110 if r.events_error.read().bits() != 0 {
111 s.end_waker.wake();
112 r.intenclr.write(|w| w.error().clear());
113 }
114 }
115}
116
117/// TWI driver.
76pub struct Twim<'d, T: Instance> { 118pub struct Twim<'d, T: Instance> {
77 _p: PeripheralRef<'d, T>, 119 _p: PeripheralRef<'d, T>,
78} 120}
79 121
80impl<'d, T: Instance> Twim<'d, T> { 122impl<'d, T: Instance> Twim<'d, T> {
123 /// Create a new TWI driver.
81 pub fn new( 124 pub fn new(
82 twim: impl Peripheral<P = T> + 'd, 125 twim: impl Peripheral<P = T> + 'd,
83 irq: impl Peripheral<P = T::Interrupt> + 'd, 126 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
84 sda: impl Peripheral<P = impl GpioPin> + 'd, 127 sda: impl Peripheral<P = impl GpioPin> + 'd,
85 scl: impl Peripheral<P = impl GpioPin> + 'd, 128 scl: impl Peripheral<P = impl GpioPin> + 'd,
86 config: Config, 129 config: Config,
87 ) -> Self { 130 ) -> Self {
88 into_ref!(twim, irq, sda, scl); 131 into_ref!(twim, sda, scl);
89 132
90 let r = T::regs(); 133 let r = T::regs();
91 134
@@ -131,30 +174,15 @@ impl<'d, T: Instance> Twim<'d, T> {
131 // Disable all events interrupts 174 // Disable all events interrupts
132 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); 175 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
133 176
134 irq.set_handler(Self::on_interrupt); 177 T::Interrupt::unpend();
135 irq.unpend(); 178 unsafe { T::Interrupt::enable() };
136 irq.enable();
137 179
138 Self { _p: twim } 180 Self { _p: twim }
139 } 181 }
140 182
141 fn on_interrupt(_: *mut ()) {
142 let r = T::regs();
143 let s = T::state();
144
145 if r.events_stopped.read().bits() != 0 {
146 s.end_waker.wake();
147 r.intenclr.write(|w| w.stopped().clear());
148 }
149 if r.events_error.read().bits() != 0 {
150 s.end_waker.wake();
151 r.intenclr.write(|w| w.error().clear());
152 }
153 }
154
155 /// Set TX buffer, checking that it is in RAM and has suitable length. 183 /// Set TX buffer, checking that it is in RAM and has suitable length.
156 unsafe fn set_tx_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> { 184 unsafe fn set_tx_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> {
157 slice_in_ram_or(buffer, Error::DMABufferNotInDataMemory)?; 185 slice_in_ram_or(buffer, Error::BufferNotInRAM)?;
158 186
159 if buffer.len() > EASY_DMA_SIZE { 187 if buffer.len() > EASY_DMA_SIZE {
160 return Err(Error::TxBufferTooLong); 188 return Err(Error::TxBufferTooLong);
@@ -234,7 +262,7 @@ impl<'d, T: Instance> Twim<'d, T> {
234 return Err(Error::DataNack); 262 return Err(Error::DataNack);
235 } 263 }
236 if err.overrun().is_received() { 264 if err.overrun().is_received() {
237 return Err(Error::DataNack); 265 return Err(Error::Overrun);
238 } 266 }
239 Ok(()) 267 Ok(())
240 } 268 }
@@ -308,7 +336,7 @@ impl<'d, T: Instance> Twim<'d, T> {
308 return Poll::Ready(()); 336 return Poll::Ready(());
309 } 337 }
310 338
311 // stop if an error occured 339 // stop if an error occurred
312 if r.events_error.read().bits() != 0 { 340 if r.events_error.read().bits() != 0 {
313 r.events_error.reset(); 341 r.events_error.reset();
314 r.tasks_stop.write(|w| unsafe { w.bits(1) }); 342 r.tasks_stop.write(|w| unsafe { w.bits(1) });
@@ -436,7 +464,7 @@ impl<'d, T: Instance> Twim<'d, T> {
436 ) -> Result<(), Error> { 464 ) -> Result<(), Error> {
437 match self.setup_write_read_from_ram(address, wr_buffer, rd_buffer, inten) { 465 match self.setup_write_read_from_ram(address, wr_buffer, rd_buffer, inten) {
438 Ok(_) => Ok(()), 466 Ok(_) => Ok(()),
439 Err(Error::DMABufferNotInDataMemory) => { 467 Err(Error::BufferNotInRAM) => {
440 trace!("Copying TWIM tx buffer into RAM for DMA"); 468 trace!("Copying TWIM tx buffer into RAM for DMA");
441 let tx_ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..wr_buffer.len()]; 469 let tx_ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..wr_buffer.len()];
442 tx_ram_buf.copy_from_slice(wr_buffer); 470 tx_ram_buf.copy_from_slice(wr_buffer);
@@ -449,7 +477,7 @@ impl<'d, T: Instance> Twim<'d, T> {
449 fn setup_write(&mut self, address: u8, wr_buffer: &[u8], inten: bool) -> Result<(), Error> { 477 fn setup_write(&mut self, address: u8, wr_buffer: &[u8], inten: bool) -> Result<(), Error> {
450 match self.setup_write_from_ram(address, wr_buffer, inten) { 478 match self.setup_write_from_ram(address, wr_buffer, inten) {
451 Ok(_) => Ok(()), 479 Ok(_) => Ok(()),
452 Err(Error::DMABufferNotInDataMemory) => { 480 Err(Error::BufferNotInRAM) => {
453 trace!("Copying TWIM tx buffer into RAM for DMA"); 481 trace!("Copying TWIM tx buffer into RAM for DMA");
454 let tx_ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..wr_buffer.len()]; 482 let tx_ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..wr_buffer.len()];
455 tx_ram_buf.copy_from_slice(wr_buffer); 483 tx_ram_buf.copy_from_slice(wr_buffer);
@@ -613,6 +641,10 @@ impl<'d, T: Instance> Twim<'d, T> {
613 641
614 // =========================================== 642 // ===========================================
615 643
644 /// Read from an I2C slave.
645 ///
646 /// The buffer must have a length of at most 255 bytes on the nRF52832
647 /// and at most 65535 bytes on the nRF52840.
616 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { 648 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
617 self.setup_read(address, buffer, true)?; 649 self.setup_read(address, buffer, true)?;
618 self.async_wait().await; 650 self.async_wait().await;
@@ -622,6 +654,10 @@ impl<'d, T: Instance> Twim<'d, T> {
622 Ok(()) 654 Ok(())
623 } 655 }
624 656
657 /// Write to an I2C slave.
658 ///
659 /// The buffer must have a length of at most 255 bytes on the nRF52832
660 /// and at most 65535 bytes on the nRF52840.
625 pub async fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> { 661 pub async fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> {
626 self.setup_write(address, buffer, true)?; 662 self.setup_write(address, buffer, true)?;
627 self.async_wait().await; 663 self.async_wait().await;
@@ -641,6 +677,11 @@ impl<'d, T: Instance> Twim<'d, T> {
641 Ok(()) 677 Ok(())
642 } 678 }
643 679
680 /// Write data to an I2C slave, then read data from the slave without
681 /// triggering a stop condition between the two.
682 ///
683 /// The buffers must have a length of at most 255 bytes on the nRF52832
684 /// and at most 65535 bytes on the nRF52840.
644 pub async fn write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Error> { 685 pub async fn write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Error> {
645 self.setup_write_read(address, wr_buffer, rd_buffer, true)?; 686 self.setup_write_read(address, wr_buffer, rd_buffer, true)?;
646 self.async_wait().await; 687 self.async_wait().await;
@@ -706,8 +747,10 @@ pub(crate) mod sealed {
706 } 747 }
707} 748}
708 749
750/// TWIM peripheral instance.
709pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static { 751pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static {
710 type Interrupt: Interrupt; 752 /// Interrupt for this peripheral.
753 type Interrupt: interrupt::typelevel::Interrupt;
711} 754}
712 755
713macro_rules! impl_twim { 756macro_rules! impl_twim {
@@ -722,7 +765,7 @@ macro_rules! impl_twim {
722 } 765 }
723 } 766 }
724 impl crate::twim::Instance for peripherals::$type { 767 impl crate::twim::Instance for peripherals::$type {
725 type Interrupt = crate::interrupt::$irq; 768 type Interrupt = crate::interrupt::typelevel::$irq;
726 } 769 }
727 }; 770 };
728} 771}
@@ -777,7 +820,7 @@ mod eh1 {
777 Self::RxBufferTooLong => embedded_hal_1::i2c::ErrorKind::Other, 820 Self::RxBufferTooLong => embedded_hal_1::i2c::ErrorKind::Other,
778 Self::Transmit => embedded_hal_1::i2c::ErrorKind::Other, 821 Self::Transmit => embedded_hal_1::i2c::ErrorKind::Other,
779 Self::Receive => embedded_hal_1::i2c::ErrorKind::Other, 822 Self::Receive => embedded_hal_1::i2c::ErrorKind::Other,
780 Self::DMABufferNotInDataMemory => embedded_hal_1::i2c::ErrorKind::Other, 823 Self::BufferNotInRAM => embedded_hal_1::i2c::ErrorKind::Other,
781 Self::AddressNack => { 824 Self::AddressNack => {
782 embedded_hal_1::i2c::ErrorKind::NoAcknowledge(embedded_hal_1::i2c::NoAcknowledgeSource::Address) 825 embedded_hal_1::i2c::ErrorKind::NoAcknowledge(embedded_hal_1::i2c::NoAcknowledgeSource::Address)
783 } 826 }
@@ -794,7 +837,7 @@ mod eh1 {
794 type Error = Error; 837 type Error = Error;
795 } 838 }
796 839
797 impl<'d, T: Instance> embedded_hal_1::i2c::blocking::I2c for Twim<'d, T> { 840 impl<'d, T: Instance> embedded_hal_1::i2c::I2c for Twim<'d, T> {
798 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { 841 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
799 self.blocking_read(address, buffer) 842 self.blocking_read(address, buffer)
800 } 843 }
@@ -803,20 +846,6 @@ mod eh1 {
803 self.blocking_write(address, buffer) 846 self.blocking_write(address, buffer)
804 } 847 }
805 848
806 fn write_iter<B>(&mut self, _address: u8, _bytes: B) -> Result<(), Self::Error>
807 where
808 B: IntoIterator<Item = u8>,
809 {
810 todo!();
811 }
812
813 fn write_iter_read<B>(&mut self, _address: u8, _bytes: B, _buffer: &mut [u8]) -> Result<(), Self::Error>
814 where
815 B: IntoIterator<Item = u8>,
816 {
817 todo!();
818 }
819
820 fn write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Self::Error> { 849 fn write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Self::Error> {
821 self.blocking_write_read(address, wr_buffer, rd_buffer) 850 self.blocking_write_read(address, wr_buffer, rd_buffer)
822 } 851 }
@@ -824,57 +853,36 @@ mod eh1 {
824 fn transaction<'a>( 853 fn transaction<'a>(
825 &mut self, 854 &mut self,
826 _address: u8, 855 _address: u8,
827 _operations: &mut [embedded_hal_1::i2c::blocking::Operation<'a>], 856 _operations: &mut [embedded_hal_1::i2c::Operation<'a>],
828 ) -> Result<(), Self::Error> { 857 ) -> Result<(), Self::Error> {
829 todo!(); 858 todo!();
830 } 859 }
831
832 fn transaction_iter<'a, O>(&mut self, _address: u8, _operations: O) -> Result<(), Self::Error>
833 where
834 O: IntoIterator<Item = embedded_hal_1::i2c::blocking::Operation<'a>>,
835 {
836 todo!();
837 }
838 } 860 }
839} 861}
840 862
841cfg_if::cfg_if! { 863#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
842 if #[cfg(all(feature = "unstable-traits", feature = "nightly"))] { 864mod eha {
843 impl<'d, T: Instance> embedded_hal_async::i2c::I2c for Twim<'d, T> { 865 use super::*;
844 type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; 866 impl<'d, T: Instance> embedded_hal_async::i2c::I2c for Twim<'d, T> {
845 867 async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
846 fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { 868 self.read(address, read).await
847 self.read(address, buffer) 869 }
848 }
849
850 type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
851
852 fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Self::WriteFuture<'a> {
853 self.write(address, bytes)
854 }
855
856 type WriteReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
857
858 fn write_read<'a>(
859 &'a mut self,
860 address: u8,
861 wr_buffer: &'a [u8],
862 rd_buffer: &'a mut [u8],
863 ) -> Self::WriteReadFuture<'a> {
864 self.write_read(address, wr_buffer, rd_buffer)
865 }
866 870
867 type TransactionFuture<'a, 'b> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a, 'b: 'a; 871 async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
872 self.write(address, write).await
873 }
874 async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
875 self.write_read(address, write, read).await
876 }
868 877
869 fn transaction<'a, 'b>( 878 async fn transaction(
870 &'a mut self, 879 &mut self,
871 address: u8, 880 address: u8,
872 operations: &'a mut [embedded_hal_async::i2c::Operation<'b>], 881 operations: &mut [embedded_hal_1::i2c::Operation<'_>],
873 ) -> Self::TransactionFuture<'a, 'b> { 882 ) -> Result<(), Self::Error> {
874 let _ = address; 883 let _ = address;
875 let _ = operations; 884 let _ = operations;
876 async move { todo!() } 885 todo!()
877 }
878 } 886 }
879 } 887 }
880} 888}
diff --git a/embassy-nrf/src/twis.rs b/embassy-nrf/src/twis.rs
new file mode 100644
index 000000000..a115d5616
--- /dev/null
+++ b/embassy-nrf/src/twis.rs
@@ -0,0 +1,799 @@
1//! I2C-compatible Two Wire Interface in slave mode (TWIM) driver.
2
3#![macro_use]
4
5use core::future::{poll_fn, Future};
6use core::marker::PhantomData;
7use core::sync::atomic::compiler_fence;
8use core::sync::atomic::Ordering::SeqCst;
9use core::task::Poll;
10
11use embassy_hal_common::{into_ref, PeripheralRef};
12use embassy_sync::waitqueue::AtomicWaker;
13#[cfg(feature = "time")]
14use embassy_time::{Duration, Instant};
15
16use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
17use crate::gpio::Pin as GpioPin;
18use crate::interrupt::typelevel::Interrupt;
19use crate::util::slice_in_ram_or;
20use crate::{gpio, interrupt, pac, Peripheral};
21
22/// TWIS config.
23#[non_exhaustive]
24pub struct Config {
25 /// First address
26 pub address0: u8,
27
28 /// Second address, optional.
29 pub address1: Option<u8>,
30
31 /// Overread character.
32 ///
33 /// If the master keeps clocking the bus after all the bytes in the TX buffer have
34 /// already been transmitted, this byte will be constantly transmitted.
35 pub orc: u8,
36
37 /// Enable high drive for the SDA line.
38 pub sda_high_drive: bool,
39
40 /// Enable internal pullup for the SDA line.
41 ///
42 /// Note that using external pullups is recommended for I2C, and
43 /// most boards already have them.
44 pub sda_pullup: bool,
45
46 /// Enable high drive for the SCL line.
47 pub scl_high_drive: bool,
48
49 /// Enable internal pullup for the SCL line.
50 ///
51 /// Note that using external pullups is recommended for I2C, and
52 /// most boards already have them.
53 pub scl_pullup: bool,
54}
55
56impl Default for Config {
57 fn default() -> Self {
58 Self {
59 address0: 0x55,
60 address1: None,
61 orc: 0x00,
62 scl_high_drive: false,
63 sda_pullup: false,
64 sda_high_drive: false,
65 scl_pullup: false,
66 }
67 }
68}
69
70#[derive(Debug, Copy, Clone, Eq, PartialEq)]
71#[cfg_attr(feature = "defmt", derive(defmt::Format))]
72enum Status {
73 Read,
74 Write,
75}
76
77/// TWIS error.
78#[derive(Debug, Copy, Clone, Eq, PartialEq)]
79#[cfg_attr(feature = "defmt", derive(defmt::Format))]
80#[non_exhaustive]
81pub enum Error {
82 /// TX buffer was too long.
83 TxBufferTooLong,
84 /// RX buffer was too long.
85 RxBufferTooLong,
86 /// Didn't receive an ACK bit after a data byte.
87 DataNack,
88 /// Bus error.
89 Bus,
90 /// The buffer is not in data RAM. It's most likely in flash, and nRF's DMA cannot access flash.
91 BufferNotInRAM,
92 /// Overflow
93 Overflow,
94 /// Overread
95 OverRead,
96 /// Timeout
97 Timeout,
98}
99
100/// Received command
101#[derive(Debug, Copy, Clone, Eq, PartialEq)]
102#[cfg_attr(feature = "defmt", derive(defmt::Format))]
103pub enum Command {
104 /// Read
105 Read,
106 /// Write+read
107 WriteRead(usize),
108 /// Write
109 Write(usize),
110}
111
112/// Interrupt handler.
113pub struct InterruptHandler<T: Instance> {
114 _phantom: PhantomData<T>,
115}
116
117impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
118 unsafe fn on_interrupt() {
119 let r = T::regs();
120 let s = T::state();
121
122 if r.events_read.read().bits() != 0 || r.events_write.read().bits() != 0 {
123 s.waker.wake();
124 r.intenclr.modify(|_r, w| w.read().clear().write().clear());
125 }
126 if r.events_stopped.read().bits() != 0 {
127 s.waker.wake();
128 r.intenclr.modify(|_r, w| w.stopped().clear());
129 }
130 if r.events_error.read().bits() != 0 {
131 s.waker.wake();
132 r.intenclr.modify(|_r, w| w.error().clear());
133 }
134 }
135}
136
137/// TWIS driver.
138pub struct Twis<'d, T: Instance> {
139 _p: PeripheralRef<'d, T>,
140}
141
142impl<'d, T: Instance> Twis<'d, T> {
143 /// Create a new TWIS driver.
144 pub fn new(
145 twis: impl Peripheral<P = T> + 'd,
146 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
147 sda: impl Peripheral<P = impl GpioPin> + 'd,
148 scl: impl Peripheral<P = impl GpioPin> + 'd,
149 config: Config,
150 ) -> Self {
151 into_ref!(twis, sda, scl);
152
153 let r = T::regs();
154
155 // Configure pins
156 sda.conf().write(|w| {
157 w.dir().input();
158 w.input().connect();
159 if config.sda_high_drive {
160 w.drive().h0d1();
161 } else {
162 w.drive().s0d1();
163 }
164 if config.sda_pullup {
165 w.pull().pullup();
166 }
167 w
168 });
169 scl.conf().write(|w| {
170 w.dir().input();
171 w.input().connect();
172 if config.scl_high_drive {
173 w.drive().h0d1();
174 } else {
175 w.drive().s0d1();
176 }
177 if config.scl_pullup {
178 w.pull().pullup();
179 }
180 w
181 });
182
183 // Select pins.
184 r.psel.sda.write(|w| unsafe { w.bits(sda.psel_bits()) });
185 r.psel.scl.write(|w| unsafe { w.bits(scl.psel_bits()) });
186
187 // Enable TWIS instance.
188 r.enable.write(|w| w.enable().enabled());
189
190 // Disable all events interrupts
191 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
192
193 // Set address
194 r.address[0].write(|w| unsafe { w.address().bits(config.address0) });
195 r.config.write(|w| w.address0().enabled());
196 if let Some(address1) = config.address1 {
197 r.address[1].write(|w| unsafe { w.address().bits(address1) });
198 r.config.modify(|_r, w| w.address1().enabled());
199 }
200
201 // Set over-read character
202 r.orc.write(|w| unsafe { w.orc().bits(config.orc) });
203
204 // Generate suspend on read event
205 r.shorts.write(|w| w.read_suspend().enabled());
206
207 T::Interrupt::unpend();
208 unsafe { T::Interrupt::enable() };
209
210 Self { _p: twis }
211 }
212
213 /// Set TX buffer, checking that it is in RAM and has suitable length.
214 unsafe fn set_tx_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> {
215 slice_in_ram_or(buffer, Error::BufferNotInRAM)?;
216
217 if buffer.len() > EASY_DMA_SIZE {
218 return Err(Error::TxBufferTooLong);
219 }
220
221 let r = T::regs();
222
223 r.txd.ptr.write(|w|
224 // We're giving the register a pointer to the stack. Since we're
225 // waiting for the I2C transaction to end before this stack pointer
226 // becomes invalid, there's nothing wrong here.
227 //
228 // The PTR field is a full 32 bits wide and accepts the full range
229 // of values.
230 w.ptr().bits(buffer.as_ptr() as u32));
231 r.txd.maxcnt.write(|w|
232 // We're giving it the length of the buffer, so no danger of
233 // accessing invalid memory. We have verified that the length of the
234 // buffer fits in an `u8`, so the cast to `u8` is also fine.
235 //
236 // The MAXCNT field is 8 bits wide and accepts the full range of
237 // values.
238 w.maxcnt().bits(buffer.len() as _));
239
240 Ok(())
241 }
242
243 /// Set RX buffer, checking that it has suitable length.
244 unsafe fn set_rx_buffer(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
245 // NOTE: RAM slice check is not necessary, as a mutable
246 // slice can only be built from data located in RAM.
247
248 if buffer.len() > EASY_DMA_SIZE {
249 return Err(Error::RxBufferTooLong);
250 }
251
252 let r = T::regs();
253
254 r.rxd.ptr.write(|w|
255 // 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
257 // becomes invalid, there's nothing wrong here.
258 //
259 // The PTR field is a full 32 bits wide and accepts the full range
260 // of values.
261 w.ptr().bits(buffer.as_mut_ptr() as u32));
262 r.rxd.maxcnt.write(|w|
263 // We're giving it the length of the buffer, so no danger of
264 // accessing invalid memory. We have verified that the length of the
265 // buffer fits in an `u8`, so the cast to the type of maxcnt
266 // is also fine.
267 //
268 // Note that that nrf52840 maxcnt is a wider
269 // type than a u8, so we use a `_` cast rather than a `u8` cast.
270 // The MAXCNT field is thus at least 8 bits wide and accepts the
271 // full range of values that fit in a `u8`.
272 w.maxcnt().bits(buffer.len() as _));
273
274 Ok(())
275 }
276
277 fn clear_errorsrc(&mut self) {
278 let r = T::regs();
279 r.errorsrc
280 .write(|w| w.overflow().bit(true).overread().bit(true).dnack().bit(true));
281 }
282
283 /// Returns matched address for latest command.
284 pub fn address_match(&self) -> u8 {
285 let r = T::regs();
286 r.address[r.match_.read().bits() as usize].read().address().bits()
287 }
288
289 /// Returns the index of the address matched in the latest command.
290 pub fn address_match_index(&self) -> usize {
291 T::regs().match_.read().bits() as _
292 }
293
294 /// Wait for read, write, stop or error
295 fn blocking_listen_wait(&mut self) -> Result<Status, Error> {
296 let r = T::regs();
297 loop {
298 if r.events_error.read().bits() != 0 {
299 r.events_error.reset();
300 r.tasks_stop.write(|w| unsafe { w.bits(1) });
301 while r.events_stopped.read().bits() == 0 {}
302 return Err(Error::Overflow);
303 }
304 if r.events_stopped.read().bits() != 0 {
305 r.events_stopped.reset();
306 return Err(Error::Bus);
307 }
308 if r.events_read.read().bits() != 0 {
309 r.events_read.reset();
310 return Ok(Status::Read);
311 }
312 if r.events_write.read().bits() != 0 {
313 r.events_write.reset();
314 return Ok(Status::Write);
315 }
316 }
317 }
318
319 /// Wait for stop, repeated start or error
320 fn blocking_listen_wait_end(&mut self, status: Status) -> Result<Command, Error> {
321 let r = T::regs();
322 loop {
323 // stop if an error occurred
324 if r.events_error.read().bits() != 0 {
325 r.events_error.reset();
326 r.tasks_stop.write(|w| unsafe { w.bits(1) });
327 return Err(Error::Overflow);
328 } else if r.events_stopped.read().bits() != 0 {
329 r.events_stopped.reset();
330 return match status {
331 Status::Read => Ok(Command::Read),
332 Status::Write => {
333 let n = r.rxd.amount.read().bits() as usize;
334 Ok(Command::Write(n))
335 }
336 };
337 } else if r.events_read.read().bits() != 0 {
338 r.events_read.reset();
339 let n = r.rxd.amount.read().bits() as usize;
340 return Ok(Command::WriteRead(n));
341 }
342 }
343 }
344
345 /// Wait for stop or error
346 fn blocking_wait(&mut self) -> Result<usize, Error> {
347 let r = T::regs();
348 loop {
349 // stop if an error occurred
350 if r.events_error.read().bits() != 0 {
351 r.events_error.reset();
352 r.tasks_stop.write(|w| unsafe { w.bits(1) });
353 let errorsrc = r.errorsrc.read();
354 if errorsrc.overread().is_detected() {
355 return Err(Error::OverRead);
356 } else if errorsrc.dnack().is_received() {
357 return Err(Error::DataNack);
358 } else {
359 return Err(Error::Bus);
360 }
361 } else if r.events_stopped.read().bits() != 0 {
362 r.events_stopped.reset();
363 let n = r.txd.amount.read().bits() as usize;
364 return Ok(n);
365 }
366 }
367 }
368
369 /// Wait for stop or error with timeout
370 #[cfg(feature = "time")]
371 fn blocking_wait_timeout(&mut self, timeout: Duration) -> Result<usize, Error> {
372 let r = T::regs();
373 let deadline = Instant::now() + timeout;
374 loop {
375 // stop if an error occurred
376 if r.events_error.read().bits() != 0 {
377 r.events_error.reset();
378 r.tasks_stop.write(|w| unsafe { w.bits(1) });
379 let errorsrc = r.errorsrc.read();
380 if errorsrc.overread().is_detected() {
381 return Err(Error::OverRead);
382 } else if errorsrc.dnack().is_received() {
383 return Err(Error::DataNack);
384 } else {
385 return Err(Error::Bus);
386 }
387 } else if r.events_stopped.read().bits() != 0 {
388 r.events_stopped.reset();
389 let n = r.txd.amount.read().bits() as usize;
390 return Ok(n);
391 } else if Instant::now() > deadline {
392 r.tasks_stop.write(|w| unsafe { w.bits(1) });
393 return Err(Error::Timeout);
394 }
395 }
396 }
397
398 /// Wait for read, write, stop or error with timeout
399 #[cfg(feature = "time")]
400 fn blocking_listen_wait_timeout(&mut self, timeout: Duration) -> Result<Status, Error> {
401 let r = T::regs();
402 let deadline = Instant::now() + timeout;
403 loop {
404 if r.events_error.read().bits() != 0 {
405 r.events_error.reset();
406 r.tasks_stop.write(|w| unsafe { w.bits(1) });
407 while r.events_stopped.read().bits() == 0 {}
408 return Err(Error::Overflow);
409 }
410 if r.events_stopped.read().bits() != 0 {
411 r.events_stopped.reset();
412 return Err(Error::Bus);
413 }
414 if r.events_read.read().bits() != 0 {
415 r.events_read.reset();
416 return Ok(Status::Read);
417 }
418 if r.events_write.read().bits() != 0 {
419 r.events_write.reset();
420 return Ok(Status::Write);
421 }
422 if Instant::now() > deadline {
423 r.tasks_stop.write(|w| unsafe { w.bits(1) });
424 return Err(Error::Timeout);
425 }
426 }
427 }
428
429 /// Wait for stop, repeated start or error with timeout
430 #[cfg(feature = "time")]
431 fn blocking_listen_wait_end_timeout(&mut self, status: Status, timeout: Duration) -> Result<Command, Error> {
432 let r = T::regs();
433 let deadline = Instant::now() + timeout;
434 loop {
435 // stop if an error occurred
436 if r.events_error.read().bits() != 0 {
437 r.events_error.reset();
438 r.tasks_stop.write(|w| unsafe { w.bits(1) });
439 return Err(Error::Overflow);
440 } else if r.events_stopped.read().bits() != 0 {
441 r.events_stopped.reset();
442 return match status {
443 Status::Read => Ok(Command::Read),
444 Status::Write => {
445 let n = r.rxd.amount.read().bits() as usize;
446 Ok(Command::Write(n))
447 }
448 };
449 } else if r.events_read.read().bits() != 0 {
450 r.events_read.reset();
451 let n = r.rxd.amount.read().bits() as usize;
452 return Ok(Command::WriteRead(n));
453 } else if Instant::now() > deadline {
454 r.tasks_stop.write(|w| unsafe { w.bits(1) });
455 return Err(Error::Timeout);
456 }
457 }
458 }
459
460 /// Wait for stop or error
461 fn async_wait(&mut self) -> impl Future<Output = Result<usize, Error>> {
462 poll_fn(move |cx| {
463 let r = T::regs();
464 let s = T::state();
465
466 s.waker.register(cx.waker());
467
468 // stop if an error occurred
469 if r.events_error.read().bits() != 0 {
470 r.events_error.reset();
471 r.tasks_stop.write(|w| unsafe { w.bits(1) });
472 let errorsrc = r.errorsrc.read();
473 if errorsrc.overread().is_detected() {
474 return Poll::Ready(Err(Error::OverRead));
475 } else if errorsrc.dnack().is_received() {
476 return Poll::Ready(Err(Error::DataNack));
477 } else {
478 return Poll::Ready(Err(Error::Bus));
479 }
480 } else if r.events_stopped.read().bits() != 0 {
481 r.events_stopped.reset();
482 let n = r.txd.amount.read().bits() as usize;
483 return Poll::Ready(Ok(n));
484 }
485
486 Poll::Pending
487 })
488 }
489
490 /// Wait for read or write
491 fn async_listen_wait(&mut self) -> impl Future<Output = Result<Status, Error>> {
492 poll_fn(move |cx| {
493 let r = T::regs();
494 let s = T::state();
495
496 s.waker.register(cx.waker());
497
498 // stop if an error occurred
499 if r.events_error.read().bits() != 0 {
500 r.events_error.reset();
501 r.tasks_stop.write(|w| unsafe { w.bits(1) });
502 return Poll::Ready(Err(Error::Overflow));
503 } else if r.events_read.read().bits() != 0 {
504 r.events_read.reset();
505 return Poll::Ready(Ok(Status::Read));
506 } else if r.events_write.read().bits() != 0 {
507 r.events_write.reset();
508 return Poll::Ready(Ok(Status::Write));
509 } else if r.events_stopped.read().bits() != 0 {
510 r.events_stopped.reset();
511 return Poll::Ready(Err(Error::Bus));
512 }
513 Poll::Pending
514 })
515 }
516
517 /// Wait for stop, repeated start or error
518 fn async_listen_wait_end(&mut self, status: Status) -> impl Future<Output = Result<Command, Error>> {
519 poll_fn(move |cx| {
520 let r = T::regs();
521 let s = T::state();
522
523 s.waker.register(cx.waker());
524
525 // stop if an error occurred
526 if r.events_error.read().bits() != 0 {
527 r.events_error.reset();
528 r.tasks_stop.write(|w| unsafe { w.bits(1) });
529 return Poll::Ready(Err(Error::Overflow));
530 } else if r.events_stopped.read().bits() != 0 {
531 r.events_stopped.reset();
532 return match status {
533 Status::Read => Poll::Ready(Ok(Command::Read)),
534 Status::Write => {
535 let n = r.rxd.amount.read().bits() as usize;
536 Poll::Ready(Ok(Command::Write(n)))
537 }
538 };
539 } else if r.events_read.read().bits() != 0 {
540 r.events_read.reset();
541 let n = r.rxd.amount.read().bits() as usize;
542 return Poll::Ready(Ok(Command::WriteRead(n)));
543 }
544 Poll::Pending
545 })
546 }
547
548 fn setup_respond_from_ram(&mut self, buffer: &[u8], inten: bool) -> Result<(), Error> {
549 let r = T::regs();
550
551 compiler_fence(SeqCst);
552
553 // Set up the DMA write.
554 unsafe { self.set_tx_buffer(buffer)? };
555
556 // Clear events
557 r.events_stopped.reset();
558 r.events_error.reset();
559 self.clear_errorsrc();
560
561 if inten {
562 r.intenset.write(|w| w.stopped().set().error().set());
563 } else {
564 r.intenclr.write(|w| w.stopped().clear().error().clear());
565 }
566
567 // Start write operation.
568 r.tasks_preparetx.write(|w| unsafe { w.bits(1) });
569 r.tasks_resume.write(|w| unsafe { w.bits(1) });
570 Ok(())
571 }
572
573 fn setup_respond(&mut self, wr_buffer: &[u8], inten: bool) -> Result<(), Error> {
574 match self.setup_respond_from_ram(wr_buffer, inten) {
575 Ok(_) => Ok(()),
576 Err(Error::BufferNotInRAM) => {
577 trace!("Copying TWIS tx buffer into RAM for DMA");
578 let tx_ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..wr_buffer.len()];
579 tx_ram_buf.copy_from_slice(wr_buffer);
580 self.setup_respond_from_ram(&tx_ram_buf, inten)
581 }
582 Err(error) => Err(error),
583 }
584 }
585
586 fn setup_listen(&mut self, buffer: &mut [u8], inten: bool) -> Result<(), Error> {
587 let r = T::regs();
588 compiler_fence(SeqCst);
589
590 // Set up the DMA read.
591 unsafe { self.set_rx_buffer(buffer)? };
592
593 // Clear events
594 r.events_read.reset();
595 r.events_write.reset();
596 r.events_stopped.reset();
597 r.events_error.reset();
598 self.clear_errorsrc();
599
600 if inten {
601 r.intenset
602 .write(|w| w.stopped().set().error().set().read().set().write().set());
603 } else {
604 r.intenclr
605 .write(|w| w.stopped().clear().error().clear().read().clear().write().clear());
606 }
607
608 // Start read operation.
609 r.tasks_preparerx.write(|w| unsafe { w.bits(1) });
610
611 Ok(())
612 }
613
614 fn setup_listen_end(&mut self, inten: bool) -> Result<(), Error> {
615 let r = T::regs();
616 compiler_fence(SeqCst);
617
618 // Clear events
619 r.events_read.reset();
620 r.events_write.reset();
621 r.events_stopped.reset();
622 r.events_error.reset();
623 self.clear_errorsrc();
624
625 if inten {
626 r.intenset.write(|w| w.stopped().set().error().set().read().set());
627 } else {
628 r.intenclr.write(|w| w.stopped().clear().error().clear().read().clear());
629 }
630
631 Ok(())
632 }
633
634 /// Wait for commands from an I2C master.
635 /// `buffer` is provided in case master does a 'write' and is unused for 'read'.
636 /// The buffer must have a length of at most 255 bytes on the nRF52832
637 /// and at most 65535 bytes on the nRF52840.
638 /// To know which one of the addresses were matched, call `address_match` or `address_match_index`
639 pub fn blocking_listen(&mut self, buffer: &mut [u8]) -> Result<Command, Error> {
640 self.setup_listen(buffer, false)?;
641 let status = self.blocking_listen_wait()?;
642 if status == Status::Write {
643 self.setup_listen_end(false)?;
644 let command = self.blocking_listen_wait_end(status)?;
645 return Ok(command);
646 }
647 Ok(Command::Read)
648 }
649
650 /// Respond to an I2C master READ command.
651 /// Returns the number of bytes written.
652 /// The buffer must have a length of at most 255 bytes on the nRF52832
653 /// and at most 65535 bytes on the nRF52840.
654 pub fn blocking_respond_to_read(&mut self, buffer: &[u8]) -> Result<usize, Error> {
655 self.setup_respond(buffer, false)?;
656 self.blocking_wait()
657 }
658
659 /// Same as [`blocking_respond_to_read`](Twis::blocking_respond_to_read) but will fail instead of copying data into RAM.
660 /// Consult the module level documentation to learn more.
661 pub fn blocking_respond_to_read_from_ram(&mut self, buffer: &[u8]) -> Result<usize, Error> {
662 self.setup_respond_from_ram(buffer, false)?;
663 self.blocking_wait()
664 }
665
666 // ===========================================
667
668 /// Wait for commands from an I2C master, with timeout.
669 /// `buffer` is provided in case master does a 'write' and is unused for 'read'.
670 /// The buffer must have a length of at most 255 bytes on the nRF52832
671 /// and at most 65535 bytes on the nRF52840.
672 /// To know which one of the addresses were matched, call `address_match` or `address_match_index`
673 #[cfg(feature = "time")]
674 pub fn blocking_listen_timeout(&mut self, buffer: &mut [u8], timeout: Duration) -> Result<Command, Error> {
675 self.setup_listen(buffer, false)?;
676 let status = self.blocking_listen_wait_timeout(timeout)?;
677 if status == Status::Write {
678 self.setup_listen_end(false)?;
679 let command = self.blocking_listen_wait_end_timeout(status, timeout)?;
680 return Ok(command);
681 }
682 Ok(Command::Read)
683 }
684
685 /// Respond to an I2C master READ command with timeout.
686 /// Returns the number of bytes written.
687 /// See [`blocking_respond_to_read`].
688 #[cfg(feature = "time")]
689 pub fn blocking_respond_to_read_timeout(&mut self, buffer: &[u8], timeout: Duration) -> Result<usize, Error> {
690 self.setup_respond(buffer, false)?;
691 self.blocking_wait_timeout(timeout)
692 }
693
694 /// Same as [`blocking_respond_to_read_timeout`](Twis::blocking_respond_to_read_timeout) but will fail instead of copying data into RAM.
695 /// Consult the module level documentation to learn more.
696 #[cfg(feature = "time")]
697 pub fn blocking_respond_to_read_from_ram_timeout(
698 &mut self,
699 buffer: &[u8],
700 timeout: Duration,
701 ) -> Result<usize, Error> {
702 self.setup_respond_from_ram(buffer, false)?;
703 self.blocking_wait_timeout(timeout)
704 }
705
706 // ===========================================
707
708 /// Wait asynchronously for commands from an I2C master.
709 /// `buffer` is provided in case master does a 'write' and is unused for 'read'.
710 /// The buffer must have a length of at most 255 bytes on the nRF52832
711 /// and at most 65535 bytes on the nRF52840.
712 /// To know which one of the addresses were matched, call `address_match` or `address_match_index`
713 pub async fn listen(&mut self, buffer: &mut [u8]) -> Result<Command, Error> {
714 self.setup_listen(buffer, true)?;
715 let status = self.async_listen_wait().await?;
716 if status == Status::Write {
717 self.setup_listen_end(true)?;
718 let command = self.async_listen_wait_end(status).await?;
719 return Ok(command);
720 }
721 Ok(Command::Read)
722 }
723
724 /// Respond to an I2C master READ command, asynchronously.
725 /// Returns the number of bytes written.
726 /// The buffer must have a length of at most 255 bytes on the nRF52832
727 /// and at most 65535 bytes on the nRF52840.
728 pub async fn respond_to_read(&mut self, buffer: &[u8]) -> Result<usize, Error> {
729 self.setup_respond(buffer, true)?;
730 self.async_wait().await
731 }
732
733 /// Same as [`respond_to_read`](Twis::respond_to_read) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
734 pub async fn respond_to_read_from_ram(&mut self, buffer: &[u8]) -> Result<usize, Error> {
735 self.setup_respond_from_ram(buffer, true)?;
736 self.async_wait().await
737 }
738}
739
740impl<'a, T: Instance> Drop for Twis<'a, T> {
741 fn drop(&mut self) {
742 trace!("twis drop");
743
744 // TODO: check for abort
745
746 // disable!
747 let r = T::regs();
748 r.enable.write(|w| w.enable().disabled());
749
750 gpio::deconfigure_pin(r.psel.sda.read().bits());
751 gpio::deconfigure_pin(r.psel.scl.read().bits());
752
753 trace!("twis drop: done");
754 }
755}
756
757pub(crate) mod sealed {
758 use super::*;
759
760 pub struct State {
761 pub waker: AtomicWaker,
762 }
763
764 impl State {
765 pub const fn new() -> Self {
766 Self {
767 waker: AtomicWaker::new(),
768 }
769 }
770 }
771
772 pub trait Instance {
773 fn regs() -> &'static pac::twis0::RegisterBlock;
774 fn state() -> &'static State;
775 }
776}
777
778/// TWIS peripheral instance.
779pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static {
780 /// Interrupt for this peripheral.
781 type Interrupt: interrupt::typelevel::Interrupt;
782}
783
784macro_rules! impl_twis {
785 ($type:ident, $pac_type:ident, $irq:ident) => {
786 impl crate::twis::sealed::Instance for peripherals::$type {
787 fn regs() -> &'static pac::twis0::RegisterBlock {
788 unsafe { &*pac::$pac_type::ptr() }
789 }
790 fn state() -> &'static crate::twis::sealed::State {
791 static STATE: crate::twis::sealed::State = crate::twis::sealed::State::new();
792 &STATE
793 }
794 }
795 impl crate::twis::Instance for peripherals::$type {
796 type Interrupt = crate::interrupt::typelevel::$irq;
797 }
798 };
799}
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs
index 4347ea558..48d57fea4 100644
--- a/embassy-nrf/src/uarte.rs
+++ b/embassy-nrf/src/uarte.rs
@@ -1,8 +1,6 @@
1#![macro_use] 1//! Universal Asynchronous Receiver Transmitter (UART) driver.
2
3//! Async UART
4//! 2//!
5//! Async UART is provided in two flavors - this one and also [crate::buffered_uarte::BufferedUarte]. 3//! The UART driver is provided in two flavors - this one and also [crate::buffered_uarte::BufferedUarte].
6//! The [Uarte] here is useful for those use-cases where reading the UARTE peripheral is 4//! The [Uarte] here is useful for those use-cases where reading the UARTE peripheral is
7//! exclusively awaited on. If the [Uarte] is required to be awaited on with some other future, 5//! exclusively awaited on. If the [Uarte] is required to be awaited on with some other future,
8//! for example when using `futures_util::future::select`, then you should consider 6//! for example when using `futures_util::future::select`, then you should consider
@@ -13,12 +11,15 @@
13//! memory may be used given that buffers are passed in directly to its read and write 11//! memory may be used given that buffers are passed in directly to its read and write
14//! methods. 12//! methods.
15 13
14#![macro_use]
15
16use core::future::poll_fn;
17use core::marker::PhantomData;
16use core::sync::atomic::{compiler_fence, Ordering}; 18use core::sync::atomic::{compiler_fence, Ordering};
17use core::task::Poll; 19use core::task::Poll;
18 20
19use embassy_hal_common::drop::OnDrop; 21use embassy_hal_common::drop::OnDrop;
20use embassy_hal_common::{into_ref, PeripheralRef}; 22use embassy_hal_common::{into_ref, PeripheralRef};
21use futures::future::poll_fn;
22use pac::uarte0::RegisterBlock; 23use pac::uarte0::RegisterBlock;
23// Re-export SVD variants to allow user to directly set values. 24// Re-export SVD variants to allow user to directly set values.
24pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; 25pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
@@ -26,16 +27,19 @@ pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Pari
26use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; 27use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
27use crate::gpio::sealed::Pin as _; 28use crate::gpio::sealed::Pin as _;
28use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; 29use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits};
29use crate::interrupt::{Interrupt, InterruptExt}; 30use crate::interrupt::typelevel::Interrupt;
30use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; 31use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
31use crate::timer::{Frequency, Instance as TimerInstance, Timer}; 32use crate::timer::{Frequency, Instance as TimerInstance, Timer};
32use crate::util::slice_in_ram_or; 33use crate::util::slice_in_ram_or;
33use crate::{pac, Peripheral}; 34use crate::{interrupt, pac, Peripheral};
34 35
36/// UARTE config.
35#[derive(Clone)] 37#[derive(Clone)]
36#[non_exhaustive] 38#[non_exhaustive]
37pub struct Config { 39pub struct Config {
40 /// Parity bit.
38 pub parity: Parity, 41 pub parity: Parity,
42 /// Baud rate.
39 pub baudrate: Baudrate, 43 pub baudrate: Baudrate,
40} 44}
41 45
@@ -48,32 +52,54 @@ impl Default for Config {
48 } 52 }
49} 53}
50 54
55/// UART error.
51#[derive(Debug, Clone, Copy, PartialEq, Eq)] 56#[derive(Debug, Clone, Copy, PartialEq, Eq)]
52#[cfg_attr(feature = "defmt", derive(defmt::Format))] 57#[cfg_attr(feature = "defmt", derive(defmt::Format))]
53#[non_exhaustive] 58#[non_exhaustive]
54pub enum Error { 59pub enum Error {
60 /// Buffer was too long.
55 BufferTooLong, 61 BufferTooLong,
56 BufferZeroLength, 62 /// The buffer is not in data RAM. It's most likely in flash, and nRF's DMA cannot access flash.
57 DMABufferNotInDataMemory, 63 BufferNotInRAM,
58 // TODO: add other error variants.
59} 64}
60 65
61/// Interface to the UARTE peripheral using EasyDMA to offload the transmission and reception workload. 66/// Interrupt handler.
62/// 67pub struct InterruptHandler<T: Instance> {
63/// For more details about EasyDMA, consult the module documentation. 68 _phantom: PhantomData<T>,
69}
70
71impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
72 unsafe fn on_interrupt() {
73 let r = T::regs();
74 let s = T::state();
75
76 if r.events_endrx.read().bits() != 0 {
77 s.endrx_waker.wake();
78 r.intenclr.write(|w| w.endrx().clear());
79 }
80 if r.events_endtx.read().bits() != 0 {
81 s.endtx_waker.wake();
82 r.intenclr.write(|w| w.endtx().clear());
83 }
84 }
85}
86
87/// UARTE driver.
64pub struct Uarte<'d, T: Instance> { 88pub struct Uarte<'d, T: Instance> {
65 tx: UarteTx<'d, T>, 89 tx: UarteTx<'d, T>,
66 rx: UarteRx<'d, T>, 90 rx: UarteRx<'d, T>,
67} 91}
68 92
69/// Transmitter interface to the UARTE peripheral obtained 93/// Transmitter part of the UARTE driver.
70/// via [Uarte]::split. 94///
95/// This can be obtained via [`Uarte::split`], or created directly.
71pub struct UarteTx<'d, T: Instance> { 96pub struct UarteTx<'d, T: Instance> {
72 _p: PeripheralRef<'d, T>, 97 _p: PeripheralRef<'d, T>,
73} 98}
74 99
75/// Receiver interface to the UARTE peripheral obtained 100/// Receiver part of the UARTE driver.
76/// via [Uarte]::split. 101///
102/// This can be obtained via [`Uarte::split`], or created directly.
77pub struct UarteRx<'d, T: Instance> { 103pub struct UarteRx<'d, T: Instance> {
78 _p: PeripheralRef<'d, T>, 104 _p: PeripheralRef<'d, T>,
79} 105}
@@ -82,19 +108,19 @@ impl<'d, T: Instance> Uarte<'d, T> {
82 /// Create a new UARTE without hardware flow control 108 /// Create a new UARTE without hardware flow control
83 pub fn new( 109 pub fn new(
84 uarte: impl Peripheral<P = T> + 'd, 110 uarte: impl Peripheral<P = T> + 'd,
85 irq: impl Peripheral<P = T::Interrupt> + 'd, 111 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
86 rxd: impl Peripheral<P = impl GpioPin> + 'd, 112 rxd: impl Peripheral<P = impl GpioPin> + 'd,
87 txd: impl Peripheral<P = impl GpioPin> + 'd, 113 txd: impl Peripheral<P = impl GpioPin> + 'd,
88 config: Config, 114 config: Config,
89 ) -> Self { 115 ) -> Self {
90 into_ref!(rxd, txd); 116 into_ref!(rxd, txd);
91 Self::new_inner(uarte, irq, rxd.map_into(), txd.map_into(), None, None, config) 117 Self::new_inner(uarte, rxd.map_into(), txd.map_into(), None, None, config)
92 } 118 }
93 119
94 /// Create a new UARTE with hardware flow control (RTS/CTS) 120 /// Create a new UARTE with hardware flow control (RTS/CTS)
95 pub fn new_with_rtscts( 121 pub fn new_with_rtscts(
96 uarte: impl Peripheral<P = T> + 'd, 122 uarte: impl Peripheral<P = T> + 'd,
97 irq: impl Peripheral<P = T::Interrupt> + 'd, 123 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
98 rxd: impl Peripheral<P = impl GpioPin> + 'd, 124 rxd: impl Peripheral<P = impl GpioPin> + 'd,
99 txd: impl Peripheral<P = impl GpioPin> + 'd, 125 txd: impl Peripheral<P = impl GpioPin> + 'd,
100 cts: impl Peripheral<P = impl GpioPin> + 'd, 126 cts: impl Peripheral<P = impl GpioPin> + 'd,
@@ -104,7 +130,6 @@ impl<'d, T: Instance> Uarte<'d, T> {
104 into_ref!(rxd, txd, cts, rts); 130 into_ref!(rxd, txd, cts, rts);
105 Self::new_inner( 131 Self::new_inner(
106 uarte, 132 uarte,
107 irq,
108 rxd.map_into(), 133 rxd.map_into(),
109 txd.map_into(), 134 txd.map_into(),
110 Some(cts.map_into()), 135 Some(cts.map_into()),
@@ -115,14 +140,13 @@ impl<'d, T: Instance> Uarte<'d, T> {
115 140
116 fn new_inner( 141 fn new_inner(
117 uarte: impl Peripheral<P = T> + 'd, 142 uarte: impl Peripheral<P = T> + 'd,
118 irq: impl Peripheral<P = T::Interrupt> + 'd,
119 rxd: PeripheralRef<'d, AnyPin>, 143 rxd: PeripheralRef<'d, AnyPin>,
120 txd: PeripheralRef<'d, AnyPin>, 144 txd: PeripheralRef<'d, AnyPin>,
121 cts: Option<PeripheralRef<'d, AnyPin>>, 145 cts: Option<PeripheralRef<'d, AnyPin>>,
122 rts: Option<PeripheralRef<'d, AnyPin>>, 146 rts: Option<PeripheralRef<'d, AnyPin>>,
123 config: Config, 147 config: Config,
124 ) -> Self { 148 ) -> Self {
125 into_ref!(uarte, irq); 149 into_ref!(uarte);
126 150
127 let r = T::regs(); 151 let r = T::regs();
128 152
@@ -144,9 +168,8 @@ impl<'d, T: Instance> Uarte<'d, T> {
144 } 168 }
145 r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) }); 169 r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) });
146 170
147 irq.set_handler(Self::on_interrupt); 171 T::Interrupt::unpend();
148 irq.unpend(); 172 unsafe { T::Interrupt::enable() };
149 irq.enable();
150 173
151 let hardware_flow_control = match (rts.is_some(), cts.is_some()) { 174 let hardware_flow_control = match (rts.is_some(), cts.is_some()) {
152 (false, false) => false, 175 (false, false) => false,
@@ -166,37 +189,37 @@ impl<'d, T: Instance> Uarte<'d, T> {
166 } 189 }
167 } 190 }
168 191
169 /// Split the Uarte into a transmitter and receiver, which is 192 /// Split the Uarte into the transmitter and receiver parts.
170 /// particuarly useful when having two tasks correlating to 193 ///
171 /// transmitting and receiving. 194 /// This is useful to concurrently transmit and receive from independent tasks.
172 pub fn split(self) -> (UarteTx<'d, T>, UarteRx<'d, T>) { 195 pub fn split(self) -> (UarteTx<'d, T>, UarteRx<'d, T>) {
173 (self.tx, self.rx) 196 (self.tx, self.rx)
174 } 197 }
175 198
199 /// Split the Uarte into the transmitter and receiver with idle support parts.
200 ///
201 /// This is useful to concurrently transmit and receive from independent tasks.
202 pub fn split_with_idle<U: TimerInstance>(
203 self,
204 timer: impl Peripheral<P = U> + 'd,
205 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd,
206 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd,
207 ) -> (UarteTx<'d, T>, UarteRxWithIdle<'d, T, U>) {
208 (self.tx, self.rx.with_idle(timer, ppi_ch1, ppi_ch2))
209 }
210
176 /// Return the endtx event for use with PPI 211 /// Return the endtx event for use with PPI
177 pub fn event_endtx(&self) -> Event { 212 pub fn event_endtx(&self) -> Event {
178 let r = T::regs(); 213 let r = T::regs();
179 Event::from_reg(&r.events_endtx) 214 Event::from_reg(&r.events_endtx)
180 } 215 }
181 216
182 fn on_interrupt(_: *mut ()) { 217 /// Read bytes until the buffer is filled.
183 let r = T::regs();
184 let s = T::state();
185
186 if r.events_endrx.read().bits() != 0 {
187 s.endrx_waker.wake();
188 r.intenclr.write(|w| w.endrx().clear());
189 }
190 if r.events_endtx.read().bits() != 0 {
191 s.endtx_waker.wake();
192 r.intenclr.write(|w| w.endtx().clear());
193 }
194 }
195
196 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 218 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
197 self.rx.read(buffer).await 219 self.rx.read(buffer).await
198 } 220 }
199 221
222 /// Write all bytes in the buffer.
200 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { 223 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
201 self.tx.write(buffer).await 224 self.tx.write(buffer).await
202 } 225 }
@@ -206,10 +229,12 @@ impl<'d, T: Instance> Uarte<'d, T> {
206 self.tx.write_from_ram(buffer).await 229 self.tx.write_from_ram(buffer).await
207 } 230 }
208 231
232 /// Read bytes until the buffer is filled.
209 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 233 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
210 self.rx.blocking_read(buffer) 234 self.rx.blocking_read(buffer)
211 } 235 }
212 236
237 /// Write all bytes in the buffer.
213 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { 238 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
214 self.tx.blocking_write(buffer) 239 self.tx.blocking_write(buffer)
215 } 240 }
@@ -245,34 +270,33 @@ impl<'d, T: Instance> UarteTx<'d, T> {
245 /// Create a new tx-only UARTE without hardware flow control 270 /// Create a new tx-only UARTE without hardware flow control
246 pub fn new( 271 pub fn new(
247 uarte: impl Peripheral<P = T> + 'd, 272 uarte: impl Peripheral<P = T> + 'd,
248 irq: impl Peripheral<P = T::Interrupt> + 'd, 273 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
249 txd: impl Peripheral<P = impl GpioPin> + 'd, 274 txd: impl Peripheral<P = impl GpioPin> + 'd,
250 config: Config, 275 config: Config,
251 ) -> Self { 276 ) -> Self {
252 into_ref!(txd); 277 into_ref!(txd);
253 Self::new_inner(uarte, irq, txd.map_into(), None, config) 278 Self::new_inner(uarte, txd.map_into(), None, config)
254 } 279 }
255 280
256 /// Create a new tx-only UARTE with hardware flow control (RTS/CTS) 281 /// Create a new tx-only UARTE with hardware flow control (RTS/CTS)
257 pub fn new_with_rtscts( 282 pub fn new_with_rtscts(
258 uarte: impl Peripheral<P = T> + 'd, 283 uarte: impl Peripheral<P = T> + 'd,
259 irq: impl Peripheral<P = T::Interrupt> + 'd, 284 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
260 txd: impl Peripheral<P = impl GpioPin> + 'd, 285 txd: impl Peripheral<P = impl GpioPin> + 'd,
261 cts: impl Peripheral<P = impl GpioPin> + 'd, 286 cts: impl Peripheral<P = impl GpioPin> + 'd,
262 config: Config, 287 config: Config,
263 ) -> Self { 288 ) -> Self {
264 into_ref!(txd, cts); 289 into_ref!(txd, cts);
265 Self::new_inner(uarte, irq, txd.map_into(), Some(cts.map_into()), config) 290 Self::new_inner(uarte, txd.map_into(), Some(cts.map_into()), config)
266 } 291 }
267 292
268 fn new_inner( 293 fn new_inner(
269 uarte: impl Peripheral<P = T> + 'd, 294 uarte: impl Peripheral<P = T> + 'd,
270 irq: impl Peripheral<P = T::Interrupt> + 'd,
271 txd: PeripheralRef<'d, AnyPin>, 295 txd: PeripheralRef<'d, AnyPin>,
272 cts: Option<PeripheralRef<'d, AnyPin>>, 296 cts: Option<PeripheralRef<'d, AnyPin>>,
273 config: Config, 297 config: Config,
274 ) -> Self { 298 ) -> Self {
275 into_ref!(uarte, irq); 299 into_ref!(uarte);
276 300
277 let r = T::regs(); 301 let r = T::regs();
278 302
@@ -291,9 +315,8 @@ impl<'d, T: Instance> UarteTx<'d, T> {
291 let hardware_flow_control = cts.is_some(); 315 let hardware_flow_control = cts.is_some();
292 configure(r, config, hardware_flow_control); 316 configure(r, config, hardware_flow_control);
293 317
294 irq.set_handler(Uarte::<T>::on_interrupt); 318 T::Interrupt::unpend();
295 irq.unpend(); 319 unsafe { T::Interrupt::enable() };
296 irq.enable();
297 320
298 let s = T::state(); 321 let s = T::state();
299 s.tx_rx_refcount.store(1, Ordering::Relaxed); 322 s.tx_rx_refcount.store(1, Ordering::Relaxed);
@@ -301,10 +324,11 @@ impl<'d, T: Instance> UarteTx<'d, T> {
301 Self { _p: uarte } 324 Self { _p: uarte }
302 } 325 }
303 326
327 /// Write all bytes in the buffer.
304 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { 328 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
305 match self.write_from_ram(buffer).await { 329 match self.write_from_ram(buffer).await {
306 Ok(_) => Ok(()), 330 Ok(_) => Ok(()),
307 Err(Error::DMABufferNotInDataMemory) => { 331 Err(Error::BufferNotInRAM) => {
308 trace!("Copying UARTE tx buffer into RAM for DMA"); 332 trace!("Copying UARTE tx buffer into RAM for DMA");
309 let ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..buffer.len()]; 333 let ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..buffer.len()];
310 ram_buf.copy_from_slice(buffer); 334 ram_buf.copy_from_slice(buffer);
@@ -314,11 +338,13 @@ impl<'d, T: Instance> UarteTx<'d, T> {
314 } 338 }
315 } 339 }
316 340
341 /// Same as [`write`](Self::write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
317 pub async fn write_from_ram(&mut self, buffer: &[u8]) -> Result<(), Error> { 342 pub async fn write_from_ram(&mut self, buffer: &[u8]) -> Result<(), Error> {
318 slice_in_ram_or(buffer, Error::DMABufferNotInDataMemory)?;
319 if buffer.len() == 0 { 343 if buffer.len() == 0 {
320 return Err(Error::BufferZeroLength); 344 return Ok(());
321 } 345 }
346
347 slice_in_ram_or(buffer, Error::BufferNotInRAM)?;
322 if buffer.len() > EASY_DMA_SIZE { 348 if buffer.len() > EASY_DMA_SIZE {
323 return Err(Error::BufferTooLong); 349 return Err(Error::BufferTooLong);
324 } 350 }
@@ -368,10 +394,11 @@ impl<'d, T: Instance> UarteTx<'d, T> {
368 Ok(()) 394 Ok(())
369 } 395 }
370 396
397 /// Write all bytes in the buffer.
371 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { 398 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
372 match self.blocking_write_from_ram(buffer) { 399 match self.blocking_write_from_ram(buffer) {
373 Ok(_) => Ok(()), 400 Ok(_) => Ok(()),
374 Err(Error::DMABufferNotInDataMemory) => { 401 Err(Error::BufferNotInRAM) => {
375 trace!("Copying UARTE tx buffer into RAM for DMA"); 402 trace!("Copying UARTE tx buffer into RAM for DMA");
376 let ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..buffer.len()]; 403 let ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..buffer.len()];
377 ram_buf.copy_from_slice(buffer); 404 ram_buf.copy_from_slice(buffer);
@@ -381,11 +408,13 @@ impl<'d, T: Instance> UarteTx<'d, T> {
381 } 408 }
382 } 409 }
383 410
411 /// Same as [`write_from_ram`](Self::write_from_ram) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
384 pub fn blocking_write_from_ram(&mut self, buffer: &[u8]) -> Result<(), Error> { 412 pub fn blocking_write_from_ram(&mut self, buffer: &[u8]) -> Result<(), Error> {
385 slice_in_ram_or(buffer, Error::DMABufferNotInDataMemory)?;
386 if buffer.len() == 0 { 413 if buffer.len() == 0 {
387 return Err(Error::BufferZeroLength); 414 return Ok(());
388 } 415 }
416
417 slice_in_ram_or(buffer, Error::BufferNotInRAM)?;
389 if buffer.len() > EASY_DMA_SIZE { 418 if buffer.len() > EASY_DMA_SIZE {
390 return Err(Error::BufferTooLong); 419 return Err(Error::BufferTooLong);
391 } 420 }
@@ -437,34 +466,33 @@ impl<'d, T: Instance> UarteRx<'d, T> {
437 /// Create a new rx-only UARTE without hardware flow control 466 /// Create a new rx-only UARTE without hardware flow control
438 pub fn new( 467 pub fn new(
439 uarte: impl Peripheral<P = T> + 'd, 468 uarte: impl Peripheral<P = T> + 'd,
440 irq: impl Peripheral<P = T::Interrupt> + 'd, 469 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
441 rxd: impl Peripheral<P = impl GpioPin> + 'd, 470 rxd: impl Peripheral<P = impl GpioPin> + 'd,
442 config: Config, 471 config: Config,
443 ) -> Self { 472 ) -> Self {
444 into_ref!(rxd); 473 into_ref!(rxd);
445 Self::new_inner(uarte, irq, rxd.map_into(), None, config) 474 Self::new_inner(uarte, rxd.map_into(), None, config)
446 } 475 }
447 476
448 /// Create a new rx-only UARTE with hardware flow control (RTS/CTS) 477 /// Create a new rx-only UARTE with hardware flow control (RTS/CTS)
449 pub fn new_with_rtscts( 478 pub fn new_with_rtscts(
450 uarte: impl Peripheral<P = T> + 'd, 479 uarte: impl Peripheral<P = T> + 'd,
451 irq: impl Peripheral<P = T::Interrupt> + 'd, 480 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
452 rxd: impl Peripheral<P = impl GpioPin> + 'd, 481 rxd: impl Peripheral<P = impl GpioPin> + 'd,
453 rts: impl Peripheral<P = impl GpioPin> + 'd, 482 rts: impl Peripheral<P = impl GpioPin> + 'd,
454 config: Config, 483 config: Config,
455 ) -> Self { 484 ) -> Self {
456 into_ref!(rxd, rts); 485 into_ref!(rxd, rts);
457 Self::new_inner(uarte, irq, rxd.map_into(), Some(rts.map_into()), config) 486 Self::new_inner(uarte, rxd.map_into(), Some(rts.map_into()), config)
458 } 487 }
459 488
460 fn new_inner( 489 fn new_inner(
461 uarte: impl Peripheral<P = T> + 'd, 490 uarte: impl Peripheral<P = T> + 'd,
462 irq: impl Peripheral<P = T::Interrupt> + 'd,
463 rxd: PeripheralRef<'d, AnyPin>, 491 rxd: PeripheralRef<'d, AnyPin>,
464 rts: Option<PeripheralRef<'d, AnyPin>>, 492 rts: Option<PeripheralRef<'d, AnyPin>>,
465 config: Config, 493 config: Config,
466 ) -> Self { 494 ) -> Self {
467 into_ref!(uarte, irq); 495 into_ref!(uarte);
468 496
469 let r = T::regs(); 497 let r = T::regs();
470 498
@@ -480,9 +508,8 @@ impl<'d, T: Instance> UarteRx<'d, T> {
480 r.psel.txd.write(|w| w.connect().disconnected()); 508 r.psel.txd.write(|w| w.connect().disconnected());
481 r.psel.cts.write(|w| w.connect().disconnected()); 509 r.psel.cts.write(|w| w.connect().disconnected());
482 510
483 irq.set_handler(Uarte::<T>::on_interrupt); 511 T::Interrupt::unpend();
484 irq.unpend(); 512 unsafe { T::Interrupt::enable() };
485 irq.enable();
486 513
487 let hardware_flow_control = rts.is_some(); 514 let hardware_flow_control = rts.is_some();
488 configure(r, config, hardware_flow_control); 515 configure(r, config, hardware_flow_control);
@@ -493,9 +520,60 @@ impl<'d, T: Instance> UarteRx<'d, T> {
493 Self { _p: uarte } 520 Self { _p: uarte }
494 } 521 }
495 522
523 /// Upgrade to an instance that supports idle line detection.
524 pub fn with_idle<U: TimerInstance>(
525 self,
526 timer: impl Peripheral<P = U> + 'd,
527 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd,
528 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd,
529 ) -> UarteRxWithIdle<'d, T, U> {
530 let timer = Timer::new(timer);
531
532 into_ref!(ppi_ch1, ppi_ch2);
533
534 let r = T::regs();
535
536 // BAUDRATE register values are `baudrate * 2^32 / 16000000`
537 // source: https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values
538 //
539 // We want to stop RX if line is idle for 2 bytes worth of time
540 // That is 20 bits (each byte is 1 start bit + 8 data bits + 1 stop bit)
541 // This gives us the amount of 16M ticks for 20 bits.
542 let baudrate = r.baudrate.read().baudrate().variant().unwrap();
543 let timeout = 0x8000_0000 / (baudrate as u32 / 40);
544
545 timer.set_frequency(Frequency::F16MHz);
546 timer.cc(0).write(timeout);
547 timer.cc(0).short_compare_clear();
548 timer.cc(0).short_compare_stop();
549
550 let mut ppi_ch1 = Ppi::new_one_to_two(
551 ppi_ch1.map_into(),
552 Event::from_reg(&r.events_rxdrdy),
553 timer.task_clear(),
554 timer.task_start(),
555 );
556 ppi_ch1.enable();
557
558 let mut ppi_ch2 = Ppi::new_one_to_one(
559 ppi_ch2.map_into(),
560 timer.cc(0).event_compare(),
561 Task::from_reg(&r.tasks_stoprx),
562 );
563 ppi_ch2.enable();
564
565 UarteRxWithIdle {
566 rx: self,
567 timer,
568 ppi_ch1: ppi_ch1,
569 _ppi_ch2: ppi_ch2,
570 }
571 }
572
573 /// Read bytes until the buffer is filled.
496 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 574 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
497 if buffer.len() == 0 { 575 if buffer.len() == 0 {
498 return Err(Error::BufferZeroLength); 576 return Ok(());
499 } 577 }
500 if buffer.len() > EASY_DMA_SIZE { 578 if buffer.len() > EASY_DMA_SIZE {
501 return Err(Error::BufferTooLong); 579 return Err(Error::BufferTooLong);
@@ -546,9 +624,10 @@ impl<'d, T: Instance> UarteRx<'d, T> {
546 Ok(()) 624 Ok(())
547 } 625 }
548 626
627 /// Read bytes until the buffer is filled.
549 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 628 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
550 if buffer.len() == 0 { 629 if buffer.len() == 0 {
551 return Err(Error::BufferZeroLength); 630 return Ok(());
552 } 631 }
553 if buffer.len() > EASY_DMA_SIZE { 632 if buffer.len() > EASY_DMA_SIZE {
554 return Err(Error::BufferTooLong); 633 return Err(Error::BufferTooLong);
@@ -597,249 +676,35 @@ impl<'a, T: Instance> Drop for UarteRx<'a, T> {
597 } 676 }
598} 677}
599 678
600#[cfg(not(any(feature = "_nrf9160", feature = "nrf5340")))] 679/// Receiver part of the UARTE driver, with `read_until_idle` support.
601pub(crate) fn apply_workaround_for_enable_anomaly(_r: &crate::pac::uarte0::RegisterBlock) { 680///
602 // Do nothing 681/// This can be obtained via [`Uarte::split_with_idle`].
603} 682pub struct UarteRxWithIdle<'d, T: Instance, U: TimerInstance> {
604 683 rx: UarteRx<'d, T>,
605#[cfg(any(feature = "_nrf9160", feature = "nrf5340"))] 684 timer: Timer<'d, U>,
606pub(crate) fn apply_workaround_for_enable_anomaly(r: &crate::pac::uarte0::RegisterBlock) {
607 use core::ops::Deref;
608
609 // Apply workaround for anomalies:
610 // - nRF9160 - anomaly 23
611 // - nRF5340 - anomaly 44
612 let rxenable_reg: *const u32 = ((r.deref() as *const _ as usize) + 0x564) as *const u32;
613 let txenable_reg: *const u32 = ((r.deref() as *const _ as usize) + 0x568) as *const u32;
614
615 // NB Safety: This is taken from Nordic's driver -
616 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
617 if unsafe { core::ptr::read_volatile(txenable_reg) } == 1 {
618 r.tasks_stoptx.write(|w| unsafe { w.bits(1) });
619 }
620
621 // NB Safety: This is taken from Nordic's driver -
622 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
623 if unsafe { core::ptr::read_volatile(rxenable_reg) } == 1 {
624 r.enable.write(|w| w.enable().enabled());
625 r.tasks_stoprx.write(|w| unsafe { w.bits(1) });
626
627 let mut workaround_succeded = false;
628 // The UARTE is able to receive up to four bytes after the STOPRX task has been triggered.
629 // On lowest supported baud rate (1200 baud), with parity bit and two stop bits configured
630 // (resulting in 12 bits per data byte sent), this may take up to 40 ms.
631 for _ in 0..40000 {
632 // NB Safety: This is taken from Nordic's driver -
633 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
634 if unsafe { core::ptr::read_volatile(rxenable_reg) } == 0 {
635 workaround_succeded = true;
636 break;
637 } else {
638 // Need to sleep for 1us here
639 }
640 }
641
642 if !workaround_succeded {
643 panic!("Failed to apply workaround for UART");
644 }
645
646 let errors = r.errorsrc.read().bits();
647 // NB Safety: safe to write back the bits we just read to clear them
648 r.errorsrc.write(|w| unsafe { w.bits(errors) });
649 r.enable.write(|w| w.enable().disabled());
650 }
651}
652
653pub(crate) fn drop_tx_rx(r: &pac::uarte0::RegisterBlock, s: &sealed::State) {
654 if s.tx_rx_refcount.fetch_sub(1, Ordering::Relaxed) == 1 {
655 // Finally we can disable, and we do so for the peripheral
656 // i.e. not just rx concerns.
657 r.enable.write(|w| w.enable().disabled());
658
659 gpio::deconfigure_pin(r.psel.rxd.read().bits());
660 gpio::deconfigure_pin(r.psel.txd.read().bits());
661 gpio::deconfigure_pin(r.psel.rts.read().bits());
662 gpio::deconfigure_pin(r.psel.cts.read().bits());
663
664 trace!("uarte tx and rx drop: done");
665 }
666}
667
668/// Interface to an UARTE peripheral that uses an additional timer and two PPI channels,
669/// allowing it to implement the ReadUntilIdle trait.
670pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> {
671 tx: UarteTx<'d, U>,
672 rx: UarteRxWithIdle<'d, U, T>,
673}
674
675impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> {
676 /// Create a new UARTE without hardware flow control
677 pub fn new(
678 uarte: impl Peripheral<P = U> + 'd,
679 timer: impl Peripheral<P = T> + 'd,
680 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd,
681 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd,
682 irq: impl Peripheral<P = U::Interrupt> + 'd,
683 rxd: impl Peripheral<P = impl GpioPin> + 'd,
684 txd: impl Peripheral<P = impl GpioPin> + 'd,
685 config: Config,
686 ) -> Self {
687 into_ref!(rxd, txd);
688 Self::new_inner(
689 uarte,
690 timer,
691 ppi_ch1,
692 ppi_ch2,
693 irq,
694 rxd.map_into(),
695 txd.map_into(),
696 None,
697 None,
698 config,
699 )
700 }
701
702 /// Create a new UARTE with hardware flow control (RTS/CTS)
703 pub fn new_with_rtscts(
704 uarte: impl Peripheral<P = U> + 'd,
705 timer: impl Peripheral<P = T> + 'd,
706 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd,
707 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd,
708 irq: impl Peripheral<P = U::Interrupt> + 'd,
709 rxd: impl Peripheral<P = impl GpioPin> + 'd,
710 txd: impl Peripheral<P = impl GpioPin> + 'd,
711 cts: impl Peripheral<P = impl GpioPin> + 'd,
712 rts: impl Peripheral<P = impl GpioPin> + 'd,
713 config: Config,
714 ) -> Self {
715 into_ref!(rxd, txd, cts, rts);
716 Self::new_inner(
717 uarte,
718 timer,
719 ppi_ch1,
720 ppi_ch2,
721 irq,
722 rxd.map_into(),
723 txd.map_into(),
724 Some(cts.map_into()),
725 Some(rts.map_into()),
726 config,
727 )
728 }
729
730 fn new_inner(
731 uarte: impl Peripheral<P = U> + 'd,
732 timer: impl Peripheral<P = T> + 'd,
733 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd,
734 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd,
735 irq: impl Peripheral<P = U::Interrupt> + 'd,
736 rxd: PeripheralRef<'d, AnyPin>,
737 txd: PeripheralRef<'d, AnyPin>,
738 cts: Option<PeripheralRef<'d, AnyPin>>,
739 rts: Option<PeripheralRef<'d, AnyPin>>,
740 config: Config,
741 ) -> Self {
742 let baudrate = config.baudrate;
743 let (tx, rx) = Uarte::new_inner(uarte, irq, rxd, txd, cts, rts, config).split();
744
745 let mut timer = Timer::new(timer);
746
747 into_ref!(ppi_ch1, ppi_ch2);
748
749 let r = U::regs();
750
751 // BAUDRATE register values are `baudrate * 2^32 / 16000000`
752 // source: https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values
753 //
754 // We want to stop RX if line is idle for 2 bytes worth of time
755 // That is 20 bits (each byte is 1 start bit + 8 data bits + 1 stop bit)
756 // This gives us the amount of 16M ticks for 20 bits.
757 let timeout = 0x8000_0000 / (baudrate as u32 / 40);
758
759 timer.set_frequency(Frequency::F16MHz);
760 timer.cc(0).write(timeout);
761 timer.cc(0).short_compare_clear();
762 timer.cc(0).short_compare_stop();
763
764 let mut ppi_ch1 = Ppi::new_one_to_two(
765 ppi_ch1.map_into(),
766 Event::from_reg(&r.events_rxdrdy),
767 timer.task_clear(),
768 timer.task_start(),
769 );
770 ppi_ch1.enable();
771
772 let mut ppi_ch2 = Ppi::new_one_to_one(
773 ppi_ch2.map_into(),
774 timer.cc(0).event_compare(),
775 Task::from_reg(&r.tasks_stoprx),
776 );
777 ppi_ch2.enable();
778
779 Self {
780 tx,
781 rx: UarteRxWithIdle {
782 rx,
783 timer,
784 ppi_ch1: ppi_ch1,
785 _ppi_ch2: ppi_ch2,
786 },
787 }
788 }
789
790 /// Split the Uarte into a transmitter and receiver, which is
791 /// particuarly useful when having two tasks correlating to
792 /// transmitting and receiving.
793 pub fn split(self) -> (UarteTx<'d, U>, UarteRxWithIdle<'d, U, T>) {
794 (self.tx, self.rx)
795 }
796
797 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
798 self.rx.read(buffer).await
799 }
800
801 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
802 self.tx.write(buffer).await
803 }
804
805 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
806 self.rx.blocking_read(buffer)
807 }
808
809 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
810 self.tx.blocking_write(buffer)
811 }
812
813 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
814 self.rx.read_until_idle(buffer).await
815 }
816
817 pub fn blocking_read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
818 self.rx.blocking_read_until_idle(buffer)
819 }
820}
821
822pub struct UarteRxWithIdle<'d, U: Instance, T: TimerInstance> {
823 rx: UarteRx<'d, U>,
824 timer: Timer<'d, T>,
825 ppi_ch1: Ppi<'d, AnyConfigurableChannel, 1, 2>, 685 ppi_ch1: Ppi<'d, AnyConfigurableChannel, 1, 2>,
826 _ppi_ch2: Ppi<'d, AnyConfigurableChannel, 1, 1>, 686 _ppi_ch2: Ppi<'d, AnyConfigurableChannel, 1, 1>,
827} 687}
828 688
829impl<'d, U: Instance, T: TimerInstance> UarteRxWithIdle<'d, U, T> { 689impl<'d, T: Instance, U: TimerInstance> UarteRxWithIdle<'d, T, U> {
690 /// Read bytes until the buffer is filled.
830 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 691 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
831 self.ppi_ch1.disable(); 692 self.ppi_ch1.disable();
832 self.rx.read(buffer).await 693 self.rx.read(buffer).await
833 } 694 }
834 695
696 /// Read bytes until the buffer is filled.
835 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 697 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
836 self.ppi_ch1.disable(); 698 self.ppi_ch1.disable();
837 self.rx.blocking_read(buffer) 699 self.rx.blocking_read(buffer)
838 } 700 }
839 701
702 /// Read bytes until the buffer is filled, or the line becomes idle.
703 ///
704 /// Returns the amount of bytes read.
840 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { 705 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
841 if buffer.len() == 0 { 706 if buffer.len() == 0 {
842 return Err(Error::BufferZeroLength); 707 return Ok(0);
843 } 708 }
844 if buffer.len() > EASY_DMA_SIZE { 709 if buffer.len() > EASY_DMA_SIZE {
845 return Err(Error::BufferTooLong); 710 return Err(Error::BufferTooLong);
@@ -848,8 +713,8 @@ impl<'d, U: Instance, T: TimerInstance> UarteRxWithIdle<'d, U, T> {
848 let ptr = buffer.as_ptr(); 713 let ptr = buffer.as_ptr();
849 let len = buffer.len(); 714 let len = buffer.len();
850 715
851 let r = U::regs(); 716 let r = T::regs();
852 let s = U::state(); 717 let s = T::state();
853 718
854 self.ppi_ch1.enable(); 719 self.ppi_ch1.enable();
855 720
@@ -893,9 +758,12 @@ impl<'d, U: Instance, T: TimerInstance> UarteRxWithIdle<'d, U, T> {
893 Ok(n) 758 Ok(n)
894 } 759 }
895 760
761 /// Read bytes until the buffer is filled, or the line becomes idle.
762 ///
763 /// Returns the amount of bytes read.
896 pub fn blocking_read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { 764 pub fn blocking_read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
897 if buffer.len() == 0 { 765 if buffer.len() == 0 {
898 return Err(Error::BufferZeroLength); 766 return Ok(0);
899 } 767 }
900 if buffer.len() > EASY_DMA_SIZE { 768 if buffer.len() > EASY_DMA_SIZE {
901 return Err(Error::BufferTooLong); 769 return Err(Error::BufferTooLong);
@@ -904,7 +772,7 @@ impl<'d, U: Instance, T: TimerInstance> UarteRxWithIdle<'d, U, T> {
904 let ptr = buffer.as_ptr(); 772 let ptr = buffer.as_ptr();
905 let len = buffer.len(); 773 let len = buffer.len();
906 774
907 let r = U::regs(); 775 let r = T::regs();
908 776
909 self.ppi_ch1.enable(); 777 self.ppi_ch1.enable();
910 778
@@ -929,6 +797,73 @@ impl<'d, U: Instance, T: TimerInstance> UarteRxWithIdle<'d, U, T> {
929 Ok(n) 797 Ok(n)
930 } 798 }
931} 799}
800
801#[cfg(not(any(feature = "_nrf9160", feature = "_nrf5340")))]
802pub(crate) fn apply_workaround_for_enable_anomaly(_r: &crate::pac::uarte0::RegisterBlock) {
803 // Do nothing
804}
805
806#[cfg(any(feature = "_nrf9160", feature = "_nrf5340"))]
807pub(crate) fn apply_workaround_for_enable_anomaly(r: &crate::pac::uarte0::RegisterBlock) {
808 // Apply workaround for anomalies:
809 // - nRF9160 - anomaly 23
810 // - nRF5340 - anomaly 44
811 let rxenable_reg: *const u32 = ((r as *const _ as usize) + 0x564) as *const u32;
812 let txenable_reg: *const u32 = ((r as *const _ as usize) + 0x568) as *const u32;
813
814 // NB Safety: This is taken from Nordic's driver -
815 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
816 if unsafe { core::ptr::read_volatile(txenable_reg) } == 1 {
817 r.tasks_stoptx.write(|w| unsafe { w.bits(1) });
818 }
819
820 // NB Safety: This is taken from Nordic's driver -
821 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
822 if unsafe { core::ptr::read_volatile(rxenable_reg) } == 1 {
823 r.enable.write(|w| w.enable().enabled());
824 r.tasks_stoprx.write(|w| unsafe { w.bits(1) });
825
826 let mut workaround_succeded = false;
827 // The UARTE is able to receive up to four bytes after the STOPRX task has been triggered.
828 // On lowest supported baud rate (1200 baud), with parity bit and two stop bits configured
829 // (resulting in 12 bits per data byte sent), this may take up to 40 ms.
830 for _ in 0..40000 {
831 // NB Safety: This is taken from Nordic's driver -
832 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
833 if unsafe { core::ptr::read_volatile(rxenable_reg) } == 0 {
834 workaround_succeded = true;
835 break;
836 } else {
837 // Need to sleep for 1us here
838 }
839 }
840
841 if !workaround_succeded {
842 panic!("Failed to apply workaround for UART");
843 }
844
845 let errors = r.errorsrc.read().bits();
846 // NB Safety: safe to write back the bits we just read to clear them
847 r.errorsrc.write(|w| unsafe { w.bits(errors) });
848 r.enable.write(|w| w.enable().disabled());
849 }
850}
851
852pub(crate) fn drop_tx_rx(r: &pac::uarte0::RegisterBlock, s: &sealed::State) {
853 if s.tx_rx_refcount.fetch_sub(1, Ordering::Relaxed) == 1 {
854 // Finally we can disable, and we do so for the peripheral
855 // i.e. not just rx concerns.
856 r.enable.write(|w| w.enable().disabled());
857
858 gpio::deconfigure_pin(r.psel.rxd.read().bits());
859 gpio::deconfigure_pin(r.psel.txd.read().bits());
860 gpio::deconfigure_pin(r.psel.rts.read().bits());
861 gpio::deconfigure_pin(r.psel.cts.read().bits());
862
863 trace!("uarte tx and rx drop: done");
864 }
865}
866
932pub(crate) mod sealed { 867pub(crate) mod sealed {
933 use core::sync::atomic::AtomicU8; 868 use core::sync::atomic::AtomicU8;
934 869
@@ -954,11 +889,14 @@ pub(crate) mod sealed {
954 pub trait Instance { 889 pub trait Instance {
955 fn regs() -> &'static pac::uarte0::RegisterBlock; 890 fn regs() -> &'static pac::uarte0::RegisterBlock;
956 fn state() -> &'static State; 891 fn state() -> &'static State;
892 fn buffered_state() -> &'static crate::buffered_uarte::State;
957 } 893 }
958} 894}
959 895
896/// UARTE peripheral instance.
960pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send { 897pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
961 type Interrupt: Interrupt; 898 /// Interrupt for this peripheral.
899 type Interrupt: interrupt::typelevel::Interrupt;
962} 900}
963 901
964macro_rules! impl_uarte { 902macro_rules! impl_uarte {
@@ -971,9 +909,13 @@ macro_rules! impl_uarte {
971 static STATE: crate::uarte::sealed::State = crate::uarte::sealed::State::new(); 909 static STATE: crate::uarte::sealed::State = crate::uarte::sealed::State::new();
972 &STATE 910 &STATE
973 } 911 }
912 fn buffered_state() -> &'static crate::buffered_uarte::State {
913 static STATE: crate::buffered_uarte::State = crate::buffered_uarte::State::new();
914 &STATE
915 }
974 } 916 }
975 impl crate::uarte::Instance for peripherals::$type { 917 impl crate::uarte::Instance for peripherals::$type {
976 type Interrupt = crate::interrupt::$irq; 918 type Interrupt = crate::interrupt::typelevel::$irq;
977 } 919 }
978 }; 920 };
979} 921}
@@ -1006,18 +948,6 @@ mod eh02 {
1006 Ok(()) 948 Ok(())
1007 } 949 }
1008 } 950 }
1009
1010 impl<'d, U: Instance, T: TimerInstance> embedded_hal_02::blocking::serial::Write<u8> for UarteWithIdle<'d, U, T> {
1011 type Error = Error;
1012
1013 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
1014 self.blocking_write(buffer)
1015 }
1016
1017 fn bflush(&mut self) -> Result<(), Self::Error> {
1018 Ok(())
1019 }
1020 }
1021} 951}
1022 952
1023#[cfg(feature = "unstable-traits")] 953#[cfg(feature = "unstable-traits")]
@@ -1028,8 +958,7 @@ mod eh1 {
1028 fn kind(&self) -> embedded_hal_1::serial::ErrorKind { 958 fn kind(&self) -> embedded_hal_1::serial::ErrorKind {
1029 match *self { 959 match *self {
1030 Self::BufferTooLong => embedded_hal_1::serial::ErrorKind::Other, 960 Self::BufferTooLong => embedded_hal_1::serial::ErrorKind::Other,
1031 Self::BufferZeroLength => embedded_hal_1::serial::ErrorKind::Other, 961 Self::BufferNotInRAM => embedded_hal_1::serial::ErrorKind::Other,
1032 Self::DMABufferNotInDataMemory => embedded_hal_1::serial::ErrorKind::Other,
1033 } 962 }
1034 } 963 }
1035 } 964 }
@@ -1040,7 +969,7 @@ mod eh1 {
1040 type Error = Error; 969 type Error = Error;
1041 } 970 }
1042 971
1043 impl<'d, T: Instance> embedded_hal_1::serial::blocking::Write for Uarte<'d, T> { 972 impl<'d, T: Instance> embedded_hal_1::serial::Write for Uarte<'d, T> {
1044 fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { 973 fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
1045 self.blocking_write(buffer) 974 self.blocking_write(buffer)
1046 } 975 }
@@ -1054,7 +983,7 @@ mod eh1 {
1054 type Error = Error; 983 type Error = Error;
1055 } 984 }
1056 985
1057 impl<'d, T: Instance> embedded_hal_1::serial::blocking::Write for UarteTx<'d, T> { 986 impl<'d, T: Instance> embedded_hal_1::serial::Write for UarteTx<'d, T> {
1058 fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { 987 fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
1059 self.blocking_write(buffer) 988 self.blocking_write(buffer)
1060 } 989 }
@@ -1067,84 +996,4 @@ mod eh1 {
1067 impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for UarteRx<'d, T> { 996 impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for UarteRx<'d, T> {
1068 type Error = Error; 997 type Error = Error;
1069 } 998 }
1070
1071 impl<'d, U: Instance, T: TimerInstance> embedded_hal_1::serial::ErrorType for UarteWithIdle<'d, U, T> {
1072 type Error = Error;
1073 }
1074}
1075
1076cfg_if::cfg_if! {
1077 if #[cfg(all(feature = "unstable-traits", feature = "nightly", feature = "_todo_embedded_hal_serial"))] {
1078 use core::future::Future;
1079
1080 impl<'d, T: Instance> embedded_hal_async::serial::Read for Uarte<'d, T> {
1081 type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
1082
1083 fn read<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
1084 self.read(buffer)
1085 }
1086 }
1087
1088 impl<'d, T: Instance> embedded_hal_async::serial::Write for Uarte<'d, T> {
1089 type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
1090
1091 fn write<'a>(&'a mut self, buffer: &'a [u8]) -> Self::WriteFuture<'a> {
1092 self.write(buffer)
1093 }
1094
1095 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
1096
1097 fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
1098 async move { Ok(()) }
1099 }
1100 }
1101
1102 impl<'d, T: Instance> embedded_hal_async::serial::Write for UarteTx<'d, T> {
1103 type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
1104
1105 fn write<'a>(&'a mut self, buffer: &'a [u8]) -> Self::WriteFuture<'a> {
1106 self.write(buffer)
1107 }
1108
1109 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
1110
1111 fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
1112 async move { Ok(()) }
1113 }
1114 }
1115
1116 impl<'d, T: Instance> embedded_hal_async::serial::Read for UarteRx<'d, T> {
1117 type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
1118
1119 fn read<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
1120 self.read(buffer)
1121 }
1122 }
1123
1124 impl<'d, U: Instance, T: TimerInstance> embedded_hal_async::serial::Read
1125 for UarteWithIdle<'d, U, T>
1126 {
1127 type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
1128
1129 fn read<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
1130 self.read(buffer)
1131 }
1132 }
1133
1134 impl<'d, U: Instance, T: TimerInstance> embedded_hal_async::serial::Write
1135 for UarteWithIdle<'d, U, T>
1136 {
1137 type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
1138
1139 fn write<'a>(&'a mut self, buffer: &'a [u8]) -> Self::WriteFuture<'a> {
1140 self.write(buffer)
1141 }
1142
1143 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
1144
1145 fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
1146 async move { Ok(()) }
1147 }
1148 }
1149 }
1150} 999}
diff --git a/embassy-nrf/src/usb.rs b/embassy-nrf/src/usb/mod.rs
index 688326e9c..76cf40ac7 100644
--- a/embassy-nrf/src/usb.rs
+++ b/embassy-nrf/src/usb/mod.rs
@@ -1,23 +1,26 @@
1//! Universal Serial Bus (USB) driver.
2
1#![macro_use] 3#![macro_use]
2 4
5pub mod vbus_detect;
6
7use core::future::poll_fn;
3use core::marker::PhantomData; 8use core::marker::PhantomData;
4use core::mem::MaybeUninit; 9use core::mem::MaybeUninit;
5use core::sync::atomic::{compiler_fence, AtomicBool, AtomicU32, Ordering}; 10use core::sync::atomic::{compiler_fence, AtomicU32, Ordering};
6use core::task::Poll; 11use core::task::Poll;
7 12
8use cortex_m::peripheral::NVIC; 13use cortex_m::peripheral::NVIC;
9use embassy_hal_common::{into_ref, PeripheralRef}; 14use embassy_hal_common::{into_ref, PeripheralRef};
10use embassy_sync::waitqueue::AtomicWaker; 15use embassy_sync::waitqueue::AtomicWaker;
11pub use embassy_usb; 16use embassy_usb_driver as driver;
12use embassy_usb::driver::{self, EndpointError, Event, Unsupported}; 17use embassy_usb_driver::{Direction, EndpointAddress, EndpointError, EndpointInfo, EndpointType, Event, Unsupported};
13use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection};
14use futures::future::poll_fn;
15use futures::Future;
16use pac::usbd::RegisterBlock; 18use pac::usbd::RegisterBlock;
17 19
18use crate::interrupt::{Interrupt, InterruptExt}; 20use self::vbus_detect::VbusDetect;
21use crate::interrupt::typelevel::Interrupt;
19use crate::util::slice_in_ram; 22use crate::util::slice_in_ram;
20use crate::{pac, Peripheral}; 23use crate::{interrupt, pac, Peripheral};
21 24
22const NEW_AW: AtomicWaker = AtomicWaker::new(); 25const NEW_AW: AtomicWaker = AtomicWaker::new();
23static BUS_WAKER: AtomicWaker = NEW_AW; 26static BUS_WAKER: AtomicWaker = NEW_AW;
@@ -26,161 +29,13 @@ static EP_IN_WAKERS: [AtomicWaker; 8] = [NEW_AW; 8];
26static EP_OUT_WAKERS: [AtomicWaker; 8] = [NEW_AW; 8]; 29static EP_OUT_WAKERS: [AtomicWaker; 8] = [NEW_AW; 8];
27static READY_ENDPOINTS: AtomicU32 = AtomicU32::new(0); 30static READY_ENDPOINTS: AtomicU32 = AtomicU32::new(0);
28 31
29/// There are multiple ways to detect USB power. The behavior 32/// Interrupt handler.
30/// here provides a hook into determining whether it is. 33pub struct InterruptHandler<T: Instance> {
31pub trait UsbSupply { 34 _phantom: PhantomData<T>,
32 fn is_usb_detected(&self) -> bool;
33
34 type UsbPowerReadyFuture<'a>: Future<Output = Result<(), ()>> + 'a
35 where
36 Self: 'a;
37 fn wait_power_ready(&mut self) -> Self::UsbPowerReadyFuture<'_>;
38}
39
40pub struct Driver<'d, T: Instance, P: UsbSupply> {
41 _p: PeripheralRef<'d, T>,
42 alloc_in: Allocator,
43 alloc_out: Allocator,
44 usb_supply: P,
45}
46
47/// Uses the POWER peripheral to detect when power is available
48/// for USB. Unsuitable for usage with the nRF softdevice.
49#[cfg(not(feature = "_nrf5340-app"))]
50pub struct PowerUsb {
51 _private: (),
52}
53
54/// Can be used to signal that power is available. Particularly suited for
55/// use with the nRF softdevice.
56pub struct SignalledSupply {
57 usb_detected: AtomicBool,
58 power_ready: AtomicBool,
59}
60
61static POWER_WAKER: AtomicWaker = NEW_AW;
62
63#[cfg(not(feature = "_nrf5340-app"))]
64impl PowerUsb {
65 pub fn new(power_irq: impl Interrupt) -> Self {
66 let regs = unsafe { &*pac::POWER::ptr() };
67
68 power_irq.set_handler(Self::on_interrupt);
69 power_irq.unpend();
70 power_irq.enable();
71
72 regs.intenset
73 .write(|w| w.usbdetected().set().usbremoved().set().usbpwrrdy().set());
74
75 Self { _private: () }
76 }
77
78 #[cfg(not(feature = "_nrf5340-app"))]
79 fn on_interrupt(_: *mut ()) {
80 let regs = unsafe { &*pac::POWER::ptr() };
81
82 if regs.events_usbdetected.read().bits() != 0 {
83 regs.events_usbdetected.reset();
84 BUS_WAKER.wake();
85 }
86
87 if regs.events_usbremoved.read().bits() != 0 {
88 regs.events_usbremoved.reset();
89 BUS_WAKER.wake();
90 POWER_WAKER.wake();
91 }
92
93 if regs.events_usbpwrrdy.read().bits() != 0 {
94 regs.events_usbpwrrdy.reset();
95 POWER_WAKER.wake();
96 }
97 }
98}
99
100#[cfg(not(feature = "_nrf5340-app"))]
101impl UsbSupply for PowerUsb {
102 fn is_usb_detected(&self) -> bool {
103 let regs = unsafe { &*pac::POWER::ptr() };
104 regs.usbregstatus.read().vbusdetect().is_vbus_present()
105 }
106
107 type UsbPowerReadyFuture<'a> = impl Future<Output = Result<(), ()>> + 'a where Self: 'a;
108 fn wait_power_ready(&mut self) -> Self::UsbPowerReadyFuture<'_> {
109 poll_fn(move |cx| {
110 POWER_WAKER.register(cx.waker());
111 let regs = unsafe { &*pac::POWER::ptr() };
112
113 if regs.usbregstatus.read().outputrdy().is_ready() {
114 Poll::Ready(Ok(()))
115 } else if !self.is_usb_detected() {
116 Poll::Ready(Err(()))
117 } else {
118 Poll::Pending
119 }
120 })
121 }
122}
123
124impl SignalledSupply {
125 pub fn new(usb_detected: bool, power_ready: bool) -> Self {
126 BUS_WAKER.wake();
127
128 Self {
129 usb_detected: AtomicBool::new(usb_detected),
130 power_ready: AtomicBool::new(power_ready),
131 }
132 }
133
134 pub fn detected(&self, detected: bool) {
135 self.usb_detected.store(detected, Ordering::Relaxed);
136 self.power_ready.store(false, Ordering::Relaxed);
137 BUS_WAKER.wake();
138 POWER_WAKER.wake();
139 }
140
141 pub fn ready(&self) {
142 self.power_ready.store(true, Ordering::Relaxed);
143 POWER_WAKER.wake();
144 }
145}
146
147impl UsbSupply for &SignalledSupply {
148 fn is_usb_detected(&self) -> bool {
149 self.usb_detected.load(Ordering::Relaxed)
150 }
151
152 type UsbPowerReadyFuture<'a> = impl Future<Output = Result<(), ()>> + 'a where Self: 'a;
153 fn wait_power_ready(&mut self) -> Self::UsbPowerReadyFuture<'_> {
154 poll_fn(move |cx| {
155 POWER_WAKER.register(cx.waker());
156
157 if self.power_ready.load(Ordering::Relaxed) {
158 Poll::Ready(Ok(()))
159 } else if !self.usb_detected.load(Ordering::Relaxed) {
160 Poll::Ready(Err(()))
161 } else {
162 Poll::Pending
163 }
164 })
165 }
166} 35}
167 36
168impl<'d, T: Instance, P: UsbSupply> Driver<'d, T, P> { 37impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
169 pub fn new(usb: impl Peripheral<P = T> + 'd, irq: impl Peripheral<P = T::Interrupt> + 'd, usb_supply: P) -> Self { 38 unsafe fn on_interrupt() {
170 into_ref!(usb, irq);
171 irq.set_handler(Self::on_interrupt);
172 irq.unpend();
173 irq.enable();
174
175 Self {
176 _p: usb,
177 alloc_in: Allocator::new(),
178 alloc_out: Allocator::new(),
179 usb_supply,
180 }
181 }
182
183 fn on_interrupt(_: *mut ()) {
184 let regs = T::regs(); 39 let regs = T::regs();
185 40
186 if regs.events_usbreset.read().bits() != 0 { 41 if regs.events_usbreset.read().bits() != 0 {
@@ -231,25 +86,54 @@ impl<'d, T: Instance, P: UsbSupply> Driver<'d, T, P> {
231 } 86 }
232} 87}
233 88
234impl<'d, T: Instance, P: UsbSupply + 'd> driver::Driver<'d> for Driver<'d, T, P> { 89/// USB driver.
90pub struct Driver<'d, T: Instance, V: VbusDetect> {
91 _p: PeripheralRef<'d, T>,
92 alloc_in: Allocator,
93 alloc_out: Allocator,
94 vbus_detect: V,
95}
96
97impl<'d, T: Instance, V: VbusDetect> Driver<'d, T, V> {
98 /// Create a new USB driver.
99 pub fn new(
100 usb: impl Peripheral<P = T> + 'd,
101 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
102 vbus_detect: V,
103 ) -> Self {
104 into_ref!(usb);
105
106 T::Interrupt::unpend();
107 unsafe { T::Interrupt::enable() };
108
109 Self {
110 _p: usb,
111 alloc_in: Allocator::new(),
112 alloc_out: Allocator::new(),
113 vbus_detect,
114 }
115 }
116}
117
118impl<'d, T: Instance, V: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, T, V> {
235 type EndpointOut = Endpoint<'d, T, Out>; 119 type EndpointOut = Endpoint<'d, T, Out>;
236 type EndpointIn = Endpoint<'d, T, In>; 120 type EndpointIn = Endpoint<'d, T, In>;
237 type ControlPipe = ControlPipe<'d, T>; 121 type ControlPipe = ControlPipe<'d, T>;
238 type Bus = Bus<'d, T, P>; 122 type Bus = Bus<'d, T, V>;
239 123
240 fn alloc_endpoint_in( 124 fn alloc_endpoint_in(
241 &mut self, 125 &mut self,
242 ep_type: EndpointType, 126 ep_type: EndpointType,
243 packet_size: u16, 127 packet_size: u16,
244 interval: u8, 128 interval_ms: u8,
245 ) -> Result<Self::EndpointIn, driver::EndpointAllocError> { 129 ) -> Result<Self::EndpointIn, driver::EndpointAllocError> {
246 let index = self.alloc_in.allocate(ep_type)?; 130 let index = self.alloc_in.allocate(ep_type)?;
247 let ep_addr = EndpointAddress::from_parts(index, UsbDirection::In); 131 let ep_addr = EndpointAddress::from_parts(index, Direction::In);
248 Ok(Endpoint::new(EndpointInfo { 132 Ok(Endpoint::new(EndpointInfo {
249 addr: ep_addr, 133 addr: ep_addr,
250 ep_type, 134 ep_type,
251 max_packet_size: packet_size, 135 max_packet_size: packet_size,
252 interval, 136 interval_ms,
253 })) 137 }))
254 } 138 }
255 139
@@ -257,24 +141,24 @@ impl<'d, T: Instance, P: UsbSupply + 'd> driver::Driver<'d> for Driver<'d, T, P>
257 &mut self, 141 &mut self,
258 ep_type: EndpointType, 142 ep_type: EndpointType,
259 packet_size: u16, 143 packet_size: u16,
260 interval: u8, 144 interval_ms: u8,
261 ) -> Result<Self::EndpointOut, driver::EndpointAllocError> { 145 ) -> Result<Self::EndpointOut, driver::EndpointAllocError> {
262 let index = self.alloc_out.allocate(ep_type)?; 146 let index = self.alloc_out.allocate(ep_type)?;
263 let ep_addr = EndpointAddress::from_parts(index, UsbDirection::Out); 147 let ep_addr = EndpointAddress::from_parts(index, Direction::Out);
264 Ok(Endpoint::new(EndpointInfo { 148 Ok(Endpoint::new(EndpointInfo {
265 addr: ep_addr, 149 addr: ep_addr,
266 ep_type, 150 ep_type,
267 max_packet_size: packet_size, 151 max_packet_size: packet_size,
268 interval, 152 interval_ms,
269 })) 153 }))
270 } 154 }
271 155
272 fn start(mut self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) { 156 fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
273 ( 157 (
274 Bus { 158 Bus {
275 _p: unsafe { self._p.clone_unchecked() }, 159 _p: unsafe { self._p.clone_unchecked() },
276 power_available: false, 160 power_available: false,
277 usb_supply: self.usb_supply, 161 vbus_detect: self.vbus_detect,
278 }, 162 },
279 ControlPipe { 163 ControlPipe {
280 _p: self._p, 164 _p: self._p,
@@ -284,68 +168,60 @@ impl<'d, T: Instance, P: UsbSupply + 'd> driver::Driver<'d> for Driver<'d, T, P>
284 } 168 }
285} 169}
286 170
287pub struct Bus<'d, T: Instance, P: UsbSupply> { 171/// USB bus.
172pub struct Bus<'d, T: Instance, V: VbusDetect> {
288 _p: PeripheralRef<'d, T>, 173 _p: PeripheralRef<'d, T>,
289 power_available: bool, 174 power_available: bool,
290 usb_supply: P, 175 vbus_detect: V,
291} 176}
292 177
293impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> { 178impl<'d, T: Instance, V: VbusDetect> driver::Bus for Bus<'d, T, V> {
294 type EnableFuture<'a> = impl Future<Output = ()> + 'a where Self: 'a; 179 async fn enable(&mut self) {
295 type DisableFuture<'a> = impl Future<Output = ()> + 'a where Self: 'a; 180 let regs = T::regs();
296 type PollFuture<'a> = impl Future<Output = Event> + 'a where Self: 'a;
297 type RemoteWakeupFuture<'a> = impl Future<Output = Result<(), Unsupported>> + 'a where Self: 'a;
298
299 fn enable(&mut self) -> Self::EnableFuture<'_> {
300 async move {
301 let regs = T::regs();
302
303 errata::pre_enable();
304
305 regs.enable.write(|w| w.enable().enabled());
306
307 // Wait until the peripheral is ready.
308 regs.intenset.write(|w| w.usbevent().set_bit());
309 poll_fn(|cx| {
310 BUS_WAKER.register(cx.waker());
311 if regs.eventcause.read().ready().is_ready() {
312 Poll::Ready(())
313 } else {
314 Poll::Pending
315 }
316 })
317 .await;
318 regs.eventcause.write(|w| w.ready().set_bit()); // Write 1 to clear.
319
320 errata::post_enable();
321 181
322 unsafe { NVIC::unmask(pac::Interrupt::USBD) }; 182 errata::pre_enable();
323 183
324 regs.intenset.write(|w| { 184 regs.enable.write(|w| w.enable().enabled());
325 w.usbreset().set_bit();
326 w.usbevent().set_bit();
327 w.epdata().set_bit();
328 w
329 });
330 185
331 if self.usb_supply.wait_power_ready().await.is_ok() { 186 // Wait until the peripheral is ready.
332 // Enable the USB pullup, allowing enumeration. 187 regs.intenset.write(|w| w.usbevent().set_bit());
333 regs.usbpullup.write(|w| w.connect().enabled()); 188 poll_fn(|cx| {
334 trace!("enabled"); 189 BUS_WAKER.register(cx.waker());
190 if regs.eventcause.read().ready().is_ready() {
191 Poll::Ready(())
335 } else { 192 } else {
336 trace!("usb power not ready due to usb removal"); 193 Poll::Pending
337 } 194 }
195 })
196 .await;
197 regs.eventcause.write(|w| w.ready().clear_bit_by_one());
198
199 errata::post_enable();
200
201 unsafe { NVIC::unmask(pac::Interrupt::USBD) };
202
203 regs.intenset.write(|w| {
204 w.usbreset().set_bit();
205 w.usbevent().set_bit();
206 w.epdata().set_bit();
207 w
208 });
209
210 if self.vbus_detect.wait_power_ready().await.is_ok() {
211 // Enable the USB pullup, allowing enumeration.
212 regs.usbpullup.write(|w| w.connect().enabled());
213 trace!("enabled");
214 } else {
215 trace!("usb power not ready due to usb removal");
338 } 216 }
339 } 217 }
340 218
341 fn disable(&mut self) -> Self::DisableFuture<'_> { 219 async fn disable(&mut self) {
342 async move { 220 let regs = T::regs();
343 let regs = T::regs(); 221 regs.enable.write(|x| x.enable().disabled());
344 regs.enable.write(|x| x.enable().disabled());
345 }
346 } 222 }
347 223
348 fn poll<'a>(&'a mut self) -> Self::PollFuture<'a> { 224 async fn poll(&mut self) -> Event {
349 poll_fn(move |cx| { 225 poll_fn(move |cx| {
350 BUS_WAKER.register(cx.waker()); 226 BUS_WAKER.register(cx.waker());
351 let regs = T::regs(); 227 let regs = T::regs();
@@ -369,28 +245,28 @@ impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> {
369 let r = regs.eventcause.read(); 245 let r = regs.eventcause.read();
370 246
371 if r.isooutcrc().bit() { 247 if r.isooutcrc().bit() {
372 regs.eventcause.write(|w| w.isooutcrc().set_bit()); 248 regs.eventcause.write(|w| w.isooutcrc().detected());
373 trace!("USB event: isooutcrc"); 249 trace!("USB event: isooutcrc");
374 } 250 }
375 if r.usbwuallowed().bit() { 251 if r.usbwuallowed().bit() {
376 regs.eventcause.write(|w| w.usbwuallowed().set_bit()); 252 regs.eventcause.write(|w| w.usbwuallowed().allowed());
377 trace!("USB event: usbwuallowed"); 253 trace!("USB event: usbwuallowed");
378 } 254 }
379 if r.suspend().bit() { 255 if r.suspend().bit() {
380 regs.eventcause.write(|w| w.suspend().set_bit()); 256 regs.eventcause.write(|w| w.suspend().detected());
381 regs.lowpower.write(|w| w.lowpower().low_power()); 257 regs.lowpower.write(|w| w.lowpower().low_power());
382 return Poll::Ready(Event::Suspend); 258 return Poll::Ready(Event::Suspend);
383 } 259 }
384 if r.resume().bit() { 260 if r.resume().bit() {
385 regs.eventcause.write(|w| w.resume().set_bit()); 261 regs.eventcause.write(|w| w.resume().detected());
386 return Poll::Ready(Event::Resume); 262 return Poll::Ready(Event::Resume);
387 } 263 }
388 if r.ready().bit() { 264 if r.ready().bit() {
389 regs.eventcause.write(|w| w.ready().set_bit()); 265 regs.eventcause.write(|w| w.ready().ready());
390 trace!("USB event: ready"); 266 trace!("USB event: ready");
391 } 267 }
392 268
393 if self.usb_supply.is_usb_detected() != self.power_available { 269 if self.vbus_detect.is_usb_detected() != self.power_available {
394 self.power_available = !self.power_available; 270 self.power_available = !self.power_available;
395 if self.power_available { 271 if self.power_available {
396 trace!("Power event: available"); 272 trace!("Power event: available");
@@ -403,11 +279,7 @@ impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> {
403 279
404 Poll::Pending 280 Poll::Pending
405 }) 281 })
406 } 282 .await
407
408 #[inline]
409 fn set_address(&mut self, _addr: u8) {
410 // Nothing to do, the peripheral handles this.
411 } 283 }
412 284
413 fn endpoint_set_stalled(&mut self, ep_addr: EndpointAddress, stalled: bool) { 285 fn endpoint_set_stalled(&mut self, ep_addr: EndpointAddress, stalled: bool) {
@@ -429,8 +301,8 @@ impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> {
429 let regs = T::regs(); 301 let regs = T::regs();
430 let i = ep_addr.index(); 302 let i = ep_addr.index();
431 match ep_addr.direction() { 303 match ep_addr.direction() {
432 UsbDirection::Out => regs.halted.epout[i].read().getstatus().is_halted(), 304 Direction::Out => regs.halted.epout[i].read().getstatus().is_halted(),
433 UsbDirection::In => regs.halted.epin[i].read().getstatus().is_halted(), 305 Direction::In => regs.halted.epin[i].read().getstatus().is_halted(),
434 } 306 }
435 } 307 }
436 308
@@ -443,7 +315,7 @@ impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> {
443 debug!("endpoint_set_enabled {:?} {}", ep_addr, enabled); 315 debug!("endpoint_set_enabled {:?} {}", ep_addr, enabled);
444 316
445 match ep_addr.direction() { 317 match ep_addr.direction() {
446 UsbDirection::In => { 318 Direction::In => {
447 let mut was_enabled = false; 319 let mut was_enabled = false;
448 regs.epinen.modify(|r, w| { 320 regs.epinen.modify(|r, w| {
449 let mut bits = r.bits(); 321 let mut bits = r.bits();
@@ -467,7 +339,7 @@ impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> {
467 339
468 In::waker(i).wake(); 340 In::waker(i).wake();
469 } 341 }
470 UsbDirection::Out => { 342 Direction::Out => {
471 regs.epouten.modify(|r, w| { 343 regs.epouten.modify(|r, w| {
472 let mut bits = r.bits(); 344 let mut bits = r.bits();
473 if enabled { 345 if enabled {
@@ -495,46 +367,47 @@ impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> {
495 } 367 }
496 368
497 #[inline] 369 #[inline]
498 fn remote_wakeup(&mut self) -> Self::RemoteWakeupFuture<'_> { 370 async fn remote_wakeup(&mut self) -> Result<(), Unsupported> {
499 async move { 371 let regs = T::regs();
500 let regs = T::regs();
501 372
502 if regs.lowpower.read().lowpower().is_low_power() { 373 if regs.lowpower.read().lowpower().is_low_power() {
503 errata::pre_wakeup(); 374 errata::pre_wakeup();
504 375
505 regs.lowpower.write(|w| w.lowpower().force_normal()); 376 regs.lowpower.write(|w| w.lowpower().force_normal());
506 377
507 poll_fn(|cx| { 378 poll_fn(|cx| {
508 BUS_WAKER.register(cx.waker()); 379 BUS_WAKER.register(cx.waker());
509 let regs = T::regs(); 380 let regs = T::regs();
510 let r = regs.eventcause.read(); 381 let r = regs.eventcause.read();
511 382
512 if regs.events_usbreset.read().bits() != 0 { 383 if regs.events_usbreset.read().bits() != 0 {
513 Poll::Ready(()) 384 Poll::Ready(())
514 } else if r.resume().bit() { 385 } else if r.resume().bit() {
515 Poll::Ready(()) 386 Poll::Ready(())
516 } else if r.usbwuallowed().bit() { 387 } else if r.usbwuallowed().bit() {
517 regs.eventcause.write(|w| w.usbwuallowed().set_bit()); 388 regs.eventcause.write(|w| w.usbwuallowed().allowed());
518 389
519 regs.dpdmvalue.write(|w| w.state().resume()); 390 regs.dpdmvalue.write(|w| w.state().resume());
520 regs.tasks_dpdmdrive.write(|w| w.tasks_dpdmdrive().set_bit()); 391 regs.tasks_dpdmdrive.write(|w| w.tasks_dpdmdrive().set_bit());
521 392
522 Poll::Ready(()) 393 Poll::Ready(())
523 } else { 394 } else {
524 Poll::Pending 395 Poll::Pending
525 } 396 }
526 }) 397 })
527 .await; 398 .await;
528
529 errata::post_wakeup();
530 }
531 399
532 Ok(()) 400 errata::post_wakeup();
533 } 401 }
402
403 Ok(())
534 } 404 }
535} 405}
536 406
407/// Type-level marker for OUT endpoints.
537pub enum Out {} 408pub enum Out {}
409
410/// Type-level marker for IN endpoints.
538pub enum In {} 411pub enum In {}
539 412
540trait EndpointDir { 413trait EndpointDir {
@@ -577,6 +450,7 @@ impl EndpointDir for Out {
577 } 450 }
578} 451}
579 452
453/// USB endpoint.
580pub struct Endpoint<'d, T: Instance, Dir> { 454pub struct Endpoint<'d, T: Instance, Dir> {
581 _phantom: PhantomData<(&'d mut T, Dir)>, 455 _phantom: PhantomData<(&'d mut T, Dir)>,
582 info: EndpointInfo, 456 info: EndpointInfo,
@@ -596,9 +470,7 @@ impl<'d, T: Instance, Dir: EndpointDir> driver::Endpoint for Endpoint<'d, T, Dir
596 &self.info 470 &self.info
597 } 471 }
598 472
599 type WaitEnabledFuture<'a> = impl Future<Output = ()> + 'a where Self: 'a; 473 async fn wait_enabled(&mut self) {
600
601 fn wait_enabled(&mut self) -> Self::WaitEnabledFuture<'_> {
602 let i = self.info.addr.index(); 474 let i = self.info.addr.index();
603 assert!(i != 0); 475 assert!(i != 0);
604 476
@@ -610,6 +482,7 @@ impl<'d, T: Instance, Dir: EndpointDir> driver::Endpoint for Endpoint<'d, T, Dir
610 Poll::Pending 482 Poll::Pending
611 } 483 }
612 }) 484 })
485 .await
613 } 486 }
614} 487}
615 488
@@ -714,173 +587,155 @@ unsafe fn write_dma<T: Instance>(i: usize, buf: &[u8]) {
714} 587}
715 588
716impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> { 589impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> {
717 type ReadFuture<'a> = impl Future<Output = Result<usize, EndpointError>> + 'a where Self: 'a; 590 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> {
718 591 let i = self.info.addr.index();
719 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { 592 assert!(i != 0);
720 async move {
721 let i = self.info.addr.index();
722 assert!(i != 0);
723 593
724 self.wait_data_ready().await.map_err(|_| EndpointError::Disabled)?; 594 self.wait_data_ready().await.map_err(|_| EndpointError::Disabled)?;
725 595
726 unsafe { read_dma::<T>(i, buf) } 596 unsafe { read_dma::<T>(i, buf) }
727 }
728 } 597 }
729} 598}
730 599
731impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> { 600impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
732 type WriteFuture<'a> = impl Future<Output = Result<(), EndpointError>> + 'a where Self: 'a; 601 async fn write(&mut self, buf: &[u8]) -> Result<(), EndpointError> {
733 602 let i = self.info.addr.index();
734 fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { 603 assert!(i != 0);
735 async move {
736 let i = self.info.addr.index();
737 assert!(i != 0);
738 604
739 self.wait_data_ready().await.map_err(|_| EndpointError::Disabled)?; 605 self.wait_data_ready().await.map_err(|_| EndpointError::Disabled)?;
740 606
741 unsafe { write_dma::<T>(i, buf) } 607 unsafe { write_dma::<T>(i, buf) }
742 608
743 Ok(()) 609 Ok(())
744 }
745 } 610 }
746} 611}
747 612
613/// USB control pipe.
748pub struct ControlPipe<'d, T: Instance> { 614pub struct ControlPipe<'d, T: Instance> {
749 _p: PeripheralRef<'d, T>, 615 _p: PeripheralRef<'d, T>,
750 max_packet_size: u16, 616 max_packet_size: u16,
751} 617}
752 618
753impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { 619impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
754 type SetupFuture<'a> = impl Future<Output = [u8;8]> + 'a where Self: 'a;
755 type DataOutFuture<'a> = impl Future<Output = Result<usize, EndpointError>> + 'a where Self: 'a;
756 type DataInFuture<'a> = impl Future<Output = Result<(), EndpointError>> + 'a where Self: 'a;
757 type AcceptFuture<'a> = impl Future<Output = ()> + 'a where Self: 'a;
758 type RejectFuture<'a> = impl Future<Output = ()> + 'a where Self: 'a;
759
760 fn max_packet_size(&self) -> usize { 620 fn max_packet_size(&self) -> usize {
761 usize::from(self.max_packet_size) 621 usize::from(self.max_packet_size)
762 } 622 }
763 623
764 fn setup<'a>(&'a mut self) -> Self::SetupFuture<'a> { 624 async fn setup(&mut self) -> [u8; 8] {
765 async move { 625 let regs = T::regs();
766 let regs = T::regs();
767 626
768 // Reset shorts 627 // Reset shorts
769 regs.shorts.write(|w| w); 628 regs.shorts.write(|w| w);
770 629
771 // Wait for SETUP packet 630 // Wait for SETUP packet
772 regs.intenset.write(|w| w.ep0setup().set()); 631 regs.intenset.write(|w| w.ep0setup().set());
773 poll_fn(|cx| { 632 poll_fn(|cx| {
774 EP0_WAKER.register(cx.waker()); 633 EP0_WAKER.register(cx.waker());
775 let regs = T::regs(); 634 let regs = T::regs();
776 if regs.events_ep0setup.read().bits() != 0 { 635 if regs.events_ep0setup.read().bits() != 0 {
777 Poll::Ready(()) 636 Poll::Ready(())
778 } else { 637 } else {
779 Poll::Pending 638 Poll::Pending
780 } 639 }
781 }) 640 })
782 .await; 641 .await;
783 642
784 regs.events_ep0setup.reset(); 643 regs.events_ep0setup.reset();
785 644
786 let mut buf = [0; 8]; 645 let mut buf = [0; 8];
787 buf[0] = regs.bmrequesttype.read().bits() as u8; 646 buf[0] = regs.bmrequesttype.read().bits() as u8;
788 buf[1] = regs.brequest.read().brequest().bits(); 647 buf[1] = regs.brequest.read().brequest().bits();
789 buf[2] = regs.wvaluel.read().wvaluel().bits(); 648 buf[2] = regs.wvaluel.read().wvaluel().bits();
790 buf[3] = regs.wvalueh.read().wvalueh().bits(); 649 buf[3] = regs.wvalueh.read().wvalueh().bits();
791 buf[4] = regs.windexl.read().windexl().bits(); 650 buf[4] = regs.windexl.read().windexl().bits();
792 buf[5] = regs.windexh.read().windexh().bits(); 651 buf[5] = regs.windexh.read().windexh().bits();
793 buf[6] = regs.wlengthl.read().wlengthl().bits(); 652 buf[6] = regs.wlengthl.read().wlengthl().bits();
794 buf[7] = regs.wlengthh.read().wlengthh().bits(); 653 buf[7] = regs.wlengthh.read().wlengthh().bits();
795 654
796 buf 655 buf
797 }
798 } 656 }
799 657
800 fn data_out<'a>(&'a mut self, buf: &'a mut [u8], _first: bool, _last: bool) -> Self::DataOutFuture<'a> { 658 async fn data_out(&mut self, buf: &mut [u8], _first: bool, _last: bool) -> Result<usize, EndpointError> {
801 async move { 659 let regs = T::regs();
802 let regs = T::regs();
803 660
804 regs.events_ep0datadone.reset(); 661 regs.events_ep0datadone.reset();
805 662
806 // This starts a RX on EP0. events_ep0datadone notifies when done. 663 // This starts a RX on EP0. events_ep0datadone notifies when done.
807 regs.tasks_ep0rcvout.write(|w| w.tasks_ep0rcvout().set_bit()); 664 regs.tasks_ep0rcvout.write(|w| w.tasks_ep0rcvout().set_bit());
808 665
809 // Wait until ready 666 // Wait until ready
810 regs.intenset.write(|w| { 667 regs.intenset.write(|w| {
811 w.usbreset().set(); 668 w.usbreset().set();
812 w.ep0setup().set(); 669 w.ep0setup().set();
813 w.ep0datadone().set() 670 w.ep0datadone().set()
814 }); 671 });
815 poll_fn(|cx| { 672 poll_fn(|cx| {
816 EP0_WAKER.register(cx.waker()); 673 EP0_WAKER.register(cx.waker());
817 let regs = T::regs(); 674 let regs = T::regs();
818 if regs.events_ep0datadone.read().bits() != 0 { 675 if regs.events_ep0datadone.read().bits() != 0 {
819 Poll::Ready(Ok(())) 676 Poll::Ready(Ok(()))
820 } else if regs.events_usbreset.read().bits() != 0 { 677 } else if regs.events_usbreset.read().bits() != 0 {
821 trace!("aborted control data_out: usb reset"); 678 trace!("aborted control data_out: usb reset");
822 Poll::Ready(Err(EndpointError::Disabled)) 679 Poll::Ready(Err(EndpointError::Disabled))
823 } else if regs.events_ep0setup.read().bits() != 0 { 680 } else if regs.events_ep0setup.read().bits() != 0 {
824 trace!("aborted control data_out: received another SETUP"); 681 trace!("aborted control data_out: received another SETUP");
825 Poll::Ready(Err(EndpointError::Disabled)) 682 Poll::Ready(Err(EndpointError::Disabled))
826 } else { 683 } else {
827 Poll::Pending 684 Poll::Pending
828 } 685 }
829 }) 686 })
830 .await?; 687 .await?;
831 688
832 unsafe { read_dma::<T>(0, buf) } 689 unsafe { read_dma::<T>(0, buf) }
833 }
834 } 690 }
835 691
836 fn data_in<'a>(&'a mut self, buf: &'a [u8], _first: bool, last: bool) -> Self::DataInFuture<'a> { 692 async fn data_in(&mut self, buf: &[u8], _first: bool, last: bool) -> Result<(), EndpointError> {
837 async move { 693 let regs = T::regs();
838 let regs = T::regs(); 694 regs.events_ep0datadone.reset();
839 regs.events_ep0datadone.reset();
840 695
841 regs.shorts.write(|w| w.ep0datadone_ep0status().bit(last)); 696 regs.shorts.write(|w| w.ep0datadone_ep0status().bit(last));
842 697
843 // This starts a TX on EP0. events_ep0datadone notifies when done. 698 // This starts a TX on EP0. events_ep0datadone notifies when done.
844 unsafe { write_dma::<T>(0, buf) } 699 unsafe { write_dma::<T>(0, buf) }
845 700
846 regs.intenset.write(|w| { 701 regs.intenset.write(|w| {
847 w.usbreset().set(); 702 w.usbreset().set();
848 w.ep0setup().set(); 703 w.ep0setup().set();
849 w.ep0datadone().set() 704 w.ep0datadone().set()
850 }); 705 });
851 706
852 poll_fn(|cx| { 707 poll_fn(|cx| {
853 cx.waker().wake_by_ref(); 708 cx.waker().wake_by_ref();
854 EP0_WAKER.register(cx.waker()); 709 EP0_WAKER.register(cx.waker());
855 let regs = T::regs(); 710 let regs = T::regs();
856 if regs.events_ep0datadone.read().bits() != 0 { 711 if regs.events_ep0datadone.read().bits() != 0 {
857 Poll::Ready(Ok(())) 712 Poll::Ready(Ok(()))
858 } else if regs.events_usbreset.read().bits() != 0 { 713 } else if regs.events_usbreset.read().bits() != 0 {
859 trace!("aborted control data_in: usb reset"); 714 trace!("aborted control data_in: usb reset");
860 Poll::Ready(Err(EndpointError::Disabled)) 715 Poll::Ready(Err(EndpointError::Disabled))
861 } else if regs.events_ep0setup.read().bits() != 0 { 716 } else if regs.events_ep0setup.read().bits() != 0 {
862 trace!("aborted control data_in: received another SETUP"); 717 trace!("aborted control data_in: received another SETUP");
863 Poll::Ready(Err(EndpointError::Disabled)) 718 Poll::Ready(Err(EndpointError::Disabled))
864 } else { 719 } else {
865 Poll::Pending 720 Poll::Pending
866 } 721 }
867 }) 722 })
868 .await 723 .await
869 }
870 } 724 }
871 725
872 fn accept<'a>(&'a mut self) -> Self::AcceptFuture<'a> { 726 async fn accept(&mut self) {
873 async move { 727 let regs = T::regs();
874 let regs = T::regs(); 728 regs.tasks_ep0status.write(|w| w.tasks_ep0status().bit(true));
875 regs.tasks_ep0status.write(|w| w.tasks_ep0status().bit(true));
876 }
877 } 729 }
878 730
879 fn reject<'a>(&'a mut self) -> Self::RejectFuture<'a> { 731 async fn reject(&mut self) {
880 async move { 732 let regs = T::regs();
881 let regs = T::regs(); 733 regs.tasks_ep0stall.write(|w| w.tasks_ep0stall().bit(true));
882 regs.tasks_ep0stall.write(|w| w.tasks_ep0stall().bit(true)); 734 }
883 } 735
736 async fn accept_set_address(&mut self, _addr: u8) {
737 self.accept().await;
738 // Nothing to do, the peripheral handles this.
884 } 739 }
885} 740}
886 741
@@ -946,8 +801,10 @@ pub(crate) mod sealed {
946 } 801 }
947} 802}
948 803
804/// USB peripheral instance.
949pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send { 805pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
950 type Interrupt: Interrupt; 806 /// Interrupt for this peripheral.
807 type Interrupt: interrupt::typelevel::Interrupt;
951} 808}
952 809
953macro_rules! impl_usb { 810macro_rules! impl_usb {
@@ -958,7 +815,7 @@ macro_rules! impl_usb {
958 } 815 }
959 } 816 }
960 impl crate::usb::Instance for peripherals::$type { 817 impl crate::usb::Instance for peripherals::$type {
961 type Interrupt = crate::interrupt::$irq; 818 type Interrupt = crate::interrupt::typelevel::$irq;
962 } 819 }
963 }; 820 };
964} 821}
diff --git a/embassy-nrf/src/usb/vbus_detect.rs b/embassy-nrf/src/usb/vbus_detect.rs
new file mode 100644
index 000000000..a05e5aa52
--- /dev/null
+++ b/embassy-nrf/src/usb/vbus_detect.rs
@@ -0,0 +1,177 @@
1//! Trait and implementations for performing VBUS detection.
2
3use core::future::poll_fn;
4use core::sync::atomic::{AtomicBool, Ordering};
5use core::task::Poll;
6
7use embassy_sync::waitqueue::AtomicWaker;
8
9use super::BUS_WAKER;
10use crate::interrupt::typelevel::Interrupt;
11use crate::{interrupt, pac};
12
13/// Trait for detecting USB VBUS power.
14///
15/// There are multiple ways to detect USB power. The behavior
16/// here provides a hook into determining whether it is.
17pub trait VbusDetect {
18 /// Report whether power is detected.
19 ///
20 /// This is indicated by the `USBREGSTATUS.VBUSDETECT` register, or the
21 /// `USBDETECTED`, `USBREMOVED` events from the `POWER` peripheral.
22 fn is_usb_detected(&self) -> bool;
23
24 /// Wait until USB power is ready.
25 ///
26 /// USB power ready is indicated by the `USBREGSTATUS.OUTPUTRDY` register, or the
27 /// `USBPWRRDY` event from the `POWER` peripheral.
28 async fn wait_power_ready(&mut self) -> Result<(), ()>;
29}
30
31#[cfg(not(feature = "_nrf5340"))]
32type UsbRegIrq = interrupt::typelevel::POWER_CLOCK;
33#[cfg(feature = "_nrf5340")]
34type UsbRegIrq = interrupt::typelevel::USBREGULATOR;
35
36#[cfg(not(feature = "_nrf5340"))]
37type UsbRegPeri = pac::POWER;
38#[cfg(feature = "_nrf5340")]
39type UsbRegPeri = pac::USBREGULATOR;
40
41/// Interrupt handler.
42pub struct InterruptHandler {
43 _private: (),
44}
45
46impl interrupt::typelevel::Handler<UsbRegIrq> for InterruptHandler {
47 unsafe fn on_interrupt() {
48 let regs = unsafe { &*UsbRegPeri::ptr() };
49
50 if regs.events_usbdetected.read().bits() != 0 {
51 regs.events_usbdetected.reset();
52 BUS_WAKER.wake();
53 }
54
55 if regs.events_usbremoved.read().bits() != 0 {
56 regs.events_usbremoved.reset();
57 BUS_WAKER.wake();
58 POWER_WAKER.wake();
59 }
60
61 if regs.events_usbpwrrdy.read().bits() != 0 {
62 regs.events_usbpwrrdy.reset();
63 POWER_WAKER.wake();
64 }
65 }
66}
67
68/// [`VbusDetect`] implementation using the native hardware POWER peripheral.
69///
70/// Unsuitable for usage with the nRF softdevice, since it reserves exclusive acces
71/// to POWER. In that case, use [`VbusDetectSignal`].
72pub struct HardwareVbusDetect {
73 _private: (),
74}
75
76static POWER_WAKER: AtomicWaker = AtomicWaker::new();
77
78impl HardwareVbusDetect {
79 /// Create a new `VbusDetectNative`.
80 pub fn new(_irq: impl interrupt::typelevel::Binding<UsbRegIrq, InterruptHandler> + 'static) -> Self {
81 let regs = unsafe { &*UsbRegPeri::ptr() };
82
83 UsbRegIrq::unpend();
84 unsafe { UsbRegIrq::enable() };
85
86 regs.intenset
87 .write(|w| w.usbdetected().set().usbremoved().set().usbpwrrdy().set());
88
89 Self { _private: () }
90 }
91}
92
93impl VbusDetect for HardwareVbusDetect {
94 fn is_usb_detected(&self) -> bool {
95 let regs = unsafe { &*UsbRegPeri::ptr() };
96 regs.usbregstatus.read().vbusdetect().is_vbus_present()
97 }
98
99 async fn wait_power_ready(&mut self) -> Result<(), ()> {
100 poll_fn(move |cx| {
101 POWER_WAKER.register(cx.waker());
102 let regs = unsafe { &*UsbRegPeri::ptr() };
103
104 if regs.usbregstatus.read().outputrdy().is_ready() {
105 Poll::Ready(Ok(()))
106 } else if !self.is_usb_detected() {
107 Poll::Ready(Err(()))
108 } else {
109 Poll::Pending
110 }
111 })
112 .await
113 }
114}
115
116/// Software-backed [`VbusDetect`] implementation.
117///
118/// This implementation does not interact with the hardware, it allows user code
119/// to notify the power events by calling functions instead.
120///
121/// This is suitable for use with the nRF softdevice, by calling the functions
122/// when the softdevice reports power-related events.
123pub struct SoftwareVbusDetect {
124 usb_detected: AtomicBool,
125 power_ready: AtomicBool,
126}
127
128impl SoftwareVbusDetect {
129 /// Create a new `SoftwareVbusDetect`.
130 pub fn new(usb_detected: bool, power_ready: bool) -> Self {
131 BUS_WAKER.wake();
132
133 Self {
134 usb_detected: AtomicBool::new(usb_detected),
135 power_ready: AtomicBool::new(power_ready),
136 }
137 }
138
139 /// Report whether power was detected.
140 ///
141 /// Equivalent to the `USBDETECTED`, `USBREMOVED` events from the `POWER` peripheral.
142 pub fn detected(&self, detected: bool) {
143 self.usb_detected.store(detected, Ordering::Relaxed);
144 self.power_ready.store(false, Ordering::Relaxed);
145 BUS_WAKER.wake();
146 POWER_WAKER.wake();
147 }
148
149 /// Report when USB power is ready.
150 ///
151 /// Equivalent to the `USBPWRRDY` event from the `POWER` peripheral.
152 pub fn ready(&self) {
153 self.power_ready.store(true, Ordering::Relaxed);
154 POWER_WAKER.wake();
155 }
156}
157
158impl VbusDetect for &SoftwareVbusDetect {
159 fn is_usb_detected(&self) -> bool {
160 self.usb_detected.load(Ordering::Relaxed)
161 }
162
163 async fn wait_power_ready(&mut self) -> Result<(), ()> {
164 poll_fn(move |cx| {
165 POWER_WAKER.register(cx.waker());
166
167 if self.power_ready.load(Ordering::Relaxed) {
168 Poll::Ready(Ok(()))
169 } else if !self.usb_detected.load(Ordering::Relaxed) {
170 Poll::Ready(Err(()))
171 } else {
172 Poll::Pending
173 }
174 })
175 .await
176 }
177}
diff --git a/embassy-nrf/src/wdt.rs b/embassy-nrf/src/wdt.rs
index 8760aa301..40a674424 100644
--- a/embassy-nrf/src/wdt.rs
+++ b/embassy-nrf/src/wdt.rs
@@ -1,4 +1,4 @@
1//! HAL interface to the WDT peripheral. 1//! Watchdog Timer (WDT) driver.
2//! 2//!
3//! This HAL implements a basic watchdog timer with 1..=8 handles. 3//! This HAL implements a basic watchdog timer with 1..=8 handles.
4//! Once the watchdog has been started, it cannot be stopped. 4//! Once the watchdog has been started, it cannot be stopped.
@@ -8,6 +8,7 @@ use crate::peripherals;
8 8
9const MIN_TICKS: u32 = 15; 9const MIN_TICKS: u32 = 15;
10 10
11/// WDT configuration.
11#[non_exhaustive] 12#[non_exhaustive]
12pub struct Config { 13pub struct Config {
13 /// Number of 32768 Hz ticks in each watchdog period. 14 /// Number of 32768 Hz ticks in each watchdog period.
@@ -23,6 +24,30 @@ pub struct Config {
23 pub run_during_debug_halt: bool, 24 pub run_during_debug_halt: bool,
24} 25}
25 26
27impl Config {
28 /// Create a config structure from the current configuration of the WDT
29 /// peripheral.
30 pub fn try_new(_wdt: &peripherals::WDT) -> Option<Self> {
31 let r = unsafe { &*WDT::ptr() };
32
33 #[cfg(not(feature = "_nrf9160"))]
34 let runstatus = r.runstatus.read().runstatus().bit();
35 #[cfg(feature = "_nrf9160")]
36 let runstatus = r.runstatus.read().runstatuswdt().bit();
37
38 if runstatus {
39 let config = r.config.read();
40 Some(Self {
41 timeout_ticks: r.crv.read().bits(),
42 run_during_sleep: config.sleep().bit(),
43 run_during_debug_halt: config.halt().bit(),
44 })
45 } else {
46 None
47 }
48 }
49}
50
26impl Default for Config { 51impl Default for Config {
27 fn default() -> Self { 52 fn default() -> Self {
28 Self { 53 Self {
@@ -33,13 +58,13 @@ impl Default for Config {
33 } 58 }
34} 59}
35 60
36/// An interface to the Watchdog. 61/// Watchdog driver.
37pub struct Watchdog { 62pub struct Watchdog {
38 _private: (), 63 _private: (),
39} 64}
40 65
41impl Watchdog { 66impl Watchdog {
42 /// Try to create a new watchdog instance from the peripheral. 67 /// Try to create a new watchdog driver.
43 /// 68 ///
44 /// This function will return an error if the watchdog is already active 69 /// This function will return an error if the watchdog is already active
45 /// with a `config` different to the requested one, or a different number of 70 /// with a `config` different to the requested one, or a different number of
@@ -131,6 +156,7 @@ impl Watchdog {
131 } 156 }
132} 157}
133 158
159/// Watchdog handle.
134pub struct WatchdogHandle { 160pub struct WatchdogHandle {
135 index: u8, 161 index: u8,
136} 162}