aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorEekle <[email protected]>2024-06-23 16:43:12 +0200
committerEekle <[email protected]>2024-06-23 16:43:12 +0200
commit2655426cd80b828593c8cd60930da3ebbd60e85c (patch)
tree4553255a9f6b854e7d60f609004a10a39b0c3fe0 /embassy-stm32
parentd5badb94d2098b0360ed1ab8015c37f819771445 (diff)
Add async wait to TSC
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/src/tsc/mod.rs139
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};
71pub use enums::*; 71pub use enums::*;
72 72
73use crate::gpio::{AfType, AnyPin, OutputType, Speed}; 73use crate::gpio::{AfType, AnyPin, OutputType, Speed};
74use crate::pac::tsc::Tsc as Regs; 74use crate::interrupt;
75use crate::interrupt::typelevel::Interrupt;
75use crate::rcc::{self, RccPeripheral}; 76use crate::rcc::{self, RccPeripheral};
76use crate::{peripherals, Peripheral}; 77use crate::{peripherals, Peripheral};
78use core::future::poll_fn;
79use core::task::Poll;
80use embassy_sync::waitqueue::AtomicWaker;
77 81
78#[cfg(tsc_v1)] 82#[cfg(tsc_v1)]
79const TSC_NUM_GROUPS: u32 = 6; 83const TSC_NUM_GROUPS: u32 = 6;
@@ -90,6 +94,18 @@ pub enum Error {
90 Test, 94 Test,
91} 95}
92 96
97/// TSC interrupt handler.
98pub struct InterruptHandler<T: Instance> {
99 _phantom: PhantomData<T>,
100}
101
102impl<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
94pub enum PinType { 110pub 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
899pub(crate) trait SealedInstance { 942pub(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)]
905pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {} 949pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {
950 /// Interrupt for this TSC instance
951 type Interrupt: interrupt::typelevel::Interrupt;
952}
906 953
907foreach_peripheral!( 954foreach_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