diff options
| author | [email protected] <[email protected]> | 2022-06-30 21:41:45 +0200 |
|---|---|---|
| committer | [email protected] <[email protected]> | 2022-06-30 22:50:53 +0200 |
| commit | 9b3c5af92ad55bc05a72b8957784f12c1a1ddcbd (patch) | |
| tree | c654fc3ebd14e6b32a6fa30be28b18fefe97ae56 | |
| parent | ffc32d3ddb5840b476a473c0248e32f7b9a8a212 (diff) | |
Flex GPIO implementation : Input
| -rw-r--r-- | embassy-stm32/src/gpio.rs | 167 |
1 files changed, 105 insertions, 62 deletions
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index 6e445f8cd..58eed688a 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs | |||
| @@ -7,6 +7,102 @@ use embassy_hal_common::{unborrow, unsafe_impl_unborrow}; | |||
| 7 | use crate::pac::gpio::{self, vals}; | 7 | use crate::pac::gpio::{self, vals}; |
| 8 | use crate::{pac, peripherals, Unborrow}; | 8 | use crate::{pac, peripherals, Unborrow}; |
| 9 | 9 | ||
| 10 | /// GPIO flexible pin. | ||
| 11 | /// | ||
| 12 | /// This pin can either be a disconnected, input, or output pin, or both. The level register bit will remain | ||
| 13 | /// set while not in output mode, so the pin's level will be 'remembered' when it is not in output | ||
| 14 | /// mode. | ||
| 15 | pub struct Flex<'d, T: Pin> { | ||
| 16 | pub(crate) pin: T, | ||
| 17 | phantom: PhantomData<&'d mut T>, | ||
| 18 | } | ||
| 19 | |||
| 20 | impl<'d, T: Pin> Flex<'d, T> { | ||
| 21 | /// Wrap the pin in a `Flex`. | ||
| 22 | /// | ||
| 23 | /// The pin remains disconnected. The initial output level is unspecified, but can be changed | ||
| 24 | /// before the pin is put into output mode. | ||
| 25 | /// | ||
| 26 | #[inline] | ||
| 27 | pub fn new(pin: impl Unborrow<Target = T> + 'd) -> Self { | ||
| 28 | unborrow!(pin); | ||
| 29 | // Pin will be in disconnected state. | ||
| 30 | Self { | ||
| 31 | pin, | ||
| 32 | phantom: PhantomData, | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | /// Put the pin into input mode. | ||
| 37 | #[inline] | ||
| 38 | pub fn set_as_input(&mut self, pull: Pull) { | ||
| 39 | critical_section::with(|_| unsafe { | ||
| 40 | let r = self.pin.block(); | ||
| 41 | let n = self.pin.pin() as usize; | ||
| 42 | #[cfg(gpio_v1)] | ||
| 43 | { | ||
| 44 | let cnf = match pull { | ||
| 45 | Pull::Up => { | ||
| 46 | r.bsrr().write(|w| w.set_bs(n, true)); | ||
| 47 | vals::CnfIn::PULL | ||
| 48 | } | ||
| 49 | Pull::Down => { | ||
| 50 | r.bsrr().write(|w| w.set_br(n, true)); | ||
| 51 | vals::CnfIn::PULL | ||
| 52 | } | ||
| 53 | Pull::None => vals::CnfIn::FLOATING, | ||
| 54 | }; | ||
| 55 | |||
| 56 | let crlh = if n < 8 { 0 } else { 1 }; | ||
| 57 | r.cr(crlh).modify(|w| { | ||
| 58 | w.set_mode(n % 8, vals::Mode::INPUT); | ||
| 59 | w.set_cnf_in(n % 8, cnf); | ||
| 60 | }); | ||
| 61 | } | ||
| 62 | #[cfg(gpio_v2)] | ||
| 63 | { | ||
| 64 | r.pupdr().modify(|w| w.set_pupdr(n, pull.into())); | ||
| 65 | r.otyper().modify(|w| w.set_ot(n, vals::Ot::PUSHPULL)); | ||
| 66 | r.moder().modify(|w| w.set_moder(n, vals::Moder::INPUT)); | ||
| 67 | } | ||
| 68 | }); | ||
| 69 | } | ||
| 70 | |||
| 71 | #[inline] | ||
| 72 | pub fn is_high(&self) -> bool { | ||
| 73 | !self.is_low() | ||
| 74 | } | ||
| 75 | |||
| 76 | #[inline] | ||
| 77 | pub fn is_low(&self) -> bool { | ||
| 78 | let state = unsafe { self.pin.block().idr().read().idr(self.pin.pin() as _) }; | ||
| 79 | state == vals::Idr::LOW | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | impl<'d, T: Pin> Drop for Flex<'d, T> { | ||
| 84 | #[inline] | ||
| 85 | fn drop(&mut self) { | ||
| 86 | critical_section::with(|_| unsafe { | ||
| 87 | let r = self.pin.block(); | ||
| 88 | let n = self.pin.pin() as usize; | ||
| 89 | #[cfg(gpio_v1)] | ||
| 90 | { | ||
| 91 | let crlh = if n < 8 { 0 } else { 1 }; | ||
| 92 | r.cr(crlh).modify(|w| { | ||
| 93 | w.set_mode(n % 8, vals::Mode::INPUT); | ||
| 94 | w.set_cnf_in(n % 8, vals::CnfIn::FLOATING); | ||
| 95 | }); | ||
| 96 | } | ||
| 97 | #[cfg(gpio_v2)] | ||
| 98 | { | ||
| 99 | r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING)); | ||
| 100 | r.moder().modify(|w| w.set_moder(n, vals::Moder::INPUT)); | ||
| 101 | } | ||
| 102 | }); | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 10 | /// Pull setting for an input. | 106 | /// Pull setting for an input. |
| 11 | #[derive(Debug, Eq, PartialEq)] | 107 | #[derive(Debug, Eq, PartialEq)] |
| 12 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 108 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -70,78 +166,25 @@ impl From<Speed> for vals::Ospeedr { | |||
| 70 | 166 | ||
| 71 | /// GPIO input driver. | 167 | /// GPIO input driver. |
| 72 | pub struct Input<'d, T: Pin> { | 168 | pub struct Input<'d, T: Pin> { |
| 73 | pub(crate) pin: T, | 169 | pub(crate) pin: Flex<'d, T> |
| 74 | phantom: PhantomData<&'d mut T>, | ||
| 75 | } | 170 | } |
| 76 | 171 | ||
| 77 | impl<'d, T: Pin> Input<'d, T> { | 172 | impl<'d, T: Pin> Input<'d, T> { |
| 78 | #[inline] | 173 | #[inline] |
| 79 | pub fn new(pin: impl Unborrow<Target = T> + 'd, pull: Pull) -> Self { | 174 | pub fn new(pin: impl Unborrow<Target = T> + 'd, pull: Pull) -> Self { |
| 80 | unborrow!(pin); | 175 | let mut pin = Flex::new(pin); |
| 81 | 176 | pin.set_as_input(pull); | |
| 82 | critical_section::with(|_| unsafe { | 177 | Self { pin } |
| 83 | let r = pin.block(); | ||
| 84 | let n = pin.pin() as usize; | ||
| 85 | #[cfg(gpio_v1)] | ||
| 86 | { | ||
| 87 | let cnf = match pull { | ||
| 88 | Pull::Up => { | ||
| 89 | r.bsrr().write(|w| w.set_bs(n, true)); | ||
| 90 | vals::CnfIn::PULL | ||
| 91 | } | ||
| 92 | Pull::Down => { | ||
| 93 | r.bsrr().write(|w| w.set_br(n, true)); | ||
| 94 | vals::CnfIn::PULL | ||
| 95 | } | ||
| 96 | Pull::None => vals::CnfIn::FLOATING, | ||
| 97 | }; | ||
| 98 | |||
| 99 | let crlh = if n < 8 { 0 } else { 1 }; | ||
| 100 | r.cr(crlh).modify(|w| { | ||
| 101 | w.set_mode(n % 8, vals::Mode::INPUT); | ||
| 102 | w.set_cnf_in(n % 8, cnf); | ||
| 103 | }); | ||
| 104 | } | ||
| 105 | #[cfg(gpio_v2)] | ||
| 106 | { | ||
| 107 | r.pupdr().modify(|w| w.set_pupdr(n, pull.into())); | ||
| 108 | r.otyper().modify(|w| w.set_ot(n, vals::Ot::PUSHPULL)); | ||
| 109 | r.moder().modify(|w| w.set_moder(n, vals::Moder::INPUT)); | ||
| 110 | } | ||
| 111 | }); | ||
| 112 | |||
| 113 | Self { | ||
| 114 | pin, | ||
| 115 | phantom: PhantomData, | ||
| 116 | } | ||
| 117 | } | 178 | } |
| 118 | 179 | ||
| 119 | #[inline] | 180 | #[inline] |
| 120 | pub fn is_high(&self) -> bool { | 181 | pub fn is_high(&self) -> bool { |
| 121 | !self.is_low() | 182 | self.pin.is_high() |
| 122 | } | 183 | } |
| 123 | 184 | ||
| 124 | #[inline] | 185 | #[inline] |
| 125 | pub fn is_low(&self) -> bool { | 186 | pub fn is_low(&self) -> bool { |
| 126 | let state = unsafe { self.pin.block().idr().read().idr(self.pin.pin() as _) }; | 187 | self.pin.is_low() |
| 127 | state == vals::Idr::LOW | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 131 | impl<'d, T: Pin> Drop for Input<'d, T> { | ||
| 132 | #[inline] | ||
| 133 | fn drop(&mut self) { | ||
| 134 | critical_section::with(|_| unsafe { | ||
| 135 | let r = self.pin.block(); | ||
| 136 | let n = self.pin.pin() as usize; | ||
| 137 | #[cfg(gpio_v1)] | ||
| 138 | { | ||
| 139 | let crlh = if n < 8 { 0 } else { 1 }; | ||
| 140 | r.cr(crlh).modify(|w| w.set_cnf_in(n % 8, vals::CnfIn::FLOATING)); | ||
| 141 | } | ||
| 142 | #[cfg(gpio_v2)] | ||
| 143 | r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING)); | ||
| 144 | }); | ||
| 145 | } | 188 | } |
| 146 | } | 189 | } |
| 147 | 190 | ||
| @@ -609,7 +652,7 @@ mod eh02 { | |||
| 609 | 652 | ||
| 610 | use super::*; | 653 | use super::*; |
| 611 | 654 | ||
| 612 | impl<'d, T: Pin> InputPin for Input<'d, T> { | 655 | impl<'d, T: Pin> InputPin for Flex<'d, T> { |
| 613 | type Error = Infallible; | 656 | type Error = Infallible; |
| 614 | 657 | ||
| 615 | #[inline] | 658 | #[inline] |
| @@ -701,11 +744,11 @@ mod eh1 { | |||
| 701 | 744 | ||
| 702 | use super::*; | 745 | use super::*; |
| 703 | 746 | ||
| 704 | impl<'d, T: Pin> ErrorType for Input<'d, T> { | 747 | impl<'d, T: Pin> ErrorType for Flex<'d, T> { |
| 705 | type Error = Infallible; | 748 | type Error = Infallible; |
| 706 | } | 749 | } |
| 707 | 750 | ||
| 708 | impl<'d, T: Pin> InputPin for Input<'d, T> { | 751 | impl<'d, T: Pin> InputPin for Flex<'d, T> { |
| 709 | #[inline] | 752 | #[inline] |
| 710 | fn is_high(&self) -> Result<bool, Self::Error> { | 753 | fn is_high(&self) -> Result<bool, Self::Error> { |
| 711 | Ok(self.is_high()) | 754 | Ok(self.is_high()) |
