diff options
Diffstat (limited to 'src/gpio.rs')
| -rw-r--r-- | src/gpio.rs | 243 |
1 files changed, 242 insertions, 1 deletions
diff --git a/src/gpio.rs b/src/gpio.rs index 4f79aff93..332c4c8b2 100644 --- a/src/gpio.rs +++ b/src/gpio.rs | |||
| @@ -3,13 +3,96 @@ | |||
| 3 | //! concrete pin type. | 3 | //! concrete pin type. |
| 4 | 4 | ||
| 5 | use core::convert::Infallible; | 5 | use core::convert::Infallible; |
| 6 | use core::future::Future; | ||
| 6 | use core::marker::PhantomData; | 7 | use core::marker::PhantomData; |
| 8 | use core::pin::pin; | ||
| 7 | 9 | ||
| 8 | use embassy_hal_internal::{Peri, PeripheralType}; | 10 | use embassy_hal_internal::{Peri, PeripheralType}; |
| 11 | use maitake_sync::WaitMap; | ||
| 9 | use paste::paste; | 12 | use paste::paste; |
| 10 | 13 | ||
| 14 | use crate::pac::interrupt; | ||
| 11 | use crate::pac::port0::pcr0::{Dse, Inv, Mux, Pe, Ps, Sre}; | 15 | use crate::pac::port0::pcr0::{Dse, Inv, Mux, Pe, Ps, Sre}; |
| 12 | 16 | ||
| 17 | struct BitIter(u32); | ||
| 18 | |||
| 19 | impl Iterator for BitIter { | ||
| 20 | type Item = usize; | ||
| 21 | |||
| 22 | fn next(&mut self) -> Option<Self::Item> { | ||
| 23 | match self.0.trailing_zeros() { | ||
| 24 | 32 => None, | ||
| 25 | b => { | ||
| 26 | self.0 &= !(1 << b); | ||
| 27 | Some(b as usize) | ||
| 28 | } | ||
| 29 | } | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | const PORT_COUNT: usize = 5; | ||
| 34 | |||
| 35 | static PORT_WAIT_MAPS: [WaitMap<usize, ()>; PORT_COUNT] = [ | ||
| 36 | WaitMap::new(), | ||
| 37 | WaitMap::new(), | ||
| 38 | WaitMap::new(), | ||
| 39 | WaitMap::new(), | ||
| 40 | WaitMap::new(), | ||
| 41 | ]; | ||
| 42 | |||
| 43 | fn irq_handler(port_index: usize, gpio_base: *const crate::pac::gpio0::RegisterBlock) { | ||
| 44 | let gpio = unsafe { &*gpio_base }; | ||
| 45 | let isfr = gpio.isfr0().read().bits(); | ||
| 46 | |||
| 47 | for pin in BitIter(isfr) { | ||
| 48 | // Clear all pending interrupts | ||
| 49 | gpio.isfr0().write(|w| unsafe { w.bits(1 << pin) }); | ||
| 50 | gpio.icr(pin).modify(|_, w| w.irqc().irqc0()); // Disable interrupt | ||
| 51 | |||
| 52 | // Wake the corresponding port waker | ||
| 53 | if let Some(w) = PORT_WAIT_MAPS.get(port_index) { | ||
| 54 | w.wake(&pin, ()); | ||
| 55 | } | ||
| 56 | } | ||
| 57 | } | ||
| 58 | |||
| 59 | #[interrupt] | ||
| 60 | fn GPIO0() { | ||
| 61 | irq_handler(0, crate::pac::Gpio0::ptr()); | ||
| 62 | } | ||
| 63 | |||
| 64 | #[interrupt] | ||
| 65 | fn GPIO1() { | ||
| 66 | irq_handler(1, crate::pac::Gpio1::ptr()); | ||
| 67 | } | ||
| 68 | |||
| 69 | #[interrupt] | ||
| 70 | fn GPIO2() { | ||
| 71 | irq_handler(2, crate::pac::Gpio2::ptr()); | ||
| 72 | } | ||
| 73 | |||
| 74 | #[interrupt] | ||
| 75 | fn GPIO3() { | ||
| 76 | irq_handler(3, crate::pac::Gpio3::ptr()); | ||
| 77 | } | ||
| 78 | |||
| 79 | #[interrupt] | ||
| 80 | fn GPIO4() { | ||
| 81 | irq_handler(4, crate::pac::Gpio4::ptr()); | ||
| 82 | } | ||
| 83 | |||
| 84 | pub(crate) unsafe fn init() { | ||
| 85 | use embassy_hal_internal::interrupt::InterruptExt; | ||
| 86 | |||
| 87 | crate::pac::interrupt::GPIO0.enable(); | ||
| 88 | crate::pac::interrupt::GPIO1.enable(); | ||
| 89 | crate::pac::interrupt::GPIO2.enable(); | ||
| 90 | crate::pac::interrupt::GPIO3.enable(); | ||
| 91 | crate::pac::interrupt::GPIO4.enable(); | ||
| 92 | |||
| 93 | cortex_m::interrupt::enable(); | ||
| 94 | } | ||
| 95 | |||
| 13 | /// Logical level for GPIO pins. | 96 | /// Logical level for GPIO pins. |
| 14 | #[derive(Copy, Clone, Eq, PartialEq, Debug)] | 97 | #[derive(Copy, Clone, Eq, PartialEq, Debug)] |
| 15 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 98 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -598,6 +681,77 @@ impl<'d> Flex<'d> { | |||
| 598 | } | 681 | } |
| 599 | } | 682 | } |
| 600 | 683 | ||
| 684 | /// Async methods | ||
| 685 | impl<'d> Flex<'d> { | ||
| 686 | /// Helper function that waits for a given interrupt trigger | ||
| 687 | async fn wait_for_inner(&mut self, level: crate::pac::gpio0::icr::Irqc) { | ||
| 688 | // First, ensure that we have a waker that is ready for this port+pin | ||
| 689 | let w = PORT_WAIT_MAPS[self.pin.port].wait(self.pin.pin); | ||
| 690 | let mut w = pin!(w); | ||
| 691 | // Wait for the subscription to occur, which requires polling at least once | ||
| 692 | // | ||
| 693 | // This function returns a result, but can only be an Err if: | ||
| 694 | // | ||
| 695 | // * We call `.close()` on a WaitMap, which we never do | ||
| 696 | // * We have a duplicate key, which can't happen because `wait_for_*` methods | ||
| 697 | // take an &mut ref of their unique port+pin combo | ||
| 698 | // | ||
| 699 | // So we wait for it to complete, but ignore the result. | ||
| 700 | _ = w.as_mut().subscribe().await; | ||
| 701 | |||
| 702 | // Now that our waker is in the map, we can enable the appropriate interrupt | ||
| 703 | // | ||
| 704 | // Clear any existing pending interrupt on this pin | ||
| 705 | self.pin | ||
| 706 | .gpio() | ||
| 707 | .isfr0() | ||
| 708 | .write(|w| unsafe { w.bits(1 << self.pin.pin()) }); | ||
| 709 | self.pin.gpio().icr(self.pin.pin()).write(|w| w.isf().isf1()); | ||
| 710 | |||
| 711 | // Pin interrupt configuration | ||
| 712 | self.pin | ||
| 713 | .gpio() | ||
| 714 | .icr(self.pin.pin()) | ||
| 715 | .modify(|_, w| w.irqc().variant(level)); | ||
| 716 | |||
| 717 | // Finally, we can await the matching call to `.wake()` from the interrupt. | ||
| 718 | // | ||
| 719 | // Again, technically, this could return a result, but for the same reasons | ||
| 720 | // as above, this can't be an error in our case, so just wait for it to complete | ||
| 721 | _ = w.await; | ||
| 722 | } | ||
| 723 | |||
| 724 | /// Wait until the pin is high. If it is already high, return immediately. | ||
| 725 | #[inline] | ||
| 726 | pub fn wait_for_high(&mut self) -> impl Future<Output = ()> + use<'_, 'd> { | ||
| 727 | self.wait_for_inner(crate::pac::gpio0::icr::Irqc::Irqc12) | ||
| 728 | } | ||
| 729 | |||
| 730 | /// Wait until the pin is low. If it is already low, return immediately. | ||
| 731 | #[inline] | ||
| 732 | pub fn wait_for_low(&mut self) -> impl Future<Output = ()> + use<'_, 'd> { | ||
| 733 | self.wait_for_inner(crate::pac::gpio0::icr::Irqc::Irqc8) | ||
| 734 | } | ||
| 735 | |||
| 736 | /// Wait for the pin to undergo a transition from low to high. | ||
| 737 | #[inline] | ||
| 738 | pub fn wait_for_rising_edge(&mut self) -> impl Future<Output = ()> + use<'_, 'd> { | ||
| 739 | self.wait_for_inner(crate::pac::gpio0::icr::Irqc::Irqc9) | ||
| 740 | } | ||
| 741 | |||
| 742 | /// Wait for the pin to undergo a transition from high to low. | ||
| 743 | #[inline] | ||
| 744 | pub fn wait_for_falling_edge(&mut self) -> impl Future<Output = ()> + use<'_, 'd> { | ||
| 745 | self.wait_for_inner(crate::pac::gpio0::icr::Irqc::Irqc10) | ||
| 746 | } | ||
| 747 | |||
| 748 | /// Wait for the pin to undergo any transition, i.e low to high OR high to low. | ||
| 749 | #[inline] | ||
| 750 | pub fn wait_for_any_edge(&mut self) -> impl Future<Output = ()> + use<'_, 'd> { | ||
| 751 | self.wait_for_inner(crate::pac::gpio0::icr::Irqc::Irqc11) | ||
| 752 | } | ||
| 753 | } | ||
| 754 | |||
| 601 | /// GPIO output driver that owns a `Flex` pin. | 755 | /// GPIO output driver that owns a `Flex` pin. |
| 602 | pub struct Output<'d> { | 756 | pub struct Output<'d> { |
| 603 | flex: Flex<'d>, | 757 | flex: Flex<'d>, |
| @@ -691,12 +845,99 @@ impl<'d> Input<'d> { | |||
| 691 | self.flex | 845 | self.flex |
| 692 | } | 846 | } |
| 693 | 847 | ||
| 694 | // Get the pin level. | 848 | /// Get the pin level. |
| 695 | pub fn get_level(&self) -> Level { | 849 | pub fn get_level(&self) -> Level { |
| 696 | self.flex.get_level() | 850 | self.flex.get_level() |
| 697 | } | 851 | } |
| 698 | } | 852 | } |
| 699 | 853 | ||
| 854 | /// Async methods | ||
| 855 | impl<'d> Input<'d> { | ||
| 856 | /// Wait until the pin is high. If it is already high, return immediately. | ||
| 857 | #[inline] | ||
| 858 | pub fn wait_for_high(&mut self) -> impl Future<Output = ()> + use<'_, 'd> { | ||
| 859 | self.flex.wait_for_high() | ||
| 860 | } | ||
| 861 | |||
| 862 | /// Wait until the pin is low. If it is already low, return immediately. | ||
| 863 | #[inline] | ||
| 864 | pub fn wait_for_low(&mut self) -> impl Future<Output = ()> + use<'_, 'd> { | ||
| 865 | self.flex.wait_for_low() | ||
| 866 | } | ||
| 867 | |||
| 868 | /// Wait for the pin to undergo a transition from low to high. | ||
| 869 | #[inline] | ||
| 870 | pub fn wait_for_rising_edge(&mut self) -> impl Future<Output = ()> + use<'_, 'd> { | ||
| 871 | self.flex.wait_for_rising_edge() | ||
| 872 | } | ||
| 873 | |||
| 874 | /// Wait for the pin to undergo a transition from high to low. | ||
| 875 | #[inline] | ||
| 876 | pub fn wait_for_falling_edge(&mut self) -> impl Future<Output = ()> + use<'_, 'd> { | ||
| 877 | self.flex.wait_for_falling_edge() | ||
| 878 | } | ||
| 879 | |||
| 880 | /// Wait for the pin to undergo any transition, i.e low to high OR high to low. | ||
| 881 | #[inline] | ||
| 882 | pub fn wait_for_any_edge(&mut self) -> impl Future<Output = ()> + use<'_, 'd> { | ||
| 883 | self.flex.wait_for_any_edge() | ||
| 884 | } | ||
| 885 | } | ||
| 886 | |||
| 887 | impl embedded_hal_async::digital::Wait for Input<'_> { | ||
| 888 | async fn wait_for_high(&mut self) -> Result<(), Self::Error> { | ||
| 889 | self.wait_for_high().await; | ||
| 890 | Ok(()) | ||
| 891 | } | ||
| 892 | |||
| 893 | async fn wait_for_low(&mut self) -> Result<(), Self::Error> { | ||
| 894 | self.wait_for_low().await; | ||
| 895 | Ok(()) | ||
| 896 | } | ||
| 897 | |||
| 898 | async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> { | ||
| 899 | self.wait_for_rising_edge().await; | ||
| 900 | Ok(()) | ||
| 901 | } | ||
| 902 | |||
| 903 | async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> { | ||
| 904 | self.wait_for_falling_edge().await; | ||
| 905 | Ok(()) | ||
| 906 | } | ||
| 907 | |||
| 908 | async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> { | ||
| 909 | self.wait_for_any_edge().await; | ||
| 910 | Ok(()) | ||
| 911 | } | ||
| 912 | } | ||
| 913 | |||
| 914 | impl embedded_hal_async::digital::Wait for Flex<'_> { | ||
| 915 | async fn wait_for_high(&mut self) -> Result<(), Self::Error> { | ||
| 916 | self.wait_for_high().await; | ||
| 917 | Ok(()) | ||
| 918 | } | ||
| 919 | |||
| 920 | async fn wait_for_low(&mut self) -> Result<(), Self::Error> { | ||
| 921 | self.wait_for_low().await; | ||
| 922 | Ok(()) | ||
| 923 | } | ||
| 924 | |||
| 925 | async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> { | ||
| 926 | self.wait_for_rising_edge().await; | ||
| 927 | Ok(()) | ||
| 928 | } | ||
| 929 | |||
| 930 | async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> { | ||
| 931 | self.wait_for_falling_edge().await; | ||
| 932 | Ok(()) | ||
| 933 | } | ||
| 934 | |||
| 935 | async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> { | ||
| 936 | self.wait_for_any_edge().await; | ||
| 937 | Ok(()) | ||
| 938 | } | ||
| 939 | } | ||
| 940 | |||
| 700 | // Both embedded_hal 0.2 and 1.0 must be supported by embassy HALs. | 941 | // Both embedded_hal 0.2 and 1.0 must be supported by embassy HALs. |
| 701 | impl embedded_hal_02::digital::v2::InputPin for Flex<'_> { | 942 | impl embedded_hal_02::digital::v2::InputPin for Flex<'_> { |
| 702 | // GPIO operations on this block cannot fail, therefor we set the error type | 943 | // GPIO operations on this block cannot fail, therefor we set the error type |
