diff options
| author | xoviat <[email protected]> | 2025-10-30 15:49:07 -0500 |
|---|---|---|
| committer | xoviat <[email protected]> | 2025-10-30 15:49:07 -0500 |
| commit | ae726274ddb95c048c386817ef105012dcc06dad (patch) | |
| tree | b30e036481e6b687b871d253b0da6eb87c1e9897 | |
| parent | 65438769024b657f98da20646beb10e7e5a1b960 (diff) | |
reduce diff with misc. reversions
| -rw-r--r-- | embassy-stm32/src/i2c/mod.rs | 97 | ||||
| -rw-r--r-- | embassy-stm32/src/i2c/v1.rs | 144 |
2 files changed, 131 insertions, 110 deletions
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 785ebd866..ee60c3f44 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs | |||
| @@ -436,55 +436,58 @@ impl<'d, IM: MasterMode> embedded_hal_async::i2c::I2c for I2c<'d, Async, IM> { | |||
| 436 | } | 436 | } |
| 437 | } | 437 | } |
| 438 | 438 | ||
| 439 | /// Operation framing configuration for I2C transactions. | 439 | /// Frame type in I2C transaction. |
| 440 | /// | 440 | /// |
| 441 | /// This determines the I2C frame boundaries for each operation within a transaction, | 441 | /// This tells each method what kind of frame to use, to generate a (repeated) start condition (ST |
| 442 | /// controlling the generation of start conditions (ST or SR), stop conditions (SP), | 442 | /// or SR), and/or a stop condition (SP). For read operations, this also controls whether to send an |
| 443 | /// and ACK/NACK behavior for read operations. | 443 | /// ACK or NACK after the last byte received. |
| 444 | /// | 444 | /// |
| 445 | /// For write operations, some framing configurations are functionally identical | 445 | /// For write operations, the following options are identical because they differ only in the (N)ACK |
| 446 | /// because they differ only in ACK/NACK treatment which is relevant only for reads: | 446 | /// treatment relevant for read operations: |
| 447 | /// | 447 | /// |
| 448 | /// - `First` and `FirstAndNext` behave identically for writes | 448 | /// - `FirstFrame` and `FirstAndNextFrame` behave identically for writes |
| 449 | /// - `Next` and `LastNoStop` behave identically for writes | 449 | /// - `NextFrame` and `LastFrameNoStop` behave identically for writes |
| 450 | /// | ||
| 451 | /// Abbreviations used below: | ||
| 450 | /// | 452 | /// |
| 451 | /// **Framing Legend:** | ||
| 452 | /// - `ST` = start condition | 453 | /// - `ST` = start condition |
| 453 | /// - `SR` = repeated start condition | 454 | /// - `SR` = repeated start condition |
| 454 | /// - `SP` = stop condition | 455 | /// - `SP` = stop condition |
| 455 | /// - `ACK/NACK` = acknowledgment behavior for the final byte of read operations | 456 | /// - `ACK`/`NACK` = last byte in read operation |
| 456 | #[derive(Copy, Clone)] | 457 | #[derive(Copy, Clone)] |
| 457 | #[allow(dead_code)] | 458 | #[allow(dead_code)] |
| 458 | enum OperationFraming { | 459 | enum FrameOptions { |
| 459 | /// `[ST/SR]+[NACK]+[SP]` - First operation of its type in the transaction and also the final operation overall. | 460 | /// `[ST/SR]+[NACK]+[SP]` First frame (of this type) in transaction and also last frame overall. |
| 460 | FirstAndLast, | 461 | FirstAndLastFrame, |
| 461 | /// `[ST/SR]+[NACK]` - First operation of its type in the transaction, final operation in a read sequence, but not the final operation overall. | 462 | /// `[ST/SR]+[NACK]` First frame of this type in transaction, last frame in a read operation but |
| 462 | First, | 463 | /// not the last frame overall. |
| 463 | /// `[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 | FirstFrame, |
| 464 | FirstAndNext, | 465 | /// `[ST/SR]+[ACK]` First frame of this type in transaction, neither last frame overall nor last |
| 465 | /// `[ACK]` - Continuation operation in a read sequence (neither first nor last). | 466 | /// frame in a read operation. |
| 466 | Next, | 467 | FirstAndNextFrame, |
| 467 | /// `[NACK]+[SP]` - Final operation overall in the transaction, but not the first operation of its type. | 468 | /// `[ACK]` Middle frame in a read operation (neither first nor last). |
| 468 | Last, | 469 | NextFrame, |
| 469 | /// `[NACK]` - Final operation in a read sequence, but not the final operation overall in the transaction. | 470 | /// `[NACK]+[SP]` Last frame overall in this transaction but not the first frame. |
| 470 | LastNoStop, | 471 | LastFrame, |
| 472 | /// `[NACK]` Last frame in a read operation but not last frame overall in this transaction. | ||
| 473 | LastFrameNoStop, | ||
| 471 | } | 474 | } |
| 472 | 475 | ||
| 473 | #[allow(dead_code)] | 476 | #[allow(dead_code)] |
| 474 | impl OperationFraming { | 477 | impl FrameOptions { |
| 475 | /// Returns true if a start or repeated start condition should be generated before this operation. | 478 | /// Returns true if a start or repeated start condition should be generated before this operation. |
| 476 | fn send_start(self) -> bool { | 479 | fn send_start(self) -> bool { |
| 477 | match self { | 480 | match self { |
| 478 | Self::FirstAndLast | Self::First | Self::FirstAndNext => true, | 481 | Self::FirstAndLastFrame | Self::FirstFrame | Self::FirstAndNextFrame => true, |
| 479 | Self::Next | Self::Last | Self::LastNoStop => false, | 482 | Self::NextFrame | Self::LastFrame | Self::LastFrameNoStop => false, |
| 480 | } | 483 | } |
| 481 | } | 484 | } |
| 482 | 485 | ||
| 483 | /// Returns true if a stop condition should be generated after this operation. | 486 | /// Returns true if a stop condition should be generated after this operation. |
| 484 | fn send_stop(self) -> bool { | 487 | fn send_stop(self) -> bool { |
| 485 | match self { | 488 | match self { |
| 486 | Self::FirstAndLast | Self::Last => true, | 489 | Self::FirstAndLastFrame | Self::LastFrame => true, |
| 487 | Self::First | Self::FirstAndNext | Self::Next | Self::LastNoStop => false, | 490 | Self::FirstFrame | Self::FirstAndNextFrame | Self::NextFrame | Self::LastFrameNoStop => false, |
| 488 | } | 491 | } |
| 489 | } | 492 | } |
| 490 | 493 | ||
| @@ -494,16 +497,16 @@ impl OperationFraming { | |||
| 494 | /// next transmission (or stop condition). | 497 | /// next transmission (or stop condition). |
| 495 | fn send_nack(self) -> bool { | 498 | fn send_nack(self) -> bool { |
| 496 | match self { | 499 | match self { |
| 497 | Self::FirstAndLast | Self::First | Self::Last | Self::LastNoStop => true, | 500 | Self::FirstAndLastFrame | Self::FirstFrame | Self::LastFrame | Self::LastFrameNoStop => true, |
| 498 | Self::FirstAndNext | Self::Next => false, | 501 | Self::FirstAndNextFrame | Self::NextFrame => false, |
| 499 | } | 502 | } |
| 500 | } | 503 | } |
| 501 | } | 504 | } |
| 502 | 505 | ||
| 503 | /// Analyzes I2C transaction operations and assigns appropriate framing to each. | 506 | /// Analyzes I2C transaction operations and assigns appropriate frame to each. |
| 504 | /// | 507 | /// |
| 505 | /// This function processes a sequence of I2C operations and determines the correct | 508 | /// This function processes a sequence of I2C operations and determines the correct |
| 506 | /// framing configuration for each operation to ensure proper I2C protocol compliance. | 509 | /// frame configuration for each operation to ensure proper I2C protocol compliance. |
| 507 | /// It handles the complex logic of: | 510 | /// It handles the complex logic of: |
| 508 | /// | 511 | /// |
| 509 | /// - Generating start conditions for the first operation of each type (read/write) | 512 | /// - Generating start conditions for the first operation of each type (read/write) |
| @@ -512,7 +515,7 @@ impl OperationFraming { | |||
| 512 | /// - Ensuring proper bus handoff between different operation types | 515 | /// - Ensuring proper bus handoff between different operation types |
| 513 | /// | 516 | /// |
| 514 | /// **Transaction Contract Compliance:** | 517 | /// **Transaction Contract Compliance:** |
| 515 | /// The framing assignments ensure compliance with the embedded-hal I2C transaction contract, | 518 | /// The frame assignments ensure compliance with the embedded-hal I2C transaction contract, |
| 516 | /// where consecutive operations of the same type are logically merged while maintaining | 519 | /// where consecutive operations of the same type are logically merged while maintaining |
| 517 | /// proper protocol boundaries. | 520 | /// proper protocol boundaries. |
| 518 | /// | 521 | /// |
| @@ -524,12 +527,12 @@ impl OperationFraming { | |||
| 524 | /// * `operations` - Mutable slice of I2C operations from embedded-hal | 527 | /// * `operations` - Mutable slice of I2C operations from embedded-hal |
| 525 | /// | 528 | /// |
| 526 | /// # Returns | 529 | /// # Returns |
| 527 | /// An iterator over (operation, framing) pairs, or an error if the transaction is invalid | 530 | /// An iterator over (operation, frame) pairs, or an error if the transaction is invalid |
| 528 | /// | 531 | /// |
| 529 | #[allow(dead_code)] | 532 | #[allow(dead_code)] |
| 530 | fn assign_operation_framing<'a, 'b: 'a>( | 533 | fn operation_frames<'a, 'b: 'a>( |
| 531 | operations: &'a mut [embedded_hal_1::i2c::Operation<'b>], | 534 | operations: &'a mut [embedded_hal_1::i2c::Operation<'b>], |
| 532 | ) -> Result<impl IntoIterator<Item = (&'a mut embedded_hal_1::i2c::Operation<'b>, OperationFraming)>, Error> { | 535 | ) -> Result<impl IntoIterator<Item = (&'a mut embedded_hal_1::i2c::Operation<'b>, FrameOptions)>, Error> { |
| 533 | use embedded_hal_1::i2c::Operation::{Read, Write}; | 536 | use embedded_hal_1::i2c::Operation::{Read, Write}; |
| 534 | 537 | ||
| 535 | // Validate that no read operations have empty buffers before starting the transaction. | 538 | // Validate that no read operations have empty buffers before starting the transaction. |
| @@ -555,29 +558,29 @@ fn assign_operation_framing<'a, 'b: 'a>( | |||
| 555 | let is_first_of_type = next_first_operation; | 558 | let is_first_of_type = next_first_operation; |
| 556 | let next_op = operations.peek(); | 559 | let next_op = operations.peek(); |
| 557 | 560 | ||
| 558 | // Compute the appropriate framing based on three key properties: | 561 | // Compute the appropriate frame based on three key properties: |
| 559 | // | 562 | // |
| 560 | // 1. **Start Condition**: Generate (repeated) start for first operation of each type | 563 | // 1. **Start Condition**: Generate (repeated) start for first operation of each type |
| 561 | // 2. **Stop Condition**: Generate stop for the final operation in the entire transaction | 564 | // 2. **Stop Condition**: Generate stop for the final operation in the entire transaction |
| 562 | // 3. **ACK/NACK for Reads**: For read operations, send ACK if more reads follow in the | 565 | // 3. **ACK/NACK for Reads**: For read operations, send ACK if more reads follow in the |
| 563 | // sequence, or NACK for the final read in a sequence (before write or transaction end) | 566 | // sequence, or NACK for the final read in a sequence (before write or transaction end) |
| 564 | // | 567 | // |
| 565 | // The third property is checked for all operations since the resulting framing | 568 | // The third property is checked for all operations since the resulting frame |
| 566 | // configurations are identical for write operations regardless of ACK/NACK treatment. | 569 | // configurations are identical for write operations regardless of ACK/NACK treatment. |
| 567 | let framing = match (is_first_of_type, next_op) { | 570 | let frame = match (is_first_of_type, next_op) { |
| 568 | // First operation of type, and it's also the final operation overall | 571 | // First operation of type, and it's also the final operation overall |
| 569 | (true, None) => OperationFraming::FirstAndLast, | 572 | (true, None) => FrameOptions::FirstAndLastFrame, |
| 570 | // First operation of type, next operation is also a read (continue read sequence) | 573 | // First operation of type, next operation is also a read (continue read sequence) |
| 571 | (true, Some(Read(_))) => OperationFraming::FirstAndNext, | 574 | (true, Some(Read(_))) => FrameOptions::FirstAndNextFrame, |
| 572 | // First operation of type, next operation is write (end current sequence) | 575 | // First operation of type, next operation is write (end current sequence) |
| 573 | (true, Some(Write(_))) => OperationFraming::First, | 576 | (true, Some(Write(_))) => FrameOptions::FirstFrame, |
| 574 | 577 | ||
| 575 | // Continuation operation, and it's the final operation overall | 578 | // Continuation operation, and it's the final operation overall |
| 576 | (false, None) => OperationFraming::Last, | 579 | (false, None) => FrameOptions::LastFrame, |
| 577 | // Continuation operation, next operation is also a read (continue read sequence) | 580 | // Continuation operation, next operation is also a read (continue read sequence) |
| 578 | (false, Some(Read(_))) => OperationFraming::Next, | 581 | (false, Some(Read(_))) => FrameOptions::NextFrame, |
| 579 | // Continuation operation, next operation is write (end current sequence, no stop) | 582 | // Continuation operation, next operation is write (end current sequence, no stop) |
| 580 | (false, Some(Write(_))) => OperationFraming::LastNoStop, | 583 | (false, Some(Write(_))) => FrameOptions::LastFrameNoStop, |
| 581 | }; | 584 | }; |
| 582 | 585 | ||
| 583 | // Pre-calculate whether the next operation will be the first of its type. | 586 | // Pre-calculate whether the next operation will be the first of its type. |
| @@ -592,6 +595,6 @@ fn assign_operation_framing<'a, 'b: 'a>( | |||
| 592 | (Read(_), Some(Read(_))) | (Write(_), Some(Write(_))) => false, | 595 | (Read(_), Some(Read(_))) | (Write(_), Some(Write(_))) => false, |
| 593 | }; | 596 | }; |
| 594 | 597 | ||
| 595 | Some((current_op, framing)) | 598 | Some((current_op, frame)) |
| 596 | })) | 599 | })) |
| 597 | } | 600 | } |
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index 42d39655f..128a58db7 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs | |||
| @@ -14,7 +14,7 @@ use embedded_hal_1::i2c::Operation; | |||
| 14 | use mode::Master; | 14 | use mode::Master; |
| 15 | 15 | ||
| 16 | use super::*; | 16 | use super::*; |
| 17 | use crate::mode::Mode; | 17 | use crate::mode::Mode as PeriMode; |
| 18 | use crate::pac::i2c; | 18 | use crate::pac::i2c; |
| 19 | 19 | ||
| 20 | // /!\ /!\ | 20 | // /!\ /!\ |
| @@ -43,7 +43,7 @@ pub unsafe fn on_interrupt<T: Instance>() { | |||
| 43 | }); | 43 | }); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | 46 | impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> { |
| 47 | pub(crate) fn init(&mut self, config: Config) { | 47 | pub(crate) fn init(&mut self, config: Config) { |
| 48 | self.info.regs.cr1().modify(|reg| { | 48 | self.info.regs.cr1().modify(|reg| { |
| 49 | reg.set_pe(false); | 49 | reg.set_pe(false); |
| @@ -82,8 +82,8 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 82 | reg.set_freq(timings.freq); | 82 | reg.set_freq(timings.freq); |
| 83 | }); | 83 | }); |
| 84 | self.info.regs.ccr().modify(|reg| { | 84 | self.info.regs.ccr().modify(|reg| { |
| 85 | reg.set_f_s(timings.f_s); | 85 | reg.set_f_s(timings.mode.f_s()); |
| 86 | reg.set_duty(timings.duty); | 86 | reg.set_duty(timings.duty.duty()); |
| 87 | reg.set_ccr(timings.ccr); | 87 | reg.set_ccr(timings.ccr); |
| 88 | }); | 88 | }); |
| 89 | self.info.regs.trise().modify(|reg| { | 89 | self.info.regs.trise().modify(|reg| { |
| @@ -158,9 +158,9 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 158 | address: u8, | 158 | address: u8, |
| 159 | write_buffer: &[u8], | 159 | write_buffer: &[u8], |
| 160 | timeout: Timeout, | 160 | timeout: Timeout, |
| 161 | framing: OperationFraming, | 161 | frame: FrameOptions, |
| 162 | ) -> Result<(), Error> { | 162 | ) -> Result<(), Error> { |
| 163 | if framing.send_start() { | 163 | if frame.send_start() { |
| 164 | // Send a START condition | 164 | // Send a START condition |
| 165 | 165 | ||
| 166 | self.info.regs.cr1().modify(|reg| { | 166 | self.info.regs.cr1().modify(|reg| { |
| @@ -196,7 +196,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 196 | self.send_byte(*c, timeout)?; | 196 | self.send_byte(*c, timeout)?; |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | if framing.send_stop() { | 199 | if frame.send_stop() { |
| 200 | // Send a STOP condition | 200 | // Send a STOP condition |
| 201 | self.info.regs.cr1().modify(|reg| reg.set_stop(true)); | 201 | self.info.regs.cr1().modify(|reg| reg.set_stop(true)); |
| 202 | } | 202 | } |
| @@ -247,13 +247,13 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 247 | address: u8, | 247 | address: u8, |
| 248 | read_buffer: &mut [u8], | 248 | read_buffer: &mut [u8], |
| 249 | timeout: Timeout, | 249 | timeout: Timeout, |
| 250 | framing: OperationFraming, | 250 | frame: FrameOptions, |
| 251 | ) -> Result<(), Error> { | 251 | ) -> Result<(), Error> { |
| 252 | let Some((last_byte, read_buffer)) = read_buffer.split_last_mut() else { | 252 | let Some((last_byte, read_buffer)) = read_buffer.split_last_mut() else { |
| 253 | return Err(Error::Overrun); | 253 | return Err(Error::Overrun); |
| 254 | }; | 254 | }; |
| 255 | 255 | ||
| 256 | if framing.send_start() { | 256 | if frame.send_start() { |
| 257 | // Send a START condition and set ACK bit | 257 | // Send a START condition and set ACK bit |
| 258 | self.info.regs.cr1().modify(|reg| { | 258 | self.info.regs.cr1().modify(|reg| { |
| 259 | reg.set_start(true); | 259 | reg.set_start(true); |
| @@ -290,10 +290,10 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 290 | 290 | ||
| 291 | // Prepare to send NACK then STOP after next byte | 291 | // Prepare to send NACK then STOP after next byte |
| 292 | self.info.regs.cr1().modify(|reg| { | 292 | self.info.regs.cr1().modify(|reg| { |
| 293 | if framing.send_nack() { | 293 | if frame.send_nack() { |
| 294 | reg.set_ack(false); | 294 | reg.set_ack(false); |
| 295 | } | 295 | } |
| 296 | if framing.send_stop() { | 296 | if frame.send_stop() { |
| 297 | reg.set_stop(true); | 297 | reg.set_stop(true); |
| 298 | } | 298 | } |
| 299 | }); | 299 | }); |
| @@ -307,12 +307,12 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 307 | 307 | ||
| 308 | /// Blocking read. | 308 | /// Blocking read. |
| 309 | pub fn blocking_read(&mut self, address: u8, read_buffer: &mut [u8]) -> Result<(), Error> { | 309 | pub fn blocking_read(&mut self, address: u8, read_buffer: &mut [u8]) -> Result<(), Error> { |
| 310 | self.blocking_read_timeout(address, read_buffer, self.timeout(), OperationFraming::FirstAndLast) | 310 | self.blocking_read_timeout(address, read_buffer, self.timeout(), FrameOptions::FirstAndLastFrame) |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | /// Blocking write. | 313 | /// Blocking write. |
| 314 | pub fn blocking_write(&mut self, address: u8, write_buffer: &[u8]) -> Result<(), Error> { | 314 | pub fn blocking_write(&mut self, address: u8, write_buffer: &[u8]) -> Result<(), Error> { |
| 315 | self.write_bytes(address, write_buffer, self.timeout(), OperationFraming::FirstAndLast)?; | 315 | self.write_bytes(address, write_buffer, self.timeout(), FrameOptions::FirstAndLastFrame)?; |
| 316 | 316 | ||
| 317 | // Fallthrough is success | 317 | // Fallthrough is success |
| 318 | Ok(()) | 318 | Ok(()) |
| @@ -333,8 +333,8 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 333 | 333 | ||
| 334 | let timeout = self.timeout(); | 334 | let timeout = self.timeout(); |
| 335 | 335 | ||
| 336 | self.write_bytes(address, write_buffer, timeout, OperationFraming::First)?; | 336 | self.write_bytes(address, write_buffer, timeout, FrameOptions::FirstFrame)?; |
| 337 | self.blocking_read_timeout(address, read_buffer, timeout, OperationFraming::FirstAndLast)?; | 337 | self.blocking_read_timeout(address, read_buffer, timeout, FrameOptions::FirstAndLastFrame)?; |
| 338 | 338 | ||
| 339 | Ok(()) | 339 | Ok(()) |
| 340 | } | 340 | } |
| @@ -347,10 +347,10 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 347 | pub fn blocking_transaction(&mut self, address: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { | 347 | pub fn blocking_transaction(&mut self, address: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { |
| 348 | let timeout = self.timeout(); | 348 | let timeout = self.timeout(); |
| 349 | 349 | ||
| 350 | for (op, framing) in assign_operation_framing(operations)? { | 350 | for (op, frame) in operation_frames(operations)? { |
| 351 | match op { | 351 | match op { |
| 352 | Operation::Read(read_buffer) => self.blocking_read_timeout(address, read_buffer, timeout, framing)?, | 352 | Operation::Read(read_buffer) => self.blocking_read_timeout(address, read_buffer, timeout, frame)?, |
| 353 | Operation::Write(write_buffer) => self.write_bytes(address, write_buffer, timeout, framing)?, | 353 | Operation::Write(write_buffer) => self.write_bytes(address, write_buffer, timeout, frame)?, |
| 354 | } | 354 | } |
| 355 | } | 355 | } |
| 356 | 356 | ||
| @@ -380,12 +380,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 380 | } | 380 | } |
| 381 | 381 | ||
| 382 | impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | 382 | impl<'d, IM: MasterMode> I2c<'d, Async, IM> { |
| 383 | async fn write_with_framing( | 383 | async fn write_frame(&mut self, address: u8, write_buffer: &[u8], frame: FrameOptions) -> Result<(), Error> { |
| 384 | &mut self, | ||
| 385 | address: u8, | ||
| 386 | write_buffer: &[u8], | ||
| 387 | framing: OperationFraming, | ||
| 388 | ) -> Result<(), Error> { | ||
| 389 | self.info.regs.cr2().modify(|w| { | 384 | self.info.regs.cr2().modify(|w| { |
| 390 | // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for | 385 | // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for |
| 391 | // reception. | 386 | // reception. |
| @@ -407,7 +402,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 407 | }) | 402 | }) |
| 408 | }); | 403 | }); |
| 409 | 404 | ||
| 410 | if framing.send_start() { | 405 | if frame.send_start() { |
| 411 | // Send a START condition | 406 | // Send a START condition |
| 412 | self.info.regs.cr1().modify(|reg| { | 407 | self.info.regs.cr1().modify(|reg| { |
| 413 | reg.set_start(true); | 408 | reg.set_start(true); |
| @@ -498,7 +493,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 498 | w.set_dmaen(false); | 493 | w.set_dmaen(false); |
| 499 | }); | 494 | }); |
| 500 | 495 | ||
| 501 | if framing.send_stop() { | 496 | if frame.send_stop() { |
| 502 | // The I2C transfer itself will take longer than the DMA transfer, so wait for that to finish too. | 497 | // The I2C transfer itself will take longer than the DMA transfer, so wait for that to finish too. |
| 503 | 498 | ||
| 504 | // 18.3.8 “Master transmitter: In the interrupt routine after the EOT interrupt, disable DMA | 499 | // 18.3.8 “Master transmitter: In the interrupt routine after the EOT interrupt, disable DMA |
| @@ -534,7 +529,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 534 | 529 | ||
| 535 | /// Write. | 530 | /// Write. |
| 536 | pub async fn write(&mut self, address: u8, write_buffer: &[u8]) -> Result<(), Error> { | 531 | pub async fn write(&mut self, address: u8, write_buffer: &[u8]) -> Result<(), Error> { |
| 537 | self.write_with_framing(address, write_buffer, OperationFraming::FirstAndLast) | 532 | self.write_frame(address, write_buffer, FrameOptions::FirstAndLastFrame) |
| 538 | .await?; | 533 | .await?; |
| 539 | 534 | ||
| 540 | Ok(()) | 535 | Ok(()) |
| @@ -542,18 +537,13 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 542 | 537 | ||
| 543 | /// Read. | 538 | /// Read. |
| 544 | pub async fn read(&mut self, address: u8, read_buffer: &mut [u8]) -> Result<(), Error> { | 539 | pub async fn read(&mut self, address: u8, read_buffer: &mut [u8]) -> Result<(), Error> { |
| 545 | self.read_with_framing(address, read_buffer, OperationFraming::FirstAndLast) | 540 | self.read_frame(address, read_buffer, FrameOptions::FirstAndLastFrame) |
| 546 | .await?; | 541 | .await?; |
| 547 | 542 | ||
| 548 | Ok(()) | 543 | Ok(()) |
| 549 | } | 544 | } |
| 550 | 545 | ||
| 551 | async fn read_with_framing( | 546 | async fn read_frame(&mut self, address: u8, read_buffer: &mut [u8], frame: FrameOptions) -> Result<(), Error> { |
| 552 | &mut self, | ||
| 553 | address: u8, | ||
| 554 | read_buffer: &mut [u8], | ||
| 555 | framing: OperationFraming, | ||
| 556 | ) -> Result<(), Error> { | ||
| 557 | if read_buffer.is_empty() { | 547 | if read_buffer.is_empty() { |
| 558 | return Err(Error::Overrun); | 548 | return Err(Error::Overrun); |
| 559 | } | 549 | } |
| @@ -571,7 +561,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 571 | // If, in the I2C_CR2 register, the LAST bit is set, I2C automatically sends a NACK | 561 | // If, in the I2C_CR2 register, the LAST bit is set, I2C automatically sends a NACK |
| 572 | // after the next byte following EOT_1. The user can generate a Stop condition in | 562 | // after the next byte following EOT_1. The user can generate a Stop condition in |
| 573 | // the DMA Transfer Complete interrupt routine if enabled. | 563 | // the DMA Transfer Complete interrupt routine if enabled. |
| 574 | w.set_last(framing.send_nack() && !single_byte); | 564 | w.set_last(frame.send_nack() && !single_byte); |
| 575 | }); | 565 | }); |
| 576 | 566 | ||
| 577 | // Sentinel to disable transfer when an error occurs or future is canceled. | 567 | // Sentinel to disable transfer when an error occurs or future is canceled. |
| @@ -584,7 +574,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 584 | }) | 574 | }) |
| 585 | }); | 575 | }); |
| 586 | 576 | ||
| 587 | if framing.send_start() { | 577 | if frame.send_start() { |
| 588 | // Send a START condition and set ACK bit | 578 | // Send a START condition and set ACK bit |
| 589 | self.info.regs.cr1().modify(|reg| { | 579 | self.info.regs.cr1().modify(|reg| { |
| 590 | reg.set_start(true); | 580 | reg.set_start(true); |
| @@ -639,7 +629,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 639 | 629 | ||
| 640 | // 18.3.8: When a single byte must be received: the NACK must be programmed during EV6 | 630 | // 18.3.8: When a single byte must be received: the NACK must be programmed during EV6 |
| 641 | // event, i.e. program ACK=0 when ADDR=1, before clearing ADDR flag. | 631 | // event, i.e. program ACK=0 when ADDR=1, before clearing ADDR flag. |
| 642 | if framing.send_nack() && single_byte { | 632 | if frame.send_nack() && single_byte { |
| 643 | self.info.regs.cr1().modify(|w| { | 633 | self.info.regs.cr1().modify(|w| { |
| 644 | w.set_ack(false); | 634 | w.set_ack(false); |
| 645 | }); | 635 | }); |
| @@ -650,7 +640,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 650 | } else { | 640 | } else { |
| 651 | // Before starting reception of single byte (but without START condition, i.e. in case | 641 | // Before starting reception of single byte (but without START condition, i.e. in case |
| 652 | // of merged operations), program NACK to emit at end of this byte. | 642 | // of merged operations), program NACK to emit at end of this byte. |
| 653 | if framing.send_nack() && single_byte { | 643 | if frame.send_nack() && single_byte { |
| 654 | self.info.regs.cr1().modify(|w| { | 644 | self.info.regs.cr1().modify(|w| { |
| 655 | w.set_ack(false); | 645 | w.set_ack(false); |
| 656 | }); | 646 | }); |
| @@ -660,7 +650,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 660 | // 18.3.8: When a single byte must be received: [snip] Then the user can program the STOP | 650 | // 18.3.8: When a single byte must be received: [snip] Then the user can program the STOP |
| 661 | // condition either after clearing ADDR flag, or in the DMA Transfer Complete interrupt | 651 | // condition either after clearing ADDR flag, or in the DMA Transfer Complete interrupt |
| 662 | // routine. | 652 | // routine. |
| 663 | if framing.send_stop() && single_byte { | 653 | if frame.send_stop() && single_byte { |
| 664 | self.info.regs.cr1().modify(|w| { | 654 | self.info.regs.cr1().modify(|w| { |
| 665 | w.set_stop(true); | 655 | w.set_stop(true); |
| 666 | }); | 656 | }); |
| @@ -697,7 +687,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 697 | w.set_dmaen(false); | 687 | w.set_dmaen(false); |
| 698 | }); | 688 | }); |
| 699 | 689 | ||
| 700 | if framing.send_stop() && !single_byte { | 690 | if frame.send_stop() && !single_byte { |
| 701 | self.info.regs.cr1().modify(|w| { | 691 | self.info.regs.cr1().modify(|w| { |
| 702 | w.set_stop(true); | 692 | w.set_stop(true); |
| 703 | }); | 693 | }); |
| @@ -717,9 +707,9 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 717 | return Err(Error::Overrun); | 707 | return Err(Error::Overrun); |
| 718 | } | 708 | } |
| 719 | 709 | ||
| 720 | self.write_with_framing(address, write_buffer, OperationFraming::First) | 710 | self.write_frame(address, write_buffer, FrameOptions::FirstFrame) |
| 721 | .await?; | 711 | .await?; |
| 722 | self.read_with_framing(address, read_buffer, OperationFraming::FirstAndLast) | 712 | self.read_frame(address, read_buffer, FrameOptions::FirstAndLastFrame) |
| 723 | .await | 713 | .await |
| 724 | } | 714 | } |
| 725 | 715 | ||
| @@ -729,10 +719,10 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 729 | /// | 719 | /// |
| 730 | /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction | 720 | /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction |
| 731 | pub async fn transaction(&mut self, address: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { | 721 | pub async fn transaction(&mut self, address: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { |
| 732 | for (op, framing) in assign_operation_framing(operations)? { | 722 | for (op, frame) in operation_frames(operations)? { |
| 733 | match op { | 723 | match op { |
| 734 | Operation::Read(read_buffer) => self.read_with_framing(address, read_buffer, framing).await?, | 724 | Operation::Read(read_buffer) => self.read_frame(address, read_buffer, frame).await?, |
| 735 | Operation::Write(write_buffer) => self.write_with_framing(address, write_buffer, framing).await?, | 725 | Operation::Write(write_buffer) => self.write_frame(address, write_buffer, frame).await?, |
| 736 | } | 726 | } |
| 737 | } | 727 | } |
| 738 | 728 | ||
| @@ -740,6 +730,34 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 740 | } | 730 | } |
| 741 | } | 731 | } |
| 742 | 732 | ||
| 733 | enum Mode { | ||
| 734 | Fast, | ||
| 735 | Standard, | ||
| 736 | } | ||
| 737 | |||
| 738 | impl Mode { | ||
| 739 | fn f_s(&self) -> i2c::vals::FS { | ||
| 740 | match self { | ||
| 741 | Mode::Fast => i2c::vals::FS::FAST, | ||
| 742 | Mode::Standard => i2c::vals::FS::STANDARD, | ||
| 743 | } | ||
| 744 | } | ||
| 745 | } | ||
| 746 | |||
| 747 | enum Duty { | ||
| 748 | Duty2_1, | ||
| 749 | Duty16_9, | ||
| 750 | } | ||
| 751 | |||
| 752 | impl Duty { | ||
| 753 | fn duty(&self) -> i2c::vals::Duty { | ||
| 754 | match self { | ||
| 755 | Duty::Duty2_1 => i2c::vals::Duty::DUTY2_1, | ||
| 756 | Duty::Duty16_9 => i2c::vals::Duty::DUTY16_9, | ||
| 757 | } | ||
| 758 | } | ||
| 759 | } | ||
| 760 | |||
| 743 | /// Result of attempting to send a byte in slave transmitter mode | 761 | /// Result of attempting to send a byte in slave transmitter mode |
| 744 | #[derive(Debug, PartialEq)] | 762 | #[derive(Debug, PartialEq)] |
| 745 | enum TransmitResult { | 763 | enum TransmitResult { |
| @@ -776,7 +794,7 @@ enum SlaveTermination { | |||
| 776 | Nack, | 794 | Nack, |
| 777 | } | 795 | } |
| 778 | 796 | ||
| 779 | impl<'d, M: Mode> I2c<'d, M, Master> { | 797 | impl<'d, M: PeriMode> I2c<'d, M, Master> { |
| 780 | /// Configure the I2C driver for slave operations, allowing for the driver to be used as a slave and a master (multimaster) | 798 | /// Configure the I2C driver for slave operations, allowing for the driver to be used as a slave and a master (multimaster) |
| 781 | pub fn into_slave_multimaster(mut self, slave_addr_config: SlaveAddrConfig) -> I2c<'d, M, MultiMaster> { | 799 | pub fn into_slave_multimaster(mut self, slave_addr_config: SlaveAddrConfig) -> I2c<'d, M, MultiMaster> { |
| 782 | let mut slave = I2c { | 800 | let mut slave = I2c { |
| @@ -797,7 +815,7 @@ impl<'d, M: Mode> I2c<'d, M, Master> { | |||
| 797 | } | 815 | } |
| 798 | 816 | ||
| 799 | // Address configuration methods | 817 | // Address configuration methods |
| 800 | impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | 818 | impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> { |
| 801 | /// Initialize slave mode with address configuration | 819 | /// Initialize slave mode with address configuration |
| 802 | pub(crate) fn init_slave(&mut self, config: SlaveAddrConfig) { | 820 | pub(crate) fn init_slave(&mut self, config: SlaveAddrConfig) { |
| 803 | trace!("I2C slave: initializing with config={:?}", config); | 821 | trace!("I2C slave: initializing with config={:?}", config); |
| @@ -888,7 +906,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 888 | } | 906 | } |
| 889 | } | 907 | } |
| 890 | 908 | ||
| 891 | impl<'d, M: Mode> I2c<'d, M, MultiMaster> { | 909 | impl<'d, M: PeriMode> I2c<'d, M, MultiMaster> { |
| 892 | /// Listen for incoming I2C address match and return the command type | 910 | /// Listen for incoming I2C address match and return the command type |
| 893 | /// | 911 | /// |
| 894 | /// This method blocks until the slave address is matched by a master. | 912 | /// This method blocks until the slave address is matched by a master. |
| @@ -1685,11 +1703,11 @@ impl<'d> I2c<'d, Async, MultiMaster> { | |||
| 1685 | /// peripherals, which use three separate registers (CR2.FREQ, CCR, TRISE) instead of | 1703 | /// peripherals, which use three separate registers (CR2.FREQ, CCR, TRISE) instead of |
| 1686 | /// the unified TIMINGR register found in v2 hardware. | 1704 | /// the unified TIMINGR register found in v2 hardware. |
| 1687 | struct Timings { | 1705 | struct Timings { |
| 1688 | freq: u8, // APB frequency in MHz for CR2.FREQ register | 1706 | freq: u8, // APB frequency in MHz for CR2.FREQ register |
| 1689 | f_s: i2c::vals::FS, // Standard or Fast mode selection | 1707 | mode: Mode, // Standard or Fast mode selection |
| 1690 | trise: u8, // Rise time compensation value | 1708 | trise: u8, // Rise time compensation value |
| 1691 | ccr: u16, // Clock control register value | 1709 | ccr: u16, // Clock control register value |
| 1692 | duty: i2c::vals::Duty, // Fast mode duty cycle selection | 1710 | duty: Duty, // Fast mode duty cycle selection |
| 1693 | } | 1711 | } |
| 1694 | 1712 | ||
| 1695 | impl Timings { | 1713 | impl Timings { |
| @@ -1709,25 +1727,25 @@ impl Timings { | |||
| 1709 | 1727 | ||
| 1710 | let mut ccr; | 1728 | let mut ccr; |
| 1711 | let duty; | 1729 | let duty; |
| 1712 | let f_s; | 1730 | let mode; |
| 1713 | 1731 | ||
| 1714 | // I2C clock control calculation | 1732 | // I2C clock control calculation |
| 1715 | if frequency <= 100_000 { | 1733 | if frequency <= 100_000 { |
| 1716 | duty = i2c::vals::Duty::DUTY2_1; | 1734 | duty = Duty::Duty2_1; |
| 1717 | f_s = i2c::vals::FS::STANDARD; | 1735 | mode = Mode::Standard; |
| 1718 | ccr = { | 1736 | ccr = { |
| 1719 | let ccr = clock / (frequency * 2); | 1737 | let ccr = clock / (frequency * 2); |
| 1720 | if ccr < 4 { 4 } else { ccr } | 1738 | if ccr < 4 { 4 } else { ccr } |
| 1721 | }; | 1739 | }; |
| 1722 | } else { | 1740 | } else { |
| 1723 | const DUTYCYCLE: u8 = 0; | 1741 | const DUTYCYCLE: u8 = 0; |
| 1724 | f_s = i2c::vals::FS::FAST; | 1742 | mode = Mode::Fast; |
| 1725 | if DUTYCYCLE == 0 { | 1743 | if DUTYCYCLE == 0 { |
| 1726 | duty = i2c::vals::Duty::DUTY2_1; | 1744 | duty = Duty::Duty2_1; |
| 1727 | ccr = clock / (frequency * 3); | 1745 | ccr = clock / (frequency * 3); |
| 1728 | ccr = if ccr < 1 { 1 } else { ccr }; | 1746 | ccr = if ccr < 1 { 1 } else { ccr }; |
| 1729 | } else { | 1747 | } else { |
| 1730 | duty = i2c::vals::Duty::DUTY16_9; | 1748 | duty = Duty::Duty16_9; |
| 1731 | ccr = clock / (frequency * 25); | 1749 | ccr = clock / (frequency * 25); |
| 1732 | ccr = if ccr < 1 { 1 } else { ccr }; | 1750 | ccr = if ccr < 1 { 1 } else { ccr }; |
| 1733 | } | 1751 | } |
| @@ -1735,15 +1753,15 @@ impl Timings { | |||
| 1735 | 1753 | ||
| 1736 | Self { | 1754 | Self { |
| 1737 | freq: freq as u8, | 1755 | freq: freq as u8, |
| 1738 | f_s, | ||
| 1739 | trise: trise as u8, | 1756 | trise: trise as u8, |
| 1740 | ccr: ccr as u16, | 1757 | ccr: ccr as u16, |
| 1741 | duty, | 1758 | duty, |
| 1759 | mode, | ||
| 1742 | } | 1760 | } |
| 1743 | } | 1761 | } |
| 1744 | } | 1762 | } |
| 1745 | 1763 | ||
| 1746 | impl<'d, M: Mode> SetConfig for I2c<'d, M, Master> { | 1764 | impl<'d, M: PeriMode> SetConfig for I2c<'d, M, Master> { |
| 1747 | type Config = Hertz; | 1765 | type Config = Hertz; |
| 1748 | type ConfigError = (); | 1766 | type ConfigError = (); |
| 1749 | fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { | 1767 | fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { |
| @@ -1752,8 +1770,8 @@ impl<'d, M: Mode> SetConfig for I2c<'d, M, Master> { | |||
| 1752 | reg.set_freq(timings.freq); | 1770 | reg.set_freq(timings.freq); |
| 1753 | }); | 1771 | }); |
| 1754 | self.info.regs.ccr().modify(|reg| { | 1772 | self.info.regs.ccr().modify(|reg| { |
| 1755 | reg.set_f_s(timings.f_s); | 1773 | reg.set_f_s(timings.mode.f_s()); |
| 1756 | reg.set_duty(timings.duty); | 1774 | reg.set_duty(timings.duty.duty()); |
| 1757 | reg.set_ccr(timings.ccr); | 1775 | reg.set_ccr(timings.ccr); |
| 1758 | }); | 1776 | }); |
| 1759 | self.info.regs.trise().modify(|reg| { | 1777 | self.info.regs.trise().modify(|reg| { |
