diff options
| author | Fredrik Reinholdsen <[email protected]> | 2025-02-27 20:18:24 +0100 |
|---|---|---|
| committer | Fredrik Reinholdsen <[email protected]> | 2025-04-01 21:28:07 +0200 |
| commit | 47869d122ab68ea9a962ba749c523b94066d0763 (patch) | |
| tree | afcb217b741fb4cc8eef31c602b55b3155e8dd9e | |
| parent | a44abaf7e4562fa5393087fd845bf0d02141325b (diff) | |
fix: Fix for #3888 async I2C read bug for introduced in #3887 in STM32 I2C v2 driver
In fixing a different timing related bug, #3887, a new bug was introduced causing I2C reads longer than 255 bytes to timeout for some I2C devices, #3888.
The issue was caused by incorrect branch order, and poll function being called unnecessarily.
Async I2C read poll function now only looks for I2C transfer complete reload (TCR) interrupts, intead of TCR and transfer complete (TC) interrupts,
since TC interrupts are not raised when AUTOEND bit is set.
| -rw-r--r-- | embassy-stm32/src/i2c/v2.rs | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 1f53a995d..50a25754e 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs | |||
| @@ -617,9 +617,10 @@ impl<'d> I2c<'d, Async> { | |||
| 617 | restart, | 617 | restart, |
| 618 | timeout, | 618 | timeout, |
| 619 | )?; | 619 | )?; |
| 620 | } else if remaining_len == 0 { | 620 | if total_len <= 255 { |
| 621 | return Poll::Ready(Ok(())); | 621 | return Poll::Ready(Ok(())); |
| 622 | } else if !(isr.tcr() || isr.tc()) { | 622 | } |
| 623 | } else if isr.tcr() { | ||
| 623 | // poll_fn was woken without an interrupt present | 624 | // poll_fn was woken without an interrupt present |
| 624 | return Poll::Pending; | 625 | return Poll::Pending; |
| 625 | } else { | 626 | } else { |
| @@ -628,6 +629,11 @@ impl<'d> I2c<'d, Async> { | |||
| 628 | if let Err(e) = Self::master_continue(self.info, remaining_len.min(255), !last_piece, timeout) { | 629 | if let Err(e) = Self::master_continue(self.info, remaining_len.min(255), !last_piece, timeout) { |
| 629 | return Poll::Ready(Err(e)); | 630 | return Poll::Ready(Err(e)); |
| 630 | } | 631 | } |
| 632 | // Return here if we are on last chunk, | ||
| 633 | // end of transfer will be awaited with the DMA below | ||
| 634 | if last_piece { | ||
| 635 | return Poll::Ready(Ok(())); | ||
| 636 | } | ||
| 631 | self.info.regs.cr1().modify(|w| w.set_tcie(true)); | 637 | self.info.regs.cr1().modify(|w| w.set_tcie(true)); |
| 632 | } | 638 | } |
| 633 | 639 | ||
