diff options
| -rw-r--r-- | embassy-stm32/src/i2c/v2.rs | 67 |
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, |
