aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 8801fddf0..71769bbc1 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
@@ -450,6 +454,8 @@ impl<'d> I2c<'d, Async> {
450 if first_slice { 454 if first_slice {
451 w.set_tcie(true); 455 w.set_tcie(true);
452 } 456 }
457 w.set_nackie(true);
458 w.set_errie(true);
453 }); 459 });
454 let dst = regs.txdr().as_ptr() as *mut u8; 460 let dst = regs.txdr().as_ptr() as *mut u8;
455 461
@@ -460,18 +466,41 @@ impl<'d> I2c<'d, Async> {
460 466
461 let on_drop = OnDrop::new(|| { 467 let on_drop = OnDrop::new(|| {
462 let regs = self.info.regs; 468 let regs = self.info.regs;
469 let isr = regs.isr().read();
463 regs.cr1().modify(|w| { 470 regs.cr1().modify(|w| {
464 if last_slice { 471 if last_slice || isr.nackf() || isr.arlo() || isr.berr() || isr.ovr() {
465 w.set_txdmaen(false); 472 w.set_txdmaen(false);
466 } 473 }
467 w.set_tcie(false); 474 w.set_tcie(false);
468 }) 475 w.set_nackie(false);
476 w.set_errie(false);
477 });
478 regs.icr().write(|w| {
479 w.set_nackcf(true);
480 w.set_berrcf(true);
481 w.set_arlocf(true);
482 w.set_ovrcf(true);
483 });
469 }); 484 });
470 485
471 poll_fn(|cx| { 486 poll_fn(|cx| {
472 self.state.waker.register(cx.waker()); 487 self.state.waker.register(cx.waker());
473 488
474 let isr = self.info.regs.isr().read(); 489 let isr = self.info.regs.isr().read();
490
491 if isr.nackf() {
492 return Poll::Ready(Err(Error::Nack));
493 }
494 if isr.arlo() {
495 return Poll::Ready(Err(Error::Arbitration));
496 }
497 if isr.berr() {
498 return Poll::Ready(Err(Error::Bus));
499 }
500 if isr.ovr() {
501 return Poll::Ready(Err(Error::Overrun));
502 }
503
475 if remaining_len == total_len { 504 if remaining_len == total_len {
476 if first_slice { 505 if first_slice {
477 Self::master_write( 506 Self::master_write(
@@ -534,6 +563,8 @@ impl<'d> I2c<'d, Async> {
534 regs.cr1().modify(|w| { 563 regs.cr1().modify(|w| {
535 w.set_rxdmaen(true); 564 w.set_rxdmaen(true);
536 w.set_tcie(true); 565 w.set_tcie(true);
566 w.set_nackie(true);
567 w.set_errie(true);
537 }); 568 });
538 let src = regs.rxdr().as_ptr() as *mut u8; 569 let src = regs.rxdr().as_ptr() as *mut u8;
539 570
@@ -547,13 +578,35 @@ impl<'d> I2c<'d, Async> {
547 regs.cr1().modify(|w| { 578 regs.cr1().modify(|w| {
548 w.set_rxdmaen(false); 579 w.set_rxdmaen(false);
549 w.set_tcie(false); 580 w.set_tcie(false);
550 }) 581 w.set_nackie(false);
582 w.set_errie(false);
583 });
584 regs.icr().write(|w| {
585 w.set_nackcf(true);
586 w.set_berrcf(true);
587 w.set_arlocf(true);
588 w.set_ovrcf(true);
589 });
551 }); 590 });
552 591
553 poll_fn(|cx| { 592 poll_fn(|cx| {
554 self.state.waker.register(cx.waker()); 593 self.state.waker.register(cx.waker());
555 594
556 let isr = self.info.regs.isr().read(); 595 let isr = self.info.regs.isr().read();
596
597 if isr.nackf() {
598 return Poll::Ready(Err(Error::Nack));
599 }
600 if isr.arlo() {
601 return Poll::Ready(Err(Error::Arbitration));
602 }
603 if isr.berr() {
604 return Poll::Ready(Err(Error::Bus));
605 }
606 if isr.ovr() {
607 return Poll::Ready(Err(Error::Overrun));
608 }
609
557 if remaining_len == total_len { 610 if remaining_len == total_len {
558 Self::master_read( 611 Self::master_read(
559 self.info, 612 self.info,