aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-12-18 18:24:55 +0100
committerDario Nieuwenhuis <[email protected]>2023-12-18 18:24:55 +0100
commit7044e53af45e472d52d6e523bddf5632f0375487 (patch)
tree15c0e4e73f1a07c25fd948c37ad1417131fb730e
parent88e77c733cc3d52a2bd20e9e25446fe1d37c830b (diff)
stm32/i2c: remove _timeout public API, share more code between v1/v2.
-rw-r--r--embassy-stm32/src/i2c/mod.rs162
-rw-r--r--embassy-stm32/src/i2c/v1.rs145
-rw-r--r--embassy-stm32/src/i2c/v2.rs460
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
3use core::marker::PhantomData;
4
5use crate::dma::NoDma;
6use 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")]
10mod _version; 5mod _version;
11pub use _version::*; 6
7use core::future::Future;
8use core::marker::PhantomData;
9
10use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
12use embassy_sync::waitqueue::AtomicWaker; 11use embassy_sync::waitqueue::AtomicWaker;
12#[cfg(feature = "time")]
13use embassy_time::{Duration, Instant};
13 14
14use crate::peripherals; 15use crate::dma::NoDma;
16use crate::gpio::sealed::AFType;
17use crate::gpio::Pull;
18use crate::interrupt::typelevel::Interrupt;
19use crate::time::Hertz;
20use 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)]
45pub 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
61impl 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.
73pub 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
83impl<'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)]
143struct Timeout {
144 #[cfg(feature = "time")]
145 deadline: Instant,
146}
147
148#[allow(dead_code)]
149impl 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
36pub(crate) mod sealed { 184pub(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 @@
1use core::future::poll_fn; 1use core::future::poll_fn;
2use core::marker::PhantomData;
3use core::task::Poll; 2use core::task::Poll;
4 3
5use embassy_embedded_hal::SetConfig; 4use embassy_embedded_hal::SetConfig;
6use embassy_futures::select::{select, Either}; 5use embassy_futures::select::{select, Either};
7use embassy_hal_internal::drop::OnDrop; 6use embassy_hal_internal::drop::OnDrop;
8use embassy_hal_internal::{into_ref, PeripheralRef};
9 7
10use super::*; 8use super::*;
11use crate::dma::{NoDma, Transfer}; 9use crate::dma::Transfer;
12use crate::gpio::sealed::AFType;
13use crate::gpio::Pull;
14use crate::interrupt::typelevel::Interrupt;
15use crate::pac::i2c; 10use crate::pac::i2c;
16use crate::time::Hertz; 11use crate::time::Hertz;
17use crate::{interrupt, Peripheral};
18 12
19pub unsafe fn on_interrupt<T: Instance>() { 13pub 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)]
35pub struct Config {
36 pub sda_pullup: bool,
37 pub scl_pullup: bool,
38}
39
40pub 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
48impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { 27impl<'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
5use embassy_embedded_hal::SetConfig; 5use embassy_embedded_hal::SetConfig;
6use embassy_hal_internal::drop::OnDrop; 6use embassy_hal_internal::drop::OnDrop;
7use embassy_hal_internal::{into_ref, PeripheralRef};
8#[cfg(feature = "time")]
9use embassy_time::{Duration, Instant};
10 7
11use super::*; 8use super::*;
12use crate::dma::{NoDma, Transfer}; 9use crate::dma::Transfer;
13use crate::gpio::sealed::AFType;
14use crate::gpio::Pull;
15use crate::interrupt::typelevel::Interrupt;
16use crate::pac::i2c; 10use crate::pac::i2c;
17use crate::time::Hertz; 11use crate::time::Hertz;
18use crate::{interrupt, Peripheral};
19
20#[cfg(feature = "time")]
21fn 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"))]
33pub fn no_timeout_fn() -> impl Fn() -> Result<(), Error> {
34 move || Ok(())
35}
36 12
37pub unsafe fn on_interrupt<T: Instance>() { 13pub(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)]
53pub struct Config {
54 pub sda_pullup: bool,
55 pub scl_pullup: bool,
56 #[cfg(feature = "time")]
57 pub transaction_timeout: Duration,
58}
59
60impl 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
71pub 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
81impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { 27impl<'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
965impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> { 661impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> {