aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-07-24 22:22:06 +0000
committerGitHub <[email protected]>2025-07-24 22:22:06 +0000
commit9381c35e9dc2d8ff1fc287b1605362e28ec16a25 (patch)
treece3dc65d90742fc5ca5e7577b798f7a38ee62bbf /embassy-stm32
parentbb68f5593112376fa779d7f4a2d8bc2a3f12f0dc (diff)
parent9863406346fdf5defcb8fe8de4bb5d122fa0b05f (diff)
Merge pull request #4454 from embassy-rs/stm32-i2c-slave-v2
fix: stm32 i2c slave blocking r/w
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/Cargo.toml1
-rw-r--r--embassy-stm32/src/i2c/v2.rs278
2 files changed, 221 insertions, 58 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 38254ee40..02e75733e 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -129,6 +129,7 @@ defmt = [
129 "embassy-net-driver/defmt", 129 "embassy-net-driver/defmt",
130 "embassy-time?/defmt", 130 "embassy-time?/defmt",
131 "embassy-usb-synopsys-otg/defmt", 131 "embassy-usb-synopsys-otg/defmt",
132 "stm32-metapac/defmt"
132] 133]
133 134
134exti = [] 135exti = []
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 35dc91c86..e24cce5c6 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -36,11 +36,46 @@ impl Address {
36 } 36 }
37} 37}
38 38
39enum ReceiveResult {
40 DataAvailable,
41 StopReceived,
42 NewStart,
43}
44
45fn debug_print_interrupts(isr: stm32_metapac::i2c::regs::Isr) {
46 if isr.tcr() {
47 trace!("interrupt: tcr");
48 }
49 if isr.tc() {
50 trace!("interrupt: tc");
51 }
52 if isr.addr() {
53 trace!("interrupt: addr");
54 }
55 if isr.stopf() {
56 trace!("interrupt: stopf");
57 }
58 if isr.nackf() {
59 trace!("interrupt: nackf");
60 }
61 if isr.berr() {
62 trace!("interrupt: berr");
63 }
64 if isr.arlo() {
65 trace!("interrupt: arlo");
66 }
67 if isr.ovr() {
68 trace!("interrupt: ovr");
69 }
70}
71
39pub(crate) unsafe fn on_interrupt<T: Instance>() { 72pub(crate) unsafe fn on_interrupt<T: Instance>() {
40 let regs = T::info().regs; 73 let regs = T::info().regs;
41 let isr = regs.isr().read(); 74 let isr = regs.isr().read();
42 75
43 if isr.tcr() || isr.tc() || isr.addr() || isr.stopf() || isr.nackf() || isr.berr() || isr.arlo() || isr.ovr() { 76 if isr.tcr() || isr.tc() || isr.addr() || isr.stopf() || isr.nackf() || isr.berr() || isr.arlo() || isr.ovr() {
77 debug_print_interrupts(isr);
78
44 T::state().waker.wake(); 79 T::state().waker.wake();
45 } 80 }
46 81
@@ -193,49 +228,132 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
193 228
194 fn flush_txdr(&self) { 229 fn flush_txdr(&self) {
195 if self.info.regs.isr().read().txis() { 230 if self.info.regs.isr().read().txis() {
196 self.info.regs.txdr().write(|w| w.set_txdata(0)); 231 trace!("Flush TXDATA with zeroes");
232 self.info.regs.txdr().modify(|w| w.set_txdata(0));
197 } 233 }
198 if !self.info.regs.isr().read().txe() { 234 if !self.info.regs.isr().read().txe() {
235 trace!("Flush TXDR");
199 self.info.regs.isr().modify(|w| w.set_txe(true)) 236 self.info.regs.isr().modify(|w| w.set_txe(true))
200 } 237 }
201 } 238 }
202 239
203 fn wait_txe(&self, timeout: Timeout) -> Result<(), Error> { 240 fn error_occurred(&self, isr: &i2c::regs::Isr, timeout: Timeout) -> Result<(), Error> {
241 if isr.nackf() {
242 trace!("NACK triggered.");
243 self.info.regs.icr().modify(|reg| reg.set_nackcf(true));
244 // NACK should be followed by STOP
245 if let Ok(()) = self.wait_stop(timeout) {
246 trace!("Got STOP after NACK, clearing flag.");
247 self.info.regs.icr().modify(|reg| reg.set_stopcf(true));
248 }
249 self.flush_txdr();
250 return Err(Error::Nack);
251 } else if isr.berr() {
252 trace!("BERR triggered.");
253 self.info.regs.icr().modify(|reg| reg.set_berrcf(true));
254 self.flush_txdr();
255 return Err(Error::Bus);
256 } else if isr.arlo() {
257 trace!("ARLO triggered.");
258 self.info.regs.icr().modify(|reg| reg.set_arlocf(true));
259 self.flush_txdr();
260 return Err(Error::Arbitration);
261 } else if isr.ovr() {
262 trace!("OVR triggered.");
263 self.info.regs.icr().modify(|reg| reg.set_ovrcf(true));
264 return Err(Error::Overrun);
265 }
266 return Ok(());
267 }
268
269 fn wait_txis(&self, timeout: Timeout) -> Result<(), Error> {
270 let mut first_loop = true;
271
204 loop { 272 loop {
205 let isr = self.info.regs.isr().read(); 273 let isr = self.info.regs.isr().read();
206 if isr.txe() { 274 self.error_occurred(&isr, timeout)?;
275 if isr.txis() {
276 trace!("TXIS");
207 return Ok(()); 277 return Ok(());
208 } else if isr.berr() {
209 self.info.regs.icr().write(|reg| reg.set_berrcf(true));
210 return Err(Error::Bus);
211 } else if isr.arlo() {
212 self.info.regs.icr().write(|reg| reg.set_arlocf(true));
213 return Err(Error::Arbitration);
214 } else if isr.nackf() {
215 self.info.regs.icr().write(|reg| reg.set_nackcf(true));
216 self.flush_txdr();
217 return Err(Error::Nack);
218 } 278 }
219 279
280 {
281 if first_loop {
282 trace!("Waiting for TXIS...");
283 first_loop = false;
284 }
285 }
220 timeout.check()?; 286 timeout.check()?;
221 } 287 }
222 } 288 }
223 289
224 fn wait_rxne(&self, timeout: Timeout) -> Result<(), Error> { 290 fn wait_stop_or_err(&self, timeout: Timeout) -> Result<(), Error> {
291 loop {
292 let isr = self.info.regs.isr().read();
293 self.error_occurred(&isr, timeout)?;
294 if isr.stopf() {
295 trace!("STOP triggered.");
296 self.info.regs.icr().modify(|reg| reg.set_stopcf(true));
297 return Ok(());
298 }
299 timeout.check()?;
300 }
301 }
302 fn wait_stop(&self, timeout: Timeout) -> Result<(), Error> {
225 loop { 303 loop {
226 let isr = self.info.regs.isr().read(); 304 let isr = self.info.regs.isr().read();
227 if isr.rxne() { 305 if isr.stopf() {
306 trace!("STOP triggered.");
307 self.info.regs.icr().modify(|reg| reg.set_stopcf(true));
228 return Ok(()); 308 return Ok(());
229 } else if isr.berr() { 309 }
230 self.info.regs.icr().write(|reg| reg.set_berrcf(true)); 310 timeout.check()?;
231 return Err(Error::Bus); 311 }
232 } else if isr.arlo() { 312 }
233 self.info.regs.icr().write(|reg| reg.set_arlocf(true)); 313
234 return Err(Error::Arbitration); 314 fn wait_af(&self, timeout: Timeout) -> Result<(), Error> {
235 } else if isr.nackf() { 315 loop {
236 self.info.regs.icr().write(|reg| reg.set_nackcf(true)); 316 let isr = self.info.regs.isr().read();
237 self.flush_txdr(); 317 if isr.nackf() {
238 return Err(Error::Nack); 318 trace!("AF triggered.");
319 self.info.regs.icr().modify(|reg| reg.set_nackcf(true));
320 return Ok(());
321 }
322 timeout.check()?;
323 }
324 }
325
326 fn wait_rxne(&self, timeout: Timeout) -> Result<ReceiveResult, Error> {
327 let mut first_loop = true;
328
329 loop {
330 let isr = self.info.regs.isr().read();
331 self.error_occurred(&isr, timeout)?;
332 if isr.stopf() {
333 trace!("STOP when waiting for RXNE.");
334 if self.info.regs.isr().read().rxne() {
335 trace!("Data received with STOP.");
336 return Ok(ReceiveResult::DataAvailable);
337 }
338 trace!("STOP triggered without data.");
339 return Ok(ReceiveResult::StopReceived);
340 } else if isr.rxne() {
341 trace!("RXNE.");
342 return Ok(ReceiveResult::DataAvailable);
343 } else if isr.addr() {
344 // Another addr event received, which means START was sent again
345 // which happens when accessing memory registers (common i2c interface design)
346 // e.g. master sends: START, write 1 byte (register index), START, read N bytes (until NACK)
347 // Possible to receive this flag at the same time as rxne, so check rxne first
348 trace!("START when waiting for RXNE. Ending receive loop.");
349 // Return without clearing ADDR so `listen` can catch it
350 return Ok(ReceiveResult::NewStart);
351 }
352 {
353 if first_loop {
354 trace!("Waiting for RXNE...");
355 first_loop = false;
356 }
239 } 357 }
240 358
241 timeout.check()?; 359 timeout.check()?;
@@ -245,20 +363,10 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
245 fn wait_tc(&self, timeout: Timeout) -> Result<(), Error> { 363 fn wait_tc(&self, timeout: Timeout) -> Result<(), Error> {
246 loop { 364 loop {
247 let isr = self.info.regs.isr().read(); 365 let isr = self.info.regs.isr().read();
366 self.error_occurred(&isr, timeout)?;
248 if isr.tc() { 367 if isr.tc() {
249 return Ok(()); 368 return Ok(());
250 } else if isr.berr() {
251 self.info.regs.icr().write(|reg| reg.set_berrcf(true));
252 return Err(Error::Bus);
253 } else if isr.arlo() {
254 self.info.regs.icr().write(|reg| reg.set_arlocf(true));
255 return Err(Error::Arbitration);
256 } else if isr.nackf() {
257 self.info.regs.icr().write(|reg| reg.set_nackcf(true));
258 self.flush_txdr();
259 return Err(Error::Nack);
260 } 369 }
261
262 timeout.check()?; 370 timeout.check()?;
263 } 371 }
264 } 372 }
@@ -344,7 +452,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
344 // Wait until we are allowed to send data 452 // Wait until we are allowed to send data
345 // (START has been ACKed or last byte when 453 // (START has been ACKed or last byte when
346 // through) 454 // through)
347 if let Err(err) = self.wait_txe(timeout) { 455 if let Err(err) = self.wait_txis(timeout) {
348 if send_stop { 456 if send_stop {
349 self.master_stop(); 457 self.master_stop();
350 } 458 }
@@ -459,7 +567,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
459 // Wait until we are allowed to send data 567 // Wait until we are allowed to send data
460 // (START has been ACKed or last byte when 568 // (START has been ACKed or last byte when
461 // through) 569 // through)
462 if let Err(err) = self.wait_txe(timeout) { 570 if let Err(err) = self.wait_txis(timeout) {
463 self.master_stop(); 571 self.master_stop();
464 return Err(err); 572 return Err(err);
465 } 573 }
@@ -884,10 +992,11 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
884 // clear the address flag, will stop the clock stretching. 992 // clear the address flag, will stop the clock stretching.
885 // this should only be done after the dma transfer has been set up. 993 // this should only be done after the dma transfer has been set up.
886 info.regs.icr().modify(|reg| reg.set_addrcf(true)); 994 info.regs.icr().modify(|reg| reg.set_addrcf(true));
995 trace!("ADDRCF cleared (ADDR interrupt enabled, clock stretching ended)");
887 } 996 }
888 997
889 // A blocking read operation 998 // A blocking read operation
890 fn slave_read_internal(&self, read: &mut [u8], timeout: Timeout) -> Result<(), Error> { 999 fn slave_read_internal(&self, read: &mut [u8], timeout: Timeout) -> Result<usize, Error> {
891 let completed_chunks = read.len() / 255; 1000 let completed_chunks = read.len() / 255;
892 let total_chunks = if completed_chunks * 255 == read.len() { 1001 let total_chunks = if completed_chunks * 255 == read.len() {
893 completed_chunks 1002 completed_chunks
@@ -895,20 +1004,46 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
895 completed_chunks + 1 1004 completed_chunks + 1
896 }; 1005 };
897 let last_chunk_idx = total_chunks.saturating_sub(1); 1006 let last_chunk_idx = total_chunks.saturating_sub(1);
1007 let total_len = read.len();
1008 let mut remaining_len = total_len;
1009
898 for (number, chunk) in read.chunks_mut(255).enumerate() { 1010 for (number, chunk) in read.chunks_mut(255).enumerate() {
899 if number != 0 { 1011 trace!(
1012 "--- Slave RX transmission start - chunk: {}, expected (max) size: {}",
1013 number,
1014 chunk.len()
1015 );
1016 if number == 0 {
1017 Self::slave_start(self.info, chunk.len(), number != last_chunk_idx);
1018 } else {
900 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; 1019 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?;
901 } 1020 }
902 1021
1022 let mut index = 0;
1023
903 for byte in chunk { 1024 for byte in chunk {
904 // Wait until we have received something 1025 // Wait until we have received something
905 self.wait_rxne(timeout)?; 1026 match self.wait_rxne(timeout) {
906 1027 Ok(ReceiveResult::StopReceived) | Ok(ReceiveResult::NewStart) => {
907 *byte = self.info.regs.rxdr().read().rxdata(); 1028 trace!("--- Slave RX transmission end (early)");
1029 return Ok(total_len - remaining_len); // Return N bytes read
1030 }
1031 Ok(ReceiveResult::DataAvailable) => {
1032 *byte = self.info.regs.rxdr().read().rxdata();
1033 remaining_len = remaining_len.saturating_sub(1);
1034 {
1035 trace!("Slave RX data {}: {:#04x}", index, byte);
1036 index = index + 1;
1037 }
1038 }
1039 Err(e) => return Err(e),
1040 };
908 } 1041 }
909 } 1042 }
1043 self.wait_stop_or_err(timeout)?;
910 1044
911 Ok(()) 1045 trace!("--- Slave RX transmission end");
1046 Ok(total_len - remaining_len) // Return N bytes read
912 } 1047 }
913 1048
914 // A blocking write operation 1049 // A blocking write operation
@@ -922,19 +1057,36 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
922 let last_chunk_idx = total_chunks.saturating_sub(1); 1057 let last_chunk_idx = total_chunks.saturating_sub(1);
923 1058
924 for (number, chunk) in write.chunks(255).enumerate() { 1059 for (number, chunk) in write.chunks(255).enumerate() {
925 if number != 0 { 1060 trace!(
1061 "--- Slave TX transmission start - chunk: {}, size: {}",
1062 number,
1063 chunk.len()
1064 );
1065 if number == 0 {
1066 Self::slave_start(self.info, chunk.len(), number != last_chunk_idx);
1067 } else {
926 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; 1068 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?;
927 } 1069 }
928 1070
1071 let mut index = 0;
1072
929 for byte in chunk { 1073 for byte in chunk {
930 // Wait until we are allowed to send data 1074 // Wait until we are allowed to send data
931 // (START has been ACKed or last byte when 1075 // (START has been ACKed or last byte when through)
932 // through) 1076 self.wait_txis(timeout)?;
933 self.wait_txe(timeout)?;
934 1077
1078 {
1079 trace!("Slave TX data {}: {:#04x}", index, byte);
1080 index = index + 1;
1081 }
935 self.info.regs.txdr().write(|w| w.set_txdata(*byte)); 1082 self.info.regs.txdr().write(|w| w.set_txdata(*byte));
936 } 1083 }
937 } 1084 }
1085 self.wait_af(timeout)?;
1086 self.flush_txdr();
1087 self.wait_stop_or_err(timeout)?;
1088
1089 trace!("--- Slave TX transmission end");
938 Ok(()) 1090 Ok(())
939 } 1091 }
940 1092
@@ -945,6 +1097,7 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
945 let state = self.state; 1097 let state = self.state;
946 self.info.regs.cr1().modify(|reg| { 1098 self.info.regs.cr1().modify(|reg| {
947 reg.set_addrie(true); 1099 reg.set_addrie(true);
1100 trace!("Enable ADDRIE");
948 }); 1101 });
949 1102
950 poll_fn(|cx| { 1103 poll_fn(|cx| {
@@ -953,17 +1106,24 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
953 if !isr.addr() { 1106 if !isr.addr() {
954 Poll::Pending 1107 Poll::Pending
955 } else { 1108 } else {
1109 trace!("ADDR triggered (address match)");
956 // we do not clear the address flag here as it will be cleared by the dma read/write 1110 // we do not clear the address flag here as it will be cleared by the dma read/write
957 // 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 1111 // 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
958 match isr.dir() { 1112 match isr.dir() {
959 i2c::vals::Dir::WRITE => Poll::Ready(Ok(SlaveCommand { 1113 i2c::vals::Dir::WRITE => {
960 kind: SlaveCommandKind::Write, 1114 trace!("DIR: write");
961 address: self.determine_matched_address()?, 1115 Poll::Ready(Ok(SlaveCommand {
962 })), 1116 kind: SlaveCommandKind::Write,
963 i2c::vals::Dir::READ => Poll::Ready(Ok(SlaveCommand { 1117 address: self.determine_matched_address()?,
964 kind: SlaveCommandKind::Read, 1118 }))
965 address: self.determine_matched_address()?, 1119 }
966 })), 1120 i2c::vals::Dir::READ => {
1121 trace!("DIR: read");
1122 Poll::Ready(Ok(SlaveCommand {
1123 kind: SlaveCommandKind::Read,
1124 address: self.determine_matched_address()?,
1125 }))
1126 }
967 } 1127 }
968 } 1128 }
969 }) 1129 })
@@ -971,7 +1131,9 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
971 } 1131 }
972 1132
973 /// Respond to a write command. 1133 /// Respond to a write command.
974 pub fn blocking_respond_to_write(&self, read: &mut [u8]) -> Result<(), Error> { 1134 ///
1135 /// Returns total number of bytes received.
1136 pub fn blocking_respond_to_write(&self, read: &mut [u8]) -> Result<usize, Error> {
975 let timeout = self.timeout(); 1137 let timeout = self.timeout();
976 self.slave_read_internal(read, timeout) 1138 self.slave_read_internal(read, timeout)
977 } 1139 }
@@ -1025,7 +1187,7 @@ impl<'d> I2c<'d, Async, MultiMaster> {
1025 w.set_rxdmaen(false); 1187 w.set_rxdmaen(false);
1026 w.set_stopie(false); 1188 w.set_stopie(false);
1027 w.set_tcie(false); 1189 w.set_tcie(false);
1028 }) 1190 });
1029 }); 1191 });
1030 1192
1031 let total_received = poll_fn(|cx| { 1193 let total_received = poll_fn(|cx| {