aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-11-17 23:47:46 +0000
committerGitHub <[email protected]>2023-11-17 23:47:46 +0000
commit5bc75578260f4c644cc060e6458a05d7fc0ffb41 (patch)
treeb870b676717d597b251b0888f176d5a5cf942e15
parent006260feddf4d362a99260a38d86dffddab39d2e (diff)
parent0f2208c0af8b89d91368c04ead9f84df664951e6 (diff)
Merge pull request #2173 from andresv/expose-i2c-async-api-without-time
STM32 I2C: expose async API without needing "time" feature.
-rw-r--r--embassy-stm32/src/i2c/v2.rs160
1 files changed, 90 insertions, 70 deletions
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index fc6dcd6ed..062a6225f 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -1,21 +1,16 @@
1use core::cmp; 1use core::cmp;
2#[cfg(feature = "time")]
3use core::future::poll_fn; 2use core::future::poll_fn;
4use core::marker::PhantomData; 3use core::marker::PhantomData;
5#[cfg(feature = "time")]
6use core::task::Poll; 4use core::task::Poll;
7 5
8use embassy_embedded_hal::SetConfig; 6use embassy_embedded_hal::SetConfig;
9#[cfg(feature = "time")]
10use embassy_hal_internal::drop::OnDrop; 7use embassy_hal_internal::drop::OnDrop;
11use embassy_hal_internal::{into_ref, PeripheralRef}; 8use embassy_hal_internal::{into_ref, PeripheralRef};
12use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
13#[cfg(feature = "time")] 10#[cfg(feature = "time")]
14use embassy_time::{Duration, Instant}; 11use embassy_time::{Duration, Instant};
15 12
16use crate::dma::NoDma; 13use crate::dma::{NoDma, Transfer};
17#[cfg(feature = "time")]
18use crate::dma::Transfer;
19use crate::gpio::sealed::AFType; 14use crate::gpio::sealed::AFType;
20use crate::gpio::Pull; 15use crate::gpio::Pull;
21use crate::i2c::{Error, Instance, SclPin, SdaPin}; 16use crate::i2c::{Error, Instance, SclPin, SdaPin};
@@ -24,6 +19,23 @@ use crate::pac::i2c;
24use crate::time::Hertz; 19use crate::time::Hertz;
25use crate::{interrupt, Peripheral}; 20use crate::{interrupt, Peripheral};
26 21
22#[cfg(feature = "time")]
23fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> {
24 let deadline = Instant::now() + timeout;
25 move || {
26 if Instant::now() > deadline {
27 Err(Error::Timeout)
28 } else {
29 Ok(())
30 }
31 }
32}
33
34#[cfg(not(feature = "time"))]
35pub fn no_timeout_fn() -> impl Fn() -> Result<(), Error> {
36 move || Ok(())
37}
38
27/// Interrupt handler. 39/// Interrupt handler.
28pub struct InterruptHandler<T: Instance> { 40pub struct InterruptHandler<T: Instance> {
29 _phantom: PhantomData<T>, 41 _phantom: PhantomData<T>,
@@ -260,21 +272,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
260 } 272 }
261 273
262 fn flush_txdr(&self) { 274 fn flush_txdr(&self) {
263 //if $i2c.isr.read().txis().bit_is_set() {
264 //$i2c.txdr.write(|w| w.txdata().bits(0));
265 //}
266
267 if T::regs().isr().read().txis() { 275 if T::regs().isr().read().txis() {
268 T::regs().txdr().write(|w| w.set_txdata(0)); 276 T::regs().txdr().write(|w| w.set_txdata(0));
269 } 277 }
270 if !T::regs().isr().read().txe() { 278 if !T::regs().isr().read().txe() {
271 T::regs().isr().modify(|w| w.set_txe(true)) 279 T::regs().isr().modify(|w| w.set_txe(true))
272 } 280 }
273
274 // If TXDR is not flagged as empty, write 1 to flush it
275 //if $i2c.isr.read().txe().is_not_empty() {
276 //$i2c.isr.write(|w| w.txe().set_bit());
277 //}
278 } 281 }
279 282
280 fn wait_txe(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { 283 fn wait_txe(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
@@ -437,7 +440,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
437 result 440 result
438 } 441 }
439 442
440 #[cfg(feature = "time")]
441 async fn write_dma_internal( 443 async fn write_dma_internal(
442 &mut self, 444 &mut self,
443 address: u8, 445 address: u8,
@@ -528,7 +530,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
528 Ok(()) 530 Ok(())
529 } 531 }
530 532
531 #[cfg(feature = "time")]
532 async fn read_dma_internal( 533 async fn read_dma_internal(
533 &mut self, 534 &mut self,
534 address: u8, 535 address: u8,
@@ -610,42 +611,38 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
610 611
611 // ========================= 612 // =========================
612 // Async public API 613 // Async public API
613
614 #[cfg(feature = "time")] 614 #[cfg(feature = "time")]
615 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> 615 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error>
616 where 616 where
617 TXDMA: crate::i2c::TxDma<T>, 617 TXDMA: crate::i2c::TxDma<T>,
618 { 618 {
619 self.write_timeout(address, write, self.timeout).await
620 }
621
622 #[cfg(feature = "time")]
623 pub async fn write_timeout(&mut self, address: u8, write: &[u8], timeout: Duration) -> Result<(), Error>
624 where
625 TXDMA: crate::i2c::TxDma<T>,
626 {
627 if write.is_empty() { 619 if write.is_empty() {
628 self.write_internal(address, write, true, timeout_fn(timeout)) 620 self.write_internal(address, write, true, timeout_fn(self.timeout))
629 } else { 621 } else {
630 embassy_time::with_timeout( 622 embassy_time::with_timeout(
631 timeout, 623 self.timeout,
632 self.write_dma_internal(address, write, true, true, timeout_fn(timeout)), 624 self.write_dma_internal(address, write, true, true, timeout_fn(self.timeout)),
633 ) 625 )
634 .await 626 .await
635 .unwrap_or(Err(Error::Timeout)) 627 .unwrap_or(Err(Error::Timeout))
636 } 628 }
637 } 629 }
638 630
639 #[cfg(feature = "time")] 631 #[cfg(not(feature = "time"))]
640 pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> 632 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error>
641 where 633 where
642 TXDMA: crate::i2c::TxDma<T>, 634 TXDMA: crate::i2c::TxDma<T>,
643 { 635 {
644 self.write_vectored_timeout(address, write, self.timeout).await 636 if write.is_empty() {
637 self.write_internal(address, write, true, no_timeout_fn())
638 } else {
639 self.write_dma_internal(address, write, true, true, no_timeout_fn())
640 .await
641 }
645 } 642 }
646 643
647 #[cfg(feature = "time")] 644 #[cfg(feature = "time")]
648 pub async fn write_vectored_timeout(&mut self, address: u8, write: &[&[u8]], timeout: Duration) -> Result<(), Error> 645 pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error>
649 where 646 where
650 TXDMA: crate::i2c::TxDma<T>, 647 TXDMA: crate::i2c::TxDma<T>,
651 { 648 {
@@ -661,8 +658,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
661 let is_last = next.is_none(); 658 let is_last = next.is_none();
662 659
663 embassy_time::with_timeout( 660 embassy_time::with_timeout(
664 timeout, 661 self.timeout,
665 self.write_dma_internal(address, c, first, is_last, timeout_fn(timeout)), 662 self.write_dma_internal(address, c, first, is_last, timeout_fn(self.timeout)),
666 ) 663 )
667 .await 664 .await
668 .unwrap_or(Err(Error::Timeout))?; 665 .unwrap_or(Err(Error::Timeout))?;
@@ -672,66 +669,79 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
672 Ok(()) 669 Ok(())
673 } 670 }
674 671
675 #[cfg(feature = "time")] 672 #[cfg(not(feature = "time"))]
676 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> 673 pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error>
677 where 674 where
678 RXDMA: crate::i2c::RxDma<T>, 675 TXDMA: crate::i2c::TxDma<T>,
679 { 676 {
680 self.read_timeout(address, buffer, self.timeout).await 677 if write.is_empty() {
678 return Err(Error::ZeroLengthTransfer);
679 }
680 let mut iter = write.iter();
681
682 let mut first = true;
683 let mut current = iter.next();
684 while let Some(c) = current {
685 let next = iter.next();
686 let is_last = next.is_none();
687
688 self.write_dma_internal(address, c, first, is_last, no_timeout_fn())
689 .await?;
690 first = false;
691 current = next;
692 }
693 Ok(())
681 } 694 }
682 695
683 #[cfg(feature = "time")] 696 #[cfg(feature = "time")]
684 pub async fn read_timeout(&mut self, address: u8, buffer: &mut [u8], timeout: Duration) -> Result<(), Error> 697 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
685 where 698 where
686 RXDMA: crate::i2c::RxDma<T>, 699 RXDMA: crate::i2c::RxDma<T>,
687 { 700 {
688 if buffer.is_empty() { 701 if buffer.is_empty() {
689 self.read_internal(address, buffer, false, timeout_fn(timeout)) 702 self.read_internal(address, buffer, false, timeout_fn(self.timeout))
690 } else { 703 } else {
691 embassy_time::with_timeout( 704 embassy_time::with_timeout(
692 timeout, 705 self.timeout,
693 self.read_dma_internal(address, buffer, false, timeout_fn(timeout)), 706 self.read_dma_internal(address, buffer, false, timeout_fn(self.timeout)),
694 ) 707 )
695 .await 708 .await
696 .unwrap_or(Err(Error::Timeout)) 709 .unwrap_or(Err(Error::Timeout))
697 } 710 }
698 } 711 }
699 712
700 #[cfg(feature = "time")] 713 #[cfg(not(feature = "time"))]
701 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> 714 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
702 where 715 where
703 TXDMA: super::TxDma<T>, 716 RXDMA: crate::i2c::RxDma<T>,
704 RXDMA: super::RxDma<T>,
705 { 717 {
706 self.write_read_timeout(address, write, read, self.timeout).await 718 if buffer.is_empty() {
719 self.read_internal(address, buffer, false, no_timeout_fn())
720 } else {
721 self.read_dma_internal(address, buffer, false, no_timeout_fn()).await
722 }
707 } 723 }
708 724
709 #[cfg(feature = "time")] 725 #[cfg(feature = "time")]
710 pub async fn write_read_timeout( 726 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error>
711 &mut self,
712 address: u8,
713 write: &[u8],
714 read: &mut [u8],
715 timeout: Duration,
716 ) -> Result<(), Error>
717 where 727 where
718 TXDMA: super::TxDma<T>, 728 TXDMA: super::TxDma<T>,
719 RXDMA: super::RxDma<T>, 729 RXDMA: super::RxDma<T>,
720 { 730 {
721 let start_instant = Instant::now(); 731 let start_instant = Instant::now();
722 let check_timeout = timeout_fn(timeout); 732 let check_timeout = timeout_fn(self.timeout);
723 if write.is_empty() { 733 if write.is_empty() {
724 self.write_internal(address, write, false, &check_timeout)?; 734 self.write_internal(address, write, false, &check_timeout)?;
725 } else { 735 } else {
726 embassy_time::with_timeout( 736 embassy_time::with_timeout(
727 timeout, 737 self.timeout,
728 self.write_dma_internal(address, write, true, true, &check_timeout), 738 self.write_dma_internal(address, write, true, true, &check_timeout),
729 ) 739 )
730 .await 740 .await
731 .unwrap_or(Err(Error::Timeout))?; 741 .unwrap_or(Err(Error::Timeout))?;
732 } 742 }
733 743
734 let time_left_until_timeout = timeout - Instant::now().duration_since(start_instant); 744 let time_left_until_timeout = self.timeout - Instant::now().duration_since(start_instant);
735 745
736 if read.is_empty() { 746 if read.is_empty() {
737 self.read_internal(address, read, true, &check_timeout)?; 747 self.read_internal(address, read, true, &check_timeout)?;
@@ -747,6 +757,28 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
747 Ok(()) 757 Ok(())
748 } 758 }
749 759
760 #[cfg(not(feature = "time"))]
761 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error>
762 where
763 TXDMA: super::TxDma<T>,
764 RXDMA: super::RxDma<T>,
765 {
766 let no_timeout = no_timeout_fn();
767 if write.is_empty() {
768 self.write_internal(address, write, false, &no_timeout)?;
769 } else {
770 self.write_dma_internal(address, write, true, true, &no_timeout).await?;
771 }
772
773 if read.is_empty() {
774 self.read_internal(address, read, true, &no_timeout)?;
775 } else {
776 self.read_dma_internal(address, read, true, &no_timeout).await?;
777 }
778
779 Ok(())
780 }
781
750 // ========================= 782 // =========================
751 // Blocking public API 783 // Blocking public API
752 784
@@ -1201,15 +1233,3 @@ impl<'d, T: Instance> SetConfig for I2c<'d, T> {
1201 Ok(()) 1233 Ok(())
1202 } 1234 }
1203} 1235}
1204
1205#[cfg(feature = "time")]
1206fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> {
1207 let deadline = Instant::now() + timeout;
1208 move || {
1209 if Instant::now() > deadline {
1210 Err(Error::Timeout)
1211 } else {
1212 Ok(())
1213 }
1214 }
1215}