aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchemicstry <[email protected]>2022-10-24 12:33:17 +0300
committerchemicstry <[email protected]>2022-10-24 12:33:17 +0300
commit1bed02296cf15013e0149b36c3ddedb3278e9b88 (patch)
treed2cbc692ea1aab186f8994c24aab97fb4c877faf
parentd99841fea90caccfd95c2dad8f233ab3198f7371 (diff)
i2cv2 timeouts
-rw-r--r--embassy-stm32/src/i2c/v2.rs188
-rw-r--r--examples/stm32h7/src/bin/i2c.rs41
2 files changed, 174 insertions, 55 deletions
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 89b52da98..40413b696 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,19 @@ 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(address: u8, length: usize, stop: Stop, reload: bool, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
182 assert!(length < 256); 193 assert!(length < 256);
183 194
184 // Wait for any previous address sequence to end 195 // Wait for any previous address sequence to end
185 // automatically. This could be up to 50% of a bus 196 // automatically. This could be up to 50% of a bus
186 // cycle (ie. up to 0.5/freq) 197 // cycle (ie. up to 0.5/freq)
187 while T::regs().cr2().read().start() {} 198 while T::regs().cr2().read().start() {
199 check_timeout()?;
200 }
188 201
189 let reload = if reload { 202 let reload = if reload {
190 i2c::vals::Reload::NOTCOMPLETED 203 i2c::vals::Reload::NOTCOMPLETED
@@ -204,12 +217,16 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
204 w.set_autoend(stop.autoend()); 217 w.set_autoend(stop.autoend());
205 w.set_reload(reload); 218 w.set_reload(reload);
206 }); 219 });
220
221 Ok(())
207 } 222 }
208 223
209 unsafe fn master_continue(length: usize, reload: bool) { 224 unsafe fn master_continue(length: usize, reload: bool, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
210 assert!(length < 256 && length > 0); 225 assert!(length < 256 && length > 0);
211 226
212 while !T::regs().isr().read().tcr() {} 227 while !T::regs().isr().read().tcr() {
228 check_timeout()?;
229 }
213 230
214 let reload = if reload { 231 let reload = if reload {
215 i2c::vals::Reload::NOTCOMPLETED 232 i2c::vals::Reload::NOTCOMPLETED
@@ -221,6 +238,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
221 w.set_nbytes(length as u8); 238 w.set_nbytes(length as u8);
222 w.set_reload(reload); 239 w.set_reload(reload);
223 }); 240 });
241
242 Ok(())
224 } 243 }
225 244
226 fn flush_txdr(&self) { 245 fn flush_txdr(&self) {
@@ -243,7 +262,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
243 //} 262 //}
244 } 263 }
245 264
246 fn wait_txe(&self) -> Result<(), Error> { 265 fn wait_txe(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
247 loop { 266 loop {
248 unsafe { 267 unsafe {
249 let isr = T::regs().isr().read(); 268 let isr = T::regs().isr().read();
@@ -261,10 +280,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
261 return Err(Error::Nack); 280 return Err(Error::Nack);
262 } 281 }
263 } 282 }
283
284 check_timeout()?;
264 } 285 }
265 } 286 }
266 287
267 fn wait_rxne(&self) -> Result<(), Error> { 288 fn wait_rxne(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
268 loop { 289 loop {
269 unsafe { 290 unsafe {
270 let isr = T::regs().isr().read(); 291 let isr = T::regs().isr().read();
@@ -282,10 +303,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
282 return Err(Error::Nack); 303 return Err(Error::Nack);
283 } 304 }
284 } 305 }
306
307 check_timeout()?;
285 } 308 }
286 } 309 }
287 310
288 fn wait_tc(&self) -> Result<(), Error> { 311 fn wait_tc(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
289 loop { 312 loop {
290 unsafe { 313 unsafe {
291 let isr = T::regs().isr().read(); 314 let isr = T::regs().isr().read();
@@ -303,10 +326,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
303 return Err(Error::Nack); 326 return Err(Error::Nack);
304 } 327 }
305 } 328 }
329
330 check_timeout()?;
306 } 331 }
307 } 332 }
308 333
309 fn read_internal(&mut self, address: u8, buffer: &mut [u8], restart: bool) -> Result<(), Error> { 334 fn read_internal(&mut self, address: u8, buffer: &mut [u8], restart: bool, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
310 let completed_chunks = buffer.len() / 255; 335 let completed_chunks = buffer.len() / 255;
311 let total_chunks = if completed_chunks * 255 == buffer.len() { 336 let total_chunks = if completed_chunks * 255 == buffer.len() {
312 completed_chunks 337 completed_chunks
@@ -322,20 +347,21 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
322 Stop::Automatic, 347 Stop::Automatic,
323 last_chunk_idx != 0, 348 last_chunk_idx != 0,
324 restart, 349 restart,
325 ); 350 &check_timeout
351 )?;
326 } 352 }
327 353
328 for (number, chunk) in buffer.chunks_mut(255).enumerate() { 354 for (number, chunk) in buffer.chunks_mut(255).enumerate() {
329 if number != 0 { 355 if number != 0 {
330 // NOTE(unsafe) We have &mut self 356 // NOTE(unsafe) We have &mut self
331 unsafe { 357 unsafe {
332 Self::master_continue(chunk.len(), number != last_chunk_idx); 358 Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?;
333 } 359 }
334 } 360 }
335 361
336 for byte in chunk { 362 for byte in chunk {
337 // Wait until we have received something 363 // Wait until we have received something
338 self.wait_rxne()?; 364 self.wait_rxne(&check_timeout)?;
339 365
340 unsafe { 366 unsafe {
341 *byte = T::regs().rxdr().read().rxdata(); 367 *byte = T::regs().rxdr().read().rxdata();
@@ -345,7 +371,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
345 Ok(()) 371 Ok(())
346 } 372 }
347 373
348 fn write_internal(&mut self, address: u8, bytes: &[u8], send_stop: bool) -> Result<(), Error> { 374 fn write_internal(&mut self, address: u8, bytes: &[u8], send_stop: bool, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
349 let completed_chunks = bytes.len() / 255; 375 let completed_chunks = bytes.len() / 255;
350 let total_chunks = if completed_chunks * 255 == bytes.len() { 376 let total_chunks = if completed_chunks * 255 == bytes.len() {
351 completed_chunks 377 completed_chunks
@@ -359,14 +385,14 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
359 // ST SAD+W 385 // ST SAD+W
360 // NOTE(unsafe) We have &mut self 386 // NOTE(unsafe) We have &mut self
361 unsafe { 387 unsafe {
362 Self::master_write(address, bytes.len().min(255), Stop::Software, last_chunk_idx != 0); 388 Self::master_write(address, bytes.len().min(255), Stop::Software, last_chunk_idx != 0, &check_timeout)?;
363 } 389 }
364 390
365 for (number, chunk) in bytes.chunks(255).enumerate() { 391 for (number, chunk) in bytes.chunks(255).enumerate() {
366 if number != 0 { 392 if number != 0 {
367 // NOTE(unsafe) We have &mut self 393 // NOTE(unsafe) We have &mut self
368 unsafe { 394 unsafe {
369 Self::master_continue(chunk.len(), number != last_chunk_idx); 395 Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?;
370 } 396 }
371 } 397 }
372 398
@@ -374,7 +400,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
374 // Wait until we are allowed to send data 400 // Wait until we are allowed to send data
375 // (START has been ACKed or last byte when 401 // (START has been ACKed or last byte when
376 // through) 402 // through)
377 self.wait_txe()?; 403 self.wait_txe(&check_timeout)?;
378 404
379 unsafe { 405 unsafe {
380 T::regs().txdr().write(|w| w.set_txdata(*byte)); 406 T::regs().txdr().write(|w| w.set_txdata(*byte));
@@ -382,7 +408,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
382 } 408 }
383 } 409 }
384 // Wait until the write finishes 410 // Wait until the write finishes
385 self.wait_tc()?; 411 self.wait_tc(&check_timeout)?;
386 412
387 if send_stop { 413 if send_stop {
388 self.master_stop(); 414 self.master_stop();
@@ -396,6 +422,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
396 bytes: &[u8], 422 bytes: &[u8],
397 first_slice: bool, 423 first_slice: bool,
398 last_slice: bool, 424 last_slice: bool,
425 check_timeout: impl Fn() -> Result<(), Error>
399 ) -> Result<(), Error> 426 ) -> Result<(), Error>
400 where 427 where
401 TXDMA: crate::i2c::TxDma<T>, 428 TXDMA: crate::i2c::TxDma<T>,
@@ -447,11 +474,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
447 total_len.min(255), 474 total_len.min(255),
448 Stop::Software, 475 Stop::Software,
449 (total_chunks != 1) || !last_slice, 476 (total_chunks != 1) || !last_slice,
450 ); 477 &check_timeout
478 )?;
451 } 479 }
452 } else { 480 } else {
453 unsafe { 481 unsafe {
454 Self::master_continue(total_len.min(255), (total_chunks != 1) || !last_slice); 482 Self::master_continue(total_len.min(255), (total_chunks != 1) || !last_slice, &check_timeout)?;
455 T::regs().cr1().modify(|w| w.set_tcie(true)); 483 T::regs().cr1().modify(|w| w.set_tcie(true));
456 } 484 }
457 } 485 }
@@ -461,32 +489,34 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
461 let chunks_transferred = state.chunks_transferred.load(Ordering::Relaxed); 489 let chunks_transferred = state.chunks_transferred.load(Ordering::Relaxed);
462 490
463 if chunks_transferred == total_chunks { 491 if chunks_transferred == total_chunks {
464 return Poll::Ready(()); 492 return Poll::Ready(Ok(()));
465 } else if chunks_transferred != 0 { 493 } else if chunks_transferred != 0 {
466 remaining_len = remaining_len.saturating_sub(255); 494 remaining_len = remaining_len.saturating_sub(255);
467 let last_piece = (chunks_transferred + 1 == total_chunks) && last_slice; 495 let last_piece = (chunks_transferred + 1 == total_chunks) && last_slice;
468 496
469 // NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers 497 // NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers
470 unsafe { 498 unsafe {
471 Self::master_continue(remaining_len.min(255), !last_piece); 499 if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) {
500 return Poll::Ready(Err(e));
501 }
472 T::regs().cr1().modify(|w| w.set_tcie(true)); 502 T::regs().cr1().modify(|w| w.set_tcie(true));
473 } 503 }
474 } 504 }
475 Poll::Pending 505 Poll::Pending
476 }) 506 })
477 .await; 507 .await?;
478 508
479 dma_transfer.await; 509 dma_transfer.await;
480 510
481 if last_slice { 511 if last_slice {
482 // This should be done already 512 // This should be done already
483 self.wait_tc()?; 513 self.wait_tc(&check_timeout)?;
484 self.master_stop(); 514 self.master_stop();
485 } 515 }
486 Ok(()) 516 Ok(())
487 } 517 }
488 518
489 async fn read_dma_internal(&mut self, address: u8, buffer: &mut [u8], restart: bool) -> Result<(), Error> 519 async fn read_dma_internal(&mut self, address: u8, buffer: &mut [u8], restart: bool, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error>
490 where 520 where
491 RXDMA: crate::i2c::RxDma<T>, 521 RXDMA: crate::i2c::RxDma<T>,
492 { 522 {
@@ -527,7 +557,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
527 557
528 // NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers 558 // NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers
529 unsafe { 559 unsafe {
530 Self::master_read(address, total_len.min(255), Stop::Software, total_chunks != 1, restart); 560 Self::master_read(address, total_len.min(255), Stop::Software, total_chunks != 1, restart, &check_timeout)?;
531 } 561 }
532 562
533 poll_fn(|cx| { 563 poll_fn(|cx| {
@@ -535,25 +565,27 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
535 let chunks_transferred = state.chunks_transferred.load(Ordering::Relaxed); 565 let chunks_transferred = state.chunks_transferred.load(Ordering::Relaxed);
536 566
537 if chunks_transferred == total_chunks { 567 if chunks_transferred == total_chunks {
538 return Poll::Ready(()); 568 return Poll::Ready(Ok(()));
539 } else if chunks_transferred != 0 { 569 } else if chunks_transferred != 0 {
540 remaining_len = remaining_len.saturating_sub(255); 570 remaining_len = remaining_len.saturating_sub(255);
541 let last_piece = chunks_transferred + 1 == total_chunks; 571 let last_piece = chunks_transferred + 1 == total_chunks;
542 572
543 // NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers 573 // NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers
544 unsafe { 574 unsafe {
545 Self::master_continue(remaining_len.min(255), !last_piece); 575 if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) {
576 return Poll::Ready(Err(e))
577 }
546 T::regs().cr1().modify(|w| w.set_tcie(true)); 578 T::regs().cr1().modify(|w| w.set_tcie(true));
547 } 579 }
548 } 580 }
549 Poll::Pending 581 Poll::Pending
550 }) 582 })
551 .await; 583 .await?;
552 584
553 dma_transfer.await; 585 dma_transfer.await;
554 586
555 // This should be done already 587 // This should be done already
556 self.wait_tc()?; 588 self.wait_tc(&check_timeout)?;
557 self.master_stop(); 589 self.master_stop();
558 Ok(()) 590 Ok(())
559 } 591 }
@@ -561,18 +593,25 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
561 // ========================= 593 // =========================
562 // Async public API 594 // Async public API
563 595
564 pub async fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Error> 596 pub async fn write_timeout(&mut self, address: u8, bytes: &[u8], check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error>
565 where 597 where
566 TXDMA: crate::i2c::TxDma<T>, 598 TXDMA: crate::i2c::TxDma<T>,
567 { 599 {
568 if bytes.is_empty() { 600 if bytes.is_empty() {
569 self.write_internal(address, bytes, true) 601 self.write_internal(address, bytes, true, &check_timeout)
570 } else { 602 } else {
571 self.write_dma_internal(address, bytes, true, true).await 603 self.write_dma_internal(address, bytes, true, true, &check_timeout).await
572 } 604 }
573 } 605 }
574 606
575 pub async fn write_vectored(&mut self, address: u8, bytes: &[&[u8]]) -> Result<(), Error> 607 pub async fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Error>
608 where
609 TXDMA: crate::i2c::TxDma<T>,
610 {
611 self.write_timeout(address, bytes, || Ok(())).await
612 }
613
614 pub async fn write_vectored_timeout(&mut self, address: u8, bytes: &[&[u8]], check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error>
576 where 615 where
577 TXDMA: crate::i2c::TxDma<T>, 616 TXDMA: crate::i2c::TxDma<T>,
578 { 617 {
@@ -587,63 +626,97 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
587 let next = iter.next(); 626 let next = iter.next();
588 let is_last = next.is_none(); 627 let is_last = next.is_none();
589 628
590 self.write_dma_internal(address, c, first, is_last).await?; 629 self.write_dma_internal(address, c, first, is_last, &check_timeout).await?;
591 first = false; 630 first = false;
592 current = next; 631 current = next;
593 } 632 }
594 Ok(()) 633 Ok(())
595 } 634 }
596 635
597 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> 636 pub async fn write_vectored(&mut self, address: u8, bytes: &[&[u8]]) -> Result<(), Error>
637 where
638 TXDMA: crate::i2c::TxDma<T>,
639 {
640 self.write_vectored_timeout(address, bytes, || Ok(())).await
641 }
642
643 pub async fn read_timeout(&mut self, address: u8, buffer: &mut [u8], check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error>
598 where 644 where
599 RXDMA: crate::i2c::RxDma<T>, 645 RXDMA: crate::i2c::RxDma<T>,
600 { 646 {
601 if buffer.is_empty() { 647 if buffer.is_empty() {
602 self.read_internal(address, buffer, false) 648 self.read_internal(address, buffer, false, &check_timeout)
603 } else { 649 } else {
604 self.read_dma_internal(address, buffer, false).await 650 self.read_dma_internal(address, buffer, false, &check_timeout).await
605 } 651 }
606 } 652 }
607 653
608 pub async fn write_read(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> 654 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
655 where
656 RXDMA: crate::i2c::RxDma<T>,
657 {
658 self.read_timeout(address, buffer, || Ok(())).await
659 }
660
661 pub async fn write_read_timeout(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8], check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error>
609 where 662 where
610 TXDMA: super::TxDma<T>, 663 TXDMA: super::TxDma<T>,
611 RXDMA: super::RxDma<T>, 664 RXDMA: super::RxDma<T>,
612 { 665 {
613 if bytes.is_empty() { 666 if bytes.is_empty() {
614 self.write_internal(address, bytes, false)?; 667 self.write_internal(address, bytes, false, &check_timeout)?;
615 } else { 668 } else {
616 self.write_dma_internal(address, bytes, true, true).await?; 669 self.write_dma_internal(address, bytes, true, true, &check_timeout).await?;
617 } 670 }
618 671
619 if buffer.is_empty() { 672 if buffer.is_empty() {
620 self.read_internal(address, buffer, true)?; 673 self.read_internal(address, buffer, true, &check_timeout)?;
621 } else { 674 } else {
622 self.read_dma_internal(address, buffer, true).await?; 675 self.read_dma_internal(address, buffer, true, &check_timeout).await?;
623 } 676 }
624 677
625 Ok(()) 678 Ok(())
626 } 679 }
627 680
681 pub async fn write_read(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error>
682 where
683 TXDMA: super::TxDma<T>,
684 RXDMA: super::RxDma<T>,
685 {
686 self.write_read_timeout(address, bytes, buffer, || Ok(())).await
687 }
688
628 // ========================= 689 // =========================
629 // Blocking public API 690 // Blocking public API
630 691
631 pub fn blocking_read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { 692 pub fn blocking_read_timeout(&mut self, address: u8, buffer: &mut [u8], check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
632 self.read_internal(address, buffer, false) 693 self.read_internal(address, buffer, false, &check_timeout)
633 // Automatic Stop 694 // Automatic Stop
634 } 695 }
635 696
697 pub fn blocking_read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
698 self.blocking_read_timeout(address, buffer, || Ok(()))
699 }
700
701 pub fn blocking_write_timeout(&mut self, address: u8, bytes: &[u8], check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
702 self.write_internal(address, bytes, true, &check_timeout)
703 }
704
636 pub fn blocking_write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Error> { 705 pub fn blocking_write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Error> {
637 self.write_internal(address, bytes, true) 706 self.blocking_write_timeout(address, bytes, || Ok(()))
638 } 707 }
639 708
640 pub fn blocking_write_read(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> { 709 pub fn blocking_write_read_timeout(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8], check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
641 self.write_internal(address, bytes, false)?; 710 self.write_internal(address, bytes, false, &check_timeout)?;
642 self.read_internal(address, buffer, true) 711 self.read_internal(address, buffer, true, &check_timeout)
643 // Automatic Stop 712 // Automatic Stop
644 } 713 }
645 714
646 pub fn blocking_write_vectored(&mut self, address: u8, bytes: &[&[u8]]) -> Result<(), Error> { 715 pub fn blocking_write_read(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
716 self.blocking_write_read_timeout(address, bytes, buffer, || Ok(()))
717 }
718
719 pub fn blocking_write_vectored_timeout(&mut self, address: u8, bytes: &[&[u8]], check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
647 if bytes.is_empty() { 720 if bytes.is_empty() {
648 return Err(Error::ZeroLengthTransfer); 721 return Err(Error::ZeroLengthTransfer);
649 } 722 }
@@ -657,7 +730,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
657 first_length.min(255), 730 first_length.min(255),
658 Stop::Software, 731 Stop::Software,
659 (first_length > 255) || (last_slice_index != 0), 732 (first_length > 255) || (last_slice_index != 0),
660 ); 733 &check_timeout
734 )?;
661 } 735 }
662 736
663 for (idx, slice) in bytes.iter().enumerate() { 737 for (idx, slice) in bytes.iter().enumerate() {
@@ -673,7 +747,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
673 if idx != 0 { 747 if idx != 0 {
674 // NOTE(unsafe) We have &mut self 748 // NOTE(unsafe) We have &mut self
675 unsafe { 749 unsafe {
676 Self::master_continue(slice_len.min(255), (idx != last_slice_index) || (slice_len > 255)); 750 Self::master_continue(slice_len.min(255), (idx != last_slice_index) || (slice_len > 255), &check_timeout)?;
677 } 751 }
678 } 752 }
679 753
@@ -681,7 +755,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
681 if number != 0 { 755 if number != 0 {
682 // NOTE(unsafe) We have &mut self 756 // NOTE(unsafe) We have &mut self
683 unsafe { 757 unsafe {
684 Self::master_continue(chunk.len(), (number != last_chunk_idx) || (idx != last_slice_index)); 758 Self::master_continue(chunk.len(), (number != last_chunk_idx) || (idx != last_slice_index), &check_timeout)?;
685 } 759 }
686 } 760 }
687 761
@@ -689,7 +763,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
689 // Wait until we are allowed to send data 763 // Wait until we are allowed to send data
690 // (START has been ACKed or last byte when 764 // (START has been ACKed or last byte when
691 // through) 765 // through)
692 self.wait_txe()?; 766 self.wait_txe(&check_timeout)?;
693 767
694 // Put byte on the wire 768 // Put byte on the wire
695 //self.i2c.txdr.write(|w| w.txdata().bits(*byte)); 769 //self.i2c.txdr.write(|w| w.txdata().bits(*byte));
@@ -700,11 +774,15 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
700 } 774 }
701 } 775 }
702 // Wait until the write finishes 776 // Wait until the write finishes
703 self.wait_tc()?; 777 self.wait_tc(&check_timeout)?;
704 self.master_stop(); 778 self.master_stop();
705 779
706 Ok(()) 780 Ok(())
707 } 781 }
782
783 pub fn blocking_write_vectored(&mut self, address: u8, bytes: &[&[u8]]) -> Result<(), Error> {
784 self.blocking_write_vectored_timeout(address, bytes, || Ok(()))
785 }
708} 786}
709 787
710mod eh02 { 788mod eh02 {
diff --git a/examples/stm32h7/src/bin/i2c.rs b/examples/stm32h7/src/bin/i2c.rs
new file mode 100644
index 000000000..7a314b996
--- /dev/null
+++ b/examples/stm32h7/src/bin/i2c.rs
@@ -0,0 +1,41 @@
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 let mut timeout_i2c = TimeoutI2c::new(&mut i2c, Duration::from_millis(1000));
33
34 let mut data = [0u8; 1];
35
36 match timeout_i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data) {
37 Ok(()) => info!("Whoami: {}", data[0]),
38 Err(Error::Timeout) => error!("Operation timed out"),
39 Err(e) => error!("I2c Error: {:?}", e),
40 }
41}