aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-10-30 15:49:07 -0500
committerxoviat <[email protected]>2025-10-30 15:49:07 -0500
commitae726274ddb95c048c386817ef105012dcc06dad (patch)
treeb30e036481e6b687b871d253b0da6eb87c1e9897
parent65438769024b657f98da20646beb10e7e5a1b960 (diff)
reduce diff with misc. reversions
-rw-r--r--embassy-stm32/src/i2c/mod.rs97
-rw-r--r--embassy-stm32/src/i2c/v1.rs144
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)]
458enum OperationFraming { 459enum 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)]
474impl OperationFraming { 477impl 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)]
530fn assign_operation_framing<'a, 'b: 'a>( 533fn 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;
14use mode::Master; 14use mode::Master;
15 15
16use super::*; 16use super::*;
17use crate::mode::Mode; 17use crate::mode::Mode as PeriMode;
18use crate::pac::i2c; 18use crate::pac::i2c;
19 19
20// /!\ /!\ 20// /!\ /!\
@@ -43,7 +43,7 @@ pub unsafe fn on_interrupt<T: Instance>() {
43 }); 43 });
44} 44}
45 45
46impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { 46impl<'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
382impl<'d, IM: MasterMode> I2c<'d, Async, IM> { 382impl<'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
733enum Mode {
734 Fast,
735 Standard,
736}
737
738impl 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
747enum Duty {
748 Duty2_1,
749 Duty16_9,
750}
751
752impl 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)]
745enum TransmitResult { 763enum TransmitResult {
@@ -776,7 +794,7 @@ enum SlaveTermination {
776 Nack, 794 Nack,
777} 795}
778 796
779impl<'d, M: Mode> I2c<'d, M, Master> { 797impl<'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
800impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { 818impl<'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
891impl<'d, M: Mode> I2c<'d, M, MultiMaster> { 909impl<'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.
1687struct Timings { 1705struct 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
1695impl Timings { 1713impl 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
1746impl<'d, M: Mode> SetConfig for I2c<'d, M, Master> { 1764impl<'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| {