aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaw Drastin <[email protected]>2025-02-12 20:54:07 +0800
committerShaw Drastin <[email protected]>2025-02-12 21:16:18 +0800
commit1c1aea62d00fcf920c8c756eb9a8518c1d9338cd (patch)
treed909726160c1a333ce4ad999bac4aea39e30c870
parent712143b81fd02cca2621f021438fdfd042563651 (diff)
stm32: i2c-v2: Add error handling
Currently when error occurres, we have to wait for timeout, which is less than ideal. Enable related interrupts, and return Err when error occurres.
-rw-r--r--embassy-stm32/src/i2c/v2.rs67
1 files changed, 60 insertions, 7 deletions
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 05ac9afcc..e2eb6f367 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -13,13 +13,17 @@ pub(crate) unsafe fn on_interrupt<T: Instance>() {
13 let regs = T::info().regs; 13 let regs = T::info().regs;
14 let isr = regs.isr().read(); 14 let isr = regs.isr().read();
15 15
16 if isr.tcr() || isr.tc() { 16 if isr.tcr() || isr.tc() || isr.nackf() || isr.berr() || isr.arlo() || isr.ovr() {
17 T::state().waker.wake(); 17 T::state().waker.wake();
18 } 18 }
19 // The flag can only be cleared by writting to nbytes, we won't do that here, so disable
20 // the interrupt
21 critical_section::with(|_| { 19 critical_section::with(|_| {
22 regs.cr1().modify(|w| w.set_tcie(false)); 20 regs.cr1().modify(|w| {
21 // The flag can only be cleared by writting to nbytes, we won't do that here
22 w.set_tcie(false);
23 // Error flags are to be read in the routines, so we also don't clear them here
24 w.set_nackie(false);
25 w.set_errie(false);
26 });
23 }); 27 });
24} 28}
25 29
@@ -449,6 +453,8 @@ impl<'d> I2c<'d, Async> {
449 if first_slice { 453 if first_slice {
450 w.set_tcie(true); 454 w.set_tcie(true);
451 } 455 }
456 w.set_nackie(true);
457 w.set_errie(true);
452 }); 458 });
453 let dst = regs.txdr().as_ptr() as *mut u8; 459 let dst = regs.txdr().as_ptr() as *mut u8;
454 460
@@ -459,18 +465,41 @@ impl<'d> I2c<'d, Async> {
459 465
460 let on_drop = OnDrop::new(|| { 466 let on_drop = OnDrop::new(|| {
461 let regs = self.info.regs; 467 let regs = self.info.regs;
468 let isr = regs.isr().read();
462 regs.cr1().modify(|w| { 469 regs.cr1().modify(|w| {
463 if last_slice { 470 if last_slice || isr.nackf() || isr.arlo() || isr.berr() || isr.ovr() {
464 w.set_txdmaen(false); 471 w.set_txdmaen(false);
465 } 472 }
466 w.set_tcie(false); 473 w.set_tcie(false);
467 }) 474 w.set_nackie(false);
475 w.set_errie(false);
476 });
477 regs.icr().write(|w| {
478 w.set_nackcf(true);
479 w.set_berrcf(true);
480 w.set_arlocf(true);
481 w.set_ovrcf(true);
482 });
468 }); 483 });
469 484
470 poll_fn(|cx| { 485 poll_fn(|cx| {
471 self.state.waker.register(cx.waker()); 486 self.state.waker.register(cx.waker());
472 487
473 let isr = self.info.regs.isr().read(); 488 let isr = self.info.regs.isr().read();
489
490 if isr.nackf() {
491 return Poll::Ready(Err(Error::Nack));
492 }
493 if isr.arlo() {
494 return Poll::Ready(Err(Error::Arbitration));
495 }
496 if isr.berr() {
497 return Poll::Ready(Err(Error::Bus));
498 }
499 if isr.ovr() {
500 return Poll::Ready(Err(Error::Overrun));
501 }
502
474 if remaining_len == total_len { 503 if remaining_len == total_len {
475 if first_slice { 504 if first_slice {
476 Self::master_write( 505 Self::master_write(
@@ -531,6 +560,8 @@ impl<'d> I2c<'d, Async> {
531 regs.cr1().modify(|w| { 560 regs.cr1().modify(|w| {
532 w.set_rxdmaen(true); 561 w.set_rxdmaen(true);
533 w.set_tcie(true); 562 w.set_tcie(true);
563 w.set_nackie(true);
564 w.set_errie(true);
534 }); 565 });
535 let src = regs.rxdr().as_ptr() as *mut u8; 566 let src = regs.rxdr().as_ptr() as *mut u8;
536 567
@@ -544,13 +575,35 @@ impl<'d> I2c<'d, Async> {
544 regs.cr1().modify(|w| { 575 regs.cr1().modify(|w| {
545 w.set_rxdmaen(false); 576 w.set_rxdmaen(false);
546 w.set_tcie(false); 577 w.set_tcie(false);
547 }) 578 w.set_nackie(false);
579 w.set_errie(false);
580 });
581 regs.icr().write(|w| {
582 w.set_nackcf(true);
583 w.set_berrcf(true);
584 w.set_arlocf(true);
585 w.set_ovrcf(true);
586 });
548 }); 587 });
549 588
550 poll_fn(|cx| { 589 poll_fn(|cx| {
551 self.state.waker.register(cx.waker()); 590 self.state.waker.register(cx.waker());
552 591
553 let isr = self.info.regs.isr().read(); 592 let isr = self.info.regs.isr().read();
593
594 if isr.nackf() {
595 return Poll::Ready(Err(Error::Nack));
596 }
597 if isr.arlo() {
598 return Poll::Ready(Err(Error::Arbitration));
599 }
600 if isr.berr() {
601 return Poll::Ready(Err(Error::Bus));
602 }
603 if isr.ovr() {
604 return Poll::Ready(Err(Error::Overrun));
605 }
606
554 if remaining_len == total_len { 607 if remaining_len == total_len {
555 Self::master_read( 608 Self::master_read(
556 self.info, 609 self.info,