diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-12-18 18:24:55 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2023-12-18 18:24:55 +0100 |
| commit | 7044e53af45e472d52d6e523bddf5632f0375487 (patch) | |
| tree | 15c0e4e73f1a07c25fd948c37ad1417131fb730e | |
| parent | 88e77c733cc3d52a2bd20e9e25446fe1d37c830b (diff) | |
stm32/i2c: remove _timeout public API, share more code between v1/v2.
| -rw-r--r-- | embassy-stm32/src/i2c/mod.rs | 162 | ||||
| -rw-r--r-- | embassy-stm32/src/i2c/v1.rs | 145 | ||||
| -rw-r--r-- | embassy-stm32/src/i2c/v2.rs | 460 |
3 files changed, 262 insertions, 505 deletions
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index a8dc8e0e5..0af291e9c 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs | |||
| @@ -1,17 +1,23 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | use core::marker::PhantomData; | ||
| 4 | |||
| 5 | use crate::dma::NoDma; | ||
| 6 | use crate::interrupt; | ||
| 7 | |||
| 8 | #[cfg_attr(i2c_v1, path = "v1.rs")] | 3 | #[cfg_attr(i2c_v1, path = "v1.rs")] |
| 9 | #[cfg_attr(i2c_v2, path = "v2.rs")] | 4 | #[cfg_attr(i2c_v2, path = "v2.rs")] |
| 10 | mod _version; | 5 | mod _version; |
| 11 | pub use _version::*; | 6 | |
| 7 | use core::future::Future; | ||
| 8 | use core::marker::PhantomData; | ||
| 9 | |||
| 10 | use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; | ||
| 12 | use embassy_sync::waitqueue::AtomicWaker; | 11 | use embassy_sync::waitqueue::AtomicWaker; |
| 12 | #[cfg(feature = "time")] | ||
| 13 | use embassy_time::{Duration, Instant}; | ||
| 13 | 14 | ||
| 14 | use crate::peripherals; | 15 | use crate::dma::NoDma; |
| 16 | use crate::gpio::sealed::AFType; | ||
| 17 | use crate::gpio::Pull; | ||
| 18 | use crate::interrupt::typelevel::Interrupt; | ||
| 19 | use crate::time::Hertz; | ||
| 20 | use crate::{interrupt, peripherals}; | ||
| 15 | 21 | ||
| 16 | /// I2C error. | 22 | /// I2C error. |
| 17 | #[derive(Debug, PartialEq, Eq)] | 23 | #[derive(Debug, PartialEq, Eq)] |
| @@ -33,6 +39,148 @@ pub enum Error { | |||
| 33 | ZeroLengthTransfer, | 39 | ZeroLengthTransfer, |
| 34 | } | 40 | } |
| 35 | 41 | ||
| 42 | /// I2C config | ||
| 43 | #[non_exhaustive] | ||
| 44 | #[derive(Copy, Clone)] | ||
| 45 | pub struct Config { | ||
| 46 | /// Enable internal pullup on SDA. | ||
| 47 | /// | ||
| 48 | /// Using external pullup resistors is recommended for I2C. If you do | ||
| 49 | /// have external pullups you should not enable this. | ||
| 50 | pub sda_pullup: bool, | ||
| 51 | /// Enable internal pullup on SCL. | ||
| 52 | /// | ||
| 53 | /// Using external pullup resistors is recommended for I2C. If you do | ||
| 54 | /// have external pullups you should not enable this. | ||
| 55 | pub scl_pullup: bool, | ||
| 56 | /// Timeout. | ||
| 57 | #[cfg(feature = "time")] | ||
| 58 | pub timeout: embassy_time::Duration, | ||
| 59 | } | ||
| 60 | |||
| 61 | impl Default for Config { | ||
| 62 | fn default() -> Self { | ||
| 63 | Self { | ||
| 64 | sda_pullup: false, | ||
| 65 | scl_pullup: false, | ||
| 66 | #[cfg(feature = "time")] | ||
| 67 | timeout: embassy_time::Duration::from_millis(1000), | ||
| 68 | } | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | /// I2C driver. | ||
| 73 | pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> { | ||
| 74 | _peri: PeripheralRef<'d, T>, | ||
| 75 | #[allow(dead_code)] | ||
| 76 | tx_dma: PeripheralRef<'d, TXDMA>, | ||
| 77 | #[allow(dead_code)] | ||
| 78 | rx_dma: PeripheralRef<'d, RXDMA>, | ||
| 79 | #[cfg(feature = "time")] | ||
| 80 | timeout: Duration, | ||
| 81 | } | ||
| 82 | |||
| 83 | impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | ||
| 84 | /// Create a new I2C driver. | ||
| 85 | pub fn new( | ||
| 86 | peri: impl Peripheral<P = T> + 'd, | ||
| 87 | scl: impl Peripheral<P = impl SclPin<T>> + 'd, | ||
| 88 | sda: impl Peripheral<P = impl SdaPin<T>> + 'd, | ||
| 89 | _irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>> | ||
| 90 | + interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>> | ||
| 91 | + 'd, | ||
| 92 | tx_dma: impl Peripheral<P = TXDMA> + 'd, | ||
| 93 | rx_dma: impl Peripheral<P = RXDMA> + 'd, | ||
| 94 | freq: Hertz, | ||
| 95 | config: Config, | ||
| 96 | ) -> Self { | ||
| 97 | into_ref!(peri, scl, sda, tx_dma, rx_dma); | ||
| 98 | |||
| 99 | T::enable_and_reset(); | ||
| 100 | |||
| 101 | scl.set_as_af_pull( | ||
| 102 | scl.af_num(), | ||
| 103 | AFType::OutputOpenDrain, | ||
| 104 | match config.scl_pullup { | ||
| 105 | true => Pull::Up, | ||
| 106 | false => Pull::None, | ||
| 107 | }, | ||
| 108 | ); | ||
| 109 | sda.set_as_af_pull( | ||
| 110 | sda.af_num(), | ||
| 111 | AFType::OutputOpenDrain, | ||
| 112 | match config.sda_pullup { | ||
| 113 | true => Pull::Up, | ||
| 114 | false => Pull::None, | ||
| 115 | }, | ||
| 116 | ); | ||
| 117 | |||
| 118 | unsafe { T::EventInterrupt::enable() }; | ||
| 119 | unsafe { T::ErrorInterrupt::enable() }; | ||
| 120 | |||
| 121 | let mut this = Self { | ||
| 122 | _peri: peri, | ||
| 123 | tx_dma, | ||
| 124 | rx_dma, | ||
| 125 | #[cfg(feature = "time")] | ||
| 126 | timeout: config.timeout, | ||
| 127 | }; | ||
| 128 | |||
| 129 | this.init(freq, config); | ||
| 130 | |||
| 131 | this | ||
| 132 | } | ||
| 133 | |||
| 134 | fn timeout(&self) -> Timeout { | ||
| 135 | Timeout { | ||
| 136 | #[cfg(feature = "time")] | ||
| 137 | deadline: Instant::now() + self.timeout, | ||
| 138 | } | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | #[derive(Copy, Clone)] | ||
| 143 | struct Timeout { | ||
| 144 | #[cfg(feature = "time")] | ||
| 145 | deadline: Instant, | ||
| 146 | } | ||
| 147 | |||
| 148 | #[allow(dead_code)] | ||
| 149 | impl Timeout { | ||
| 150 | #[cfg(not(feature = "time"))] | ||
| 151 | #[inline] | ||
| 152 | fn check(self) -> Result<(), Error> { | ||
| 153 | Ok(()) | ||
| 154 | } | ||
| 155 | |||
| 156 | #[cfg(feature = "time")] | ||
| 157 | #[inline] | ||
| 158 | fn check(self) -> Result<(), Error> { | ||
| 159 | if Instant::now() > self.deadline { | ||
| 160 | Err(Error::Timeout) | ||
| 161 | } else { | ||
| 162 | Ok(()) | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | #[cfg(not(feature = "time"))] | ||
| 167 | #[inline] | ||
| 168 | fn with<R>(self, fut: impl Future<Output = Result<R, Error>>) -> impl Future<Output = Result<R, Error>> { | ||
| 169 | fut | ||
| 170 | } | ||
| 171 | |||
| 172 | #[cfg(feature = "time")] | ||
| 173 | #[inline] | ||
| 174 | fn with<R>(self, fut: impl Future<Output = Result<R, Error>>) -> impl Future<Output = Result<R, Error>> { | ||
| 175 | use futures::FutureExt; | ||
| 176 | |||
| 177 | embassy_futures::select::select(embassy_time::Timer::at(self.deadline), fut).map(|r| match r { | ||
| 178 | embassy_futures::select::Either::First(_) => Err(Error::Timeout), | ||
| 179 | embassy_futures::select::Either::Second(r) => r, | ||
| 180 | }) | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 36 | pub(crate) mod sealed { | 184 | pub(crate) mod sealed { |
| 37 | use super::*; | 185 | use super::*; |
| 38 | 186 | ||
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index b62ee8246..84802d129 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs | |||
| @@ -1,20 +1,14 @@ | |||
| 1 | use core::future::poll_fn; | 1 | use core::future::poll_fn; |
| 2 | use core::marker::PhantomData; | ||
| 3 | use core::task::Poll; | 2 | use core::task::Poll; |
| 4 | 3 | ||
| 5 | use embassy_embedded_hal::SetConfig; | 4 | use embassy_embedded_hal::SetConfig; |
| 6 | use embassy_futures::select::{select, Either}; | 5 | use embassy_futures::select::{select, Either}; |
| 7 | use embassy_hal_internal::drop::OnDrop; | 6 | use embassy_hal_internal::drop::OnDrop; |
| 8 | use embassy_hal_internal::{into_ref, PeripheralRef}; | ||
| 9 | 7 | ||
| 10 | use super::*; | 8 | use super::*; |
| 11 | use crate::dma::{NoDma, Transfer}; | 9 | use crate::dma::Transfer; |
| 12 | use crate::gpio::sealed::AFType; | ||
| 13 | use crate::gpio::Pull; | ||
| 14 | use crate::interrupt::typelevel::Interrupt; | ||
| 15 | use crate::pac::i2c; | 10 | use crate::pac::i2c; |
| 16 | use crate::time::Hertz; | 11 | use crate::time::Hertz; |
| 17 | use crate::{interrupt, Peripheral}; | ||
| 18 | 12 | ||
| 19 | pub unsafe fn on_interrupt<T: Instance>() { | 13 | pub unsafe fn on_interrupt<T: Instance>() { |
| 20 | let regs = T::regs(); | 14 | let regs = T::regs(); |
| @@ -30,55 +24,8 @@ pub unsafe fn on_interrupt<T: Instance>() { | |||
| 30 | }); | 24 | }); |
| 31 | } | 25 | } |
| 32 | 26 | ||
| 33 | #[non_exhaustive] | ||
| 34 | #[derive(Copy, Clone, Default)] | ||
| 35 | pub struct Config { | ||
| 36 | pub sda_pullup: bool, | ||
| 37 | pub scl_pullup: bool, | ||
| 38 | } | ||
| 39 | |||
| 40 | pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> { | ||
| 41 | phantom: PhantomData<&'d mut T>, | ||
| 42 | #[allow(dead_code)] | ||
| 43 | tx_dma: PeripheralRef<'d, TXDMA>, | ||
| 44 | #[allow(dead_code)] | ||
| 45 | rx_dma: PeripheralRef<'d, RXDMA>, | ||
| 46 | } | ||
| 47 | |||
| 48 | impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | 27 | impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { |
| 49 | pub fn new( | 28 | pub(crate) fn init(&mut self, freq: Hertz, _config: Config) { |
| 50 | _peri: impl Peripheral<P = T> + 'd, | ||
| 51 | scl: impl Peripheral<P = impl SclPin<T>> + 'd, | ||
| 52 | sda: impl Peripheral<P = impl SdaPin<T>> + 'd, | ||
| 53 | _irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>> | ||
| 54 | + interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>> | ||
| 55 | + 'd, | ||
| 56 | tx_dma: impl Peripheral<P = TXDMA> + 'd, | ||
| 57 | rx_dma: impl Peripheral<P = RXDMA> + 'd, | ||
| 58 | freq: Hertz, | ||
| 59 | config: Config, | ||
| 60 | ) -> Self { | ||
| 61 | into_ref!(scl, sda, tx_dma, rx_dma); | ||
| 62 | |||
| 63 | T::enable_and_reset(); | ||
| 64 | |||
| 65 | scl.set_as_af_pull( | ||
| 66 | scl.af_num(), | ||
| 67 | AFType::OutputOpenDrain, | ||
| 68 | match config.scl_pullup { | ||
| 69 | true => Pull::Up, | ||
| 70 | false => Pull::None, | ||
| 71 | }, | ||
| 72 | ); | ||
| 73 | sda.set_as_af_pull( | ||
| 74 | sda.af_num(), | ||
| 75 | AFType::OutputOpenDrain, | ||
| 76 | match config.sda_pullup { | ||
| 77 | true => Pull::Up, | ||
| 78 | false => Pull::None, | ||
| 79 | }, | ||
| 80 | ); | ||
| 81 | |||
| 82 | T::regs().cr1().modify(|reg| { | 29 | T::regs().cr1().modify(|reg| { |
| 83 | reg.set_pe(false); | 30 | reg.set_pe(false); |
| 84 | //reg.set_anfoff(false); | 31 | //reg.set_anfoff(false); |
| @@ -101,15 +48,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 101 | T::regs().cr1().modify(|reg| { | 48 | T::regs().cr1().modify(|reg| { |
| 102 | reg.set_pe(true); | 49 | reg.set_pe(true); |
| 103 | }); | 50 | }); |
| 104 | |||
| 105 | unsafe { T::EventInterrupt::enable() }; | ||
| 106 | unsafe { T::ErrorInterrupt::enable() }; | ||
| 107 | |||
| 108 | Self { | ||
| 109 | phantom: PhantomData, | ||
| 110 | tx_dma, | ||
| 111 | rx_dma, | ||
| 112 | } | ||
| 113 | } | 51 | } |
| 114 | 52 | ||
| 115 | fn check_and_clear_error_flags() -> Result<i2c::regs::Sr1, Error> { | 53 | fn check_and_clear_error_flags() -> Result<i2c::regs::Sr1, Error> { |
| @@ -169,12 +107,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 169 | Ok(sr1) | 107 | Ok(sr1) |
| 170 | } | 108 | } |
| 171 | 109 | ||
| 172 | fn write_bytes( | 110 | fn write_bytes(&mut self, addr: u8, bytes: &[u8], timeout: Timeout) -> Result<(), Error> { |
| 173 | &mut self, | ||
| 174 | addr: u8, | ||
| 175 | bytes: &[u8], | ||
| 176 | check_timeout: impl Fn() -> Result<(), Error>, | ||
| 177 | ) -> Result<(), Error> { | ||
| 178 | // Send a START condition | 111 | // Send a START condition |
| 179 | 112 | ||
| 180 | T::regs().cr1().modify(|reg| { | 113 | T::regs().cr1().modify(|reg| { |
| @@ -183,7 +116,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 183 | 116 | ||
| 184 | // Wait until START condition was generated | 117 | // Wait until START condition was generated |
| 185 | while !Self::check_and_clear_error_flags()?.start() { | 118 | while !Self::check_and_clear_error_flags()?.start() { |
| 186 | check_timeout()?; | 119 | timeout.check()?; |
| 187 | } | 120 | } |
| 188 | 121 | ||
| 189 | // Also wait until signalled we're master and everything is waiting for us | 122 | // Also wait until signalled we're master and everything is waiting for us |
| @@ -193,7 +126,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 193 | let sr2 = T::regs().sr2().read(); | 126 | let sr2 = T::regs().sr2().read(); |
| 194 | !sr2.msl() && !sr2.busy() | 127 | !sr2.msl() && !sr2.busy() |
| 195 | } { | 128 | } { |
| 196 | check_timeout()?; | 129 | timeout.check()?; |
| 197 | } | 130 | } |
| 198 | 131 | ||
| 199 | // Set up current address, we're trying to talk to | 132 | // Set up current address, we're trying to talk to |
| @@ -203,7 +136,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 203 | // Wait for the address to be acknowledged | 136 | // Wait for the address to be acknowledged |
| 204 | // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. | 137 | // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. |
| 205 | while !Self::check_and_clear_error_flags()?.addr() { | 138 | while !Self::check_and_clear_error_flags()?.addr() { |
| 206 | check_timeout()?; | 139 | timeout.check()?; |
| 207 | } | 140 | } |
| 208 | 141 | ||
| 209 | // Clear condition by reading SR2 | 142 | // Clear condition by reading SR2 |
| @@ -211,20 +144,20 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 211 | 144 | ||
| 212 | // Send bytes | 145 | // Send bytes |
| 213 | for c in bytes { | 146 | for c in bytes { |
| 214 | self.send_byte(*c, &check_timeout)?; | 147 | self.send_byte(*c, timeout)?; |
| 215 | } | 148 | } |
| 216 | 149 | ||
| 217 | // Fallthrough is success | 150 | // Fallthrough is success |
| 218 | Ok(()) | 151 | Ok(()) |
| 219 | } | 152 | } |
| 220 | 153 | ||
| 221 | fn send_byte(&self, byte: u8, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { | 154 | fn send_byte(&self, byte: u8, timeout: Timeout) -> Result<(), Error> { |
| 222 | // Wait until we're ready for sending | 155 | // Wait until we're ready for sending |
| 223 | while { | 156 | while { |
| 224 | // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. | 157 | // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. |
| 225 | !Self::check_and_clear_error_flags()?.txe() | 158 | !Self::check_and_clear_error_flags()?.txe() |
| 226 | } { | 159 | } { |
| 227 | check_timeout()?; | 160 | timeout.check()?; |
| 228 | } | 161 | } |
| 229 | 162 | ||
| 230 | // Push out a byte of data | 163 | // Push out a byte of data |
| @@ -235,32 +168,27 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 235 | // Check for any potential error conditions. | 168 | // Check for any potential error conditions. |
| 236 | !Self::check_and_clear_error_flags()?.btf() | 169 | !Self::check_and_clear_error_flags()?.btf() |
| 237 | } { | 170 | } { |
| 238 | check_timeout()?; | 171 | timeout.check()?; |
| 239 | } | 172 | } |
| 240 | 173 | ||
| 241 | Ok(()) | 174 | Ok(()) |
| 242 | } | 175 | } |
| 243 | 176 | ||
| 244 | fn recv_byte(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<u8, Error> { | 177 | fn recv_byte(&self, timeout: Timeout) -> Result<u8, Error> { |
| 245 | while { | 178 | while { |
| 246 | // Check for any potential error conditions. | 179 | // Check for any potential error conditions. |
| 247 | Self::check_and_clear_error_flags()?; | 180 | Self::check_and_clear_error_flags()?; |
| 248 | 181 | ||
| 249 | !T::regs().sr1().read().rxne() | 182 | !T::regs().sr1().read().rxne() |
| 250 | } { | 183 | } { |
| 251 | check_timeout()?; | 184 | timeout.check()?; |
| 252 | } | 185 | } |
| 253 | 186 | ||
| 254 | let value = T::regs().dr().read().dr(); | 187 | let value = T::regs().dr().read().dr(); |
| 255 | Ok(value) | 188 | Ok(value) |
| 256 | } | 189 | } |
| 257 | 190 | ||
| 258 | pub fn blocking_read_timeout( | 191 | fn blocking_read_timeout(&mut self, addr: u8, buffer: &mut [u8], timeout: Timeout) -> Result<(), Error> { |
| 259 | &mut self, | ||
| 260 | addr: u8, | ||
| 261 | buffer: &mut [u8], | ||
| 262 | check_timeout: impl Fn() -> Result<(), Error>, | ||
| 263 | ) -> Result<(), Error> { | ||
| 264 | if let Some((last, buffer)) = buffer.split_last_mut() { | 192 | if let Some((last, buffer)) = buffer.split_last_mut() { |
| 265 | // Send a START condition and set ACK bit | 193 | // Send a START condition and set ACK bit |
| 266 | T::regs().cr1().modify(|reg| { | 194 | T::regs().cr1().modify(|reg| { |
| @@ -270,7 +198,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 270 | 198 | ||
| 271 | // Wait until START condition was generated | 199 | // Wait until START condition was generated |
| 272 | while !Self::check_and_clear_error_flags()?.start() { | 200 | while !Self::check_and_clear_error_flags()?.start() { |
| 273 | check_timeout()?; | 201 | timeout.check()?; |
| 274 | } | 202 | } |
| 275 | 203 | ||
| 276 | // Also wait until signalled we're master and everything is waiting for us | 204 | // Also wait until signalled we're master and everything is waiting for us |
| @@ -278,7 +206,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 278 | let sr2 = T::regs().sr2().read(); | 206 | let sr2 = T::regs().sr2().read(); |
| 279 | !sr2.msl() && !sr2.busy() | 207 | !sr2.msl() && !sr2.busy() |
| 280 | } { | 208 | } { |
| 281 | check_timeout()?; | 209 | timeout.check()?; |
| 282 | } | 210 | } |
| 283 | 211 | ||
| 284 | // Set up current address, we're trying to talk to | 212 | // Set up current address, we're trying to talk to |
| @@ -287,7 +215,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 287 | // Wait until address was sent | 215 | // Wait until address was sent |
| 288 | // Wait for the address to be acknowledged | 216 | // Wait for the address to be acknowledged |
| 289 | while !Self::check_and_clear_error_flags()?.addr() { | 217 | while !Self::check_and_clear_error_flags()?.addr() { |
| 290 | check_timeout()?; | 218 | timeout.check()?; |
| 291 | } | 219 | } |
| 292 | 220 | ||
| 293 | // Clear condition by reading SR2 | 221 | // Clear condition by reading SR2 |
| @@ -295,7 +223,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 295 | 223 | ||
| 296 | // Receive bytes into buffer | 224 | // Receive bytes into buffer |
| 297 | for c in buffer { | 225 | for c in buffer { |
| 298 | *c = self.recv_byte(&check_timeout)?; | 226 | *c = self.recv_byte(timeout)?; |
| 299 | } | 227 | } |
| 300 | 228 | ||
| 301 | // Prepare to send NACK then STOP after next byte | 229 | // Prepare to send NACK then STOP after next byte |
| @@ -305,11 +233,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 305 | }); | 233 | }); |
| 306 | 234 | ||
| 307 | // Receive last byte | 235 | // Receive last byte |
| 308 | *last = self.recv_byte(&check_timeout)?; | 236 | *last = self.recv_byte(timeout)?; |
| 309 | 237 | ||
| 310 | // Wait for the STOP to be sent. | 238 | // Wait for the STOP to be sent. |
| 311 | while T::regs().cr1().read().stop() { | 239 | while T::regs().cr1().read().stop() { |
| 312 | check_timeout()?; | 240 | timeout.check()?; |
| 313 | } | 241 | } |
| 314 | 242 | ||
| 315 | // Fallthrough is success | 243 | // Fallthrough is success |
| @@ -320,48 +248,33 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 320 | } | 248 | } |
| 321 | 249 | ||
| 322 | pub fn blocking_read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Error> { | 250 | pub fn blocking_read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Error> { |
| 323 | self.blocking_read_timeout(addr, read, || Ok(())) | 251 | self.blocking_read_timeout(addr, read, self.timeout()) |
| 324 | } | 252 | } |
| 325 | 253 | ||
| 326 | pub fn blocking_write_timeout( | 254 | pub fn blocking_write(&mut self, addr: u8, write: &[u8]) -> Result<(), Error> { |
| 327 | &mut self, | 255 | let timeout = self.timeout(); |
| 328 | addr: u8, | 256 | |
| 329 | write: &[u8], | 257 | self.write_bytes(addr, write, timeout)?; |
| 330 | check_timeout: impl Fn() -> Result<(), Error>, | ||
| 331 | ) -> Result<(), Error> { | ||
| 332 | self.write_bytes(addr, write, &check_timeout)?; | ||
| 333 | // Send a STOP condition | 258 | // Send a STOP condition |
| 334 | T::regs().cr1().modify(|reg| reg.set_stop(true)); | 259 | T::regs().cr1().modify(|reg| reg.set_stop(true)); |
| 335 | // Wait for STOP condition to transmit. | 260 | // Wait for STOP condition to transmit. |
| 336 | while T::regs().cr1().read().stop() { | 261 | while T::regs().cr1().read().stop() { |
| 337 | check_timeout()?; | 262 | timeout.check()?; |
| 338 | } | 263 | } |
| 339 | 264 | ||
| 340 | // Fallthrough is success | 265 | // Fallthrough is success |
| 341 | Ok(()) | 266 | Ok(()) |
| 342 | } | 267 | } |
| 343 | 268 | ||
| 344 | pub fn blocking_write(&mut self, addr: u8, write: &[u8]) -> Result<(), Error> { | 269 | pub fn blocking_write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { |
| 345 | self.blocking_write_timeout(addr, write, || Ok(())) | 270 | let timeout = self.timeout(); |
| 346 | } | ||
| 347 | 271 | ||
| 348 | pub fn blocking_write_read_timeout( | 272 | self.write_bytes(addr, write, timeout)?; |
| 349 | &mut self, | 273 | self.blocking_read_timeout(addr, read, timeout)?; |
| 350 | addr: u8, | ||
| 351 | write: &[u8], | ||
| 352 | read: &mut [u8], | ||
| 353 | check_timeout: impl Fn() -> Result<(), Error>, | ||
| 354 | ) -> Result<(), Error> { | ||
| 355 | self.write_bytes(addr, write, &check_timeout)?; | ||
| 356 | self.blocking_read_timeout(addr, read, &check_timeout)?; | ||
| 357 | 274 | ||
| 358 | Ok(()) | 275 | Ok(()) |
| 359 | } | 276 | } |
| 360 | 277 | ||
| 361 | pub fn blocking_write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { | ||
| 362 | self.blocking_write_read_timeout(addr, write, read, || Ok(())) | ||
| 363 | } | ||
| 364 | |||
| 365 | // Async | 278 | // Async |
| 366 | 279 | ||
| 367 | #[inline] // pretty sure this should always be inlined | 280 | #[inline] // pretty sure this should always be inlined |
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 8c20e1c54..bd3abaac1 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs | |||
| @@ -4,37 +4,13 @@ use core::task::Poll; | |||
| 4 | 4 | ||
| 5 | use embassy_embedded_hal::SetConfig; | 5 | use embassy_embedded_hal::SetConfig; |
| 6 | use embassy_hal_internal::drop::OnDrop; | 6 | use embassy_hal_internal::drop::OnDrop; |
| 7 | use embassy_hal_internal::{into_ref, PeripheralRef}; | ||
| 8 | #[cfg(feature = "time")] | ||
| 9 | use embassy_time::{Duration, Instant}; | ||
| 10 | 7 | ||
| 11 | use super::*; | 8 | use super::*; |
| 12 | use crate::dma::{NoDma, Transfer}; | 9 | use crate::dma::Transfer; |
| 13 | use crate::gpio::sealed::AFType; | ||
| 14 | use crate::gpio::Pull; | ||
| 15 | use crate::interrupt::typelevel::Interrupt; | ||
| 16 | use crate::pac::i2c; | 10 | use crate::pac::i2c; |
| 17 | use crate::time::Hertz; | 11 | use crate::time::Hertz; |
| 18 | use crate::{interrupt, Peripheral}; | ||
| 19 | |||
| 20 | #[cfg(feature = "time")] | ||
| 21 | fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> { | ||
| 22 | let deadline = Instant::now() + timeout; | ||
| 23 | move || { | ||
| 24 | if Instant::now() > deadline { | ||
| 25 | Err(Error::Timeout) | ||
| 26 | } else { | ||
| 27 | Ok(()) | ||
| 28 | } | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | #[cfg(not(feature = "time"))] | ||
| 33 | pub fn no_timeout_fn() -> impl Fn() -> Result<(), Error> { | ||
| 34 | move || Ok(()) | ||
| 35 | } | ||
| 36 | 12 | ||
| 37 | pub unsafe fn on_interrupt<T: Instance>() { | 13 | pub(crate) unsafe fn on_interrupt<T: Instance>() { |
| 38 | let regs = T::regs(); | 14 | let regs = T::regs(); |
| 39 | let isr = regs.isr().read(); | 15 | let isr = regs.isr().read(); |
| 40 | 16 | ||
| @@ -48,70 +24,8 @@ pub unsafe fn on_interrupt<T: Instance>() { | |||
| 48 | }); | 24 | }); |
| 49 | } | 25 | } |
| 50 | 26 | ||
| 51 | #[non_exhaustive] | ||
| 52 | #[derive(Copy, Clone)] | ||
| 53 | pub struct Config { | ||
| 54 | pub sda_pullup: bool, | ||
| 55 | pub scl_pullup: bool, | ||
| 56 | #[cfg(feature = "time")] | ||
| 57 | pub transaction_timeout: Duration, | ||
| 58 | } | ||
| 59 | |||
| 60 | impl Default for Config { | ||
| 61 | fn default() -> Self { | ||
| 62 | Self { | ||
| 63 | sda_pullup: false, | ||
| 64 | scl_pullup: false, | ||
| 65 | #[cfg(feature = "time")] | ||
| 66 | transaction_timeout: Duration::from_millis(100), | ||
| 67 | } | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 | pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> { | ||
| 72 | _peri: PeripheralRef<'d, T>, | ||
| 73 | #[allow(dead_code)] | ||
| 74 | tx_dma: PeripheralRef<'d, TXDMA>, | ||
| 75 | #[allow(dead_code)] | ||
| 76 | rx_dma: PeripheralRef<'d, RXDMA>, | ||
| 77 | #[cfg(feature = "time")] | ||
| 78 | timeout: Duration, | ||
| 79 | } | ||
| 80 | |||
| 81 | impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | 27 | impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { |
| 82 | pub fn new( | 28 | pub(crate) fn init(&mut self, freq: Hertz, _config: Config) { |
| 83 | peri: impl Peripheral<P = T> + 'd, | ||
| 84 | scl: impl Peripheral<P = impl SclPin<T>> + 'd, | ||
| 85 | sda: impl Peripheral<P = impl SdaPin<T>> + 'd, | ||
| 86 | _irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>> | ||
| 87 | + interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>> | ||
| 88 | + 'd, | ||
| 89 | tx_dma: impl Peripheral<P = TXDMA> + 'd, | ||
| 90 | rx_dma: impl Peripheral<P = RXDMA> + 'd, | ||
| 91 | freq: Hertz, | ||
| 92 | config: Config, | ||
| 93 | ) -> Self { | ||
| 94 | into_ref!(peri, scl, sda, tx_dma, rx_dma); | ||
| 95 | |||
| 96 | T::enable_and_reset(); | ||
| 97 | |||
| 98 | scl.set_as_af_pull( | ||
| 99 | scl.af_num(), | ||
| 100 | AFType::OutputOpenDrain, | ||
| 101 | match config.scl_pullup { | ||
| 102 | true => Pull::Up, | ||
| 103 | false => Pull::None, | ||
| 104 | }, | ||
| 105 | ); | ||
| 106 | sda.set_as_af_pull( | ||
| 107 | sda.af_num(), | ||
| 108 | AFType::OutputOpenDrain, | ||
| 109 | match config.sda_pullup { | ||
| 110 | true => Pull::Up, | ||
| 111 | false => Pull::None, | ||
| 112 | }, | ||
| 113 | ); | ||
| 114 | |||
| 115 | T::regs().cr1().modify(|reg| { | 29 | T::regs().cr1().modify(|reg| { |
| 116 | reg.set_pe(false); | 30 | reg.set_pe(false); |
| 117 | reg.set_anfoff(false); | 31 | reg.set_anfoff(false); |
| @@ -130,17 +44,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 130 | T::regs().cr1().modify(|reg| { | 44 | T::regs().cr1().modify(|reg| { |
| 131 | reg.set_pe(true); | 45 | reg.set_pe(true); |
| 132 | }); | 46 | }); |
| 133 | |||
| 134 | unsafe { T::EventInterrupt::enable() }; | ||
| 135 | unsafe { T::ErrorInterrupt::enable() }; | ||
| 136 | |||
| 137 | Self { | ||
| 138 | _peri: peri, | ||
| 139 | tx_dma, | ||
| 140 | rx_dma, | ||
| 141 | #[cfg(feature = "time")] | ||
| 142 | timeout: config.transaction_timeout, | ||
| 143 | } | ||
| 144 | } | 47 | } |
| 145 | 48 | ||
| 146 | fn master_stop(&mut self) { | 49 | fn master_stop(&mut self) { |
| @@ -153,7 +56,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 153 | stop: Stop, | 56 | stop: Stop, |
| 154 | reload: bool, | 57 | reload: bool, |
| 155 | restart: bool, | 58 | restart: bool, |
| 156 | check_timeout: impl Fn() -> Result<(), Error>, | 59 | timeout: Timeout, |
| 157 | ) -> Result<(), Error> { | 60 | ) -> Result<(), Error> { |
| 158 | assert!(length < 256); | 61 | assert!(length < 256); |
| 159 | 62 | ||
| @@ -162,7 +65,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 162 | // automatically. This could be up to 50% of a bus | 65 | // automatically. This could be up to 50% of a bus |
| 163 | // cycle (ie. up to 0.5/freq) | 66 | // cycle (ie. up to 0.5/freq) |
| 164 | while T::regs().cr2().read().start() { | 67 | while T::regs().cr2().read().start() { |
| 165 | check_timeout()?; | 68 | timeout.check()?; |
| 166 | } | 69 | } |
| 167 | } | 70 | } |
| 168 | 71 | ||
| @@ -189,20 +92,14 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 189 | Ok(()) | 92 | Ok(()) |
| 190 | } | 93 | } |
| 191 | 94 | ||
| 192 | fn master_write( | 95 | fn master_write(address: u8, length: usize, stop: Stop, reload: bool, timeout: Timeout) -> Result<(), Error> { |
| 193 | address: u8, | ||
| 194 | length: usize, | ||
| 195 | stop: Stop, | ||
| 196 | reload: bool, | ||
| 197 | check_timeout: impl Fn() -> Result<(), Error>, | ||
| 198 | ) -> Result<(), Error> { | ||
| 199 | assert!(length < 256); | 96 | assert!(length < 256); |
| 200 | 97 | ||
| 201 | // Wait for any previous address sequence to end | 98 | // Wait for any previous address sequence to end |
| 202 | // automatically. This could be up to 50% of a bus | 99 | // automatically. This could be up to 50% of a bus |
| 203 | // cycle (ie. up to 0.5/freq) | 100 | // cycle (ie. up to 0.5/freq) |
| 204 | while T::regs().cr2().read().start() { | 101 | while T::regs().cr2().read().start() { |
| 205 | check_timeout()?; | 102 | timeout.check()?; |
| 206 | } | 103 | } |
| 207 | 104 | ||
| 208 | let reload = if reload { | 105 | let reload = if reload { |
| @@ -227,15 +124,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 227 | Ok(()) | 124 | Ok(()) |
| 228 | } | 125 | } |
| 229 | 126 | ||
| 230 | fn master_continue( | 127 | fn master_continue(length: usize, reload: bool, timeout: Timeout) -> Result<(), Error> { |
| 231 | length: usize, | ||
| 232 | reload: bool, | ||
| 233 | check_timeout: impl Fn() -> Result<(), Error>, | ||
| 234 | ) -> Result<(), Error> { | ||
| 235 | assert!(length < 256 && length > 0); | 128 | assert!(length < 256 && length > 0); |
| 236 | 129 | ||
| 237 | while !T::regs().isr().read().tcr() { | 130 | while !T::regs().isr().read().tcr() { |
| 238 | check_timeout()?; | 131 | timeout.check()?; |
| 239 | } | 132 | } |
| 240 | 133 | ||
| 241 | let reload = if reload { | 134 | let reload = if reload { |
| @@ -261,7 +154,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 261 | } | 154 | } |
| 262 | } | 155 | } |
| 263 | 156 | ||
| 264 | fn wait_txe(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { | 157 | fn wait_txe(&self, timeout: Timeout) -> Result<(), Error> { |
| 265 | loop { | 158 | loop { |
| 266 | let isr = T::regs().isr().read(); | 159 | let isr = T::regs().isr().read(); |
| 267 | if isr.txe() { | 160 | if isr.txe() { |
| @@ -278,11 +171,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 278 | return Err(Error::Nack); | 171 | return Err(Error::Nack); |
| 279 | } | 172 | } |
| 280 | 173 | ||
| 281 | check_timeout()?; | 174 | timeout.check()?; |
| 282 | } | 175 | } |
| 283 | } | 176 | } |
| 284 | 177 | ||
| 285 | fn wait_rxne(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { | 178 | fn wait_rxne(&self, timeout: Timeout) -> Result<(), Error> { |
| 286 | loop { | 179 | loop { |
| 287 | let isr = T::regs().isr().read(); | 180 | let isr = T::regs().isr().read(); |
| 288 | if isr.rxne() { | 181 | if isr.rxne() { |
| @@ -299,11 +192,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 299 | return Err(Error::Nack); | 192 | return Err(Error::Nack); |
| 300 | } | 193 | } |
| 301 | 194 | ||
| 302 | check_timeout()?; | 195 | timeout.check()?; |
| 303 | } | 196 | } |
| 304 | } | 197 | } |
| 305 | 198 | ||
| 306 | fn wait_tc(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { | 199 | fn wait_tc(&self, timeout: Timeout) -> Result<(), Error> { |
| 307 | loop { | 200 | loop { |
| 308 | let isr = T::regs().isr().read(); | 201 | let isr = T::regs().isr().read(); |
| 309 | if isr.tc() { | 202 | if isr.tc() { |
| @@ -320,17 +213,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 320 | return Err(Error::Nack); | 213 | return Err(Error::Nack); |
| 321 | } | 214 | } |
| 322 | 215 | ||
| 323 | check_timeout()?; | 216 | timeout.check()?; |
| 324 | } | 217 | } |
| 325 | } | 218 | } |
| 326 | 219 | ||
| 327 | fn read_internal( | 220 | fn read_internal(&mut self, address: u8, read: &mut [u8], restart: bool, timeout: Timeout) -> Result<(), Error> { |
| 328 | &mut self, | ||
| 329 | address: u8, | ||
| 330 | read: &mut [u8], | ||
| 331 | restart: bool, | ||
| 332 | check_timeout: impl Fn() -> Result<(), Error>, | ||
| 333 | ) -> Result<(), Error> { | ||
| 334 | let completed_chunks = read.len() / 255; | 221 | let completed_chunks = read.len() / 255; |
| 335 | let total_chunks = if completed_chunks * 255 == read.len() { | 222 | let total_chunks = if completed_chunks * 255 == read.len() { |
| 336 | completed_chunks | 223 | completed_chunks |
| @@ -345,17 +232,17 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 345 | Stop::Automatic, | 232 | Stop::Automatic, |
| 346 | last_chunk_idx != 0, | 233 | last_chunk_idx != 0, |
| 347 | restart, | 234 | restart, |
| 348 | &check_timeout, | 235 | timeout, |
| 349 | )?; | 236 | )?; |
| 350 | 237 | ||
| 351 | for (number, chunk) in read.chunks_mut(255).enumerate() { | 238 | for (number, chunk) in read.chunks_mut(255).enumerate() { |
| 352 | if number != 0 { | 239 | if number != 0 { |
| 353 | Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?; | 240 | Self::master_continue(chunk.len(), number != last_chunk_idx, timeout)?; |
| 354 | } | 241 | } |
| 355 | 242 | ||
| 356 | for byte in chunk { | 243 | for byte in chunk { |
| 357 | // Wait until we have received something | 244 | // Wait until we have received something |
| 358 | self.wait_rxne(&check_timeout)?; | 245 | self.wait_rxne(timeout)?; |
| 359 | 246 | ||
| 360 | *byte = T::regs().rxdr().read().rxdata(); | 247 | *byte = T::regs().rxdr().read().rxdata(); |
| 361 | } | 248 | } |
| @@ -363,13 +250,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 363 | Ok(()) | 250 | Ok(()) |
| 364 | } | 251 | } |
| 365 | 252 | ||
| 366 | fn write_internal( | 253 | fn write_internal(&mut self, address: u8, write: &[u8], send_stop: bool, timeout: Timeout) -> Result<(), Error> { |
| 367 | &mut self, | ||
| 368 | address: u8, | ||
| 369 | write: &[u8], | ||
| 370 | send_stop: bool, | ||
| 371 | check_timeout: impl Fn() -> Result<(), Error>, | ||
| 372 | ) -> Result<(), Error> { | ||
| 373 | let completed_chunks = write.len() / 255; | 254 | let completed_chunks = write.len() / 255; |
| 374 | let total_chunks = if completed_chunks * 255 == write.len() { | 255 | let total_chunks = if completed_chunks * 255 == write.len() { |
| 375 | completed_chunks | 256 | completed_chunks |
| @@ -386,7 +267,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 386 | write.len().min(255), | 267 | write.len().min(255), |
| 387 | Stop::Software, | 268 | Stop::Software, |
| 388 | last_chunk_idx != 0, | 269 | last_chunk_idx != 0, |
| 389 | &check_timeout, | 270 | timeout, |
| 390 | ) { | 271 | ) { |
| 391 | if send_stop { | 272 | if send_stop { |
| 392 | self.master_stop(); | 273 | self.master_stop(); |
| @@ -396,14 +277,14 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 396 | 277 | ||
| 397 | for (number, chunk) in write.chunks(255).enumerate() { | 278 | for (number, chunk) in write.chunks(255).enumerate() { |
| 398 | if number != 0 { | 279 | if number != 0 { |
| 399 | Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?; | 280 | Self::master_continue(chunk.len(), number != last_chunk_idx, timeout)?; |
| 400 | } | 281 | } |
| 401 | 282 | ||
| 402 | for byte in chunk { | 283 | for byte in chunk { |
| 403 | // Wait until we are allowed to send data | 284 | // Wait until we are allowed to send data |
| 404 | // (START has been ACKed or last byte when | 285 | // (START has been ACKed or last byte when |
| 405 | // through) | 286 | // through) |
| 406 | if let Err(err) = self.wait_txe(&check_timeout) { | 287 | if let Err(err) = self.wait_txe(timeout) { |
| 407 | if send_stop { | 288 | if send_stop { |
| 408 | self.master_stop(); | 289 | self.master_stop(); |
| 409 | } | 290 | } |
| @@ -414,7 +295,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 414 | } | 295 | } |
| 415 | } | 296 | } |
| 416 | // Wait until the write finishes | 297 | // Wait until the write finishes |
| 417 | let result = self.wait_tc(&check_timeout); | 298 | let result = self.wait_tc(timeout); |
| 418 | if send_stop { | 299 | if send_stop { |
| 419 | self.master_stop(); | 300 | self.master_stop(); |
| 420 | } | 301 | } |
| @@ -427,7 +308,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 427 | write: &[u8], | 308 | write: &[u8], |
| 428 | first_slice: bool, | 309 | first_slice: bool, |
| 429 | last_slice: bool, | 310 | last_slice: bool, |
| 430 | check_timeout: impl Fn() -> Result<(), Error>, | 311 | timeout: Timeout, |
| 431 | ) -> Result<(), Error> | 312 | ) -> Result<(), Error> |
| 432 | where | 313 | where |
| 433 | TXDMA: crate::i2c::TxDma<T>, | 314 | TXDMA: crate::i2c::TxDma<T>, |
| @@ -473,10 +354,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 473 | total_len.min(255), | 354 | total_len.min(255), |
| 474 | Stop::Software, | 355 | Stop::Software, |
| 475 | (total_len > 255) || !last_slice, | 356 | (total_len > 255) || !last_slice, |
| 476 | &check_timeout, | 357 | timeout, |
| 477 | )?; | 358 | )?; |
| 478 | } else { | 359 | } else { |
| 479 | Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, &check_timeout)?; | 360 | Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, timeout)?; |
| 480 | T::regs().cr1().modify(|w| w.set_tcie(true)); | 361 | T::regs().cr1().modify(|w| w.set_tcie(true)); |
| 481 | } | 362 | } |
| 482 | } else if !(isr.tcr() || isr.tc()) { | 363 | } else if !(isr.tcr() || isr.tc()) { |
| @@ -487,7 +368,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 487 | } else { | 368 | } else { |
| 488 | let last_piece = (remaining_len <= 255) && last_slice; | 369 | let last_piece = (remaining_len <= 255) && last_slice; |
| 489 | 370 | ||
| 490 | if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) { | 371 | if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, timeout) { |
| 491 | return Poll::Ready(Err(e)); | 372 | return Poll::Ready(Err(e)); |
| 492 | } | 373 | } |
| 493 | T::regs().cr1().modify(|w| w.set_tcie(true)); | 374 | T::regs().cr1().modify(|w| w.set_tcie(true)); |
| @@ -502,7 +383,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 502 | 383 | ||
| 503 | if last_slice { | 384 | if last_slice { |
| 504 | // This should be done already | 385 | // This should be done already |
| 505 | self.wait_tc(&check_timeout)?; | 386 | self.wait_tc(timeout)?; |
| 506 | self.master_stop(); | 387 | self.master_stop(); |
| 507 | } | 388 | } |
| 508 | 389 | ||
| @@ -516,7 +397,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 516 | address: u8, | 397 | address: u8, |
| 517 | buffer: &mut [u8], | 398 | buffer: &mut [u8], |
| 518 | restart: bool, | 399 | restart: bool, |
| 519 | check_timeout: impl Fn() -> Result<(), Error>, | 400 | timeout: Timeout, |
| 520 | ) -> Result<(), Error> | 401 | ) -> Result<(), Error> |
| 521 | where | 402 | where |
| 522 | RXDMA: crate::i2c::RxDma<T>, | 403 | RXDMA: crate::i2c::RxDma<T>, |
| @@ -558,7 +439,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 558 | Stop::Software, | 439 | Stop::Software, |
| 559 | total_len > 255, | 440 | total_len > 255, |
| 560 | restart, | 441 | restart, |
| 561 | &check_timeout, | 442 | timeout, |
| 562 | )?; | 443 | )?; |
| 563 | } else if !(isr.tcr() || isr.tc()) { | 444 | } else if !(isr.tcr() || isr.tc()) { |
| 564 | // poll_fn was woken without an interrupt present | 445 | // poll_fn was woken without an interrupt present |
| @@ -568,7 +449,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 568 | } else { | 449 | } else { |
| 569 | let last_piece = remaining_len <= 255; | 450 | let last_piece = remaining_len <= 255; |
| 570 | 451 | ||
| 571 | if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) { | 452 | if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, timeout) { |
| 572 | return Poll::Ready(Err(e)); | 453 | return Poll::Ready(Err(e)); |
| 573 | } | 454 | } |
| 574 | T::regs().cr1().modify(|w| w.set_tcie(true)); | 455 | T::regs().cr1().modify(|w| w.set_tcie(true)); |
| @@ -582,7 +463,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 582 | dma_transfer.await; | 463 | dma_transfer.await; |
| 583 | 464 | ||
| 584 | // This should be done already | 465 | // This should be done already |
| 585 | self.wait_tc(&check_timeout)?; | 466 | self.wait_tc(timeout)?; |
| 586 | self.master_stop(); | 467 | self.master_stop(); |
| 587 | 468 | ||
| 588 | drop(on_drop); | 469 | drop(on_drop); |
| @@ -592,69 +473,31 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 592 | 473 | ||
| 593 | // ========================= | 474 | // ========================= |
| 594 | // Async public API | 475 | // Async public API |
| 595 | #[cfg(feature = "time")] | ||
| 596 | pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> | ||
| 597 | where | ||
| 598 | TXDMA: crate::i2c::TxDma<T>, | ||
| 599 | { | ||
| 600 | if write.is_empty() { | ||
| 601 | self.write_internal(address, write, true, timeout_fn(self.timeout)) | ||
| 602 | } else { | ||
| 603 | embassy_time::with_timeout( | ||
| 604 | self.timeout, | ||
| 605 | self.write_dma_internal(address, write, true, true, timeout_fn(self.timeout)), | ||
| 606 | ) | ||
| 607 | .await | ||
| 608 | .unwrap_or(Err(Error::Timeout)) | ||
| 609 | } | ||
| 610 | } | ||
| 611 | 476 | ||
| 612 | #[cfg(not(feature = "time"))] | 477 | /// Write. |
| 613 | pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> | 478 | pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> |
| 614 | where | 479 | where |
| 615 | TXDMA: crate::i2c::TxDma<T>, | 480 | TXDMA: crate::i2c::TxDma<T>, |
| 616 | { | 481 | { |
| 482 | let timeout = self.timeout(); | ||
| 617 | if write.is_empty() { | 483 | if write.is_empty() { |
| 618 | self.write_internal(address, write, true, no_timeout_fn()) | 484 | self.write_internal(address, write, true, timeout) |
| 619 | } else { | 485 | } else { |
| 620 | self.write_dma_internal(address, write, true, true, no_timeout_fn()) | 486 | timeout |
| 487 | .with(self.write_dma_internal(address, write, true, true, timeout)) | ||
| 621 | .await | 488 | .await |
| 622 | } | 489 | } |
| 623 | } | 490 | } |
| 624 | 491 | ||
| 625 | #[cfg(feature = "time")] | 492 | /// Write multiple buffers. |
| 493 | /// | ||
| 494 | /// The buffers are concatenated in a single write transaction. | ||
| 626 | pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> | 495 | pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> |
| 627 | where | 496 | where |
| 628 | TXDMA: crate::i2c::TxDma<T>, | 497 | TXDMA: crate::i2c::TxDma<T>, |
| 629 | { | 498 | { |
| 630 | if write.is_empty() { | 499 | let timeout = self.timeout(); |
| 631 | return Err(Error::ZeroLengthTransfer); | ||
| 632 | } | ||
| 633 | let mut iter = write.iter(); | ||
| 634 | |||
| 635 | let mut first = true; | ||
| 636 | let mut current = iter.next(); | ||
| 637 | while let Some(c) = current { | ||
| 638 | let next = iter.next(); | ||
| 639 | let is_last = next.is_none(); | ||
| 640 | |||
| 641 | embassy_time::with_timeout( | ||
| 642 | self.timeout, | ||
| 643 | self.write_dma_internal(address, c, first, is_last, timeout_fn(self.timeout)), | ||
| 644 | ) | ||
| 645 | .await | ||
| 646 | .unwrap_or(Err(Error::Timeout))?; | ||
| 647 | first = false; | ||
| 648 | current = next; | ||
| 649 | } | ||
| 650 | Ok(()) | ||
| 651 | } | ||
| 652 | 500 | ||
| 653 | #[cfg(not(feature = "time"))] | ||
| 654 | pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> | ||
| 655 | where | ||
| 656 | TXDMA: crate::i2c::TxDma<T>, | ||
| 657 | { | ||
| 658 | if write.is_empty() { | 501 | if write.is_empty() { |
| 659 | return Err(Error::ZeroLengthTransfer); | 502 | return Err(Error::ZeroLengthTransfer); |
| 660 | } | 503 | } |
| @@ -666,95 +509,49 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 666 | let next = iter.next(); | 509 | let next = iter.next(); |
| 667 | let is_last = next.is_none(); | 510 | let is_last = next.is_none(); |
| 668 | 511 | ||
| 669 | self.write_dma_internal(address, c, first, is_last, no_timeout_fn()) | 512 | let fut = self.write_dma_internal(address, c, first, is_last, timeout); |
| 670 | .await?; | 513 | timeout.with(fut).await?; |
| 671 | first = false; | 514 | first = false; |
| 672 | current = next; | 515 | current = next; |
| 673 | } | 516 | } |
| 674 | Ok(()) | 517 | Ok(()) |
| 675 | } | 518 | } |
| 676 | 519 | ||
| 677 | #[cfg(feature = "time")] | 520 | /// Read. |
| 678 | pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> | 521 | pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> |
| 679 | where | 522 | where |
| 680 | RXDMA: crate::i2c::RxDma<T>, | 523 | RXDMA: crate::i2c::RxDma<T>, |
| 681 | { | 524 | { |
| 682 | if buffer.is_empty() { | 525 | let timeout = self.timeout(); |
| 683 | self.read_internal(address, buffer, false, timeout_fn(self.timeout)) | ||
| 684 | } else { | ||
| 685 | embassy_time::with_timeout( | ||
| 686 | self.timeout, | ||
| 687 | self.read_dma_internal(address, buffer, false, timeout_fn(self.timeout)), | ||
| 688 | ) | ||
| 689 | .await | ||
| 690 | .unwrap_or(Err(Error::Timeout)) | ||
| 691 | } | ||
| 692 | } | ||
| 693 | 526 | ||
| 694 | #[cfg(not(feature = "time"))] | ||
| 695 | pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> | ||
| 696 | where | ||
| 697 | RXDMA: crate::i2c::RxDma<T>, | ||
| 698 | { | ||
| 699 | if buffer.is_empty() { | 527 | if buffer.is_empty() { |
| 700 | self.read_internal(address, buffer, false, no_timeout_fn()) | 528 | self.read_internal(address, buffer, false, timeout) |
| 701 | } else { | 529 | } else { |
| 702 | self.read_dma_internal(address, buffer, false, no_timeout_fn()).await | 530 | let fut = self.read_dma_internal(address, buffer, false, timeout); |
| 531 | timeout.with(fut).await | ||
| 703 | } | 532 | } |
| 704 | } | 533 | } |
| 705 | 534 | ||
| 706 | #[cfg(feature = "time")] | 535 | /// Write, restart, read. |
| 707 | pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> | 536 | pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> |
| 708 | where | 537 | where |
| 709 | TXDMA: super::TxDma<T>, | 538 | TXDMA: super::TxDma<T>, |
| 710 | RXDMA: super::RxDma<T>, | 539 | RXDMA: super::RxDma<T>, |
| 711 | { | 540 | { |
| 712 | let start_instant = Instant::now(); | 541 | let timeout = self.timeout(); |
| 713 | let check_timeout = timeout_fn(self.timeout); | ||
| 714 | if write.is_empty() { | ||
| 715 | self.write_internal(address, write, false, &check_timeout)?; | ||
| 716 | } else { | ||
| 717 | embassy_time::with_timeout( | ||
| 718 | self.timeout, | ||
| 719 | self.write_dma_internal(address, write, true, true, &check_timeout), | ||
| 720 | ) | ||
| 721 | .await | ||
| 722 | .unwrap_or(Err(Error::Timeout))?; | ||
| 723 | } | ||
| 724 | |||
| 725 | let time_left_until_timeout = self.timeout - Instant::now().duration_since(start_instant); | ||
| 726 | 542 | ||
| 727 | if read.is_empty() { | ||
| 728 | self.read_internal(address, read, true, &check_timeout)?; | ||
| 729 | } else { | ||
| 730 | embassy_time::with_timeout( | ||
| 731 | time_left_until_timeout, | ||
| 732 | self.read_dma_internal(address, read, true, &check_timeout), | ||
| 733 | ) | ||
| 734 | .await | ||
| 735 | .unwrap_or(Err(Error::Timeout))?; | ||
| 736 | } | ||
| 737 | |||
| 738 | Ok(()) | ||
| 739 | } | ||
| 740 | |||
| 741 | #[cfg(not(feature = "time"))] | ||
| 742 | pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> | ||
| 743 | where | ||
| 744 | TXDMA: super::TxDma<T>, | ||
| 745 | RXDMA: super::RxDma<T>, | ||
| 746 | { | ||
| 747 | let no_timeout = no_timeout_fn(); | ||
| 748 | if write.is_empty() { | 543 | if write.is_empty() { |
| 749 | self.write_internal(address, write, false, &no_timeout)?; | 544 | self.write_internal(address, write, false, timeout)?; |
| 750 | } else { | 545 | } else { |
| 751 | self.write_dma_internal(address, write, true, true, &no_timeout).await?; | 546 | let fut = self.write_dma_internal(address, write, true, true, timeout); |
| 547 | timeout.with(fut).await?; | ||
| 752 | } | 548 | } |
| 753 | 549 | ||
| 754 | if read.is_empty() { | 550 | if read.is_empty() { |
| 755 | self.read_internal(address, read, true, &no_timeout)?; | 551 | self.read_internal(address, read, true, timeout)?; |
| 756 | } else { | 552 | } else { |
| 757 | self.read_dma_internal(address, read, true, &no_timeout).await?; | 553 | let fut = self.read_dma_internal(address, read, true, timeout); |
| 554 | timeout.with(fut).await?; | ||
| 758 | } | 555 | } |
| 759 | 556 | ||
| 760 | Ok(()) | 557 | Ok(()) |
| @@ -763,105 +560,35 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 763 | // ========================= | 560 | // ========================= |
| 764 | // Blocking public API | 561 | // Blocking public API |
| 765 | 562 | ||
| 766 | #[cfg(feature = "time")] | 563 | /// Blocking read. |
| 767 | pub fn blocking_read_timeout(&mut self, address: u8, read: &mut [u8], timeout: Duration) -> Result<(), Error> { | ||
| 768 | self.read_internal(address, read, false, timeout_fn(timeout)) | ||
| 769 | // Automatic Stop | ||
| 770 | } | ||
| 771 | |||
| 772 | #[cfg(not(feature = "time"))] | ||
| 773 | pub fn blocking_read_timeout( | ||
| 774 | &mut self, | ||
| 775 | address: u8, | ||
| 776 | read: &mut [u8], | ||
| 777 | check_timeout: impl Fn() -> Result<(), Error>, | ||
| 778 | ) -> Result<(), Error> { | ||
| 779 | self.read_internal(address, read, false, check_timeout) | ||
| 780 | // Automatic Stop | ||
| 781 | } | ||
| 782 | |||
| 783 | #[cfg(feature = "time")] | ||
| 784 | pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> { | ||
| 785 | self.blocking_read_timeout(address, read, self.timeout) | ||
| 786 | } | ||
| 787 | |||
| 788 | #[cfg(not(feature = "time"))] | ||
| 789 | pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> { | 564 | pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> { |
| 790 | self.blocking_read_timeout(address, read, || Ok(())) | 565 | self.read_internal(address, read, false, self.timeout()) |
| 791 | } | ||
| 792 | |||
| 793 | #[cfg(feature = "time")] | ||
| 794 | pub fn blocking_write_timeout(&mut self, address: u8, write: &[u8], timeout: Duration) -> Result<(), Error> { | ||
| 795 | self.write_internal(address, write, true, timeout_fn(timeout)) | ||
| 796 | } | ||
| 797 | |||
| 798 | #[cfg(not(feature = "time"))] | ||
| 799 | pub fn blocking_write_timeout( | ||
| 800 | &mut self, | ||
| 801 | address: u8, | ||
| 802 | write: &[u8], | ||
| 803 | check_timeout: impl Fn() -> Result<(), Error>, | ||
| 804 | ) -> Result<(), Error> { | ||
| 805 | self.write_internal(address, write, true, check_timeout) | ||
| 806 | } | ||
| 807 | |||
| 808 | #[cfg(feature = "time")] | ||
| 809 | pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { | ||
| 810 | self.blocking_write_timeout(address, write, self.timeout) | ||
| 811 | } | ||
| 812 | |||
| 813 | #[cfg(not(feature = "time"))] | ||
| 814 | pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { | ||
| 815 | self.blocking_write_timeout(address, write, || Ok(())) | ||
| 816 | } | ||
| 817 | |||
| 818 | #[cfg(feature = "time")] | ||
| 819 | pub fn blocking_write_read_timeout( | ||
| 820 | &mut self, | ||
| 821 | address: u8, | ||
| 822 | write: &[u8], | ||
| 823 | read: &mut [u8], | ||
| 824 | timeout: Duration, | ||
| 825 | ) -> Result<(), Error> { | ||
| 826 | let check_timeout = timeout_fn(timeout); | ||
| 827 | self.write_internal(address, write, false, &check_timeout)?; | ||
| 828 | self.read_internal(address, read, true, &check_timeout) | ||
| 829 | // Automatic Stop | 566 | // Automatic Stop |
| 830 | } | 567 | } |
| 831 | 568 | ||
| 832 | #[cfg(not(feature = "time"))] | 569 | /// Blocking write. |
| 833 | pub fn blocking_write_read_timeout( | 570 | pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { |
| 834 | &mut self, | 571 | self.write_internal(address, write, true, self.timeout()) |
| 835 | address: u8, | ||
| 836 | write: &[u8], | ||
| 837 | read: &mut [u8], | ||
| 838 | check_timeout: impl Fn() -> Result<(), Error>, | ||
| 839 | ) -> Result<(), Error> { | ||
| 840 | self.write_internal(address, write, false, &check_timeout)?; | ||
| 841 | self.read_internal(address, read, true, &check_timeout) | ||
| 842 | // Automatic Stop | ||
| 843 | } | ||
| 844 | |||
| 845 | #[cfg(feature = "time")] | ||
| 846 | pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { | ||
| 847 | self.blocking_write_read_timeout(address, write, read, self.timeout) | ||
| 848 | } | 572 | } |
| 849 | 573 | ||
| 850 | #[cfg(not(feature = "time"))] | 574 | /// Blocking write, restart, read. |
| 851 | pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { | 575 | pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { |
| 852 | self.blocking_write_read_timeout(address, write, read, || Ok(())) | 576 | let timeout = self.timeout(); |
| 577 | self.write_internal(address, write, false, timeout)?; | ||
| 578 | self.read_internal(address, read, true, timeout) | ||
| 579 | // Automatic Stop | ||
| 853 | } | 580 | } |
| 854 | 581 | ||
| 855 | fn blocking_write_vectored_with_timeout( | 582 | /// Blocking write multiple buffers. |
| 856 | &mut self, | 583 | /// |
| 857 | address: u8, | 584 | /// The buffers are concatenated in a single write transaction. |
| 858 | write: &[&[u8]], | 585 | pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> { |
| 859 | check_timeout: impl Fn() -> Result<(), Error>, | ||
| 860 | ) -> Result<(), Error> { | ||
| 861 | if write.is_empty() { | 586 | if write.is_empty() { |
| 862 | return Err(Error::ZeroLengthTransfer); | 587 | return Err(Error::ZeroLengthTransfer); |
| 863 | } | 588 | } |
| 864 | 589 | ||
| 590 | let timeout = self.timeout(); | ||
| 591 | |||
| 865 | let first_length = write[0].len(); | 592 | let first_length = write[0].len(); |
| 866 | let last_slice_index = write.len() - 1; | 593 | let last_slice_index = write.len() - 1; |
| 867 | 594 | ||
| @@ -870,7 +597,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 870 | first_length.min(255), | 597 | first_length.min(255), |
| 871 | Stop::Software, | 598 | Stop::Software, |
| 872 | (first_length > 255) || (last_slice_index != 0), | 599 | (first_length > 255) || (last_slice_index != 0), |
| 873 | &check_timeout, | 600 | timeout, |
| 874 | ) { | 601 | ) { |
| 875 | self.master_stop(); | 602 | self.master_stop(); |
| 876 | return Err(err); | 603 | return Err(err); |
| @@ -890,7 +617,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 890 | if let Err(err) = Self::master_continue( | 617 | if let Err(err) = Self::master_continue( |
| 891 | slice_len.min(255), | 618 | slice_len.min(255), |
| 892 | (idx != last_slice_index) || (slice_len > 255), | 619 | (idx != last_slice_index) || (slice_len > 255), |
| 893 | &check_timeout, | 620 | timeout, |
| 894 | ) { | 621 | ) { |
| 895 | self.master_stop(); | 622 | self.master_stop(); |
| 896 | return Err(err); | 623 | return Err(err); |
| @@ -902,7 +629,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 902 | if let Err(err) = Self::master_continue( | 629 | if let Err(err) = Self::master_continue( |
| 903 | chunk.len(), | 630 | chunk.len(), |
| 904 | (number != last_chunk_idx) || (idx != last_slice_index), | 631 | (number != last_chunk_idx) || (idx != last_slice_index), |
| 905 | &check_timeout, | 632 | timeout, |
| 906 | ) { | 633 | ) { |
| 907 | self.master_stop(); | 634 | self.master_stop(); |
| 908 | return Err(err); | 635 | return Err(err); |
| @@ -913,7 +640,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 913 | // Wait until we are allowed to send data | 640 | // Wait until we are allowed to send data |
| 914 | // (START has been ACKed or last byte when | 641 | // (START has been ACKed or last byte when |
| 915 | // through) | 642 | // through) |
| 916 | if let Err(err) = self.wait_txe(&check_timeout) { | 643 | if let Err(err) = self.wait_txe(timeout) { |
| 917 | self.master_stop(); | 644 | self.master_stop(); |
| 918 | return Err(err); | 645 | return Err(err); |
| 919 | } | 646 | } |
| @@ -925,41 +652,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 925 | } | 652 | } |
| 926 | } | 653 | } |
| 927 | // Wait until the write finishes | 654 | // Wait until the write finishes |
| 928 | let result = self.wait_tc(&check_timeout); | 655 | let result = self.wait_tc(timeout); |
| 929 | self.master_stop(); | 656 | self.master_stop(); |
| 930 | result | 657 | result |
| 931 | } | 658 | } |
| 932 | |||
| 933 | #[cfg(feature = "time")] | ||
| 934 | pub fn blocking_write_vectored_timeout( | ||
| 935 | &mut self, | ||
| 936 | address: u8, | ||
| 937 | write: &[&[u8]], | ||
| 938 | timeout: Duration, | ||
| 939 | ) -> Result<(), Error> { | ||
| 940 | let check_timeout = timeout_fn(timeout); | ||
| 941 | self.blocking_write_vectored_with_timeout(address, write, check_timeout) | ||
| 942 | } | ||
| 943 | |||
| 944 | #[cfg(not(feature = "time"))] | ||
| 945 | pub fn blocking_write_vectored_timeout( | ||
| 946 | &mut self, | ||
| 947 | address: u8, | ||
| 948 | write: &[&[u8]], | ||
| 949 | check_timeout: impl Fn() -> Result<(), Error>, | ||
| 950 | ) -> Result<(), Error> { | ||
| 951 | self.blocking_write_vectored_with_timeout(address, write, check_timeout) | ||
| 952 | } | ||
| 953 | |||
| 954 | #[cfg(feature = "time")] | ||
| 955 | pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> { | ||
| 956 | self.blocking_write_vectored_timeout(address, write, self.timeout) | ||
| 957 | } | ||
| 958 | |||
| 959 | #[cfg(not(feature = "time"))] | ||
| 960 | pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> { | ||
| 961 | self.blocking_write_vectored_timeout(address, write, || Ok(())) | ||
| 962 | } | ||
| 963 | } | 659 | } |
| 964 | 660 | ||
| 965 | impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> { | 661 | impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> { |
