aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/CHANGELOG.md1
-rw-r--r--embassy-stm32/src/i2c/v2.rs93
2 files changed, 64 insertions, 30 deletions
diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md
index 449152485..38f22b1c3 100644
--- a/embassy-stm32/CHANGELOG.md
+++ b/embassy-stm32/CHANGELOG.md
@@ -90,6 +90,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
90- change: add error messages to can timing calculations ([#4961](https://github.com/embassy-rs/embassy/pull/4961)) 90- change: add error messages to can timing calculations ([#4961](https://github.com/embassy-rs/embassy/pull/4961))
91- feat: stm32/spi bidirectional mode 91- feat: stm32/spi bidirectional mode
92- fix: stm32/i2c v2: add stop flag on stop received 92- fix: stm32/i2c v2: add stop flag on stop received
93- stm32: Add blocking_listen for blocking I2C driver
93- fix: stm32l47*/stm32l48* adc analog pin setup 94- fix: stm32l47*/stm32l48* adc analog pin setup
94- fix: keep stm32/sai: make NODIV independent of MCKDIV 95- fix: keep stm32/sai: make NODIV independent of MCKDIV
95 96
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 32ce83d40..fe7782a7c 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -1680,43 +1680,50 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
1680 1680
1681 /// Listen for incoming I2C messages. 1681 /// Listen for incoming I2C messages.
1682 /// 1682 ///
1683 /// The listen method is an asynchronous method but it does not require DMA to be asynchronous. 1683 /// This method blocks until the slave address is matched by a master.
1684 pub async fn listen(&mut self) -> Result<SlaveCommand, Error> { 1684 pub fn blocking_listen(&mut self) -> Result<SlaveCommand, Error> {
1685 let _scoped_block_stop = self.info.rcc.block_stop(); 1685 let timeout = self.timeout();
1686 let state = self.state; 1686
1687 self.info.regs.cr1().modify(|reg| { 1687 self.info.regs.cr1().modify(|reg| {
1688 reg.set_addrie(true); 1688 reg.set_addrie(true);
1689 trace!("Enable ADDRIE"); 1689 trace!("Enable ADDRIE");
1690 }); 1690 });
1691 1691
1692 poll_fn(|cx| { 1692 loop {
1693 state.waker.register(cx.waker());
1694 let isr = self.info.regs.isr().read(); 1693 let isr = self.info.regs.isr().read();
1695 if !isr.addr() { 1694 if isr.addr() {
1696 Poll::Pending 1695 break;
1697 } else {
1698 trace!("ADDR triggered (address match)");
1699 // we do not clear the address flag here as it will be cleared by the dma read/write
1700 // 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
1701 match isr.dir() {
1702 i2c::vals::Dir::WRITE => {
1703 trace!("DIR: write");
1704 Poll::Ready(Ok(SlaveCommand {
1705 kind: SlaveCommandKind::Write,
1706 address: self.determine_matched_address()?,
1707 }))
1708 }
1709 i2c::vals::Dir::READ => {
1710 trace!("DIR: read");
1711 Poll::Ready(Ok(SlaveCommand {
1712 kind: SlaveCommandKind::Read,
1713 address: self.determine_matched_address()?,
1714 }))
1715 }
1716 }
1717 } 1696 }
1718 }) 1697 timeout.check()?;
1719 .await 1698 }
1699
1700 trace!("ADDR triggered (address match)");
1701
1702 // we do not clear the address flag here as it will be cleared by the dma read/write
1703 // 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
1704 self.slave_command()
1705 }
1706
1707 /// Determine the received slave command.
1708 fn slave_command(&self) -> Result<SlaveCommand, Error> {
1709 let isr = self.info.regs.isr().read();
1710
1711 match isr.dir() {
1712 i2c::vals::Dir::WRITE => {
1713 trace!("DIR: write");
1714 Ok(SlaveCommand {
1715 kind: SlaveCommandKind::Write,
1716 address: self.determine_matched_address()?,
1717 })
1718 }
1719 i2c::vals::Dir::READ => {
1720 trace!("DIR: read");
1721 Ok(SlaveCommand {
1722 kind: SlaveCommandKind::Read,
1723 address: self.determine_matched_address()?,
1724 })
1725 }
1726 }
1720 } 1727 }
1721 1728
1722 /// Respond to a write command. 1729 /// Respond to a write command.
@@ -1735,6 +1742,32 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
1735} 1742}
1736 1743
1737impl<'d> I2c<'d, Async, MultiMaster> { 1744impl<'d> I2c<'d, Async, MultiMaster> {
1745 /// Listen for incoming I2C messages.
1746 ///
1747 /// The listen method is an asynchronous method but it does not require DMA to be asynchronous.
1748 pub async fn listen(&mut self) -> Result<SlaveCommand, Error> {
1749 let _scoped_block_stop = self.info.rcc.block_stop();
1750 let state = self.state;
1751 self.info.regs.cr1().modify(|reg| {
1752 reg.set_addrie(true);
1753 trace!("Enable ADDRIE");
1754 });
1755
1756 poll_fn(|cx| {
1757 state.waker.register(cx.waker());
1758 let isr = self.info.regs.isr().read();
1759 if !isr.addr() {
1760 Poll::Pending
1761 } else {
1762 trace!("ADDR triggered (address match)");
1763 // we do not clear the address flag here as it will be cleared by the dma read/write
1764 // 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
1765 Poll::Ready(self.slave_command())
1766 }
1767 })
1768 .await
1769 }
1770
1738 /// Respond to a write command. 1771 /// Respond to a write command.
1739 /// 1772 ///
1740 /// Returns the total number of bytes received. 1773 /// Returns the total number of bytes received.