diff options
| author | Dario Nieuwenhuis <[email protected]> | 2025-07-24 22:22:06 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-07-24 22:22:06 +0000 |
| commit | 9381c35e9dc2d8ff1fc287b1605362e28ec16a25 (patch) | |
| tree | ce3dc65d90742fc5ca5e7577b798f7a38ee62bbf | |
| parent | bb68f5593112376fa779d7f4a2d8bc2a3f12f0dc (diff) | |
| parent | 9863406346fdf5defcb8fe8de4bb5d122fa0b05f (diff) | |
Merge pull request #4454 from embassy-rs/stm32-i2c-slave-v2
fix: stm32 i2c slave blocking r/w
| -rw-r--r-- | embassy-stm32/Cargo.toml | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/i2c/v2.rs | 278 |
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 | ||
| 134 | exti = [] | 135 | exti = [] |
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 | ||
| 39 | enum ReceiveResult { | ||
| 40 | DataAvailable, | ||
| 41 | StopReceived, | ||
| 42 | NewStart, | ||
| 43 | } | ||
| 44 | |||
| 45 | fn 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 | |||
| 39 | pub(crate) unsafe fn on_interrupt<T: Instance>() { | 72 | pub(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| { |
