aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32/src/i2c')
-rw-r--r--embassy-stm32/src/i2c/config.rs8
-rw-r--r--embassy-stm32/src/i2c/mod.rs110
-rw-r--r--embassy-stm32/src/i2c/v1.rs1095
-rw-r--r--embassy-stm32/src/i2c/v2.rs825
4 files changed, 1834 insertions, 204 deletions
diff --git a/embassy-stm32/src/i2c/config.rs b/embassy-stm32/src/i2c/config.rs
index 4e3b736c7..74fac14b2 100644
--- a/embassy-stm32/src/i2c/config.rs
+++ b/embassy-stm32/src/i2c/config.rs
@@ -4,7 +4,7 @@ use crate::gpio::{AfType, OutputType, Speed};
4use crate::time::Hertz; 4use crate::time::Hertz;
5 5
6#[repr(u8)] 6#[repr(u8)]
7#[derive(Copy, Clone)] 7#[derive(Debug, Copy, Clone)]
8#[cfg_attr(feature = "defmt", derive(defmt::Format))] 8#[cfg_attr(feature = "defmt", derive(defmt::Format))]
9/// Bits of the I2C OA2 register to mask out. 9/// Bits of the I2C OA2 register to mask out.
10pub enum AddrMask { 10pub enum AddrMask {
@@ -60,7 +60,7 @@ impl Address {
60 } 60 }
61} 61}
62 62
63#[derive(Copy, Clone)] 63#[derive(Debug, Copy, Clone)]
64#[cfg_attr(feature = "defmt", derive(defmt::Format))] 64#[cfg_attr(feature = "defmt", derive(defmt::Format))]
65/// The second Own Address register. 65/// The second Own Address register.
66pub struct OA2 { 66pub struct OA2 {
@@ -70,7 +70,7 @@ pub struct OA2 {
70 pub mask: AddrMask, 70 pub mask: AddrMask,
71} 71}
72 72
73#[derive(Copy, Clone)] 73#[derive(Debug, Copy, Clone)]
74#[cfg_attr(feature = "defmt", derive(defmt::Format))] 74#[cfg_attr(feature = "defmt", derive(defmt::Format))]
75/// The Own Address(es) of the I2C peripheral. 75/// The Own Address(es) of the I2C peripheral.
76pub enum OwnAddresses { 76pub enum OwnAddresses {
@@ -88,7 +88,7 @@ pub enum OwnAddresses {
88} 88}
89 89
90/// Slave Configuration 90/// Slave Configuration
91#[derive(Copy, Clone)] 91#[derive(Debug, Copy, Clone)]
92#[cfg_attr(feature = "defmt", derive(defmt::Format))] 92#[cfg_attr(feature = "defmt", derive(defmt::Format))]
93pub struct SlaveAddrConfig { 93pub struct SlaveAddrConfig {
94 /// Target Address(es) 94 /// Target Address(es)
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs
index 249bac41c..0aa2d1da9 100644
--- a/embassy-stm32/src/i2c/mod.rs
+++ b/embassy-stm32/src/i2c/mod.rs
@@ -129,7 +129,7 @@ impl<'d> Drop for I2CDropGuard<'d> {
129 x.set_as_disconnected() 129 x.set_as_disconnected()
130 } 130 }
131 131
132 self.info.rcc.disable(); 132 self.info.rcc.disable_without_stop();
133 } 133 }
134} 134}
135 135
@@ -154,8 +154,8 @@ impl<'d> I2c<'d, Async, Master> {
154 scl: Peri<'d, if_afio!(impl SclPin<T, A>)>, 154 scl: Peri<'d, if_afio!(impl SclPin<T, A>)>,
155 sda: Peri<'d, if_afio!(impl SdaPin<T, A>)>, 155 sda: Peri<'d, if_afio!(impl SdaPin<T, A>)>,
156 _irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>> 156 _irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>>
157 + interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>> 157 + interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>>
158 + 'd, 158 + 'd,
159 tx_dma: Peri<'d, impl TxDma<T>>, 159 tx_dma: Peri<'d, impl TxDma<T>>,
160 rx_dma: Peri<'d, impl RxDma<T>>, 160 rx_dma: Peri<'d, impl RxDma<T>>,
161 config: Config, 161 config: Config,
@@ -219,13 +219,14 @@ impl<'d, M: Mode> I2c<'d, M, Master> {
219 sda, 219 sda,
220 }, 220 },
221 }; 221 };
222
222 this.enable_and_init(config); 223 this.enable_and_init(config);
223 224
224 this 225 this
225 } 226 }
226 227
227 fn enable_and_init(&mut self, config: Config) { 228 fn enable_and_init(&mut self, config: Config) {
228 self.info.rcc.enable_and_reset(); 229 self.info.rcc.enable_and_reset_without_stop();
229 self.init(config); 230 self.init(config);
230 } 231 }
231} 232}
@@ -437,15 +438,15 @@ impl<'d, IM: MasterMode> embedded_hal_async::i2c::I2c for I2c<'d, Async, IM> {
437 438
438/// Frame type in I2C transaction. 439/// Frame type in I2C transaction.
439/// 440///
440/// This tells each method what kind of framing to use, to generate a (repeated) start condition (ST 441/// This tells each method what kind of frame to use, to generate a (repeated) start condition (ST
441/// or SR), and/or a stop condition (SP). For read operations, this also controls whether to send an 442/// or SR), and/or a stop condition (SP). For read operations, this also controls whether to send an
442/// ACK or NACK after the last byte received. 443/// ACK or NACK after the last byte received.
443/// 444///
444/// For write operations, the following options are identical because they differ only in the (N)ACK 445/// For write operations, the following options are identical because they differ only in the (N)ACK
445/// treatment relevant for read operations: 446/// treatment relevant for read operations:
446/// 447///
447/// - `FirstFrame` and `FirstAndNextFrame` 448/// - `FirstFrame` and `FirstAndNextFrame` behave identically for writes
448/// - `NextFrame` and `LastFrameNoStop` 449/// - `NextFrame` and `LastFrameNoStop` behave identically for writes
449/// 450///
450/// Abbreviations used below: 451/// Abbreviations used below:
451/// 452///
@@ -474,7 +475,7 @@ enum FrameOptions {
474 475
475#[allow(dead_code)] 476#[allow(dead_code)]
476impl FrameOptions { 477impl FrameOptions {
477 /// Sends start or repeated start condition before transfer. 478 /// Returns true if a start or repeated start condition should be generated before this operation.
478 fn send_start(self) -> bool { 479 fn send_start(self) -> bool {
479 match self { 480 match self {
480 Self::FirstAndLastFrame | Self::FirstFrame | Self::FirstAndNextFrame => true, 481 Self::FirstAndLastFrame | Self::FirstFrame | Self::FirstAndNextFrame => true,
@@ -482,7 +483,7 @@ impl FrameOptions {
482 } 483 }
483 } 484 }
484 485
485 /// Sends stop condition after transfer. 486 /// Returns true if a stop condition should be generated after this operation.
486 fn send_stop(self) -> bool { 487 fn send_stop(self) -> bool {
487 match self { 488 match self {
488 Self::FirstAndLastFrame | Self::LastFrame => true, 489 Self::FirstAndLastFrame | Self::LastFrame => true,
@@ -490,7 +491,10 @@ impl FrameOptions {
490 } 491 }
491 } 492 }
492 493
493 /// Sends NACK after last byte received, indicating end of read operation. 494 /// Returns true if NACK should be sent after the last byte received in a read operation.
495 ///
496 /// This signals the end of a read sequence and releases the bus for the master's
497 /// next transmission (or stop condition).
494 fn send_nack(self) -> bool { 498 fn send_nack(self) -> bool {
495 match self { 499 match self {
496 Self::FirstAndLastFrame | Self::FirstFrame | Self::LastFrame | Self::LastFrameNoStop => true, 500 Self::FirstAndLastFrame | Self::FirstFrame | Self::LastFrame | Self::LastFrameNoStop => true,
@@ -499,24 +503,44 @@ impl FrameOptions {
499 } 503 }
500} 504}
501 505
502/// Iterates over operations in transaction. 506/// Analyzes I2C transaction operations and assigns appropriate frame to each.
507///
508/// This function processes a sequence of I2C operations and determines the correct
509/// frame configuration for each operation to ensure proper I2C protocol compliance.
510/// It handles the complex logic of:
511///
512/// - Generating start conditions for the first operation of each type (read/write)
513/// - Generating stop conditions for the final operation in the entire transaction
514/// - Managing ACK/NACK behavior for read operations, including merging consecutive reads
515/// - Ensuring proper bus handoff between different operation types
516///
517/// **Transaction Contract Compliance:**
518/// The frame assignments ensure compliance with the embedded-hal I2C transaction contract,
519/// where consecutive operations of the same type are logically merged while maintaining
520/// proper protocol boundaries.
503/// 521///
504/// Returns necessary frame options for each operation to uphold the [transaction contract] and have 522/// **Error Handling:**
505/// the right start/stop/(N)ACK conditions on the wire. 523/// Returns an error if any read operation has an empty buffer, as this would create
524/// an invalid I2C transaction that could halt mid-execution.
525///
526/// # Arguments
527/// * `operations` - Mutable slice of I2C operations from embedded-hal
528///
529/// # Returns
530/// An iterator over (operation, frame) pairs, or an error if the transaction is invalid
506/// 531///
507/// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
508#[allow(dead_code)] 532#[allow(dead_code)]
509fn operation_frames<'a, 'b: 'a>( 533fn operation_frames<'a, 'b: 'a>(
510 operations: &'a mut [embedded_hal_1::i2c::Operation<'b>], 534 operations: &'a mut [embedded_hal_1::i2c::Operation<'b>],
511) -> Result<impl IntoIterator<Item = (&'a mut embedded_hal_1::i2c::Operation<'b>, FrameOptions)>, Error> { 535) -> Result<impl IntoIterator<Item = (&'a mut embedded_hal_1::i2c::Operation<'b>, FrameOptions)>, Error> {
512 use embedded_hal_1::i2c::Operation::{Read, Write}; 536 use embedded_hal_1::i2c::Operation::{Read, Write};
513 537
514 // Check empty read buffer before starting transaction. Otherwise, we would risk halting with an 538 // Validate that no read operations have empty buffers before starting the transaction.
515 // error in the middle of the transaction. 539 // Empty read operations would risk halting with an error mid-transaction.
516 // 540 //
517 // In principle, we could allow empty read frames within consecutive read operations, as long as 541 // 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 542 // sequences as long as the final merged read has at least one byte, but this would
519 // complicated and error-prone. 543 // complicate the logic significantly and create error-prone edge cases.
520 if operations.iter().any(|op| match op { 544 if operations.iter().any(|op| match op {
521 Read(read) => read.is_empty(), 545 Read(read) => read.is_empty(),
522 Write(_) => false, 546 Write(_) => false,
@@ -525,46 +549,52 @@ fn operation_frames<'a, 'b: 'a>(
525 } 549 }
526 550
527 let mut operations = operations.iter_mut().peekable(); 551 let mut operations = operations.iter_mut().peekable();
528 552 let mut next_first_operation = true;
529 let mut next_first_frame = true;
530 553
531 Ok(iter::from_fn(move || { 554 Ok(iter::from_fn(move || {
532 let op = operations.next()?; 555 let current_op = operations.next()?;
533 556
534 // Is `op` first frame of its type? 557 // Determine if this is the first operation of its type (read or write)
535 let first_frame = next_first_frame; 558 let is_first_of_type = next_first_operation;
536 let next_op = operations.peek(); 559 let next_op = operations.peek();
537 560
538 // Get appropriate frame options as combination of the following properties: 561 // Compute the appropriate frame based on three key properties:
539 // 562 //
540 // - For each first operation of its type, generate a (repeated) start condition. 563 // 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. 564 // 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 565 // 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 566 // 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 // 567 //
547 // We check the third property unconditionally, i.e. even for write opeartions. This is okay 568 // The third property is checked for all operations since the resulting frame
548 // because the resulting frame options are identical for write operations. 569 // configurations are identical for write operations regardless of ACK/NACK treatment.
549 let frame = match (first_frame, next_op) { 570 let frame = match (is_first_of_type, next_op) {
571 // First operation of type, and it's also the final operation overall
550 (true, None) => FrameOptions::FirstAndLastFrame, 572 (true, None) => FrameOptions::FirstAndLastFrame,
573 // First operation of type, next operation is also a read (continue read sequence)
551 (true, Some(Read(_))) => FrameOptions::FirstAndNextFrame, 574 (true, Some(Read(_))) => FrameOptions::FirstAndNextFrame,
575 // First operation of type, next operation is write (end current sequence)
552 (true, Some(Write(_))) => FrameOptions::FirstFrame, 576 (true, Some(Write(_))) => FrameOptions::FirstFrame,
553 // 577
578 // Continuation operation, and it's the final operation overall
554 (false, None) => FrameOptions::LastFrame, 579 (false, None) => FrameOptions::LastFrame,
580 // Continuation operation, next operation is also a read (continue read sequence)
555 (false, Some(Read(_))) => FrameOptions::NextFrame, 581 (false, Some(Read(_))) => FrameOptions::NextFrame,
582 // Continuation operation, next operation is write (end current sequence, no stop)
556 (false, Some(Write(_))) => FrameOptions::LastFrameNoStop, 583 (false, Some(Write(_))) => FrameOptions::LastFrameNoStop,
557 }; 584 };
558 585
559 // Pre-calculate if `next_op` is the first operation of its type. We do this here and not at 586 // 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 587 // This is done here because we consume `current_op` as the iterator value
561 // anymore in the next iteration. 588 // and cannot access it in the next iteration.
562 next_first_frame = match (&op, next_op) { 589 next_first_operation = match (&current_op, next_op) {
590 // No next operation
563 (_, None) => false, 591 (_, None) => false,
592 // Operation type changes: next will be first of its type
564 (Read(_), Some(Write(_))) | (Write(_), Some(Read(_))) => true, 593 (Read(_), Some(Write(_))) | (Write(_), Some(Read(_))) => true,
594 // Operation type continues: next will not be first of its type
565 (Read(_), Some(Read(_))) | (Write(_), Some(Write(_))) => false, 595 (Read(_), Some(Read(_))) | (Write(_), Some(Write(_))) => false,
566 }; 596 };
567 597
568 Some((op, frame)) 598 Some((current_op, frame))
569 })) 599 }))
570} 600}
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index 081eb1191..81a6d74c1 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -8,7 +8,7 @@ use core::future::poll_fn;
8use core::task::Poll; 8use core::task::Poll;
9 9
10use embassy_embedded_hal::SetConfig; 10use embassy_embedded_hal::SetConfig;
11use embassy_futures::select::{select, Either}; 11use embassy_futures::select::{Either, select};
12use embassy_hal_internal::drop::OnDrop; 12use embassy_hal_internal::drop::OnDrop;
13use embedded_hal_1::i2c::Operation; 13use embedded_hal_1::i2c::Operation;
14use mode::Master; 14use mode::Master;
@@ -30,6 +30,7 @@ use crate::pac::i2c;
30// hit a case like this! 30// hit a case like this!
31pub unsafe fn on_interrupt<T: Instance>() { 31pub unsafe fn on_interrupt<T: Instance>() {
32 let regs = T::info().regs; 32 let regs = T::info().regs;
33 trace!("I2C interrupt triggered");
33 // i2c v2 only woke the task on transfer complete interrupts. v1 uses interrupts for a bunch of 34 // i2c v2 only woke the task on transfer complete interrupts. v1 uses interrupts for a bunch of
34 // other stuff, so we wake the task on every interrupt. 35 // other stuff, so we wake the task on every interrupt.
35 T::state().waker.wake(); 36 T::state().waker.wake();
@@ -92,6 +93,7 @@ impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
92 self.info.regs.cr1().modify(|reg| { 93 self.info.regs.cr1().modify(|reg| {
93 reg.set_pe(true); 94 reg.set_pe(true);
94 }); 95 });
96 trace!("i2c v1 init complete");
95 } 97 }
96 98
97 fn check_and_clear_error_flags(info: &'static Info) -> Result<i2c::regs::Sr1, Error> { 99 fn check_and_clear_error_flags(info: &'static Info) -> Result<i2c::regs::Sr1, Error> {
@@ -151,7 +153,13 @@ impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
151 Ok(sr1) 153 Ok(sr1)
152 } 154 }
153 155
154 fn write_bytes(&mut self, addr: u8, bytes: &[u8], timeout: Timeout, frame: FrameOptions) -> Result<(), Error> { 156 fn write_bytes(
157 &mut self,
158 address: u8,
159 write_buffer: &[u8],
160 timeout: Timeout,
161 frame: FrameOptions,
162 ) -> Result<(), Error> {
155 if frame.send_start() { 163 if frame.send_start() {
156 // Send a START condition 164 // Send a START condition
157 165
@@ -170,7 +178,7 @@ impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
170 } 178 }
171 179
172 // Set up current address we're trying to talk to 180 // Set up current address we're trying to talk to
173 self.info.regs.dr().write(|reg| reg.set_dr(addr << 1)); 181 self.info.regs.dr().write(|reg| reg.set_dr(address << 1));
174 182
175 // Wait until address was sent 183 // Wait until address was sent
176 // Wait for the address to be acknowledged 184 // Wait for the address to be acknowledged
@@ -184,7 +192,7 @@ impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
184 } 192 }
185 193
186 // Send bytes 194 // Send bytes
187 for c in bytes { 195 for c in write_buffer {
188 self.send_byte(*c, timeout)?; 196 self.send_byte(*c, timeout)?;
189 } 197 }
190 198
@@ -236,12 +244,12 @@ impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
236 244
237 fn blocking_read_timeout( 245 fn blocking_read_timeout(
238 &mut self, 246 &mut self,
239 addr: u8, 247 address: u8,
240 buffer: &mut [u8], 248 read_buffer: &mut [u8],
241 timeout: Timeout, 249 timeout: Timeout,
242 frame: FrameOptions, 250 frame: FrameOptions,
243 ) -> Result<(), Error> { 251 ) -> Result<(), Error> {
244 let Some((last, buffer)) = buffer.split_last_mut() else { 252 let Some((last_byte, read_buffer)) = read_buffer.split_last_mut() else {
245 return Err(Error::Overrun); 253 return Err(Error::Overrun);
246 }; 254 };
247 255
@@ -263,7 +271,7 @@ impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
263 } 271 }
264 272
265 // Set up current address we're trying to talk to 273 // Set up current address we're trying to talk to
266 self.info.regs.dr().write(|reg| reg.set_dr((addr << 1) + 1)); 274 self.info.regs.dr().write(|reg| reg.set_dr((address << 1) + 1));
267 275
268 // Wait until address was sent 276 // Wait until address was sent
269 // Wait for the address to be acknowledged 277 // Wait for the address to be acknowledged
@@ -276,7 +284,7 @@ impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
276 } 284 }
277 285
278 // Receive bytes into buffer 286 // Receive bytes into buffer
279 for c in buffer { 287 for c in read_buffer {
280 *c = self.recv_byte(timeout)?; 288 *c = self.recv_byte(timeout)?;
281 } 289 }
282 290
@@ -291,37 +299,42 @@ impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
291 }); 299 });
292 300
293 // Receive last byte 301 // Receive last byte
294 *last = self.recv_byte(timeout)?; 302 *last_byte = self.recv_byte(timeout)?;
295 303
296 // Fallthrough is success 304 // Fallthrough is success
297 Ok(()) 305 Ok(())
298 } 306 }
299 307
300 /// Blocking read. 308 /// Blocking read.
301 pub fn blocking_read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Error> { 309 pub fn blocking_read(&mut self, address: u8, read_buffer: &mut [u8]) -> Result<(), Error> {
302 self.blocking_read_timeout(addr, read, self.timeout(), FrameOptions::FirstAndLastFrame) 310 self.blocking_read_timeout(address, read_buffer, self.timeout(), FrameOptions::FirstAndLastFrame)
303 } 311 }
304 312
305 /// Blocking write. 313 /// Blocking write.
306 pub fn blocking_write(&mut self, addr: u8, write: &[u8]) -> Result<(), Error> { 314 pub fn blocking_write(&mut self, address: u8, write_buffer: &[u8]) -> Result<(), Error> {
307 self.write_bytes(addr, write, self.timeout(), FrameOptions::FirstAndLastFrame)?; 315 self.write_bytes(address, write_buffer, self.timeout(), FrameOptions::FirstAndLastFrame)?;
308 316
309 // Fallthrough is success 317 // Fallthrough is success
310 Ok(()) 318 Ok(())
311 } 319 }
312 320
313 /// Blocking write, restart, read. 321 /// Blocking write, restart, read.
314 pub fn blocking_write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { 322 pub fn blocking_write_read(
323 &mut self,
324 address: u8,
325 write_buffer: &[u8],
326 read_buffer: &mut [u8],
327 ) -> Result<(), Error> {
315 // Check empty read buffer before starting transaction. Otherwise, we would not generate the 328 // Check empty read buffer before starting transaction. Otherwise, we would not generate the
316 // stop condition below. 329 // stop condition below.
317 if read.is_empty() { 330 if read_buffer.is_empty() {
318 return Err(Error::Overrun); 331 return Err(Error::Overrun);
319 } 332 }
320 333
321 let timeout = self.timeout(); 334 let timeout = self.timeout();
322 335
323 self.write_bytes(addr, write, timeout, FrameOptions::FirstFrame)?; 336 self.write_bytes(address, write_buffer, timeout, FrameOptions::FirstFrame)?;
324 self.blocking_read_timeout(addr, read, timeout, FrameOptions::FirstAndLastFrame)?; 337 self.blocking_read_timeout(address, read_buffer, timeout, FrameOptions::FirstAndLastFrame)?;
325 338
326 Ok(()) 339 Ok(())
327 } 340 }
@@ -331,32 +344,43 @@ impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
331 /// Consecutive operations of same type are merged. See [transaction contract] for details. 344 /// Consecutive operations of same type are merged. See [transaction contract] for details.
332 /// 345 ///
333 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction 346 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
334 pub fn blocking_transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { 347 pub fn blocking_transaction(&mut self, address: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
335 let timeout = self.timeout(); 348 let timeout = self.timeout();
336 349
337 for (op, frame) in operation_frames(operations)? { 350 for (op, frame) in operation_frames(operations)? {
338 match op { 351 match op {
339 Operation::Read(read) => self.blocking_read_timeout(addr, read, timeout, frame)?, 352 Operation::Read(read_buffer) => self.blocking_read_timeout(address, read_buffer, timeout, frame)?,
340 Operation::Write(write) => self.write_bytes(addr, write, timeout, frame)?, 353 Operation::Write(write_buffer) => self.write_bytes(address, write_buffer, timeout, frame)?,
341 } 354 }
342 } 355 }
343 356
344 Ok(()) 357 Ok(())
345 } 358 }
346 359
347 // Async 360 /// Can be used by both blocking and async implementations
348
349 #[inline] // pretty sure this should always be inlined 361 #[inline] // pretty sure this should always be inlined
350 fn enable_interrupts(info: &'static Info) -> () { 362 fn enable_interrupts(info: &'static Info) {
351 info.regs.cr2().modify(|w| { 363 // The interrupt handler disables interrupts globally, so we need to re-enable them
352 w.set_iterren(true); 364 // This must be done in a critical section to avoid races
353 w.set_itevten(true); 365 critical_section::with(|_| {
366 info.regs.cr2().modify(|w| {
367 w.set_iterren(true);
368 w.set_itevten(true);
369 });
354 }); 370 });
355 } 371 }
372
373 /// Can be used by both blocking and async implementations
374 fn clear_stop_flag(info: &'static Info) {
375 trace!("I2C slave: clearing STOPF flag (v1 sequence)");
376 // v1 requires: READ SR1 then WRITE CR1 to clear STOPF
377 let _ = info.regs.sr1().read();
378 info.regs.cr1().modify(|_| {}); // Dummy write to clear STOPF
379 }
356} 380}
357 381
358impl<'d, IM: MasterMode> I2c<'d, Async, IM> { 382impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
359 async fn write_frame(&mut self, address: u8, write: &[u8], frame: FrameOptions) -> Result<(), Error> { 383 async fn write_frame(&mut self, address: u8, write_buffer: &[u8], frame: FrameOptions) -> Result<(), Error> {
360 self.info.regs.cr2().modify(|w| { 384 self.info.regs.cr2().modify(|w| {
361 // 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
362 // reception. 386 // reception.
@@ -439,7 +463,10 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
439 // this address from the memory after each TxE event. 463 // this address from the memory after each TxE event.
440 let dst = self.info.regs.dr().as_ptr() as *mut u8; 464 let dst = self.info.regs.dr().as_ptr() as *mut u8;
441 465
442 self.tx_dma.as_mut().unwrap().write(write, dst, Default::default()) 466 self.tx_dma
467 .as_mut()
468 .unwrap()
469 .write(write_buffer, dst, Default::default())
443 }; 470 };
444 471
445 // Wait for bytes to be sent, or an error to occur. 472 // Wait for bytes to be sent, or an error to occur.
@@ -501,28 +528,30 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
501 } 528 }
502 529
503 /// Write. 530 /// Write.
504 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { 531 pub async fn write(&mut self, address: u8, write_buffer: &[u8]) -> Result<(), Error> {
505 self.write_frame(address, write, FrameOptions::FirstAndLastFrame) 532 let _scoped_block_stop = self.info.rcc.block_stop();
533 self.write_frame(address, write_buffer, FrameOptions::FirstAndLastFrame)
506 .await?; 534 .await?;
507 535
508 Ok(()) 536 Ok(())
509 } 537 }
510 538
511 /// Read. 539 /// Read.
512 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { 540 pub async fn read(&mut self, address: u8, read_buffer: &mut [u8]) -> Result<(), Error> {
513 self.read_frame(address, buffer, FrameOptions::FirstAndLastFrame) 541 let _scoped_block_stop = self.info.rcc.block_stop();
542 self.read_frame(address, read_buffer, FrameOptions::FirstAndLastFrame)
514 .await?; 543 .await?;
515 544
516 Ok(()) 545 Ok(())
517 } 546 }
518 547
519 async fn read_frame(&mut self, address: u8, buffer: &mut [u8], frame: FrameOptions) -> Result<(), Error> { 548 async fn read_frame(&mut self, address: u8, read_buffer: &mut [u8], frame: FrameOptions) -> Result<(), Error> {
520 if buffer.is_empty() { 549 if read_buffer.is_empty() {
521 return Err(Error::Overrun); 550 return Err(Error::Overrun);
522 } 551 }
523 552
524 // Some branches below depend on whether the buffer contains only a single byte. 553 // Some branches below depend on whether the buffer contains only a single byte.
525 let single_byte = buffer.len() == 1; 554 let single_byte = read_buffer.len() == 1;
526 555
527 self.info.regs.cr2().modify(|w| { 556 self.info.regs.cr2().modify(|w| {
528 // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for 557 // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
@@ -612,7 +641,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
612 self.info.regs.sr2().read(); 641 self.info.regs.sr2().read();
613 } else { 642 } else {
614 // Before starting reception of single byte (but without START condition, i.e. in case 643 // Before starting reception of single byte (but without START condition, i.e. in case
615 // of continued frame), program NACK to emit at end of this byte. 644 // of merged operations), program NACK to emit at end of this byte.
616 if frame.send_nack() && single_byte { 645 if frame.send_nack() && single_byte {
617 self.info.regs.cr1().modify(|w| { 646 self.info.regs.cr1().modify(|w| {
618 w.set_ack(false); 647 w.set_ack(false);
@@ -634,7 +663,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
634 // from this address from the memory after each RxE event. 663 // from this address from the memory after each RxE event.
635 let src = self.info.regs.dr().as_ptr() as *mut u8; 664 let src = self.info.regs.dr().as_ptr() as *mut u8;
636 665
637 self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default()) 666 self.rx_dma.as_mut().unwrap().read(src, read_buffer, Default::default())
638 }; 667 };
639 668
640 // Wait for bytes to be received, or an error to occur. 669 // Wait for bytes to be received, or an error to occur.
@@ -673,15 +702,18 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
673 } 702 }
674 703
675 /// Write, restart, read. 704 /// Write, restart, read.
676 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { 705 pub async fn write_read(&mut self, address: u8, write_buffer: &[u8], read_buffer: &mut [u8]) -> Result<(), Error> {
706 let _scoped_block_stop = self.info.rcc.block_stop();
677 // Check empty read buffer before starting transaction. Otherwise, we would not generate the 707 // Check empty read buffer before starting transaction. Otherwise, we would not generate the
678 // stop condition below. 708 // stop condition below.
679 if read.is_empty() { 709 if read_buffer.is_empty() {
680 return Err(Error::Overrun); 710 return Err(Error::Overrun);
681 } 711 }
682 712
683 self.write_frame(address, write, FrameOptions::FirstFrame).await?; 713 self.write_frame(address, write_buffer, FrameOptions::FirstFrame)
684 self.read_frame(address, read, FrameOptions::FirstAndLastFrame).await 714 .await?;
715 self.read_frame(address, read_buffer, FrameOptions::FirstAndLastFrame)
716 .await
685 } 717 }
686 718
687 /// Transaction with operations. 719 /// Transaction with operations.
@@ -689,11 +721,12 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
689 /// Consecutive operations of same type are merged. See [transaction contract] for details. 721 /// Consecutive operations of same type are merged. See [transaction contract] for details.
690 /// 722 ///
691 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction 723 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
692 pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { 724 pub async fn transaction(&mut self, address: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
725 let _scoped_block_stop = self.info.rcc.block_stop();
693 for (op, frame) in operation_frames(operations)? { 726 for (op, frame) in operation_frames(operations)? {
694 match op { 727 match op {
695 Operation::Read(read) => self.read_frame(addr, read, frame).await?, 728 Operation::Read(read_buffer) => self.read_frame(address, read_buffer, frame).await?,
696 Operation::Write(write) => self.write_frame(addr, write, frame).await?, 729 Operation::Write(write_buffer) => self.write_frame(address, write_buffer, frame).await?,
697 } 730 }
698 } 731 }
699 732
@@ -729,12 +762,959 @@ impl Duty {
729 } 762 }
730} 763}
731 764
765/// Result of attempting to send a byte in slave transmitter mode
766#[derive(Debug, PartialEq)]
767enum TransmitResult {
768 /// Byte sent and ACKed by master - continue transmission
769 Acknowledged,
770 /// Byte sent but NACKed by master - normal end of read transaction
771 NotAcknowledged,
772 /// STOP condition detected - master terminated transaction
773 Stopped,
774 /// RESTART condition detected - master starting new transaction
775 Restarted,
776}
777
778/// Result of attempting to receive a byte in slave receiver mode
779#[derive(Debug, PartialEq)]
780enum ReceiveResult {
781 /// Data byte successfully received
782 Data(u8),
783 /// STOP condition detected - end of write transaction
784 Stopped,
785 /// RESTART condition detected - master starting new transaction
786 Restarted,
787}
788
789/// Enumeration of slave transaction termination conditions
790#[derive(Debug, Clone, Copy, PartialEq)]
791#[cfg_attr(feature = "defmt", derive(defmt::Format))]
792enum SlaveTermination {
793 /// STOP condition received - normal end of transaction
794 Stop,
795 /// RESTART condition received - master starting new transaction
796 Restart,
797 /// NACK received - normal end of read transaction
798 Nack,
799}
800
801impl<'d, M: PeriMode> I2c<'d, M, Master> {
802 /// Configure the I2C driver for slave operations, allowing for the driver to be used as a slave and a master (multimaster)
803 pub fn into_slave_multimaster(mut self, slave_addr_config: SlaveAddrConfig) -> I2c<'d, M, MultiMaster> {
804 let mut slave = I2c {
805 info: self.info,
806 state: self.state,
807 kernel_clock: self.kernel_clock,
808 tx_dma: self.tx_dma.take(), // Use take() to move ownership
809 rx_dma: self.rx_dma.take(), // Use take() to move ownership
810 #[cfg(feature = "time")]
811 timeout: self.timeout,
812 _phantom: PhantomData,
813 _phantom2: PhantomData,
814 _drop_guard: self._drop_guard, // Move the drop guard
815 };
816 slave.init_slave(slave_addr_config);
817 slave
818 }
819}
820
821// Address configuration methods
822impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
823 /// Initialize slave mode with address configuration
824 pub(crate) fn init_slave(&mut self, config: SlaveAddrConfig) {
825 trace!("I2C slave: initializing with config={:?}", config);
826
827 // Disable peripheral for configuration
828 self.info.regs.cr1().modify(|reg| reg.set_pe(false));
829
830 // Configure slave addresses
831 self.apply_address_configuration(config);
832
833 // Enable peripheral with slave settings
834 self.info.regs.cr1().modify(|reg| {
835 reg.set_pe(true);
836 reg.set_ack(true); // Enable acknowledgment for slave mode
837 reg.set_nostretch(false); // Allow clock stretching for processing time
838 });
839
840 trace!("I2C slave: initialization complete");
841 }
842
843 /// Apply the complete address configuration for slave mode
844 fn apply_address_configuration(&mut self, config: SlaveAddrConfig) {
845 match config.addr {
846 OwnAddresses::OA1(addr) => {
847 self.configure_primary_address(addr);
848 self.disable_secondary_address();
849 }
850 OwnAddresses::OA2(oa2) => {
851 self.configure_default_primary_address();
852 self.configure_secondary_address(oa2.addr); // v1 ignores mask
853 }
854 OwnAddresses::Both { oa1, oa2 } => {
855 self.configure_primary_address(oa1);
856 self.configure_secondary_address(oa2.addr); // v1 ignores mask
857 }
858 }
859
860 // Configure general call detection
861 if config.general_call {
862 self.info.regs.cr1().modify(|w| w.set_engc(true));
863 }
864 }
865
866 /// Configure the primary address (OA1) register
867 fn configure_primary_address(&mut self, addr: Address) {
868 match addr {
869 Address::SevenBit(addr) => {
870 self.info.regs.oar1().write(|reg| {
871 let hw_addr = (addr as u16) << 1; // Address in bits [7:1]
872 reg.set_add(hw_addr);
873 reg.set_addmode(i2c::vals::Addmode::BIT7);
874 });
875 }
876 Address::TenBit(addr) => {
877 self.info.regs.oar1().write(|reg| {
878 reg.set_add(addr);
879 reg.set_addmode(i2c::vals::Addmode::BIT10);
880 });
881 }
882 }
883
884 // Set required bit 14 as per reference manual
885 self.info.regs.oar1().modify(|reg| reg.0 |= 1 << 14);
886 }
887
888 /// Configure the secondary address (OA2) register
889 fn configure_secondary_address(&mut self, addr: u8) {
890 self.info.regs.oar2().write(|reg| {
891 reg.set_add2(addr);
892 reg.set_endual(i2c::vals::Endual::DUAL);
893 });
894 }
895
896 /// Set a default primary address when using OA2-only mode
897 fn configure_default_primary_address(&mut self) {
898 self.info.regs.oar1().write(|reg| {
899 reg.set_add(0); // Reserved address, safe to use
900 reg.set_addmode(i2c::vals::Addmode::BIT7);
901 });
902 self.info.regs.oar1().modify(|reg| reg.0 |= 1 << 14);
903 }
904
905 /// Disable secondary address when not needed
906 fn disable_secondary_address(&mut self) {
907 self.info.regs.oar2().write(|reg| {
908 reg.set_endual(i2c::vals::Endual::SINGLE);
909 });
910 }
911}
912
913impl<'d, M: PeriMode> I2c<'d, M, MultiMaster> {
914 /// Listen for incoming I2C address match and return the command type
915 ///
916 /// This method blocks until the slave address is matched by a master.
917 /// Returns the command type (Read/Write) and the matched address.
918 pub fn blocking_listen(&mut self) -> Result<SlaveCommand, Error> {
919 trace!("I2C slave: starting blocking listen for address match");
920 let result = self.blocking_listen_with_timeout(self.timeout());
921 trace!("I2C slave: blocking listen complete, result={:?}", result);
922 result
923 }
924
925 /// Respond to a master read request by transmitting data
926 ///
927 /// Sends the provided data to the master. If the master requests more bytes
928 /// than available, padding bytes (0x00) are sent until the master terminates
929 /// the transaction with NACK.
930 ///
931 /// Returns the total number of bytes transmitted (including padding).
932 pub fn blocking_respond_to_read(&mut self, data: &[u8]) -> Result<usize, Error> {
933 trace!("I2C slave: starting blocking respond_to_read, data_len={}", data.len());
934
935 if let Some(zero_length_result) = self.detect_zero_length_read(self.timeout())? {
936 trace!("I2C slave: zero-length read detected");
937 return Ok(zero_length_result);
938 }
939
940 let result = self.transmit_to_master(data, self.timeout());
941 trace!("I2C slave: blocking respond_to_read complete, result={:?}", result);
942 result
943 }
944
945 /// Respond to a master write request by receiving data
946 ///
947 /// Receives data from the master into the provided buffer. If the master
948 /// sends more bytes than the buffer can hold, excess bytes are acknowledged
949 /// but discarded.
950 ///
951 /// Returns the number of bytes stored in the buffer (not total received).
952 pub fn blocking_respond_to_write(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
953 trace!(
954 "I2C slave: starting blocking respond_to_write, buffer_len={}",
955 buffer.len()
956 );
957 let result = self.receive_from_master(buffer, self.timeout());
958 trace!("I2C slave: blocking respond_to_write complete, result={:?}", result);
959 result
960 }
961
962 // Private implementation methods
963
964 /// Wait for address match and determine transaction type
965 fn blocking_listen_with_timeout(&mut self, timeout: Timeout) -> Result<SlaveCommand, Error> {
966 // Ensure interrupts are disabled for blocking operation
967 self.disable_i2c_interrupts();
968
969 // Wait for address match (ADDR flag)
970 loop {
971 let sr1 = Self::read_status_and_handle_errors(self.info)?;
972
973 if sr1.addr() {
974 // Address matched - read SR2 to get direction and clear ADDR flag
975 let sr2 = self.info.regs.sr2().read();
976 let direction = if sr2.tra() {
977 SlaveCommandKind::Read
978 } else {
979 SlaveCommandKind::Write
980 };
981
982 // Use the static method instead of the instance method
983 let matched_address = Self::decode_matched_address(sr2, self.info)?;
984 trace!(
985 "I2C slave: address matched, direction={:?}, addr={:?}",
986 direction, matched_address
987 );
988
989 return Ok(SlaveCommand {
990 kind: direction,
991 address: matched_address,
992 });
993 }
994
995 timeout.check()?;
996 }
997 }
998
999 /// Transmit data to master in response to read request
1000 fn transmit_to_master(&mut self, data: &[u8], timeout: Timeout) -> Result<usize, Error> {
1001 let mut bytes_transmitted = 0;
1002 let mut padding_count = 0;
1003
1004 loop {
1005 let byte_to_send = if bytes_transmitted < data.len() {
1006 data[bytes_transmitted]
1007 } else {
1008 padding_count += 1;
1009 0x00 // Send padding bytes when data is exhausted
1010 };
1011
1012 match self.transmit_byte(byte_to_send, timeout)? {
1013 TransmitResult::Acknowledged => {
1014 bytes_transmitted += 1;
1015 }
1016 TransmitResult::NotAcknowledged => {
1017 bytes_transmitted += 1; // Count the NACKed byte
1018 break;
1019 }
1020 TransmitResult::Stopped | TransmitResult::Restarted => {
1021 break;
1022 }
1023 }
1024 }
1025
1026 if padding_count > 0 {
1027 trace!(
1028 "I2C slave: sent {} data bytes + {} padding bytes = {} total",
1029 data.len(),
1030 padding_count,
1031 bytes_transmitted
1032 );
1033 }
1034
1035 Ok(bytes_transmitted)
1036 }
1037
1038 /// Receive data from master during write request
1039 fn receive_from_master(&mut self, buffer: &mut [u8], timeout: Timeout) -> Result<usize, Error> {
1040 let mut bytes_stored = 0;
1041
1042 // Receive bytes that fit in buffer
1043 while bytes_stored < buffer.len() {
1044 match self.receive_byte(timeout)? {
1045 ReceiveResult::Data(byte) => {
1046 buffer[bytes_stored] = byte;
1047 bytes_stored += 1;
1048 }
1049 ReceiveResult::Stopped | ReceiveResult::Restarted => {
1050 return Ok(bytes_stored);
1051 }
1052 }
1053 }
1054
1055 // Handle buffer overflow by discarding excess bytes
1056 if bytes_stored == buffer.len() {
1057 trace!("I2C slave: buffer full, discarding excess bytes");
1058 self.discard_excess_bytes(timeout)?;
1059 }
1060
1061 Ok(bytes_stored)
1062 }
1063
1064 /// Detect zero-length read pattern early
1065 ///
1066 /// Zero-length reads occur when a master sends START+ADDR+R followed immediately
1067 /// by NACK+STOP without wanting any data. This must be detected before attempting
1068 /// to transmit any bytes to avoid SDA line issues.
1069 fn detect_zero_length_read(&mut self, _timeout: Timeout) -> Result<Option<usize>, Error> {
1070 // Quick check for immediate termination signals
1071 let sr1 = self.info.regs.sr1().read();
1072
1073 // Check for immediate NACK (fastest zero-length pattern)
1074 if sr1.af() {
1075 self.clear_acknowledge_failure();
1076 return Ok(Some(0));
1077 }
1078
1079 // Check for immediate STOP (alternative zero-length pattern)
1080 if sr1.stopf() {
1081 Self::clear_stop_flag(self.info);
1082 return Ok(Some(0));
1083 }
1084
1085 // Give a brief window for master to send termination signals
1086 // This handles masters that have slight delays between address ACK and NACK
1087 const ZERO_LENGTH_DETECTION_CYCLES: u32 = 20; // ~5-10µs window
1088
1089 for _ in 0..ZERO_LENGTH_DETECTION_CYCLES {
1090 let sr1 = self.info.regs.sr1().read();
1091
1092 // Immediate NACK indicates zero-length read
1093 if sr1.af() {
1094 self.clear_acknowledge_failure();
1095 return Ok(Some(0));
1096 }
1097
1098 // Immediate STOP indicates zero-length read
1099 if sr1.stopf() {
1100 Self::clear_stop_flag(self.info);
1101 return Ok(Some(0));
1102 }
1103
1104 // If TXE becomes ready, master is waiting for data - not zero-length
1105 if sr1.txe() {
1106 return Ok(None); // Proceed with normal transmission
1107 }
1108
1109 // If RESTART detected, handle as zero-length
1110 if sr1.addr() {
1111 return Ok(Some(0));
1112 }
1113 }
1114
1115 // No zero-length pattern detected within the window
1116 Ok(None)
1117 }
1118
1119 /// Discard excess bytes when buffer is full
1120 fn discard_excess_bytes(&mut self, timeout: Timeout) -> Result<(), Error> {
1121 let mut discarded_count = 0;
1122
1123 loop {
1124 match self.receive_byte(timeout)? {
1125 ReceiveResult::Data(_) => {
1126 discarded_count += 1;
1127 continue;
1128 }
1129 ReceiveResult::Stopped | ReceiveResult::Restarted => {
1130 if discarded_count > 0 {
1131 trace!("I2C slave: discarded {} excess bytes", discarded_count);
1132 }
1133 break;
1134 }
1135 }
1136 }
1137 Ok(())
1138 }
1139
1140 /// Send a single byte and wait for master's response
1141 fn transmit_byte(&mut self, byte: u8, timeout: Timeout) -> Result<TransmitResult, Error> {
1142 // Wait for transmit buffer ready
1143 self.wait_for_transmit_ready(timeout)?;
1144
1145 // Send the byte
1146 self.info.regs.dr().write(|w| w.set_dr(byte));
1147
1148 // Wait for transmission completion or master response
1149 self.wait_for_transmit_completion(timeout)
1150 }
1151
1152 /// Wait until transmit buffer is ready (TXE flag set)
1153 fn wait_for_transmit_ready(&mut self, timeout: Timeout) -> Result<(), Error> {
1154 loop {
1155 let sr1 = Self::read_status_and_handle_errors(self.info)?;
1156
1157 // Check for early termination conditions
1158 if let Some(result) = Self::check_early_termination(sr1) {
1159 return Err(self.handle_early_termination(result));
1160 }
1161
1162 if sr1.txe() {
1163 return Ok(()); // Ready to transmit
1164 }
1165
1166 timeout.check()?;
1167 }
1168 }
1169
1170 /// Wait for byte transmission completion or master response
1171 fn wait_for_transmit_completion(&mut self, timeout: Timeout) -> Result<TransmitResult, Error> {
1172 loop {
1173 let sr1 = self.info.regs.sr1().read();
1174
1175 // Check flags in priority order
1176 if sr1.af() {
1177 self.clear_acknowledge_failure();
1178 return Ok(TransmitResult::NotAcknowledged);
1179 }
1180
1181 if sr1.btf() {
1182 return Ok(TransmitResult::Acknowledged);
1183 }
1184
1185 if sr1.stopf() {
1186 Self::clear_stop_flag(self.info);
1187 return Ok(TransmitResult::Stopped);
1188 }
1189
1190 if sr1.addr() {
1191 return Ok(TransmitResult::Restarted);
1192 }
1193
1194 // Check for other error conditions
1195 self.check_for_hardware_errors(sr1)?;
1196
1197 timeout.check()?;
1198 }
1199 }
1200
1201 /// Receive a single byte or detect transaction termination
1202 fn receive_byte(&mut self, timeout: Timeout) -> Result<ReceiveResult, Error> {
1203 loop {
1204 let sr1 = Self::read_status_and_handle_errors(self.info)?;
1205
1206 // Check for received data first (prioritize data over control signals)
1207 if sr1.rxne() {
1208 let byte = self.info.regs.dr().read().dr();
1209 return Ok(ReceiveResult::Data(byte));
1210 }
1211
1212 // Check for transaction termination
1213 if sr1.addr() {
1214 return Ok(ReceiveResult::Restarted);
1215 }
1216
1217 if sr1.stopf() {
1218 Self::clear_stop_flag(self.info);
1219 return Ok(ReceiveResult::Stopped);
1220 }
1221
1222 timeout.check()?;
1223 }
1224 }
1225
1226 /// Determine which slave address was matched based on SR2 flags
1227 fn decode_matched_address(sr2: i2c::regs::Sr2, info: &'static Info) -> Result<Address, Error> {
1228 if sr2.gencall() {
1229 Ok(Address::SevenBit(0x00)) // General call address
1230 } else if sr2.dualf() {
1231 // OA2 (secondary address) was matched
1232 let oar2 = info.regs.oar2().read();
1233 if oar2.endual() != i2c::vals::Endual::DUAL {
1234 return Err(Error::Bus); // Hardware inconsistency
1235 }
1236 Ok(Address::SevenBit(oar2.add2()))
1237 } else {
1238 // OA1 (primary address) was matched
1239 let oar1 = info.regs.oar1().read();
1240 match oar1.addmode() {
1241 i2c::vals::Addmode::BIT7 => {
1242 let addr = (oar1.add() >> 1) as u8;
1243 Ok(Address::SevenBit(addr))
1244 }
1245 i2c::vals::Addmode::BIT10 => Ok(Address::TenBit(oar1.add())),
1246 }
1247 }
1248 }
1249
1250 // Helper methods for hardware interaction
1251
1252 /// Read status register and handle I2C errors (except NACK in slave mode)
1253 fn read_status_and_handle_errors(info: &'static Info) -> Result<i2c::regs::Sr1, Error> {
1254 match Self::check_and_clear_error_flags(info) {
1255 Ok(sr1) => Ok(sr1),
1256 Err(Error::Nack) => {
1257 // In slave mode, NACK is normal protocol behavior, not an error
1258 Ok(info.regs.sr1().read())
1259 }
1260 Err(other_error) => Err(other_error),
1261 }
1262 }
1263
1264 /// Check for conditions that cause early termination of operations
1265 fn check_early_termination(sr1: i2c::regs::Sr1) -> Option<TransmitResult> {
1266 if sr1.stopf() {
1267 Some(TransmitResult::Stopped)
1268 } else if sr1.addr() {
1269 Some(TransmitResult::Restarted)
1270 } else if sr1.af() {
1271 Some(TransmitResult::NotAcknowledged)
1272 } else {
1273 None
1274 }
1275 }
1276
1277 /// Convert early termination to appropriate error
1278 fn handle_early_termination(&mut self, result: TransmitResult) -> Error {
1279 match result {
1280 TransmitResult::Stopped => {
1281 Self::clear_stop_flag(self.info);
1282 Error::Bus // Unexpected STOP during setup
1283 }
1284 TransmitResult::Restarted => {
1285 Error::Bus // Unexpected RESTART during setup
1286 }
1287 TransmitResult::NotAcknowledged => {
1288 self.clear_acknowledge_failure();
1289 Error::Bus // Unexpected NACK during setup
1290 }
1291 TransmitResult::Acknowledged => {
1292 unreachable!() // This should never be passed to this function
1293 }
1294 }
1295 }
1296
1297 /// Check for hardware-level I2C errors during transmission
1298 fn check_for_hardware_errors(&self, sr1: i2c::regs::Sr1) -> Result<(), Error> {
1299 if sr1.timeout() || sr1.ovr() || sr1.arlo() || sr1.berr() {
1300 // Delegate to existing error handling
1301 Self::check_and_clear_error_flags(self.info)?;
1302 }
1303 Ok(())
1304 }
1305
1306 /// Disable I2C event and error interrupts for blocking operations
1307 fn disable_i2c_interrupts(&mut self) {
1308 self.info.regs.cr2().modify(|w| {
1309 w.set_itevten(false);
1310 w.set_iterren(false);
1311 });
1312 }
1313
1314 /// Clear the acknowledge failure flag
1315 fn clear_acknowledge_failure(&mut self) {
1316 self.info.regs.sr1().write(|reg| {
1317 reg.0 = !0;
1318 reg.set_af(false);
1319 });
1320 }
1321
1322 /// Configure DMA settings for slave operations (shared between read/write)
1323 fn setup_slave_dma_base(&mut self) {
1324 self.info.regs.cr2().modify(|w| {
1325 w.set_itbufen(false); // Always disable buffer interrupts when using DMA
1326 w.set_dmaen(true); // Enable DMA requests
1327 w.set_last(false); // LAST bit not used in slave mode for v1 hardware
1328 });
1329 }
1330
1331 /// Disable DMA and interrupts in a critical section
1332 fn disable_dma_and_interrupts(info: &'static Info) {
1333 critical_section::with(|_| {
1334 info.regs.cr2().modify(|w| {
1335 w.set_dmaen(false);
1336 w.set_iterren(false);
1337 w.set_itevten(false);
1338 });
1339 });
1340 }
1341
1342 /// Check for early termination conditions during slave operations
1343 /// Returns Some(result) if termination detected, None to continue
1344 fn check_slave_termination_conditions(sr1: i2c::regs::Sr1) -> Option<SlaveTermination> {
1345 if sr1.stopf() {
1346 Some(SlaveTermination::Stop)
1347 } else if sr1.addr() {
1348 Some(SlaveTermination::Restart)
1349 } else if sr1.af() {
1350 Some(SlaveTermination::Nack)
1351 } else {
1352 None
1353 }
1354 }
1355}
1356
1357impl<'d> I2c<'d, Async, MultiMaster> {
1358 /// Async listen for incoming I2C messages using interrupts
1359 ///
1360 /// Waits for a master to address this slave and returns the command type
1361 /// (Read/Write) and the matched address. This method will suspend until
1362 /// an address match occurs.
1363 pub async fn listen(&mut self) -> Result<SlaveCommand, Error> {
1364 let _scoped_block_stop = self.info.rcc.block_stop();
1365 trace!("I2C slave: starting async listen for address match");
1366 let state = self.state;
1367 let info = self.info;
1368
1369 Self::enable_interrupts(info);
1370
1371 let on_drop = OnDrop::new(|| {
1372 Self::disable_dma_and_interrupts(info);
1373 });
1374
1375 let result = poll_fn(|cx| {
1376 state.waker.register(cx.waker());
1377
1378 match Self::check_and_clear_error_flags(info) {
1379 Err(e) => {
1380 error!("I2C slave: error during listen: {:?}", e);
1381 Poll::Ready(Err(e))
1382 }
1383 Ok(sr1) => {
1384 if sr1.addr() {
1385 let sr2 = info.regs.sr2().read();
1386 let direction = if sr2.tra() {
1387 SlaveCommandKind::Read
1388 } else {
1389 SlaveCommandKind::Write
1390 };
1391
1392 let matched_address = match Self::decode_matched_address(sr2, info) {
1393 Ok(addr) => {
1394 trace!("I2C slave: address matched, direction={:?}, addr={:?}", direction, addr);
1395 addr
1396 }
1397 Err(e) => {
1398 error!("I2C slave: failed to decode matched address: {:?}", e);
1399 return Poll::Ready(Err(e));
1400 }
1401 };
1402
1403 Poll::Ready(Ok(SlaveCommand {
1404 kind: direction,
1405 address: matched_address,
1406 }))
1407 } else {
1408 Self::enable_interrupts(info);
1409 Poll::Pending
1410 }
1411 }
1412 }
1413 })
1414 .await;
1415
1416 drop(on_drop);
1417 trace!("I2C slave: listen complete, result={:?}", result);
1418 result
1419 }
1420
1421 /// Async respond to write command using RX DMA
1422 ///
1423 /// Receives data from the master into the provided buffer using DMA.
1424 /// If the master sends more bytes than the buffer can hold, excess bytes
1425 /// are acknowledged but discarded to prevent interrupt flooding.
1426 ///
1427 /// Returns the number of bytes stored in the buffer (not total received).
1428 pub async fn respond_to_write(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
1429 let _scoped_block_stop = self.info.rcc.block_stop();
1430 trace!("I2C slave: starting respond_to_write, buffer_len={}", buffer.len());
1431
1432 if buffer.is_empty() {
1433 warn!("I2C slave: respond_to_write called with empty buffer");
1434 return Err(Error::Overrun);
1435 }
1436
1437 let state = self.state;
1438 let info = self.info;
1439
1440 self.setup_slave_dma_base();
1441
1442 let on_drop = OnDrop::new(|| {
1443 Self::disable_dma_and_interrupts(info);
1444 });
1445
1446 info.regs.sr2().read();
1447
1448 let result = self.execute_slave_receive_transfer(buffer, state, info).await;
1449
1450 drop(on_drop);
1451 trace!("I2C slave: respond_to_write complete, result={:?}", result);
1452 result
1453 }
1454
1455 /// Async respond to read command using TX DMA
1456 ///
1457 /// Transmits data to the master using DMA. If the master requests more bytes
1458 /// than available in the data buffer, padding bytes (0x00) are sent until
1459 /// the master terminates the transaction with NACK, STOP, or RESTART.
1460 ///
1461 /// Returns the total number of bytes transmitted (data + padding).
1462 pub async fn respond_to_read(&mut self, data: &[u8]) -> Result<usize, Error> {
1463 let _scoped_block_stop = self.info.rcc.block_stop();
1464 trace!("I2C slave: starting respond_to_read, data_len={}", data.len());
1465
1466 if data.is_empty() {
1467 warn!("I2C slave: respond_to_read called with empty data");
1468 return Err(Error::Overrun);
1469 }
1470
1471 let state = self.state;
1472 let info = self.info;
1473
1474 self.setup_slave_dma_base();
1475
1476 let on_drop = OnDrop::new(|| {
1477 Self::disable_dma_and_interrupts(info);
1478 });
1479
1480 info.regs.sr2().read();
1481
1482 let result = self.execute_slave_transmit_transfer(data, state, info).await;
1483
1484 drop(on_drop);
1485 trace!("I2C slave: respond_to_read complete, result={:?}", result);
1486 result
1487 }
1488
1489 // === Private Transfer Execution Methods ===
1490
1491 /// Execute complete slave receive transfer with excess byte handling
1492 async fn execute_slave_receive_transfer(
1493 &mut self,
1494 buffer: &mut [u8],
1495 state: &'static State,
1496 info: &'static Info,
1497 ) -> Result<usize, Error> {
1498 let dma_transfer = unsafe {
1499 let src = info.regs.dr().as_ptr() as *mut u8;
1500 self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default())
1501 };
1502
1503 let i2c_monitor =
1504 Self::create_termination_monitor(state, info, &[SlaveTermination::Stop, SlaveTermination::Restart]);
1505
1506 match select(dma_transfer, i2c_monitor).await {
1507 Either::Second(Err(e)) => {
1508 error!("I2C slave: error during receive transfer: {:?}", e);
1509 Self::disable_dma_and_interrupts(info);
1510 Err(e)
1511 }
1512 Either::First(_) => {
1513 trace!("I2C slave: DMA receive completed, handling excess bytes");
1514 Self::disable_dma_and_interrupts(info);
1515 self.handle_excess_bytes(state, info).await?;
1516 Ok(buffer.len())
1517 }
1518 Either::Second(Ok(termination)) => {
1519 trace!("I2C slave: receive terminated by I2C event: {:?}", termination);
1520 Self::disable_dma_and_interrupts(info);
1521 Ok(buffer.len())
1522 }
1523 }
1524 }
1525
1526 /// Execute complete slave transmit transfer with padding byte handling
1527 async fn execute_slave_transmit_transfer(
1528 &mut self,
1529 data: &[u8],
1530 state: &'static State,
1531 info: &'static Info,
1532 ) -> Result<usize, Error> {
1533 let dma_transfer = unsafe {
1534 let dst = info.regs.dr().as_ptr() as *mut u8;
1535 self.tx_dma.as_mut().unwrap().write(data, dst, Default::default())
1536 };
1537
1538 let i2c_monitor = Self::create_termination_monitor(
1539 state,
1540 info,
1541 &[
1542 SlaveTermination::Stop,
1543 SlaveTermination::Restart,
1544 SlaveTermination::Nack,
1545 ],
1546 );
1547
1548 match select(dma_transfer, i2c_monitor).await {
1549 Either::Second(Err(e)) => {
1550 error!("I2C slave: error during transmit transfer: {:?}", e);
1551 Self::disable_dma_and_interrupts(info);
1552 Err(e)
1553 }
1554 Either::First(_) => {
1555 trace!("I2C slave: DMA transmit completed, handling padding bytes");
1556 Self::disable_dma_and_interrupts(info);
1557 let padding_count = self.handle_padding_bytes(state, info).await?;
1558 let total_bytes = data.len() + padding_count;
1559 trace!(
1560 "I2C slave: sent {} data bytes + {} padding bytes = {} total",
1561 data.len(),
1562 padding_count,
1563 total_bytes
1564 );
1565 Ok(total_bytes)
1566 }
1567 Either::Second(Ok(termination)) => {
1568 trace!("I2C slave: transmit terminated by I2C event: {:?}", termination);
1569 Self::disable_dma_and_interrupts(info);
1570 Ok(data.len())
1571 }
1572 }
1573 }
1574
1575 /// Create a future that monitors for specific slave termination conditions
1576 fn create_termination_monitor(
1577 state: &'static State,
1578 info: &'static Info,
1579 allowed_terminations: &'static [SlaveTermination],
1580 ) -> impl Future<Output = Result<SlaveTermination, Error>> {
1581 poll_fn(move |cx| {
1582 state.waker.register(cx.waker());
1583
1584 match Self::check_and_clear_error_flags(info) {
1585 Err(Error::Nack) if allowed_terminations.contains(&SlaveTermination::Nack) => {
1586 Poll::Ready(Ok(SlaveTermination::Nack))
1587 }
1588 Err(e) => Poll::Ready(Err(e)),
1589 Ok(sr1) => {
1590 if let Some(termination) = Self::check_slave_termination_conditions(sr1) {
1591 if allowed_terminations.contains(&termination) {
1592 // Handle the specific termination condition
1593 match termination {
1594 SlaveTermination::Stop => Self::clear_stop_flag(info),
1595 SlaveTermination::Nack => {
1596 info.regs.sr1().write(|reg| {
1597 reg.0 = !0;
1598 reg.set_af(false);
1599 });
1600 }
1601 SlaveTermination::Restart => {
1602 // ADDR flag will be handled by next listen() call
1603 }
1604 }
1605 Poll::Ready(Ok(termination))
1606 } else {
1607 // Unexpected termination condition
1608 Poll::Ready(Err(Error::Bus))
1609 }
1610 } else {
1611 Self::enable_interrupts(info);
1612 Poll::Pending
1613 }
1614 }
1615 }
1616 })
1617 }
1618
1619 /// Handle excess bytes after DMA buffer is full
1620 ///
1621 /// Reads and discards bytes until transaction termination to prevent interrupt flooding
1622 async fn handle_excess_bytes(&mut self, state: &'static State, info: &'static Info) -> Result<(), Error> {
1623 let mut discarded_count = 0;
1624
1625 poll_fn(|cx| {
1626 state.waker.register(cx.waker());
1627
1628 match Self::check_and_clear_error_flags(info) {
1629 Err(e) => {
1630 error!("I2C slave: error while discarding excess bytes: {:?}", e);
1631 Poll::Ready(Err(e))
1632 }
1633 Ok(sr1) => {
1634 if let Some(termination) = Self::check_slave_termination_conditions(sr1) {
1635 match termination {
1636 SlaveTermination::Stop => Self::clear_stop_flag(info),
1637 SlaveTermination::Restart => {}
1638 SlaveTermination::Nack => unreachable!("NACK not expected during receive"),
1639 }
1640 if discarded_count > 0 {
1641 trace!("I2C slave: discarded {} excess bytes", discarded_count);
1642 }
1643 return Poll::Ready(Ok(()));
1644 }
1645
1646 if sr1.rxne() {
1647 let _discarded_byte = info.regs.dr().read().dr();
1648 discarded_count += 1;
1649 Self::enable_interrupts(info);
1650 return Poll::Pending;
1651 }
1652
1653 Self::enable_interrupts(info);
1654 Poll::Pending
1655 }
1656 }
1657 })
1658 .await
1659 }
1660
1661 /// Handle padding bytes after DMA data is exhausted
1662 ///
1663 /// Sends 0x00 bytes until transaction termination to prevent interrupt flooding
1664 async fn handle_padding_bytes(&mut self, state: &'static State, info: &'static Info) -> Result<usize, Error> {
1665 let mut padding_count = 0;
1666
1667 poll_fn(|cx| {
1668 state.waker.register(cx.waker());
1669
1670 match Self::check_and_clear_error_flags(info) {
1671 Err(Error::Nack) => Poll::Ready(Ok(padding_count)),
1672 Err(e) => {
1673 error!("I2C slave: error while sending padding bytes: {:?}", e);
1674 Poll::Ready(Err(e))
1675 }
1676 Ok(sr1) => {
1677 if let Some(termination) = Self::check_slave_termination_conditions(sr1) {
1678 match termination {
1679 SlaveTermination::Stop => Self::clear_stop_flag(info),
1680 SlaveTermination::Restart => {}
1681 SlaveTermination::Nack => {
1682 info.regs.sr1().write(|reg| {
1683 reg.0 = !0;
1684 reg.set_af(false);
1685 });
1686 }
1687 }
1688 return Poll::Ready(Ok(padding_count));
1689 }
1690
1691 if sr1.txe() {
1692 info.regs.dr().write(|w| w.set_dr(0x00));
1693 padding_count += 1;
1694 Self::enable_interrupts(info);
1695 return Poll::Pending;
1696 }
1697
1698 Self::enable_interrupts(info);
1699 Poll::Pending
1700 }
1701 }
1702 })
1703 .await
1704 }
1705}
1706
1707/// Timing configuration for I2C v1 hardware
1708///
1709/// This struct encapsulates the complex timing calculations required for STM32 I2C v1
1710/// peripherals, which use three separate registers (CR2.FREQ, CCR, TRISE) instead of
1711/// the unified TIMINGR register found in v2 hardware.
732struct Timings { 1712struct Timings {
733 freq: u8, 1713 freq: u8, // APB frequency in MHz for CR2.FREQ register
734 mode: Mode, 1714 mode: Mode, // Standard or Fast mode selection
735 trise: u8, 1715 trise: u8, // Rise time compensation value
736 ccr: u16, 1716 ccr: u16, // Clock control register value
737 duty: Duty, 1717 duty: Duty, // Fast mode duty cycle selection
738} 1718}
739 1719
740impl Timings { 1720impl Timings {
@@ -762,11 +1742,7 @@ impl Timings {
762 mode = Mode::Standard; 1742 mode = Mode::Standard;
763 ccr = { 1743 ccr = {
764 let ccr = clock / (frequency * 2); 1744 let ccr = clock / (frequency * 2);
765 if ccr < 4 { 1745 if ccr < 4 { 4 } else { ccr }
766 4
767 } else {
768 ccr
769 }
770 }; 1746 };
771 } else { 1747 } else {
772 const DUTYCYCLE: u8 = 0; 1748 const DUTYCYCLE: u8 = 0;
@@ -775,14 +1751,10 @@ impl Timings {
775 duty = Duty::Duty2_1; 1751 duty = Duty::Duty2_1;
776 ccr = clock / (frequency * 3); 1752 ccr = clock / (frequency * 3);
777 ccr = if ccr < 1 { 1 } else { ccr }; 1753 ccr = if ccr < 1 { 1 } else { ccr };
778
779 // Set clock to fast mode with appropriate parameters for selected speed (2:1 duty cycle)
780 } else { 1754 } else {
781 duty = Duty::Duty16_9; 1755 duty = Duty::Duty16_9;
782 ccr = clock / (frequency * 25); 1756 ccr = clock / (frequency * 25);
783 ccr = if ccr < 1 { 1 } else { ccr }; 1757 ccr = if ccr < 1 { 1 } else { ccr };
784
785 // Set clock to fast mode with appropriate parameters for selected speed (16:9 duty cycle)
786 } 1758 }
787 } 1759 }
788 1760
@@ -792,11 +1764,6 @@ impl Timings {
792 ccr: ccr as u16, 1764 ccr: ccr as u16,
793 duty, 1765 duty,
794 mode, 1766 mode,
795 //prescale: presc_reg,
796 //scll,
797 //sclh,
798 //sdadel,
799 //scldel,
800 } 1767 }
801 } 1768 }
802} 1769}
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 0bfc795ac..fe7782a7c 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -2,7 +2,7 @@ use core::cmp;
2use core::future::poll_fn; 2use core::future::poll_fn;
3use core::task::Poll; 3use core::task::Poll;
4 4
5use config::{Address, OwnAddresses, OA2}; 5use config::{Address, OA2, OwnAddresses};
6use embassy_embedded_hal::SetConfig; 6use embassy_embedded_hal::SetConfig;
7use embassy_hal_internal::drop::OnDrop; 7use embassy_hal_internal::drop::OnDrop;
8use embedded_hal_1::i2c::Operation; 8use embedded_hal_1::i2c::Operation;
@@ -70,6 +70,11 @@ fn debug_print_interrupts(isr: stm32_metapac::i2c::regs::Isr) {
70} 70}
71 71
72pub(crate) unsafe fn on_interrupt<T: Instance>() { 72pub(crate) unsafe fn on_interrupt<T: Instance>() {
73 // restore the clocks to their last configured state as
74 // much is lost in STOP modes
75 #[cfg(all(feature = "low-power", stm32wlex))]
76 crate::low_power::Executor::on_wakeup_irq_or_event();
77
73 let regs = T::info().regs; 78 let regs = T::info().regs;
74 let isr = regs.isr().read(); 79 let isr = regs.isr().read();
75 80
@@ -93,6 +98,27 @@ pub(crate) unsafe fn on_interrupt<T: Instance>() {
93} 98}
94 99
95impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { 100impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
101 #[inline]
102 fn to_reload(reload: bool) -> i2c::vals::Reload {
103 if reload {
104 i2c::vals::Reload::NOT_COMPLETED
105 } else {
106 i2c::vals::Reload::COMPLETED
107 }
108 }
109
110 /// Calculate total bytes in a group of operations
111 #[inline]
112 fn total_operation_bytes(operations: &[Operation<'_>]) -> usize {
113 operations
114 .iter()
115 .map(|op| match op {
116 Operation::Write(buf) => buf.len(),
117 Operation::Read(buf) => buf.len(),
118 })
119 .sum()
120 }
121
96 pub(crate) fn init(&mut self, config: Config) { 122 pub(crate) fn init(&mut self, config: Config) {
97 self.info.regs.cr1().modify(|reg| { 123 self.info.regs.cr1().modify(|reg| {
98 reg.set_pe(false); 124 reg.set_pe(false);
@@ -142,12 +168,6 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
142 // `buffer`. The START bit can be set even if the bus 168 // `buffer`. The START bit can be set even if the bus
143 // is BUSY or I2C is in slave mode. 169 // is BUSY or I2C is in slave mode.
144 170
145 let reload = if reload {
146 i2c::vals::Reload::NOT_COMPLETED
147 } else {
148 i2c::vals::Reload::COMPLETED
149 };
150
151 info.regs.cr2().modify(|w| { 171 info.regs.cr2().modify(|w| {
152 w.set_sadd(address.addr() << 1); 172 w.set_sadd(address.addr() << 1);
153 w.set_add10(address.add_mode()); 173 w.set_add10(address.add_mode());
@@ -155,7 +175,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
155 w.set_nbytes(length as u8); 175 w.set_nbytes(length as u8);
156 w.set_start(true); 176 w.set_start(true);
157 w.set_autoend(stop.autoend()); 177 w.set_autoend(stop.autoend());
158 w.set_reload(reload); 178 w.set_reload(Self::to_reload(reload));
159 }); 179 });
160 180
161 Ok(()) 181 Ok(())
@@ -167,28 +187,25 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
167 length: usize, 187 length: usize,
168 stop: Stop, 188 stop: Stop,
169 reload: bool, 189 reload: bool,
190 restart: bool,
170 timeout: Timeout, 191 timeout: Timeout,
171 ) -> Result<(), Error> { 192 ) -> Result<(), Error> {
172 assert!(length < 256); 193 assert!(length < 256);
173 194
174 // Wait for any previous address sequence to end 195 if !restart {
175 // automatically. This could be up to 50% of a bus 196 // Wait for any previous address sequence to end
176 // cycle (ie. up to 0.5/freq) 197 // automatically. This could be up to 50% of a bus
177 while info.regs.cr2().read().start() { 198 // cycle (ie. up to 0.5/freq)
178 timeout.check()?; 199 while info.regs.cr2().read().start() {
179 } 200 timeout.check()?;
201 }
180 202
181 // Wait for the bus to be free 203 // Wait for the bus to be free
182 while info.regs.isr().read().busy() { 204 while info.regs.isr().read().busy() {
183 timeout.check()?; 205 timeout.check()?;
206 }
184 } 207 }
185 208
186 let reload = if reload {
187 i2c::vals::Reload::NOT_COMPLETED
188 } else {
189 i2c::vals::Reload::COMPLETED
190 };
191
192 // Set START and prepare to send `bytes`. The 209 // Set START and prepare to send `bytes`. The
193 // START bit can be set even if the bus is BUSY or 210 // START bit can be set even if the bus is BUSY or
194 // I2C is in slave mode. 211 // I2C is in slave mode.
@@ -199,28 +216,36 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
199 w.set_nbytes(length as u8); 216 w.set_nbytes(length as u8);
200 w.set_start(true); 217 w.set_start(true);
201 w.set_autoend(stop.autoend()); 218 w.set_autoend(stop.autoend());
202 w.set_reload(reload); 219 w.set_reload(Self::to_reload(reload));
203 }); 220 });
204 221
205 Ok(()) 222 Ok(())
206 } 223 }
207 224
208 fn reload(info: &'static Info, length: usize, will_reload: bool, timeout: Timeout) -> Result<(), Error> { 225 fn reload(
226 info: &'static Info,
227 length: usize,
228 will_reload: bool,
229 stop: Stop,
230 timeout: Timeout,
231 ) -> Result<(), Error> {
209 assert!(length < 256 && length > 0); 232 assert!(length < 256 && length > 0);
210 233
211 while !info.regs.isr().read().tcr() { 234 // Wait for either TCR (Transfer Complete Reload) or TC (Transfer Complete)
235 // TCR occurs when RELOAD=1, TC occurs when RELOAD=0
236 // Both indicate the peripheral is ready for the next transfer
237 loop {
238 let isr = info.regs.isr().read();
239 if isr.tcr() || isr.tc() {
240 break;
241 }
212 timeout.check()?; 242 timeout.check()?;
213 } 243 }
214 244
215 let will_reload = if will_reload {
216 i2c::vals::Reload::NOT_COMPLETED
217 } else {
218 i2c::vals::Reload::COMPLETED
219 };
220
221 info.regs.cr2().modify(|w| { 245 info.regs.cr2().modify(|w| {
222 w.set_nbytes(length as u8); 246 w.set_nbytes(length as u8);
223 w.set_reload(will_reload); 247 w.set_reload(Self::to_reload(will_reload));
248 w.set_autoend(stop.autoend());
224 }); 249 });
225 250
226 Ok(()) 251 Ok(())
@@ -364,7 +389,9 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
364 loop { 389 loop {
365 let isr = self.info.regs.isr().read(); 390 let isr = self.info.regs.isr().read();
366 self.error_occurred(&isr, timeout)?; 391 self.error_occurred(&isr, timeout)?;
367 if isr.tc() { 392 // Wait for either TC or TCR - both indicate transfer completion
393 // TCR occurs when RELOAD=1, TC occurs when RELOAD=0
394 if isr.tc() || isr.tcr() {
368 return Ok(()); 395 return Ok(());
369 } 396 }
370 timeout.check()?; 397 timeout.check()?;
@@ -391,14 +418,20 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
391 address, 418 address,
392 read.len().min(255), 419 read.len().min(255),
393 Stop::Automatic, 420 Stop::Automatic,
394 last_chunk_idx != 0, 421 last_chunk_idx != 0, // reload
395 restart, 422 restart,
396 timeout, 423 timeout,
397 )?; 424 )?;
398 425
399 for (number, chunk) in read.chunks_mut(255).enumerate() { 426 for (number, chunk) in read.chunks_mut(255).enumerate() {
400 if number != 0 { 427 if number != 0 {
401 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; 428 Self::reload(
429 self.info,
430 chunk.len(),
431 number != last_chunk_idx,
432 Stop::Automatic,
433 timeout,
434 )?;
402 } 435 }
403 436
404 for byte in chunk { 437 for byte in chunk {
@@ -436,6 +469,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
436 write.len().min(255), 469 write.len().min(255),
437 Stop::Software, 470 Stop::Software,
438 last_chunk_idx != 0, 471 last_chunk_idx != 0,
472 false, // restart
439 timeout, 473 timeout,
440 ) { 474 ) {
441 if send_stop { 475 if send_stop {
@@ -446,7 +480,13 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
446 480
447 for (number, chunk) in write.chunks(255).enumerate() { 481 for (number, chunk) in write.chunks(255).enumerate() {
448 if number != 0 { 482 if number != 0 {
449 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; 483 Self::reload(
484 self.info,
485 chunk.len(),
486 number != last_chunk_idx,
487 Stop::Software,
488 timeout,
489 )?;
450 } 490 }
451 491
452 for byte in chunk { 492 for byte in chunk {
@@ -502,9 +542,215 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
502 /// 542 ///
503 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction 543 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
504 pub fn blocking_transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { 544 pub fn blocking_transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
505 let _ = addr; 545 if operations.is_empty() {
506 let _ = operations; 546 return Err(Error::ZeroLengthTransfer);
507 todo!() 547 }
548
549 let address = addr.into();
550 let timeout = self.timeout();
551
552 // Group consecutive operations of the same type
553 let mut op_idx = 0;
554 let mut is_first_group = true;
555
556 while op_idx < operations.len() {
557 // Determine the type of current group and find all consecutive operations of same type
558 let is_read = matches!(operations[op_idx], Operation::Read(_));
559 let group_start = op_idx;
560
561 // Find end of this group (consecutive operations of same type)
562 while op_idx < operations.len() && matches!(operations[op_idx], Operation::Read(_)) == is_read {
563 op_idx += 1;
564 }
565 let group_end = op_idx;
566 let is_last_group = op_idx >= operations.len();
567
568 // Execute this group of operations
569 if is_read {
570 self.execute_read_group(
571 address,
572 &mut operations[group_start..group_end],
573 is_first_group,
574 is_last_group,
575 timeout,
576 )?;
577 } else {
578 self.execute_write_group(
579 address,
580 &operations[group_start..group_end],
581 is_first_group,
582 is_last_group,
583 timeout,
584 )?;
585 }
586
587 is_first_group = false;
588 }
589
590 Ok(())
591 }
592
593 fn execute_write_group(
594 &mut self,
595 address: Address,
596 operations: &[Operation<'_>],
597 is_first_group: bool,
598 is_last_group: bool,
599 timeout: Timeout,
600 ) -> Result<(), Error> {
601 // Calculate total bytes across all operations in this group
602 let total_bytes = Self::total_operation_bytes(operations);
603
604 if total_bytes == 0 {
605 // Handle empty write group - just send address
606 if is_first_group {
607 Self::master_write(self.info, address, 0, Stop::Software, false, !is_first_group, timeout)?;
608 }
609 if is_last_group {
610 self.master_stop();
611 }
612 return Ok(());
613 }
614
615 let mut total_remaining = total_bytes;
616 let mut first_chunk = true;
617
618 for operation in operations {
619 if let Operation::Write(buffer) = operation {
620 for chunk in buffer.chunks(255) {
621 let chunk_len = chunk.len();
622 total_remaining -= chunk_len;
623 let is_last_chunk = total_remaining == 0;
624 let will_reload = !is_last_chunk;
625
626 if first_chunk {
627 // First chunk: initiate transfer
628 // If not first group, use RESTART instead of START
629 Self::master_write(
630 self.info,
631 address,
632 chunk_len,
633 Stop::Software,
634 will_reload,
635 !is_first_group,
636 timeout,
637 )?;
638 first_chunk = false;
639 } else {
640 // Subsequent chunks: use reload
641 // Always use Software stop for writes
642 Self::reload(self.info, chunk_len, will_reload, Stop::Software, timeout)?;
643 }
644
645 // Send data bytes
646 for byte in chunk {
647 self.wait_txis(timeout)?;
648 self.info.regs.txdr().write(|w| w.set_txdata(*byte));
649 }
650 }
651 }
652 }
653
654 // Wait for transfer to complete
655 if is_last_group {
656 self.wait_tc(timeout)?;
657 self.master_stop();
658 self.wait_stop(timeout)?;
659 } else {
660 // Wait for TC before next group (enables RESTART)
661 self.wait_tc(timeout)?;
662 }
663
664 Ok(())
665 }
666
667 fn execute_read_group(
668 &mut self,
669 address: Address,
670 operations: &mut [Operation<'_>],
671 is_first_group: bool,
672 is_last_group: bool,
673 timeout: Timeout,
674 ) -> Result<(), Error> {
675 // Calculate total bytes across all operations in this group
676 let total_bytes = Self::total_operation_bytes(operations);
677
678 if total_bytes == 0 {
679 // Handle empty read group
680 if is_first_group {
681 Self::master_read(
682 self.info,
683 address,
684 0,
685 if is_last_group { Stop::Automatic } else { Stop::Software },
686 false, // reload
687 !is_first_group,
688 timeout,
689 )?;
690 }
691 if is_last_group {
692 self.wait_stop(timeout)?;
693 }
694 return Ok(());
695 }
696
697 let mut total_remaining = total_bytes;
698 let mut first_chunk = true;
699
700 for operation in operations {
701 if let Operation::Read(buffer) = operation {
702 for chunk in buffer.chunks_mut(255) {
703 let chunk_len = chunk.len();
704 total_remaining -= chunk_len;
705 let is_last_chunk = total_remaining == 0;
706 let will_reload = !is_last_chunk;
707
708 if first_chunk {
709 // First chunk: initiate transfer
710 let stop = if is_last_group && is_last_chunk {
711 Stop::Automatic
712 } else {
713 Stop::Software
714 };
715
716 Self::master_read(
717 self.info,
718 address,
719 chunk_len,
720 stop,
721 will_reload,
722 !is_first_group, // restart if not first group
723 timeout,
724 )?;
725 first_chunk = false;
726 } else {
727 // Subsequent chunks: use reload
728 let stop = if is_last_group && is_last_chunk {
729 Stop::Automatic
730 } else {
731 Stop::Software
732 };
733 Self::reload(self.info, chunk_len, will_reload, stop, timeout)?;
734 }
735
736 // Receive data bytes
737 for byte in chunk {
738 self.wait_rxne(timeout)?;
739 *byte = self.info.regs.rxdr().read().rxdata();
740 }
741 }
742 }
743 }
744
745 // Wait for transfer to complete
746 if is_last_group {
747 self.wait_stop(timeout)?;
748 }
749 // For non-last read groups, don't wait for TC - the peripheral may hold SCL low
750 // in Software AUTOEND mode until the next START is issued. Just proceed directly
751 // to the next group which will issue RESTART and release the clock.
752
753 Ok(())
508 } 754 }
509 755
510 /// Blocking write multiple buffers. 756 /// Blocking write multiple buffers.
@@ -526,6 +772,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
526 first_length.min(255), 772 first_length.min(255),
527 Stop::Software, 773 Stop::Software,
528 (first_length > 255) || (last_slice_index != 0), 774 (first_length > 255) || (last_slice_index != 0),
775 false, // restart
529 timeout, 776 timeout,
530 ) { 777 ) {
531 self.master_stop(); 778 self.master_stop();
@@ -547,6 +794,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
547 self.info, 794 self.info,
548 slice_len.min(255), 795 slice_len.min(255),
549 (idx != last_slice_index) || (slice_len > 255), 796 (idx != last_slice_index) || (slice_len > 255),
797 Stop::Software,
550 timeout, 798 timeout,
551 ) { 799 ) {
552 if err != Error::Nack { 800 if err != Error::Nack {
@@ -562,6 +810,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
562 self.info, 810 self.info,
563 chunk.len(), 811 chunk.len(),
564 (number != last_chunk_idx) || (idx != last_slice_index), 812 (number != last_chunk_idx) || (idx != last_slice_index),
813 Stop::Software,
565 timeout, 814 timeout,
566 ) { 815 ) {
567 if err != Error::Nack { 816 if err != Error::Nack {
@@ -605,6 +854,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
605 first_slice: bool, 854 first_slice: bool,
606 last_slice: bool, 855 last_slice: bool,
607 send_stop: bool, 856 send_stop: bool,
857 restart: bool,
608 timeout: Timeout, 858 timeout: Timeout,
609 ) -> Result<(), Error> { 859 ) -> Result<(), Error> {
610 let total_len = write.len(); 860 let total_len = write.len();
@@ -671,10 +921,17 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
671 total_len.min(255), 921 total_len.min(255),
672 Stop::Software, 922 Stop::Software,
673 (total_len > 255) || !last_slice, 923 (total_len > 255) || !last_slice,
924 restart,
674 timeout, 925 timeout,
675 )?; 926 )?;
676 } else { 927 } else {
677 Self::reload(self.info, total_len.min(255), (total_len > 255) || !last_slice, timeout)?; 928 Self::reload(
929 self.info,
930 total_len.min(255),
931 (total_len > 255) || !last_slice,
932 Stop::Software,
933 timeout,
934 )?;
678 self.info.regs.cr1().modify(|w| w.set_tcie(true)); 935 self.info.regs.cr1().modify(|w| w.set_tcie(true));
679 } 936 }
680 } else if !(isr.tcr() || isr.tc()) { 937 } else if !(isr.tcr() || isr.tc()) {
@@ -683,9 +940,13 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
683 } else if remaining_len == 0 { 940 } else if remaining_len == 0 {
684 return Poll::Ready(Ok(())); 941 return Poll::Ready(Ok(()));
685 } else { 942 } else {
686 let last_piece = (remaining_len <= 255) && last_slice; 943 if let Err(e) = Self::reload(
687 944 self.info,
688 if let Err(e) = Self::reload(self.info, remaining_len.min(255), !last_piece, timeout) { 945 remaining_len.min(255),
946 (remaining_len > 255) || !last_slice,
947 Stop::Software,
948 timeout,
949 ) {
689 return Poll::Ready(Err(e)); 950 return Poll::Ready(Err(e));
690 } 951 }
691 self.info.regs.cr1().modify(|w| w.set_tcie(true)); 952 self.info.regs.cr1().modify(|w| w.set_tcie(true));
@@ -697,10 +958,9 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
697 .await?; 958 .await?;
698 959
699 dma_transfer.await; 960 dma_transfer.await;
700 if last_slice { 961
701 // This should be done already 962 // Always wait for TC after DMA completes - needed for consecutive buffers
702 self.wait_tc(timeout)?; 963 self.wait_tc(timeout)?;
703 }
704 964
705 if last_slice & send_stop { 965 if last_slice & send_stop {
706 self.master_stop(); 966 self.master_stop();
@@ -775,7 +1035,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
775 address, 1035 address,
776 total_len.min(255), 1036 total_len.min(255),
777 Stop::Automatic, 1037 Stop::Automatic,
778 total_len > 255, 1038 total_len > 255, // reload
779 restart, 1039 restart,
780 timeout, 1040 timeout,
781 )?; 1041 )?;
@@ -783,12 +1043,10 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
783 return Poll::Ready(Ok(())); 1043 return Poll::Ready(Ok(()));
784 } 1044 }
785 } else if isr.tcr() { 1045 } else if isr.tcr() {
786 // poll_fn was woken without an interrupt present 1046 // Transfer Complete Reload - need to set up next chunk
787 return Poll::Pending;
788 } else {
789 let last_piece = remaining_len <= 255; 1047 let last_piece = remaining_len <= 255;
790 1048
791 if let Err(e) = Self::reload(self.info, remaining_len.min(255), !last_piece, timeout) { 1049 if let Err(e) = Self::reload(self.info, remaining_len.min(255), !last_piece, Stop::Automatic, timeout) {
792 return Poll::Ready(Err(e)); 1050 return Poll::Ready(Err(e));
793 } 1051 }
794 // Return here if we are on last chunk, 1052 // Return here if we are on last chunk,
@@ -797,6 +1055,9 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
797 return Poll::Ready(Ok(())); 1055 return Poll::Ready(Ok(()));
798 } 1056 }
799 self.info.regs.cr1().modify(|w| w.set_tcie(true)); 1057 self.info.regs.cr1().modify(|w| w.set_tcie(true));
1058 } else {
1059 // poll_fn was woken without TCR interrupt
1060 return Poll::Pending;
800 } 1061 }
801 1062
802 remaining_len = remaining_len.saturating_sub(255); 1063 remaining_len = remaining_len.saturating_sub(255);
@@ -814,12 +1075,13 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
814 1075
815 /// Write. 1076 /// Write.
816 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { 1077 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
1078 let _scoped_block_stop = self.info.rcc.block_stop();
817 let timeout = self.timeout(); 1079 let timeout = self.timeout();
818 if write.is_empty() { 1080 if write.is_empty() {
819 self.write_internal(address.into(), write, true, timeout) 1081 self.write_internal(address.into(), write, true, timeout)
820 } else { 1082 } else {
821 timeout 1083 timeout
822 .with(self.write_dma_internal(address.into(), write, true, true, true, timeout)) 1084 .with(self.write_dma_internal(address.into(), write, true, true, true, false, timeout))
823 .await 1085 .await
824 } 1086 }
825 } 1087 }
@@ -828,21 +1090,30 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
828 /// 1090 ///
829 /// The buffers are concatenated in a single write transaction. 1091 /// The buffers are concatenated in a single write transaction.
830 pub async fn write_vectored(&mut self, address: Address, write: &[&[u8]]) -> Result<(), Error> { 1092 pub async fn write_vectored(&mut self, address: Address, write: &[&[u8]]) -> Result<(), Error> {
1093 let _scoped_block_stop = self.info.rcc.block_stop();
831 let timeout = self.timeout(); 1094 let timeout = self.timeout();
832 1095
833 if write.is_empty() { 1096 if write.is_empty() {
834 return Err(Error::ZeroLengthTransfer); 1097 return Err(Error::ZeroLengthTransfer);
835 } 1098 }
836 let mut iter = write.iter();
837 1099
1100 let mut iter = write.iter();
838 let mut first = true; 1101 let mut first = true;
839 let mut current = iter.next(); 1102 let mut current = iter.next();
1103
840 while let Some(c) = current { 1104 while let Some(c) = current {
841 let next = iter.next(); 1105 let next = iter.next();
842 let is_last = next.is_none(); 1106 let is_last = next.is_none();
843 1107
844 let fut = self.write_dma_internal(address, c, first, is_last, is_last, timeout); 1108 let fut = self.write_dma_internal(
1109 address, c, first, // first_slice
1110 is_last, // last_slice
1111 is_last, // send_stop (only on last buffer)
1112 false, // restart (false for all - they're one continuous write)
1113 timeout,
1114 );
845 timeout.with(fut).await?; 1115 timeout.with(fut).await?;
1116
846 first = false; 1117 first = false;
847 current = next; 1118 current = next;
848 } 1119 }
@@ -851,6 +1122,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
851 1122
852 /// Read. 1123 /// Read.
853 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { 1124 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
1125 let _scoped_block_stop = self.info.rcc.block_stop();
854 let timeout = self.timeout(); 1126 let timeout = self.timeout();
855 1127
856 if buffer.is_empty() { 1128 if buffer.is_empty() {
@@ -863,12 +1135,13 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
863 1135
864 /// Write, restart, read. 1136 /// Write, restart, read.
865 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { 1137 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
1138 let _scoped_block_stop = self.info.rcc.block_stop();
866 let timeout = self.timeout(); 1139 let timeout = self.timeout();
867 1140
868 if write.is_empty() { 1141 if write.is_empty() {
869 self.write_internal(address.into(), write, false, timeout)?; 1142 self.write_internal(address.into(), write, false, timeout)?;
870 } else { 1143 } else {
871 let fut = self.write_dma_internal(address.into(), write, true, true, false, timeout); 1144 let fut = self.write_dma_internal(address.into(), write, true, true, false, false, timeout);
872 timeout.with(fut).await?; 1145 timeout.with(fut).await?;
873 } 1146 }
874 1147
@@ -888,9 +1161,299 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
888 /// 1161 ///
889 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction 1162 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
890 pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { 1163 pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
891 let _ = addr; 1164 let _scoped_block_stop = self.info.rcc.block_stop();
892 let _ = operations; 1165 if operations.is_empty() {
893 todo!() 1166 return Err(Error::ZeroLengthTransfer);
1167 }
1168
1169 let address = addr.into();
1170 let timeout = self.timeout();
1171
1172 // Group consecutive operations of the same type
1173 let mut op_idx = 0;
1174 let mut is_first_group = true;
1175
1176 while op_idx < operations.len() {
1177 // Determine the type of current group and find all consecutive operations of same type
1178 let is_read = matches!(operations[op_idx], Operation::Read(_));
1179 let group_start = op_idx;
1180
1181 // Find end of this group (consecutive operations of same type)
1182 while op_idx < operations.len() && matches!(operations[op_idx], Operation::Read(_)) == is_read {
1183 op_idx += 1;
1184 }
1185 let group_end = op_idx;
1186 let is_last_group = op_idx >= operations.len();
1187
1188 // Execute this group of operations
1189 if is_read {
1190 self.execute_read_group_async(
1191 address,
1192 &mut operations[group_start..group_end],
1193 is_first_group,
1194 is_last_group,
1195 timeout,
1196 )
1197 .await?;
1198 } else {
1199 self.execute_write_group_async(
1200 address,
1201 &operations[group_start..group_end],
1202 is_first_group,
1203 is_last_group,
1204 timeout,
1205 )
1206 .await?;
1207 }
1208
1209 is_first_group = false;
1210 }
1211
1212 Ok(())
1213 }
1214
1215 async fn execute_write_group_async(
1216 &mut self,
1217 address: Address,
1218 operations: &[Operation<'_>],
1219 is_first_group: bool,
1220 is_last_group: bool,
1221 timeout: Timeout,
1222 ) -> Result<(), Error> {
1223 // Calculate total bytes across all operations in this group
1224 let total_bytes = Self::total_operation_bytes(operations);
1225
1226 if total_bytes == 0 {
1227 // Handle empty write group using blocking call
1228 if is_first_group {
1229 Self::master_write(self.info, address, 0, Stop::Software, false, !is_first_group, timeout)?;
1230 }
1231 if is_last_group {
1232 self.master_stop();
1233 }
1234 return Ok(());
1235 }
1236
1237 // Collect all write buffers
1238 let mut write_buffers: heapless::Vec<&[u8], 16> = heapless::Vec::new();
1239 for operation in operations {
1240 if let Operation::Write(buffer) = operation {
1241 if !buffer.is_empty() {
1242 let _ = write_buffers.push(buffer);
1243 }
1244 }
1245 }
1246
1247 if write_buffers.is_empty() {
1248 return Ok(());
1249 }
1250
1251 // Send each buffer using DMA
1252 let num_buffers = write_buffers.len();
1253 for (idx, buffer) in write_buffers.iter().enumerate() {
1254 let is_first_buffer = idx == 0;
1255 let is_last_buffer = idx == num_buffers - 1;
1256
1257 let fut = self.write_dma_internal(
1258 address,
1259 buffer,
1260 is_first_buffer, // first_slice
1261 is_last_buffer, // last_slice
1262 is_last_buffer && is_last_group, // send_stop
1263 is_first_buffer && !is_first_group, // restart (only for first buffer if not first group)
1264 timeout,
1265 );
1266 timeout.with(fut).await?;
1267 }
1268
1269 Ok(())
1270 }
1271
1272 async fn execute_read_group_async(
1273 &mut self,
1274 address: Address,
1275 operations: &mut [Operation<'_>],
1276 is_first_group: bool,
1277 is_last_group: bool,
1278 timeout: Timeout,
1279 ) -> Result<(), Error> {
1280 // Calculate total bytes across all operations in this group
1281 let total_bytes = Self::total_operation_bytes(operations);
1282
1283 if total_bytes == 0 {
1284 // Handle empty read group using blocking call
1285 if is_first_group {
1286 Self::master_read(
1287 self.info,
1288 address,
1289 0,
1290 if is_last_group { Stop::Automatic } else { Stop::Software },
1291 false, // reload
1292 !is_first_group,
1293 timeout,
1294 )?;
1295 }
1296 if is_last_group {
1297 self.wait_stop(timeout)?;
1298 }
1299 return Ok(());
1300 }
1301
1302 // Use DMA for read operations - need to handle multiple buffers
1303 let restart = !is_first_group;
1304 let mut total_remaining = total_bytes;
1305 let mut is_first_in_group = true;
1306
1307 for operation in operations {
1308 if let Operation::Read(buffer) = operation {
1309 if buffer.is_empty() {
1310 // Skip empty buffers
1311 continue;
1312 }
1313
1314 let buf_len = buffer.len();
1315 total_remaining -= buf_len;
1316 let is_last_in_group = total_remaining == 0;
1317
1318 // Perform DMA read
1319 if is_first_in_group {
1320 // First buffer: use read_dma_internal which handles restart properly
1321 // Only use Automatic stop if this is the last buffer in the last group
1322 let stop_mode = if is_last_group && is_last_in_group {
1323 Stop::Automatic
1324 } else {
1325 Stop::Software
1326 };
1327
1328 // We need a custom DMA read that respects our stop mode
1329 self.read_dma_group_internal(address, buffer, restart, stop_mode, timeout)
1330 .await?;
1331 is_first_in_group = false;
1332 } else {
1333 // Subsequent buffers: need to reload and continue
1334 let stop_mode = if is_last_group && is_last_in_group {
1335 Stop::Automatic
1336 } else {
1337 Stop::Software
1338 };
1339
1340 self.read_dma_group_internal(
1341 address, buffer, false, // no restart for subsequent buffers in same group
1342 stop_mode, timeout,
1343 )
1344 .await?;
1345 }
1346 }
1347 }
1348
1349 // Wait for transfer to complete
1350 if is_last_group {
1351 self.wait_stop(timeout)?;
1352 }
1353
1354 Ok(())
1355 }
1356
1357 /// Internal DMA read helper for transaction groups
1358 async fn read_dma_group_internal(
1359 &mut self,
1360 address: Address,
1361 buffer: &mut [u8],
1362 restart: bool,
1363 stop_mode: Stop,
1364 timeout: Timeout,
1365 ) -> Result<(), Error> {
1366 let total_len = buffer.len();
1367
1368 let dma_transfer = unsafe {
1369 let regs = self.info.regs;
1370 regs.cr1().modify(|w| {
1371 w.set_rxdmaen(true);
1372 w.set_tcie(true);
1373 w.set_nackie(true);
1374 w.set_errie(true);
1375 });
1376 let src = regs.rxdr().as_ptr() as *mut u8;
1377
1378 self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default())
1379 };
1380
1381 let mut remaining_len = total_len;
1382
1383 let on_drop = OnDrop::new(|| {
1384 let regs = self.info.regs;
1385 regs.cr1().modify(|w| {
1386 w.set_rxdmaen(false);
1387 w.set_tcie(false);
1388 w.set_nackie(false);
1389 w.set_errie(false);
1390 });
1391 regs.icr().write(|w| {
1392 w.set_nackcf(true);
1393 w.set_berrcf(true);
1394 w.set_arlocf(true);
1395 w.set_ovrcf(true);
1396 });
1397 });
1398
1399 poll_fn(|cx| {
1400 self.state.waker.register(cx.waker());
1401
1402 let isr = self.info.regs.isr().read();
1403
1404 if isr.nackf() {
1405 return Poll::Ready(Err(Error::Nack));
1406 }
1407 if isr.arlo() {
1408 return Poll::Ready(Err(Error::Arbitration));
1409 }
1410 if isr.berr() {
1411 return Poll::Ready(Err(Error::Bus));
1412 }
1413 if isr.ovr() {
1414 return Poll::Ready(Err(Error::Overrun));
1415 }
1416
1417 if remaining_len == total_len {
1418 Self::master_read(
1419 self.info,
1420 address,
1421 total_len.min(255),
1422 stop_mode,
1423 total_len > 255, // reload
1424 restart,
1425 timeout,
1426 )?;
1427 if total_len <= 255 {
1428 return Poll::Ready(Ok(()));
1429 }
1430 } else if isr.tcr() {
1431 // Transfer Complete Reload - need to set up next chunk
1432 let last_piece = remaining_len <= 255;
1433
1434 if let Err(e) = Self::reload(self.info, remaining_len.min(255), !last_piece, stop_mode, timeout) {
1435 return Poll::Ready(Err(e));
1436 }
1437 // Return here if we are on last chunk,
1438 // end of transfer will be awaited with the DMA below
1439 if last_piece {
1440 return Poll::Ready(Ok(()));
1441 }
1442 self.info.regs.cr1().modify(|w| w.set_tcie(true));
1443 } else {
1444 // poll_fn was woken without TCR interrupt
1445 return Poll::Pending;
1446 }
1447
1448 remaining_len = remaining_len.saturating_sub(255);
1449 Poll::Pending
1450 })
1451 .await?;
1452
1453 dma_transfer.await;
1454 drop(on_drop);
1455
1456 Ok(())
894 } 1457 }
895} 1458}
896 1459
@@ -1028,7 +1591,13 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
1028 if number == 0 { 1591 if number == 0 {
1029 Self::slave_start(self.info, chunk.len(), number != last_chunk_idx); 1592 Self::slave_start(self.info, chunk.len(), number != last_chunk_idx);
1030 } else { 1593 } else {
1031 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; 1594 Self::reload(
1595 self.info,
1596 chunk.len(),
1597 number != last_chunk_idx,
1598 Stop::Software,
1599 timeout,
1600 )?;
1032 } 1601 }
1033 1602
1034 let mut index = 0; 1603 let mut index = 0;
@@ -1036,7 +1605,8 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
1036 for byte in chunk { 1605 for byte in chunk {
1037 // Wait until we have received something 1606 // Wait until we have received something
1038 match self.wait_rxne(timeout) { 1607 match self.wait_rxne(timeout) {
1039 Ok(ReceiveResult::StopReceived) | Ok(ReceiveResult::NewStart) => { 1608 Ok(ReceiveResult::StopReceived) => {}
1609 Ok(ReceiveResult::NewStart) => {
1040 trace!("--- Slave RX transmission end (early)"); 1610 trace!("--- Slave RX transmission end (early)");
1041 return Ok(total_len - remaining_len); // Return N bytes read 1611 return Ok(total_len - remaining_len); // Return N bytes read
1042 } 1612 }
@@ -1077,7 +1647,13 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
1077 if number == 0 { 1647 if number == 0 {
1078 Self::slave_start(self.info, chunk.len(), number != last_chunk_idx); 1648 Self::slave_start(self.info, chunk.len(), number != last_chunk_idx);
1079 } else { 1649 } else {
1080 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; 1650 Self::reload(
1651 self.info,
1652 chunk.len(),
1653 number != last_chunk_idx,
1654 Stop::Software,
1655 timeout,
1656 )?;
1081 } 1657 }
1082 1658
1083 let mut index = 0; 1659 let mut index = 0;
@@ -1104,42 +1680,50 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
1104 1680
1105 /// Listen for incoming I2C messages. 1681 /// Listen for incoming I2C messages.
1106 /// 1682 ///
1107 /// The listen method is an asynchronous method but it does not require DMA to be asynchronous. 1683 /// This method blocks until the slave address is matched by a master.
1108 pub async fn listen(&mut self) -> Result<SlaveCommand, Error> { 1684 pub fn blocking_listen(&mut self) -> Result<SlaveCommand, Error> {
1109 let state = self.state; 1685 let timeout = self.timeout();
1686
1110 self.info.regs.cr1().modify(|reg| { 1687 self.info.regs.cr1().modify(|reg| {
1111 reg.set_addrie(true); 1688 reg.set_addrie(true);
1112 trace!("Enable ADDRIE"); 1689 trace!("Enable ADDRIE");
1113 }); 1690 });
1114 1691
1115 poll_fn(|cx| { 1692 loop {
1116 state.waker.register(cx.waker());
1117 let isr = self.info.regs.isr().read(); 1693 let isr = self.info.regs.isr().read();
1118 if !isr.addr() { 1694 if isr.addr() {
1119 Poll::Pending 1695 break;
1120 } else {
1121 trace!("ADDR triggered (address match)");
1122 // we do not clear the address flag here as it will be cleared by the dma read/write
1123 // if we clear it here the clock stretching will stop and the master will read in data before the slave is ready to send it
1124 match isr.dir() {
1125 i2c::vals::Dir::WRITE => {
1126 trace!("DIR: write");
1127 Poll::Ready(Ok(SlaveCommand {
1128 kind: SlaveCommandKind::Write,
1129 address: self.determine_matched_address()?,
1130 }))
1131 }
1132 i2c::vals::Dir::READ => {
1133 trace!("DIR: read");
1134 Poll::Ready(Ok(SlaveCommand {
1135 kind: SlaveCommandKind::Read,
1136 address: self.determine_matched_address()?,
1137 }))
1138 }
1139 }
1140 } 1696 }
1141 }) 1697 timeout.check()?;
1142 .await 1698 }
1699
1700 trace!("ADDR triggered (address match)");
1701
1702 // we do not clear the address flag here as it will be cleared by the dma read/write
1703 // if we clear it here the clock stretching will stop and the master will read in data before the slave is ready to send it
1704 self.slave_command()
1705 }
1706
1707 /// Determine the received slave command.
1708 fn slave_command(&self) -> Result<SlaveCommand, Error> {
1709 let isr = self.info.regs.isr().read();
1710
1711 match isr.dir() {
1712 i2c::vals::Dir::WRITE => {
1713 trace!("DIR: write");
1714 Ok(SlaveCommand {
1715 kind: SlaveCommandKind::Write,
1716 address: self.determine_matched_address()?,
1717 })
1718 }
1719 i2c::vals::Dir::READ => {
1720 trace!("DIR: read");
1721 Ok(SlaveCommand {
1722 kind: SlaveCommandKind::Read,
1723 address: self.determine_matched_address()?,
1724 })
1725 }
1726 }
1143 } 1727 }
1144 1728
1145 /// Respond to a write command. 1729 /// Respond to a write command.
@@ -1158,16 +1742,44 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
1158} 1742}
1159 1743
1160impl<'d> I2c<'d, Async, MultiMaster> { 1744impl<'d> I2c<'d, Async, MultiMaster> {
1745 /// Listen for incoming I2C messages.
1746 ///
1747 /// The listen method is an asynchronous method but it does not require DMA to be asynchronous.
1748 pub async fn listen(&mut self) -> Result<SlaveCommand, Error> {
1749 let _scoped_block_stop = self.info.rcc.block_stop();
1750 let state = self.state;
1751 self.info.regs.cr1().modify(|reg| {
1752 reg.set_addrie(true);
1753 trace!("Enable ADDRIE");
1754 });
1755
1756 poll_fn(|cx| {
1757 state.waker.register(cx.waker());
1758 let isr = self.info.regs.isr().read();
1759 if !isr.addr() {
1760 Poll::Pending
1761 } else {
1762 trace!("ADDR triggered (address match)");
1763 // we do not clear the address flag here as it will be cleared by the dma read/write
1764 // if we clear it here the clock stretching will stop and the master will read in data before the slave is ready to send it
1765 Poll::Ready(self.slave_command())
1766 }
1767 })
1768 .await
1769 }
1770
1161 /// Respond to a write command. 1771 /// Respond to a write command.
1162 /// 1772 ///
1163 /// Returns the total number of bytes received. 1773 /// Returns the total number of bytes received.
1164 pub async fn respond_to_write(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { 1774 pub async fn respond_to_write(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
1775 let _scoped_block_stop = self.info.rcc.block_stop();
1165 let timeout = self.timeout(); 1776 let timeout = self.timeout();
1166 timeout.with(self.read_dma_internal_slave(buffer, timeout)).await 1777 timeout.with(self.read_dma_internal_slave(buffer, timeout)).await
1167 } 1778 }
1168 1779
1169 /// Respond to a read request from an I2C master. 1780 /// Respond to a read request from an I2C master.
1170 pub async fn respond_to_read(&mut self, write: &[u8]) -> Result<SendStatus, Error> { 1781 pub async fn respond_to_read(&mut self, write: &[u8]) -> Result<SendStatus, Error> {
1782 let _scoped_block_stop = self.info.rcc.block_stop();
1171 let timeout = self.timeout(); 1783 let timeout = self.timeout();
1172 timeout.with(self.write_dma_internal_slave(write, timeout)).await 1784 timeout.with(self.write_dma_internal_slave(write, timeout)).await
1173 } 1785 }
@@ -1181,7 +1793,7 @@ impl<'d> I2c<'d, Async, MultiMaster> {
1181 1793
1182 let regs = self.info.regs; 1794 let regs = self.info.regs;
1183 1795
1184 let dma_transfer = unsafe { 1796 let mut dma_transfer = unsafe {
1185 regs.cr1().modify(|w| { 1797 regs.cr1().modify(|w| {
1186 w.set_rxdmaen(true); 1798 w.set_rxdmaen(true);
1187 w.set_stopie(true); 1799 w.set_stopie(true);
@@ -1213,13 +1825,20 @@ impl<'d> I2c<'d, Async, MultiMaster> {
1213 Poll::Pending 1825 Poll::Pending
1214 } else if isr.tcr() { 1826 } else if isr.tcr() {
1215 let is_last_slice = remaining_len <= 255; 1827 let is_last_slice = remaining_len <= 255;
1216 if let Err(e) = Self::reload(self.info, remaining_len.min(255), !is_last_slice, timeout) { 1828 if let Err(e) = Self::reload(
1829 self.info,
1830 remaining_len.min(255),
1831 !is_last_slice,
1832 Stop::Software,
1833 timeout,
1834 ) {
1217 return Poll::Ready(Err(e)); 1835 return Poll::Ready(Err(e));
1218 } 1836 }
1219 remaining_len = remaining_len.saturating_sub(255); 1837 remaining_len = remaining_len.saturating_sub(255);
1220 regs.cr1().modify(|w| w.set_tcie(true)); 1838 regs.cr1().modify(|w| w.set_tcie(true));
1221 Poll::Pending 1839 Poll::Pending
1222 } else if isr.stopf() { 1840 } else if isr.stopf() {
1841 remaining_len = remaining_len.saturating_add(dma_transfer.get_remaining_transfers() as usize);
1223 regs.icr().write(|reg| reg.set_stopcf(true)); 1842 regs.icr().write(|reg| reg.set_stopcf(true));
1224 let poll = Poll::Ready(Ok(total_len - remaining_len)); 1843 let poll = Poll::Ready(Ok(total_len - remaining_len));
1225 poll 1844 poll
@@ -1229,6 +1848,7 @@ impl<'d> I2c<'d, Async, MultiMaster> {
1229 }) 1848 })
1230 .await?; 1849 .await?;
1231 1850
1851 dma_transfer.request_pause();
1232 dma_transfer.await; 1852 dma_transfer.await;
1233 1853
1234 drop(on_drop); 1854 drop(on_drop);
@@ -1258,7 +1878,8 @@ impl<'d> I2c<'d, Async, MultiMaster> {
1258 w.set_txdmaen(false); 1878 w.set_txdmaen(false);
1259 w.set_stopie(false); 1879 w.set_stopie(false);
1260 w.set_tcie(false); 1880 w.set_tcie(false);
1261 }) 1881 });
1882 regs.isr().write(|w| w.set_txe(true));
1262 }); 1883 });
1263 1884
1264 let state = self.state; 1885 let state = self.state;
@@ -1274,13 +1895,24 @@ impl<'d> I2c<'d, Async, MultiMaster> {
1274 Poll::Pending 1895 Poll::Pending
1275 } else if isr.tcr() { 1896 } else if isr.tcr() {
1276 let is_last_slice = remaining_len <= 255; 1897 let is_last_slice = remaining_len <= 255;
1277 if let Err(e) = Self::reload(self.info, remaining_len.min(255), !is_last_slice, timeout) { 1898 if let Err(e) = Self::reload(
1899 self.info,
1900 remaining_len.min(255),
1901 !is_last_slice,
1902 Stop::Software,
1903 timeout,
1904 ) {
1278 return Poll::Ready(Err(e)); 1905 return Poll::Ready(Err(e));
1279 } 1906 }
1280 remaining_len = remaining_len.saturating_sub(255); 1907 remaining_len = remaining_len.saturating_sub(255);
1281 self.info.regs.cr1().modify(|w| w.set_tcie(true)); 1908 self.info.regs.cr1().modify(|w| w.set_tcie(true));
1282 Poll::Pending 1909 Poll::Pending
1283 } else if isr.stopf() { 1910 } else if isr.stopf() {
1911 let mut leftover_bytes = dma_transfer.get_remaining_transfers();
1912 if !self.info.regs.isr().read().txe() {
1913 leftover_bytes = leftover_bytes.saturating_add(1);
1914 }
1915 remaining_len = remaining_len.saturating_add(leftover_bytes as usize);
1284 self.info.regs.icr().write(|reg| reg.set_stopcf(true)); 1916 self.info.regs.icr().write(|reg| reg.set_stopcf(true));
1285 if remaining_len > 0 { 1917 if remaining_len > 0 {
1286 dma_transfer.request_pause(); 1918 dma_transfer.request_pause();
@@ -1294,6 +1926,7 @@ impl<'d> I2c<'d, Async, MultiMaster> {
1294 }) 1926 })
1295 .await?; 1927 .await?;
1296 1928
1929 dma_transfer.request_pause();
1297 dma_transfer.await; 1930 dma_transfer.await;
1298 1931
1299 drop(on_drop); 1932 drop(on_drop);