aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-04-04 21:43:21 +0000
committerGitHub <[email protected]>2024-04-04 21:43:21 +0000
commita0439479f70e0d50cc48d0e421a3034932a882b4 (patch)
tree32efa09b6d22f6ac20e625f64c8057b16fb5058d
parent921fa9af80b4f4c8e8c827f4104abceee795b630 (diff)
parent6efac5562ad075f76121970a120e951ee8d2dd30 (diff)
Merge pull request #2742 from sgoll/i2c-async-transaction
stm32/i2c(v1): Implement asynchronous transactions
-rw-r--r--embassy-stm32/src/i2c/mod.rs141
-rw-r--r--embassy-stm32/src/i2c/v1.rs628
-rw-r--r--embassy-stm32/src/i2c/v2.rs15
3 files changed, 414 insertions, 370 deletions
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs
index f1b11cc44..a46061d54 100644
--- a/embassy-stm32/src/i2c/mod.rs
+++ b/embassy-stm32/src/i2c/mod.rs
@@ -6,6 +6,7 @@
6mod _version; 6mod _version;
7 7
8use core::future::Future; 8use core::future::Future;
9use core::iter;
9use core::marker::PhantomData; 10use core::marker::PhantomData;
10 11
11use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; 12use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
@@ -332,8 +333,142 @@ impl<'d, T: Instance, TXDMA: TxDma<T>, RXDMA: RxDma<T>> embedded_hal_async::i2c:
332 address: u8, 333 address: u8,
333 operations: &mut [embedded_hal_1::i2c::Operation<'_>], 334 operations: &mut [embedded_hal_1::i2c::Operation<'_>],
334 ) -> Result<(), Self::Error> { 335 ) -> Result<(), Self::Error> {
335 let _ = address; 336 self.transaction(address, operations).await
336 let _ = operations;
337 todo!()
338 } 337 }
339} 338}
339
340/// Frame type in I2C transaction.
341///
342/// This tells each method what kind of framing to use, to generate a (repeated) start condition (ST
343/// or SR), and/or a stop condition (SP). For read operations, this also controls whether to send an
344/// ACK or NACK after the last byte received.
345///
346/// For write operations, the following options are identical because they differ only in the (N)ACK
347/// treatment relevant for read operations:
348///
349/// - `FirstFrame` and `FirstAndNextFrame`
350/// - `NextFrame` and `LastFrameNoStop`
351///
352/// Abbreviations used below:
353///
354/// - `ST` = start condition
355/// - `SR` = repeated start condition
356/// - `SP` = stop condition
357/// - `ACK`/`NACK` = last byte in read operation
358#[derive(Copy, Clone)]
359#[allow(dead_code)]
360enum FrameOptions {
361 /// `[ST/SR]+[NACK]+[SP]` First frame (of this type) in transaction and also last frame overall.
362 FirstAndLastFrame,
363 /// `[ST/SR]+[NACK]` First frame of this type in transaction, last frame in a read operation but
364 /// not the last frame overall.
365 FirstFrame,
366 /// `[ST/SR]+[ACK]` First frame of this type in transaction, neither last frame overall nor last
367 /// frame in a read operation.
368 FirstAndNextFrame,
369 /// `[ACK]` Middle frame in a read operation (neither first nor last).
370 NextFrame,
371 /// `[NACK]+[SP]` Last frame overall in this transaction but not the first frame.
372 LastFrame,
373 /// `[NACK]` Last frame in a read operation but not last frame overall in this transaction.
374 LastFrameNoStop,
375}
376
377#[allow(dead_code)]
378impl FrameOptions {
379 /// Sends start or repeated start condition before transfer.
380 fn send_start(self) -> bool {
381 match self {
382 Self::FirstAndLastFrame | Self::FirstFrame | Self::FirstAndNextFrame => true,
383 Self::NextFrame | Self::LastFrame | Self::LastFrameNoStop => false,
384 }
385 }
386
387 /// Sends stop condition after transfer.
388 fn send_stop(self) -> bool {
389 match self {
390 Self::FirstAndLastFrame | Self::LastFrame => true,
391 Self::FirstFrame | Self::FirstAndNextFrame | Self::NextFrame | Self::LastFrameNoStop => false,
392 }
393 }
394
395 /// Sends NACK after last byte received, indicating end of read operation.
396 fn send_nack(self) -> bool {
397 match self {
398 Self::FirstAndLastFrame | Self::FirstFrame | Self::LastFrame | Self::LastFrameNoStop => true,
399 Self::FirstAndNextFrame | Self::NextFrame => false,
400 }
401 }
402}
403
404/// Iterates over operations in transaction.
405///
406/// Returns necessary frame options for each operation to uphold the [transaction contract] and have
407/// the right start/stop/(N)ACK conditions on the wire.
408///
409/// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
410#[allow(dead_code)]
411fn operation_frames<'a, 'b: 'a>(
412 operations: &'a mut [embedded_hal_1::i2c::Operation<'b>],
413) -> Result<impl IntoIterator<Item = (&'a mut embedded_hal_1::i2c::Operation<'b>, FrameOptions)>, Error> {
414 use embedded_hal_1::i2c::Operation::{Read, Write};
415
416 // Check empty read buffer before starting transaction. Otherwise, we would risk halting with an
417 // error in the middle of the transaction.
418 //
419 // In principle, we could allow empty read frames within consecutive read operations, as long as
420 // at least one byte remains in the final (merged) read operation, but that makes the logic more
421 // complicated and error-prone.
422 if operations.iter().any(|op| match op {
423 Read(read) => read.is_empty(),
424 Write(_) => false,
425 }) {
426 return Err(Error::Overrun);
427 }
428
429 let mut operations = operations.iter_mut().peekable();
430
431 let mut next_first_frame = true;
432
433 Ok(iter::from_fn(move || {
434 let Some(op) = operations.next() else {
435 return None;
436 };
437
438 // Is `op` first frame of its type?
439 let first_frame = next_first_frame;
440 let next_op = operations.peek();
441
442 // Get appropriate frame options as combination of the following properties:
443 //
444 // - For each first operation of its type, generate a (repeated) start condition.
445 // - For the last operation overall in the entire transaction, generate a stop condition.
446 // - For read operations, check the next operation: if it is also a read operation, we merge
447 // these and send ACK for all bytes in the current operation; send NACK only for the final
448 // read operation's last byte (before write or end of entire transaction) to indicate last
449 // byte read and release the bus for transmission of the bus master's next byte (or stop).
450 //
451 // We check the third property unconditionally, i.e. even for write opeartions. This is okay
452 // because the resulting frame options are identical for write operations.
453 let frame = match (first_frame, next_op) {
454 (true, None) => FrameOptions::FirstAndLastFrame,
455 (true, Some(Read(_))) => FrameOptions::FirstAndNextFrame,
456 (true, Some(Write(_))) => FrameOptions::FirstFrame,
457 //
458 (false, None) => FrameOptions::LastFrame,
459 (false, Some(Read(_))) => FrameOptions::NextFrame,
460 (false, Some(Write(_))) => FrameOptions::LastFrameNoStop,
461 };
462
463 // Pre-calculate if `next_op` is the first operation of its type. We do this here and not at
464 // the beginning of the loop because we hand out `op` as iterator value and cannot access it
465 // anymore in the next iteration.
466 next_first_frame = match (&op, next_op) {
467 (_, None) => false,
468 (Read(_), Some(Write(_))) | (Write(_), Some(Read(_))) => true,
469 (Read(_), Some(Read(_))) | (Write(_), Some(Write(_))) => false,
470 };
471
472 Some((op, frame))
473 }))
474}
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index 9f29ed5e0..d45c48b24 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -41,68 +41,6 @@ pub unsafe fn on_interrupt<T: Instance>() {
41 }); 41 });
42} 42}
43 43
44/// Frame type in I2C transaction.
45///
46/// This tells each method what kind of framing to use, to generate a (repeated) start condition (ST
47/// or SR), and/or a stop condition (SP). For read operations, this also controls whether to send an
48/// ACK or NACK after the last byte received.
49///
50/// For write operations, the following options are identical because they differ only in the (N)ACK
51/// treatment relevant for read operations:
52///
53/// - `FirstFrame` and `FirstAndNextFrame`
54/// - `NextFrame` and `LastFrameNoStop`
55///
56/// Abbreviations used below:
57///
58/// - `ST` = start condition
59/// - `SR` = repeated start condition
60/// - `SP` = stop condition
61#[derive(Copy, Clone)]
62enum FrameOptions {
63 /// `[ST/SR]+[NACK]+[SP]` First frame (of this type) in operation and last frame overall in this
64 /// transaction.
65 FirstAndLastFrame,
66 /// `[ST/SR]+[NACK]` First frame of this type in transaction, last frame in a read operation but
67 /// not the last frame overall.
68 FirstFrame,
69 /// `[ST/SR]+[ACK]` First frame of this type in transaction, neither last frame overall nor last
70 /// frame in a read operation.
71 FirstAndNextFrame,
72 /// `[ACK]` Middle frame in a read operation (neither first nor last).
73 NextFrame,
74 /// `[NACK]+[SP]` Last frame overall in this transaction but not the first frame.
75 LastFrame,
76 /// `[NACK]` Last frame in a read operation but not last frame overall in this transaction.
77 LastFrameNoStop,
78}
79
80impl FrameOptions {
81 /// Sends start or repeated start condition before transfer.
82 fn send_start(self) -> bool {
83 match self {
84 Self::FirstAndLastFrame | Self::FirstFrame | Self::FirstAndNextFrame => true,
85 Self::NextFrame | Self::LastFrame | Self::LastFrameNoStop => false,
86 }
87 }
88
89 /// Sends stop condition after transfer.
90 fn send_stop(self) -> bool {
91 match self {
92 Self::FirstAndLastFrame | Self::LastFrame => true,
93 Self::FirstFrame | Self::FirstAndNextFrame | Self::NextFrame | Self::LastFrameNoStop => false,
94 }
95 }
96
97 /// Sends NACK after last byte received, indicating end of read operation.
98 fn send_nack(self) -> bool {
99 match self {
100 Self::FirstAndLastFrame | Self::FirstFrame | Self::LastFrame | Self::LastFrameNoStop => true,
101 Self::FirstAndNextFrame | Self::NextFrame => false,
102 }
103 }
104}
105
106impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { 44impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
107 pub(crate) fn init(&mut self, freq: Hertz, _config: Config) { 45 pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
108 T::regs().cr1().modify(|reg| { 46 T::regs().cr1().modify(|reg| {
@@ -199,17 +137,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
199 timeout.check()?; 137 timeout.check()?;
200 } 138 }
201 139
202 // Also wait until signalled we're master and everything is waiting for us 140 // Check if we were the ones to generate START
203 while { 141 if T::regs().cr1().read().start() || !T::regs().sr2().read().msl() {
204 Self::check_and_clear_error_flags()?; 142 return Err(Error::Arbitration);
205
206 let sr2 = T::regs().sr2().read();
207 !sr2.msl() && !sr2.busy()
208 } {
209 timeout.check()?;
210 } 143 }
211 144
212 // Set up current address, we're trying to talk to 145 // Set up current address we're trying to talk to
213 T::regs().dr().write(|reg| reg.set_dr(addr << 1)); 146 T::regs().dr().write(|reg| reg.set_dr(addr << 1));
214 147
215 // Wait until address was sent 148 // Wait until address was sent
@@ -231,10 +164,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
231 if frame.send_stop() { 164 if frame.send_stop() {
232 // Send a STOP condition 165 // Send a STOP condition
233 T::regs().cr1().modify(|reg| reg.set_stop(true)); 166 T::regs().cr1().modify(|reg| reg.set_stop(true));
234 // Wait for STOP condition to transmit.
235 while T::regs().cr1().read().stop() {
236 timeout.check()?;
237 }
238 } 167 }
239 168
240 // Fallthrough is success 169 // Fallthrough is success
@@ -301,15 +230,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
301 timeout.check()?; 230 timeout.check()?;
302 } 231 }
303 232
304 // Also wait until signalled we're master and everything is waiting for us 233 // Check if we were the ones to generate START
305 while { 234 if T::regs().cr1().read().start() || !T::regs().sr2().read().msl() {
306 let sr2 = T::regs().sr2().read(); 235 return Err(Error::Arbitration);
307 !sr2.msl() && !sr2.busy()
308 } {
309 timeout.check()?;
310 } 236 }
311 237
312 // Set up current address, we're trying to talk to 238 // Set up current address we're trying to talk to
313 T::regs().dr().write(|reg| reg.set_dr((addr << 1) + 1)); 239 T::regs().dr().write(|reg| reg.set_dr((addr << 1) + 1));
314 240
315 // Wait until address was sent 241 // Wait until address was sent
@@ -340,13 +266,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
340 // Receive last byte 266 // Receive last byte
341 *last = self.recv_byte(timeout)?; 267 *last = self.recv_byte(timeout)?;
342 268
343 if frame.send_stop() {
344 // Wait for the STOP to be sent.
345 while T::regs().cr1().read().stop() {
346 timeout.check()?;
347 }
348 }
349
350 // Fallthrough is success 269 // Fallthrough is success
351 Ok(()) 270 Ok(())
352 } 271 }
@@ -386,64 +305,13 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
386 /// 305 ///
387 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction 306 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
388 pub fn blocking_transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { 307 pub fn blocking_transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
389 // Check empty read buffer before starting transaction. Otherwise, we would not generate the
390 // stop condition below.
391 if operations.iter().any(|op| match op {
392 Operation::Read(read) => read.is_empty(),
393 Operation::Write(_) => false,
394 }) {
395 return Err(Error::Overrun);
396 }
397
398 let timeout = self.timeout(); 308 let timeout = self.timeout();
399 309
400 let mut operations = operations.iter_mut(); 310 for (op, frame) in operation_frames(operations)? {
401
402 let mut prev_op: Option<&mut Operation<'_>> = None;
403 let mut next_op = operations.next();
404
405 while let Some(op) = next_op {
406 next_op = operations.next();
407
408 // Check if this is the first frame of this type. This is the case for the first overall
409 // frame in the transaction and whenever the type of operation changes.
410 let first_frame =
411 match (prev_op.as_ref(), &op) {
412 (None, _) => true,
413 (Some(Operation::Read(_)), Operation::Write(_))
414 | (Some(Operation::Write(_)), Operation::Read(_)) => true,
415 (Some(Operation::Read(_)), Operation::Read(_))
416 | (Some(Operation::Write(_)), Operation::Write(_)) => false,
417 };
418
419 let frame = match (first_frame, next_op.as_ref()) {
420 // If this is the first frame of this type, we generate a (repeated) start condition
421 // but have to consider the next operation: if it is the last, we generate the final
422 // stop condition. Otherwise, we branch on the operation: with read operations, only
423 // the last byte overall (before a write operation or the end of the transaction) is
424 // to be NACK'd, i.e. if another read operation follows, we must ACK this last byte.
425 (true, None) => FrameOptions::FirstAndLastFrame,
426 // Make sure to keep sending ACK for last byte in read operation when it is followed
427 // by another consecutive read operation. If the current operation is write, this is
428 // identical to `FirstFrame`.
429 (true, Some(Operation::Read(_))) => FrameOptions::FirstAndNextFrame,
430 // Otherwise, send NACK for last byte (in read operation). (For write, this does not
431 // matter and could also be `FirstAndNextFrame`.)
432 (true, Some(Operation::Write(_))) => FrameOptions::FirstFrame,
433
434 // If this is not the first frame of its type, we do not generate a (repeated) start
435 // condition. Otherwise, we branch the same way as above.
436 (false, None) => FrameOptions::LastFrame,
437 (false, Some(Operation::Read(_))) => FrameOptions::NextFrame,
438 (false, Some(Operation::Write(_))) => FrameOptions::LastFrameNoStop,
439 };
440
441 match op { 311 match op {
442 Operation::Read(read) => self.blocking_read_timeout(addr, read, timeout, frame)?, 312 Operation::Read(read) => self.blocking_read_timeout(addr, read, timeout, frame)?,
443 Operation::Write(write) => self.write_bytes(addr, write, timeout, frame)?, 313 Operation::Write(write) => self.write_bytes(addr, write, timeout, frame)?,
444 } 314 }
445
446 prev_op = Some(op);
447 } 315 }
448 316
449 Ok(()) 317 Ok(())
@@ -459,111 +327,110 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
459 }); 327 });
460 } 328 }
461 329
462 async fn write_with_stop(&mut self, address: u8, write: &[u8], send_stop: bool) -> Result<(), Error> 330 async fn write_frame(&mut self, address: u8, write: &[u8], frame: FrameOptions) -> Result<(), Error>
463 where 331 where
464 TXDMA: crate::i2c::TxDma<T>, 332 TXDMA: crate::i2c::TxDma<T>,
465 { 333 {
466 let dma_transfer = unsafe { 334 T::regs().cr2().modify(|w| {
467 let regs = T::regs(); 335 // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
468 regs.cr2().modify(|w| { 336 // reception.
469 // DMA mode can be enabled for transmission by setting the DMAEN bit in the I2C_CR2 register. 337 w.set_itbufen(false);
470 w.set_dmaen(true); 338 // DMA mode can be enabled for transmission by setting the DMAEN bit in the I2C_CR2
471 w.set_itbufen(false); 339 // register.
472 }); 340 w.set_dmaen(true);
473 // Set the I2C_DR register address in the DMA_SxPAR register. The data will be moved to this address from the memory after each TxE event. 341 // Sending NACK is not necessary (nor possible) for write transfer.
474 let dst = regs.dr().as_ptr() as *mut u8; 342 w.set_last(false);
475 343 });
476 let ch = &mut self.tx_dma;
477 let request = ch.request();
478 Transfer::new_write(ch, request, write, dst, Default::default())
479 };
480 344
345 // Sentinel to disable transfer when an error occurs or future is canceled.
346 // TODO: Generate STOP condition on cancel?
481 let on_drop = OnDrop::new(|| { 347 let on_drop = OnDrop::new(|| {
482 let regs = T::regs(); 348 T::regs().cr2().modify(|w| {
483 regs.cr2().modify(|w| {
484 w.set_dmaen(false); 349 w.set_dmaen(false);
485 w.set_iterren(false); 350 w.set_iterren(false);
486 w.set_itevten(false); 351 w.set_itevten(false);
487 }) 352 })
488 }); 353 });
489 354
490 Self::enable_interrupts();
491
492 // Send a START condition
493 T::regs().cr1().modify(|reg| {
494 reg.set_start(true);
495 });
496
497 let state = T::state(); 355 let state = T::state();
498 356
499 // Wait until START condition was generated 357 if frame.send_start() {
500 poll_fn(|cx| { 358 // Send a START condition
501 state.waker.register(cx.waker()); 359 T::regs().cr1().modify(|reg| {
360 reg.set_start(true);
361 });
502 362
503 match Self::check_and_clear_error_flags() { 363 // Wait until START condition was generated
504 Err(e) => Poll::Ready(Err(e)), 364 poll_fn(|cx| {
505 Ok(sr1) => { 365 state.waker.register(cx.waker());
506 if sr1.start() { 366
507 Poll::Ready(Ok(())) 367 match Self::check_and_clear_error_flags() {
508 } else { 368 Err(e) => Poll::Ready(Err(e)),
509 Poll::Pending 369 Ok(sr1) => {
370 if sr1.start() {
371 Poll::Ready(Ok(()))
372 } else {
373 // When pending, (re-)enable interrupts to wake us up.
374 Self::enable_interrupts();
375 Poll::Pending
376 }
510 } 377 }
511 } 378 }
379 })
380 .await?;
381
382 // Check if we were the ones to generate START
383 if T::regs().cr1().read().start() || !T::regs().sr2().read().msl() {
384 return Err(Error::Arbitration);
512 } 385 }
513 })
514 .await?;
515 386
516 // Also wait until signalled we're master and everything is waiting for us 387 // Set up current address we're trying to talk to
517 Self::enable_interrupts(); 388 T::regs().dr().write(|reg| reg.set_dr(address << 1));
518 poll_fn(|cx| {
519 state.waker.register(cx.waker());
520 389
521 match Self::check_and_clear_error_flags() { 390 // Wait for the address to be acknowledged
522 Err(e) => Poll::Ready(Err(e)), 391 poll_fn(|cx| {
523 Ok(_) => { 392 state.waker.register(cx.waker());
524 let sr2 = T::regs().sr2().read(); 393
525 if !sr2.msl() && !sr2.busy() { 394 match Self::check_and_clear_error_flags() {
526 Poll::Pending 395 Err(e) => Poll::Ready(Err(e)),
527 } else { 396 Ok(sr1) => {
528 Poll::Ready(Ok(())) 397 if sr1.addr() {
398 Poll::Ready(Ok(()))
399 } else {
400 // When pending, (re-)enable interrupts to wake us up.
401 Self::enable_interrupts();
402 Poll::Pending
403 }
529 } 404 }
530 } 405 }
531 } 406 })
532 }) 407 .await?;
533 .await?;
534 408
535 // Set up current address, we're trying to talk to 409 // Clear condition by reading SR2
536 Self::enable_interrupts(); 410 T::regs().sr2().read();
537 T::regs().dr().write(|reg| reg.set_dr(address << 1)); 411 }
538 412
539 poll_fn(|cx| { 413 let dma_transfer = unsafe {
540 state.waker.register(cx.waker()); 414 // Set the I2C_DR register address in the DMA_SxPAR register. The data will be moved to
541 match Self::check_and_clear_error_flags() { 415 // this address from the memory after each TxE event.
542 Err(e) => Poll::Ready(Err(e)), 416 let dst = T::regs().dr().as_ptr() as *mut u8;
543 Ok(sr1) => { 417
544 if sr1.addr() { 418 let ch = &mut self.tx_dma;
545 // Clear the ADDR condition by reading SR2. 419 let request = ch.request();
546 T::regs().sr2().read(); 420 Transfer::new_write(ch, request, write, dst, Default::default())
547 Poll::Ready(Ok(())) 421 };
548 } else { 422
549 // If we need to go around, then re-enable the interrupts, otherwise nothing 423 // Wait for bytes to be sent, or an error to occur.
550 // can wake us up and we'll hang.
551 Self::enable_interrupts();
552 Poll::Pending
553 }
554 }
555 }
556 })
557 .await?;
558 Self::enable_interrupts();
559 let poll_error = poll_fn(|cx| { 424 let poll_error = poll_fn(|cx| {
560 state.waker.register(cx.waker()); 425 state.waker.register(cx.waker());
561 426
562 match Self::check_and_clear_error_flags() { 427 match Self::check_and_clear_error_flags() {
563 // Unclear why the Err turbofish is necessary here? The compiler didn’t require it in the other 428 Err(e) => Poll::Ready(Err::<(), Error>(e)),
564 // identical poll_fn check_and_clear matches. 429 Ok(_) => {
565 Err(e) => Poll::Ready(Err::<T, Error>(e)), 430 // When pending, (re-)enable interrupts to wake us up.
566 Ok(_) => Poll::Pending, 431 Self::enable_interrupts();
432 Poll::Pending
433 }
567 } 434 }
568 }); 435 });
569 436
@@ -573,38 +440,37 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
573 _ => Ok(()), 440 _ => Ok(()),
574 }?; 441 }?;
575 442
576 // The I2C transfer itself will take longer than the DMA transfer, so wait for that to finish too.
577
578 // 18.3.8 “Master transmitter: In the interrupt routine after the EOT interrupt, disable DMA
579 // requests then wait for a BTF event before programming the Stop condition.”
580
581 // TODO: If this has to be done “in the interrupt routine after the EOT interrupt”, where to put it?
582 T::regs().cr2().modify(|w| { 443 T::regs().cr2().modify(|w| {
583 w.set_dmaen(false); 444 w.set_dmaen(false);
584 }); 445 });
585 446
586 Self::enable_interrupts(); 447 if frame.send_stop() {
587 poll_fn(|cx| { 448 // The I2C transfer itself will take longer than the DMA transfer, so wait for that to finish too.
588 state.waker.register(cx.waker()); 449
589 450 // 18.3.8 “Master transmitter: In the interrupt routine after the EOT interrupt, disable DMA
590 match Self::check_and_clear_error_flags() { 451 // requests then wait for a BTF event before programming the Stop condition.”
591 Err(e) => Poll::Ready(Err(e)), 452 poll_fn(|cx| {
592 Ok(sr1) => { 453 state.waker.register(cx.waker());
593 if sr1.btf() { 454
594 if send_stop { 455 match Self::check_and_clear_error_flags() {
595 T::regs().cr1().modify(|w| { 456 Err(e) => Poll::Ready(Err(e)),
596 w.set_stop(true); 457 Ok(sr1) => {
597 }); 458 if sr1.btf() {
459 Poll::Ready(Ok(()))
460 } else {
461 // When pending, (re-)enable interrupts to wake us up.
462 Self::enable_interrupts();
463 Poll::Pending
598 } 464 }
599
600 Poll::Ready(Ok(()))
601 } else {
602 Poll::Pending
603 } 465 }
604 } 466 }
605 } 467 })
606 }) 468 .await?;
607 .await?; 469
470 T::regs().cr1().modify(|w| {
471 w.set_stop(true);
472 });
473 }
608 474
609 drop(on_drop); 475 drop(on_drop);
610 476
@@ -617,20 +483,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
617 where 483 where
618 TXDMA: crate::i2c::TxDma<T>, 484 TXDMA: crate::i2c::TxDma<T>,
619 { 485 {
620 self.write_with_stop(address, write, true).await?; 486 self.write_frame(address, write, FrameOptions::FirstAndLastFrame)
621 487 .await?;
622 // Wait for STOP condition to transmit.
623 Self::enable_interrupts();
624 poll_fn(|cx| {
625 T::state().waker.register(cx.waker());
626 // TODO: error interrupts are enabled here, should we additional check for and return errors?
627 if T::regs().cr1().read().stop() {
628 Poll::Pending
629 } else {
630 Poll::Ready(Ok(()))
631 }
632 })
633 .await?;
634 488
635 Ok(()) 489 Ok(())
636 } 490 }
@@ -640,135 +494,151 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
640 where 494 where
641 RXDMA: crate::i2c::RxDma<T>, 495 RXDMA: crate::i2c::RxDma<T>,
642 { 496 {
643 let state = T::state(); 497 self.read_frame(address, buffer, FrameOptions::FirstAndLastFrame)
644 let buffer_len = buffer.len(); 498 .await?;
645 499
646 let dma_transfer = unsafe { 500 Ok(())
647 let regs = T::regs(); 501 }
648 regs.cr2().modify(|w| {
649 // DMA mode can be enabled for transmission by setting the DMAEN bit in the I2C_CR2 register.
650 w.set_itbufen(false);
651 w.set_dmaen(true);
652 });
653 // Set the I2C_DR register address in the DMA_SxPAR register. The data will be moved to this address from the memory after each TxE event.
654 let src = regs.dr().as_ptr() as *mut u8;
655 502
656 let ch = &mut self.rx_dma; 503 async fn read_frame(&mut self, address: u8, buffer: &mut [u8], frame: FrameOptions) -> Result<(), Error>
657 let request = ch.request(); 504 where
658 Transfer::new_read(ch, request, src, buffer, Default::default()) 505 RXDMA: crate::i2c::RxDma<T>,
659 }; 506 {
507 if buffer.is_empty() {
508 return Err(Error::Overrun);
509 }
510
511 // Some branches below depend on whether the buffer contains only a single byte.
512 let single_byte = buffer.len() == 1;
513
514 T::regs().cr2().modify(|w| {
515 // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
516 // reception.
517 w.set_itbufen(false);
518 // DMA mode can be enabled for transmission by setting the DMAEN bit in the I2C_CR2
519 // register.
520 w.set_dmaen(true);
521 // If, in the I2C_CR2 register, the LAST bit is set, I2C automatically sends a NACK
522 // after the next byte following EOT_1. The user can generate a Stop condition in
523 // the DMA Transfer Complete interrupt routine if enabled.
524 w.set_last(frame.send_nack() && !single_byte);
525 });
660 526
527 // Sentinel to disable transfer when an error occurs or future is canceled.
528 // TODO: Generate STOP condition on cancel?
661 let on_drop = OnDrop::new(|| { 529 let on_drop = OnDrop::new(|| {
662 let regs = T::regs(); 530 T::regs().cr2().modify(|w| {
663 regs.cr2().modify(|w| {
664 w.set_dmaen(false); 531 w.set_dmaen(false);
665 w.set_iterren(false); 532 w.set_iterren(false);
666 w.set_itevten(false); 533 w.set_itevten(false);
667 }) 534 })
668 }); 535 });
669 536
670 Self::enable_interrupts(); 537 let state = T::state();
671
672 // Send a START condition and set ACK bit
673 T::regs().cr1().modify(|reg| {
674 reg.set_start(true);
675 reg.set_ack(true);
676 });
677 538
678 // Wait until START condition was generated 539 if frame.send_start() {
679 poll_fn(|cx| { 540 // Send a START condition and set ACK bit
680 state.waker.register(cx.waker()); 541 T::regs().cr1().modify(|reg| {
542 reg.set_start(true);
543 reg.set_ack(true);
544 });
681 545
682 match Self::check_and_clear_error_flags() { 546 // Wait until START condition was generated
683 Err(e) => Poll::Ready(Err(e)), 547 poll_fn(|cx| {
684 Ok(sr1) => { 548 state.waker.register(cx.waker());
685 if sr1.start() { 549
686 Poll::Ready(Ok(())) 550 match Self::check_and_clear_error_flags() {
687 } else { 551 Err(e) => Poll::Ready(Err(e)),
688 Poll::Pending 552 Ok(sr1) => {
553 if sr1.start() {
554 Poll::Ready(Ok(()))
555 } else {
556 // When pending, (re-)enable interrupts to wake us up.
557 Self::enable_interrupts();
558 Poll::Pending
559 }
689 } 560 }
690 } 561 }
691 } 562 })
692 }) 563 .await?;
693 .await?;
694
695 // Also wait until signalled we're master and everything is waiting for us
696 Self::enable_interrupts();
697 poll_fn(|cx| {
698 state.waker.register(cx.waker());
699 564
700 // blocking read didn’t have a check_and_clear call here, but blocking write did so 565 // Check if we were the ones to generate START
701 // I’m adding it here in case that was an oversight. 566 if T::regs().cr1().read().start() || !T::regs().sr2().read().msl() {
702 match Self::check_and_clear_error_flags() { 567 return Err(Error::Arbitration);
703 Err(e) => Poll::Ready(Err(e)),
704 Ok(_) => {
705 let sr2 = T::regs().sr2().read();
706 if !sr2.msl() && !sr2.busy() {
707 Poll::Pending
708 } else {
709 Poll::Ready(Ok(()))
710 }
711 }
712 } 568 }
713 })
714 .await?;
715 569
716 // Set up current address, we're trying to talk to 570 // Set up current address we're trying to talk to
717 T::regs().dr().write(|reg| reg.set_dr((address << 1) + 1)); 571 T::regs().dr().write(|reg| reg.set_dr((address << 1) + 1));
718 572
719 // Wait for the address to be acknowledged 573 // Wait for the address to be acknowledged
720 574 poll_fn(|cx| {
721 Self::enable_interrupts(); 575 state.waker.register(cx.waker());
722 poll_fn(|cx| { 576
723 state.waker.register(cx.waker()); 577 match Self::check_and_clear_error_flags() {
724 578 Err(e) => Poll::Ready(Err(e)),
725 match Self::check_and_clear_error_flags() { 579 Ok(sr1) => {
726 Err(e) => Poll::Ready(Err(e)), 580 if sr1.addr() {
727 Ok(sr1) => { 581 Poll::Ready(Ok(()))
728 if sr1.addr() { 582 } else {
729 // 18.3.8: When a single byte must be received: the NACK must be programmed during EV6 583 // When pending, (re-)enable interrupts to wake us up.
730 // event, i.e. program ACK=0 when ADDR=1, before clearing ADDR flag. 584 Self::enable_interrupts();
731 if buffer_len == 1 { 585 Poll::Pending
732 T::regs().cr1().modify(|w| {
733 w.set_ack(false);
734 });
735 } 586 }
736 Poll::Ready(Ok(()))
737 } else {
738 Poll::Pending
739 } 587 }
740 } 588 }
589 })
590 .await?;
591
592 // 18.3.8: When a single byte must be received: the NACK must be programmed during EV6
593 // event, i.e. program ACK=0 when ADDR=1, before clearing ADDR flag.
594 if frame.send_nack() && single_byte {
595 T::regs().cr1().modify(|w| {
596 w.set_ack(false);
597 });
741 } 598 }
742 })
743 .await?;
744 599
745 // Clear ADDR condition by reading SR2 600 // Clear condition by reading SR2
746 T::regs().sr2().read(); 601 T::regs().sr2().read();
602 } else {
603 // Before starting reception of single byte (but without START condition, i.e. in case
604 // of continued frame), program NACK to emit at end of this byte.
605 if frame.send_nack() && single_byte {
606 T::regs().cr1().modify(|w| {
607 w.set_ack(false);
608 });
609 }
610 }
747 611
748 // 18.3.8: When a single byte must be received: [snip] Then the 612 // 18.3.8: When a single byte must be received: [snip] Then the user can program the STOP
749 // user can program the STOP condition either after clearing ADDR flag, or in the 613 // condition either after clearing ADDR flag, or in the DMA Transfer Complete interrupt
750 // DMA Transfer Complete interrupt routine. 614 // routine.
751 if buffer_len == 1 { 615 if frame.send_stop() && single_byte {
752 T::regs().cr1().modify(|w| { 616 T::regs().cr1().modify(|w| {
753 w.set_stop(true); 617 w.set_stop(true);
754 }); 618 });
755 } else {
756 // If, in the I2C_CR2 register, the LAST bit is set, I2C
757 // automatically sends a NACK after the next byte following EOT_1. The user can
758 // generate a Stop condition in the DMA Transfer Complete interrupt routine if enabled.
759 T::regs().cr2().modify(|w| {
760 w.set_last(true);
761 })
762 } 619 }
763 620
621 let dma_transfer = unsafe {
622 // Set the I2C_DR register address in the DMA_SxPAR register. The data will be moved
623 // from this address from the memory after each RxE event.
624 let src = T::regs().dr().as_ptr() as *mut u8;
625
626 let ch = &mut self.rx_dma;
627 let request = ch.request();
628 Transfer::new_read(ch, request, src, buffer, Default::default())
629 };
630
764 // Wait for bytes to be received, or an error to occur. 631 // Wait for bytes to be received, or an error to occur.
765 Self::enable_interrupts();
766 let poll_error = poll_fn(|cx| { 632 let poll_error = poll_fn(|cx| {
767 state.waker.register(cx.waker()); 633 state.waker.register(cx.waker());
768 634
769 match Self::check_and_clear_error_flags() { 635 match Self::check_and_clear_error_flags() {
770 Err(e) => Poll::Ready(Err::<T, Error>(e)), 636 Err(e) => Poll::Ready(Err::<(), Error>(e)),
771 _ => Poll::Pending, 637 _ => {
638 // When pending, (re-)enable interrupts to wake us up.
639 Self::enable_interrupts();
640 Poll::Pending
641 }
772 } 642 }
773 }); 643 });
774 644
@@ -777,18 +647,16 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
777 _ => Ok(()), 647 _ => Ok(()),
778 }?; 648 }?;
779 649
780 // Wait for the STOP to be sent (STOP bit cleared). 650 T::regs().cr2().modify(|w| {
781 Self::enable_interrupts(); 651 w.set_dmaen(false);
782 poll_fn(|cx| { 652 });
783 state.waker.register(cx.waker()); 653
784 // TODO: error interrupts are enabled here, should we additional check for and return errors? 654 if frame.send_stop() && !single_byte {
785 if T::regs().cr1().read().stop() { 655 T::regs().cr1().modify(|w| {
786 Poll::Pending 656 w.set_stop(true);
787 } else { 657 });
788 Poll::Ready(Ok(())) 658 }
789 } 659
790 })
791 .await?;
792 drop(on_drop); 660 drop(on_drop);
793 661
794 // Fallthrough is success 662 // Fallthrough is success
@@ -801,8 +669,34 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
801 RXDMA: crate::i2c::RxDma<T>, 669 RXDMA: crate::i2c::RxDma<T>,
802 TXDMA: crate::i2c::TxDma<T>, 670 TXDMA: crate::i2c::TxDma<T>,
803 { 671 {
804 self.write_with_stop(address, write, false).await?; 672 // Check empty read buffer before starting transaction. Otherwise, we would not generate the
805 self.read(address, read).await 673 // stop condition below.
674 if read.is_empty() {
675 return Err(Error::Overrun);
676 }
677
678 self.write_frame(address, write, FrameOptions::FirstFrame).await?;
679 self.read_frame(address, read, FrameOptions::FirstAndLastFrame).await
680 }
681
682 /// Transaction with operations.
683 ///
684 /// Consecutive operations of same type are merged. See [transaction contract] for details.
685 ///
686 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
687 pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error>
688 where
689 RXDMA: crate::i2c::RxDma<T>,
690 TXDMA: crate::i2c::TxDma<T>,
691 {
692 for (op, frame) in operation_frames(operations)? {
693 match op {
694 Operation::Read(read) => self.read_frame(addr, read, frame).await?,
695 Operation::Write(write) => self.write_frame(addr, write, frame).await?,
696 }
697 }
698
699 Ok(())
806 } 700 }
807} 701}
808 702
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 8baf2849d..da3b0ee30 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -557,6 +557,21 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
557 Ok(()) 557 Ok(())
558 } 558 }
559 559
560 /// Transaction with operations.
561 ///
562 /// Consecutive operations of same type are merged. See [transaction contract] for details.
563 ///
564 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
565 pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error>
566 where
567 RXDMA: crate::i2c::RxDma<T>,
568 TXDMA: crate::i2c::TxDma<T>,
569 {
570 let _ = addr;
571 let _ = operations;
572 todo!()
573 }
574
560 // ========================= 575 // =========================
561 // Blocking public API 576 // Blocking public API
562 577