aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFolkert <[email protected]>2021-06-04 17:31:35 +0200
committerFolkert <[email protected]>2021-06-04 17:31:35 +0200
commit857ac3386bf13af1eeb9bf28b45b47b5169310e5 (patch)
treed0b3e2c1de7c1d5e272e510f1a31bdb45c4c5b73
parentcd44b221ed558689a20090771228c703e56e3371 (diff)
nrf async twim
-rw-r--r--embassy-nrf/src/twim.rs113
-rw-r--r--embassy-traits/src/i2c.rs20
2 files changed, 126 insertions, 7 deletions
diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs
index ea3ac7553..6a7149044 100644
--- a/embassy-nrf/src/twim.rs
+++ b/embassy-nrf/src/twim.rs
@@ -6,11 +6,16 @@
6//! 6//!
7//! - nRF52832: Section 33 7//! - nRF52832: Section 33
8//! - nRF52840: Section 6.31 8//! - nRF52840: Section 6.31
9use core::future::Future;
9use core::marker::PhantomData; 10use core::marker::PhantomData;
10use core::sync::atomic::{compiler_fence, Ordering::SeqCst}; 11use core::sync::atomic::{compiler_fence, Ordering::SeqCst};
12use core::task::Poll;
11use embassy::interrupt::{Interrupt, InterruptExt}; 13use embassy::interrupt::{Interrupt, InterruptExt};
14use embassy::traits;
12use embassy::util::{AtomicWaker, Unborrow}; 15use embassy::util::{AtomicWaker, Unborrow};
13use embassy_extras::unborrow; 16use embassy_extras::unborrow;
17use futures::future::poll_fn;
18use traits::i2c::I2c;
14 19
15use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; 20use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
16use crate::gpio::Pin as GpioPin; 21use crate::gpio::Pin as GpioPin;
@@ -437,6 +442,114 @@ impl<'a, T: Instance> Drop for Twim<'a, T> {
437 } 442 }
438} 443}
439 444
445impl<'d, T> I2c for Twim<'d, T>
446where
447 T: Instance,
448{
449 type Error = Error;
450
451 #[rustfmt::skip]
452 type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
453 #[rustfmt::skip]
454 type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
455 #[rustfmt::skip]
456 type WriteReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
457
458 fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
459 self.write_read(address, &[], buffer)
460 }
461
462 fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Self::WriteFuture<'a> {
463 self.write_read(address, bytes, &mut [])
464 }
465
466 fn write_read<'a>(
467 &'a mut self,
468 address: u8,
469 bytes: &'a [u8],
470 buffer: &'a mut [u8],
471 ) -> Self::WriteReadFuture<'a> {
472 async move {
473 slice_in_ram_or(bytes, Error::DMABufferNotInDataMemory)?;
474 // NOTE: RAM slice check for buffer is not necessary, as a mutable
475 // slice can only be built from data located in RAM.
476
477 // Conservative compiler fence to prevent optimizations that do not
478 // take in to account actions by DMA. The fence has been placed here,
479 // before any DMA action has started.
480 compiler_fence(SeqCst);
481
482 let r = T::regs();
483 let s = T::state();
484
485 // Set up current address we're trying to talk to
486 r.address.write(|w| unsafe { w.address().bits(address) });
487
488 // Set up DMA buffers.
489 unsafe {
490 self.set_tx_buffer(bytes)?;
491 self.set_rx_buffer(buffer)?;
492 }
493
494 // Reset and enable the events
495 r.events_stopped.reset();
496 r.events_error.reset();
497 r.events_lasttx.reset();
498 self.clear_errorsrc();
499
500 r.intenset.write(|w| w.stopped().set());
501 r.intenset.write(|w| w.error().set());
502 r.intenset.write(|w| w.lasttx().set());
503
504 // Start write+read operation.
505 r.shorts.write(|w| {
506 w.lasttx_startrx().enabled();
507 w.lastrx_stop().enabled();
508 w
509 });
510 // `1` is a valid value to write to task registers.
511 r.tasks_starttx.write(|w| unsafe { w.bits(1) });
512
513 // Conservative compiler fence to prevent optimizations that do not
514 // take in to account actions by DMA. The fence has been placed here,
515 // after all possible DMA actions have completed.
516 compiler_fence(SeqCst);
517
518 // Wait for 'stopped' event.
519 poll_fn(|cx| {
520 s.end_waker.register(cx.waker());
521 if r.events_stopped.read().bits() != 0 {
522 r.events_stopped.reset();
523
524 return Poll::Ready(());
525 }
526
527 // stop if an error occured
528 if r.events_error.read().bits() != 0 {
529 r.events_error.reset();
530 r.tasks_stop.write(|w| unsafe { w.bits(1) });
531 }
532
533 Poll::Pending
534 })
535 .await;
536
537 let bad_write = r.txd.amount.read().bits() != bytes.len() as u32;
538 let bad_read = r.rxd.amount.read().bits() != buffer.len() as u32;
539
540 if bad_write {
541 return Err(Error::TxBufferTooLong);
542 }
543
544 if bad_read {
545 return Err(Error::RxBufferTooLong);
546 }
547
548 Ok(())
549 }
550 }
551}
552
440impl<'a, T: Instance> embedded_hal::blocking::i2c::Write for Twim<'a, T> { 553impl<'a, T: Instance> embedded_hal::blocking::i2c::Write for Twim<'a, T> {
441 type Error = Error; 554 type Error = Error;
442 555
diff --git a/embassy-traits/src/i2c.rs b/embassy-traits/src/i2c.rs
index abe932d9c..e426a00b0 100644
--- a/embassy-traits/src/i2c.rs
+++ b/embassy-traits/src/i2c.rs
@@ -94,9 +94,15 @@ pub trait I2c<A: AddressMode = SevenBitAddress> {
94 /// Error type 94 /// Error type
95 type Error; 95 type Error;
96 96
97 type ReadFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a; 97 type WriteFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a
98 type WriteFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a; 98 where
99 type WriteReadFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a; 99 Self: 'a;
100 type ReadFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a
101 where
102 Self: 'a;
103 type WriteReadFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a
104 where
105 Self: 'a;
100 106
101 /// Reads enough bytes from slave with `address` to fill `buffer` 107 /// Reads enough bytes from slave with `address` to fill `buffer`
102 /// 108 ///
@@ -116,7 +122,7 @@ pub trait I2c<A: AddressMode = SevenBitAddress> {
116 /// - `MAK` = master acknowledge 122 /// - `MAK` = master acknowledge
117 /// - `NMAK` = master no acknowledge 123 /// - `NMAK` = master no acknowledge
118 /// - `SP` = stop condition 124 /// - `SP` = stop condition
119 fn read<'a>(&'a mut self, address: A, buffer: &mut [u8]) -> Self::ReadFuture<'a>; 125 fn read<'a>(&'a mut self, address: A, buffer: &'a mut [u8]) -> Self::ReadFuture<'a>;
120 126
121 /// Sends bytes to slave with address `address` 127 /// Sends bytes to slave with address `address`
122 /// 128 ///
@@ -134,7 +140,7 @@ pub trait I2c<A: AddressMode = SevenBitAddress> {
134 /// - `SAK` = slave acknowledge 140 /// - `SAK` = slave acknowledge
135 /// - `Bi` = ith byte of data 141 /// - `Bi` = ith byte of data
136 /// - `SP` = stop condition 142 /// - `SP` = stop condition
137 fn write<'a>(&'a mut self, address: A, bytes: &[u8]) -> Self::WriteFuture<'a>; 143 fn write<'a>(&'a mut self, address: A, bytes: &'a [u8]) -> Self::WriteFuture<'a>;
138 144
139 /// Sends bytes to slave with address `address` and then reads enough bytes to fill `buffer` *in a 145 /// Sends bytes to slave with address `address` and then reads enough bytes to fill `buffer` *in a
140 /// single transaction* 146 /// single transaction*
@@ -161,7 +167,7 @@ pub trait I2c<A: AddressMode = SevenBitAddress> {
161 fn write_read<'a>( 167 fn write_read<'a>(
162 &'a mut self, 168 &'a mut self,
163 address: A, 169 address: A,
164 bytes: &[u8], 170 bytes: &'a [u8],
165 buffer: &mut [u8], 171 buffer: &'a mut [u8],
166 ) -> Self::WriteReadFuture<'a>; 172 ) -> Self::WriteReadFuture<'a>;
167} 173}