diff options
| -rw-r--r-- | embassy-stm32/src/i2c/v1.rs | 331 |
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 | ||
