aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorUlf Lilleengen <[email protected]>2024-07-02 18:51:50 +0000
committerGitHub <[email protected]>2024-07-02 18:51:50 +0000
commit5223923bd2f8d02d53f02329836a42f2d5ccc746 (patch)
treed81024aa594729397f281546d0b0b0ab47e345c9 /embassy-stm32
parent14435d095f70cc25f592332ddc194dfa15117486 (diff)
parentd3f8905e938eecfe7789841c6232cb34b5f43a20 (diff)
Merge pull request #3111 from Eekle/feature/async_tsc
Add async API to TSC
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/src/tsc/mod.rs271
1 files changed, 173 insertions, 98 deletions
diff --git a/embassy-stm32/src/tsc/mod.rs b/embassy-stm32/src/tsc/mod.rs
index 8ba208ce7..5cb58e918 100644
--- a/embassy-stm32/src/tsc/mod.rs
+++ b/embassy-stm32/src/tsc/mod.rs
@@ -65,15 +65,19 @@
65/// Enums defined for peripheral parameters 65/// Enums defined for peripheral parameters
66pub mod enums; 66pub mod enums;
67 67
68use core::future::poll_fn;
68use core::marker::PhantomData; 69use core::marker::PhantomData;
70use core::task::Poll;
69 71
70use embassy_hal_internal::{into_ref, PeripheralRef}; 72use embassy_hal_internal::{into_ref, PeripheralRef};
73use embassy_sync::waitqueue::AtomicWaker;
71pub use enums::*; 74pub use enums::*;
72 75
73use crate::gpio::{AfType, AnyPin, OutputType, Speed}; 76use crate::gpio::{AfType, AnyPin, OutputType, Speed};
74use crate::pac::tsc::Tsc as Regs; 77use crate::interrupt::typelevel::Interrupt;
78use crate::mode::{Async, Blocking, Mode as PeriMode};
75use crate::rcc::{self, RccPeripheral}; 79use crate::rcc::{self, RccPeripheral};
76use crate::{peripherals, Peripheral}; 80use crate::{interrupt, peripherals, Peripheral};
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
@@ -490,7 +506,7 @@ pub enum G7 {}
490pub enum G8 {} 506pub enum G8 {}
491 507
492/// TSC driver 508/// TSC driver
493pub struct Tsc<'d, T: Instance> { 509pub struct Tsc<'d, T: Instance, K: PeriMode> {
494 _peri: PeripheralRef<'d, T>, 510 _peri: PeripheralRef<'d, T>,
495 _g1: Option<PinGroup<'d, T, G1>>, 511 _g1: Option<PinGroup<'d, T, G1>>,
496 _g2: Option<PinGroup<'d, T, G2>>, 512 _g2: Option<PinGroup<'d, T, G2>>,
@@ -504,11 +520,102 @@ pub struct Tsc<'d, T: Instance> {
504 _g8: Option<PinGroup<'d, T, G8>>, 520 _g8: Option<PinGroup<'d, T, G8>>,
505 state: State, 521 state: State,
506 config: Config, 522 config: Config,
523 _kind: PhantomData<K>,
507} 524}
508 525
509impl<'d, T: Instance> Tsc<'d, T> { 526impl<'d, T: Instance> Tsc<'d, T, Async> {
510 /// Create new TSC driver 527 /// Create a Tsc instance that can be awaited for completion
511 pub fn new( 528 pub fn new_async(
529 peri: impl Peripheral<P = T> + 'd,
530 g1: Option<PinGroup<'d, T, G1>>,
531 g2: Option<PinGroup<'d, T, G2>>,
532 g3: Option<PinGroup<'d, T, G3>>,
533 g4: Option<PinGroup<'d, T, G4>>,
534 g5: Option<PinGroup<'d, T, G5>>,
535 g6: Option<PinGroup<'d, T, G6>>,
536 #[cfg(any(tsc_v2, tsc_v3))] g7: Option<PinGroup<'d, T, G7>>,
537 #[cfg(tsc_v3)] g8: Option<PinGroup<'d, T, G8>>,
538 config: Config,
539 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
540 ) -> Self {
541 // Need to check valid pin configuration input
542 let g1 = g1.filter(|b| b.check_group().is_ok());
543 let g2 = g2.filter(|b| b.check_group().is_ok());
544 let g3 = g3.filter(|b| b.check_group().is_ok());
545 let g4 = g4.filter(|b| b.check_group().is_ok());
546 let g5 = g5.filter(|b| b.check_group().is_ok());
547 let g6 = g6.filter(|b| b.check_group().is_ok());
548 #[cfg(any(tsc_v2, tsc_v3))]
549 let g7 = g7.filter(|b| b.check_group().is_ok());
550 #[cfg(tsc_v3)]
551 let g8 = g8.filter(|b| b.check_group().is_ok());
552
553 match Self::check_shields(
554 &g1,
555 &g2,
556 &g3,
557 &g4,
558 &g5,
559 &g6,
560 #[cfg(any(tsc_v2, tsc_v3))]
561 &g7,
562 #[cfg(tsc_v3)]
563 &g8,
564 ) {
565 Ok(()) => Self::new_inner(
566 peri,
567 g1,
568 g2,
569 g3,
570 g4,
571 g5,
572 g6,
573 #[cfg(any(tsc_v2, tsc_v3))]
574 g7,
575 #[cfg(tsc_v3)]
576 g8,
577 config,
578 ),
579 Err(_) => Self::new_inner(
580 peri,
581 None,
582 None,
583 None,
584 None,
585 None,
586 None,
587 #[cfg(any(tsc_v2, tsc_v3))]
588 None,
589 #[cfg(tsc_v3)]
590 None,
591 config,
592 ),
593 }
594 }
595 /// Asyncronously wait for the end of an acquisition
596 pub async fn pend_for_acquisition(&mut self) {
597 poll_fn(|cx| match self.get_state() {
598 State::Busy => {
599 T::waker().register(cx.waker());
600 T::regs().ier().write(|w| w.set_eoaie(true));
601 if self.get_state() != State::Busy {
602 T::regs().ier().write(|w| w.set_eoaie(false));
603 return Poll::Ready(());
604 }
605 Poll::Pending
606 }
607 _ => {
608 T::regs().ier().write(|w| w.set_eoaie(false));
609 Poll::Ready(())
610 }
611 })
612 .await;
613 }
614}
615
616impl<'d, T: Instance> Tsc<'d, T, Blocking> {
617 /// Create a Tsc instance that must be polled for completion
618 pub fn new_blocking(
512 peri: impl Peripheral<P = T> + 'd, 619 peri: impl Peripheral<P = T> + 'd,
513 g1: Option<PinGroup<'d, T, G1>>, 620 g1: Option<PinGroup<'d, T, G1>>,
514 g2: Option<PinGroup<'d, T, G2>>, 621 g2: Option<PinGroup<'d, T, G2>>,
@@ -574,7 +681,14 @@ impl<'d, T: Instance> Tsc<'d, T> {
574 ), 681 ),
575 } 682 }
576 } 683 }
684 /// Wait for end of acquisition
685 pub fn poll_for_acquisition(&mut self) {
686 while self.get_state() == State::Busy {}
687 }
688}
577 689
690impl<'d, T: Instance, K: PeriMode> Tsc<'d, T, K> {
691 /// Create new TSC driver
578 fn check_shields( 692 fn check_shields(
579 g1: &Option<PinGroup<'d, T, G1>>, 693 g1: &Option<PinGroup<'d, T, G1>>,
580 g2: &Option<PinGroup<'d, T, G2>>, 694 g2: &Option<PinGroup<'d, T, G2>>,
@@ -663,7 +777,7 @@ impl<'d, T: Instance> Tsc<'d, T> {
663 777
664 rcc::enable_and_reset::<T>(); 778 rcc::enable_and_reset::<T>();
665 779
666 T::REGS.cr().modify(|w| { 780 T::regs().cr().modify(|w| {
667 w.set_tsce(true); 781 w.set_tsce(true);
668 w.set_ctph(config.ct_pulse_high_length.into()); 782 w.set_ctph(config.ct_pulse_high_length.into());
669 w.set_ctpl(config.ct_pulse_low_length.into()); 783 w.set_ctpl(config.ct_pulse_low_length.into());
@@ -691,33 +805,39 @@ impl<'d, T: Instance> Tsc<'d, T> {
691 805
692 // Set IO configuration 806 // Set IO configuration
693 // Disable Schmitt trigger hysteresis on all used TSC IOs 807 // Disable Schmitt trigger hysteresis on all used TSC IOs
694 T::REGS 808 T::regs()
695 .iohcr() 809 .iohcr()
696 .write(|w| w.0 = !(config.channel_ios | config.shield_ios | config.sampling_ios)); 810 .write(|w| w.0 = !(config.channel_ios | config.shield_ios | config.sampling_ios));
697 811
698 // Set channel and shield IOs 812 // Set channel and shield IOs
699 T::REGS.ioccr().write(|w| w.0 = config.channel_ios | config.shield_ios); 813 T::regs()
814 .ioccr()
815 .write(|w| w.0 = config.channel_ios | config.shield_ios);
700 816
701 // Set sampling IOs 817 // Set sampling IOs
702 T::REGS.ioscr().write(|w| w.0 = config.sampling_ios); 818 T::regs().ioscr().write(|w| w.0 = config.sampling_ios);
703 819
704 // Set the groups to be acquired 820 // Set the groups to be acquired
705 T::REGS 821 T::regs()
706 .iogcsr() 822 .iogcsr()
707 .write(|w| w.0 = Self::extract_groups(config.channel_ios)); 823 .write(|w| w.0 = Self::extract_groups(config.channel_ios));
708 824
709 // Disable interrupts 825 // Disable interrupts
710 T::REGS.ier().modify(|w| { 826 T::regs().ier().modify(|w| {
711 w.set_eoaie(false); 827 w.set_eoaie(false);
712 w.set_mceie(false); 828 w.set_mceie(false);
713 }); 829 });
714 830
715 // Clear flags 831 // Clear flags
716 T::REGS.icr().modify(|w| { 832 T::regs().icr().modify(|w| {
717 w.set_eoaic(true); 833 w.set_eoaic(true);
718 w.set_mceic(true); 834 w.set_mceic(true);
719 }); 835 });
720 836
837 unsafe {
838 T::Interrupt::enable();
839 }
840
721 Self { 841 Self {
722 _peri: peri, 842 _peri: peri,
723 _g1: g1, 843 _g1: g1,
@@ -732,6 +852,7 @@ impl<'d, T: Instance> Tsc<'d, T> {
732 _g8: g8, 852 _g8: g8,
733 state: State::Ready, 853 state: State::Ready,
734 config, 854 config,
855 _kind: PhantomData,
735 } 856 }
736 } 857 }
737 858
@@ -740,68 +861,41 @@ impl<'d, T: Instance> Tsc<'d, T> {
740 self.state = State::Busy; 861 self.state = State::Busy;
741 862
742 // Disable interrupts 863 // Disable interrupts
743 T::REGS.ier().modify(|w| { 864 T::regs().ier().modify(|w| {
744 w.set_eoaie(false); 865 w.set_eoaie(false);
745 w.set_mceie(false); 866 w.set_mceie(false);
746 }); 867 });
747 868
748 // Clear flags 869 // Clear flags
749 T::REGS.icr().modify(|w| { 870 T::regs().icr().modify(|w| {
750 w.set_eoaic(true); 871 w.set_eoaic(true);
751 w.set_mceic(true); 872 w.set_mceic(true);
752 }); 873 });
753 874
754 // Set the touch sensing IOs not acquired to the default mode 875 // Set the touch sensing IOs not acquired to the default mode
755 T::REGS.cr().modify(|w| { 876 T::regs().cr().modify(|w| {
756 w.set_iodef(self.config.io_default_mode); 877 w.set_iodef(self.config.io_default_mode);
757 }); 878 });
758 879
759 // Start the acquisition 880 // Start the acquisition
760 T::REGS.cr().modify(|w| { 881 T::regs().cr().modify(|w| {
761 w.set_start(true);
762 });
763 }
764
765 /// Start charge transfer acquisition with interrupts enabled
766 pub fn start_it(&mut self) {
767 self.state = State::Busy;
768
769 // Enable interrupts
770 T::REGS.ier().modify(|w| {
771 w.set_eoaie(true);
772 w.set_mceie(self.config.max_count_interrupt);
773 });
774
775 // Clear flags
776 T::REGS.icr().modify(|w| {
777 w.set_eoaic(true);
778 w.set_mceic(true);
779 });
780
781 // Set the touch sensing IOs not acquired to the default mode
782 T::REGS.cr().modify(|w| {
783 w.set_iodef(self.config.io_default_mode);
784 });
785
786 // Start the acquisition
787 T::REGS.cr().modify(|w| {
788 w.set_start(true); 882 w.set_start(true);
789 }); 883 });
790 } 884 }
791 885
792 /// Stop charge transfer acquisition 886 /// Stop charge transfer acquisition
793 pub fn stop(&mut self) { 887 pub fn stop(&mut self) {
794 T::REGS.cr().modify(|w| { 888 T::regs().cr().modify(|w| {
795 w.set_start(false); 889 w.set_start(false);
796 }); 890 });
797 891
798 // Set the touch sensing IOs in low power mode 892 // Set the touch sensing IOs in low power mode
799 T::REGS.cr().modify(|w| { 893 T::regs().cr().modify(|w| {
800 w.set_iodef(false); 894 w.set_iodef(false);
801 }); 895 });
802 896
803 // Clear flags 897 // Clear flags
804 T::REGS.icr().modify(|w| { 898 T::regs().icr().modify(|w| {
805 w.set_eoaic(true); 899 w.set_eoaic(true);
806 w.set_mceic(true); 900 w.set_mceic(true);
807 }); 901 });
@@ -809,42 +903,11 @@ impl<'d, T: Instance> Tsc<'d, T> {
809 self.state = State::Ready; 903 self.state = State::Ready;
810 } 904 }
811 905
812 /// Stop charge transfer acquisition and clear interrupts
813 pub fn stop_it(&mut self) {
814 T::REGS.cr().modify(|w| {
815 w.set_start(false);
816 });
817
818 // Set the touch sensing IOs in low power mode
819 T::REGS.cr().modify(|w| {
820 w.set_iodef(false);
821 });
822
823 // Disable interrupts
824 T::REGS.ier().modify(|w| {
825 w.set_eoaie(false);
826 w.set_mceie(false);
827 });
828
829 // Clear flags
830 T::REGS.icr().modify(|w| {
831 w.set_eoaic(true);
832 w.set_mceic(true);
833 });
834
835 self.state = State::Ready;
836 }
837
838 /// Wait for end of acquisition
839 pub fn poll_for_acquisition(&mut self) {
840 while self.get_state() == State::Busy {}
841 }
842
843 /// Get current state of acquisition 906 /// Get current state of acquisition
844 pub fn get_state(&mut self) -> State { 907 pub fn get_state(&mut self) -> State {
845 if self.state == State::Busy { 908 if self.state == State::Busy {
846 if T::REGS.isr().read().eoaf() { 909 if T::regs().isr().read().eoaf() {
847 if T::REGS.isr().read().mcef() { 910 if T::regs().isr().read().mcef() {
848 self.state = State::Error 911 self.state = State::Error
849 } else { 912 } else {
850 self.state = State::Ready 913 self.state = State::Ready
@@ -859,16 +922,16 @@ impl<'d, T: Instance> Tsc<'d, T> {
859 // Status bits are set by hardware when the acquisition on the corresponding 922 // 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 923 // enabled analog IO group is complete, cleared when new acquisition is started
861 let status = match index { 924 let status = match index {
862 Group::One => T::REGS.iogcsr().read().g1s(), 925 Group::One => T::regs().iogcsr().read().g1s(),
863 Group::Two => T::REGS.iogcsr().read().g2s(), 926 Group::Two => T::regs().iogcsr().read().g2s(),
864 Group::Three => T::REGS.iogcsr().read().g3s(), 927 Group::Three => T::regs().iogcsr().read().g3s(),
865 Group::Four => T::REGS.iogcsr().read().g4s(), 928 Group::Four => T::regs().iogcsr().read().g4s(),
866 Group::Five => T::REGS.iogcsr().read().g5s(), 929 Group::Five => T::regs().iogcsr().read().g5s(),
867 Group::Six => T::REGS.iogcsr().read().g6s(), 930 Group::Six => T::regs().iogcsr().read().g6s(),
868 #[cfg(any(tsc_v2, tsc_v3))] 931 #[cfg(any(tsc_v2, tsc_v3))]
869 Group::Seven => T::REGS.iogcsr().read().g7s(), 932 Group::Seven => T::regs().iogcsr().read().g7s(),
870 #[cfg(tsc_v3)] 933 #[cfg(tsc_v3)]
871 Group::Eight => T::REGS.iogcsr().read().g8s(), 934 Group::Eight => T::regs().iogcsr().read().g8s(),
872 }; 935 };
873 match status { 936 match status {
874 true => GroupStatus::Complete, 937 true => GroupStatus::Complete,
@@ -878,39 +941,51 @@ impl<'d, T: Instance> Tsc<'d, T> {
878 941
879 /// Get the count for the acquisiton, valid once group status is set 942 /// Get the count for the acquisiton, valid once group status is set
880 pub fn group_get_value(&mut self, index: Group) -> u16 { 943 pub fn group_get_value(&mut self, index: Group) -> u16 {
881 T::REGS.iogcr(index.into()).read().cnt() 944 T::regs().iogcr(index.into()).read().cnt()
882 } 945 }
883 946
884 /// Discharge the IOs for subsequent acquisition 947 /// Discharge the IOs for subsequent acquisition
885 pub fn discharge_io(&mut self, status: bool) { 948 pub fn discharge_io(&mut self, status: bool) {
886 // Set the touch sensing IOs in low power mode 949 // Set the touch sensing IOs in low power mode
887 T::REGS.cr().modify(|w| { 950 T::regs().cr().modify(|w| {
888 w.set_iodef(!status); 951 w.set_iodef(!status);
889 }); 952 });
890 } 953 }
891} 954}
892 955
893impl<'d, T: Instance> Drop for Tsc<'d, T> { 956impl<'d, T: Instance, K: PeriMode> Drop for Tsc<'d, T, K> {
894 fn drop(&mut self) { 957 fn drop(&mut self) {
895 rcc::disable::<T>(); 958 rcc::disable::<T>();
896 } 959 }
897} 960}
898 961
899pub(crate) trait SealedInstance { 962pub(crate) trait SealedInstance {
900 const REGS: Regs; 963 fn regs() -> crate::pac::tsc::Tsc;
964 fn waker() -> &'static AtomicWaker;
901} 965}
902 966
903/// TSC instance trait 967/// TSC instance trait
904#[allow(private_bounds)] 968#[allow(private_bounds)]
905pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {} 969pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {
970 /// Interrupt for this TSC instance
971 type Interrupt: interrupt::typelevel::Interrupt;
972}
906 973
907foreach_peripheral!( 974foreach_interrupt!(
908 (tsc, $inst:ident) => { 975 ($inst:ident, tsc, TSC, GLOBAL, $irq:ident) => {
909 impl SealedInstance for peripherals::$inst { 976 impl Instance for peripherals::$inst {
910 const REGS: Regs = crate::pac::$inst; 977 type Interrupt = crate::interrupt::typelevel::$irq;
911 } 978 }
912 979
913 impl Instance for peripherals::$inst {} 980 impl SealedInstance for peripherals::$inst {
981 fn regs() -> crate::pac::tsc::Tsc {
982 crate::pac::$inst
983 }
984 fn waker() -> &'static AtomicWaker {
985 static WAKER: AtomicWaker = AtomicWaker::new();
986 &WAKER
987 }
988 }
914 }; 989 };
915); 990);
916 991