aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author[email protected] <[email protected]>2022-06-30 21:41:45 +0200
committer[email protected] <[email protected]>2022-06-30 22:50:53 +0200
commit9b3c5af92ad55bc05a72b8957784f12c1a1ddcbd (patch)
treec654fc3ebd14e6b32a6fa30be28b18fefe97ae56
parentffc32d3ddb5840b476a473c0248e32f7b9a8a212 (diff)
Flex GPIO implementation : Input
-rw-r--r--embassy-stm32/src/gpio.rs167
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};
7use crate::pac::gpio::{self, vals}; 7use crate::pac::gpio::{self, vals};
8use crate::{pac, peripherals, Unborrow}; 8use 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.
15pub struct Flex<'d, T: Pin> {
16 pub(crate) pin: T,
17 phantom: PhantomData<&'d mut T>,
18}
19
20impl<'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
83impl<'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.
72pub struct Input<'d, T: Pin> { 168pub 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
77impl<'d, T: Pin> Input<'d, T> { 172impl<'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
131impl<'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())