diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 9a91e2f25..d4d4aec5d 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -415,6 +415,10 @@ fn operation_frames<'a, 'b: 'a>( // Check empty read buffer before starting transaction. Otherwise, we would risk halting with an // error in the middle of the transaction. + // + // In principle, we could allow empty read frames within consecutive read operations, as long as + // at least one byte remains in the final (merged) read operation, but that makes the logic more + // complicated and error-prone. if operations.iter().any(|op| match op { Operation::Read(read) => read.is_empty(), Operation::Write(_) => false, diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index 5c57a9ccc..d45c48b24 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs @@ -669,6 +669,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { RXDMA: crate::i2c::RxDma, TXDMA: crate::i2c::TxDma, { + // Check empty read buffer before starting transaction. Otherwise, we would not generate the + // stop condition below. + if read.is_empty() { + return Err(Error::Overrun); + } + self.write_frame(address, write, FrameOptions::FirstFrame).await?; self.read_frame(address, read, FrameOptions::FirstAndLastFrame).await }