diff options
| author | HybridChild <[email protected]> | 2025-11-13 21:18:12 +0100 |
|---|---|---|
| committer | HybridChild <[email protected]> | 2025-11-13 21:18:12 +0100 |
| commit | de16754a2d340eca49885238e265f50bfc3ec2e5 (patch) | |
| tree | b1706d3613e3eda623c499a9dbf4a828bc23f3ea | |
| parent | 2553ced205d49d2890e000069f5a170b75d267a9 (diff) | |
stm32/i2c: Fix async write_vectored and restore DMA implementation
| -rw-r--r-- | embassy-stm32/src/i2c/v2.rs | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 7bcfa00b0..c35f3694c 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs | |||
| @@ -389,7 +389,9 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 389 | loop { | 389 | loop { |
| 390 | let isr = self.info.regs.isr().read(); | 390 | let isr = self.info.regs.isr().read(); |
| 391 | self.error_occurred(&isr, timeout)?; | 391 | self.error_occurred(&isr, timeout)?; |
| 392 | if isr.tc() { | 392 | // Wait for either TC or TCR - both indicate transfer completion |
| 393 | // TCR occurs when RELOAD=1, TC occurs when RELOAD=0 | ||
| 394 | if isr.tc() || isr.tcr() { | ||
| 393 | return Ok(()); | 395 | return Ok(()); |
| 394 | } | 396 | } |
| 395 | timeout.check()?; | 397 | timeout.check()?; |
| @@ -918,12 +920,12 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 918 | address, | 920 | address, |
| 919 | total_len.min(255), | 921 | total_len.min(255), |
| 920 | Stop::Software, | 922 | Stop::Software, |
| 921 | total_len > 255, | 923 | (total_len > 255) || !last_slice, |
| 922 | restart, | 924 | restart, |
| 923 | timeout, | 925 | timeout, |
| 924 | )?; | 926 | )?; |
| 925 | } else { | 927 | } else { |
| 926 | Self::reload(self.info, total_len.min(255), total_len > 255, Stop::Software, timeout)?; | 928 | Self::reload(self.info, total_len.min(255), (total_len > 255) || !last_slice, Stop::Software, timeout)?; |
| 927 | self.info.regs.cr1().modify(|w| w.set_tcie(true)); | 929 | self.info.regs.cr1().modify(|w| w.set_tcie(true)); |
| 928 | } | 930 | } |
| 929 | } else if !(isr.tcr() || isr.tc()) { | 931 | } else if !(isr.tcr() || isr.tc()) { |
| @@ -935,7 +937,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 935 | if let Err(e) = Self::reload( | 937 | if let Err(e) = Self::reload( |
| 936 | self.info, | 938 | self.info, |
| 937 | remaining_len.min(255), | 939 | remaining_len.min(255), |
| 938 | remaining_len > 255, | 940 | (remaining_len > 255) || !last_slice, |
| 939 | Stop::Software, | 941 | Stop::Software, |
| 940 | timeout, | 942 | timeout, |
| 941 | ) { | 943 | ) { |
| @@ -1085,10 +1087,35 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 1085 | pub async fn write_vectored(&mut self, address: Address, write: &[&[u8]]) -> Result<(), Error> { | 1087 | pub async fn write_vectored(&mut self, address: Address, write: &[&[u8]]) -> Result<(), Error> { |
| 1086 | #[cfg(all(feature = "low-power", stm32wlex))] | 1088 | #[cfg(all(feature = "low-power", stm32wlex))] |
| 1087 | let _device_busy = crate::low_power::DeviceBusy::new_stop1(); | 1089 | let _device_busy = crate::low_power::DeviceBusy::new_stop1(); |
| 1090 | let timeout = self.timeout(); | ||
| 1088 | 1091 | ||
| 1089 | // For now, use blocking implementation for write_vectored | 1092 | if write.is_empty() { |
| 1090 | // This avoids complexity of handling multiple non-contiguous buffers with DMA | 1093 | return Err(Error::ZeroLengthTransfer); |
| 1091 | self.blocking_write_vectored((address.addr() & 0xFF) as u8, write) | 1094 | } |
| 1095 | |||
| 1096 | let mut iter = write.iter(); | ||
| 1097 | let mut first = true; | ||
| 1098 | let mut current = iter.next(); | ||
| 1099 | |||
| 1100 | while let Some(c) = current { | ||
| 1101 | let next = iter.next(); | ||
| 1102 | let is_last = next.is_none(); | ||
| 1103 | |||
| 1104 | let fut = self.write_dma_internal( | ||
| 1105 | address, | ||
| 1106 | c, | ||
| 1107 | first, // first_slice | ||
| 1108 | is_last, // last_slice | ||
| 1109 | is_last, // send_stop (only on last buffer) | ||
| 1110 | false, // restart (false for all - they're one continuous write) | ||
| 1111 | timeout, | ||
| 1112 | ); | ||
| 1113 | timeout.with(fut).await?; | ||
| 1114 | |||
| 1115 | first = false; | ||
| 1116 | current = next; | ||
| 1117 | } | ||
| 1118 | Ok(()) | ||
| 1092 | } | 1119 | } |
| 1093 | 1120 | ||
| 1094 | /// Read. | 1121 | /// Read. |
