diff options
| author | Eekle <[email protected]> | 2024-06-23 16:43:12 +0200 |
|---|---|---|
| committer | Eekle <[email protected]> | 2024-06-23 16:43:12 +0200 |
| commit | 2655426cd80b828593c8cd60930da3ebbd60e85c (patch) | |
| tree | 4553255a9f6b854e7d60f609004a10a39b0c3fe0 /embassy-stm32 | |
| parent | d5badb94d2098b0360ed1ab8015c37f819771445 (diff) | |
Add async wait to TSC
Diffstat (limited to 'embassy-stm32')
| -rw-r--r-- | embassy-stm32/src/tsc/mod.rs | 139 |
1 files changed, 97 insertions, 42 deletions
diff --git a/embassy-stm32/src/tsc/mod.rs b/embassy-stm32/src/tsc/mod.rs index 8ba208ce7..6497ff0ee 100644 --- a/embassy-stm32/src/tsc/mod.rs +++ b/embassy-stm32/src/tsc/mod.rs | |||
| @@ -71,9 +71,13 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; | |||
| 71 | pub use enums::*; | 71 | pub use enums::*; |
| 72 | 72 | ||
| 73 | use crate::gpio::{AfType, AnyPin, OutputType, Speed}; | 73 | use crate::gpio::{AfType, AnyPin, OutputType, Speed}; |
| 74 | use crate::pac::tsc::Tsc as Regs; | 74 | use crate::interrupt; |
| 75 | use crate::interrupt::typelevel::Interrupt; | ||
| 75 | use crate::rcc::{self, RccPeripheral}; | 76 | use crate::rcc::{self, RccPeripheral}; |
| 76 | use crate::{peripherals, Peripheral}; | 77 | use crate::{peripherals, Peripheral}; |
| 78 | use core::future::poll_fn; | ||
| 79 | use core::task::Poll; | ||
| 80 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 77 | 81 | ||
| 78 | #[cfg(tsc_v1)] | 82 | #[cfg(tsc_v1)] |
| 79 | const TSC_NUM_GROUPS: u32 = 6; | 83 | const TSC_NUM_GROUPS: u32 = 6; |
| @@ -90,6 +94,18 @@ pub enum Error { | |||
| 90 | Test, | 94 | Test, |
| 91 | } | 95 | } |
| 92 | 96 | ||
| 97 | /// TSC interrupt handler. | ||
| 98 | pub struct InterruptHandler<T: Instance> { | ||
| 99 | _phantom: PhantomData<T>, | ||
| 100 | } | ||
| 101 | |||
| 102 | impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { | ||
| 103 | unsafe fn on_interrupt() { | ||
| 104 | T::regs().ier().write(|w| w.set_eoaie(false)); | ||
| 105 | T::waker().wake(); | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 93 | /// Pin type definition to control IO parameters | 109 | /// Pin type definition to control IO parameters |
| 94 | pub enum PinType { | 110 | pub enum PinType { |
| 95 | /// Sensing channel pin connected to an electrode | 111 | /// Sensing channel pin connected to an electrode |
| @@ -510,6 +526,7 @@ impl<'d, T: Instance> Tsc<'d, T> { | |||
| 510 | /// Create new TSC driver | 526 | /// Create new TSC driver |
| 511 | pub fn new( | 527 | pub fn new( |
| 512 | peri: impl Peripheral<P = T> + 'd, | 528 | peri: impl Peripheral<P = T> + 'd, |
| 529 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | ||
| 513 | g1: Option<PinGroup<'d, T, G1>>, | 530 | g1: Option<PinGroup<'d, T, G1>>, |
| 514 | g2: Option<PinGroup<'d, T, G2>>, | 531 | g2: Option<PinGroup<'d, T, G2>>, |
| 515 | g3: Option<PinGroup<'d, T, G3>>, | 532 | g3: Option<PinGroup<'d, T, G3>>, |
| @@ -663,7 +680,7 @@ impl<'d, T: Instance> Tsc<'d, T> { | |||
| 663 | 680 | ||
| 664 | rcc::enable_and_reset::<T>(); | 681 | rcc::enable_and_reset::<T>(); |
| 665 | 682 | ||
| 666 | T::REGS.cr().modify(|w| { | 683 | T::regs().cr().modify(|w| { |
| 667 | w.set_tsce(true); | 684 | w.set_tsce(true); |
| 668 | w.set_ctph(config.ct_pulse_high_length.into()); | 685 | w.set_ctph(config.ct_pulse_high_length.into()); |
| 669 | w.set_ctpl(config.ct_pulse_low_length.into()); | 686 | w.set_ctpl(config.ct_pulse_low_length.into()); |
| @@ -691,33 +708,39 @@ impl<'d, T: Instance> Tsc<'d, T> { | |||
| 691 | 708 | ||
| 692 | // Set IO configuration | 709 | // Set IO configuration |
| 693 | // Disable Schmitt trigger hysteresis on all used TSC IOs | 710 | // Disable Schmitt trigger hysteresis on all used TSC IOs |
| 694 | T::REGS | 711 | T::regs() |
| 695 | .iohcr() | 712 | .iohcr() |
| 696 | .write(|w| w.0 = !(config.channel_ios | config.shield_ios | config.sampling_ios)); | 713 | .write(|w| w.0 = !(config.channel_ios | config.shield_ios | config.sampling_ios)); |
| 697 | 714 | ||
| 698 | // Set channel and shield IOs | 715 | // Set channel and shield IOs |
| 699 | T::REGS.ioccr().write(|w| w.0 = config.channel_ios | config.shield_ios); | 716 | T::regs() |
| 717 | .ioccr() | ||
| 718 | .write(|w| w.0 = config.channel_ios | config.shield_ios); | ||
| 700 | 719 | ||
| 701 | // Set sampling IOs | 720 | // Set sampling IOs |
| 702 | T::REGS.ioscr().write(|w| w.0 = config.sampling_ios); | 721 | T::regs().ioscr().write(|w| w.0 = config.sampling_ios); |
| 703 | 722 | ||
| 704 | // Set the groups to be acquired | 723 | // Set the groups to be acquired |
| 705 | T::REGS | 724 | T::regs() |
| 706 | .iogcsr() | 725 | .iogcsr() |
| 707 | .write(|w| w.0 = Self::extract_groups(config.channel_ios)); | 726 | .write(|w| w.0 = Self::extract_groups(config.channel_ios)); |
| 708 | 727 | ||
| 709 | // Disable interrupts | 728 | // Disable interrupts |
| 710 | T::REGS.ier().modify(|w| { | 729 | T::regs().ier().modify(|w| { |
| 711 | w.set_eoaie(false); | 730 | w.set_eoaie(false); |
| 712 | w.set_mceie(false); | 731 | w.set_mceie(false); |
| 713 | }); | 732 | }); |
| 714 | 733 | ||
| 715 | // Clear flags | 734 | // Clear flags |
| 716 | T::REGS.icr().modify(|w| { | 735 | T::regs().icr().modify(|w| { |
| 717 | w.set_eoaic(true); | 736 | w.set_eoaic(true); |
| 718 | w.set_mceic(true); | 737 | w.set_mceic(true); |
| 719 | }); | 738 | }); |
| 720 | 739 | ||
| 740 | unsafe { | ||
| 741 | T::Interrupt::enable(); | ||
| 742 | } | ||
| 743 | |||
| 721 | Self { | 744 | Self { |
| 722 | _peri: peri, | 745 | _peri: peri, |
| 723 | _g1: g1, | 746 | _g1: g1, |
| @@ -740,24 +763,24 @@ impl<'d, T: Instance> Tsc<'d, T> { | |||
| 740 | self.state = State::Busy; | 763 | self.state = State::Busy; |
| 741 | 764 | ||
| 742 | // Disable interrupts | 765 | // Disable interrupts |
| 743 | T::REGS.ier().modify(|w| { | 766 | T::regs().ier().modify(|w| { |
| 744 | w.set_eoaie(false); | 767 | w.set_eoaie(false); |
| 745 | w.set_mceie(false); | 768 | w.set_mceie(false); |
| 746 | }); | 769 | }); |
| 747 | 770 | ||
| 748 | // Clear flags | 771 | // Clear flags |
| 749 | T::REGS.icr().modify(|w| { | 772 | T::regs().icr().modify(|w| { |
| 750 | w.set_eoaic(true); | 773 | w.set_eoaic(true); |
| 751 | w.set_mceic(true); | 774 | w.set_mceic(true); |
| 752 | }); | 775 | }); |
| 753 | 776 | ||
| 754 | // Set the touch sensing IOs not acquired to the default mode | 777 | // Set the touch sensing IOs not acquired to the default mode |
| 755 | T::REGS.cr().modify(|w| { | 778 | T::regs().cr().modify(|w| { |
| 756 | w.set_iodef(self.config.io_default_mode); | 779 | w.set_iodef(self.config.io_default_mode); |
| 757 | }); | 780 | }); |
| 758 | 781 | ||
| 759 | // Start the acquisition | 782 | // Start the acquisition |
| 760 | T::REGS.cr().modify(|w| { | 783 | T::regs().cr().modify(|w| { |
| 761 | w.set_start(true); | 784 | w.set_start(true); |
| 762 | }); | 785 | }); |
| 763 | } | 786 | } |
| @@ -767,41 +790,41 @@ impl<'d, T: Instance> Tsc<'d, T> { | |||
| 767 | self.state = State::Busy; | 790 | self.state = State::Busy; |
| 768 | 791 | ||
| 769 | // Enable interrupts | 792 | // Enable interrupts |
| 770 | T::REGS.ier().modify(|w| { | 793 | T::regs().ier().modify(|w| { |
| 771 | w.set_eoaie(true); | 794 | w.set_eoaie(true); |
| 772 | w.set_mceie(self.config.max_count_interrupt); | 795 | w.set_mceie(self.config.max_count_interrupt); |
| 773 | }); | 796 | }); |
| 774 | 797 | ||
| 775 | // Clear flags | 798 | // Clear flags |
| 776 | T::REGS.icr().modify(|w| { | 799 | T::regs().icr().modify(|w| { |
| 777 | w.set_eoaic(true); | 800 | w.set_eoaic(true); |
| 778 | w.set_mceic(true); | 801 | w.set_mceic(true); |
| 779 | }); | 802 | }); |
| 780 | 803 | ||
| 781 | // Set the touch sensing IOs not acquired to the default mode | 804 | // Set the touch sensing IOs not acquired to the default mode |
| 782 | T::REGS.cr().modify(|w| { | 805 | T::regs().cr().modify(|w| { |
| 783 | w.set_iodef(self.config.io_default_mode); | 806 | w.set_iodef(self.config.io_default_mode); |
| 784 | }); | 807 | }); |
| 785 | 808 | ||
| 786 | // Start the acquisition | 809 | // Start the acquisition |
| 787 | T::REGS.cr().modify(|w| { | 810 | T::regs().cr().modify(|w| { |
| 788 | w.set_start(true); | 811 | w.set_start(true); |
| 789 | }); | 812 | }); |
| 790 | } | 813 | } |
| 791 | 814 | ||
| 792 | /// Stop charge transfer acquisition | 815 | /// Stop charge transfer acquisition |
| 793 | pub fn stop(&mut self) { | 816 | pub fn stop(&mut self) { |
| 794 | T::REGS.cr().modify(|w| { | 817 | T::regs().cr().modify(|w| { |
| 795 | w.set_start(false); | 818 | w.set_start(false); |
| 796 | }); | 819 | }); |
| 797 | 820 | ||
| 798 | // Set the touch sensing IOs in low power mode | 821 | // Set the touch sensing IOs in low power mode |
| 799 | T::REGS.cr().modify(|w| { | 822 | T::regs().cr().modify(|w| { |
| 800 | w.set_iodef(false); | 823 | w.set_iodef(false); |
| 801 | }); | 824 | }); |
| 802 | 825 | ||
| 803 | // Clear flags | 826 | // Clear flags |
| 804 | T::REGS.icr().modify(|w| { | 827 | T::regs().icr().modify(|w| { |
| 805 | w.set_eoaic(true); | 828 | w.set_eoaic(true); |
| 806 | w.set_mceic(true); | 829 | w.set_mceic(true); |
| 807 | }); | 830 | }); |
| @@ -811,23 +834,23 @@ impl<'d, T: Instance> Tsc<'d, T> { | |||
| 811 | 834 | ||
| 812 | /// Stop charge transfer acquisition and clear interrupts | 835 | /// Stop charge transfer acquisition and clear interrupts |
| 813 | pub fn stop_it(&mut self) { | 836 | pub fn stop_it(&mut self) { |
| 814 | T::REGS.cr().modify(|w| { | 837 | T::regs().cr().modify(|w| { |
| 815 | w.set_start(false); | 838 | w.set_start(false); |
| 816 | }); | 839 | }); |
| 817 | 840 | ||
| 818 | // Set the touch sensing IOs in low power mode | 841 | // Set the touch sensing IOs in low power mode |
| 819 | T::REGS.cr().modify(|w| { | 842 | T::regs().cr().modify(|w| { |
| 820 | w.set_iodef(false); | 843 | w.set_iodef(false); |
| 821 | }); | 844 | }); |
| 822 | 845 | ||
| 823 | // Disable interrupts | 846 | // Disable interrupts |
| 824 | T::REGS.ier().modify(|w| { | 847 | T::regs().ier().modify(|w| { |
| 825 | w.set_eoaie(false); | 848 | w.set_eoaie(false); |
| 826 | w.set_mceie(false); | 849 | w.set_mceie(false); |
| 827 | }); | 850 | }); |
| 828 | 851 | ||
| 829 | // Clear flags | 852 | // Clear flags |
| 830 | T::REGS.icr().modify(|w| { | 853 | T::regs().icr().modify(|w| { |
| 831 | w.set_eoaic(true); | 854 | w.set_eoaic(true); |
| 832 | w.set_mceic(true); | 855 | w.set_mceic(true); |
| 833 | }); | 856 | }); |
| @@ -840,11 +863,31 @@ impl<'d, T: Instance> Tsc<'d, T> { | |||
| 840 | while self.get_state() == State::Busy {} | 863 | while self.get_state() == State::Busy {} |
| 841 | } | 864 | } |
| 842 | 865 | ||
| 866 | /// Asyncronously wait for the end of an acquisition | ||
| 867 | pub async fn pend_for_acquisition(&mut self) { | ||
| 868 | poll_fn(|cx| match self.get_state() { | ||
| 869 | State::Busy => { | ||
| 870 | T::waker().register(cx.waker()); | ||
| 871 | T::regs().ier().write(|w| w.set_eoaie(true)); | ||
| 872 | if self.get_state() != State::Busy { | ||
| 873 | T::regs().ier().write(|w| w.set_eoaie(false)); | ||
| 874 | return Poll::Ready(()); | ||
| 875 | } | ||
| 876 | Poll::Pending | ||
| 877 | } | ||
| 878 | _ => { | ||
| 879 | T::regs().ier().write(|w| w.set_eoaie(false)); | ||
| 880 | Poll::Ready(()) | ||
| 881 | } | ||
| 882 | }) | ||
| 883 | .await; | ||
| 884 | } | ||
| 885 | |||
| 843 | /// Get current state of acquisition | 886 | /// Get current state of acquisition |
| 844 | pub fn get_state(&mut self) -> State { | 887 | pub fn get_state(&mut self) -> State { |
| 845 | if self.state == State::Busy { | 888 | if self.state == State::Busy { |
| 846 | if T::REGS.isr().read().eoaf() { | 889 | if T::regs().isr().read().eoaf() { |
| 847 | if T::REGS.isr().read().mcef() { | 890 | if T::regs().isr().read().mcef() { |
| 848 | self.state = State::Error | 891 | self.state = State::Error |
| 849 | } else { | 892 | } else { |
| 850 | self.state = State::Ready | 893 | self.state = State::Ready |
| @@ -859,16 +902,16 @@ impl<'d, T: Instance> Tsc<'d, T> { | |||
| 859 | // Status bits are set by hardware when the acquisition on the corresponding | 902 | // Status bits are set by hardware when the acquisition on the corresponding |
| 860 | // enabled analog IO group is complete, cleared when new acquisition is started | 903 | // enabled analog IO group is complete, cleared when new acquisition is started |
| 861 | let status = match index { | 904 | let status = match index { |
| 862 | Group::One => T::REGS.iogcsr().read().g1s(), | 905 | Group::One => T::regs().iogcsr().read().g1s(), |
| 863 | Group::Two => T::REGS.iogcsr().read().g2s(), | 906 | Group::Two => T::regs().iogcsr().read().g2s(), |
| 864 | Group::Three => T::REGS.iogcsr().read().g3s(), | 907 | Group::Three => T::regs().iogcsr().read().g3s(), |
| 865 | Group::Four => T::REGS.iogcsr().read().g4s(), | 908 | Group::Four => T::regs().iogcsr().read().g4s(), |
| 866 | Group::Five => T::REGS.iogcsr().read().g5s(), | 909 | Group::Five => T::regs().iogcsr().read().g5s(), |
| 867 | Group::Six => T::REGS.iogcsr().read().g6s(), | 910 | Group::Six => T::regs().iogcsr().read().g6s(), |
| 868 | #[cfg(any(tsc_v2, tsc_v3))] | 911 | #[cfg(any(tsc_v2, tsc_v3))] |
| 869 | Group::Seven => T::REGS.iogcsr().read().g7s(), | 912 | Group::Seven => T::regs().iogcsr().read().g7s(), |
| 870 | #[cfg(tsc_v3)] | 913 | #[cfg(tsc_v3)] |
| 871 | Group::Eight => T::REGS.iogcsr().read().g8s(), | 914 | Group::Eight => T::regs().iogcsr().read().g8s(), |
| 872 | }; | 915 | }; |
| 873 | match status { | 916 | match status { |
| 874 | true => GroupStatus::Complete, | 917 | true => GroupStatus::Complete, |
| @@ -878,13 +921,13 @@ impl<'d, T: Instance> Tsc<'d, T> { | |||
| 878 | 921 | ||
| 879 | /// Get the count for the acquisiton, valid once group status is set | 922 | /// Get the count for the acquisiton, valid once group status is set |
| 880 | pub fn group_get_value(&mut self, index: Group) -> u16 { | 923 | pub fn group_get_value(&mut self, index: Group) -> u16 { |
| 881 | T::REGS.iogcr(index.into()).read().cnt() | 924 | T::regs().iogcr(index.into()).read().cnt() |
| 882 | } | 925 | } |
| 883 | 926 | ||
| 884 | /// Discharge the IOs for subsequent acquisition | 927 | /// Discharge the IOs for subsequent acquisition |
| 885 | pub fn discharge_io(&mut self, status: bool) { | 928 | pub fn discharge_io(&mut self, status: bool) { |
| 886 | // Set the touch sensing IOs in low power mode | 929 | // Set the touch sensing IOs in low power mode |
| 887 | T::REGS.cr().modify(|w| { | 930 | T::regs().cr().modify(|w| { |
| 888 | w.set_iodef(!status); | 931 | w.set_iodef(!status); |
| 889 | }); | 932 | }); |
| 890 | } | 933 | } |
| @@ -897,20 +940,32 @@ impl<'d, T: Instance> Drop for Tsc<'d, T> { | |||
| 897 | } | 940 | } |
| 898 | 941 | ||
| 899 | pub(crate) trait SealedInstance { | 942 | pub(crate) trait SealedInstance { |
| 900 | const REGS: Regs; | 943 | fn regs() -> crate::pac::tsc::Tsc; |
| 944 | fn waker() -> &'static AtomicWaker; | ||
| 901 | } | 945 | } |
| 902 | 946 | ||
| 903 | /// TSC instance trait | 947 | /// TSC instance trait |
| 904 | #[allow(private_bounds)] | 948 | #[allow(private_bounds)] |
| 905 | pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {} | 949 | pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral { |
| 950 | /// Interrupt for this TSC instance | ||
| 951 | type Interrupt: interrupt::typelevel::Interrupt; | ||
| 952 | } | ||
| 906 | 953 | ||
| 907 | foreach_peripheral!( | 954 | foreach_interrupt!( |
| 908 | (tsc, $inst:ident) => { | 955 | ($inst:ident, tsc, TSC, GLOBAL, $irq:ident) => { |
| 909 | impl SealedInstance for peripherals::$inst { | 956 | impl Instance for peripherals::$inst { |
| 910 | const REGS: Regs = crate::pac::$inst; | 957 | type Interrupt = crate::interrupt::typelevel::$irq; |
| 911 | } | 958 | } |
| 912 | 959 | ||
| 913 | impl Instance for peripherals::$inst {} | 960 | impl SealedInstance for peripherals::$inst { |
| 961 | fn regs() -> crate::pac::tsc::Tsc { | ||
| 962 | crate::pac::$inst | ||
| 963 | } | ||
| 964 | fn waker() -> &'static AtomicWaker { | ||
| 965 | static WAKER: AtomicWaker = AtomicWaker::new(); | ||
| 966 | &WAKER | ||
| 967 | } | ||
| 968 | } | ||
| 914 | }; | 969 | }; |
| 915 | ); | 970 | ); |
| 916 | 971 | ||
