diff options
| author | Andres Vahter <[email protected]> | 2023-11-11 14:29:24 +0200 |
|---|---|---|
| committer | Andres Vahter <[email protected]> | 2023-11-11 14:29:24 +0200 |
| commit | 0f2208c0af8b89d91368c04ead9f84df664951e6 (patch) | |
| tree | 192ab36da86cab7dac96cd375b5194414c28df86 | |
| parent | 6c42885d4a072b7fa8662062ff4073063d8bd2ad (diff) | |
stm32 i2c: remove mod dummy_time
| -rw-r--r-- | embassy-stm32/src/i2c/v2.rs | 167 |
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 @@ | |||
| 1 | use core::cmp; | 1 | use core::cmp; |
| 2 | use core::future::{poll_fn, Future}; | 2 | use core::future::poll_fn; |
| 3 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 4 | use core::task::Poll; | 4 | use core::task::Poll; |
| 5 | 5 | ||
| @@ -7,6 +7,8 @@ use embassy_embedded_hal::SetConfig; | |||
| 7 | use embassy_hal_internal::drop::OnDrop; | 7 | use embassy_hal_internal::drop::OnDrop; |
| 8 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 8 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 9 | use embassy_sync::waitqueue::AtomicWaker; | 9 | use embassy_sync::waitqueue::AtomicWaker; |
| 10 | #[cfg(feature = "time")] | ||
| 11 | use embassy_time::{Duration, Instant}; | ||
| 10 | 12 | ||
| 11 | use crate::dma::{NoDma, Transfer}; | 13 | use crate::dma::{NoDma, Transfer}; |
| 12 | use crate::gpio::sealed::AFType; | 14 | use crate::gpio::sealed::AFType; |
| @@ -17,75 +19,6 @@ use crate::pac::i2c; | |||
| 17 | use crate::time::Hertz; | 19 | use crate::time::Hertz; |
| 18 | use crate::{interrupt, Peripheral}; | 20 | use 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"))] | ||
| 39 | mod 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"))] | ||
| 85 | use dummy_time::{timeout_fn, with_timeout, Duration, Instant}; | ||
| 86 | #[cfg(feature = "time")] | ||
| 87 | use embassy_time::{Duration, Instant}; | ||
| 88 | |||
| 89 | #[cfg(feature = "time")] | 22 | #[cfg(feature = "time")] |
| 90 | fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> { | 23 | fn 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"))] |
| 102 | async fn with_timeout<F: Future>(timeout: Duration, fut: F) -> Result<F::Output, embassy_time::TimeoutError> { | 35 | pub 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 | ||
