diff options
| author | Knaifhogg <[email protected]> | 2025-06-18 08:26:12 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2025-07-24 23:56:49 +0200 |
| commit | 9863406346fdf5defcb8fe8de4bb5d122fa0b05f (patch) | |
| tree | abe3089de5e0ab524ab73db4916b3303b706916e /embassy-stm32 | |
| parent | 915513753aea689f73d1300acc069ac985be3a0b (diff) | |
fix: stm32 i2c slave blocking r/w
This fixes an issue where the slave interface would time out when the
master goes from a short write to a read (e.g. when accessing memory
registers) with a START signal between. The previous implementation
would expect the full buffer length to be written before starting to
listen to new commands.
This also adds debug trace printing which helped during implemention and
testing.
Places error checking into a function inspired from a C implementation
of HAL.
Diffstat (limited to 'embassy-stm32')
| -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| { |
