aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/Cargo.toml5
-rw-r--r--embassy-stm32/src/i2c/mod.rs5
-rw-r--r--embassy-stm32/src/i2c/timeout.rs142
-rw-r--r--embassy-stm32/src/i2c/v1.rs123
-rw-r--r--embassy-stm32/src/i2c/v2.rs221
-rw-r--r--embassy-stm32/src/lib.rs2
-rw-r--r--embassy-stm32/src/subghz/timeout.rs1
-rw-r--r--embassy-stm32/src/subghz/tx_params.rs1
-rw-r--r--examples/stm32f4/src/bin/i2c.rs45
-rw-r--r--examples/stm32h7/src/bin/i2c.rs44
10 files changed, 508 insertions, 81 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 0b88e89c9..6b00518a6 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -82,9 +82,12 @@ memory-x = ["stm32-metapac/memory-x"]
82subghz = [] 82subghz = []
83exti = [] 83exti = []
84 84
85# Enables additional driver features that depend on embassy-time
86time = ["dep:embassy-time"]
87
85# Features starting with `_` are for internal use only. They're not intended 88# Features starting with `_` are for internal use only. They're not intended
86# to be enabled by other crates, and are not covered by semver guarantees. 89# to be enabled by other crates, and are not covered by semver guarantees.
87_time-driver = ["dep:embassy-time"] 90_time-driver = ["time"]
88time-driver-any = ["_time-driver"] 91time-driver-any = ["_time-driver"]
89time-driver-tim2 = ["_time-driver"] 92time-driver-tim2 = ["_time-driver"]
90time-driver-tim3 = ["_time-driver"] 93time-driver-tim3 = ["_time-driver"]
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs
index 9d314f411..f898fcc8b 100644
--- a/embassy-stm32/src/i2c/mod.rs
+++ b/embassy-stm32/src/i2c/mod.rs
@@ -7,6 +7,11 @@ use crate::interrupt::Interrupt;
7mod _version; 7mod _version;
8pub use _version::*; 8pub use _version::*;
9 9
10#[cfg(feature = "time")]
11mod timeout;
12#[cfg(feature = "time")]
13pub use timeout::*;
14
10use crate::peripherals; 15use crate::peripherals;
11 16
12#[derive(Debug)] 17#[derive(Debug)]
diff --git a/embassy-stm32/src/i2c/timeout.rs b/embassy-stm32/src/i2c/timeout.rs
new file mode 100644
index 000000000..4fca1ca2b
--- /dev/null
+++ b/embassy-stm32/src/i2c/timeout.rs
@@ -0,0 +1,142 @@
1use embassy_time::{Duration, Instant};
2
3use super::{Error, I2c, Instance};
4
5/// An I2C wrapper, which provides `embassy-time` based timeouts for all `embedded-hal` trait methods.
6///
7/// This is useful for recovering from a shorted bus or a device stuck in a clock stretching state.
8/// A regular [I2c] would freeze until condition is removed.
9pub struct TimeoutI2c<'d, T: Instance, TXDMA, RXDMA> {
10 i2c: &'d mut I2c<'d, T, TXDMA, RXDMA>,
11 timeout: Duration,
12}
13
14fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> {
15 let deadline = Instant::now() + timeout;
16 move || {
17 if Instant::now() > deadline {
18 Err(Error::Timeout)
19 } else {
20 Ok(())
21 }
22 }
23}
24
25impl<'d, T: Instance, TXDMA, RXDMA> TimeoutI2c<'d, T, TXDMA, RXDMA> {
26 pub fn new(i2c: &'d mut I2c<'d, T, TXDMA, RXDMA>, timeout: Duration) -> Self {
27 Self { i2c, timeout }
28 }
29
30 /// Blocking read with a custom timeout
31 pub fn blocking_read_timeout(&mut self, addr: u8, buffer: &mut [u8], timeout: Duration) -> Result<(), Error> {
32 self.i2c.blocking_read_timeout(addr, buffer, timeout_fn(timeout))
33 }
34
35 /// Blocking read with default timeout, provided in [`TimeoutI2c::new()`]
36 pub fn blocking_read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> {
37 self.blocking_read_timeout(addr, buffer, self.timeout)
38 }
39
40 /// Blocking write with a custom timeout
41 pub fn blocking_write_timeout(&mut self, addr: u8, bytes: &[u8], timeout: Duration) -> Result<(), Error> {
42 self.i2c.blocking_write_timeout(addr, bytes, timeout_fn(timeout))
43 }
44
45 /// Blocking write with default timeout, provided in [`TimeoutI2c::new()`]
46 pub fn blocking_write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
47 self.blocking_write_timeout(addr, bytes, self.timeout)
48 }
49
50 /// Blocking write-read with a custom timeout
51 pub fn blocking_write_read_timeout(
52 &mut self,
53 addr: u8,
54 bytes: &[u8],
55 buffer: &mut [u8],
56 timeout: Duration,
57 ) -> Result<(), Error> {
58 self.i2c
59 .blocking_write_read_timeout(addr, bytes, buffer, timeout_fn(timeout))
60 }
61
62 /// Blocking write-read with default timeout, provided in [`TimeoutI2c::new()`]
63 pub fn blocking_write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
64 self.blocking_write_read_timeout(addr, bytes, buffer, self.timeout)
65 }
66}
67
68impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Read for TimeoutI2c<'d, T, TXDMA, RXDMA> {
69 type Error = Error;
70
71 fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
72 self.blocking_read(addr, buffer)
73 }
74}
75
76impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Write for TimeoutI2c<'d, T, TXDMA, RXDMA> {
77 type Error = Error;
78
79 fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> {
80 self.blocking_write(addr, bytes)
81 }
82}
83
84impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::WriteRead for TimeoutI2c<'d, T, TXDMA, RXDMA> {
85 type Error = Error;
86
87 fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> {
88 self.blocking_write_read(addr, bytes, buffer)
89 }
90}
91
92#[cfg(feature = "unstable-traits")]
93mod eh1 {
94 use super::*;
95
96 impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::ErrorType for TimeoutI2c<'d, T, TXDMA, RXDMA> {
97 type Error = Error;
98 }
99
100 impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::I2c for TimeoutI2c<'d, T, TXDMA, RXDMA> {
101 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
102 self.blocking_read(address, buffer)
103 }
104
105 fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Self::Error> {
106 self.blocking_write(address, buffer)
107 }
108
109 fn write_iter<B>(&mut self, _address: u8, _bytes: B) -> Result<(), Self::Error>
110 where
111 B: IntoIterator<Item = u8>,
112 {
113 todo!();
114 }
115
116 fn write_iter_read<B>(&mut self, _address: u8, _bytes: B, _buffer: &mut [u8]) -> Result<(), Self::Error>
117 where
118 B: IntoIterator<Item = u8>,
119 {
120 todo!();
121 }
122
123 fn write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Self::Error> {
124 self.blocking_write_read(address, wr_buffer, rd_buffer)
125 }
126
127 fn transaction<'a>(
128 &mut self,
129 _address: u8,
130 _operations: &mut [embedded_hal_1::i2c::Operation<'a>],
131 ) -> Result<(), Self::Error> {
132 todo!();
133 }
134
135 fn transaction_iter<'a, O>(&mut self, _address: u8, _operations: O) -> Result<(), Self::Error>
136 where
137 O: IntoIterator<Item = embedded_hal_1::i2c::Operation<'a>>,
138 {
139 todo!();
140 }
141 }
142}
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index f39a37df6..f140e2b0d 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -1,8 +1,9 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2 2
3use embassy_embedded_hal::SetConfig; 3use embassy_embedded_hal::SetConfig;
4use embassy_hal_common::into_ref; 4use embassy_hal_common::{into_ref, PeripheralRef};
5 5
6use crate::dma::NoDma;
6use crate::gpio::sealed::AFType; 7use crate::gpio::sealed::AFType;
7use crate::gpio::Pull; 8use crate::gpio::Pull;
8use crate::i2c::{Error, Instance, SclPin, SdaPin}; 9use crate::i2c::{Error, Instance, SclPin, SdaPin};
@@ -34,19 +35,26 @@ impl State {
34 } 35 }
35} 36}
36 37
37pub struct I2c<'d, T: Instance> { 38pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> {
38 phantom: PhantomData<&'d mut T>, 39 phantom: PhantomData<&'d mut T>,
40 #[allow(dead_code)]
41 tx_dma: PeripheralRef<'d, TXDMA>,
42 #[allow(dead_code)]
43 rx_dma: PeripheralRef<'d, RXDMA>,
39} 44}
40 45
41impl<'d, T: Instance> I2c<'d, T> { 46impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
42 pub fn new( 47 pub fn new(
43 _peri: impl Peripheral<P = T> + 'd, 48 _peri: impl Peripheral<P = T> + 'd,
44 scl: impl Peripheral<P = impl SclPin<T>> + 'd, 49 scl: impl Peripheral<P = impl SclPin<T>> + 'd,
45 sda: impl Peripheral<P = impl SdaPin<T>> + 'd, 50 sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
51 _irq: impl Peripheral<P = T::Interrupt> + 'd,
52 tx_dma: impl Peripheral<P = TXDMA> + 'd,
53 rx_dma: impl Peripheral<P = RXDMA> + 'd,
46 freq: Hertz, 54 freq: Hertz,
47 config: Config, 55 config: Config,
48 ) -> Self { 56 ) -> Self {
49 into_ref!(scl, sda); 57 into_ref!(scl, sda, tx_dma, rx_dma);
50 58
51 T::enable(); 59 T::enable();
52 T::reset(); 60 T::reset();
@@ -99,7 +107,11 @@ impl<'d, T: Instance> I2c<'d, T> {
99 }); 107 });
100 } 108 }
101 109
102 Self { phantom: PhantomData } 110 Self {
111 phantom: PhantomData,
112 tx_dma,
113 rx_dma,
114 }
103 } 115 }
104 116
105 unsafe fn check_and_clear_error_flags(&self) -> Result<i2c::regs::Sr1, Error> { 117 unsafe fn check_and_clear_error_flags(&self) -> Result<i2c::regs::Sr1, Error> {
@@ -141,7 +153,12 @@ impl<'d, T: Instance> I2c<'d, T> {
141 Ok(sr1) 153 Ok(sr1)
142 } 154 }
143 155
144 unsafe fn write_bytes(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { 156 unsafe fn write_bytes(
157 &mut self,
158 addr: u8,
159 bytes: &[u8],
160 check_timeout: impl Fn() -> Result<(), Error>,
161 ) -> Result<(), Error> {
145 // Send a START condition 162 // Send a START condition
146 163
147 T::regs().cr1().modify(|reg| { 164 T::regs().cr1().modify(|reg| {
@@ -149,7 +166,9 @@ impl<'d, T: Instance> I2c<'d, T> {
149 }); 166 });
150 167
151 // Wait until START condition was generated 168 // Wait until START condition was generated
152 while !self.check_and_clear_error_flags()?.start() {} 169 while !self.check_and_clear_error_flags()?.start() {
170 check_timeout()?;
171 }
153 172
154 // Also wait until signalled we're master and everything is waiting for us 173 // Also wait until signalled we're master and everything is waiting for us
155 while { 174 while {
@@ -157,7 +176,9 @@ impl<'d, T: Instance> I2c<'d, T> {
157 176
158 let sr2 = T::regs().sr2().read(); 177 let sr2 = T::regs().sr2().read();
159 !sr2.msl() && !sr2.busy() 178 !sr2.msl() && !sr2.busy()
160 } {} 179 } {
180 check_timeout()?;
181 }
161 182
162 // Set up current address, we're trying to talk to 183 // Set up current address, we're trying to talk to
163 T::regs().dr().write(|reg| reg.set_dr(addr << 1)); 184 T::regs().dr().write(|reg| reg.set_dr(addr << 1));
@@ -165,26 +186,30 @@ impl<'d, T: Instance> I2c<'d, T> {
165 // Wait until address was sent 186 // Wait until address was sent
166 // Wait for the address to be acknowledged 187 // Wait for the address to be acknowledged
167 // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. 188 // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set.
168 while !self.check_and_clear_error_flags()?.addr() {} 189 while !self.check_and_clear_error_flags()?.addr() {
190 check_timeout()?;
191 }
169 192
170 // Clear condition by reading SR2 193 // Clear condition by reading SR2
171 let _ = T::regs().sr2().read(); 194 let _ = T::regs().sr2().read();
172 195
173 // Send bytes 196 // Send bytes
174 for c in bytes { 197 for c in bytes {
175 self.send_byte(*c)?; 198 self.send_byte(*c, &check_timeout)?;
176 } 199 }
177 200
178 // Fallthrough is success 201 // Fallthrough is success
179 Ok(()) 202 Ok(())
180 } 203 }
181 204
182 unsafe fn send_byte(&self, byte: u8) -> Result<(), Error> { 205 unsafe fn send_byte(&self, byte: u8, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
183 // Wait until we're ready for sending 206 // Wait until we're ready for sending
184 while { 207 while {
185 // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. 208 // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set.
186 !self.check_and_clear_error_flags()?.txe() 209 !self.check_and_clear_error_flags()?.txe()
187 } {} 210 } {
211 check_timeout()?;
212 }
188 213
189 // Push out a byte of data 214 // Push out a byte of data
190 T::regs().dr().write(|reg| reg.set_dr(byte)); 215 T::regs().dr().write(|reg| reg.set_dr(byte));
@@ -193,24 +218,33 @@ impl<'d, T: Instance> I2c<'d, T> {
193 while { 218 while {
194 // Check for any potential error conditions. 219 // Check for any potential error conditions.
195 !self.check_and_clear_error_flags()?.btf() 220 !self.check_and_clear_error_flags()?.btf()
196 } {} 221 } {
222 check_timeout()?;
223 }
197 224
198 Ok(()) 225 Ok(())
199 } 226 }
200 227
201 unsafe fn recv_byte(&self) -> Result<u8, Error> { 228 unsafe fn recv_byte(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<u8, Error> {
202 while { 229 while {
203 // Check for any potential error conditions. 230 // Check for any potential error conditions.
204 self.check_and_clear_error_flags()?; 231 self.check_and_clear_error_flags()?;
205 232
206 !T::regs().sr1().read().rxne() 233 !T::regs().sr1().read().rxne()
207 } {} 234 } {
235 check_timeout()?;
236 }
208 237
209 let value = T::regs().dr().read().dr(); 238 let value = T::regs().dr().read().dr();
210 Ok(value) 239 Ok(value)
211 } 240 }
212 241
213 pub fn blocking_read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> { 242 pub fn blocking_read_timeout(
243 &mut self,
244 addr: u8,
245 buffer: &mut [u8],
246 check_timeout: impl Fn() -> Result<(), Error>,
247 ) -> Result<(), Error> {
214 if let Some((last, buffer)) = buffer.split_last_mut() { 248 if let Some((last, buffer)) = buffer.split_last_mut() {
215 // Send a START condition and set ACK bit 249 // Send a START condition and set ACK bit
216 unsafe { 250 unsafe {
@@ -221,27 +255,33 @@ impl<'d, T: Instance> I2c<'d, T> {
221 } 255 }
222 256
223 // Wait until START condition was generated 257 // Wait until START condition was generated
224 while unsafe { !T::regs().sr1().read().start() } {} 258 while unsafe { !self.check_and_clear_error_flags()?.start() } {
259 check_timeout()?;
260 }
225 261
226 // Also wait until signalled we're master and everything is waiting for us 262 // Also wait until signalled we're master and everything is waiting for us
227 while { 263 while {
228 let sr2 = unsafe { T::regs().sr2().read() }; 264 let sr2 = unsafe { T::regs().sr2().read() };
229 !sr2.msl() && !sr2.busy() 265 !sr2.msl() && !sr2.busy()
230 } {} 266 } {
267 check_timeout()?;
268 }
231 269
232 // Set up current address, we're trying to talk to 270 // Set up current address, we're trying to talk to
233 unsafe { T::regs().dr().write(|reg| reg.set_dr((addr << 1) + 1)) } 271 unsafe { T::regs().dr().write(|reg| reg.set_dr((addr << 1) + 1)) }
234 272
235 // Wait until address was sent 273 // Wait until address was sent
236 // Wait for the address to be acknowledged 274 // Wait for the address to be acknowledged
237 while unsafe { !self.check_and_clear_error_flags()?.addr() } {} 275 while unsafe { !self.check_and_clear_error_flags()?.addr() } {
276 check_timeout()?;
277 }
238 278
239 // Clear condition by reading SR2 279 // Clear condition by reading SR2
240 let _ = unsafe { T::regs().sr2().read() }; 280 let _ = unsafe { T::regs().sr2().read() };
241 281
242 // Receive bytes into buffer 282 // Receive bytes into buffer
243 for c in buffer { 283 for c in buffer {
244 *c = unsafe { self.recv_byte()? }; 284 *c = unsafe { self.recv_byte(&check_timeout)? };
245 } 285 }
246 286
247 // Prepare to send NACK then STOP after next byte 287 // Prepare to send NACK then STOP after next byte
@@ -253,10 +293,12 @@ impl<'d, T: Instance> I2c<'d, T> {
253 } 293 }
254 294
255 // Receive last byte 295 // Receive last byte
256 *last = unsafe { self.recv_byte()? }; 296 *last = unsafe { self.recv_byte(&check_timeout)? };
257 297
258 // Wait for the STOP to be sent. 298 // Wait for the STOP to be sent.
259 while unsafe { T::regs().cr1().read().stop() } {} 299 while unsafe { T::regs().cr1().read().stop() } {
300 check_timeout()?;
301 }
260 302
261 // Fallthrough is success 303 // Fallthrough is success
262 Ok(()) 304 Ok(())
@@ -265,25 +307,50 @@ impl<'d, T: Instance> I2c<'d, T> {
265 } 307 }
266 } 308 }
267 309
268 pub fn blocking_write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { 310 pub fn blocking_read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> {
311 self.blocking_read_timeout(addr, buffer, || Ok(()))
312 }
313
314 pub fn blocking_write_timeout(
315 &mut self,
316 addr: u8,
317 bytes: &[u8],
318 check_timeout: impl Fn() -> Result<(), Error>,
319 ) -> Result<(), Error> {
269 unsafe { 320 unsafe {
270 self.write_bytes(addr, bytes)?; 321 self.write_bytes(addr, bytes, &check_timeout)?;
271 // Send a STOP condition 322 // Send a STOP condition
272 T::regs().cr1().modify(|reg| reg.set_stop(true)); 323 T::regs().cr1().modify(|reg| reg.set_stop(true));
273 // Wait for STOP condition to transmit. 324 // Wait for STOP condition to transmit.
274 while T::regs().cr1().read().stop() {} 325 while T::regs().cr1().read().stop() {
326 check_timeout()?;
327 }
275 }; 328 };
276 329
277 // Fallthrough is success 330 // Fallthrough is success
278 Ok(()) 331 Ok(())
279 } 332 }
280 333
281 pub fn blocking_write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> { 334 pub fn blocking_write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
282 unsafe { self.write_bytes(addr, bytes)? }; 335 self.blocking_write_timeout(addr, bytes, || Ok(()))
283 self.blocking_read(addr, buffer)?; 336 }
337
338 pub fn blocking_write_read_timeout(
339 &mut self,
340 addr: u8,
341 bytes: &[u8],
342 buffer: &mut [u8],
343 check_timeout: impl Fn() -> Result<(), Error>,
344 ) -> Result<(), Error> {
345 unsafe { self.write_bytes(addr, bytes, &check_timeout)? };
346 self.blocking_read_timeout(addr, buffer, &check_timeout)?;
284 347
285 Ok(()) 348 Ok(())
286 } 349 }
350
351 pub fn blocking_write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
352 self.blocking_write_read_timeout(addr, bytes, buffer, || Ok(()))
353 }
287} 354}
288 355
289impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Read for I2c<'d, T> { 356impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Read for I2c<'d, T> {
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 89b52da98..aa4e6bb08 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -147,14 +147,23 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
147 } 147 }
148 } 148 }
149 149
150 unsafe fn master_read(address: u8, length: usize, stop: Stop, reload: bool, restart: bool) { 150 unsafe fn master_read(
151 address: u8,
152 length: usize,
153 stop: Stop,
154 reload: bool,
155 restart: bool,
156 check_timeout: impl Fn() -> Result<(), Error>,
157 ) -> Result<(), Error> {
151 assert!(length < 256); 158 assert!(length < 256);
152 159
153 if !restart { 160 if !restart {
154 // Wait for any previous address sequence to end 161 // Wait for any previous address sequence to end
155 // automatically. This could be up to 50% of a bus 162 // automatically. This could be up to 50% of a bus
156 // cycle (ie. up to 0.5/freq) 163 // cycle (ie. up to 0.5/freq)
157 while T::regs().cr2().read().start() {} 164 while T::regs().cr2().read().start() {
165 check_timeout()?;
166 }
158 } 167 }
159 168
160 // Set START and prepare to receive bytes into 169 // Set START and prepare to receive bytes into
@@ -176,15 +185,25 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
176 w.set_autoend(stop.autoend()); 185 w.set_autoend(stop.autoend());
177 w.set_reload(reload); 186 w.set_reload(reload);
178 }); 187 });
188
189 Ok(())
179 } 190 }
180 191
181 unsafe fn master_write(address: u8, length: usize, stop: Stop, reload: bool) { 192 unsafe fn master_write(
193 address: u8,
194 length: usize,
195 stop: Stop,
196 reload: bool,
197 check_timeout: impl Fn() -> Result<(), Error>,
198 ) -> Result<(), Error> {
182 assert!(length < 256); 199 assert!(length < 256);
183 200
184 // Wait for any previous address sequence to end 201 // Wait for any previous address sequence to end
185 // automatically. This could be up to 50% of a bus 202 // automatically. This could be up to 50% of a bus
186 // cycle (ie. up to 0.5/freq) 203 // cycle (ie. up to 0.5/freq)
187 while T::regs().cr2().read().start() {} 204 while T::regs().cr2().read().start() {
205 check_timeout()?;
206 }
188 207
189 let reload = if reload { 208 let reload = if reload {
190 i2c::vals::Reload::NOTCOMPLETED 209 i2c::vals::Reload::NOTCOMPLETED
@@ -204,12 +223,20 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
204 w.set_autoend(stop.autoend()); 223 w.set_autoend(stop.autoend());
205 w.set_reload(reload); 224 w.set_reload(reload);
206 }); 225 });
226
227 Ok(())
207 } 228 }
208 229
209 unsafe fn master_continue(length: usize, reload: bool) { 230 unsafe fn master_continue(
231 length: usize,
232 reload: bool,
233 check_timeout: impl Fn() -> Result<(), Error>,
234 ) -> Result<(), Error> {
210 assert!(length < 256 && length > 0); 235 assert!(length < 256 && length > 0);
211 236
212 while !T::regs().isr().read().tcr() {} 237 while !T::regs().isr().read().tcr() {
238 check_timeout()?;
239 }
213 240
214 let reload = if reload { 241 let reload = if reload {
215 i2c::vals::Reload::NOTCOMPLETED 242 i2c::vals::Reload::NOTCOMPLETED
@@ -221,6 +248,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
221 w.set_nbytes(length as u8); 248 w.set_nbytes(length as u8);
222 w.set_reload(reload); 249 w.set_reload(reload);
223 }); 250 });
251
252 Ok(())
224 } 253 }
225 254
226 fn flush_txdr(&self) { 255 fn flush_txdr(&self) {
@@ -243,7 +272,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
243 //} 272 //}
244 } 273 }
245 274
246 fn wait_txe(&self) -> Result<(), Error> { 275 fn wait_txe(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
247 loop { 276 loop {
248 unsafe { 277 unsafe {
249 let isr = T::regs().isr().read(); 278 let isr = T::regs().isr().read();
@@ -261,10 +290,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
261 return Err(Error::Nack); 290 return Err(Error::Nack);
262 } 291 }
263 } 292 }
293
294 check_timeout()?;
264 } 295 }
265 } 296 }
266 297
267 fn wait_rxne(&self) -> Result<(), Error> { 298 fn wait_rxne(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
268 loop { 299 loop {
269 unsafe { 300 unsafe {
270 let isr = T::regs().isr().read(); 301 let isr = T::regs().isr().read();
@@ -282,10 +313,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
282 return Err(Error::Nack); 313 return Err(Error::Nack);
283 } 314 }
284 } 315 }
316
317 check_timeout()?;
285 } 318 }
286 } 319 }
287 320
288 fn wait_tc(&self) -> Result<(), Error> { 321 fn wait_tc(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
289 loop { 322 loop {
290 unsafe { 323 unsafe {
291 let isr = T::regs().isr().read(); 324 let isr = T::regs().isr().read();
@@ -303,10 +336,18 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
303 return Err(Error::Nack); 336 return Err(Error::Nack);
304 } 337 }
305 } 338 }
339
340 check_timeout()?;
306 } 341 }
307 } 342 }
308 343
309 fn read_internal(&mut self, address: u8, buffer: &mut [u8], restart: bool) -> Result<(), Error> { 344 fn read_internal(
345 &mut self,
346 address: u8,
347 buffer: &mut [u8],
348 restart: bool,
349 check_timeout: impl Fn() -> Result<(), Error>,
350 ) -> Result<(), Error> {
310 let completed_chunks = buffer.len() / 255; 351 let completed_chunks = buffer.len() / 255;
311 let total_chunks = if completed_chunks * 255 == buffer.len() { 352 let total_chunks = if completed_chunks * 255 == buffer.len() {
312 completed_chunks 353 completed_chunks
@@ -322,20 +363,21 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
322 Stop::Automatic, 363 Stop::Automatic,
323 last_chunk_idx != 0, 364 last_chunk_idx != 0,
324 restart, 365 restart,
325 ); 366 &check_timeout,
367 )?;
326 } 368 }
327 369
328 for (number, chunk) in buffer.chunks_mut(255).enumerate() { 370 for (number, chunk) in buffer.chunks_mut(255).enumerate() {
329 if number != 0 { 371 if number != 0 {
330 // NOTE(unsafe) We have &mut self 372 // NOTE(unsafe) We have &mut self
331 unsafe { 373 unsafe {
332 Self::master_continue(chunk.len(), number != last_chunk_idx); 374 Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?;
333 } 375 }
334 } 376 }
335 377
336 for byte in chunk { 378 for byte in chunk {
337 // Wait until we have received something 379 // Wait until we have received something
338 self.wait_rxne()?; 380 self.wait_rxne(&check_timeout)?;
339 381
340 unsafe { 382 unsafe {
341 *byte = T::regs().rxdr().read().rxdata(); 383 *byte = T::regs().rxdr().read().rxdata();
@@ -345,7 +387,13 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
345 Ok(()) 387 Ok(())
346 } 388 }
347 389
348 fn write_internal(&mut self, address: u8, bytes: &[u8], send_stop: bool) -> Result<(), Error> { 390 fn write_internal(
391 &mut self,
392 address: u8,
393 bytes: &[u8],
394 send_stop: bool,
395 check_timeout: impl Fn() -> Result<(), Error>,
396 ) -> Result<(), Error> {
349 let completed_chunks = bytes.len() / 255; 397 let completed_chunks = bytes.len() / 255;
350 let total_chunks = if completed_chunks * 255 == bytes.len() { 398 let total_chunks = if completed_chunks * 255 == bytes.len() {
351 completed_chunks 399 completed_chunks
@@ -359,14 +407,20 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
359 // ST SAD+W 407 // ST SAD+W
360 // NOTE(unsafe) We have &mut self 408 // NOTE(unsafe) We have &mut self
361 unsafe { 409 unsafe {
362 Self::master_write(address, bytes.len().min(255), Stop::Software, last_chunk_idx != 0); 410 Self::master_write(
411 address,
412 bytes.len().min(255),
413 Stop::Software,
414 last_chunk_idx != 0,
415 &check_timeout,
416 )?;
363 } 417 }
364 418
365 for (number, chunk) in bytes.chunks(255).enumerate() { 419 for (number, chunk) in bytes.chunks(255).enumerate() {
366 if number != 0 { 420 if number != 0 {
367 // NOTE(unsafe) We have &mut self 421 // NOTE(unsafe) We have &mut self
368 unsafe { 422 unsafe {
369 Self::master_continue(chunk.len(), number != last_chunk_idx); 423 Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?;
370 } 424 }
371 } 425 }
372 426
@@ -374,7 +428,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
374 // Wait until we are allowed to send data 428 // Wait until we are allowed to send data
375 // (START has been ACKed or last byte when 429 // (START has been ACKed or last byte when
376 // through) 430 // through)
377 self.wait_txe()?; 431 self.wait_txe(&check_timeout)?;
378 432
379 unsafe { 433 unsafe {
380 T::regs().txdr().write(|w| w.set_txdata(*byte)); 434 T::regs().txdr().write(|w| w.set_txdata(*byte));
@@ -382,7 +436,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
382 } 436 }
383 } 437 }
384 // Wait until the write finishes 438 // Wait until the write finishes
385 self.wait_tc()?; 439 self.wait_tc(&check_timeout)?;
386 440
387 if send_stop { 441 if send_stop {
388 self.master_stop(); 442 self.master_stop();
@@ -396,6 +450,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
396 bytes: &[u8], 450 bytes: &[u8],
397 first_slice: bool, 451 first_slice: bool,
398 last_slice: bool, 452 last_slice: bool,
453 check_timeout: impl Fn() -> Result<(), Error>,
399 ) -> Result<(), Error> 454 ) -> Result<(), Error>
400 where 455 where
401 TXDMA: crate::i2c::TxDma<T>, 456 TXDMA: crate::i2c::TxDma<T>,
@@ -447,11 +502,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
447 total_len.min(255), 502 total_len.min(255),
448 Stop::Software, 503 Stop::Software,
449 (total_chunks != 1) || !last_slice, 504 (total_chunks != 1) || !last_slice,
450 ); 505 &check_timeout,
506 )?;
451 } 507 }
452 } else { 508 } else {
453 unsafe { 509 unsafe {
454 Self::master_continue(total_len.min(255), (total_chunks != 1) || !last_slice); 510 Self::master_continue(total_len.min(255), (total_chunks != 1) || !last_slice, &check_timeout)?;
455 T::regs().cr1().modify(|w| w.set_tcie(true)); 511 T::regs().cr1().modify(|w| w.set_tcie(true));
456 } 512 }
457 } 513 }
@@ -461,32 +517,40 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
461 let chunks_transferred = state.chunks_transferred.load(Ordering::Relaxed); 517 let chunks_transferred = state.chunks_transferred.load(Ordering::Relaxed);
462 518
463 if chunks_transferred == total_chunks { 519 if chunks_transferred == total_chunks {
464 return Poll::Ready(()); 520 return Poll::Ready(Ok(()));
465 } else if chunks_transferred != 0 { 521 } else if chunks_transferred != 0 {
466 remaining_len = remaining_len.saturating_sub(255); 522 remaining_len = remaining_len.saturating_sub(255);
467 let last_piece = (chunks_transferred + 1 == total_chunks) && last_slice; 523 let last_piece = (chunks_transferred + 1 == total_chunks) && last_slice;
468 524
469 // NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers 525 // NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers
470 unsafe { 526 unsafe {
471 Self::master_continue(remaining_len.min(255), !last_piece); 527 if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) {
528 return Poll::Ready(Err(e));
529 }
472 T::regs().cr1().modify(|w| w.set_tcie(true)); 530 T::regs().cr1().modify(|w| w.set_tcie(true));
473 } 531 }
474 } 532 }
475 Poll::Pending 533 Poll::Pending
476 }) 534 })
477 .await; 535 .await?;
478 536
479 dma_transfer.await; 537 dma_transfer.await;
480 538
481 if last_slice { 539 if last_slice {
482 // This should be done already 540 // This should be done already
483 self.wait_tc()?; 541 self.wait_tc(&check_timeout)?;
484 self.master_stop(); 542 self.master_stop();
485 } 543 }
486 Ok(()) 544 Ok(())
487 } 545 }
488 546
489 async fn read_dma_internal(&mut self, address: u8, buffer: &mut [u8], restart: bool) -> Result<(), Error> 547 async fn read_dma_internal(
548 &mut self,
549 address: u8,
550 buffer: &mut [u8],
551 restart: bool,
552 check_timeout: impl Fn() -> Result<(), Error>,
553 ) -> Result<(), Error>
490 where 554 where
491 RXDMA: crate::i2c::RxDma<T>, 555 RXDMA: crate::i2c::RxDma<T>,
492 { 556 {
@@ -527,7 +591,14 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
527 591
528 // NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers 592 // NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers
529 unsafe { 593 unsafe {
530 Self::master_read(address, total_len.min(255), Stop::Software, total_chunks != 1, restart); 594 Self::master_read(
595 address,
596 total_len.min(255),
597 Stop::Software,
598 total_chunks != 1,
599 restart,
600 &check_timeout,
601 )?;
531 } 602 }
532 603
533 poll_fn(|cx| { 604 poll_fn(|cx| {
@@ -535,25 +606,27 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
535 let chunks_transferred = state.chunks_transferred.load(Ordering::Relaxed); 606 let chunks_transferred = state.chunks_transferred.load(Ordering::Relaxed);
536 607
537 if chunks_transferred == total_chunks { 608 if chunks_transferred == total_chunks {
538 return Poll::Ready(()); 609 return Poll::Ready(Ok(()));
539 } else if chunks_transferred != 0 { 610 } else if chunks_transferred != 0 {
540 remaining_len = remaining_len.saturating_sub(255); 611 remaining_len = remaining_len.saturating_sub(255);
541 let last_piece = chunks_transferred + 1 == total_chunks; 612 let last_piece = chunks_transferred + 1 == total_chunks;
542 613
543 // NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers 614 // NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers
544 unsafe { 615 unsafe {
545 Self::master_continue(remaining_len.min(255), !last_piece); 616 if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) {
617 return Poll::Ready(Err(e));
618 }
546 T::regs().cr1().modify(|w| w.set_tcie(true)); 619 T::regs().cr1().modify(|w| w.set_tcie(true));
547 } 620 }
548 } 621 }
549 Poll::Pending 622 Poll::Pending
550 }) 623 })
551 .await; 624 .await?;
552 625
553 dma_transfer.await; 626 dma_transfer.await;
554 627
555 // This should be done already 628 // This should be done already
556 self.wait_tc()?; 629 self.wait_tc(&check_timeout)?;
557 self.master_stop(); 630 self.master_stop();
558 Ok(()) 631 Ok(())
559 } 632 }
@@ -566,9 +639,9 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
566 TXDMA: crate::i2c::TxDma<T>, 639 TXDMA: crate::i2c::TxDma<T>,
567 { 640 {
568 if bytes.is_empty() { 641 if bytes.is_empty() {
569 self.write_internal(address, bytes, true) 642 self.write_internal(address, bytes, true, || Ok(()))
570 } else { 643 } else {
571 self.write_dma_internal(address, bytes, true, true).await 644 self.write_dma_internal(address, bytes, true, true, || Ok(())).await
572 } 645 }
573 } 646 }
574 647
@@ -587,7 +660,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
587 let next = iter.next(); 660 let next = iter.next();
588 let is_last = next.is_none(); 661 let is_last = next.is_none();
589 662
590 self.write_dma_internal(address, c, first, is_last).await?; 663 self.write_dma_internal(address, c, first, is_last, || Ok(())).await?;
591 first = false; 664 first = false;
592 current = next; 665 current = next;
593 } 666 }
@@ -599,9 +672,9 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
599 RXDMA: crate::i2c::RxDma<T>, 672 RXDMA: crate::i2c::RxDma<T>,
600 { 673 {
601 if buffer.is_empty() { 674 if buffer.is_empty() {
602 self.read_internal(address, buffer, false) 675 self.read_internal(address, buffer, false, || Ok(()))
603 } else { 676 } else {
604 self.read_dma_internal(address, buffer, false).await 677 self.read_dma_internal(address, buffer, false, || Ok(())).await
605 } 678 }
606 } 679 }
607 680
@@ -611,15 +684,15 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
611 RXDMA: super::RxDma<T>, 684 RXDMA: super::RxDma<T>,
612 { 685 {
613 if bytes.is_empty() { 686 if bytes.is_empty() {
614 self.write_internal(address, bytes, false)?; 687 self.write_internal(address, bytes, false, || Ok(()))?;
615 } else { 688 } else {
616 self.write_dma_internal(address, bytes, true, true).await?; 689 self.write_dma_internal(address, bytes, true, true, || Ok(())).await?;
617 } 690 }
618 691
619 if buffer.is_empty() { 692 if buffer.is_empty() {
620 self.read_internal(address, buffer, true)?; 693 self.read_internal(address, buffer, true, || Ok(()))?;
621 } else { 694 } else {
622 self.read_dma_internal(address, buffer, true).await?; 695 self.read_dma_internal(address, buffer, true, || Ok(())).await?;
623 } 696 }
624 697
625 Ok(()) 698 Ok(())
@@ -628,22 +701,55 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
628 // ========================= 701 // =========================
629 // Blocking public API 702 // Blocking public API
630 703
631 pub fn blocking_read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { 704 pub fn blocking_read_timeout(
632 self.read_internal(address, buffer, false) 705 &mut self,
706 address: u8,
707 buffer: &mut [u8],
708 check_timeout: impl Fn() -> Result<(), Error>,
709 ) -> Result<(), Error> {
710 self.read_internal(address, buffer, false, &check_timeout)
633 // Automatic Stop 711 // Automatic Stop
634 } 712 }
635 713
714 pub fn blocking_read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
715 self.blocking_read_timeout(address, buffer, || Ok(()))
716 }
717
718 pub fn blocking_write_timeout(
719 &mut self,
720 address: u8,
721 bytes: &[u8],
722 check_timeout: impl Fn() -> Result<(), Error>,
723 ) -> Result<(), Error> {
724 self.write_internal(address, bytes, true, &check_timeout)
725 }
726
636 pub fn blocking_write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Error> { 727 pub fn blocking_write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Error> {
637 self.write_internal(address, bytes, true) 728 self.blocking_write_timeout(address, bytes, || Ok(()))
638 } 729 }
639 730
640 pub fn blocking_write_read(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> { 731 pub fn blocking_write_read_timeout(
641 self.write_internal(address, bytes, false)?; 732 &mut self,
642 self.read_internal(address, buffer, true) 733 address: u8,
734 bytes: &[u8],
735 buffer: &mut [u8],
736 check_timeout: impl Fn() -> Result<(), Error>,
737 ) -> Result<(), Error> {
738 self.write_internal(address, bytes, false, &check_timeout)?;
739 self.read_internal(address, buffer, true, &check_timeout)
643 // Automatic Stop 740 // Automatic Stop
644 } 741 }
645 742
646 pub fn blocking_write_vectored(&mut self, address: u8, bytes: &[&[u8]]) -> Result<(), Error> { 743 pub fn blocking_write_read(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
744 self.blocking_write_read_timeout(address, bytes, buffer, || Ok(()))
745 }
746
747 pub fn blocking_write_vectored_timeout(
748 &mut self,
749 address: u8,
750 bytes: &[&[u8]],
751 check_timeout: impl Fn() -> Result<(), Error>,
752 ) -> Result<(), Error> {
647 if bytes.is_empty() { 753 if bytes.is_empty() {
648 return Err(Error::ZeroLengthTransfer); 754 return Err(Error::ZeroLengthTransfer);
649 } 755 }
@@ -657,7 +763,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
657 first_length.min(255), 763 first_length.min(255),
658 Stop::Software, 764 Stop::Software,
659 (first_length > 255) || (last_slice_index != 0), 765 (first_length > 255) || (last_slice_index != 0),
660 ); 766 &check_timeout,
767 )?;
661 } 768 }
662 769
663 for (idx, slice) in bytes.iter().enumerate() { 770 for (idx, slice) in bytes.iter().enumerate() {
@@ -673,7 +780,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
673 if idx != 0 { 780 if idx != 0 {
674 // NOTE(unsafe) We have &mut self 781 // NOTE(unsafe) We have &mut self
675 unsafe { 782 unsafe {
676 Self::master_continue(slice_len.min(255), (idx != last_slice_index) || (slice_len > 255)); 783 Self::master_continue(
784 slice_len.min(255),
785 (idx != last_slice_index) || (slice_len > 255),
786 &check_timeout,
787 )?;
677 } 788 }
678 } 789 }
679 790
@@ -681,7 +792,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
681 if number != 0 { 792 if number != 0 {
682 // NOTE(unsafe) We have &mut self 793 // NOTE(unsafe) We have &mut self
683 unsafe { 794 unsafe {
684 Self::master_continue(chunk.len(), (number != last_chunk_idx) || (idx != last_slice_index)); 795 Self::master_continue(
796 chunk.len(),
797 (number != last_chunk_idx) || (idx != last_slice_index),
798 &check_timeout,
799 )?;
685 } 800 }
686 } 801 }
687 802
@@ -689,7 +804,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
689 // Wait until we are allowed to send data 804 // Wait until we are allowed to send data
690 // (START has been ACKed or last byte when 805 // (START has been ACKed or last byte when
691 // through) 806 // through)
692 self.wait_txe()?; 807 self.wait_txe(&check_timeout)?;
693 808
694 // Put byte on the wire 809 // Put byte on the wire
695 //self.i2c.txdr.write(|w| w.txdata().bits(*byte)); 810 //self.i2c.txdr.write(|w| w.txdata().bits(*byte));
@@ -700,11 +815,15 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
700 } 815 }
701 } 816 }
702 // Wait until the write finishes 817 // Wait until the write finishes
703 self.wait_tc()?; 818 self.wait_tc(&check_timeout)?;
704 self.master_stop(); 819 self.master_stop();
705 820
706 Ok(()) 821 Ok(())
707 } 822 }
823
824 pub fn blocking_write_vectored(&mut self, address: u8, bytes: &[&[u8]]) -> Result<(), Error> {
825 self.blocking_write_vectored_timeout(address, bytes, || Ok(()))
826 }
708} 827}
709 828
710mod eh02 { 829mod eh02 {
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 0392e8086..bcf2feee8 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -52,7 +52,7 @@ pub mod sdmmc;
52pub mod spi; 52pub mod spi;
53#[cfg(usart)] 53#[cfg(usart)]
54pub mod usart; 54pub mod usart;
55#[cfg(usb)] 55#[cfg(all(usb, feature = "time"))]
56pub mod usb; 56pub mod usb;
57#[cfg(any(otgfs, otghs))] 57#[cfg(any(otgfs, otghs))]
58pub mod usb_otg; 58pub mod usb_otg;
diff --git a/embassy-stm32/src/subghz/timeout.rs b/embassy-stm32/src/subghz/timeout.rs
index 28b3b0c21..0ae49dd90 100644
--- a/embassy-stm32/src/subghz/timeout.rs
+++ b/embassy-stm32/src/subghz/timeout.rs
@@ -439,6 +439,7 @@ impl From<Timeout> for [u8; 3] {
439 } 439 }
440} 440}
441 441
442#[cfg(feature = "time")]
442impl From<Timeout> for embassy_time::Duration { 443impl From<Timeout> for embassy_time::Duration {
443 fn from(to: Timeout) -> Self { 444 fn from(to: Timeout) -> Self {
444 embassy_time::Duration::from_micros(to.as_micros().into()) 445 embassy_time::Duration::from_micros(to.as_micros().into())
diff --git a/embassy-stm32/src/subghz/tx_params.rs b/embassy-stm32/src/subghz/tx_params.rs
index cede6f2c1..03bdb1ea8 100644
--- a/embassy-stm32/src/subghz/tx_params.rs
+++ b/embassy-stm32/src/subghz/tx_params.rs
@@ -44,6 +44,7 @@ impl From<RampTime> for core::time::Duration {
44 } 44 }
45} 45}
46 46
47#[cfg(feature = "time")]
47impl From<RampTime> for embassy_time::Duration { 48impl From<RampTime> for embassy_time::Duration {
48 fn from(rt: RampTime) -> Self { 49 fn from(rt: RampTime) -> Self {
49 match rt { 50 match rt {
diff --git a/examples/stm32f4/src/bin/i2c.rs b/examples/stm32f4/src/bin/i2c.rs
new file mode 100644
index 000000000..6e51c211d
--- /dev/null
+++ b/examples/stm32f4/src/bin/i2c.rs
@@ -0,0 +1,45 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::*;
6use embassy_executor::Spawner;
7use embassy_stm32::dma::NoDma;
8use embassy_stm32::i2c::{Error, I2c, TimeoutI2c};
9use embassy_stm32::interrupt;
10use embassy_stm32::time::Hertz;
11use embassy_time::Duration;
12use {defmt_rtt as _, panic_probe as _};
13
14const ADDRESS: u8 = 0x5F;
15const WHOAMI: u8 = 0x0F;
16
17#[embassy_executor::main]
18async fn main(_spawner: Spawner) -> ! {
19 info!("Hello world!");
20 let p = embassy_stm32::init(Default::default());
21
22 let irq = interrupt::take!(I2C2_EV);
23 let mut i2c = I2c::new(
24 p.I2C2,
25 p.PB10,
26 p.PB11,
27 irq,
28 NoDma,
29 NoDma,
30 Hertz(100_000),
31 Default::default(),
32 );
33
34 // I2C bus can freeze if SCL line is shorted or due to a broken device that clock stretches for too long.
35 // TimeoutI2c allows recovering from such errors by throwing `Error::Timeout` after a given delay.
36 let mut timeout_i2c = TimeoutI2c::new(&mut i2c, Duration::from_millis(1000));
37
38 let mut data = [0u8; 1];
39
40 match timeout_i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data) {
41 Ok(()) => info!("Whoami: {}", data[0]),
42 Err(Error::Timeout) => error!("Operation timed out"),
43 Err(e) => error!("I2c Error: {:?}", e),
44 }
45}
diff --git a/examples/stm32h7/src/bin/i2c.rs b/examples/stm32h7/src/bin/i2c.rs
new file mode 100644
index 000000000..d44319ae6
--- /dev/null
+++ b/examples/stm32h7/src/bin/i2c.rs
@@ -0,0 +1,44 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::*;
6use embassy_executor::Spawner;
7use embassy_stm32::i2c::{Error, I2c, TimeoutI2c};
8use embassy_stm32::interrupt;
9use embassy_stm32::time::Hertz;
10use embassy_time::Duration;
11use {defmt_rtt as _, panic_probe as _};
12
13const ADDRESS: u8 = 0x5F;
14const WHOAMI: u8 = 0x0F;
15
16#[embassy_executor::main]
17async fn main(_spawner: Spawner) -> ! {
18 info!("Hello world!");
19 let p = embassy_stm32::init(Default::default());
20
21 let irq = interrupt::take!(I2C2_EV);
22 let mut i2c = I2c::new(
23 p.I2C2,
24 p.PB10,
25 p.PB11,
26 irq,
27 p.DMA1_CH4,
28 p.DMA1_CH5,
29 Hertz(100_000),
30 Default::default(),
31 );
32
33 // I2C bus can freeze if SCL line is shorted or due to a broken device that clock stretches for too long.
34 // TimeoutI2c allows recovering from such errors by throwing `Error::Timeout` after a given delay.
35 let mut timeout_i2c = TimeoutI2c::new(&mut i2c, Duration::from_millis(1000));
36
37 let mut data = [0u8; 1];
38
39 match timeout_i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data) {
40 Ok(()) => info!("Whoami: {}", data[0]),
41 Err(Error::Timeout) => error!("Operation timed out"),
42 Err(e) => error!("I2c Error: {:?}", e),
43 }
44}