diff options
| author | Ulf Lilleengen <[email protected]> | 2024-07-02 18:51:50 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-07-02 18:51:50 +0000 |
| commit | 5223923bd2f8d02d53f02329836a42f2d5ccc746 (patch) | |
| tree | d81024aa594729397f281546d0b0b0ab47e345c9 /embassy-stm32 | |
| parent | 14435d095f70cc25f592332ddc194dfa15117486 (diff) | |
| parent | d3f8905e938eecfe7789841c6232cb34b5f43a20 (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.rs | 271 |
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 |
| 66 | pub mod enums; | 66 | pub mod enums; |
| 67 | 67 | ||
| 68 | use core::future::poll_fn; | ||
| 68 | use core::marker::PhantomData; | 69 | use core::marker::PhantomData; |
| 70 | use core::task::Poll; | ||
| 69 | 71 | ||
| 70 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 72 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 73 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 71 | pub use enums::*; | 74 | pub use enums::*; |
| 72 | 75 | ||
| 73 | use crate::gpio::{AfType, AnyPin, OutputType, Speed}; | 76 | use crate::gpio::{AfType, AnyPin, OutputType, Speed}; |
| 74 | use crate::pac::tsc::Tsc as Regs; | 77 | use crate::interrupt::typelevel::Interrupt; |
| 78 | use crate::mode::{Async, Blocking, Mode as PeriMode}; | ||
| 75 | use crate::rcc::{self, RccPeripheral}; | 79 | use crate::rcc::{self, RccPeripheral}; |
| 76 | use crate::{peripherals, Peripheral}; | 80 | use crate::{interrupt, peripherals, Peripheral}; |
| 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 |
| @@ -490,7 +506,7 @@ pub enum G7 {} | |||
| 490 | pub enum G8 {} | 506 | pub enum G8 {} |
| 491 | 507 | ||
| 492 | /// TSC driver | 508 | /// TSC driver |
| 493 | pub struct Tsc<'d, T: Instance> { | 509 | pub 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 | ||
| 509 | impl<'d, T: Instance> Tsc<'d, T> { | 526 | impl<'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 | |||
| 616 | impl<'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 | ||
| 690 | impl<'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 | ||
| 893 | impl<'d, T: Instance> Drop for Tsc<'d, T> { | 956 | impl<'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 | ||
| 899 | pub(crate) trait SealedInstance { | 962 | pub(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)] |
| 905 | pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {} | 969 | pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral { |
| 970 | /// Interrupt for this TSC instance | ||
| 971 | type Interrupt: interrupt::typelevel::Interrupt; | ||
| 972 | } | ||
| 906 | 973 | ||
| 907 | foreach_peripheral!( | 974 | foreach_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 | ||
