diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-08-01 08:20:48 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-08-01 08:20:48 +0000 |
| commit | 0d8a9b1e7a963fe1a1a3cf0e10c33314bba65e2d (patch) | |
| tree | cc2eaa14fa266f03e930c3397dd7ccaeff657af9 | |
| parent | ef3b1f46a99bd44f4702459adcc42a176a36b2f8 (diff) | |
| parent | 036bc669cd46012e37e09af070ddb8353454719a (diff) | |
Merge pull request #1729 from mattico/i2c-async-timeout
stm32: add async timeout functions to I2c and TimeoutI2c
| -rw-r--r-- | embassy-stm32/src/i2c/timeout.rs | 98 | ||||
| -rw-r--r-- | embassy-stm32/src/i2c/v2.rs | 70 |
2 files changed, 153 insertions, 15 deletions
diff --git a/embassy-stm32/src/i2c/timeout.rs b/embassy-stm32/src/i2c/timeout.rs index 8dc228b34..103017cd1 100644 --- a/embassy-stm32/src/i2c/timeout.rs +++ b/embassy-stm32/src/i2c/timeout.rs | |||
| @@ -22,11 +22,93 @@ fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> { | |||
| 22 | } | 22 | } |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | impl<'a, 'd, T: Instance, TXDMA, RXDMA> TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { | 25 | impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { |
| 26 | pub fn new(i2c: &'a mut I2c<'d, T, TXDMA, RXDMA>, timeout: Duration) -> Self { | 26 | pub fn new(i2c: &'a mut I2c<'d, T, TXDMA, RXDMA>, timeout: Duration) -> Self { |
| 27 | Self { i2c, timeout } | 27 | Self { i2c, timeout } |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | // ========================= | ||
| 31 | // Async public API | ||
| 32 | |||
| 33 | #[cfg(i2c_v2)] | ||
| 34 | pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> | ||
| 35 | where | ||
| 36 | TXDMA: crate::i2c::TxDma<T>, | ||
| 37 | { | ||
| 38 | self.write_timeout(address, write, self.timeout).await | ||
| 39 | } | ||
| 40 | |||
| 41 | #[cfg(i2c_v2)] | ||
| 42 | pub async fn write_timeout(&mut self, address: u8, write: &[u8], timeout: Duration) -> Result<(), Error> | ||
| 43 | where | ||
| 44 | TXDMA: crate::i2c::TxDma<T>, | ||
| 45 | { | ||
| 46 | self.i2c.write_timeout(address, write, timeout_fn(timeout)).await | ||
| 47 | } | ||
| 48 | |||
| 49 | #[cfg(i2c_v2)] | ||
| 50 | pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> | ||
| 51 | where | ||
| 52 | TXDMA: crate::i2c::TxDma<T>, | ||
| 53 | { | ||
| 54 | self.write_vectored_timeout(address, write, self.timeout).await | ||
| 55 | } | ||
| 56 | |||
| 57 | #[cfg(i2c_v2)] | ||
| 58 | pub async fn write_vectored_timeout(&mut self, address: u8, write: &[&[u8]], timeout: Duration) -> Result<(), Error> | ||
| 59 | where | ||
| 60 | TXDMA: crate::i2c::TxDma<T>, | ||
| 61 | { | ||
| 62 | self.i2c | ||
| 63 | .write_vectored_timeout(address, write, timeout_fn(timeout)) | ||
| 64 | .await | ||
| 65 | } | ||
| 66 | |||
| 67 | #[cfg(i2c_v2)] | ||
| 68 | pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> | ||
| 69 | where | ||
| 70 | RXDMA: crate::i2c::RxDma<T>, | ||
| 71 | { | ||
| 72 | self.read_timeout(address, buffer, self.timeout).await | ||
| 73 | } | ||
| 74 | |||
| 75 | #[cfg(i2c_v2)] | ||
| 76 | pub async fn read_timeout(&mut self, address: u8, buffer: &mut [u8], timeout: Duration) -> Result<(), Error> | ||
| 77 | where | ||
| 78 | RXDMA: crate::i2c::RxDma<T>, | ||
| 79 | { | ||
| 80 | self.i2c.read_timeout(address, buffer, timeout_fn(timeout)).await | ||
| 81 | } | ||
| 82 | |||
| 83 | #[cfg(i2c_v2)] | ||
| 84 | pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> | ||
| 85 | where | ||
| 86 | TXDMA: super::TxDma<T>, | ||
| 87 | RXDMA: super::RxDma<T>, | ||
| 88 | { | ||
| 89 | self.write_read_timeout(address, write, read, self.timeout).await | ||
| 90 | } | ||
| 91 | |||
| 92 | #[cfg(i2c_v2)] | ||
| 93 | pub async fn write_read_timeout( | ||
| 94 | &mut self, | ||
| 95 | address: u8, | ||
| 96 | write: &[u8], | ||
| 97 | read: &mut [u8], | ||
| 98 | timeout: Duration, | ||
| 99 | ) -> Result<(), Error> | ||
| 100 | where | ||
| 101 | TXDMA: super::TxDma<T>, | ||
| 102 | RXDMA: super::RxDma<T>, | ||
| 103 | { | ||
| 104 | self.i2c | ||
| 105 | .write_read_timeout(address, write, read, timeout_fn(timeout)) | ||
| 106 | .await | ||
| 107 | } | ||
| 108 | |||
| 109 | // ========================= | ||
| 110 | // Blocking public API | ||
| 111 | |||
| 30 | /// Blocking read with a custom timeout | 112 | /// Blocking read with a custom timeout |
| 31 | pub fn blocking_read_timeout(&mut self, addr: u8, read: &mut [u8], timeout: Duration) -> Result<(), Error> { | 113 | pub fn blocking_read_timeout(&mut self, addr: u8, read: &mut [u8], timeout: Duration) -> Result<(), Error> { |
| 32 | self.i2c.blocking_read_timeout(addr, read, timeout_fn(timeout)) | 114 | self.i2c.blocking_read_timeout(addr, read, timeout_fn(timeout)) |
| @@ -65,7 +147,9 @@ impl<'a, 'd, T: Instance, TXDMA, RXDMA> TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { | |||
| 65 | } | 147 | } |
| 66 | } | 148 | } |
| 67 | 149 | ||
| 68 | impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Read for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { | 150 | impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Read |
| 151 | for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> | ||
| 152 | { | ||
| 69 | type Error = Error; | 153 | type Error = Error; |
| 70 | 154 | ||
| 71 | fn read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Self::Error> { | 155 | fn read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Self::Error> { |
| @@ -73,7 +157,9 @@ impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Read for | |||
| 73 | } | 157 | } |
| 74 | } | 158 | } |
| 75 | 159 | ||
| 76 | impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Write for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { | 160 | impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Write |
| 161 | for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> | ||
| 162 | { | ||
| 77 | type Error = Error; | 163 | type Error = Error; |
| 78 | 164 | ||
| 79 | fn write(&mut self, addr: u8, write: &[u8]) -> Result<(), Self::Error> { | 165 | fn write(&mut self, addr: u8, write: &[u8]) -> Result<(), Self::Error> { |
| @@ -81,7 +167,7 @@ impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Write fo | |||
| 81 | } | 167 | } |
| 82 | } | 168 | } |
| 83 | 169 | ||
| 84 | impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::WriteRead | 170 | impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::WriteRead |
| 85 | for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> | 171 | for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> |
| 86 | { | 172 | { |
| 87 | type Error = Error; | 173 | type Error = Error; |
| @@ -95,11 +181,11 @@ impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::WriteRea | |||
| 95 | mod eh1 { | 181 | mod eh1 { |
| 96 | use super::*; | 182 | use super::*; |
| 97 | 183 | ||
| 98 | impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::ErrorType for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { | 184 | impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::ErrorType for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { |
| 99 | type Error = Error; | 185 | type Error = Error; |
| 100 | } | 186 | } |
| 101 | 187 | ||
| 102 | impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::I2c for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { | 188 | impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::I2c for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { |
| 103 | fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { | 189 | fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { |
| 104 | self.blocking_read(address, read) | 190 | self.blocking_read(address, read) |
| 105 | } | 191 | } |
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index eaf980a4d..4327899bb 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs | |||
| @@ -598,10 +598,22 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 598 | where | 598 | where |
| 599 | TXDMA: crate::i2c::TxDma<T>, | 599 | TXDMA: crate::i2c::TxDma<T>, |
| 600 | { | 600 | { |
| 601 | self.write_timeout(address, write, || Ok(())).await | ||
| 602 | } | ||
| 603 | |||
| 604 | pub async fn write_timeout( | ||
| 605 | &mut self, | ||
| 606 | address: u8, | ||
| 607 | write: &[u8], | ||
| 608 | check_timeout: impl Fn() -> Result<(), Error>, | ||
| 609 | ) -> Result<(), Error> | ||
| 610 | where | ||
| 611 | TXDMA: crate::i2c::TxDma<T>, | ||
| 612 | { | ||
| 601 | if write.is_empty() { | 613 | if write.is_empty() { |
| 602 | self.write_internal(address, write, true, || Ok(())) | 614 | self.write_internal(address, write, true, check_timeout) |
| 603 | } else { | 615 | } else { |
| 604 | self.write_dma_internal(address, write, true, true, || Ok(())).await | 616 | self.write_dma_internal(address, write, true, true, check_timeout).await |
| 605 | } | 617 | } |
| 606 | } | 618 | } |
| 607 | 619 | ||
| @@ -609,6 +621,18 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 609 | where | 621 | where |
| 610 | TXDMA: crate::i2c::TxDma<T>, | 622 | TXDMA: crate::i2c::TxDma<T>, |
| 611 | { | 623 | { |
| 624 | self.write_vectored_timeout(address, write, || Ok(())).await | ||
| 625 | } | ||
| 626 | |||
| 627 | pub async fn write_vectored_timeout( | ||
| 628 | &mut self, | ||
| 629 | address: u8, | ||
| 630 | write: &[&[u8]], | ||
| 631 | check_timeout: impl Fn() -> Result<(), Error>, | ||
| 632 | ) -> Result<(), Error> | ||
| 633 | where | ||
| 634 | TXDMA: crate::i2c::TxDma<T>, | ||
| 635 | { | ||
| 612 | if write.is_empty() { | 636 | if write.is_empty() { |
| 613 | return Err(Error::ZeroLengthTransfer); | 637 | return Err(Error::ZeroLengthTransfer); |
| 614 | } | 638 | } |
| @@ -620,7 +644,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 620 | let next = iter.next(); | 644 | let next = iter.next(); |
| 621 | let is_last = next.is_none(); | 645 | let is_last = next.is_none(); |
| 622 | 646 | ||
| 623 | self.write_dma_internal(address, c, first, is_last, || Ok(())).await?; | 647 | self.write_dma_internal(address, c, first, is_last, || check_timeout()) |
| 648 | .await?; | ||
| 624 | first = false; | 649 | first = false; |
| 625 | current = next; | 650 | current = next; |
| 626 | } | 651 | } |
| @@ -631,10 +656,22 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 631 | where | 656 | where |
| 632 | RXDMA: crate::i2c::RxDma<T>, | 657 | RXDMA: crate::i2c::RxDma<T>, |
| 633 | { | 658 | { |
| 659 | self.read_timeout(address, buffer, || Ok(())).await | ||
| 660 | } | ||
| 661 | |||
| 662 | pub async fn read_timeout( | ||
| 663 | &mut self, | ||
| 664 | address: u8, | ||
| 665 | buffer: &mut [u8], | ||
| 666 | check_timeout: impl Fn() -> Result<(), Error>, | ||
| 667 | ) -> Result<(), Error> | ||
| 668 | where | ||
| 669 | RXDMA: crate::i2c::RxDma<T>, | ||
| 670 | { | ||
| 634 | if buffer.is_empty() { | 671 | if buffer.is_empty() { |
| 635 | self.read_internal(address, buffer, false, || Ok(())) | 672 | self.read_internal(address, buffer, false, check_timeout) |
| 636 | } else { | 673 | } else { |
| 637 | self.read_dma_internal(address, buffer, false, || Ok(())).await | 674 | self.read_dma_internal(address, buffer, false, check_timeout).await |
| 638 | } | 675 | } |
| 639 | } | 676 | } |
| 640 | 677 | ||
| @@ -643,16 +680,31 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 643 | TXDMA: super::TxDma<T>, | 680 | TXDMA: super::TxDma<T>, |
| 644 | RXDMA: super::RxDma<T>, | 681 | RXDMA: super::RxDma<T>, |
| 645 | { | 682 | { |
| 683 | self.write_read_timeout(address, write, read, || Ok(())).await | ||
| 684 | } | ||
| 685 | |||
| 686 | pub async fn write_read_timeout( | ||
| 687 | &mut self, | ||
| 688 | address: u8, | ||
| 689 | write: &[u8], | ||
| 690 | read: &mut [u8], | ||
| 691 | check_timeout: impl Fn() -> Result<(), Error>, | ||
| 692 | ) -> Result<(), Error> | ||
| 693 | where | ||
| 694 | TXDMA: super::TxDma<T>, | ||
| 695 | RXDMA: super::RxDma<T>, | ||
| 696 | { | ||
| 646 | if write.is_empty() { | 697 | if write.is_empty() { |
| 647 | self.write_internal(address, write, false, || Ok(()))?; | 698 | self.write_internal(address, write, false, || check_timeout())?; |
| 648 | } else { | 699 | } else { |
| 649 | self.write_dma_internal(address, write, true, true, || Ok(())).await?; | 700 | self.write_dma_internal(address, write, true, true, || check_timeout()) |
| 701 | .await?; | ||
| 650 | } | 702 | } |
| 651 | 703 | ||
| 652 | if read.is_empty() { | 704 | if read.is_empty() { |
| 653 | self.read_internal(address, read, true, || Ok(()))?; | 705 | self.read_internal(address, read, true, check_timeout)?; |
| 654 | } else { | 706 | } else { |
| 655 | self.read_dma_internal(address, read, true, || Ok(())).await?; | 707 | self.read_dma_internal(address, read, true, check_timeout).await?; |
| 656 | } | 708 | } |
| 657 | 709 | ||
| 658 | Ok(()) | 710 | Ok(()) |
