diff options
| -rw-r--r-- | embassy-stm32/src/i2c/mod.rs | 33 | ||||
| -rw-r--r-- | embassy-stm32/src/i2c/v2.rs | 11 |
2 files changed, 28 insertions, 16 deletions
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 3303b9f4b..82e28b3ff 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs | |||
| @@ -162,19 +162,32 @@ pub enum SendStatus { | |||
| 162 | LeftoverBytes(usize), | 162 | LeftoverBytes(usize), |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | struct I2CDropGuard<'d> { | ||
| 166 | info: &'static Info, | ||
| 167 | scl: Option<PeripheralRef<'d, AnyPin>>, | ||
| 168 | sda: Option<PeripheralRef<'d, AnyPin>>, | ||
| 169 | } | ||
| 170 | impl<'d> Drop for I2CDropGuard<'d> { | ||
| 171 | fn drop(&mut self) { | ||
| 172 | self.scl.as_ref().map(|x| x.set_as_disconnected()); | ||
| 173 | self.sda.as_ref().map(|x| x.set_as_disconnected()); | ||
| 174 | |||
| 175 | self.info.rcc.disable(); | ||
| 176 | } | ||
| 177 | } | ||
| 178 | |||
| 165 | /// I2C driver. | 179 | /// I2C driver. |
| 166 | pub struct I2c<'d, M: Mode, IM: MasterMode> { | 180 | pub struct I2c<'d, M: Mode, IM: MasterMode> { |
| 167 | info: &'static Info, | 181 | info: &'static Info, |
| 168 | state: &'static State, | 182 | state: &'static State, |
| 169 | kernel_clock: Hertz, | 183 | kernel_clock: Hertz, |
| 170 | scl: Option<PeripheralRef<'d, AnyPin>>, | ||
| 171 | sda: Option<PeripheralRef<'d, AnyPin>>, | ||
| 172 | tx_dma: Option<ChannelAndRequest<'d>>, | 184 | tx_dma: Option<ChannelAndRequest<'d>>, |
| 173 | rx_dma: Option<ChannelAndRequest<'d>>, | 185 | rx_dma: Option<ChannelAndRequest<'d>>, |
| 174 | #[cfg(feature = "time")] | 186 | #[cfg(feature = "time")] |
| 175 | timeout: Duration, | 187 | timeout: Duration, |
| 176 | _phantom: PhantomData<M>, | 188 | _phantom: PhantomData<M>, |
| 177 | _phantom2: PhantomData<IM>, | 189 | _phantom2: PhantomData<IM>, |
| 190 | drop_guard: I2CDropGuard<'d>, | ||
| 178 | } | 191 | } |
| 179 | 192 | ||
| 180 | impl<'d> I2c<'d, Async, Master> { | 193 | impl<'d> I2c<'d, Async, Master> { |
| @@ -242,14 +255,17 @@ impl<'d, M: Mode> I2c<'d, M, Master> { | |||
| 242 | info: T::info(), | 255 | info: T::info(), |
| 243 | state: T::state(), | 256 | state: T::state(), |
| 244 | kernel_clock: T::frequency(), | 257 | kernel_clock: T::frequency(), |
| 245 | scl, | ||
| 246 | sda, | ||
| 247 | tx_dma, | 258 | tx_dma, |
| 248 | rx_dma, | 259 | rx_dma, |
| 249 | #[cfg(feature = "time")] | 260 | #[cfg(feature = "time")] |
| 250 | timeout: config.timeout, | 261 | timeout: config.timeout, |
| 251 | _phantom: PhantomData, | 262 | _phantom: PhantomData, |
| 252 | _phantom2: PhantomData, | 263 | _phantom2: PhantomData, |
| 264 | drop_guard: I2CDropGuard { | ||
| 265 | info: T::info(), | ||
| 266 | scl, | ||
| 267 | sda, | ||
| 268 | }, | ||
| 253 | }; | 269 | }; |
| 254 | this.enable_and_init(freq, config); | 270 | this.enable_and_init(freq, config); |
| 255 | 271 | ||
| @@ -271,15 +287,6 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 271 | } | 287 | } |
| 272 | } | 288 | } |
| 273 | 289 | ||
| 274 | impl<'d, M: Mode, IM: MasterMode> Drop for I2c<'d, M, IM> { | ||
| 275 | fn drop(&mut self) { | ||
| 276 | self.scl.as_ref().map(|x| x.set_as_disconnected()); | ||
| 277 | self.sda.as_ref().map(|x| x.set_as_disconnected()); | ||
| 278 | |||
| 279 | self.info.rcc.disable() | ||
| 280 | } | ||
| 281 | } | ||
| 282 | |||
| 283 | #[derive(Copy, Clone)] | 290 | #[derive(Copy, Clone)] |
| 284 | struct Timeout { | 291 | struct Timeout { |
| 285 | #[cfg(feature = "time")] | 292 | #[cfg(feature = "time")] |
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 531358efa..a90bdd551 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs | |||
| @@ -47,6 +47,8 @@ pub(crate) unsafe fn on_interrupt<T: Instance>() { | |||
| 47 | critical_section::with(|_| { | 47 | critical_section::with(|_| { |
| 48 | regs.cr1().modify(|w| { | 48 | regs.cr1().modify(|w| { |
| 49 | w.set_addrie(false); | 49 | w.set_addrie(false); |
| 50 | w.set_stopie(false); | ||
| 51 | w.set_tcie(false); | ||
| 50 | // The flag can only be cleared by writting to nbytes, we won't do that here, so disable | 52 | // The flag can only be cleared by writting to nbytes, we won't do that here, so disable |
| 51 | // the interrupt | 53 | // the interrupt |
| 52 | w.set_tcie(false); | 54 | w.set_tcie(false); |
| @@ -725,14 +727,13 @@ impl<'d, M: Mode> I2c<'d, M, Master> { | |||
| 725 | info: self.info, | 727 | info: self.info, |
| 726 | state: self.state, | 728 | state: self.state, |
| 727 | kernel_clock: self.kernel_clock, | 729 | kernel_clock: self.kernel_clock, |
| 728 | scl: self.scl.take(), | ||
| 729 | sda: self.sda.take(), | ||
| 730 | tx_dma: self.tx_dma.take(), | 730 | tx_dma: self.tx_dma.take(), |
| 731 | rx_dma: self.rx_dma.take(), | 731 | rx_dma: self.rx_dma.take(), |
| 732 | #[cfg(feature = "time")] | 732 | #[cfg(feature = "time")] |
| 733 | timeout: self.timeout, | 733 | timeout: self.timeout, |
| 734 | _phantom: PhantomData, | 734 | _phantom: PhantomData, |
| 735 | _phantom2: PhantomData, | 735 | _phantom2: PhantomData, |
| 736 | drop_guard: self.drop_guard, | ||
| 736 | }; | 737 | }; |
| 737 | slave.init_slave(slave_addr_config); | 738 | slave.init_slave(slave_addr_config); |
| 738 | slave | 739 | slave |
| @@ -930,6 +931,8 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> { | |||
| 930 | 931 | ||
| 931 | impl<'d> I2c<'d, Async, MultiMaster> { | 932 | impl<'d> I2c<'d, Async, MultiMaster> { |
| 932 | /// Respond to a receive command. | 933 | /// Respond to a receive command. |
| 934 | /// | ||
| 935 | /// Returns the total number of bytes received. | ||
| 933 | pub async fn respond_to_receive(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { | 936 | pub async fn respond_to_receive(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { |
| 934 | let timeout = self.timeout(); | 937 | let timeout = self.timeout(); |
| 935 | timeout.with(self.read_dma_internal_slave(buffer, timeout)).await | 938 | timeout.with(self.read_dma_internal_slave(buffer, timeout)).await |
| @@ -942,6 +945,8 @@ impl<'d> I2c<'d, Async, MultiMaster> { | |||
| 942 | } | 945 | } |
| 943 | 946 | ||
| 944 | // for data reception in slave mode | 947 | // for data reception in slave mode |
| 948 | // | ||
| 949 | // returns the total number of bytes received | ||
| 945 | async fn read_dma_internal_slave(&mut self, buffer: &mut [u8], timeout: Timeout) -> Result<usize, Error> { | 950 | async fn read_dma_internal_slave(&mut self, buffer: &mut [u8], timeout: Timeout) -> Result<usize, Error> { |
| 946 | let total_len = buffer.len(); | 951 | let total_len = buffer.len(); |
| 947 | let mut remaining_len = total_len; | 952 | let mut remaining_len = total_len; |
| @@ -988,7 +993,7 @@ impl<'d> I2c<'d, Async, MultiMaster> { | |||
| 988 | Poll::Pending | 993 | Poll::Pending |
| 989 | } else if isr.stopf() { | 994 | } else if isr.stopf() { |
| 990 | regs.icr().write(|reg| reg.set_stopcf(true)); | 995 | regs.icr().write(|reg| reg.set_stopcf(true)); |
| 991 | let poll = Poll::Ready(Ok(remaining_len)); | 996 | let poll = Poll::Ready(Ok(total_len - remaining_len)); |
| 992 | poll | 997 | poll |
| 993 | } else { | 998 | } else { |
| 994 | Poll::Pending | 999 | Poll::Pending |
