diff options
| author | HybridChild <[email protected]> | 2025-07-27 10:35:52 +0200 |
|---|---|---|
| committer | HybridChild <[email protected]> | 2025-08-23 08:48:46 +0200 |
| commit | 399ec8d90f1c4f62fd20d21dabbb9ce64c6986eb (patch) | |
| tree | 25e9ef00eda482e229f956d658426a579aa5726f | |
| parent | bf01151bbb793c36431820bd814db775bf10a870 (diff) | |
stm32/i2c: Rename FrameOptions enum to OperationFraming
| -rw-r--r-- | embassy-stm32/src/i2c/mod.rs | 185 | ||||
| -rw-r--r-- | embassy-stm32/src/i2c/v1.rs | 28 |
2 files changed, 124 insertions, 89 deletions
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 5fb49f943..f51682900 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs | |||
| @@ -435,88 +435,117 @@ impl<'d, IM: MasterMode> embedded_hal_async::i2c::I2c for I2c<'d, Async, IM> { | |||
| 435 | } | 435 | } |
| 436 | } | 436 | } |
| 437 | 437 | ||
| 438 | /// Frame type in I2C transaction. | 438 | /// Operation framing configuration for I2C transactions. |
| 439 | /// | 439 | /// |
| 440 | /// This tells each method what kind of framing to use, to generate a (repeated) start condition (ST | 440 | /// This determines the I2C frame boundaries for each operation within a transaction, |
| 441 | /// or SR), and/or a stop condition (SP). For read operations, this also controls whether to send an | 441 | /// controlling the generation of start conditions (ST or SR), stop conditions (SP), |
| 442 | /// ACK or NACK after the last byte received. | 442 | /// and ACK/NACK behavior for read operations. |
| 443 | /// | 443 | /// |
| 444 | /// For write operations, the following options are identical because they differ only in the (N)ACK | 444 | /// For write operations, some framing configurations are functionally identical |
| 445 | /// treatment relevant for read operations: | 445 | /// because they differ only in ACK/NACK treatment which is relevant only for reads: |
| 446 | /// | 446 | /// |
| 447 | /// - `FirstFrame` and `FirstAndNextFrame` | 447 | /// - `First` and `FirstAndNext` behave identically for writes |
| 448 | /// - `NextFrame` and `LastFrameNoStop` | 448 | /// - `Next` and `LastNoStop` behave identically for writes |
| 449 | /// | ||
| 450 | /// Abbreviations used below: | ||
| 451 | /// | 449 | /// |
| 450 | /// **Framing Legend:** | ||
| 452 | /// - `ST` = start condition | 451 | /// - `ST` = start condition |
| 453 | /// - `SR` = repeated start condition | 452 | /// - `SR` = repeated start condition |
| 454 | /// - `SP` = stop condition | 453 | /// - `SP` = stop condition |
| 455 | /// - `ACK`/`NACK` = last byte in read operation | 454 | /// - `ACK/NACK` = acknowledgment behavior for the final byte of read operations |
| 456 | #[derive(Copy, Clone)] | 455 | #[derive(Copy, Clone)] |
| 457 | #[allow(dead_code)] | 456 | #[allow(dead_code)] |
| 458 | enum FrameOptions { | 457 | enum OperationFraming { |
| 459 | /// `[ST/SR]+[NACK]+[SP]` First frame (of this type) in transaction and also last frame overall. | 458 | /// `[ST/SR]+[NACK]+[SP]` - First operation of its type in the transaction and also the final operation overall. |
| 460 | FirstAndLastFrame, | 459 | FirstAndLast, |
| 461 | /// `[ST/SR]+[NACK]` First frame of this type in transaction, last frame in a read operation but | 460 | /// `[ST/SR]+[NACK]` - First operation of its type in the transaction, final operation in a read sequence, but not the final operation overall. |
| 462 | /// not the last frame overall. | 461 | First, |
| 463 | FirstFrame, | 462 | /// `[ST/SR]+[ACK]` - First operation of its type in the transaction, but neither the final operation overall nor the final operation in a read sequence. |
| 464 | /// `[ST/SR]+[ACK]` First frame of this type in transaction, neither last frame overall nor last | 463 | FirstAndNext, |
| 465 | /// frame in a read operation. | 464 | /// `[ACK]` - Continuation operation in a read sequence (neither first nor last). |
| 466 | FirstAndNextFrame, | 465 | Next, |
| 467 | /// `[ACK]` Middle frame in a read operation (neither first nor last). | 466 | /// `[NACK]+[SP]` - Final operation overall in the transaction, but not the first operation of its type. |
| 468 | NextFrame, | 467 | Last, |
| 469 | /// `[NACK]+[SP]` Last frame overall in this transaction but not the first frame. | 468 | /// `[NACK]` - Final operation in a read sequence, but not the final operation overall in the transaction. |
| 470 | LastFrame, | 469 | LastNoStop, |
| 471 | /// `[NACK]` Last frame in a read operation but not last frame overall in this transaction. | ||
| 472 | LastFrameNoStop, | ||
| 473 | } | 470 | } |
| 474 | 471 | ||
| 475 | #[allow(dead_code)] | 472 | #[allow(dead_code)] |
| 476 | impl FrameOptions { | 473 | impl OperationFraming { |
| 477 | /// Sends start or repeated start condition before transfer. | 474 | /// Returns true if a start or repeated start condition should be generated before this operation. |
| 478 | fn send_start(self) -> bool { | 475 | fn send_start(self) -> bool { |
| 479 | match self { | 476 | match self { |
| 480 | Self::FirstAndLastFrame | Self::FirstFrame | Self::FirstAndNextFrame => true, | 477 | Self::FirstAndLast | Self::First | Self::FirstAndNext => true, |
| 481 | Self::NextFrame | Self::LastFrame | Self::LastFrameNoStop => false, | 478 | Self::Next | Self::Last | Self::LastNoStop => false, |
| 482 | } | 479 | } |
| 483 | } | 480 | } |
| 484 | 481 | ||
| 485 | /// Sends stop condition after transfer. | 482 | /// Returns true if a stop condition should be generated after this operation. |
| 486 | fn send_stop(self) -> bool { | 483 | fn send_stop(self) -> bool { |
| 487 | match self { | 484 | match self { |
| 488 | Self::FirstAndLastFrame | Self::LastFrame => true, | 485 | Self::FirstAndLast | Self::Last => true, |
| 489 | Self::FirstFrame | Self::FirstAndNextFrame | Self::NextFrame | Self::LastFrameNoStop => false, | 486 | Self::First | Self::FirstAndNext | Self::Next | Self::LastNoStop => false, |
| 490 | } | 487 | } |
| 491 | } | 488 | } |
| 492 | 489 | ||
| 493 | /// Sends NACK after last byte received, indicating end of read operation. | 490 | /// Returns true if NACK should be sent after the last byte received in a read operation. |
| 491 | /// | ||
| 492 | /// This signals the end of a read sequence and releases the bus for the master's | ||
| 493 | /// next transmission (or stop condition). | ||
| 494 | fn send_nack(self) -> bool { | 494 | fn send_nack(self) -> bool { |
| 495 | match self { | 495 | match self { |
| 496 | Self::FirstAndLastFrame | Self::FirstFrame | Self::LastFrame | Self::LastFrameNoStop => true, | 496 | Self::FirstAndLast | Self::First | Self::Last | Self::LastNoStop => true, |
| 497 | Self::FirstAndNextFrame | Self::NextFrame => false, | 497 | Self::FirstAndNext | Self::Next => false, |
| 498 | } | 498 | } |
| 499 | } | 499 | } |
| 500 | } | 500 | } |
| 501 | 501 | ||
| 502 | /// Iterates over operations in transaction. | 502 | /// Analyzes I2C transaction operations and assigns appropriate framing to each. |
| 503 | /// | ||
| 504 | /// This function processes a sequence of I2C operations and determines the correct | ||
| 505 | /// framing configuration for each operation to ensure proper I2C protocol compliance. | ||
| 506 | /// It handles the complex logic of: | ||
| 507 | /// | ||
| 508 | /// - Generating start conditions for the first operation of each type (read/write) | ||
| 509 | /// - Generating stop conditions for the final operation in the entire transaction | ||
| 510 | /// - Managing ACK/NACK behavior for read operations, including merging consecutive reads | ||
| 511 | /// - Ensuring proper bus handoff between different operation types | ||
| 512 | /// | ||
| 513 | /// **Transaction Contract Compliance:** | ||
| 514 | /// The framing assignments ensure compliance with the embedded-hal I2C transaction contract, | ||
| 515 | /// where consecutive operations of the same type are logically merged while maintaining | ||
| 516 | /// proper protocol boundaries. | ||
| 503 | /// | 517 | /// |
| 504 | /// Returns necessary frame options for each operation to uphold the [transaction contract] and have | 518 | /// **Error Handling:** |
| 505 | /// the right start/stop/(N)ACK conditions on the wire. | 519 | /// Returns an error if any read operation has an empty buffer, as this would create |
| 520 | /// an invalid I2C transaction that could halt mid-execution. | ||
| 506 | /// | 521 | /// |
| 507 | /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction | 522 | /// # Arguments |
| 523 | /// * `operations` - Mutable slice of I2C operations from embedded-hal | ||
| 524 | /// | ||
| 525 | /// # Returns | ||
| 526 | /// An iterator over (operation, framing) pairs, or an error if the transaction is invalid | ||
| 527 | /// | ||
| 528 | /// # Example | ||
| 529 | /// ```rust | ||
| 530 | /// for (op, framing) in assign_operation_framing(operations)? { | ||
| 531 | /// match op { | ||
| 532 | /// Operation::Read(buffer) => self.read_with_framing(addr, buffer, framing).await?, | ||
| 533 | /// Operation::Write(data) => self.write_with_framing(addr, data, framing).await?, | ||
| 534 | /// } | ||
| 535 | /// } | ||
| 536 | /// ``` | ||
| 508 | #[allow(dead_code)] | 537 | #[allow(dead_code)] |
| 509 | fn operation_frames<'a, 'b: 'a>( | 538 | fn assign_operation_framing<'a, 'b: 'a>( |
| 510 | operations: &'a mut [embedded_hal_1::i2c::Operation<'b>], | 539 | operations: &'a mut [embedded_hal_1::i2c::Operation<'b>], |
| 511 | ) -> Result<impl IntoIterator<Item = (&'a mut embedded_hal_1::i2c::Operation<'b>, FrameOptions)>, Error> { | 540 | ) -> Result<impl IntoIterator<Item = (&'a mut embedded_hal_1::i2c::Operation<'b>, OperationFraming)>, Error> { |
| 512 | use embedded_hal_1::i2c::Operation::{Read, Write}; | 541 | use embedded_hal_1::i2c::Operation::{Read, Write}; |
| 513 | 542 | ||
| 514 | // Check empty read buffer before starting transaction. Otherwise, we would risk halting with an | 543 | // Validate that no read operations have empty buffers before starting the transaction. |
| 515 | // error in the middle of the transaction. | 544 | // Empty read operations would risk halting with an error mid-transaction. |
| 516 | // | 545 | // |
| 517 | // In principle, we could allow empty read frames within consecutive read operations, as long as | 546 | // Note: We could theoretically allow empty read operations within consecutive read |
| 518 | // at least one byte remains in the final (merged) read operation, but that makes the logic more | 547 | // sequences as long as the final merged read has at least one byte, but this would |
| 519 | // complicated and error-prone. | 548 | // complicate the logic significantly and create error-prone edge cases. |
| 520 | if operations.iter().any(|op| match op { | 549 | if operations.iter().any(|op| match op { |
| 521 | Read(read) => read.is_empty(), | 550 | Read(read) => read.is_empty(), |
| 522 | Write(_) => false, | 551 | Write(_) => false, |
| @@ -525,46 +554,52 @@ fn operation_frames<'a, 'b: 'a>( | |||
| 525 | } | 554 | } |
| 526 | 555 | ||
| 527 | let mut operations = operations.iter_mut().peekable(); | 556 | let mut operations = operations.iter_mut().peekable(); |
| 528 | 557 | let mut next_first_operation = true; | |
| 529 | let mut next_first_frame = true; | ||
| 530 | 558 | ||
| 531 | Ok(iter::from_fn(move || { | 559 | Ok(iter::from_fn(move || { |
| 532 | let op = operations.next()?; | 560 | let current_op = operations.next()?; |
| 533 | 561 | ||
| 534 | // Is `op` first frame of its type? | 562 | // Determine if this is the first operation of its type (read or write) |
| 535 | let first_frame = next_first_frame; | 563 | let is_first_of_type = next_first_operation; |
| 536 | let next_op = operations.peek(); | 564 | let next_op = operations.peek(); |
| 537 | 565 | ||
| 538 | // Get appropriate frame options as combination of the following properties: | 566 | // Compute the appropriate framing based on three key properties: |
| 539 | // | 567 | // |
| 540 | // - For each first operation of its type, generate a (repeated) start condition. | 568 | // 1. **Start Condition**: Generate (repeated) start for first operation of each type |
| 541 | // - For the last operation overall in the entire transaction, generate a stop condition. | 569 | // 2. **Stop Condition**: Generate stop for the final operation in the entire transaction |
| 542 | // - For read operations, check the next operation: if it is also a read operation, we merge | 570 | // 3. **ACK/NACK for Reads**: For read operations, send ACK if more reads follow in the |
| 543 | // these and send ACK for all bytes in the current operation; send NACK only for the final | 571 | // sequence, or NACK for the final read in a sequence (before write or transaction end) |
| 544 | // read operation's last byte (before write or end of entire transaction) to indicate last | ||
| 545 | // byte read and release the bus for transmission of the bus master's next byte (or stop). | ||
| 546 | // | 572 | // |
| 547 | // We check the third property unconditionally, i.e. even for write opeartions. This is okay | 573 | // The third property is checked for all operations since the resulting framing |
| 548 | // because the resulting frame options are identical for write operations. | 574 | // configurations are identical for write operations regardless of ACK/NACK treatment. |
| 549 | let frame = match (first_frame, next_op) { | 575 | let framing = match (is_first_of_type, next_op) { |
| 550 | (true, None) => FrameOptions::FirstAndLastFrame, | 576 | // First operation of type, and it's also the final operation overall |
| 551 | (true, Some(Read(_))) => FrameOptions::FirstAndNextFrame, | 577 | (true, None) => OperationFraming::FirstAndLast, |
| 552 | (true, Some(Write(_))) => FrameOptions::FirstFrame, | 578 | // First operation of type, next operation is also a read (continue read sequence) |
| 553 | // | 579 | (true, Some(Read(_))) => OperationFraming::FirstAndNext, |
| 554 | (false, None) => FrameOptions::LastFrame, | 580 | // First operation of type, next operation is write (end current sequence) |
| 555 | (false, Some(Read(_))) => FrameOptions::NextFrame, | 581 | (true, Some(Write(_))) => OperationFraming::First, |
| 556 | (false, Some(Write(_))) => FrameOptions::LastFrameNoStop, | 582 | |
| 583 | // Continuation operation, and it's the final operation overall | ||
| 584 | (false, None) => OperationFraming::Last, | ||
| 585 | // Continuation operation, next operation is also a read (continue read sequence) | ||
| 586 | (false, Some(Read(_))) => OperationFraming::Next, | ||
| 587 | // Continuation operation, next operation is write (end current sequence, no stop) | ||
| 588 | (false, Some(Write(_))) => OperationFraming::LastNoStop, | ||
| 557 | }; | 589 | }; |
| 558 | 590 | ||
| 559 | // Pre-calculate if `next_op` is the first operation of its type. We do this here and not at | 591 | // Pre-calculate whether the next operation will be the first of its type. |
| 560 | // the beginning of the loop because we hand out `op` as iterator value and cannot access it | 592 | // This is done here because we consume `current_op` as the iterator value |
| 561 | // anymore in the next iteration. | 593 | // and cannot access it in the next iteration. |
| 562 | next_first_frame = match (&op, next_op) { | 594 | next_first_operation = match (¤t_op, next_op) { |
| 595 | // No next operation | ||
| 563 | (_, None) => false, | 596 | (_, None) => false, |
| 597 | // Operation type changes: next will be first of its type | ||
| 564 | (Read(_), Some(Write(_))) | (Write(_), Some(Read(_))) => true, | 598 | (Read(_), Some(Write(_))) | (Write(_), Some(Read(_))) => true, |
| 599 | // Operation type continues: next will not be first of its type | ||
| 565 | (Read(_), Some(Read(_))) | (Write(_), Some(Write(_))) => false, | 600 | (Read(_), Some(Read(_))) | (Write(_), Some(Write(_))) => false, |
| 566 | }; | 601 | }; |
| 567 | 602 | ||
| 568 | Some((op, frame)) | 603 | Some((current_op, framing)) |
| 569 | })) | 604 | })) |
| 570 | } | 605 | } |
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index a1ad9caef..7d2b731d5 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs | |||
| @@ -151,7 +151,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 151 | Ok(sr1) | 151 | Ok(sr1) |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | fn write_bytes(&mut self, addr: u8, bytes: &[u8], timeout: Timeout, frame: FrameOptions) -> Result<(), Error> { | 154 | fn write_bytes(&mut self, addr: u8, bytes: &[u8], timeout: Timeout, frame: OperationFraming) -> Result<(), Error> { |
| 155 | if frame.send_start() { | 155 | if frame.send_start() { |
| 156 | // Send a START condition | 156 | // Send a START condition |
| 157 | 157 | ||
| @@ -239,7 +239,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 239 | addr: u8, | 239 | addr: u8, |
| 240 | buffer: &mut [u8], | 240 | buffer: &mut [u8], |
| 241 | timeout: Timeout, | 241 | timeout: Timeout, |
| 242 | frame: FrameOptions, | 242 | frame: OperationFraming, |
| 243 | ) -> Result<(), Error> { | 243 | ) -> Result<(), Error> { |
| 244 | let Some((last, buffer)) = buffer.split_last_mut() else { | 244 | let Some((last, buffer)) = buffer.split_last_mut() else { |
| 245 | return Err(Error::Overrun); | 245 | return Err(Error::Overrun); |
| @@ -299,12 +299,12 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 299 | 299 | ||
| 300 | /// Blocking read. | 300 | /// Blocking read. |
| 301 | pub fn blocking_read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Error> { | 301 | pub fn blocking_read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Error> { |
| 302 | self.blocking_read_timeout(addr, read, self.timeout(), FrameOptions::FirstAndLastFrame) | 302 | self.blocking_read_timeout(addr, read, self.timeout(), OperationFraming::FirstAndLast) |
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | /// Blocking write. | 305 | /// Blocking write. |
| 306 | pub fn blocking_write(&mut self, addr: u8, write: &[u8]) -> Result<(), Error> { | 306 | pub fn blocking_write(&mut self, addr: u8, write: &[u8]) -> Result<(), Error> { |
| 307 | self.write_bytes(addr, write, self.timeout(), FrameOptions::FirstAndLastFrame)?; | 307 | self.write_bytes(addr, write, self.timeout(), OperationFraming::FirstAndLast)?; |
| 308 | 308 | ||
| 309 | // Fallthrough is success | 309 | // Fallthrough is success |
| 310 | Ok(()) | 310 | Ok(()) |
| @@ -320,8 +320,8 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 320 | 320 | ||
| 321 | let timeout = self.timeout(); | 321 | let timeout = self.timeout(); |
| 322 | 322 | ||
| 323 | self.write_bytes(addr, write, timeout, FrameOptions::FirstFrame)?; | 323 | self.write_bytes(addr, write, timeout, OperationFraming::First)?; |
| 324 | self.blocking_read_timeout(addr, read, timeout, FrameOptions::FirstAndLastFrame)?; | 324 | self.blocking_read_timeout(addr, read, timeout, OperationFraming::FirstAndLast)?; |
| 325 | 325 | ||
| 326 | Ok(()) | 326 | Ok(()) |
| 327 | } | 327 | } |
| @@ -334,7 +334,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 334 | pub fn blocking_transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { | 334 | pub fn blocking_transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { |
| 335 | let timeout = self.timeout(); | 335 | let timeout = self.timeout(); |
| 336 | 336 | ||
| 337 | for (op, frame) in operation_frames(operations)? { | 337 | for (op, frame) in assign_operation_framing(operations)? { |
| 338 | match op { | 338 | match op { |
| 339 | Operation::Read(read) => self.blocking_read_timeout(addr, read, timeout, frame)?, | 339 | Operation::Read(read) => self.blocking_read_timeout(addr, read, timeout, frame)?, |
| 340 | Operation::Write(write) => self.write_bytes(addr, write, timeout, frame)?, | 340 | Operation::Write(write) => self.write_bytes(addr, write, timeout, frame)?, |
| @@ -356,7 +356,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 356 | } | 356 | } |
| 357 | 357 | ||
| 358 | impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | 358 | impl<'d, IM: MasterMode> I2c<'d, Async, IM> { |
| 359 | async fn write_frame(&mut self, address: u8, write: &[u8], frame: FrameOptions) -> Result<(), Error> { | 359 | async fn write_frame(&mut self, address: u8, write: &[u8], frame: OperationFraming) -> Result<(), Error> { |
| 360 | self.info.regs.cr2().modify(|w| { | 360 | self.info.regs.cr2().modify(|w| { |
| 361 | // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for | 361 | // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for |
| 362 | // reception. | 362 | // reception. |
| @@ -502,7 +502,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 502 | 502 | ||
| 503 | /// Write. | 503 | /// Write. |
| 504 | pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { | 504 | pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { |
| 505 | self.write_frame(address, write, FrameOptions::FirstAndLastFrame) | 505 | self.write_frame(address, write, OperationFraming::FirstAndLast) |
| 506 | .await?; | 506 | .await?; |
| 507 | 507 | ||
| 508 | Ok(()) | 508 | Ok(()) |
| @@ -510,13 +510,13 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 510 | 510 | ||
| 511 | /// Read. | 511 | /// Read. |
| 512 | pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { | 512 | pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { |
| 513 | self.read_frame(address, buffer, FrameOptions::FirstAndLastFrame) | 513 | self.read_frame(address, buffer, OperationFraming::FirstAndLast) |
| 514 | .await?; | 514 | .await?; |
| 515 | 515 | ||
| 516 | Ok(()) | 516 | Ok(()) |
| 517 | } | 517 | } |
| 518 | 518 | ||
| 519 | async fn read_frame(&mut self, address: u8, buffer: &mut [u8], frame: FrameOptions) -> Result<(), Error> { | 519 | async fn read_frame(&mut self, address: u8, buffer: &mut [u8], frame: OperationFraming) -> Result<(), Error> { |
| 520 | if buffer.is_empty() { | 520 | if buffer.is_empty() { |
| 521 | return Err(Error::Overrun); | 521 | return Err(Error::Overrun); |
| 522 | } | 522 | } |
| @@ -680,8 +680,8 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 680 | return Err(Error::Overrun); | 680 | return Err(Error::Overrun); |
| 681 | } | 681 | } |
| 682 | 682 | ||
| 683 | self.write_frame(address, write, FrameOptions::FirstFrame).await?; | 683 | self.write_frame(address, write, OperationFraming::First).await?; |
| 684 | self.read_frame(address, read, FrameOptions::FirstAndLastFrame).await | 684 | self.read_frame(address, read, OperationFraming::FirstAndLast).await |
| 685 | } | 685 | } |
| 686 | 686 | ||
| 687 | /// Transaction with operations. | 687 | /// Transaction with operations. |
| @@ -690,7 +690,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 690 | /// | 690 | /// |
| 691 | /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction | 691 | /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction |
| 692 | pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { | 692 | pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { |
| 693 | for (op, frame) in operation_frames(operations)? { | 693 | for (op, frame) in assign_operation_framing(operations)? { |
| 694 | match op { | 694 | match op { |
| 695 | Operation::Read(read) => self.read_frame(addr, read, frame).await?, | 695 | Operation::Read(read) => self.read_frame(addr, read, frame).await?, |
| 696 | Operation::Write(write) => self.write_frame(addr, write, frame).await?, | 696 | Operation::Write(write) => self.write_frame(addr, write, frame).await?, |
