From 8e7d0e6406d8e701860a3138292ae87d75ddc8b0 Mon Sep 17 00:00:00 2001 From: TrAyZeN Date: Mon, 1 Dec 2025 10:57:41 +0100 Subject: [PATCH 1/3] stm32/i2c: Restrict listen to async I2c mode --- embassy-stm32/src/i2c/v2.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 6b213484c6..4f105adefa 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -1673,6 +1673,22 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> { Ok(()) } + /// Respond to a write command. + /// + /// Returns total number of bytes received. + pub fn blocking_respond_to_write(&self, read: &mut [u8]) -> Result { + let timeout = self.timeout(); + self.slave_read_internal(read, timeout) + } + + /// Respond to a read command. + pub fn blocking_respond_to_read(&mut self, write: &[u8]) -> Result<(), Error> { + let timeout = self.timeout(); + self.slave_write_internal(write, timeout) + } +} + +impl<'d> I2c<'d, Async, MultiMaster> { /// Listen for incoming I2C messages. /// /// The listen method is an asynchronous method but it does not require DMA to be asynchronous. @@ -1713,22 +1729,6 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> { .await } - /// Respond to a write command. - /// - /// Returns total number of bytes received. - pub fn blocking_respond_to_write(&self, read: &mut [u8]) -> Result { - let timeout = self.timeout(); - self.slave_read_internal(read, timeout) - } - - /// Respond to a read command. - pub fn blocking_respond_to_read(&mut self, write: &[u8]) -> Result<(), Error> { - let timeout = self.timeout(); - self.slave_write_internal(write, timeout) - } -} - -impl<'d> I2c<'d, Async, MultiMaster> { /// Respond to a write command. /// /// Returns the total number of bytes received. From ac89dbd3447993f7940b60400fb3e2d479956836 Mon Sep 17 00:00:00 2001 From: TrAyZeN Date: Mon, 1 Dec 2025 11:25:06 +0100 Subject: [PATCH 2/3] stm32/i2c: Add blocking_listen --- embassy-stm32/src/i2c/v2.rs | 65 ++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 4f105adefa..933cca9cb1 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -1673,6 +1673,54 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> { Ok(()) } + /// Listen for incoming I2C messages. + /// + /// This method blocks until the slave address is matched by a master. + pub fn blocking_listen(&mut self) -> Result { + let timeout = self.timeout(); + + self.info.regs.cr1().modify(|reg| { + reg.set_addrie(true); + trace!("Enable ADDRIE"); + }); + + loop { + let isr = self.info.regs.isr().read(); + if isr.addr() { + break; + } + timeout.check()?; + } + + trace!("ADDR triggered (address match)"); + + // we do not clear the address flag here as it will be cleared by the dma read/write + // if we clear it here the clock stretching will stop and the master will read in data before the slave is ready to send it + self.slave_command() + } + + /// Determine the received slave command. + fn slave_command(&self) -> Result { + let isr = self.info.regs.isr().read(); + + match isr.dir() { + i2c::vals::Dir::WRITE => { + trace!("DIR: write"); + Ok(SlaveCommand { + kind: SlaveCommandKind::Write, + address: self.determine_matched_address()?, + }) + } + i2c::vals::Dir::READ => { + trace!("DIR: read"); + Ok(SlaveCommand { + kind: SlaveCommandKind::Read, + address: self.determine_matched_address()?, + }) + } + } + } + /// Respond to a write command. /// /// Returns total number of bytes received. @@ -1708,22 +1756,7 @@ impl<'d> I2c<'d, Async, MultiMaster> { trace!("ADDR triggered (address match)"); // we do not clear the address flag here as it will be cleared by the dma read/write // if we clear it here the clock stretching will stop and the master will read in data before the slave is ready to send it - match isr.dir() { - i2c::vals::Dir::WRITE => { - trace!("DIR: write"); - Poll::Ready(Ok(SlaveCommand { - kind: SlaveCommandKind::Write, - address: self.determine_matched_address()?, - })) - } - i2c::vals::Dir::READ => { - trace!("DIR: read"); - Poll::Ready(Ok(SlaveCommand { - kind: SlaveCommandKind::Read, - address: self.determine_matched_address()?, - })) - } - } + Poll::Ready(self.slave_command()) } }) .await From 52a9b08f0ca13d23bfb039c884a9101997c10567 Mon Sep 17 00:00:00 2001 From: TrAyZeN Date: Mon, 1 Dec 2025 11:51:33 +0100 Subject: [PATCH 3/3] chore: Update changelog --- embassy-stm32/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 2a99d0a96d..6c36bc1089 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -86,6 +86,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - feat: stm32/lcd: added implementation - change: add error messages to can timing calculations ([#4961](https://github.com/embassy-rs/embassy/pull/4961)) - fix: stm32/i2c v2: add stop flag on stop received +- stm32: Add blocking_listen for blocking I2C driver ## 0.4.0 - 2025-08-26