From 47869d122ab68ea9a962ba749c523b94066d0763 Mon Sep 17 00:00:00 2001 From: Fredrik Reinholdsen Date: Thu, 27 Feb 2025 20:18:24 +0100 Subject: [PATCH] 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. --- embassy-stm32/src/i2c/v2.rs | 12 +++++++++--- 1 file 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> { restart, timeout, )?; - } else if remaining_len == 0 { - return Poll::Ready(Ok(())); - } else if !(isr.tcr() || isr.tc()) { + if total_len <= 255 { + return Poll::Ready(Ok(())); + } + } else if isr.tcr() { // poll_fn was woken without an interrupt present return Poll::Pending; } else { @@ -628,6 +629,11 @@ impl<'d> I2c<'d, Async> { if let Err(e) = Self::master_continue(self.info, remaining_len.min(255), !last_piece, timeout) { return Poll::Ready(Err(e)); } + // Return here if we are on last chunk, + // end of transfer will be awaited with the DMA below + if last_piece { + return Poll::Ready(Ok(())); + } self.info.regs.cr1().modify(|w| w.set_tcie(true)); }