aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/i2c/v2.rs41
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.