aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf/Cargo.toml8
-rw-r--r--embassy-nrf/src/buffered_uarte.rs14
-rw-r--r--embassy-nrf/src/gpio.rs253
-rw-r--r--embassy-nrf/src/gpiote.rs224
-rw-r--r--embassy-nrf/src/qspi.rs208
-rw-r--r--embassy-nrf/src/rng.rs115
-rw-r--r--embassy-nrf/src/spim.rs460
-rw-r--r--embassy-nrf/src/twim.rs687
-rw-r--r--embassy-nrf/src/uarte.rs644
-rw-r--r--embassy-nrf/src/util.rs22
-rw-r--r--examples/nrf/Cargo.toml1
-rw-r--r--examples/nrf/src/bin/gpiote_port.rs1
-rw-r--r--examples/nrf/src/bin/qspi.rs1
-rw-r--r--examples/nrf/src/bin/qspi_lowpower.rs1
-rw-r--r--examples/nrf/src/bin/rng.rs6
-rw-r--r--examples/nrf/src/bin/spim.rs9
-rw-r--r--examples/nrf/src/bin/twim.rs2
-rw-r--r--examples/nrf/src/bin/twim_lowpower.rs2
-rw-r--r--examples/nrf/src/bin/uart.rs1
-rw-r--r--examples/nrf/src/bin/uart_idle.rs10
-rw-r--r--examples/nrf/src/bin/uart_split.rs9
-rw-r--r--examples/nrf/src/bin/wdt.rs1
22 files changed, 1594 insertions, 1085 deletions
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml
index 3d0c171f3..c9bd2bc14 100644
--- a/embassy-nrf/Cargo.toml
+++ b/embassy-nrf/Cargo.toml
@@ -12,6 +12,9 @@ edition = "2018"
12# There are no plans to make this stable. 12# There are no plans to make this stable.
13unstable-pac = [] 13unstable-pac = []
14 14
15# Implement embedded-hal 1.0 alpha and embedded-hal-async traits.
16unstable-traits = ["embedded-hal-1", "embedded-hal-async"]
17
15nrf52805 = ["nrf52805-pac", "_ppi"] 18nrf52805 = ["nrf52805-pac", "_ppi"]
16nrf52810 = ["nrf52810-pac", "_ppi"] 19nrf52810 = ["nrf52810-pac", "_ppi"]
17nrf52811 = ["nrf52811-pac", "_ppi"] 20nrf52811 = ["nrf52811-pac", "_ppi"]
@@ -47,11 +50,14 @@ embassy = { version = "0.1.0", path = "../embassy" }
47embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["nrf"]} 50embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["nrf"]}
48embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } 51embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" }
49 52
53embedded-hal-02 = { package = "embedded-hal", version = "0.2.6" }
54embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.6", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy", optional = true}
55embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy", optional = true}
56
50defmt = { version = "0.3", optional = true } 57defmt = { version = "0.3", optional = true }
51log = { version = "0.4.14", optional = true } 58log = { version = "0.4.14", optional = true }
52cortex-m-rt = ">=0.6.15,<0.8" 59cortex-m-rt = ">=0.6.15,<0.8"
53cortex-m = "0.7.3" 60cortex-m = "0.7.3"
54embedded-hal = "0.2.6"
55embedded-dma = "0.1.2" 61embedded-dma = "0.1.2"
56futures = { version = "0.3.17", default-features = false } 62futures = { version = "0.3.17", default-features = false }
57critical-section = "0.2.5" 63critical-section = "0.2.5"
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs
index 45e8afc4b..2880c84f6 100644
--- a/embassy-nrf/src/buffered_uarte.rs
+++ b/embassy-nrf/src/buffered_uarte.rs
@@ -213,9 +213,6 @@ impl<'d, U: UarteInstance, T: TimerInstance> AsyncBufRead for BufferedUarte<'d,
213 cx: &mut Context<'_>, 213 cx: &mut Context<'_>,
214 ) -> Poll<embassy::io::Result<&[u8]>> { 214 ) -> Poll<embassy::io::Result<&[u8]>> {
215 self.inner.with(|state| { 215 self.inner.with(|state| {
216 // Conservative compiler fence to prevent optimizations that do not
217 // take in to account actions by DMA. The fence has been placed here,
218 // before any DMA action has started
219 compiler_fence(Ordering::SeqCst); 216 compiler_fence(Ordering::SeqCst);
220 trace!("poll_read"); 217 trace!("poll_read");
221 218
@@ -265,9 +262,6 @@ impl<'d, U: UarteInstance, T: TimerInstance> AsyncWrite for BufferedUarte<'d, U,
265 262
266 trace!("poll_write: queued {:?}", n); 263 trace!("poll_write: queued {:?}", n);
267 264
268 // Conservative compiler fence to prevent optimizations that do not
269 // take in to account actions by DMA. The fence has been placed here,
270 // before any DMA action has started
271 compiler_fence(Ordering::SeqCst); 265 compiler_fence(Ordering::SeqCst);
272 266
273 Poll::Ready(Ok(n)) 267 Poll::Ready(Ok(n))
@@ -347,9 +341,7 @@ impl<'a, U: UarteInstance, T: TimerInstance> PeripheralState for StateInner<'a,
347 trace!(" irq_rx: buf {:?} {:?}", buf.as_ptr() as u32, buf.len()); 341 trace!(" irq_rx: buf {:?} {:?}", buf.as_ptr() as u32, buf.len());
348 342
349 // Start UARTE Receive transaction 343 // Start UARTE Receive transaction
350 r.tasks_startrx.write(|w| 344 r.tasks_startrx.write(|w| unsafe { w.bits(1) });
351 // `1` is a valid value to write to task registers.
352 unsafe { w.bits(1) });
353 } 345 }
354 break; 346 break;
355 } 347 }
@@ -397,9 +389,7 @@ impl<'a, U: UarteInstance, T: TimerInstance> PeripheralState for StateInner<'a,
397 unsafe { w.maxcnt().bits(buf.len() as _) }); 389 unsafe { w.maxcnt().bits(buf.len() as _) });
398 390
399 // Start UARTE Transmit transaction 391 // Start UARTE Transmit transaction
400 r.tasks_starttx.write(|w| 392 r.tasks_starttx.write(|w| unsafe { w.bits(1) });
401 // `1` is a valid value to write to task registers.
402 unsafe { w.bits(1) });
403 } 393 }
404 break; 394 break;
405 } 395 }
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs
index ddc84cf5d..3f204d564 100644
--- a/embassy-nrf/src/gpio.rs
+++ b/embassy-nrf/src/gpio.rs
@@ -7,7 +7,6 @@ use core::marker::PhantomData;
7use cfg_if::cfg_if; 7use cfg_if::cfg_if;
8use embassy::util::Unborrow; 8use embassy::util::Unborrow;
9use embassy_hal_common::{unborrow, unsafe_impl_unborrow}; 9use embassy_hal_common::{unborrow, unsafe_impl_unborrow};
10use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
11use gpio::pin_cnf::DRIVE_A; 10use gpio::pin_cnf::DRIVE_A;
12 11
13use crate::pac; 12use crate::pac;
@@ -37,12 +36,12 @@ pub enum Pull {
37 36
38/// GPIO input driver. 37/// GPIO input driver.
39pub struct Input<'d, T: Pin> { 38pub struct Input<'d, T: Pin> {
40 pub(crate) pin: FlexPin<'d, T>, 39 pub(crate) pin: Flex<'d, T>,
41} 40}
42 41
43impl<'d, T: Pin> Input<'d, T> { 42impl<'d, T: Pin> Input<'d, T> {
44 pub fn new(pin: impl Unborrow<Target = T> + 'd, pull: Pull) -> Self { 43 pub fn new(pin: impl Unborrow<Target = T> + 'd, pull: Pull) -> Self {
45 let mut pin = FlexPin::new(pin); 44 let mut pin = Flex::new(pin);
46 pin.set_as_input(pull); 45 pin.set_as_input(pull);
47 46
48 Self { pin } 47 Self { pin }
@@ -57,18 +56,6 @@ impl<'d, T: Pin> Input<'d, T> {
57 } 56 }
58} 57}
59 58
60impl<'d, T: Pin> InputPin for Input<'d, T> {
61 type Error = Infallible;
62
63 fn is_high(&self) -> Result<bool, Self::Error> {
64 Ok(self.is_high())
65 }
66
67 fn is_low(&self) -> Result<bool, Self::Error> {
68 Ok(self.is_low())
69 }
70}
71
72/// Digital input or output level. 59/// Digital input or output level.
73#[derive(Debug, Eq, PartialEq)] 60#[derive(Debug, Eq, PartialEq)]
74#[cfg_attr(feature = "defmt", derive(defmt::Format))] 61#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -102,7 +89,7 @@ pub enum OutputDrive {
102 89
103/// GPIO output driver. 90/// GPIO output driver.
104pub struct Output<'d, T: Pin> { 91pub struct Output<'d, T: Pin> {
105 pub(crate) pin: FlexPin<'d, T>, 92 pub(crate) pin: Flex<'d, T>,
106} 93}
107 94
108impl<'d, T: Pin> Output<'d, T> { 95impl<'d, T: Pin> Output<'d, T> {
@@ -111,7 +98,7 @@ impl<'d, T: Pin> Output<'d, T> {
111 initial_output: Level, 98 initial_output: Level,
112 drive: OutputDrive, 99 drive: OutputDrive,
113 ) -> Self { 100 ) -> Self {
114 let mut pin = FlexPin::new(pin); 101 let mut pin = Flex::new(pin);
115 match initial_output { 102 match initial_output {
116 Level::High => pin.set_high(), 103 Level::High => pin.set_high(),
117 Level::Low => pin.set_low(), 104 Level::Low => pin.set_low(),
@@ -142,40 +129,18 @@ impl<'d, T: Pin> Output<'d, T> {
142 } 129 }
143} 130}
144 131
145impl<'d, T: Pin> OutputPin for Output<'d, T> {
146 type Error = Infallible;
147
148 fn set_high(&mut self) -> Result<(), Self::Error> {
149 Ok(self.set_high())
150 }
151
152 fn set_low(&mut self) -> Result<(), Self::Error> {
153 Ok(self.set_low())
154 }
155}
156
157impl<'d, T: Pin> StatefulOutputPin for Output<'d, T> {
158 fn is_set_high(&self) -> Result<bool, Self::Error> {
159 Ok(self.is_set_high())
160 }
161
162 fn is_set_low(&self) -> Result<bool, Self::Error> {
163 Ok(self.is_set_low())
164 }
165}
166
167/// GPIO flexible pin. 132/// GPIO flexible pin.
168/// 133///
169/// This pin can either be a disconnected, input, or output pin. The level register bit will remain 134/// This pin can either be a disconnected, input, or output pin. The level register bit will remain
170/// set while not in output mode, so the pin's level will be 'remembered' when it is not in output 135/// set while not in output mode, so the pin's level will be 'remembered' when it is not in output
171/// mode. 136/// mode.
172pub struct FlexPin<'d, T: Pin> { 137pub struct Flex<'d, T: Pin> {
173 pub(crate) pin: T, 138 pub(crate) pin: T,
174 phantom: PhantomData<&'d mut T>, 139 phantom: PhantomData<&'d mut T>,
175} 140}
176 141
177impl<'d, T: Pin> FlexPin<'d, T> { 142impl<'d, T: Pin> Flex<'d, T> {
178 /// Wrap the pin in a `FlexPin`. 143 /// Wrap the pin in a `Flex`.
179 /// 144 ///
180 /// The pin remains disconnected. The initial output level is unspecified, but can be changed 145 /// The pin remains disconnected. The initial output level is unspecified, but can be changed
181 /// before the pin is put into output mode. 146 /// before the pin is put into output mode.
@@ -270,49 +235,12 @@ impl<'d, T: Pin> FlexPin<'d, T> {
270 } 235 }
271} 236}
272 237
273impl<'d, T: Pin> Drop for FlexPin<'d, T> { 238impl<'d, T: Pin> Drop for Flex<'d, T> {
274 fn drop(&mut self) { 239 fn drop(&mut self) {
275 self.pin.conf().reset(); 240 self.pin.conf().reset();
276 } 241 }
277} 242}
278 243
279/// Implement [`InputPin`] for [`FlexPin`];
280///
281/// If the pin is not in input mode the result is unspecified.
282impl<'d, T: Pin> InputPin for FlexPin<'d, T> {
283 type Error = Infallible;
284
285 fn is_high(&self) -> Result<bool, Self::Error> {
286 Ok(self.is_high())
287 }
288
289 fn is_low(&self) -> Result<bool, Self::Error> {
290 Ok(self.is_low())
291 }
292}
293
294impl<'d, T: Pin> OutputPin for FlexPin<'d, T> {
295 type Error = Infallible;
296
297 fn set_high(&mut self) -> Result<(), Self::Error> {
298 Ok(self.set_high())
299 }
300
301 fn set_low(&mut self) -> Result<(), Self::Error> {
302 Ok(self.set_low())
303 }
304}
305
306impl<'d, T: Pin> StatefulOutputPin for FlexPin<'d, T> {
307 fn is_set_high(&self) -> Result<bool, Self::Error> {
308 Ok(self.is_set_high())
309 }
310
311 fn is_set_low(&self) -> Result<bool, Self::Error> {
312 Ok(self.is_set_low())
313 }
314}
315
316pub(crate) mod sealed { 244pub(crate) mod sealed {
317 use super::*; 245 use super::*;
318 246
@@ -350,17 +278,13 @@ pub(crate) mod sealed {
350 /// Set the output as high. 278 /// Set the output as high.
351 #[inline] 279 #[inline]
352 fn set_high(&self) { 280 fn set_high(&self) {
353 unsafe { 281 unsafe { self.block().outset.write(|w| w.bits(1u32 << self._pin())) }
354 self.block().outset.write(|w| w.bits(1u32 << self._pin()));
355 }
356 } 282 }
357 283
358 /// Set the output as low. 284 /// Set the output as low.
359 #[inline] 285 #[inline]
360 fn set_low(&self) { 286 fn set_low(&self) {
361 unsafe { 287 unsafe { self.block().outclr.write(|w| w.bits(1u32 << self._pin())) }
362 self.block().outclr.write(|w| w.bits(1u32 << self._pin()));
363 }
364 } 288 }
365 } 289 }
366 290
@@ -495,3 +419,160 @@ macro_rules! impl_pin {
495 } 419 }
496 }; 420 };
497} 421}
422
423// ====================
424
425mod eh02 {
426 use super::*;
427
428 impl<'d, T: Pin> embedded_hal_02::digital::v2::InputPin for Input<'d, T> {
429 type Error = Infallible;
430
431 fn is_high(&self) -> Result<bool, Self::Error> {
432 Ok(self.is_high())
433 }
434
435 fn is_low(&self) -> Result<bool, Self::Error> {
436 Ok(self.is_low())
437 }
438 }
439
440 impl<'d, T: Pin> embedded_hal_02::digital::v2::OutputPin for Output<'d, T> {
441 type Error = Infallible;
442
443 fn set_high(&mut self) -> Result<(), Self::Error> {
444 Ok(self.set_high())
445 }
446
447 fn set_low(&mut self) -> Result<(), Self::Error> {
448 Ok(self.set_low())
449 }
450 }
451
452 impl<'d, T: Pin> embedded_hal_02::digital::v2::StatefulOutputPin for Output<'d, T> {
453 fn is_set_high(&self) -> Result<bool, Self::Error> {
454 Ok(self.is_set_high())
455 }
456
457 fn is_set_low(&self) -> Result<bool, Self::Error> {
458 Ok(self.is_set_low())
459 }
460 }
461
462 /// Implement [`InputPin`] for [`Flex`];
463 ///
464 /// If the pin is not in input mode the result is unspecified.
465 impl<'d, T: Pin> embedded_hal_02::digital::v2::InputPin for Flex<'d, T> {
466 type Error = Infallible;
467
468 fn is_high(&self) -> Result<bool, Self::Error> {
469 Ok(self.is_high())
470 }
471
472 fn is_low(&self) -> Result<bool, Self::Error> {
473 Ok(self.is_low())
474 }
475 }
476
477 impl<'d, T: Pin> embedded_hal_02::digital::v2::OutputPin for Flex<'d, T> {
478 type Error = Infallible;
479
480 fn set_high(&mut self) -> Result<(), Self::Error> {
481 Ok(self.set_high())
482 }
483
484 fn set_low(&mut self) -> Result<(), Self::Error> {
485 Ok(self.set_low())
486 }
487 }
488
489 impl<'d, T: Pin> embedded_hal_02::digital::v2::StatefulOutputPin for Flex<'d, T> {
490 fn is_set_high(&self) -> Result<bool, Self::Error> {
491 Ok(self.is_set_high())
492 }
493
494 fn is_set_low(&self) -> Result<bool, Self::Error> {
495 Ok(self.is_set_low())
496 }
497 }
498}
499
500#[cfg(feature = "unstable-traits")]
501mod eh1 {
502 use super::*;
503
504 impl<'d, T: Pin> embedded_hal_1::digital::ErrorType for Input<'d, T> {
505 type Error = Infallible;
506 }
507
508 impl<'d, T: Pin> embedded_hal_1::digital::blocking::InputPin for Input<'d, T> {
509 fn is_high(&self) -> Result<bool, Self::Error> {
510 Ok(self.is_high())
511 }
512
513 fn is_low(&self) -> Result<bool, Self::Error> {
514 Ok(self.is_low())
515 }
516 }
517
518 impl<'d, T: Pin> embedded_hal_1::digital::ErrorType for Output<'d, T> {
519 type Error = Infallible;
520 }
521
522 impl<'d, T: Pin> embedded_hal_1::digital::blocking::OutputPin for Output<'d, T> {
523 fn set_high(&mut self) -> Result<(), Self::Error> {
524 Ok(self.set_high())
525 }
526
527 fn set_low(&mut self) -> Result<(), Self::Error> {
528 Ok(self.set_low())
529 }
530 }
531
532 impl<'d, T: Pin> embedded_hal_1::digital::blocking::StatefulOutputPin for Output<'d, T> {
533 fn is_set_high(&self) -> Result<bool, Self::Error> {
534 Ok(self.is_set_high())
535 }
536
537 fn is_set_low(&self) -> Result<bool, Self::Error> {
538 Ok(self.is_set_low())
539 }
540 }
541
542 impl<'d, T: Pin> embedded_hal_1::digital::ErrorType for Flex<'d, T> {
543 type Error = Infallible;
544 }
545
546 /// Implement [`InputPin`] for [`Flex`];
547 ///
548 /// If the pin is not in input mode the result is unspecified.
549 impl<'d, T: Pin> embedded_hal_1::digital::blocking::InputPin for Flex<'d, T> {
550 fn is_high(&self) -> Result<bool, Self::Error> {
551 Ok(self.is_high())
552 }
553
554 fn is_low(&self) -> Result<bool, Self::Error> {
555 Ok(self.is_low())
556 }
557 }
558
559 impl<'d, T: Pin> embedded_hal_1::digital::blocking::OutputPin for Flex<'d, T> {
560 fn set_high(&mut self) -> Result<(), Self::Error> {
561 Ok(self.set_high())
562 }
563
564 fn set_low(&mut self) -> Result<(), Self::Error> {
565 Ok(self.set_low())
566 }
567 }
568
569 impl<'d, T: Pin> embedded_hal_1::digital::blocking::StatefulOutputPin for Flex<'d, T> {
570 fn is_set_high(&self) -> Result<bool, Self::Error> {
571 Ok(self.is_set_high())
572 }
573
574 fn is_set_low(&self) -> Result<bool, Self::Error> {
575 Ok(self.is_set_low())
576 }
577 }
578}
diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs
index 99dfd1ebd..a4c24058c 100644
--- a/embassy-nrf/src/gpiote.rs
+++ b/embassy-nrf/src/gpiote.rs
@@ -5,11 +5,10 @@ use core::task::{Context, Poll};
5use embassy::interrupt::{Interrupt, InterruptExt}; 5use embassy::interrupt::{Interrupt, InterruptExt};
6use embassy::waitqueue::AtomicWaker; 6use embassy::waitqueue::AtomicWaker;
7use embassy_hal_common::unsafe_impl_unborrow; 7use embassy_hal_common::unsafe_impl_unborrow;
8use embedded_hal::digital::v2::InputPin;
9use futures::future::poll_fn; 8use futures::future::poll_fn;
10 9
11use crate::gpio::sealed::Pin as _; 10use crate::gpio::sealed::Pin as _;
12use crate::gpio::{AnyPin, FlexPin, Input, Output, Pin as GpioPin}; 11use crate::gpio::{AnyPin, Flex, Input, Output, Pin as GpioPin};
13use crate::pac; 12use crate::pac;
14use crate::ppi::{Event, Task}; 13use crate::ppi::{Event, Task};
15use crate::{interrupt, peripherals}; 14use crate::{interrupt, peripherals};
@@ -216,18 +215,6 @@ impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> {
216 } 215 }
217} 216}
218 217
219impl<'d, C: Channel, T: GpioPin> InputPin for InputChannel<'d, C, T> {
220 type Error = Infallible;
221
222 fn is_high(&self) -> Result<bool, Self::Error> {
223 self.pin.is_high()
224 }
225
226 fn is_low(&self) -> Result<bool, Self::Error> {
227 self.pin.is_low()
228 }
229}
230
231/// GPIOTE channel driver in output mode 218/// GPIOTE channel driver in output mode
232pub struct OutputChannel<'d, C: Channel, T: GpioPin> { 219pub struct OutputChannel<'d, C: Channel, T: GpioPin> {
233 ch: C, 220 ch: C,
@@ -342,78 +329,60 @@ impl<'a> Future for PortInputFuture<'a> {
342 } 329 }
343} 330}
344 331
345impl<'d, T: GpioPin> embassy::traits::gpio::WaitForHigh for Input<'d, T> { 332impl<'d, T: GpioPin> Input<'d, T> {
346 type Future<'a> 333 pub async fn wait_for_high(&mut self) {
347 where 334 self.pin.wait_for_high().await
348 Self: 'a,
349 = impl Future<Output = ()> + Unpin + 'a;
350
351 fn wait_for_high<'a>(&'a mut self) -> Self::Future<'a> {
352 self.pin.wait_for_high()
353 } 335 }
354}
355 336
356impl<'d, T: GpioPin> embassy::traits::gpio::WaitForLow for Input<'d, T> { 337 pub async fn wait_for_low(&mut self) {
357 type Future<'a> 338 self.pin.wait_for_low().await
358 where 339 }
359 Self: 'a,
360 = impl Future<Output = ()> + Unpin + 'a;
361 340
362 fn wait_for_low<'a>(&'a mut self) -> Self::Future<'a> { 341 pub async fn wait_for_rising_edge(&mut self) {
363 self.pin.wait_for_low() 342 self.pin.wait_for_rising_edge().await
364 } 343 }
365}
366 344
367impl<'d, T: GpioPin> embassy::traits::gpio::WaitForAnyEdge for Input<'d, T> { 345 pub async fn wait_for_falling_edge(&mut self) {
368 type Future<'a> 346 self.pin.wait_for_falling_edge().await
369 where 347 }
370 Self: 'a,
371 = impl Future<Output = ()> + Unpin + 'a;
372 348
373 fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> { 349 pub async fn wait_for_any_edge(&mut self) {
374 self.pin.wait_for_any_edge() 350 self.pin.wait_for_any_edge().await
375 } 351 }
376} 352}
377 353
378impl<'d, T: GpioPin> embassy::traits::gpio::WaitForHigh for FlexPin<'d, T> { 354impl<'d, T: GpioPin> Flex<'d, T> {
379 type Future<'a> 355 pub async fn wait_for_high(&mut self) {
380 where
381 Self: 'a,
382 = impl Future<Output = ()> + Unpin + 'a;
383
384 fn wait_for_high<'a>(&'a mut self) -> Self::Future<'a> {
385 self.pin.conf().modify(|_, w| w.sense().high()); 356 self.pin.conf().modify(|_, w| w.sense().high());
386 357
387 PortInputFuture { 358 PortInputFuture {
388 pin_port: self.pin.pin_port(), 359 pin_port: self.pin.pin_port(),
389 phantom: PhantomData, 360 phantom: PhantomData,
390 } 361 }
362 .await
391 } 363 }
392}
393 364
394impl<'d, T: GpioPin> embassy::traits::gpio::WaitForLow for FlexPin<'d, T> { 365 pub async fn wait_for_low(&mut self) {
395 type Future<'a>
396 where
397 Self: 'a,
398 = impl Future<Output = ()> + Unpin + 'a;
399
400 fn wait_for_low<'a>(&'a mut self) -> Self::Future<'a> {
401 self.pin.conf().modify(|_, w| w.sense().low()); 366 self.pin.conf().modify(|_, w| w.sense().low());
402 367
403 PortInputFuture { 368 PortInputFuture {
404 pin_port: self.pin.pin_port(), 369 pin_port: self.pin.pin_port(),
405 phantom: PhantomData, 370 phantom: PhantomData,
406 } 371 }
372 .await
373 }
374
375 pub async fn wait_for_rising_edge(&mut self) {
376 self.wait_for_low().await;
377 self.wait_for_high().await;
407 } 378 }
408}
409 379
410impl<'d, T: GpioPin> embassy::traits::gpio::WaitForAnyEdge for FlexPin<'d, T> { 380 pub async fn wait_for_falling_edge(&mut self) {
411 type Future<'a> 381 self.wait_for_high().await;
412 where 382 self.wait_for_low().await;
413 Self: 'a, 383 }
414 = impl Future<Output = ()> + Unpin + 'a;
415 384
416 fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> { 385 pub async fn wait_for_any_edge(&mut self) {
417 if self.is_high() { 386 if self.is_high() {
418 self.pin.conf().modify(|_, w| w.sense().low()); 387 self.pin.conf().modify(|_, w| w.sense().low());
419 } else { 388 } else {
@@ -423,6 +392,7 @@ impl<'d, T: GpioPin> embassy::traits::gpio::WaitForAnyEdge for FlexPin<'d, T> {
423 pin_port: self.pin.pin_port(), 392 pin_port: self.pin.pin_port(),
424 phantom: PhantomData, 393 phantom: PhantomData,
425 } 394 }
395 .await
426 } 396 }
427} 397}
428 398
@@ -471,3 +441,137 @@ impl_channel!(GPIOTE_CH4, 4);
471impl_channel!(GPIOTE_CH5, 5); 441impl_channel!(GPIOTE_CH5, 5);
472impl_channel!(GPIOTE_CH6, 6); 442impl_channel!(GPIOTE_CH6, 6);
473impl_channel!(GPIOTE_CH7, 7); 443impl_channel!(GPIOTE_CH7, 7);
444
445// ====================
446
447mod eh02 {
448 use super::*;
449
450 impl<'d, C: Channel, T: GpioPin> embedded_hal_02::digital::v2::InputPin for InputChannel<'d, C, T> {
451 type Error = Infallible;
452
453 fn is_high(&self) -> Result<bool, Self::Error> {
454 self.pin.is_high()
455 }
456
457 fn is_low(&self) -> Result<bool, Self::Error> {
458 self.pin.is_low()
459 }
460 }
461}
462
463#[cfg(feature = "unstable-traits")]
464mod eh1 {
465 use super::*;
466 use futures::FutureExt;
467
468 impl<'d, C: Channel, T: GpioPin> embedded_hal_1::digital::ErrorType for InputChannel<'d, C, T> {
469 type Error = Infallible;
470 }
471
472 impl<'d, C: Channel, T: GpioPin> embedded_hal_1::digital::blocking::InputPin
473 for InputChannel<'d, C, T>
474 {
475 fn is_high(&self) -> Result<bool, Self::Error> {
476 self.pin.is_high()
477 }
478
479 fn is_low(&self) -> Result<bool, Self::Error> {
480 self.pin.is_low()
481 }
482 }
483
484 impl<'d, T: GpioPin> embedded_hal_async::digital::Wait for Input<'d, T> {
485 type WaitForHighFuture<'a>
486 where
487 Self: 'a,
488 = impl Future<Output = Result<(), Self::Error>> + 'a;
489
490 fn wait_for_high<'a>(&'a mut self) -> Self::WaitForHighFuture<'a> {
491 self.wait_for_high().map(Ok)
492 }
493
494 type WaitForLowFuture<'a>
495 where
496 Self: 'a,
497 = impl Future<Output = Result<(), Self::Error>> + 'a;
498
499 fn wait_for_low<'a>(&'a mut self) -> Self::WaitForLowFuture<'a> {
500 self.wait_for_low().map(Ok)
501 }
502
503 type WaitForRisingEdgeFuture<'a>
504 where
505 Self: 'a,
506 = impl Future<Output = Result<(), Self::Error>> + 'a;
507
508 fn wait_for_rising_edge<'a>(&'a mut self) -> Self::WaitForRisingEdgeFuture<'a> {
509 self.wait_for_rising_edge().map(Ok)
510 }
511
512 type WaitForFallingEdgeFuture<'a>
513 where
514 Self: 'a,
515 = impl Future<Output = Result<(), Self::Error>> + 'a;
516
517 fn wait_for_falling_edge<'a>(&'a mut self) -> Self::WaitForFallingEdgeFuture<'a> {
518 self.wait_for_falling_edge().map(Ok)
519 }
520
521 type WaitForAnyEdgeFuture<'a>
522 where
523 Self: 'a,
524 = impl Future<Output = Result<(), Self::Error>> + 'a;
525
526 fn wait_for_any_edge<'a>(&'a mut self) -> Self::WaitForAnyEdgeFuture<'a> {
527 self.wait_for_any_edge().map(Ok)
528 }
529 }
530
531 impl<'d, T: GpioPin> embedded_hal_async::digital::Wait for Flex<'d, T> {
532 type WaitForHighFuture<'a>
533 where
534 Self: 'a,
535 = impl Future<Output = Result<(), Self::Error>> + 'a;
536
537 fn wait_for_high<'a>(&'a mut self) -> Self::WaitForHighFuture<'a> {
538 self.wait_for_high().map(Ok)
539 }
540
541 type WaitForLowFuture<'a>
542 where
543 Self: 'a,
544 = impl Future<Output = Result<(), Self::Error>> + 'a;
545
546 fn wait_for_low<'a>(&'a mut self) -> Self::WaitForLowFuture<'a> {
547 self.wait_for_low().map(Ok)
548 }
549
550 type WaitForRisingEdgeFuture<'a>
551 where
552 Self: 'a,
553 = impl Future<Output = Result<(), Self::Error>> + 'a;
554
555 fn wait_for_rising_edge<'a>(&'a mut self) -> Self::WaitForRisingEdgeFuture<'a> {
556 self.wait_for_rising_edge().map(Ok)
557 }
558
559 type WaitForFallingEdgeFuture<'a>
560 where
561 Self: 'a,
562 = impl Future<Output = Result<(), Self::Error>> + 'a;
563
564 fn wait_for_falling_edge<'a>(&'a mut self) -> Self::WaitForFallingEdgeFuture<'a> {
565 self.wait_for_falling_edge().map(Ok)
566 }
567
568 type WaitForAnyEdgeFuture<'a>
569 where
570 Self: 'a,
571 = impl Future<Output = Result<(), Self::Error>> + 'a;
572
573 fn wait_for_any_edge<'a>(&'a mut self) -> Self::WaitForAnyEdgeFuture<'a> {
574 self.wait_for_any_edge().map(Ok)
575 }
576 }
577}
diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs
index 6afba4931..89262ac05 100644
--- a/embassy-nrf/src/qspi.rs
+++ b/embassy-nrf/src/qspi.rs
@@ -1,11 +1,9 @@
1#![macro_use] 1#![macro_use]
2 2
3use core::future::Future;
4use core::marker::PhantomData; 3use core::marker::PhantomData;
5use core::ptr; 4use core::ptr;
6use core::task::Poll; 5use core::task::Poll;
7use embassy::interrupt::{Interrupt, InterruptExt}; 6use embassy::interrupt::{Interrupt, InterruptExt};
8use embassy::traits::flash::{Error, Flash};
9use embassy::util::Unborrow; 7use embassy::util::Unborrow;
10use embassy_hal_common::drop::DropBomb; 8use embassy_hal_common::drop::DropBomb;
11use embassy_hal_common::unborrow; 9use embassy_hal_common::unborrow;
@@ -58,6 +56,13 @@ impl Default for Config {
58 } 56 }
59} 57}
60 58
59#[derive(Debug, Copy, Clone, Eq, PartialEq)]
60#[cfg_attr(feature = "defmt", derive(defmt::Format))]
61#[non_exhaustive]
62pub enum Error {
63 // TODO add "not in data memory" error and check for it
64}
65
61pub struct Qspi<'d, T: Instance> { 66pub struct Qspi<'d, T: Instance> {
62 dpm_enabled: bool, 67 dpm_enabled: bool,
63 phantom: PhantomData<&'d mut T>, 68 phantom: PhantomData<&'d mut T>,
@@ -240,6 +245,87 @@ impl<'d, T: Instance> Qspi<'d, T> {
240 }) 245 })
241 .await 246 .await
242 } 247 }
248
249 pub async fn read(&mut self, address: usize, data: &mut [u8]) -> Result<(), Error> {
250 let bomb = DropBomb::new();
251
252 assert_eq!(data.as_ptr() as u32 % 4, 0);
253 assert_eq!(data.len() as u32 % 4, 0);
254 assert_eq!(address as u32 % 4, 0);
255
256 let r = T::regs();
257
258 r.read
259 .src
260 .write(|w| unsafe { w.src().bits(address as u32) });
261 r.read
262 .dst
263 .write(|w| unsafe { w.dst().bits(data.as_ptr() as u32) });
264 r.read
265 .cnt
266 .write(|w| unsafe { w.cnt().bits(data.len() as u32) });
267
268 r.events_ready.reset();
269 r.intenset.write(|w| w.ready().set());
270 r.tasks_readstart.write(|w| w.tasks_readstart().bit(true));
271
272 self.wait_ready().await;
273
274 bomb.defuse();
275
276 Ok(())
277 }
278
279 pub async fn write(&mut self, address: usize, data: &[u8]) -> Result<(), Error> {
280 let bomb = DropBomb::new();
281
282 assert_eq!(data.as_ptr() as u32 % 4, 0);
283 assert_eq!(data.len() as u32 % 4, 0);
284 assert_eq!(address as u32 % 4, 0);
285
286 let r = T::regs();
287 r.write
288 .src
289 .write(|w| unsafe { w.src().bits(data.as_ptr() as u32) });
290 r.write
291 .dst
292 .write(|w| unsafe { w.dst().bits(address as u32) });
293 r.write
294 .cnt
295 .write(|w| unsafe { w.cnt().bits(data.len() as u32) });
296
297 r.events_ready.reset();
298 r.intenset.write(|w| w.ready().set());
299 r.tasks_writestart.write(|w| w.tasks_writestart().bit(true));
300
301 self.wait_ready().await;
302
303 bomb.defuse();
304
305 Ok(())
306 }
307
308 pub async fn erase(&mut self, address: usize) -> Result<(), Error> {
309 let bomb = DropBomb::new();
310
311 assert_eq!(address as u32 % 4096, 0);
312
313 let r = T::regs();
314 r.erase
315 .ptr
316 .write(|w| unsafe { w.ptr().bits(address as u32) });
317 r.erase.len.write(|w| w.len()._4kb());
318
319 r.events_ready.reset();
320 r.intenset.write(|w| w.ready().set());
321 r.tasks_erasestart.write(|w| w.tasks_erasestart().bit(true));
322
323 self.wait_ready().await;
324
325 bomb.defuse();
326
327 Ok(())
328 }
243} 329}
244 330
245impl<'d, T: Instance> Drop for Qspi<'d, T> { 331impl<'d, T: Instance> Drop for Qspi<'d, T> {
@@ -285,124 +371,6 @@ impl<'d, T: Instance> Drop for Qspi<'d, T> {
285 } 371 }
286} 372}
287 373
288impl<'d, T: Instance> Flash for Qspi<'d, T> {
289 type ReadFuture<'a>
290 where
291 Self: 'a,
292 = impl Future<Output = Result<(), Error>> + 'a;
293 type WriteFuture<'a>
294 where
295 Self: 'a,
296 = impl Future<Output = Result<(), Error>> + 'a;
297 type ErasePageFuture<'a>
298 where
299 Self: 'a,
300 = impl Future<Output = Result<(), Error>> + 'a;
301
302 fn read<'a>(&'a mut self, address: usize, data: &'a mut [u8]) -> Self::ReadFuture<'a> {
303 async move {
304 let bomb = DropBomb::new();
305
306 assert_eq!(data.as_ptr() as u32 % 4, 0);
307 assert_eq!(data.len() as u32 % 4, 0);
308 assert_eq!(address as u32 % 4, 0);
309
310 let r = T::regs();
311
312 r.read
313 .src
314 .write(|w| unsafe { w.src().bits(address as u32) });
315 r.read
316 .dst
317 .write(|w| unsafe { w.dst().bits(data.as_ptr() as u32) });
318 r.read
319 .cnt
320 .write(|w| unsafe { w.cnt().bits(data.len() as u32) });
321
322 r.events_ready.reset();
323 r.intenset.write(|w| w.ready().set());
324 r.tasks_readstart.write(|w| w.tasks_readstart().bit(true));
325
326 self.wait_ready().await;
327
328 bomb.defuse();
329
330 Ok(())
331 }
332 }
333
334 fn write<'a>(&'a mut self, address: usize, data: &'a [u8]) -> Self::WriteFuture<'a> {
335 async move {
336 let bomb = DropBomb::new();
337
338 assert_eq!(data.as_ptr() as u32 % 4, 0);
339 assert_eq!(data.len() as u32 % 4, 0);
340 assert_eq!(address as u32 % 4, 0);
341
342 let r = T::regs();
343 r.write
344 .src
345 .write(|w| unsafe { w.src().bits(data.as_ptr() as u32) });
346 r.write
347 .dst
348 .write(|w| unsafe { w.dst().bits(address as u32) });
349 r.write
350 .cnt
351 .write(|w| unsafe { w.cnt().bits(data.len() as u32) });
352
353 r.events_ready.reset();
354 r.intenset.write(|w| w.ready().set());
355 r.tasks_writestart.write(|w| w.tasks_writestart().bit(true));
356
357 self.wait_ready().await;
358
359 bomb.defuse();
360
361 Ok(())
362 }
363 }
364
365 fn erase<'a>(&'a mut self, address: usize) -> Self::ErasePageFuture<'a> {
366 async move {
367 let bomb = DropBomb::new();
368
369 assert_eq!(address as u32 % 4096, 0);
370
371 let r = T::regs();
372 r.erase
373 .ptr
374 .write(|w| unsafe { w.ptr().bits(address as u32) });
375 r.erase.len.write(|w| w.len()._4kb());
376
377 r.events_ready.reset();
378 r.intenset.write(|w| w.ready().set());
379 r.tasks_erasestart.write(|w| w.tasks_erasestart().bit(true));
380
381 self.wait_ready().await;
382
383 bomb.defuse();
384
385 Ok(())
386 }
387 }
388
389 fn size(&self) -> usize {
390 256 * 4096 // TODO
391 }
392
393 fn read_size(&self) -> usize {
394 4 // TODO
395 }
396
397 fn write_size(&self) -> usize {
398 4 // TODO
399 }
400
401 fn erase_size(&self) -> usize {
402 4096 // TODO
403 }
404}
405
406pub(crate) mod sealed { 374pub(crate) mod sealed {
407 use embassy::waitqueue::AtomicWaker; 375 use embassy::waitqueue::AtomicWaker;
408 376
diff --git a/embassy-nrf/src/rng.rs b/embassy-nrf/src/rng.rs
index 6b36cbb88..98833c52b 100644
--- a/embassy-nrf/src/rng.rs
+++ b/embassy-nrf/src/rng.rs
@@ -1,5 +1,3 @@
1use core::convert::Infallible;
2use core::future::Future;
3use core::marker::PhantomData; 1use core::marker::PhantomData;
4use core::ptr; 2use core::ptr;
5use core::sync::atomic::AtomicPtr; 3use core::sync::atomic::AtomicPtr;
@@ -7,13 +5,11 @@ use core::sync::atomic::Ordering;
7use core::task::Poll; 5use core::task::Poll;
8 6
9use embassy::interrupt::InterruptExt; 7use embassy::interrupt::InterruptExt;
10use embassy::traits;
11use embassy::util::Unborrow; 8use embassy::util::Unborrow;
12use embassy::waitqueue::AtomicWaker; 9use embassy::waitqueue::AtomicWaker;
13use embassy_hal_common::drop::OnDrop; 10use embassy_hal_common::drop::OnDrop;
14use embassy_hal_common::unborrow; 11use embassy_hal_common::unborrow;
15use futures::future::poll_fn; 12use futures::future::poll_fn;
16use rand_core::RngCore;
17 13
18use crate::interrupt; 14use crate::interrupt;
19use crate::pac; 15use crate::pac;
@@ -39,7 +35,7 @@ struct State {
39 35
40/// A wrapper around an nRF RNG peripheral. 36/// A wrapper around an nRF RNG peripheral.
41/// 37///
42/// It has a non-blocking API, through `embassy::traits::Rng`, and a blocking api through `rand`. 38/// It has a non-blocking API, and a blocking api through `rand`.
43pub struct Rng<'d> { 39pub struct Rng<'d> {
44 irq: interrupt::RNG, 40 irq: interrupt::RNG,
45 phantom: PhantomData<(&'d mut RNG, &'d mut interrupt::RNG)>, 41 phantom: PhantomData<(&'d mut RNG, &'d mut interrupt::RNG)>,
@@ -146,72 +142,51 @@ impl<'d> Rng<'d> {
146 pub fn bias_correction(&self, enable: bool) { 142 pub fn bias_correction(&self, enable: bool) {
147 RNG::regs().config.write(|w| w.dercen().bit(enable)) 143 RNG::regs().config.write(|w| w.dercen().bit(enable))
148 } 144 }
149}
150
151impl<'d> Drop for Rng<'d> {
152 fn drop(&mut self) {
153 self.irq.disable()
154 }
155}
156
157impl<'d> traits::rng::Rng for Rng<'d> {
158 type Error = Infallible;
159 145
160 type RngFuture<'a> 146 pub async fn fill_bytes(&mut self, dest: &mut [u8]) {
161 where 147 if dest.len() == 0 {
162 'd: 'a, 148 return; // Nothing to fill
163 = impl Future<Output = Result<(), Self::Error>> + 'a; 149 }
164
165 fn fill_bytes<'a>(&'a mut self, dest: &'a mut [u8]) -> Self::RngFuture<'a> {
166 async move {
167 if dest.len() == 0 {
168 return Ok(()); // Nothing to fill
169 }
170
171 let range = dest.as_mut_ptr_range();
172 // Even if we've preempted the interrupt, it can't preempt us again,
173 // so we don't need to worry about the order we write these in.
174 STATE.ptr.store(range.start, Ordering::Relaxed);
175 STATE.end.store(range.end, Ordering::Relaxed);
176 150
177 self.enable_irq(); 151 let range = dest.as_mut_ptr_range();
178 self.start(); 152 // Even if we've preempted the interrupt, it can't preempt us again,
153 // so we don't need to worry about the order we write these in.
154 STATE.ptr.store(range.start, Ordering::Relaxed);
155 STATE.end.store(range.end, Ordering::Relaxed);
179 156
180 let on_drop = OnDrop::new(|| { 157 self.enable_irq();
181 self.stop(); 158 self.start();
182 self.disable_irq();
183 159
184 // The interrupt is now disabled and can't preempt us anymore, so the order doesn't matter here. 160 let on_drop = OnDrop::new(|| {
185 STATE.ptr.store(ptr::null_mut(), Ordering::Relaxed); 161 self.stop();
186 STATE.end.store(ptr::null_mut(), Ordering::Relaxed); 162 self.disable_irq();
187 });
188 163
189 poll_fn(|cx| { 164 // The interrupt is now disabled and can't preempt us anymore, so the order doesn't matter here.
190 STATE.waker.register(cx.waker()); 165 STATE.ptr.store(ptr::null_mut(), Ordering::Relaxed);
166 STATE.end.store(ptr::null_mut(), Ordering::Relaxed);
167 });
191 168
192 // The interrupt will never modify `end`, so load it first and then get the most up-to-date `ptr`. 169 poll_fn(|cx| {
193 let end = STATE.end.load(Ordering::Relaxed); 170 STATE.waker.register(cx.waker());
194 let ptr = STATE.ptr.load(Ordering::Relaxed);
195 171
196 if ptr == end { 172 // The interrupt will never modify `end`, so load it first and then get the most up-to-date `ptr`.
197 // We're done. 173 let end = STATE.end.load(Ordering::Relaxed);
198 Poll::Ready(()) 174 let ptr = STATE.ptr.load(Ordering::Relaxed);
199 } else {
200 Poll::Pending
201 }
202 })
203 .await;
204 175
205 // Trigger the teardown 176 if ptr == end {
206 drop(on_drop); 177 // We're done.
178 Poll::Ready(())
179 } else {
180 Poll::Pending
181 }
182 })
183 .await;
207 184
208 Ok(()) 185 // Trigger the teardown
209 } 186 drop(on_drop);
210 } 187 }
211}
212 188
213impl<'d> RngCore for Rng<'d> { 189 pub fn blocking_fill_bytes(&mut self, dest: &mut [u8]) {
214 fn fill_bytes(&mut self, dest: &mut [u8]) {
215 self.start(); 190 self.start();
216 191
217 for byte in dest.iter_mut() { 192 for byte in dest.iter_mut() {
@@ -223,24 +198,36 @@ impl<'d> RngCore for Rng<'d> {
223 198
224 self.stop(); 199 self.stop();
225 } 200 }
201}
202
203impl<'d> Drop for Rng<'d> {
204 fn drop(&mut self) {
205 self.irq.disable()
206 }
207}
208
209impl<'d> rand_core::RngCore for Rng<'d> {
210 fn fill_bytes(&mut self, dest: &mut [u8]) {
211 self.blocking_fill_bytes(dest);
212 }
226 213
227 fn next_u32(&mut self) -> u32 { 214 fn next_u32(&mut self) -> u32 {
228 let mut bytes = [0; 4]; 215 let mut bytes = [0; 4];
229 self.fill_bytes(&mut bytes); 216 self.blocking_fill_bytes(&mut bytes);
230 // We don't care about the endianness, so just use the native one. 217 // We don't care about the endianness, so just use the native one.
231 u32::from_ne_bytes(bytes) 218 u32::from_ne_bytes(bytes)
232 } 219 }
233 220
234 fn next_u64(&mut self) -> u64 { 221 fn next_u64(&mut self) -> u64 {
235 let mut bytes = [0; 8]; 222 let mut bytes = [0; 8];
236 self.fill_bytes(&mut bytes); 223 self.blocking_fill_bytes(&mut bytes);
237 u64::from_ne_bytes(bytes) 224 u64::from_ne_bytes(bytes)
238 } 225 }
239 226
240 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> { 227 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
241 self.fill_bytes(dest); 228 self.blocking_fill_bytes(dest);
242 Ok(()) 229 Ok(())
243 } 230 }
244} 231}
245 232
246// TODO: Should `Rng` implement `CryptoRng`? It's 'suitable for cryptographic purposes' according to the specification. 233impl<'d> rand_core::CryptoRng for Rng<'d> {}
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs
index bc5823f6a..cd43b26e6 100644
--- a/embassy-nrf/src/spim.rs
+++ b/embassy-nrf/src/spim.rs
@@ -1,23 +1,21 @@
1#![macro_use] 1#![macro_use]
2 2
3use core::future::Future;
4use core::marker::PhantomData; 3use core::marker::PhantomData;
5use core::sync::atomic::{compiler_fence, Ordering}; 4use core::sync::atomic::{compiler_fence, Ordering};
6use core::task::Poll; 5use core::task::Poll;
7use embassy::interrupt::InterruptExt; 6use embassy::interrupt::InterruptExt;
8use embassy::traits;
9use embassy::util::Unborrow; 7use embassy::util::Unborrow;
10use embassy_hal_common::unborrow; 8use embassy_hal_common::unborrow;
11use futures::future::poll_fn; 9use futures::future::poll_fn;
12use traits::spi::{FullDuplex, Read, Spi, Write};
13 10
14use crate::gpio; 11use crate::gpio;
15use crate::gpio::sealed::Pin as _; 12use crate::gpio::sealed::Pin as _;
16use crate::gpio::{OptionalPin, Pin as GpioPin}; 13use crate::gpio::{OptionalPin, Pin as GpioPin};
17use crate::interrupt::Interrupt; 14use crate::interrupt::Interrupt;
15use crate::util::{slice_ptr_parts, slice_ptr_parts_mut};
18use crate::{pac, util::slice_in_ram_or}; 16use crate::{pac, util::slice_in_ram_or};
19 17
20pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; 18pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
21pub use pac::spim0::frequency::FREQUENCY_A as Frequency; 19pub use pac::spim0::frequency::FREQUENCY_A as Frequency;
22 20
23#[derive(Debug, Clone, Copy, PartialEq, Eq)] 21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -132,9 +130,7 @@ impl<'d, T: Instance> Spim<'d, T> {
132 130
133 // Set over-read character 131 // Set over-read character
134 let orc = config.orc; 132 let orc = config.orc;
135 r.orc.write(|w| 133 r.orc.write(|w| unsafe { w.orc().bits(orc) });
136 // The ORC field is 8 bits long, so any u8 is a valid value to write.
137 unsafe { w.orc().bits(orc) });
138 134
139 // Disable all events interrupts 135 // Disable all events interrupts
140 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); 136 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
@@ -157,210 +153,114 @@ impl<'d, T: Instance> Spim<'d, T> {
157 r.intenclr.write(|w| w.end().clear()); 153 r.intenclr.write(|w| w.end().clear());
158 } 154 }
159 } 155 }
160}
161 156
162impl<'d, T: Instance> Drop for Spim<'d, T> { 157 fn prepare(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
163 fn drop(&mut self) { 158 slice_in_ram_or(tx, Error::DMABufferNotInDataMemory)?;
164 trace!("spim drop"); 159 // NOTE: RAM slice check for rx is not necessary, as a mutable
160 // slice can only be built from data located in RAM.
165 161
166 // TODO check for abort, wait for xxxstopped 162 compiler_fence(Ordering::SeqCst);
167 163
168 // disable!
169 let r = T::regs(); 164 let r = T::regs();
170 r.enable.write(|w| w.enable().disabled());
171 165
172 gpio::deconfigure_pin(r.psel.sck.read().bits()); 166 // Set up the DMA write.
173 gpio::deconfigure_pin(r.psel.miso.read().bits()); 167 let (ptr, len) = slice_ptr_parts(tx);
174 gpio::deconfigure_pin(r.psel.mosi.read().bits()); 168 r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) });
169 r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
175 170
176 trace!("spim drop: done"); 171 // Set up the DMA read.
177 } 172 let (ptr, len) = slice_ptr_parts_mut(rx);
178} 173 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) });
174 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
179 175
180impl<'d, T: Instance> Spi<u8> for Spim<'d, T> { 176 // Reset and enable the event
181 type Error = Error; 177 r.events_end.reset();
182} 178 r.intenset.write(|w| w.end().set());
183 179
184impl<'d, T: Instance> Read<u8> for Spim<'d, T> { 180 // Start SPI transaction.
185 type ReadFuture<'a> 181 r.tasks_start.write(|w| unsafe { w.bits(1) });
186 where
187 Self: 'a,
188 = impl Future<Output = Result<(), Self::Error>> + 'a;
189 182
190 fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> { 183 Ok(())
191 self.read_write(data, &[])
192 } 184 }
193}
194 185
195impl<'d, T: Instance> Write<u8> for Spim<'d, T> { 186 fn blocking_inner(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
196 type WriteFuture<'a> 187 self.prepare(rx, tx)?;
197 where
198 Self: 'a,
199 = impl Future<Output = Result<(), Self::Error>> + 'a;
200
201 fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> {
202 self.read_write(&mut [], data)
203 }
204}
205 188
206impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> { 189 // Wait for 'end' event.
207 type WriteReadFuture<'a> 190 while T::regs().events_end.read().bits() == 0 {}
208 where
209 Self: 'a,
210 = impl Future<Output = Result<(), Self::Error>> + 'a;
211
212 fn read_write<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Self::WriteReadFuture<'a> {
213 async move {
214 slice_in_ram_or(tx, Error::DMABufferNotInDataMemory)?;
215 // NOTE: RAM slice check for rx is not necessary, as a mutable
216 // slice can only be built from data located in RAM.
217
218 // Conservative compiler fence to prevent optimizations that do not
219 // take in to account actions by DMA. The fence has been placed here,
220 // before any DMA action has started.
221 compiler_fence(Ordering::SeqCst);
222
223 let r = T::regs();
224 let s = T::state();
225
226 // Set up the DMA write.
227 r.txd
228 .ptr
229 .write(|w| unsafe { w.ptr().bits(tx.as_ptr() as u32) });
230 r.txd
231 .maxcnt
232 .write(|w| unsafe { w.maxcnt().bits(tx.len() as _) });
233
234 // Set up the DMA read.
235 r.rxd
236 .ptr
237 .write(|w| unsafe { w.ptr().bits(rx.as_mut_ptr() as u32) });
238 r.rxd
239 .maxcnt
240 .write(|w| unsafe { w.maxcnt().bits(rx.len() as _) });
241
242 // Reset and enable the event
243 r.events_end.reset();
244 r.intenset.write(|w| w.end().set());
245
246 // Start SPI transaction.
247 r.tasks_start.write(|w| unsafe { w.bits(1) });
248
249 // Conservative compiler fence to prevent optimizations that do not
250 // take in to account actions by DMA. The fence has been placed here,
251 // after all possible DMA actions have completed.
252 compiler_fence(Ordering::SeqCst);
253
254 // Wait for 'end' event.
255 poll_fn(|cx| {
256 s.end_waker.register(cx.waker());
257 if r.events_end.read().bits() != 0 {
258 return Poll::Ready(());
259 }
260 191
261 Poll::Pending 192 compiler_fence(Ordering::SeqCst);
262 })
263 .await;
264 193
265 Ok(()) 194 Ok(())
266 }
267 } 195 }
268}
269 196
270// Blocking functions are provided by implementing `embedded_hal` traits. 197 async fn async_inner(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
271// 198 self.prepare(rx, tx)?;
272// Code could be shared between traits to reduce code size.
273impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spim<'d, T> {
274 type Error = Error;
275 fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
276 slice_in_ram_or(words, Error::DMABufferNotInDataMemory)?;
277
278 // Conservative compiler fence to prevent optimizations that do not
279 // take in to account actions by DMA. The fence has been placed here,
280 // before any DMA action has started.
281 compiler_fence(Ordering::SeqCst);
282 199
283 let r = T::regs(); 200 // Wait for 'end' event.
201 poll_fn(|cx| {
202 T::state().end_waker.register(cx.waker());
203 if T::regs().events_end.read().bits() != 0 {
204 return Poll::Ready(());
205 }
284 206
285 // Set up the DMA write. 207 Poll::Pending
286 r.txd 208 })
287 .ptr 209 .await;
288 .write(|w| unsafe { w.ptr().bits(words.as_ptr() as u32) });
289 r.txd
290 .maxcnt
291 .write(|w| unsafe { w.maxcnt().bits(words.len() as _) });
292 210
293 // Set up the DMA read. 211 compiler_fence(Ordering::SeqCst);
294 r.rxd
295 .ptr
296 .write(|w| unsafe { w.ptr().bits(words.as_mut_ptr() as u32) });
297 r.rxd
298 .maxcnt
299 .write(|w| unsafe { w.maxcnt().bits(words.len() as _) });
300
301 // Disable the end event since we are busy-polling.
302 r.events_end.reset();
303 212
304 // Start SPI transaction. 213 Ok(())
305 r.tasks_start.write(|w| unsafe { w.bits(1) }); 214 }
306 215
307 // Wait for 'end' event. 216 pub fn blocking_read(&mut self, data: &mut [u8]) -> Result<(), Error> {
308 while r.events_end.read().bits() == 0 {} 217 self.blocking_inner(data, &[])
218 }
309 219
310 // Conservative compiler fence to prevent optimizations that do not 220 pub fn blocking_transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
311 // take in to account actions by DMA. The fence has been placed here, 221 self.blocking_inner(read, write)
312 // after all possible DMA actions have completed. 222 }
313 compiler_fence(Ordering::SeqCst);
314 223
315 Ok(words) 224 pub fn blocking_transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Error> {
225 self.blocking_inner(data, data)
316 } 226 }
317}
318 227
319impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spim<'d, T> { 228 pub fn blocking_write(&mut self, data: &[u8]) -> Result<(), Error> {
320 type Error = Error; 229 self.blocking_inner(&mut [], data)
230 }
321 231
322 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { 232 pub async fn read(&mut self, data: &mut [u8]) -> Result<(), Error> {
323 slice_in_ram_or(words, Error::DMABufferNotInDataMemory)?; 233 self.async_inner(data, &[]).await
324 let recv: &mut [u8] = &mut []; 234 }
325 235
326 // Conservative compiler fence to prevent optimizations that do not 236 pub async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
327 // take in to account actions by DMA. The fence has been placed here, 237 self.async_inner(read, write).await
328 // before any DMA action has started. 238 }
329 compiler_fence(Ordering::SeqCst);
330 239
331 let r = T::regs(); 240 pub async fn transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Error> {
241 self.async_inner(data, data).await
242 }
332 243
333 // Set up the DMA write. 244 pub async fn write(&mut self, data: &[u8]) -> Result<(), Error> {
334 r.txd 245 self.async_inner(&mut [], data).await
335 .ptr 246 }
336 .write(|w| unsafe { w.ptr().bits(words.as_ptr() as u32) }); 247}
337 r.txd
338 .maxcnt
339 .write(|w| unsafe { w.maxcnt().bits(words.len() as _) });
340 248
341 // Set up the DMA read. 249impl<'d, T: Instance> Drop for Spim<'d, T> {
342 r.rxd 250 fn drop(&mut self) {
343 .ptr 251 trace!("spim drop");
344 .write(|w| unsafe { w.ptr().bits(recv.as_mut_ptr() as u32) });
345 r.rxd
346 .maxcnt
347 .write(|w| unsafe { w.maxcnt().bits(recv.len() as _) });
348
349 // Disable the end event since we are busy-polling.
350 r.events_end.reset();
351 252
352 // Start SPI transaction. 253 // TODO check for abort, wait for xxxstopped
353 r.tasks_start.write(|w| unsafe { w.bits(1) });
354 254
355 // Wait for 'end' event. 255 // disable!
356 while r.events_end.read().bits() == 0 {} 256 let r = T::regs();
257 r.enable.write(|w| w.enable().disabled());
357 258
358 // Conservative compiler fence to prevent optimizations that do not 259 gpio::deconfigure_pin(r.psel.sck.read().bits());
359 // take in to account actions by DMA. The fence has been placed here, 260 gpio::deconfigure_pin(r.psel.miso.read().bits());
360 // after all possible DMA actions have completed. 261 gpio::deconfigure_pin(r.psel.mosi.read().bits());
361 compiler_fence(Ordering::SeqCst);
362 262
363 Ok(()) 263 trace!("spim drop: done");
364 } 264 }
365} 265}
366 266
@@ -407,3 +307,209 @@ macro_rules! impl_spim {
407 } 307 }
408 }; 308 };
409} 309}
310
311// ====================
312
313mod eh02 {
314 use super::*;
315
316 impl<'d, T: Instance> embedded_hal_02::blocking::spi::Transfer<u8> for Spim<'d, T> {
317 type Error = Error;
318 fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
319 self.blocking_transfer_in_place(words)?;
320 Ok(words)
321 }
322 }
323
324 impl<'d, T: Instance> embedded_hal_02::blocking::spi::Write<u8> for Spim<'d, T> {
325 type Error = Error;
326
327 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
328 self.blocking_write(words)
329 }
330 }
331}
332
333#[cfg(feature = "unstable-traits")]
334mod eh1 {
335 use super::*;
336 use core::future::Future;
337
338 impl embedded_hal_1::spi::Error for Error {
339 fn kind(&self) -> embedded_hal_1::spi::ErrorKind {
340 match *self {
341 Self::TxBufferTooLong => embedded_hal_1::spi::ErrorKind::Other,
342 Self::RxBufferTooLong => embedded_hal_1::spi::ErrorKind::Other,
343 Self::DMABufferNotInDataMemory => embedded_hal_1::spi::ErrorKind::Other,
344 }
345 }
346 }
347
348 impl<'d, T: Instance> embedded_hal_1::spi::ErrorType for Spim<'d, T> {
349 type Error = Error;
350 }
351
352 impl<'d, T: Instance> embedded_hal_1::spi::blocking::Read<u8> for Spim<'d, T> {
353 fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
354 self.blocking_transfer(words, &[])
355 }
356
357 fn read_transaction(&mut self, words: &mut [&mut [u8]]) -> Result<(), Self::Error> {
358 for buf in words {
359 self.blocking_read(buf)?
360 }
361 Ok(())
362 }
363 }
364
365 impl<'d, T: Instance> embedded_hal_1::spi::blocking::Write<u8> for Spim<'d, T> {
366 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
367 self.blocking_write(words)
368 }
369
370 fn write_transaction(&mut self, words: &[&[u8]]) -> Result<(), Self::Error> {
371 for buf in words {
372 self.blocking_write(buf)?
373 }
374 Ok(())
375 }
376
377 fn write_iter<WI>(&mut self, words: WI) -> Result<(), Self::Error>
378 where
379 WI: IntoIterator<Item = u8>,
380 {
381 for w in words {
382 self.blocking_write(&[w])?;
383 }
384 Ok(())
385 }
386 }
387
388 impl<'d, T: Instance> embedded_hal_1::spi::blocking::ReadWrite<u8> for Spim<'d, T> {
389 fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
390 self.blocking_transfer(read, write)
391 }
392
393 fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
394 self.blocking_transfer_in_place(words)
395 }
396
397 fn transaction<'a>(
398 &mut self,
399 operations: &mut [embedded_hal_async::spi::Operation<'a, u8>],
400 ) -> Result<(), Self::Error> {
401 use embedded_hal_1::spi::blocking::Operation;
402 for o in operations {
403 match o {
404 Operation::Read(b) => self.blocking_read(b)?,
405 Operation::Write(b) => self.blocking_write(b)?,
406 Operation::Transfer(r, w) => self.blocking_transfer(r, w)?,
407 Operation::TransferInPlace(b) => self.blocking_transfer_in_place(b)?,
408 }
409 }
410 Ok(())
411 }
412 }
413
414 impl<'d, T: Instance> embedded_hal_async::spi::Read<u8> for Spim<'d, T> {
415 type ReadFuture<'a>
416 where
417 Self: 'a,
418 = impl Future<Output = Result<(), Self::Error>> + 'a;
419
420 fn read<'a>(&'a mut self, words: &'a mut [u8]) -> Self::ReadFuture<'a> {
421 self.read(words)
422 }
423
424 type ReadTransactionFuture<'a>
425 where
426 Self: 'a,
427 = impl Future<Output = Result<(), Self::Error>> + 'a;
428
429 fn read_transaction<'a>(
430 &'a mut self,
431 words: &'a mut [&'a mut [u8]],
432 ) -> Self::ReadTransactionFuture<'a> {
433 async move {
434 for buf in words {
435 self.read(buf).await?
436 }
437 Ok(())
438 }
439 }
440 }
441
442 impl<'d, T: Instance> embedded_hal_async::spi::Write<u8> for Spim<'d, T> {
443 type WriteFuture<'a>
444 where
445 Self: 'a,
446 = impl Future<Output = Result<(), Self::Error>> + 'a;
447
448 fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> {
449 self.write(data)
450 }
451
452 type WriteTransactionFuture<'a>
453 where
454 Self: 'a,
455 = impl Future<Output = Result<(), Self::Error>> + 'a;
456
457 fn write_transaction<'a>(
458 &'a mut self,
459 words: &'a [&'a [u8]],
460 ) -> Self::WriteTransactionFuture<'a> {
461 async move {
462 for buf in words {
463 self.write(buf).await?
464 }
465 Ok(())
466 }
467 }
468 }
469
470 impl<'d, T: Instance> embedded_hal_async::spi::ReadWrite<u8> for Spim<'d, T> {
471 type TransferFuture<'a>
472 where
473 Self: 'a,
474 = impl Future<Output = Result<(), Self::Error>> + 'a;
475
476 fn transfer<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Self::TransferFuture<'a> {
477 self.transfer(rx, tx)
478 }
479
480 type TransferInPlaceFuture<'a>
481 where
482 Self: 'a,
483 = impl Future<Output = Result<(), Self::Error>> + 'a;
484
485 fn transfer_in_place<'a>(
486 &'a mut self,
487 words: &'a mut [u8],
488 ) -> Self::TransferInPlaceFuture<'a> {
489 self.transfer_in_place(words)
490 }
491
492 type TransactionFuture<'a>
493 where
494 Self: 'a,
495 = impl Future<Output = Result<(), Self::Error>> + 'a;
496
497 fn transaction<'a>(
498 &'a mut self,
499 operations: &'a mut [embedded_hal_async::spi::Operation<'a, u8>],
500 ) -> Self::TransactionFuture<'a> {
501 use embedded_hal_1::spi::blocking::Operation;
502 async move {
503 for o in operations {
504 match o {
505 Operation::Read(b) => self.read(b).await?,
506 Operation::Write(b) => self.write(b).await?,
507 Operation::Transfer(r, w) => self.transfer(r, w).await?,
508 Operation::TransferInPlace(b) => self.transfer_in_place(b).await?,
509 }
510 }
511 Ok(())
512 }
513 }
514 }
515}
diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs
index 3cc79227e..4cd47c897 100644
--- a/embassy-nrf/src/twim.rs
+++ b/embassy-nrf/src/twim.rs
@@ -11,12 +11,10 @@ use core::marker::PhantomData;
11use core::sync::atomic::{compiler_fence, Ordering::SeqCst}; 11use core::sync::atomic::{compiler_fence, Ordering::SeqCst};
12use core::task::Poll; 12use core::task::Poll;
13use embassy::interrupt::{Interrupt, InterruptExt}; 13use embassy::interrupt::{Interrupt, InterruptExt};
14use embassy::traits;
15use embassy::util::Unborrow; 14use embassy::util::Unborrow;
16use embassy::waitqueue::AtomicWaker; 15use embassy::waitqueue::AtomicWaker;
17use embassy_hal_common::unborrow; 16use embassy_hal_common::unborrow;
18use futures::future::poll_fn; 17use futures::future::poll_fn;
19use traits::i2c::I2c;
20 18
21use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; 19use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
22use crate::gpio; 20use crate::gpio;
@@ -50,6 +48,22 @@ impl Default for Config {
50 } 48 }
51} 49}
52 50
51#[derive(Debug, Copy, Clone, Eq, PartialEq)]
52#[cfg_attr(feature = "defmt", derive(defmt::Format))]
53#[non_exhaustive]
54pub enum Error {
55 TxBufferTooLong,
56 RxBufferTooLong,
57 TxBufferZeroLength,
58 RxBufferZeroLength,
59 Transmit,
60 Receive,
61 DMABufferNotInDataMemory,
62 AddressNack,
63 DataNack,
64 Overrun,
65}
66
53/// Interface to a TWIM instance. 67/// Interface to a TWIM instance.
54pub struct Twim<'d, T: Instance> { 68pub struct Twim<'d, T: Instance> {
55 phantom: PhantomData<&'d mut T>, 69 phantom: PhantomData<&'d mut T>,
@@ -201,7 +215,7 @@ impl<'d, T: Instance> Twim<'d, T> {
201 } 215 }
202 216
203 /// Get Error instance, if any occurred. 217 /// Get Error instance, if any occurred.
204 fn read_errorsrc(&self) -> Result<(), Error> { 218 fn check_errorsrc(&self) -> Result<(), Error> {
205 let r = T::regs(); 219 let r = T::regs();
206 220
207 let err = r.errorsrc.read(); 221 let err = r.errorsrc.read();
@@ -217,8 +231,26 @@ impl<'d, T: Instance> Twim<'d, T> {
217 Ok(()) 231 Ok(())
218 } 232 }
219 233
234 fn check_rx(&self, len: usize) -> Result<(), Error> {
235 let r = T::regs();
236 if r.rxd.amount.read().bits() != len as u32 {
237 Err(Error::Receive)
238 } else {
239 Ok(())
240 }
241 }
242
243 fn check_tx(&self, len: usize) -> Result<(), Error> {
244 let r = T::regs();
245 if r.txd.amount.read().bits() != len as u32 {
246 Err(Error::Transmit)
247 } else {
248 Ok(())
249 }
250 }
251
220 /// Wait for stop or error 252 /// Wait for stop or error
221 fn wait(&mut self) { 253 fn blocking_wait(&mut self) {
222 let r = T::regs(); 254 let r = T::regs();
223 loop { 255 loop {
224 if r.events_stopped.read().bits() != 0 { 256 if r.events_stopped.read().bits() != 0 {
@@ -232,16 +264,32 @@ impl<'d, T: Instance> Twim<'d, T> {
232 } 264 }
233 } 265 }
234 266
235 /// Write to an I2C slave. 267 /// Wait for stop or error
236 /// 268 fn async_wait(&mut self) -> impl Future<Output = ()> {
237 /// The buffer must have a length of at most 255 bytes on the nRF52832 269 poll_fn(move |cx| {
238 /// and at most 65535 bytes on the nRF52840. 270 let r = T::regs();
239 pub fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> { 271 let s = T::state();
272
273 s.end_waker.register(cx.waker());
274 if r.events_stopped.read().bits() != 0 {
275 r.events_stopped.reset();
276
277 return Poll::Ready(());
278 }
279
280 // stop if an error occured
281 if r.events_error.read().bits() != 0 {
282 r.events_error.reset();
283 r.tasks_stop.write(|w| unsafe { w.bits(1) });
284 }
285
286 Poll::Pending
287 })
288 }
289
290 fn setup_write(&mut self, address: u8, buffer: &[u8], inten: bool) -> Result<(), Error> {
240 let r = T::regs(); 291 let r = T::regs();
241 292
242 // Conservative compiler fence to prevent optimizations that do not
243 // take in to account actions by DMA. The fence has been placed here,
244 // before any DMA action has started.
245 compiler_fence(SeqCst); 293 compiler_fence(SeqCst);
246 294
247 r.address.write(|w| unsafe { w.address().bits(address) }); 295 r.address.write(|w| unsafe { w.address().bits(address) });
@@ -255,38 +303,21 @@ impl<'d, T: Instance> Twim<'d, T> {
255 r.events_lasttx.reset(); 303 r.events_lasttx.reset();
256 self.clear_errorsrc(); 304 self.clear_errorsrc();
257 305
258 // Start write operation. 306 if inten {
259 r.shorts.write(|w| w.lasttx_stop().enabled()); 307 r.intenset.write(|w| w.stopped().set().error().set());
260 r.tasks_starttx.write(|w| 308 } else {
261 // `1` is a valid value to write to task registers. 309 r.intenclr.write(|w| w.stopped().clear().error().clear());
262 unsafe { w.bits(1) });
263
264 self.wait();
265
266 // Conservative compiler fence to prevent optimizations that do not
267 // take in to account actions by DMA. The fence has been placed here,
268 // after all possible DMA actions have completed.
269 compiler_fence(SeqCst);
270
271 self.read_errorsrc()?;
272
273 if r.txd.amount.read().bits() != buffer.len() as u32 {
274 return Err(Error::Transmit);
275 } 310 }
276 311
312 // Start write operation.
313 r.shorts.write(|w| w.lasttx_stop().enabled());
314 r.tasks_starttx.write(|w| unsafe { w.bits(1) });
277 Ok(()) 315 Ok(())
278 } 316 }
279 317
280 /// Read from an I2C slave. 318 fn setup_read(&mut self, address: u8, buffer: &mut [u8], inten: bool) -> Result<(), Error> {
281 ///
282 /// The buffer must have a length of at most 255 bytes on the nRF52832
283 /// and at most 65535 bytes on the nRF52840.
284 pub fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
285 let r = T::regs(); 319 let r = T::regs();
286 320
287 // Conservative compiler fence to prevent optimizations that do not
288 // take in to account actions by DMA. The fence has been placed here,
289 // before any DMA action has started.
290 compiler_fence(SeqCst); 321 compiler_fence(SeqCst);
291 322
292 r.address.write(|w| unsafe { w.address().bits(address) }); 323 r.address.write(|w| unsafe { w.address().bits(address) });
@@ -299,44 +330,27 @@ impl<'d, T: Instance> Twim<'d, T> {
299 r.events_error.reset(); 330 r.events_error.reset();
300 self.clear_errorsrc(); 331 self.clear_errorsrc();
301 332
302 // Start read operation. 333 if inten {
303 r.shorts.write(|w| w.lastrx_stop().enabled()); 334 r.intenset.write(|w| w.stopped().set().error().set());
304 r.tasks_startrx.write(|w| 335 } else {
305 // `1` is a valid value to write to task registers. 336 r.intenclr.write(|w| w.stopped().clear().error().clear());
306 unsafe { w.bits(1) });
307
308 self.wait();
309
310 // Conservative compiler fence to prevent optimizations that do not
311 // take in to account actions by DMA. The fence has been placed here,
312 // after all possible DMA actions have completed.
313 compiler_fence(SeqCst);
314
315 self.read_errorsrc()?;
316
317 if r.rxd.amount.read().bits() != buffer.len() as u32 {
318 return Err(Error::Receive);
319 } 337 }
320 338
339 // Start read operation.
340 r.shorts.write(|w| w.lastrx_stop().enabled());
341 r.tasks_startrx.write(|w| unsafe { w.bits(1) });
321 Ok(()) 342 Ok(())
322 } 343 }
323 344
324 /// Write data to an I2C slave, then read data from the slave without 345 fn setup_write_read(
325 /// triggering a stop condition between the two.
326 ///
327 /// The buffers must have a length of at most 255 bytes on the nRF52832
328 /// and at most 65535 bytes on the nRF52840.
329 pub fn write_then_read(
330 &mut self, 346 &mut self,
331 address: u8, 347 address: u8,
332 wr_buffer: &[u8], 348 wr_buffer: &[u8],
333 rd_buffer: &mut [u8], 349 rd_buffer: &mut [u8],
350 inten: bool,
334 ) -> Result<(), Error> { 351 ) -> Result<(), Error> {
335 let r = T::regs(); 352 let r = T::regs();
336 353
337 // Conservative compiler fence to prevent optimizations that do not
338 // take in to account actions by DMA. The fence has been placed here,
339 // before any DMA action has started.
340 compiler_fence(SeqCst); 354 compiler_fence(SeqCst);
341 355
342 r.address.write(|w| unsafe { w.address().bits(address) }); 356 r.address.write(|w| unsafe { w.address().bits(address) });
@@ -352,35 +366,65 @@ impl<'d, T: Instance> Twim<'d, T> {
352 r.events_error.reset(); 366 r.events_error.reset();
353 self.clear_errorsrc(); 367 self.clear_errorsrc();
354 368
369 if inten {
370 r.intenset.write(|w| w.stopped().set().error().set());
371 } else {
372 r.intenclr.write(|w| w.stopped().clear().error().clear());
373 }
374
355 // Start write+read operation. 375 // Start write+read operation.
356 r.shorts.write(|w| { 376 r.shorts.write(|w| {
357 w.lasttx_startrx().enabled(); 377 w.lasttx_startrx().enabled();
358 w.lastrx_stop().enabled(); 378 w.lastrx_stop().enabled();
359 w 379 w
360 }); 380 });
361 // `1` is a valid value to write to task registers.
362 r.tasks_starttx.write(|w| unsafe { w.bits(1) }); 381 r.tasks_starttx.write(|w| unsafe { w.bits(1) });
382 Ok(())
383 }
363 384
364 self.wait(); 385 /// Write to an I2C slave.
365 386 ///
366 // Conservative compiler fence to prevent optimizations that do not 387 /// The buffer must have a length of at most 255 bytes on the nRF52832
367 // take in to account actions by DMA. The fence has been placed here, 388 /// and at most 65535 bytes on the nRF52840.
368 // after all possible DMA actions have completed. 389 pub fn blocking_write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> {
390 self.setup_write(address, buffer, false)?;
391 self.blocking_wait();
369 compiler_fence(SeqCst); 392 compiler_fence(SeqCst);
393 self.check_errorsrc()?;
394 self.check_tx(buffer.len())?;
395 Ok(())
396 }
370 397
371 self.read_errorsrc()?; 398 /// Read from an I2C slave.
372 399 ///
373 let bad_write = r.txd.amount.read().bits() != wr_buffer.len() as u32; 400 /// The buffer must have a length of at most 255 bytes on the nRF52832
374 let bad_read = r.rxd.amount.read().bits() != rd_buffer.len() as u32; 401 /// and at most 65535 bytes on the nRF52840.
375 402 pub fn blocking_read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
376 if bad_write { 403 self.setup_read(address, buffer, false)?;
377 return Err(Error::Transmit); 404 self.blocking_wait();
378 } 405 compiler_fence(SeqCst);
379 406 self.check_errorsrc()?;
380 if bad_read { 407 self.check_rx(buffer.len())?;
381 return Err(Error::Receive); 408 Ok(())
382 } 409 }
383 410
411 /// Write data to an I2C slave, then read data from the slave without
412 /// triggering a stop condition between the two.
413 ///
414 /// The buffers must have a length of at most 255 bytes on the nRF52832
415 /// and at most 65535 bytes on the nRF52840.
416 pub fn blocking_write_read(
417 &mut self,
418 address: u8,
419 wr_buffer: &[u8],
420 rd_buffer: &mut [u8],
421 ) -> Result<(), Error> {
422 self.setup_write_read(address, wr_buffer, rd_buffer, false)?;
423 self.blocking_wait();
424 compiler_fence(SeqCst);
425 self.check_errorsrc()?;
426 self.check_tx(wr_buffer.len())?;
427 self.check_rx(rd_buffer.len())?;
384 Ok(()) 428 Ok(())
385 } 429 }
386 430
@@ -388,7 +432,7 @@ impl<'d, T: Instance> Twim<'d, T> {
388 /// 432 ///
389 /// The write buffer must have a length of at most 255 bytes on the nRF52832 433 /// The write buffer must have a length of at most 255 bytes on the nRF52832
390 /// and at most 1024 bytes on the nRF52840. 434 /// and at most 1024 bytes on the nRF52840.
391 pub fn copy_write(&mut self, address: u8, wr_buffer: &[u8]) -> Result<(), Error> { 435 pub fn blocking_copy_write(&mut self, address: u8, wr_buffer: &[u8]) -> Result<(), Error> {
392 if wr_buffer.len() > FORCE_COPY_BUFFER_SIZE { 436 if wr_buffer.len() > FORCE_COPY_BUFFER_SIZE {
393 return Err(Error::TxBufferTooLong); 437 return Err(Error::TxBufferTooLong);
394 } 438 }
@@ -397,7 +441,7 @@ impl<'d, T: Instance> Twim<'d, T> {
397 let wr_ram_buffer = &mut [0; FORCE_COPY_BUFFER_SIZE][..wr_buffer.len()]; 441 let wr_ram_buffer = &mut [0; FORCE_COPY_BUFFER_SIZE][..wr_buffer.len()];
398 wr_ram_buffer.copy_from_slice(wr_buffer); 442 wr_ram_buffer.copy_from_slice(wr_buffer);
399 443
400 self.write(address, wr_ram_buffer) 444 self.blocking_write(address, wr_ram_buffer)
401 } 445 }
402 446
403 /// Copy data into RAM and write to an I2C slave, then read data from the slave without 447 /// Copy data into RAM and write to an I2C slave, then read data from the slave without
@@ -408,7 +452,7 @@ impl<'d, T: Instance> Twim<'d, T> {
408 /// 452 ///
409 /// The read buffer must have a length of at most 255 bytes on the nRF52832 453 /// The read buffer must have a length of at most 255 bytes on the nRF52832
410 /// and at most 65535 bytes on the nRF52840. 454 /// and at most 65535 bytes on the nRF52840.
411 pub fn copy_write_then_read( 455 pub fn blocking_copy_write_read(
412 &mut self, 456 &mut self,
413 address: u8, 457 address: u8,
414 wr_buffer: &[u8], 458 wr_buffer: &[u8],
@@ -422,27 +466,40 @@ impl<'d, T: Instance> Twim<'d, T> {
422 let wr_ram_buffer = &mut [0; FORCE_COPY_BUFFER_SIZE][..wr_buffer.len()]; 466 let wr_ram_buffer = &mut [0; FORCE_COPY_BUFFER_SIZE][..wr_buffer.len()];
423 wr_ram_buffer.copy_from_slice(wr_buffer); 467 wr_ram_buffer.copy_from_slice(wr_buffer);
424 468
425 self.write_then_read(address, wr_ram_buffer, rd_buffer) 469 self.blocking_write_read(address, wr_ram_buffer, rd_buffer)
426 } 470 }
427 471
428 fn wait_for_stopped_event(cx: &mut core::task::Context) -> Poll<()> { 472 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
429 let r = T::regs(); 473 self.setup_read(address, buffer, true)?;
430 let s = T::state(); 474 self.async_wait().await;
431 475 compiler_fence(SeqCst);
432 s.end_waker.register(cx.waker()); 476 self.check_errorsrc()?;
433 if r.events_stopped.read().bits() != 0 { 477 self.check_rx(buffer.len())?;
434 r.events_stopped.reset(); 478 Ok(())
435 479 }
436 return Poll::Ready(());
437 }
438 480
439 // stop if an error occured 481 pub async fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> {
440 if r.events_error.read().bits() != 0 { 482 self.setup_write(address, buffer, true)?;
441 r.events_error.reset(); 483 self.async_wait().await;
442 r.tasks_stop.write(|w| unsafe { w.bits(1) }); 484 compiler_fence(SeqCst);
443 } 485 self.check_errorsrc()?;
486 self.check_tx(buffer.len())?;
487 Ok(())
488 }
444 489
445 Poll::Pending 490 pub async fn write_read(
491 &mut self,
492 address: u8,
493 wr_buffer: &[u8],
494 rd_buffer: &mut [u8],
495 ) -> Result<(), Error> {
496 self.setup_write_read(address, wr_buffer, rd_buffer, true)?;
497 self.async_wait().await;
498 compiler_fence(SeqCst);
499 self.check_errorsrc()?;
500 self.check_tx(wr_buffer.len())?;
501 self.check_rx(rd_buffer.len())?;
502 Ok(())
446 } 503 }
447} 504}
448 505
@@ -450,7 +507,7 @@ impl<'a, T: Instance> Drop for Twim<'a, T> {
450 fn drop(&mut self) { 507 fn drop(&mut self) {
451 trace!("twim drop"); 508 trace!("twim drop");
452 509
453 // TODO when implementing async here, check for abort 510 // TODO: check for abort
454 511
455 // disable! 512 // disable!
456 let r = T::regs(); 513 let r = T::regs();
@@ -463,292 +520,228 @@ impl<'a, T: Instance> Drop for Twim<'a, T> {
463 } 520 }
464} 521}
465 522
466impl<'d, T> I2c for Twim<'d, T> 523pub(crate) mod sealed {
467where 524 use super::*;
468 T: Instance,
469{
470 type Error = Error;
471
472 type WriteFuture<'a>
473 where
474 Self: 'a,
475 = impl Future<Output = Result<(), Self::Error>> + 'a;
476 type ReadFuture<'a>
477 where
478 Self: 'a,
479 = impl Future<Output = Result<(), Self::Error>> + 'a;
480 type WriteReadFuture<'a>
481 where
482 Self: 'a,
483 = impl Future<Output = Result<(), Self::Error>> + 'a;
484
485 fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
486 async move {
487 // NOTE: RAM slice check for buffer is not necessary, as a mutable
488 // slice can only be built from data located in RAM.
489
490 let r = T::regs();
491
492 // Conservative compiler fence to prevent optimizations that do not
493 // take in to account actions by DMA. The fence has been placed here,
494 // before any DMA action has started.
495 compiler_fence(SeqCst);
496
497 r.address.write(|w| unsafe { w.address().bits(address) });
498
499 // Set up the DMA read.
500 unsafe { self.set_rx_buffer(buffer)? };
501
502 // Reset events
503 r.events_stopped.reset();
504 r.events_error.reset();
505 self.clear_errorsrc();
506
507 // Enable events
508 r.intenset.write(|w| w.stopped().set().error().set());
509
510 // Start read operation.
511 r.shorts.write(|w| w.lastrx_stop().enabled());
512 r.tasks_startrx.write(|w|
513 // `1` is a valid value to write to task registers.
514 unsafe { w.bits(1) });
515
516 // Conservative compiler fence to prevent optimizations that do not
517 // take in to account actions by DMA. The fence has been placed here,
518 // after all possible DMA actions have completed.
519 compiler_fence(SeqCst);
520
521 // Wait for 'stopped' event.
522 poll_fn(Self::wait_for_stopped_event).await;
523 525
524 self.read_errorsrc()?; 526 pub struct State {
527 pub end_waker: AtomicWaker,
528 }
525 529
526 if r.rxd.amount.read().bits() != buffer.len() as u32 { 530 impl State {
527 return Err(Error::Receive); 531 pub const fn new() -> Self {
532 Self {
533 end_waker: AtomicWaker::new(),
528 } 534 }
529
530 Ok(())
531 } 535 }
532 } 536 }
533 537
534 fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Self::WriteFuture<'a> { 538 pub trait Instance {
535 async move { 539 fn regs() -> &'static pac::twim0::RegisterBlock;
536 slice_in_ram_or(bytes, Error::DMABufferNotInDataMemory)?; 540 fn state() -> &'static State;
537 541 }
538 // Conservative compiler fence to prevent optimizations that do not 542}
539 // take in to account actions by DMA. The fence has been placed here,
540 // before any DMA action has started.
541 compiler_fence(SeqCst);
542
543 let r = T::regs();
544 543
545 // Set up current address we're trying to talk to 544pub trait Instance: Unborrow<Target = Self> + sealed::Instance + 'static {
546 r.address.write(|w| unsafe { w.address().bits(address) }); 545 type Interrupt: Interrupt;
546}
547 547
548 // Set up DMA write. 548macro_rules! impl_twim {
549 unsafe { 549 ($type:ident, $pac_type:ident, $irq:ident) => {
550 self.set_tx_buffer(bytes)?; 550 impl crate::twim::sealed::Instance for peripherals::$type {
551 fn regs() -> &'static pac::twim0::RegisterBlock {
552 unsafe { &*pac::$pac_type::ptr() }
551 } 553 }
552 554 fn state() -> &'static crate::twim::sealed::State {
553 // Reset events 555 static STATE: crate::twim::sealed::State = crate::twim::sealed::State::new();
554 r.events_stopped.reset(); 556 &STATE
555 r.events_error.reset();
556 r.events_lasttx.reset();
557 self.clear_errorsrc();
558
559 // Enable events
560 r.intenset.write(|w| w.stopped().set().error().set());
561
562 // Start write operation.
563 r.shorts.write(|w| w.lasttx_stop().enabled());
564 r.tasks_starttx.write(|w|
565 // `1` is a valid value to write to task registers.
566 unsafe { w.bits(1) });
567
568 // Conservative compiler fence to prevent optimizations that do not
569 // take in to account actions by DMA. The fence has been placed here,
570 // after all possible DMA actions have completed.
571 compiler_fence(SeqCst);
572
573 // Wait for 'stopped' event.
574 poll_fn(Self::wait_for_stopped_event).await;
575
576 self.read_errorsrc()?;
577
578 if r.txd.amount.read().bits() != bytes.len() as u32 {
579 return Err(Error::Transmit);
580 } 557 }
581
582 Ok(())
583 } 558 }
584 } 559 impl crate::twim::Instance for peripherals::$type {
585 560 type Interrupt = crate::interrupt::$irq;
586 fn write_read<'a>( 561 }
587 &'a mut self, 562 };
588 address: u8, 563}
589 bytes: &'a [u8],
590 buffer: &'a mut [u8],
591 ) -> Self::WriteReadFuture<'a> {
592 async move {
593 slice_in_ram_or(bytes, Error::DMABufferNotInDataMemory)?;
594 // NOTE: RAM slice check for buffer is not necessary, as a mutable
595 // slice can only be built from data located in RAM.
596
597 // Conservative compiler fence to prevent optimizations that do not
598 // take in to account actions by DMA. The fence has been placed here,
599 // before any DMA action has started.
600 compiler_fence(SeqCst);
601 564
602 let r = T::regs(); 565// ====================
603 566
604 // Set up current address we're trying to talk to 567mod eh02 {
605 r.address.write(|w| unsafe { w.address().bits(address) }); 568 use super::*;
606 569
607 // Set up DMA buffers. 570 impl<'a, T: Instance> embedded_hal_02::blocking::i2c::Write for Twim<'a, T> {
608 unsafe { 571 type Error = Error;
609 self.set_tx_buffer(bytes)?; 572
610 self.set_rx_buffer(buffer)?; 573 fn write<'w>(&mut self, addr: u8, bytes: &'w [u8]) -> Result<(), Error> {
574 if slice_in_ram(bytes) {
575 self.blocking_write(addr, bytes)
576 } else {
577 let buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..];
578 for chunk in bytes.chunks(FORCE_COPY_BUFFER_SIZE) {
579 buf[..chunk.len()].copy_from_slice(chunk);
580 self.blocking_write(addr, &buf[..chunk.len()])?;
581 }
582 Ok(())
611 } 583 }
584 }
585 }
612 586
613 // Reset events 587 impl<'a, T: Instance> embedded_hal_02::blocking::i2c::Read for Twim<'a, T> {
614 r.events_stopped.reset(); 588 type Error = Error;
615 r.events_error.reset();
616 r.events_lasttx.reset();
617 self.clear_errorsrc();
618
619 // Enable events
620 r.intenset.write(|w| w.stopped().set().error().set());
621
622 // Start write+read operation.
623 r.shorts.write(|w| {
624 w.lasttx_startrx().enabled();
625 w.lastrx_stop().enabled();
626 w
627 });
628 // `1` is a valid value to write to task registers.
629 r.tasks_starttx.write(|w| unsafe { w.bits(1) });
630
631 // Conservative compiler fence to prevent optimizations that do not
632 // take in to account actions by DMA. The fence has been placed here,
633 // after all possible DMA actions have completed.
634 compiler_fence(SeqCst);
635
636 // Wait for 'stopped' event.
637 poll_fn(Self::wait_for_stopped_event).await;
638
639 self.read_errorsrc()?;
640
641 let bad_write = r.txd.amount.read().bits() != bytes.len() as u32;
642 let bad_read = r.rxd.amount.read().bits() != buffer.len() as u32;
643 589
644 if bad_write { 590 fn read<'w>(&mut self, addr: u8, bytes: &'w mut [u8]) -> Result<(), Error> {
645 return Err(Error::Transmit); 591 self.blocking_read(addr, bytes)
646 } 592 }
593 }
647 594
648 if bad_read { 595 impl<'a, T: Instance> embedded_hal_02::blocking::i2c::WriteRead for Twim<'a, T> {
649 return Err(Error::Receive); 596 type Error = Error;
597
598 fn write_read<'w>(
599 &mut self,
600 addr: u8,
601 bytes: &'w [u8],
602 buffer: &'w mut [u8],
603 ) -> Result<(), Error> {
604 if slice_in_ram(bytes) {
605 self.blocking_write_read(addr, bytes, buffer)
606 } else {
607 self.blocking_copy_write_read(addr, bytes, buffer)
650 } 608 }
651
652 Ok(())
653 } 609 }
654 } 610 }
655} 611}
656 612
657impl<'a, T: Instance> embedded_hal::blocking::i2c::Write for Twim<'a, T> { 613#[cfg(feature = "unstable-traits")]
658 type Error = Error; 614mod eh1 {
615 use super::*;
659 616
660 fn write<'w>(&mut self, addr: u8, bytes: &'w [u8]) -> Result<(), Error> { 617 impl embedded_hal_1::i2c::Error for Error {
661 if slice_in_ram(bytes) { 618 fn kind(&self) -> embedded_hal_1::i2c::ErrorKind {
662 self.write(addr, bytes) 619 match *self {
663 } else { 620 Self::TxBufferTooLong => embedded_hal_1::i2c::ErrorKind::Other,
664 let buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..]; 621 Self::RxBufferTooLong => embedded_hal_1::i2c::ErrorKind::Other,
665 for chunk in bytes.chunks(FORCE_COPY_BUFFER_SIZE) { 622 Self::TxBufferZeroLength => embedded_hal_1::i2c::ErrorKind::Other,
666 buf[..chunk.len()].copy_from_slice(chunk); 623 Self::RxBufferZeroLength => embedded_hal_1::i2c::ErrorKind::Other,
667 self.write(addr, &buf[..chunk.len()])?; 624 Self::Transmit => embedded_hal_1::i2c::ErrorKind::Other,
625 Self::Receive => embedded_hal_1::i2c::ErrorKind::Other,
626 Self::DMABufferNotInDataMemory => embedded_hal_1::i2c::ErrorKind::Other,
627 Self::AddressNack => embedded_hal_1::i2c::ErrorKind::NoAcknowledge(
628 embedded_hal_1::i2c::NoAcknowledgeSource::Address,
629 ),
630 Self::DataNack => embedded_hal_1::i2c::ErrorKind::NoAcknowledge(
631 embedded_hal_1::i2c::NoAcknowledgeSource::Data,
632 ),
633 Self::Overrun => embedded_hal_1::i2c::ErrorKind::Overrun,
668 } 634 }
669 Ok(())
670 } 635 }
671 } 636 }
672}
673 637
674impl<'a, T: Instance> embedded_hal::blocking::i2c::Read for Twim<'a, T> { 638 impl<'d, T: Instance> embedded_hal_1::i2c::ErrorType for Twim<'d, T> {
675 type Error = Error; 639 type Error = Error;
676
677 fn read<'w>(&mut self, addr: u8, bytes: &'w mut [u8]) -> Result<(), Error> {
678 self.read(addr, bytes)
679 } 640 }
680}
681 641
682impl<'a, T: Instance> embedded_hal::blocking::i2c::WriteRead for Twim<'a, T> { 642 impl<'d, T: Instance> embedded_hal_1::i2c::blocking::I2c for Twim<'d, T> {
683 type Error = Error; 643 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
644 self.blocking_read(address, buffer)
645 }
684 646
685 fn write_read<'w>( 647 fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Self::Error> {
686 &mut self, 648 self.blocking_write(address, buffer)
687 addr: u8,
688 bytes: &'w [u8],
689 buffer: &'w mut [u8],
690 ) -> Result<(), Error> {
691 if slice_in_ram(bytes) {
692 self.write_then_read(addr, bytes, buffer)
693 } else {
694 self.copy_write_then_read(addr, bytes, buffer)
695 } 649 }
696 }
697}
698 650
699#[derive(Debug, Copy, Clone, Eq, PartialEq)] 651 fn write_iter<B>(&mut self, _address: u8, _bytes: B) -> Result<(), Self::Error>
700#[cfg_attr(feature = "defmt", derive(defmt::Format))] 652 where
701pub enum Error { 653 B: IntoIterator<Item = u8>,
702 TxBufferTooLong, 654 {
703 RxBufferTooLong, 655 todo!();
704 TxBufferZeroLength, 656 }
705 RxBufferZeroLength,
706 Transmit,
707 Receive,
708 DMABufferNotInDataMemory,
709 AddressNack,
710 DataNack,
711 Overrun,
712}
713 657
714pub(crate) mod sealed { 658 fn write_iter_read<B>(
715 use super::*; 659 &mut self,
660 _address: u8,
661 _bytes: B,
662 _buffer: &mut [u8],
663 ) -> Result<(), Self::Error>
664 where
665 B: IntoIterator<Item = u8>,
666 {
667 todo!();
668 }
716 669
717 pub struct State { 670 fn write_read(
718 pub end_waker: AtomicWaker, 671 &mut self,
719 } 672 address: u8,
673 wr_buffer: &[u8],
674 rd_buffer: &mut [u8],
675 ) -> Result<(), Self::Error> {
676 self.blocking_write_read(address, wr_buffer, rd_buffer)
677 }
720 678
721 impl State { 679 fn transaction<'a>(
722 pub const fn new() -> Self { 680 &mut self,
723 Self { 681 _address: u8,
724 end_waker: AtomicWaker::new(), 682 _operations: &mut [embedded_hal_async::i2c::Operation<'a>],
725 } 683 ) -> Result<(), Self::Error> {
684 todo!();
726 } 685 }
727 }
728 686
729 pub trait Instance { 687 fn transaction_iter<'a, O>(
730 fn regs() -> &'static pac::twim0::RegisterBlock; 688 &mut self,
731 fn state() -> &'static State; 689 _address: u8,
690 _operations: O,
691 ) -> Result<(), Self::Error>
692 where
693 O: IntoIterator<Item = embedded_hal_async::i2c::Operation<'a>>,
694 {
695 todo!();
696 }
732 } 697 }
733}
734 698
735pub trait Instance: Unborrow<Target = Self> + sealed::Instance + 'static { 699 impl<'d, T: Instance> embedded_hal_async::i2c::I2c for Twim<'d, T> {
736 type Interrupt: Interrupt; 700 type ReadFuture<'a>
737} 701 where
702 Self: 'a,
703 = impl Future<Output = Result<(), Self::Error>> + 'a;
738 704
739macro_rules! impl_twim { 705 fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
740 ($type:ident, $pac_type:ident, $irq:ident) => { 706 self.read(address, buffer)
741 impl crate::twim::sealed::Instance for peripherals::$type {
742 fn regs() -> &'static pac::twim0::RegisterBlock {
743 unsafe { &*pac::$pac_type::ptr() }
744 }
745 fn state() -> &'static crate::twim::sealed::State {
746 static STATE: crate::twim::sealed::State = crate::twim::sealed::State::new();
747 &STATE
748 }
749 } 707 }
750 impl crate::twim::Instance for peripherals::$type { 708
751 type Interrupt = crate::interrupt::$irq; 709 type WriteFuture<'a>
710 where
711 Self: 'a,
712 = impl Future<Output = Result<(), Self::Error>> + 'a;
713
714 fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Self::WriteFuture<'a> {
715 self.write(address, bytes)
752 } 716 }
753 }; 717
718 type WriteReadFuture<'a>
719 where
720 Self: 'a,
721 = impl Future<Output = Result<(), Self::Error>> + 'a;
722
723 fn write_read<'a>(
724 &'a mut self,
725 address: u8,
726 wr_buffer: &'a [u8],
727 rd_buffer: &'a mut [u8],
728 ) -> Self::WriteReadFuture<'a> {
729 self.write_read(address, wr_buffer, rd_buffer)
730 }
731
732 type TransactionFuture<'a>
733 where
734 Self: 'a,
735 = impl Future<Output = Result<(), Self::Error>> + 'a;
736
737 fn transaction<'a>(
738 &'a mut self,
739 address: u8,
740 operations: &mut [embedded_hal_async::i2c::Operation<'a>],
741 ) -> Self::TransactionFuture<'a> {
742 let _ = address;
743 let _ = operations;
744 async move { todo!() }
745 }
746 }
754} 747}
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs
index 38480ecca..b10e55a05 100644
--- a/embassy-nrf/src/uarte.rs
+++ b/embassy-nrf/src/uarte.rs
@@ -13,12 +13,10 @@
13//! memory may be used given that buffers are passed in directly to its read and write 13//! memory may be used given that buffers are passed in directly to its read and write
14//! methods. 14//! methods.
15 15
16use core::future::Future;
17use core::marker::PhantomData; 16use core::marker::PhantomData;
18use core::sync::atomic::{compiler_fence, Ordering}; 17use core::sync::atomic::{compiler_fence, Ordering};
19use core::task::Poll; 18use core::task::Poll;
20use embassy::interrupt::InterruptExt; 19use embassy::interrupt::InterruptExt;
21use embassy::traits::uart::{Error as TraitError, Read, ReadUntilIdle, Write};
22use embassy::util::Unborrow; 20use embassy::util::Unborrow;
23use embassy_hal_common::drop::OnDrop; 21use embassy_hal_common::drop::OnDrop;
24use embassy_hal_common::unborrow; 22use embassy_hal_common::unborrow;
@@ -32,6 +30,7 @@ use crate::pac;
32use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; 30use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
33use crate::timer::Instance as TimerInstance; 31use crate::timer::Instance as TimerInstance;
34use crate::timer::{Frequency, Timer}; 32use crate::timer::{Frequency, Timer};
33use crate::util::slice_in_ram_or;
35 34
36// Re-export SVD variants to allow user to directly set values. 35// Re-export SVD variants to allow user to directly set values.
37pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; 36pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
@@ -51,6 +50,16 @@ impl Default for Config {
51 } 50 }
52} 51}
53 52
53#[derive(Debug, Clone, Copy, PartialEq, Eq)]
54#[cfg_attr(feature = "defmt", derive(defmt::Format))]
55#[non_exhaustive]
56pub enum Error {
57 BufferTooLong,
58 BufferZeroLength,
59 DMABufferNotInDataMemory,
60 // TODO: add other error variants.
61}
62
54/// Interface to the UARTE peripheral 63/// Interface to the UARTE peripheral
55pub struct Uarte<'d, T: Instance> { 64pub struct Uarte<'d, T: Instance> {
56 phantom: PhantomData<&'d mut T>, 65 phantom: PhantomData<&'d mut T>,
@@ -139,8 +148,12 @@ impl<'d, T: Instance> Uarte<'d, T> {
139 148
140 Self { 149 Self {
141 phantom: PhantomData, 150 phantom: PhantomData,
142 tx: UarteTx::new(), 151 tx: UarteTx {
143 rx: UarteRx::new(), 152 phantom: PhantomData,
153 },
154 rx: UarteRx {
155 phantom: PhantomData,
156 },
144 } 157 }
145 } 158 }
146 159
@@ -170,92 +183,110 @@ impl<'d, T: Instance> Uarte<'d, T> {
170 r.intenclr.write(|w| w.endtx().clear()); 183 r.intenclr.write(|w| w.endtx().clear());
171 } 184 }
172 } 185 }
173}
174 186
175impl<'d, T: Instance> Read for Uarte<'d, T> { 187 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
176 type ReadFuture<'a> 188 self.rx.read(buffer).await
177 where 189 }
178 Self: 'a,
179 = impl Future<Output = Result<(), TraitError>> + 'a;
180 190
181 fn read<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { 191 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
182 self.rx.read(rx_buffer) 192 self.tx.write(buffer).await
183 } 193 }
184}
185 194
186impl<'d, T: Instance> Write for Uarte<'d, T> { 195 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
187 type WriteFuture<'a> 196 self.rx.blocking_read(buffer)
188 where 197 }
189 Self: 'a,
190 = impl Future<Output = Result<(), TraitError>> + 'a;
191 198
192 fn write<'a>(&'a mut self, tx_buffer: &'a [u8]) -> Self::WriteFuture<'a> { 199 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
193 self.tx.write(tx_buffer) 200 self.tx.blocking_write(buffer)
194 } 201 }
195} 202}
196 203
197impl<'d, T: Instance> UarteTx<'d, T> { 204impl<'d, T: Instance> UarteTx<'d, T> {
198 pub fn new() -> Self { 205 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
199 Self { 206 slice_in_ram_or(buffer, Error::DMABufferNotInDataMemory)?;
200 phantom: PhantomData, 207 if buffer.len() == 0 {
208 return Err(Error::BufferZeroLength);
209 }
210 if buffer.len() > EASY_DMA_SIZE {
211 return Err(Error::BufferTooLong);
201 } 212 }
202 }
203}
204 213
205impl<'d, T: Instance> Write for UarteTx<'d, T> { 214 let ptr = buffer.as_ptr();
206 type WriteFuture<'a> 215 let len = buffer.len();
207 where
208 Self: 'a,
209 = impl Future<Output = Result<(), TraitError>> + 'a;
210 216
211 fn write<'a>(&'a mut self, tx_buffer: &'a [u8]) -> Self::WriteFuture<'a> { 217 let r = T::regs();
212 async move { 218 let s = T::state();
213 let ptr = tx_buffer.as_ptr();
214 let len = tx_buffer.len();
215 assert!(len <= EASY_DMA_SIZE);
216 // TODO: panic if buffer is not in SRAM
217 219
218 let r = T::regs(); 220 let drop = OnDrop::new(move || {
219 let s = T::state(); 221 trace!("write drop: stopping");
220 222
221 let drop = OnDrop::new(move || { 223 r.intenclr.write(|w| w.endtx().clear());
222 trace!("write drop: stopping"); 224 r.events_txstopped.reset();
225 r.tasks_stoptx.write(|w| unsafe { w.bits(1) });
223 226
224 r.intenclr.write(|w| w.endtx().clear()); 227 // TX is stopped almost instantly, spinning is fine.
225 r.events_txstopped.reset(); 228 while r.events_endtx.read().bits() == 0 {}
226 r.tasks_stoptx.write(|w| unsafe { w.bits(1) }); 229 trace!("write drop: stopped");
230 });
227 231
228 // TX is stopped almost instantly, spinning is fine. 232 r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
229 while r.events_endtx.read().bits() == 0 {} 233 r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
230 trace!("write drop: stopped");
231 });
232 234
233 r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); 235 r.events_endtx.reset();
234 r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); 236 r.intenset.write(|w| w.endtx().set());
235 237
236 r.events_endtx.reset(); 238 compiler_fence(Ordering::SeqCst);
237 r.intenset.write(|w| w.endtx().set());
238 239
239 compiler_fence(Ordering::SeqCst); 240 trace!("starttx");
241 r.tasks_starttx.write(|w| unsafe { w.bits(1) });
240 242
241 trace!("starttx"); 243 poll_fn(|cx| {
242 r.tasks_starttx.write(|w| unsafe { w.bits(1) }); 244 s.endtx_waker.register(cx.waker());
245 if r.events_endtx.read().bits() != 0 {
246 return Poll::Ready(());
247 }
248 Poll::Pending
249 })
250 .await;
243 251
244 poll_fn(|cx| { 252 compiler_fence(Ordering::SeqCst);
245 s.endtx_waker.register(cx.waker()); 253 r.events_txstarted.reset();
246 if r.events_endtx.read().bits() != 0 { 254 drop.defuse();
247 return Poll::Ready(());
248 }
249 Poll::Pending
250 })
251 .await;
252 255
253 compiler_fence(Ordering::SeqCst); 256 Ok(())
254 r.events_txstarted.reset(); 257 }
255 drop.defuse();
256 258
257 Ok(()) 259 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
260 slice_in_ram_or(buffer, Error::DMABufferNotInDataMemory)?;
261 if buffer.len() == 0 {
262 return Err(Error::BufferZeroLength);
263 }
264 if buffer.len() > EASY_DMA_SIZE {
265 return Err(Error::BufferTooLong);
258 } 266 }
267
268 let ptr = buffer.as_ptr();
269 let len = buffer.len();
270
271 let r = T::regs();
272
273 r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
274 r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
275
276 r.events_endtx.reset();
277 r.intenclr.write(|w| w.endtx().clear());
278
279 compiler_fence(Ordering::SeqCst);
280
281 trace!("starttx");
282 r.tasks_starttx.write(|w| unsafe { w.bits(1) });
283
284 while r.events_endtx.read().bits() == 0 {}
285
286 compiler_fence(Ordering::SeqCst);
287 r.events_txstarted.reset();
288
289 Ok(())
259 } 290 }
260} 291}
261 292
@@ -278,66 +309,89 @@ impl<'a, T: Instance> Drop for UarteTx<'a, T> {
278} 309}
279 310
280impl<'d, T: Instance> UarteRx<'d, T> { 311impl<'d, T: Instance> UarteRx<'d, T> {
281 pub fn new() -> Self { 312 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
282 Self { 313 if buffer.len() == 0 {
283 phantom: PhantomData, 314 return Err(Error::BufferZeroLength);
315 }
316 if buffer.len() > EASY_DMA_SIZE {
317 return Err(Error::BufferTooLong);
284 } 318 }
285 }
286}
287 319
288impl<'d, T: Instance> Read for UarteRx<'d, T> { 320 let ptr = buffer.as_ptr();
289 type ReadFuture<'a> 321 let len = buffer.len();
290 where
291 Self: 'a,
292 = impl Future<Output = Result<(), TraitError>> + 'a;
293 322
294 fn read<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { 323 let r = T::regs();
295 async move { 324 let s = T::state();
296 let ptr = rx_buffer.as_ptr();
297 let len = rx_buffer.len();
298 assert!(len <= EASY_DMA_SIZE);
299 325
300 let r = T::regs(); 326 let drop = OnDrop::new(move || {
301 let s = T::state(); 327 trace!("read drop: stopping");
302 328
303 let drop = OnDrop::new(move || { 329 r.intenclr.write(|w| w.endrx().clear());
304 trace!("read drop: stopping"); 330 r.events_rxto.reset();
331 r.tasks_stoprx.write(|w| unsafe { w.bits(1) });
305 332
306 r.intenclr.write(|w| w.endrx().clear()); 333 while r.events_endrx.read().bits() == 0 {}
307 r.events_rxto.reset();
308 r.tasks_stoprx.write(|w| unsafe { w.bits(1) });
309 334
310 while r.events_endrx.read().bits() == 0 {} 335 trace!("read drop: stopped");
336 });
311 337
312 trace!("read drop: stopped"); 338 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
313 }); 339 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
314 340
315 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); 341 r.events_endrx.reset();
316 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); 342 r.intenset.write(|w| w.endrx().set());
317 343
318 r.events_endrx.reset(); 344 compiler_fence(Ordering::SeqCst);
319 r.intenset.write(|w| w.endrx().set());
320 345
321 compiler_fence(Ordering::SeqCst); 346 trace!("startrx");
347 r.tasks_startrx.write(|w| unsafe { w.bits(1) });
322 348
323 trace!("startrx"); 349 poll_fn(|cx| {
324 r.tasks_startrx.write(|w| unsafe { w.bits(1) }); 350 s.endrx_waker.register(cx.waker());
351 if r.events_endrx.read().bits() != 0 {
352 return Poll::Ready(());
353 }
354 Poll::Pending
355 })
356 .await;
325 357
326 poll_fn(|cx| { 358 compiler_fence(Ordering::SeqCst);
327 s.endrx_waker.register(cx.waker()); 359 r.events_rxstarted.reset();
328 if r.events_endrx.read().bits() != 0 { 360 drop.defuse();
329 return Poll::Ready(());
330 }
331 Poll::Pending
332 })
333 .await;
334 361
335 compiler_fence(Ordering::SeqCst); 362 Ok(())
336 r.events_rxstarted.reset(); 363 }
337 drop.defuse();
338 364
339 Ok(()) 365 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
366 if buffer.len() == 0 {
367 return Err(Error::BufferZeroLength);
368 }
369 if buffer.len() > EASY_DMA_SIZE {
370 return Err(Error::BufferTooLong);
340 } 371 }
372
373 let ptr = buffer.as_ptr();
374 let len = buffer.len();
375
376 let r = T::regs();
377
378 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
379 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
380
381 r.events_endrx.reset();
382 r.intenclr.write(|w| w.endrx().clear());
383
384 compiler_fence(Ordering::SeqCst);
385
386 trace!("startrx");
387 r.tasks_startrx.write(|w| unsafe { w.bits(1) });
388
389 while r.events_endrx.read().bits() == 0 {}
390
391 compiler_fence(Ordering::SeqCst);
392 r.events_rxstarted.reset();
393
394 Ok(())
341 } 395 }
342} 396}
343 397
@@ -439,14 +493,7 @@ pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> {
439impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> { 493impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> {
440 /// Creates the interface to a UARTE instance. 494 /// Creates the interface to a UARTE instance.
441 /// Sets the baud rate, parity and assigns the pins to the UARTE peripheral. 495 /// Sets the baud rate, parity and assigns the pins to the UARTE peripheral.
442 /// 496 pub fn new(
443 /// # Safety
444 ///
445 /// The returned API is safe unless you use `mem::forget` (or similar safe mechanisms)
446 /// on stack allocated buffers which which have been passed to [`send()`](Uarte::send)
447 /// or [`receive`](Uarte::receive).
448 #[allow(unused_unsafe)]
449 pub unsafe fn new(
450 uarte: impl Unborrow<Target = U> + 'd, 497 uarte: impl Unborrow<Target = U> + 'd,
451 timer: impl Unborrow<Target = T> + 'd, 498 timer: impl Unborrow<Target = T> + 'd,
452 ppi_ch1: impl Unborrow<Target = impl ConfigurableChannel + 'd> + 'd, 499 ppi_ch1: impl Unborrow<Target = impl ConfigurableChannel + 'd> + 'd,
@@ -501,93 +548,119 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> {
501 _ppi_ch2: ppi_ch2, 548 _ppi_ch2: ppi_ch2,
502 } 549 }
503 } 550 }
504}
505 551
506impl<'d, U: Instance, T: TimerInstance> ReadUntilIdle for UarteWithIdle<'d, U, T> { 552 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
507 type ReadUntilIdleFuture<'a> 553 self.ppi_ch1.disable();
508 where 554 self.uarte.read(buffer).await
509 Self: 'a, 555 }
510 = impl Future<Output = Result<usize, TraitError>> + 'a;
511 fn read_until_idle<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadUntilIdleFuture<'a> {
512 async move {
513 let ptr = rx_buffer.as_ptr();
514 let len = rx_buffer.len();
515 assert!(len <= EASY_DMA_SIZE);
516 556
517 let r = U::regs(); 557 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
518 let s = U::state(); 558 self.uarte.write(buffer).await
559 }
519 560
520 let drop = OnDrop::new(|| { 561 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
521 trace!("read drop: stopping"); 562 self.ppi_ch1.disable();
563 self.uarte.blocking_read(buffer)
564 }
522 565
523 self.timer.stop(); 566 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
567 self.uarte.blocking_write(buffer)
568 }
524 569
525 r.intenclr.write(|w| w.endrx().clear()); 570 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
526 r.events_rxto.reset(); 571 if buffer.len() == 0 {
527 r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); 572 return Err(Error::BufferZeroLength);
573 }
574 if buffer.len() > EASY_DMA_SIZE {
575 return Err(Error::BufferTooLong);
576 }
528 577
529 while r.events_endrx.read().bits() == 0 {} 578 let ptr = buffer.as_ptr();
579 let len = buffer.len();
530 580
531 trace!("read drop: stopped"); 581 let r = U::regs();
532 }); 582 let s = U::state();
533 583
534 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); 584 self.ppi_ch1.enable();
535 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
536 585
537 r.events_endrx.reset(); 586 let drop = OnDrop::new(|| {
538 r.intenset.write(|w| w.endrx().set()); 587 trace!("read drop: stopping");
539 588
540 compiler_fence(Ordering::SeqCst); 589 self.timer.stop();
541 590
542 trace!("startrx"); 591 r.intenclr.write(|w| w.endrx().clear());
543 r.tasks_startrx.write(|w| unsafe { w.bits(1) }); 592 r.events_rxto.reset();
593 r.tasks_stoprx.write(|w| unsafe { w.bits(1) });
544 594
545 poll_fn(|cx| { 595 while r.events_endrx.read().bits() == 0 {}
546 s.endrx_waker.register(cx.waker());
547 if r.events_endrx.read().bits() != 0 {
548 return Poll::Ready(());
549 }
550 Poll::Pending
551 })
552 .await;
553 596
554 compiler_fence(Ordering::SeqCst); 597 trace!("read drop: stopped");
555 let n = r.rxd.amount.read().amount().bits() as usize; 598 });
556 599
557 // Stop timer 600 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
558 self.timer.stop(); 601 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
559 r.events_rxstarted.reset();
560 602
561 drop.defuse(); 603 r.events_endrx.reset();
604 r.intenset.write(|w| w.endrx().set());
562 605
563 Ok(n) 606 compiler_fence(Ordering::SeqCst);
564 } 607
608 r.tasks_startrx.write(|w| unsafe { w.bits(1) });
609
610 poll_fn(|cx| {
611 s.endrx_waker.register(cx.waker());
612 if r.events_endrx.read().bits() != 0 {
613 return Poll::Ready(());
614 }
615 Poll::Pending
616 })
617 .await;
618
619 compiler_fence(Ordering::SeqCst);
620 let n = r.rxd.amount.read().amount().bits() as usize;
621
622 self.timer.stop();
623 r.events_rxstarted.reset();
624
625 drop.defuse();
626
627 Ok(n)
565 } 628 }
566}
567 629
568impl<'d, U: Instance, T: TimerInstance> Read for UarteWithIdle<'d, U, T> { 630 pub fn blocking_read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
569 type ReadFuture<'a> 631 if buffer.len() == 0 {
570 where 632 return Err(Error::BufferZeroLength);
571 Self: 'a,
572 = impl Future<Output = Result<(), TraitError>> + 'a;
573 fn read<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
574 async move {
575 self.ppi_ch1.disable();
576 let result = self.uarte.read(rx_buffer).await;
577 self.ppi_ch1.enable();
578 result
579 } 633 }
580 } 634 if buffer.len() > EASY_DMA_SIZE {
581} 635 return Err(Error::BufferTooLong);
636 }
637
638 let ptr = buffer.as_ptr();
639 let len = buffer.len();
640
641 let r = U::regs();
642
643 self.ppi_ch1.enable();
644
645 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
646 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
647
648 r.events_endrx.reset();
649 r.intenclr.write(|w| w.endrx().clear());
650
651 compiler_fence(Ordering::SeqCst);
652
653 r.tasks_startrx.write(|w| unsafe { w.bits(1) });
582 654
583impl<'d, U: Instance, T: TimerInstance> Write for UarteWithIdle<'d, U, T> { 655 while r.events_endrx.read().bits() == 0 {}
584 type WriteFuture<'a>
585 where
586 Self: 'a,
587 = impl Future<Output = Result<(), TraitError>> + 'a;
588 656
589 fn write<'a>(&'a mut self, tx_buffer: &'a [u8]) -> Self::WriteFuture<'a> { 657 compiler_fence(Ordering::SeqCst);
590 self.uarte.write(tx_buffer) 658 let n = r.rxd.amount.read().amount().bits() as usize;
659
660 self.timer.stop();
661 r.events_rxstarted.reset();
662
663 Ok(n)
591 } 664 }
592} 665}
593 666
@@ -639,3 +712,206 @@ macro_rules! impl_uarte {
639 } 712 }
640 }; 713 };
641} 714}
715
716// ====================
717
718mod eh02 {
719 use super::*;
720
721 impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> for Uarte<'d, T> {
722 type Error = Error;
723
724 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
725 self.blocking_write(buffer)
726 }
727
728 fn bflush(&mut self) -> Result<(), Self::Error> {
729 Ok(())
730 }
731 }
732
733 impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> for UarteTx<'d, T> {
734 type Error = Error;
735
736 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
737 self.blocking_write(buffer)
738 }
739
740 fn bflush(&mut self) -> Result<(), Self::Error> {
741 Ok(())
742 }
743 }
744
745 impl<'d, U: Instance, T: TimerInstance> embedded_hal_02::blocking::serial::Write<u8>
746 for UarteWithIdle<'d, U, T>
747 {
748 type Error = Error;
749
750 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
751 self.blocking_write(buffer)
752 }
753
754 fn bflush(&mut self) -> Result<(), Self::Error> {
755 Ok(())
756 }
757 }
758}
759
760#[cfg(feature = "unstable-traits")]
761mod eh1 {
762 use super::*;
763 use core::future::Future;
764
765 impl embedded_hal_1::serial::Error for Error {
766 fn kind(&self) -> embedded_hal_1::serial::ErrorKind {
767 match *self {
768 Self::BufferTooLong => embedded_hal_1::serial::ErrorKind::Other,
769 Self::BufferZeroLength => embedded_hal_1::serial::ErrorKind::Other,
770 Self::DMABufferNotInDataMemory => embedded_hal_1::serial::ErrorKind::Other,
771 }
772 }
773 }
774
775 // =====================
776
777 impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for Uarte<'d, T> {
778 type Error = Error;
779 }
780
781 impl<'d, T: Instance> embedded_hal_1::serial::blocking::Write for Uarte<'d, T> {
782 fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
783 self.blocking_write(buffer)
784 }
785
786 fn flush(&mut self) -> Result<(), Self::Error> {
787 Ok(())
788 }
789 }
790
791 impl<'d, T: Instance> embedded_hal_async::serial::Read for Uarte<'d, T> {
792 type ReadFuture<'a>
793 where
794 Self: 'a,
795 = impl Future<Output = Result<(), Self::Error>> + 'a;
796
797 fn read<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
798 self.read(buffer)
799 }
800 }
801
802 impl<'d, T: Instance> embedded_hal_async::serial::Write for Uarte<'d, T> {
803 type WriteFuture<'a>
804 where
805 Self: 'a,
806 = impl Future<Output = Result<(), Self::Error>> + 'a;
807
808 fn write<'a>(&'a mut self, buffer: &'a [u8]) -> Self::WriteFuture<'a> {
809 self.write(buffer)
810 }
811
812 type FlushFuture<'a>
813 where
814 Self: 'a,
815 = impl Future<Output = Result<(), Self::Error>> + 'a;
816
817 fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
818 async move { Ok(()) }
819 }
820 }
821
822 // =====================
823
824 impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for UarteTx<'d, T> {
825 type Error = Error;
826 }
827
828 impl<'d, T: Instance> embedded_hal_1::serial::blocking::Write for UarteTx<'d, T> {
829 fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
830 self.blocking_write(buffer)
831 }
832
833 fn flush(&mut self) -> Result<(), Self::Error> {
834 Ok(())
835 }
836 }
837
838 impl<'d, T: Instance> embedded_hal_async::serial::Write for UarteTx<'d, T> {
839 type WriteFuture<'a>
840 where
841 Self: 'a,
842 = impl Future<Output = Result<(), Self::Error>> + 'a;
843
844 fn write<'a>(&'a mut self, buffer: &'a [u8]) -> Self::WriteFuture<'a> {
845 self.write(buffer)
846 }
847
848 type FlushFuture<'a>
849 where
850 Self: 'a,
851 = impl Future<Output = Result<(), Self::Error>> + 'a;
852
853 fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
854 async move { Ok(()) }
855 }
856 }
857
858 // =====================
859
860 impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for UarteRx<'d, T> {
861 type Error = Error;
862 }
863
864 impl<'d, T: Instance> embedded_hal_async::serial::Read for UarteRx<'d, T> {
865 type ReadFuture<'a>
866 where
867 Self: 'a,
868 = impl Future<Output = Result<(), Self::Error>> + 'a;
869
870 fn read<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
871 self.read(buffer)
872 }
873 }
874
875 // =====================
876
877 impl<'d, U: Instance, T: TimerInstance> embedded_hal_1::serial::ErrorType
878 for UarteWithIdle<'d, U, T>
879 {
880 type Error = Error;
881 }
882
883 impl<'d, U: Instance, T: TimerInstance> embedded_hal_async::serial::Read
884 for UarteWithIdle<'d, U, T>
885 {
886 type ReadFuture<'a>
887 where
888 Self: 'a,
889 = impl Future<Output = Result<(), Self::Error>> + 'a;
890
891 fn read<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
892 self.read(buffer)
893 }
894 }
895
896 impl<'d, U: Instance, T: TimerInstance> embedded_hal_async::serial::Write
897 for UarteWithIdle<'d, U, T>
898 {
899 type WriteFuture<'a>
900 where
901 Self: 'a,
902 = impl Future<Output = Result<(), Self::Error>> + 'a;
903
904 fn write<'a>(&'a mut self, buffer: &'a [u8]) -> Self::WriteFuture<'a> {
905 self.write(buffer)
906 }
907
908 type FlushFuture<'a>
909 where
910 Self: 'a,
911 = impl Future<Output = Result<(), Self::Error>> + 'a;
912
913 fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
914 async move { Ok(()) }
915 }
916 }
917}
diff --git a/embassy-nrf/src/util.rs b/embassy-nrf/src/util.rs
index 2fd0bc5a8..76162b701 100644
--- a/embassy-nrf/src/util.rs
+++ b/embassy-nrf/src/util.rs
@@ -1,16 +1,28 @@
1use core::mem;
2
1const SRAM_LOWER: usize = 0x2000_0000; 3const SRAM_LOWER: usize = 0x2000_0000;
2const SRAM_UPPER: usize = 0x3000_0000; 4const SRAM_UPPER: usize = 0x3000_0000;
3 5
6// TODO: replace transmutes with core::ptr::metadata once it's stable
7
8pub(crate) fn slice_ptr_parts<T>(slice: *const [T]) -> (usize, usize) {
9 unsafe { mem::transmute(slice) }
10}
11
12pub(crate) fn slice_ptr_parts_mut<T>(slice: *mut [T]) -> (usize, usize) {
13 unsafe { mem::transmute(slice) }
14}
15
4/// Does this slice reside entirely within RAM? 16/// Does this slice reside entirely within RAM?
5pub(crate) fn slice_in_ram<T>(slice: &[T]) -> bool { 17pub(crate) fn slice_in_ram<T>(slice: *const [T]) -> bool {
6 let ptr = slice.as_ptr() as usize; 18 let (ptr, len) = slice_ptr_parts(slice);
7 ptr >= SRAM_LOWER && (ptr + slice.len() * core::mem::size_of::<T>()) < SRAM_UPPER 19 ptr >= SRAM_LOWER && (ptr + len * core::mem::size_of::<T>()) < SRAM_UPPER
8} 20}
9 21
10/// Return an error if slice is not in RAM. 22/// Return an error if slice is not in RAM.
11#[cfg(not(feature = "nrf51"))] 23#[cfg(not(feature = "nrf51"))]
12pub(crate) fn slice_in_ram_or<T, E>(slice: &[T], err: E) -> Result<(), E> { 24pub(crate) fn slice_in_ram_or<T, E>(slice: *const [T], err: E) -> Result<(), E> {
13 if slice.is_empty() || slice_in_ram(slice) { 25 if slice_in_ram(slice) {
14 Ok(()) 26 Ok(())
15 } else { 27 } else {
16 Err(err) 28 Err(err)
diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml
index ca013f8b7..fa7286923 100644
--- a/examples/nrf/Cargo.toml
+++ b/examples/nrf/Cargo.toml
@@ -15,7 +15,6 @@ defmt-rtt = "0.3"
15 15
16cortex-m = "0.7.3" 16cortex-m = "0.7.3"
17cortex-m-rt = "0.7.0" 17cortex-m-rt = "0.7.0"
18embedded-hal = "0.2.6"
19panic-probe = { version = "0.3", features = ["print-defmt"] } 18panic-probe = { version = "0.3", features = ["print-defmt"] }
20futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 19futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
21rand = { version = "0.8.4", default-features = false } 20rand = { version = "0.8.4", default-features = false }
diff --git a/examples/nrf/src/bin/gpiote_port.rs b/examples/nrf/src/bin/gpiote_port.rs
index 76c861d95..3ea9a6e67 100644
--- a/examples/nrf/src/bin/gpiote_port.rs
+++ b/examples/nrf/src/bin/gpiote_port.rs
@@ -6,7 +6,6 @@
6mod example_common; 6mod example_common;
7 7
8use embassy::executor::Spawner; 8use embassy::executor::Spawner;
9use embassy::traits::gpio::{WaitForHigh, WaitForLow};
10use embassy_nrf::gpio::{AnyPin, Input, Pin as _, Pull}; 9use embassy_nrf::gpio::{AnyPin, Input, Pin as _, Pull};
11use embassy_nrf::Peripherals; 10use embassy_nrf::Peripherals;
12use example_common::*; 11use example_common::*;
diff --git a/examples/nrf/src/bin/qspi.rs b/examples/nrf/src/bin/qspi.rs
index c7f9503bb..b2e6bfc15 100644
--- a/examples/nrf/src/bin/qspi.rs
+++ b/examples/nrf/src/bin/qspi.rs
@@ -7,7 +7,6 @@ mod example_common;
7 7
8use defmt::assert_eq; 8use defmt::assert_eq;
9use embassy::executor::Spawner; 9use embassy::executor::Spawner;
10use embassy::traits::flash::Flash;
11use embassy_nrf::Peripherals; 10use embassy_nrf::Peripherals;
12use embassy_nrf::{interrupt, qspi}; 11use embassy_nrf::{interrupt, qspi};
13use example_common::*; 12use example_common::*;
diff --git a/examples/nrf/src/bin/qspi_lowpower.rs b/examples/nrf/src/bin/qspi_lowpower.rs
index e9e1bac42..4e264ef2f 100644
--- a/examples/nrf/src/bin/qspi_lowpower.rs
+++ b/examples/nrf/src/bin/qspi_lowpower.rs
@@ -8,7 +8,6 @@ mod example_common;
8use core::mem; 8use core::mem;
9use embassy::executor::Spawner; 9use embassy::executor::Spawner;
10use embassy::time::{Duration, Timer}; 10use embassy::time::{Duration, Timer};
11use embassy::traits::flash::Flash;
12use embassy_nrf::Peripherals; 11use embassy_nrf::Peripherals;
13use embassy_nrf::{interrupt, qspi}; 12use embassy_nrf::{interrupt, qspi};
14use example_common::*; 13use example_common::*;
diff --git a/examples/nrf/src/bin/rng.rs b/examples/nrf/src/bin/rng.rs
index 2f1a26993..a35a9fa85 100644
--- a/examples/nrf/src/bin/rng.rs
+++ b/examples/nrf/src/bin/rng.rs
@@ -5,9 +5,7 @@
5#[path = "../example_common.rs"] 5#[path = "../example_common.rs"]
6mod example_common; 6mod example_common;
7 7
8use defmt::unwrap;
9use embassy::executor::Spawner; 8use embassy::executor::Spawner;
10use embassy::traits::rng::Rng as _;
11use embassy_nrf::interrupt; 9use embassy_nrf::interrupt;
12use embassy_nrf::rng::Rng; 10use embassy_nrf::rng::Rng;
13use embassy_nrf::Peripherals; 11use embassy_nrf::Peripherals;
@@ -19,14 +17,14 @@ async fn main(_spawner: Spawner, p: Peripherals) {
19 17
20 // Async API 18 // Async API
21 let mut bytes = [0; 4]; 19 let mut bytes = [0; 4];
22 unwrap!(rng.fill_bytes(&mut bytes).await); // nRF RNG is infallible 20 rng.fill_bytes(&mut bytes).await;
23 defmt::info!("Some random bytes: {:?}", bytes); 21 defmt::info!("Some random bytes: {:?}", bytes);
24 22
25 // Sync API with `rand` 23 // Sync API with `rand`
26 defmt::info!("A random number from 1 to 10: {:?}", rng.gen_range(1..=10)); 24 defmt::info!("A random number from 1 to 10: {:?}", rng.gen_range(1..=10));
27 25
28 let mut bytes = [0; 1024]; 26 let mut bytes = [0; 1024];
29 unwrap!(rng.fill_bytes(&mut bytes).await); 27 rng.fill_bytes(&mut bytes).await;
30 let zero_count: u32 = bytes.iter().fold(0, |acc, val| acc + val.count_zeros()); 28 let zero_count: u32 = bytes.iter().fold(0, |acc, val| acc + val.count_zeros());
31 let one_count: u32 = bytes.iter().fold(0, |acc, val| acc + val.count_ones()); 29 let one_count: u32 = bytes.iter().fold(0, |acc, val| acc + val.count_ones());
32 defmt::info!( 30 defmt::info!(
diff --git a/examples/nrf/src/bin/spim.rs b/examples/nrf/src/bin/spim.rs
index fc31d140a..cda3baa26 100644
--- a/examples/nrf/src/bin/spim.rs
+++ b/examples/nrf/src/bin/spim.rs
@@ -9,7 +9,6 @@ use embassy::executor::Spawner;
9use embassy_nrf::gpio::{Level, Output, OutputDrive}; 9use embassy_nrf::gpio::{Level, Output, OutputDrive};
10use embassy_nrf::Peripherals; 10use embassy_nrf::Peripherals;
11use embassy_nrf::{interrupt, spim}; 11use embassy_nrf::{interrupt, spim};
12use embassy_traits::spi::FullDuplex;
13use example_common::*; 12use example_common::*;
14 13
15#[embassy::main] 14#[embassy::main]
@@ -31,7 +30,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
31 ncs.set_low(); 30 ncs.set_low();
32 cortex_m::asm::delay(5); 31 cortex_m::asm::delay(5);
33 let tx = [0xFF]; 32 let tx = [0xFF];
34 unwrap!(spim.read_write(&mut [], &tx).await); 33 unwrap!(spim.transfer(&mut [], &tx).await);
35 cortex_m::asm::delay(10); 34 cortex_m::asm::delay(10);
36 ncs.set_high(); 35 ncs.set_high();
37 36
@@ -44,7 +43,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
44 ncs.set_low(); 43 ncs.set_low();
45 cortex_m::asm::delay(5000); 44 cortex_m::asm::delay(5000);
46 let tx = [0b000_11101, 0]; 45 let tx = [0b000_11101, 0];
47 unwrap!(spim.read_write(&mut rx, &tx).await); 46 unwrap!(spim.transfer(&mut rx, &tx).await);
48 cortex_m::asm::delay(5000); 47 cortex_m::asm::delay(5000);
49 ncs.set_high(); 48 ncs.set_high();
50 info!("estat: {=[?]}", rx); 49 info!("estat: {=[?]}", rx);
@@ -54,7 +53,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
54 ncs.set_low(); 53 ncs.set_low();
55 cortex_m::asm::delay(5); 54 cortex_m::asm::delay(5);
56 let tx = [0b100_11111, 0b11]; 55 let tx = [0b100_11111, 0b11];
57 unwrap!(spim.read_write(&mut rx, &tx).await); 56 unwrap!(spim.transfer(&mut rx, &tx).await);
58 cortex_m::asm::delay(10); 57 cortex_m::asm::delay(10);
59 ncs.set_high(); 58 ncs.set_high();
60 59
@@ -63,7 +62,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
63 ncs.set_low(); 62 ncs.set_low();
64 cortex_m::asm::delay(5); 63 cortex_m::asm::delay(5);
65 let tx = [0b000_10010, 0]; 64 let tx = [0b000_10010, 0];
66 unwrap!(spim.read_write(&mut rx, &tx).await); 65 unwrap!(spim.transfer(&mut rx, &tx).await);
67 cortex_m::asm::delay(10); 66 cortex_m::asm::delay(10);
68 ncs.set_high(); 67 ncs.set_high();
69 68
diff --git a/examples/nrf/src/bin/twim.rs b/examples/nrf/src/bin/twim.rs
index 4c2f2bf2e..1ac3a3945 100644
--- a/examples/nrf/src/bin/twim.rs
+++ b/examples/nrf/src/bin/twim.rs
@@ -26,7 +26,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
26 info!("Reading..."); 26 info!("Reading...");
27 27
28 let mut buf = [0u8; 16]; 28 let mut buf = [0u8; 16];
29 unwrap!(twi.write_then_read(ADDRESS, &mut [0x00], &mut buf)); 29 unwrap!(twi.blocking_write_read(ADDRESS, &mut [0x00], &mut buf));
30 30
31 info!("Read: {=[u8]:x}", buf); 31 info!("Read: {=[u8]:x}", buf);
32} 32}
diff --git a/examples/nrf/src/bin/twim_lowpower.rs b/examples/nrf/src/bin/twim_lowpower.rs
index 62a5f0c94..4a0596437 100644
--- a/examples/nrf/src/bin/twim_lowpower.rs
+++ b/examples/nrf/src/bin/twim_lowpower.rs
@@ -36,7 +36,7 @@ async fn main(_spawner: Spawner, mut p: Peripherals) {
36 info!("Reading..."); 36 info!("Reading...");
37 37
38 let mut buf = [0u8; 16]; 38 let mut buf = [0u8; 16];
39 unwrap!(twi.write_then_read(ADDRESS, &mut [0x00], &mut buf)); 39 unwrap!(twi.blocking_write_read(ADDRESS, &mut [0x00], &mut buf));
40 40
41 info!("Read: {=[u8]:x}", buf); 41 info!("Read: {=[u8]:x}", buf);
42 42
diff --git a/examples/nrf/src/bin/uart.rs b/examples/nrf/src/bin/uart.rs
index 208961c8b..68ee3978a 100644
--- a/examples/nrf/src/bin/uart.rs
+++ b/examples/nrf/src/bin/uart.rs
@@ -7,7 +7,6 @@ mod example_common;
7use example_common::*; 7use example_common::*;
8 8
9use embassy::executor::Spawner; 9use embassy::executor::Spawner;
10use embassy::traits::uart::{Read, Write};
11use embassy_nrf::gpio::NoPin; 10use embassy_nrf::gpio::NoPin;
12use embassy_nrf::{interrupt, uarte, Peripherals}; 11use embassy_nrf::{interrupt, uarte, Peripherals};
13 12
diff --git a/examples/nrf/src/bin/uart_idle.rs b/examples/nrf/src/bin/uart_idle.rs
index ec9a36026..76449c0e3 100644
--- a/examples/nrf/src/bin/uart_idle.rs
+++ b/examples/nrf/src/bin/uart_idle.rs
@@ -4,11 +4,9 @@
4 4
5#[path = "../example_common.rs"] 5#[path = "../example_common.rs"]
6mod example_common; 6mod example_common;
7use embassy_traits::uart::ReadUntilIdle;
8use example_common::*; 7use example_common::*;
9 8
10use embassy::executor::Spawner; 9use embassy::executor::Spawner;
11use embassy::traits::uart::Write;
12use embassy_nrf::gpio::NoPin; 10use embassy_nrf::gpio::NoPin;
13use embassy_nrf::{interrupt, uarte, Peripherals}; 11use embassy_nrf::{interrupt, uarte, Peripherals};
14 12
@@ -19,11 +17,9 @@ async fn main(_spawner: Spawner, p: Peripherals) {
19 config.baudrate = uarte::Baudrate::BAUD115200; 17 config.baudrate = uarte::Baudrate::BAUD115200;
20 18
21 let irq = interrupt::take!(UARTE0_UART0); 19 let irq = interrupt::take!(UARTE0_UART0);
22 let mut uart = unsafe { 20 let mut uart = uarte::UarteWithIdle::new(
23 uarte::UarteWithIdle::new( 21 p.UARTE0, p.TIMER0, p.PPI_CH0, p.PPI_CH1, irq, p.P0_08, p.P0_06, NoPin, NoPin, config,
24 p.UARTE0, p.TIMER0, p.PPI_CH0, p.PPI_CH1, irq, p.P0_08, p.P0_06, NoPin, NoPin, config, 22 );
25 )
26 };
27 23
28 info!("uarte initialized!"); 24 info!("uarte initialized!");
29 25
diff --git a/examples/nrf/src/bin/uart_split.rs b/examples/nrf/src/bin/uart_split.rs
index 4b5dbb21f..a9c02e796 100644
--- a/examples/nrf/src/bin/uart_split.rs
+++ b/examples/nrf/src/bin/uart_split.rs
@@ -4,16 +4,15 @@
4 4
5#[path = "../example_common.rs"] 5#[path = "../example_common.rs"]
6mod example_common; 6mod example_common;
7use example_common::*;
8
7use embassy::blocking_mutex::kind::Noop; 9use embassy::blocking_mutex::kind::Noop;
8use embassy::channel::mpsc::{self, Channel, Sender}; 10use embassy::channel::mpsc::{self, Channel, Sender};
11use embassy::executor::Spawner;
9use embassy::util::Forever; 12use embassy::util::Forever;
13use embassy_nrf::gpio::NoPin;
10use embassy_nrf::peripherals::UARTE0; 14use embassy_nrf::peripherals::UARTE0;
11use embassy_nrf::uarte::UarteRx; 15use embassy_nrf::uarte::UarteRx;
12use example_common::*;
13
14use embassy::executor::Spawner;
15use embassy::traits::uart::{Read, Write};
16use embassy_nrf::gpio::NoPin;
17use embassy_nrf::{interrupt, uarte, Peripherals}; 16use embassy_nrf::{interrupt, uarte, Peripherals};
18 17
19static CHANNEL: Forever<Channel<Noop, [u8; 8], 1>> = Forever::new(); 18static CHANNEL: Forever<Channel<Noop, [u8; 8], 1>> = Forever::new();
diff --git a/examples/nrf/src/bin/wdt.rs b/examples/nrf/src/bin/wdt.rs
index 78c2205d9..cc199be9d 100644
--- a/examples/nrf/src/bin/wdt.rs
+++ b/examples/nrf/src/bin/wdt.rs
@@ -10,7 +10,6 @@ use embassy::executor::Spawner;
10use embassy_nrf::gpio::{Input, Pull}; 10use embassy_nrf::gpio::{Input, Pull};
11use embassy_nrf::wdt::{Config, Watchdog}; 11use embassy_nrf::wdt::{Config, Watchdog};
12use embassy_nrf::Peripherals; 12use embassy_nrf::Peripherals;
13use embassy_traits::gpio::{WaitForHigh, WaitForLow};
14 13
15#[embassy::main] 14#[embassy::main]
16async fn main(_spawner: Spawner, p: Peripherals) { 15async fn main(_spawner: Spawner, p: Peripherals) {