aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndres Vahter <[email protected]>2023-11-11 14:29:24 +0200
committerAndres Vahter <[email protected]>2023-11-11 14:29:24 +0200
commit0f2208c0af8b89d91368c04ead9f84df664951e6 (patch)
tree192ab36da86cab7dac96cd375b5194414c28df86
parent6c42885d4a072b7fa8662062ff4073063d8bd2ad (diff)
stm32 i2c: remove mod dummy_time
-rw-r--r--embassy-stm32/src/i2c/v2.rs167
1 files changed, 87 insertions, 80 deletions
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 54d2fe6ec..062a6225f 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -1,5 +1,5 @@
1use core::cmp; 1use core::cmp;
2use core::future::{poll_fn, Future}; 2use core::future::poll_fn;
3use core::marker::PhantomData; 3use core::marker::PhantomData;
4use core::task::Poll; 4use core::task::Poll;
5 5
@@ -7,6 +7,8 @@ use embassy_embedded_hal::SetConfig;
7use embassy_hal_internal::drop::OnDrop; 7use embassy_hal_internal::drop::OnDrop;
8use embassy_hal_internal::{into_ref, PeripheralRef}; 8use embassy_hal_internal::{into_ref, PeripheralRef};
9use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
10#[cfg(feature = "time")]
11use embassy_time::{Duration, Instant};
10 12
11use crate::dma::{NoDma, Transfer}; 13use crate::dma::{NoDma, Transfer};
12use crate::gpio::sealed::AFType; 14use crate::gpio::sealed::AFType;
@@ -17,75 +19,6 @@ use crate::pac::i2c;
17use crate::time::Hertz; 19use crate::time::Hertz;
18use crate::{interrupt, Peripheral}; 20use crate::{interrupt, Peripheral};
19 21
20/// # Async I2C Operations with Optional Timeouts
21///
22/// This module provides compatibility for async I2C operations with timeout-based APIs,
23/// even when the "time" feature is not enabled. In the absence of the "time" feature,
24/// operations effectively never time out.
25///
26/// ## Usage Scenario
27/// This is particularly useful in scenarios such as when using RTIC, where a user might
28/// have their own monotonic timer and thus choose not to enable the "time" feature.
29/// In such cases, this module allows the use of async I2C APIs without actual timeout
30/// handling.
31///
32/// ## Functionality
33/// - When the "time" feature is disabled, `Duration` and `Instant` types are provided
34/// as dummy implementations, and timeout functions do not perform real timing but
35/// simply mimic the required interfaces.
36/// - When the "time" feature is enabled, `Duration` and `Instant` from the `embassy_time`
37/// are used, and timeouts are handled as expected.
38#[cfg(not(feature = "time"))]
39mod dummy_time {
40 use core::ops::Sub;
41
42 use super::{Error, Future};
43
44 #[derive(Copy, Clone)]
45 pub struct Duration;
46
47 impl Duration {
48 pub fn dummy_duration() -> Duration {
49 Duration
50 }
51 }
52
53 pub struct Instant;
54
55 impl Instant {
56 pub fn now() -> Self {
57 Self
58 }
59
60 pub fn duration_since(&self, _since: Instant) -> Duration {
61 Duration
62 }
63 }
64
65 impl Sub for Duration {
66 type Output = Duration;
67
68 fn sub(self, _rhs: Duration) -> Duration {
69 Duration
70 }
71 }
72
73 /// Timeout that never times out.
74 pub fn timeout_fn(_timeout: Duration) -> impl Fn() -> Result<(), Error> {
75 move || Ok(())
76 }
77
78 /// This is compatible with `embassy_time::with_timeout` however it never times out.
79 pub async fn with_timeout<F: Future>(_timeout: Duration, fut: F) -> Result<F::Output, ()> {
80 Ok(fut.await)
81 }
82}
83
84#[cfg(not(feature = "time"))]
85use dummy_time::{timeout_fn, with_timeout, Duration, Instant};
86#[cfg(feature = "time")]
87use embassy_time::{Duration, Instant};
88
89#[cfg(feature = "time")] 22#[cfg(feature = "time")]
90fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> { 23fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> {
91 let deadline = Instant::now() + timeout; 24 let deadline = Instant::now() + timeout;
@@ -98,9 +31,9 @@ fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> {
98 } 31 }
99} 32}
100 33
101#[cfg(feature = "time")] 34#[cfg(not(feature = "time"))]
102async fn with_timeout<F: Future>(timeout: Duration, fut: F) -> Result<F::Output, embassy_time::TimeoutError> { 35pub fn no_timeout_fn() -> impl Fn() -> Result<(), Error> {
103 embassy_time::with_timeout(timeout, fut).await 36 move || Ok(())
104} 37}
105 38
106/// Interrupt handler. 39/// Interrupt handler.
@@ -162,6 +95,7 @@ pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> {
162 tx_dma: PeripheralRef<'d, TXDMA>, 95 tx_dma: PeripheralRef<'d, TXDMA>,
163 #[allow(dead_code)] 96 #[allow(dead_code)]
164 rx_dma: PeripheralRef<'d, RXDMA>, 97 rx_dma: PeripheralRef<'d, RXDMA>,
98 #[cfg(feature = "time")]
165 timeout: Duration, 99 timeout: Duration,
166} 100}
167 101
@@ -225,8 +159,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
225 rx_dma, 159 rx_dma,
226 #[cfg(feature = "time")] 160 #[cfg(feature = "time")]
227 timeout: config.transaction_timeout, 161 timeout: config.transaction_timeout,
228 #[cfg(not(feature = "time"))]
229 timeout: Duration::dummy_duration(),
230 } 162 }
231 } 163 }
232 164
@@ -679,6 +611,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
679 611
680 // ========================= 612 // =========================
681 // Async public API 613 // Async public API
614 #[cfg(feature = "time")]
682 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>
683 where 616 where
684 TXDMA: crate::i2c::TxDma<T>, 617 TXDMA: crate::i2c::TxDma<T>,
@@ -686,7 +619,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
686 if write.is_empty() { 619 if write.is_empty() {
687 self.write_internal(address, write, true, timeout_fn(self.timeout)) 620 self.write_internal(address, write, true, timeout_fn(self.timeout))
688 } else { 621 } else {
689 with_timeout( 622 embassy_time::with_timeout(
690 self.timeout, 623 self.timeout,
691 self.write_dma_internal(address, write, true, true, timeout_fn(self.timeout)), 624 self.write_dma_internal(address, write, true, true, timeout_fn(self.timeout)),
692 ) 625 )
@@ -695,6 +628,20 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
695 } 628 }
696 } 629 }
697 630
631 #[cfg(not(feature = "time"))]
632 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error>
633 where
634 TXDMA: crate::i2c::TxDma<T>,
635 {
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 }
642 }
643
644 #[cfg(feature = "time")]
698 pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> 645 pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error>
699 where 646 where
700 TXDMA: crate::i2c::TxDma<T>, 647 TXDMA: crate::i2c::TxDma<T>,
@@ -710,7 +657,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
710 let next = iter.next(); 657 let next = iter.next();
711 let is_last = next.is_none(); 658 let is_last = next.is_none();
712 659
713 with_timeout( 660 embassy_time::with_timeout(
714 self.timeout, 661 self.timeout,
715 self.write_dma_internal(address, c, first, is_last, timeout_fn(self.timeout)), 662 self.write_dma_internal(address, c, first, is_last, timeout_fn(self.timeout)),
716 ) 663 )
@@ -722,6 +669,31 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
722 Ok(()) 669 Ok(())
723 } 670 }
724 671
672 #[cfg(not(feature = "time"))]
673 pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error>
674 where
675 TXDMA: crate::i2c::TxDma<T>,
676 {
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(())
694 }
695
696 #[cfg(feature = "time")]
725 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> 697 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
726 where 698 where
727 RXDMA: crate::i2c::RxDma<T>, 699 RXDMA: crate::i2c::RxDma<T>,
@@ -729,7 +701,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
729 if buffer.is_empty() { 701 if buffer.is_empty() {
730 self.read_internal(address, buffer, false, timeout_fn(self.timeout)) 702 self.read_internal(address, buffer, false, timeout_fn(self.timeout))
731 } else { 703 } else {
732 with_timeout( 704 embassy_time::with_timeout(
733 self.timeout, 705 self.timeout,
734 self.read_dma_internal(address, buffer, false, timeout_fn(self.timeout)), 706 self.read_dma_internal(address, buffer, false, timeout_fn(self.timeout)),
735 ) 707 )
@@ -738,6 +710,19 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
738 } 710 }
739 } 711 }
740 712
713 #[cfg(not(feature = "time"))]
714 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
715 where
716 RXDMA: crate::i2c::RxDma<T>,
717 {
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 }
723 }
724
725 #[cfg(feature = "time")]
741 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> 726 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error>
742 where 727 where
743 TXDMA: super::TxDma<T>, 728 TXDMA: super::TxDma<T>,
@@ -748,7 +733,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
748 if write.is_empty() { 733 if write.is_empty() {
749 self.write_internal(address, write, false, &check_timeout)?; 734 self.write_internal(address, write, false, &check_timeout)?;
750 } else { 735 } else {
751 with_timeout( 736 embassy_time::with_timeout(
752 self.timeout, 737 self.timeout,
753 self.write_dma_internal(address, write, true, true, &check_timeout), 738 self.write_dma_internal(address, write, true, true, &check_timeout),
754 ) 739 )
@@ -761,7 +746,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
761 if read.is_empty() { 746 if read.is_empty() {
762 self.read_internal(address, read, true, &check_timeout)?; 747 self.read_internal(address, read, true, &check_timeout)?;
763 } else { 748 } else {
764 with_timeout( 749 embassy_time::with_timeout(
765 time_left_until_timeout, 750 time_left_until_timeout,
766 self.read_dma_internal(address, read, true, &check_timeout), 751 self.read_dma_internal(address, read, true, &check_timeout),
767 ) 752 )
@@ -772,6 +757,28 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
772 Ok(()) 757 Ok(())
773 } 758 }
774 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
775 // ========================= 782 // =========================
776 // Blocking public API 783 // Blocking public API
777 784