aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-06-05 16:34:36 +0200
committerGitHub <[email protected]>2021-06-05 16:34:36 +0200
commit5bd0aa9cb5bfb26122dc2f7755abd14975fadb31 (patch)
tree22637b57ece2a3a240800db0d853b7c4f8e49c0c
parent6f5c85c50f20fa336d2144c8161aea391bea52f7 (diff)
parent749633ddf2b5022f61cbba9350ce4d09f6b25691 (diff)
Merge pull request #222 from folkertdev/nrf-async-twim
nrf async twim
-rw-r--r--embassy-nrf/src/spim.rs3
-rw-r--r--embassy-nrf/src/twim.rs210
-rw-r--r--embassy-traits/src/i2c.rs20
3 files changed, 225 insertions, 8 deletions
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs
index 0ca18d88c..b5e9afbc1 100644
--- a/embassy-nrf/src/spim.rs
+++ b/embassy-nrf/src/spim.rs
@@ -196,8 +196,9 @@ impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> {
196 196
197 fn read_write<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Self::WriteReadFuture<'a> { 197 fn read_write<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Self::WriteReadFuture<'a> {
198 async move { 198 async move {
199 slice_in_ram_or(rx, Error::DMABufferNotInDataMemory)?;
200 slice_in_ram_or(tx, Error::DMABufferNotInDataMemory)?; 199 slice_in_ram_or(tx, Error::DMABufferNotInDataMemory)?;
200 // NOTE: RAM slice check for rx is not necessary, as a mutable
201 // slice can only be built from data located in RAM.
201 202
202 // Conservative compiler fence to prevent optimizations that do not 203 // Conservative compiler fence to prevent optimizations that do not
203 // take in to account actions by DMA. The fence has been placed here, 204 // take in to account actions by DMA. The fence has been placed here,
diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs
index ea3ac7553..160868d7d 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;
@@ -418,6 +423,26 @@ impl<'d, T: Instance> Twim<'d, T> {
418 423
419 self.write_then_read(address, wr_ram_buffer, rd_buffer) 424 self.write_then_read(address, wr_ram_buffer, rd_buffer)
420 } 425 }
426
427 fn wait_for_stopped_event(cx: &mut core::task::Context) -> Poll<()> {
428 let r = T::regs();
429 let s = T::state();
430
431 s.end_waker.register(cx.waker());
432 if r.events_stopped.read().bits() != 0 {
433 r.events_stopped.reset();
434
435 return Poll::Ready(());
436 }
437
438 // stop if an error occured
439 if r.events_error.read().bits() != 0 {
440 r.events_error.reset();
441 r.tasks_stop.write(|w| unsafe { w.bits(1) });
442 }
443
444 Poll::Pending
445 }
421} 446}
422 447
423impl<'a, T: Instance> Drop for Twim<'a, T> { 448impl<'a, T: Instance> Drop for Twim<'a, T> {
@@ -437,6 +462,191 @@ impl<'a, T: Instance> Drop for Twim<'a, T> {
437 } 462 }
438} 463}
439 464
465impl<'d, T> I2c for Twim<'d, T>
466where
467 T: Instance,
468{
469 type Error = Error;
470
471 #[rustfmt::skip]
472 type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
473 #[rustfmt::skip]
474 type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
475 #[rustfmt::skip]
476 type WriteReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
477
478 fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
479 async move {
480 // NOTE: RAM slice check for buffer is not necessary, as a mutable
481 // slice can only be built from data located in RAM.
482
483 let r = T::regs();
484
485 // Conservative compiler fence to prevent optimizations that do not
486 // take in to account actions by DMA. The fence has been placed here,
487 // before any DMA action has started.
488 compiler_fence(SeqCst);
489
490 r.address.write(|w| unsafe { w.address().bits(address) });
491
492 // Set up the DMA read.
493 unsafe { self.set_rx_buffer(buffer)? };
494
495 // Reset events
496 r.events_stopped.reset();
497 r.events_error.reset();
498 self.clear_errorsrc();
499
500 // Enable events
501 r.intenset.write(|w| w.stopped().set().error().set());
502
503 // Start read operation.
504 r.shorts.write(|w| w.lastrx_stop().enabled());
505 r.tasks_startrx.write(|w|
506 // `1` is a valid value to write to task registers.
507 unsafe { w.bits(1) });
508
509 // Conservative compiler fence to prevent optimizations that do not
510 // take in to account actions by DMA. The fence has been placed here,
511 // after all possible DMA actions have completed.
512 compiler_fence(SeqCst);
513
514 // Wait for 'stopped' event.
515 poll_fn(Self::wait_for_stopped_event).await;
516
517 self.read_errorsrc()?;
518
519 if r.rxd.amount.read().bits() != buffer.len() as u32 {
520 return Err(Error::Receive);
521 }
522
523 Ok(())
524 }
525 }
526
527 fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Self::WriteFuture<'a> {
528 async move {
529 slice_in_ram_or(bytes, Error::DMABufferNotInDataMemory)?;
530
531 // Conservative compiler fence to prevent optimizations that do not
532 // take in to account actions by DMA. The fence has been placed here,
533 // before any DMA action has started.
534 compiler_fence(SeqCst);
535
536 let r = T::regs();
537
538 // Set up current address we're trying to talk to
539 r.address.write(|w| unsafe { w.address().bits(address) });
540
541 // Set up DMA write.
542 unsafe {
543 self.set_tx_buffer(bytes)?;
544 }
545
546 // Reset events
547 r.events_stopped.reset();
548 r.events_error.reset();
549 r.events_lasttx.reset();
550 self.clear_errorsrc();
551
552 // Enable events
553 r.intenset.write(|w| w.stopped().set().error().set());
554
555 // Start write operation.
556 r.shorts.write(|w| w.lasttx_stop().enabled());
557 r.tasks_starttx.write(|w|
558 // `1` is a valid value to write to task registers.
559 unsafe { w.bits(1) });
560
561 // Conservative compiler fence to prevent optimizations that do not
562 // take in to account actions by DMA. The fence has been placed here,
563 // after all possible DMA actions have completed.
564 compiler_fence(SeqCst);
565
566 // Wait for 'stopped' event.
567 poll_fn(Self::wait_for_stopped_event).await;
568
569 self.read_errorsrc()?;
570
571 if r.txd.amount.read().bits() != bytes.len() as u32 {
572 return Err(Error::Transmit);
573 }
574
575 Ok(())
576 }
577 }
578
579 fn write_read<'a>(
580 &'a mut self,
581 address: u8,
582 bytes: &'a [u8],
583 buffer: &'a mut [u8],
584 ) -> Self::WriteReadFuture<'a> {
585 async move {
586 slice_in_ram_or(bytes, Error::DMABufferNotInDataMemory)?;
587 // NOTE: RAM slice check for buffer is not necessary, as a mutable
588 // slice can only be built from data located in RAM.
589
590 // Conservative compiler fence to prevent optimizations that do not
591 // take in to account actions by DMA. The fence has been placed here,
592 // before any DMA action has started.
593 compiler_fence(SeqCst);
594
595 let r = T::regs();
596
597 // Set up current address we're trying to talk to
598 r.address.write(|w| unsafe { w.address().bits(address) });
599
600 // Set up DMA buffers.
601 unsafe {
602 self.set_tx_buffer(bytes)?;
603 self.set_rx_buffer(buffer)?;
604 }
605
606 // Reset events
607 r.events_stopped.reset();
608 r.events_error.reset();
609 r.events_lasttx.reset();
610 self.clear_errorsrc();
611
612 // Enable events
613 r.intenset.write(|w| w.stopped().set().error().set());
614
615 // Start write+read operation.
616 r.shorts.write(|w| {
617 w.lasttx_startrx().enabled();
618 w.lastrx_stop().enabled();
619 w
620 });
621 // `1` is a valid value to write to task registers.
622 r.tasks_starttx.write(|w| unsafe { w.bits(1) });
623
624 // Conservative compiler fence to prevent optimizations that do not
625 // take in to account actions by DMA. The fence has been placed here,
626 // after all possible DMA actions have completed.
627 compiler_fence(SeqCst);
628
629 // Wait for 'stopped' event.
630 poll_fn(Self::wait_for_stopped_event).await;
631
632 self.read_errorsrc()?;
633
634 let bad_write = r.txd.amount.read().bits() != bytes.len() as u32;
635 let bad_read = r.rxd.amount.read().bits() != buffer.len() as u32;
636
637 if bad_write {
638 return Err(Error::Transmit);
639 }
640
641 if bad_read {
642 return Err(Error::Receive);
643 }
644
645 Ok(())
646 }
647 }
648}
649
440impl<'a, T: Instance> embedded_hal::blocking::i2c::Write for Twim<'a, T> { 650impl<'a, T: Instance> embedded_hal::blocking::i2c::Write for Twim<'a, T> {
441 type Error = Error; 651 type Error = Error;
442 652
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}