diff options
| author | xoviat <[email protected]> | 2025-12-11 15:50:56 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-12-11 15:50:56 +0000 |
| commit | b1d4efab76fb767948724927b62be9b75d070a7d (patch) | |
| tree | 28f17134cf72bf04c270e809e205ec40c61f7832 /embassy-stm32 | |
| parent | ba04de6f56f837eafce6b9ccd754c51e5302649f (diff) | |
| parent | 1aadce76847a7686bf66e3a6532e18e05042f78a (diff) | |
Merge pull request #4969 from TrAyZeN/main
stm32: Add blocking_listen for blocking I2C driver
Diffstat (limited to 'embassy-stm32')
| -rw-r--r-- | embassy-stm32/CHANGELOG.md | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/i2c/v2.rs | 93 |
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 | ||
| 1737 | impl<'d> I2c<'d, Async, MultiMaster> { | 1744 | impl<'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. |
