diff options
| author | Thales Fragoso <[email protected]> | 2021-07-09 02:57:34 -0300 |
|---|---|---|
| committer | Thales Fragoso <[email protected]> | 2021-07-14 23:39:50 -0300 |
| commit | aa8c7f990f3d00ddf8305dae7d278399d9573ecb (patch) | |
| tree | 5cb27dc2a39096ea30c4fb6b6233f9782bcd5614 | |
| parent | f2e78e9c3413994fa264345ceacc44463e5bb0ec (diff) | |
i2c-v2: Implement write_vectored
| -rw-r--r-- | embassy-stm32/src/i2c/mod.rs | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/i2c/v2.rs | 60 |
2 files changed, 61 insertions, 0 deletions
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index fc154a953..daf7e31e8 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs | |||
| @@ -14,6 +14,7 @@ pub enum Error { | |||
| 14 | Timeout, | 14 | Timeout, |
| 15 | Crc, | 15 | Crc, |
| 16 | Overrun, | 16 | Overrun, |
| 17 | ZeroLengthTransfer, | ||
| 17 | } | 18 | } |
| 18 | 19 | ||
| 19 | pub(crate) mod sealed { | 20 | pub(crate) mod sealed { |
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 787bf679a..a5eb5612d 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs | |||
| @@ -325,6 +325,66 @@ impl<'d, T: Instance> I2c<'d, T> { | |||
| 325 | } | 325 | } |
| 326 | Ok(()) | 326 | Ok(()) |
| 327 | } | 327 | } |
| 328 | |||
| 329 | pub fn write_vectored(&mut self, address: u8, bytes: &[&[u8]]) -> Result<(), Error> { | ||
| 330 | if bytes.is_empty() { | ||
| 331 | return Err(Error::ZeroLengthTransfer); | ||
| 332 | } | ||
| 333 | let first_length = bytes[0].len(); | ||
| 334 | let last_slice_index = bytes.len() - 1; | ||
| 335 | |||
| 336 | self.master_write( | ||
| 337 | address, | ||
| 338 | first_length.min(255), | ||
| 339 | Stop::Software, | ||
| 340 | (first_length > 255) || (last_slice_index != 0), | ||
| 341 | ); | ||
| 342 | |||
| 343 | for (idx, slice) in bytes.iter().enumerate() { | ||
| 344 | let slice_len = slice.len(); | ||
| 345 | let completed_chunks = slice_len / 255; | ||
| 346 | let total_chunks = if completed_chunks * 255 == slice_len { | ||
| 347 | completed_chunks | ||
| 348 | } else { | ||
| 349 | completed_chunks + 1 | ||
| 350 | }; | ||
| 351 | let last_chunk_idx = total_chunks.saturating_sub(1); | ||
| 352 | |||
| 353 | if idx != 0 { | ||
| 354 | self.master_continue( | ||
| 355 | slice_len.min(255), | ||
| 356 | (idx != last_slice_index) || (slice_len > 255), | ||
| 357 | ); | ||
| 358 | } | ||
| 359 | |||
| 360 | for (number, chunk) in slice.chunks(255).enumerate() { | ||
| 361 | if number != 0 { | ||
| 362 | self.master_continue( | ||
| 363 | chunk.len(), | ||
| 364 | (number != last_chunk_idx) || (idx != last_slice_index), | ||
| 365 | ); | ||
| 366 | } | ||
| 367 | |||
| 368 | for byte in chunk { | ||
| 369 | // Wait until we are allowed to send data | ||
| 370 | // (START has been ACKed or last byte when | ||
| 371 | // through) | ||
| 372 | self.wait_txe()?; | ||
| 373 | |||
| 374 | // Put byte on the wire | ||
| 375 | //self.i2c.txdr.write(|w| w.txdata().bits(*byte)); | ||
| 376 | unsafe { | ||
| 377 | T::regs().txdr().write(|w| w.set_txdata(*byte)); | ||
| 378 | } | ||
| 379 | } | ||
| 380 | } | ||
| 381 | } | ||
| 382 | // Wait until the write finishes | ||
| 383 | self.wait_tc()?; | ||
| 384 | self.master_stop(); | ||
| 385 | |||
| 386 | Ok(()) | ||
| 387 | } | ||
| 328 | } | 388 | } |
| 329 | 389 | ||
| 330 | impl<'d, T: Instance> Read for I2c<'d, T> { | 390 | impl<'d, T: Instance> Read for I2c<'d, T> { |
