aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Goll <[email protected]>2024-03-20 20:11:59 +0100
committerSebastian Goll <[email protected]>2024-03-26 22:53:14 +0100
commit0885c102d3c332591b2d913113cde08fca8fe41b (patch)
treed3af77d8a3c3d4d63c69f190e836e3ba2b23e48e
parent746ded94b13d037c5be16071d2d9d195b979c0c7 (diff)
Refactor async I2C transfers to use frame options
-rw-r--r--embassy-stm32/src/i2c/v1.rs331
1 files changed, 178 insertions, 153 deletions
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index 563bbfdaf..2751d443f 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -459,7 +459,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
459 }); 459 });
460 } 460 }
461 461
462 async fn write_with_stop(&mut self, address: u8, write: &[u8], send_stop: bool) -> Result<(), Error> 462 async fn write_frame(&mut self, address: u8, write: &[u8], frame: FrameOptions) -> Result<(), Error>
463 where 463 where
464 TXDMA: crate::i2c::TxDma<T>, 464 TXDMA: crate::i2c::TxDma<T>,
465 { 465 {
@@ -487,74 +487,76 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
487 }) 487 })
488 }); 488 });
489 489
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(); 490 let state = T::state();
498 491
499 // Wait until START condition was generated 492 if frame.send_start() {
500 poll_fn(|cx| { 493 // Send a START condition
501 state.waker.register(cx.waker()); 494 Self::enable_interrupts();
495 T::regs().cr1().modify(|reg| {
496 reg.set_start(true);
497 });
502 498
503 match Self::check_and_clear_error_flags() { 499 // Wait until START condition was generated
504 Err(e) => Poll::Ready(Err(e)), 500 poll_fn(|cx| {
505 Ok(sr1) => { 501 state.waker.register(cx.waker());
506 if sr1.start() { 502
507 Poll::Ready(Ok(())) 503 match Self::check_and_clear_error_flags() {
508 } else { 504 Err(e) => Poll::Ready(Err(e)),
509 Poll::Pending 505 Ok(sr1) => {
506 if sr1.start() {
507 Poll::Ready(Ok(()))
508 } else {
509 Poll::Pending
510 }
510 } 511 }
511 } 512 }
512 } 513 })
513 }) 514 .await?;
514 .await?;
515
516 // Also wait until signalled we're master and everything is waiting for us
517 Self::enable_interrupts();
518 poll_fn(|cx| {
519 state.waker.register(cx.waker());
520 515
521 match Self::check_and_clear_error_flags() { 516 // Also wait until signalled we're master and everything is waiting for us
522 Err(e) => Poll::Ready(Err(e)), 517 Self::enable_interrupts();
523 Ok(_) => { 518 poll_fn(|cx| {
524 let sr2 = T::regs().sr2().read(); 519 state.waker.register(cx.waker());
525 if !sr2.msl() && !sr2.busy() { 520
526 Poll::Pending 521 match Self::check_and_clear_error_flags() {
527 } else { 522 Err(e) => Poll::Ready(Err(e)),
528 Poll::Ready(Ok(())) 523 Ok(_) => {
524 let sr2 = T::regs().sr2().read();
525 if !sr2.msl() && !sr2.busy() {
526 Poll::Pending
527 } else {
528 Poll::Ready(Ok(()))
529 }
529 } 530 }
530 } 531 }
531 } 532 })
532 }) 533 .await?;
533 .await?;
534
535 // Set up current address, we're trying to talk to
536 Self::enable_interrupts();
537 T::regs().dr().write(|reg| reg.set_dr(address << 1));
538 534
539 poll_fn(|cx| { 535 // Set up current address, we're trying to talk to
540 state.waker.register(cx.waker()); 536 Self::enable_interrupts();
541 match Self::check_and_clear_error_flags() { 537 T::regs().dr().write(|reg| reg.set_dr(address << 1));
542 Err(e) => Poll::Ready(Err(e)), 538
543 Ok(sr1) => { 539 poll_fn(|cx| {
544 if sr1.addr() { 540 state.waker.register(cx.waker());
545 // Clear the ADDR condition by reading SR2. 541 match Self::check_and_clear_error_flags() {
546 T::regs().sr2().read(); 542 Err(e) => Poll::Ready(Err(e)),
547 Poll::Ready(Ok(())) 543 Ok(sr1) => {
548 } else { 544 if sr1.addr() {
549 // If we need to go around, then re-enable the interrupts, otherwise nothing 545 // Clear the ADDR condition by reading SR2.
550 // can wake us up and we'll hang. 546 T::regs().sr2().read();
551 Self::enable_interrupts(); 547 Poll::Ready(Ok(()))
552 Poll::Pending 548 } else {
549 // If we need to go around, then re-enable the interrupts, otherwise nothing
550 // can wake us up and we'll hang.
551 Self::enable_interrupts();
552 Poll::Pending
553 }
553 } 554 }
554 } 555 }
555 } 556 })
556 }) 557 .await?;
557 .await?; 558 }
559
558 Self::enable_interrupts(); 560 Self::enable_interrupts();
559 let poll_error = poll_fn(|cx| { 561 let poll_error = poll_fn(|cx| {
560 state.waker.register(cx.waker()); 562 state.waker.register(cx.waker());
@@ -591,7 +593,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
591 Err(e) => Poll::Ready(Err(e)), 593 Err(e) => Poll::Ready(Err(e)),
592 Ok(sr1) => { 594 Ok(sr1) => {
593 if sr1.btf() { 595 if sr1.btf() {
594 if send_stop { 596 if frame.send_stop() {
595 T::regs().cr1().modify(|w| { 597 T::regs().cr1().modify(|w| {
596 w.set_stop(true); 598 w.set_stop(true);
597 }); 599 });
@@ -606,6 +608,21 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
606 }) 608 })
607 .await?; 609 .await?;
608 610
611 if frame.send_stop() {
612 // Wait for STOP condition to transmit.
613 Self::enable_interrupts();
614 poll_fn(|cx| {
615 T::state().waker.register(cx.waker());
616 // TODO: error interrupts are enabled here, should we additional check for and return errors?
617 if T::regs().cr1().read().stop() {
618 Poll::Pending
619 } else {
620 Poll::Ready(Ok(()))
621 }
622 })
623 .await?;
624 }
625
609 drop(on_drop); 626 drop(on_drop);
610 627
611 // Fallthrough is success 628 // Fallthrough is success
@@ -617,20 +634,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
617 where 634 where
618 TXDMA: crate::i2c::TxDma<T>, 635 TXDMA: crate::i2c::TxDma<T>,
619 { 636 {
620 self.write_with_stop(address, write, true).await?; 637 self.write_frame(address, write, FrameOptions::FirstAndLastFrame)
621 638 .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 639
635 Ok(()) 640 Ok(())
636 } 641 }
@@ -640,6 +645,16 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
640 where 645 where
641 RXDMA: crate::i2c::RxDma<T>, 646 RXDMA: crate::i2c::RxDma<T>,
642 { 647 {
648 self.read_frame(address, buffer, FrameOptions::FirstAndLastFrame)
649 .await?;
650
651 Ok(())
652 }
653
654 async fn read_frame(&mut self, address: u8, buffer: &mut [u8], frame: FrameOptions) -> Result<(), Error>
655 where
656 RXDMA: crate::i2c::RxDma<T>,
657 {
643 let state = T::state(); 658 let state = T::state();
644 let buffer_len = buffer.len(); 659 let buffer_len = buffer.len();
645 660
@@ -667,98 +682,99 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
667 }) 682 })
668 }); 683 });
669 684
670 Self::enable_interrupts(); 685 if frame.send_start() {
671 686 // Send a START condition and set ACK bit
672 // Send a START condition and set ACK bit 687 Self::enable_interrupts();
673 T::regs().cr1().modify(|reg| { 688 T::regs().cr1().modify(|reg| {
674 reg.set_start(true); 689 reg.set_start(true);
675 reg.set_ack(true); 690 reg.set_ack(true);
676 }); 691 });
677
678 // Wait until START condition was generated
679 poll_fn(|cx| {
680 state.waker.register(cx.waker());
681 692
682 match Self::check_and_clear_error_flags() { 693 // Wait until START condition was generated
683 Err(e) => Poll::Ready(Err(e)), 694 poll_fn(|cx| {
684 Ok(sr1) => { 695 state.waker.register(cx.waker());
685 if sr1.start() { 696
686 Poll::Ready(Ok(())) 697 match Self::check_and_clear_error_flags() {
687 } else { 698 Err(e) => Poll::Ready(Err(e)),
688 Poll::Pending 699 Ok(sr1) => {
700 if sr1.start() {
701 Poll::Ready(Ok(()))
702 } else {
703 Poll::Pending
704 }
689 } 705 }
690 } 706 }
691 } 707 })
692 }) 708 .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 709
700 // blocking read didn’t have a check_and_clear call here, but blocking write did so 710 // Also wait until signalled we're master and everything is waiting for us
701 // I’m adding it here in case that was an oversight. 711 Self::enable_interrupts();
702 match Self::check_and_clear_error_flags() { 712 poll_fn(|cx| {
703 Err(e) => Poll::Ready(Err(e)), 713 state.waker.register(cx.waker());
704 Ok(_) => { 714
705 let sr2 = T::regs().sr2().read(); 715 // blocking read didn’t have a check_and_clear call here, but blocking write did so
706 if !sr2.msl() && !sr2.busy() { 716 // I’m adding it here in case that was an oversight.
707 Poll::Pending 717 match Self::check_and_clear_error_flags() {
708 } else { 718 Err(e) => Poll::Ready(Err(e)),
709 Poll::Ready(Ok(())) 719 Ok(_) => {
720 let sr2 = T::regs().sr2().read();
721 if !sr2.msl() && !sr2.busy() {
722 Poll::Pending
723 } else {
724 Poll::Ready(Ok(()))
725 }
710 } 726 }
711 } 727 }
712 } 728 })
713 }) 729 .await?;
714 .await?;
715
716 // Set up current address, we're trying to talk to
717 T::regs().dr().write(|reg| reg.set_dr((address << 1) + 1));
718 730
719 // Wait for the address to be acknowledged 731 // Set up current address, we're trying to talk to
732 T::regs().dr().write(|reg| reg.set_dr((address << 1) + 1));
720 733
721 Self::enable_interrupts(); 734 // Wait for the address to be acknowledged
722 poll_fn(|cx| {
723 state.waker.register(cx.waker());
724 735
725 match Self::check_and_clear_error_flags() { 736 Self::enable_interrupts();
726 Err(e) => Poll::Ready(Err(e)), 737 poll_fn(|cx| {
727 Ok(sr1) => { 738 state.waker.register(cx.waker());
728 if sr1.addr() { 739
729 // 18.3.8: When a single byte must be received: the NACK must be programmed during EV6 740 match Self::check_and_clear_error_flags() {
730 // event, i.e. program ACK=0 when ADDR=1, before clearing ADDR flag. 741 Err(e) => Poll::Ready(Err(e)),
731 if buffer_len == 1 { 742 Ok(sr1) => {
732 T::regs().cr1().modify(|w| { 743 if sr1.addr() {
733 w.set_ack(false); 744 // 18.3.8: When a single byte must be received: the NACK must be programmed during EV6
734 }); 745 // event, i.e. program ACK=0 when ADDR=1, before clearing ADDR flag.
746 if buffer_len == 1 && frame.send_nack() {
747 T::regs().cr1().modify(|w| {
748 w.set_ack(false);
749 });
750 }
751 Poll::Ready(Ok(()))
752 } else {
753 Poll::Pending
735 } 754 }
736 Poll::Ready(Ok(()))
737 } else {
738 Poll::Pending
739 } 755 }
740 } 756 }
741 } 757 })
742 }) 758 .await?;
743 .await?;
744 759
745 // Clear ADDR condition by reading SR2 760 // Clear ADDR condition by reading SR2
746 T::regs().sr2().read(); 761 T::regs().sr2().read();
762 }
747 763
748 // 18.3.8: When a single byte must be received: [snip] Then the 764 // 18.3.8: When a single byte must be received: [snip] Then the
749 // user can program the STOP condition either after clearing ADDR flag, or in the 765 // user can program the STOP condition either after clearing ADDR flag, or in the
750 // DMA Transfer Complete interrupt routine. 766 // DMA Transfer Complete interrupt routine.
751 if buffer_len == 1 { 767 if buffer_len == 1 && frame.send_stop() {
752 T::regs().cr1().modify(|w| { 768 T::regs().cr1().modify(|w| {
753 w.set_stop(true); 769 w.set_stop(true);
754 }); 770 });
755 } else { 771 } else if buffer_len != 1 && frame.send_nack() {
756 // If, in the I2C_CR2 register, the LAST bit is set, I2C 772 // 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 773 // 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. 774 // generate a Stop condition in the DMA Transfer Complete interrupt routine if enabled.
759 T::regs().cr2().modify(|w| { 775 T::regs().cr2().modify(|w| {
760 w.set_last(true); 776 w.set_last(true);
761 }) 777 });
762 } 778 }
763 779
764 // Wait for bytes to be received, or an error to occur. 780 // Wait for bytes to be received, or an error to occur.
@@ -777,18 +793,27 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
777 _ => Ok(()), 793 _ => Ok(()),
778 }?; 794 }?;
779 795
780 // Wait for the STOP to be sent (STOP bit cleared). 796 if frame.send_stop() {
781 Self::enable_interrupts(); 797 if buffer_len != 1 {
782 poll_fn(|cx| { 798 T::regs().cr1().modify(|w| {
783 state.waker.register(cx.waker()); 799 w.set_stop(true);
784 // TODO: error interrupts are enabled here, should we additional check for and return errors? 800 });
785 if T::regs().cr1().read().stop() {
786 Poll::Pending
787 } else {
788 Poll::Ready(Ok(()))
789 } 801 }
790 }) 802
791 .await?; 803 // Wait for the STOP to be sent (STOP bit cleared).
804 Self::enable_interrupts();
805 poll_fn(|cx| {
806 state.waker.register(cx.waker());
807 // TODO: error interrupts are enabled here, should we additional check for and return errors?
808 if T::regs().cr1().read().stop() {
809 Poll::Pending
810 } else {
811 Poll::Ready(Ok(()))
812 }
813 })
814 .await?;
815 }
816
792 drop(on_drop); 817 drop(on_drop);
793 818
794 // Fallthrough is success 819 // Fallthrough is success
@@ -801,8 +826,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
801 RXDMA: crate::i2c::RxDma<T>, 826 RXDMA: crate::i2c::RxDma<T>,
802 TXDMA: crate::i2c::TxDma<T>, 827 TXDMA: crate::i2c::TxDma<T>,
803 { 828 {
804 self.write_with_stop(address, write, false).await?; 829 self.write_frame(address, write, FrameOptions::FirstFrame).await?;
805 self.read(address, read).await 830 self.read_frame(address, read, FrameOptions::FirstAndLastFrame).await
806 } 831 }
807} 832}
808 833