embedded_c_sdk_bind_hal/gpio/
port.rs1use crate::ll_api::{ll_cmd::*, GpioInitFlag, PortNum};
2use core::marker::PhantomData;
3
4#[derive(Clone, Copy, PartialEq, Eq, Debug)]
5pub enum PortModeInput {
6 InFloating,
7 InPullUp,
8 InPullDown,
9}
10
11impl PortModeInput {
12 fn to_flag(&self) -> u32 {
13 match self {
14 PortModeInput::InFloating => GpioInitFlag::InFloating as u32,
15 PortModeInput::InPullUp => GpioInitFlag::InPU as u32,
16 PortModeInput::InPullDown => GpioInitFlag::InPD as u32,
17 }
18 }
19}
20
21pub enum PortModeOutput {
22 OutOD,
23 OutPP,
24}
25
26impl PortModeOutput {
27 fn to_flag(&self) -> u32 {
28 match self {
29 PortModeOutput::OutOD => GpioInitFlag::OutOD as u32,
30 PortModeOutput::OutPP => GpioInitFlag::OutPP as u32,
31 }
32 }
33}
34
35#[derive(Clone, Copy, PartialEq, Eq, Debug)]
36#[repr(C)]
37pub struct PortReg {
38 pub idr: *mut u16,
40 pub odr: *mut u16,
42 pub bsr: *mut u16,
44 pub bcr: *mut u16,
46}
47
48unsafe impl Send for PortReg {}
49unsafe impl Sync for PortReg {}
50
51pub struct InputPort;
52pub struct OutputPort;
53
54#[derive(Clone, Copy, Debug)]
55pub struct Port<MODE> {
56 gpio: PortNum,
57 mask: u16,
58 regs: &'static PortReg,
59 _mode: PhantomData<MODE>,
60}
61
62impl Port<()> {
63 pub fn new(gpio: PortNum, mask: u16, regs: &'static PortReg) -> Self {
72 let port = Port {
73 gpio,
74 mask,
75 regs,
76 _mode: PhantomData,
77 };
78
79 port
80 }
81
82 pub fn into_input(&self, mode: PortModeInput) -> Port<InputPort> {
90 let pin_mode = mode.to_flag();
91 self.port_init(pin_mode);
92
93 Port {
94 gpio: self.gpio,
95 mask: self.mask,
96 regs: self.regs,
97 _mode: PhantomData,
98 }
99 }
100
101 pub fn into_output(&self, mode: PortModeOutput) -> Port<OutputPort> {
109 let pin_mode = mode.to_flag();
110 self.port_init(pin_mode);
111
112 Port {
113 gpio: self.gpio,
114 mask: self.mask,
115 regs: self.regs,
116 _mode: PhantomData,
117 }
118 }
119
120 fn port_init(&self, mode: u32) {
125 for pin in 0..16 {
126 if (self.mask & (1 << pin)) > 0 {
127 ll_invoke_inner!(INVOKE_ID_GPIO_INIT, self.gpio, pin, mode);
128 }
129 }
130 }
131}
132
133impl Port<OutputPort> {
134 #[inline]
139 pub unsafe fn set_bits_uncheck(&mut self, bits: u16) {
140 core::ptr::write_volatile(self.regs.bsr, bits)
141 }
142
143 #[inline]
148 pub unsafe fn clr_bits_uncheck(&mut self, bits: u16) {
149 core::ptr::write_volatile(self.regs.bcr, bits);
150 }
151
152 #[inline]
157 pub unsafe fn read_output_bits_uncheck(&mut self) -> u16 {
158 core::ptr::read_volatile(self.regs.odr)
159 }
160
161 #[inline]
166 pub unsafe fn write_bits_uncheck(&mut self, bits: u16) {
167 core::ptr::write_volatile(self.regs.odr, bits);
168 }
169
170 pub fn set_bits(&mut self, bits: u16) {
172 if !self.regs.bsr.is_null() {
173 unsafe { self.set_bits_uncheck(bits & self.mask) }
174 } else {
175 let read = self.read_output_bits();
176 self.write_bits(bits | read);
177 }
178 }
179
180 pub fn clr_bits(&mut self, bits: u16) {
182 if !self.regs.bcr.is_null() {
183 unsafe { self.clr_bits_uncheck(bits & self.mask) }
184 } else {
185 let read = self.read_output_bits();
186 self.write_bits(!bits & read);
187 }
188 }
189
190 pub fn read_output_bits(&mut self) -> u16 {
192 if !self.regs.odr.is_null() {
193 return unsafe { self.read_output_bits_uncheck() } & self.mask;
194 }
195 return 0;
196 }
197
198 pub fn write_bits(&mut self, bits: u16) {
200 if !self.regs.odr.is_null() {
201 unsafe {
202 let read = self.read_output_bits_uncheck() & !self.mask;
203 self.write_bits_uncheck((bits & self.mask) | read);
204 }
205 }
206 }
207
208 pub fn read_input_bits(&mut self) -> u16 {
210 if !self.regs.idr.is_null() {
211 return unsafe { core::ptr::read_volatile(self.regs.idr) } & self.mask;
212 }
213 return 0;
214 }
215}
216
217impl Port<InputPort> {
218 #[inline]
223 pub unsafe fn read_input_bits_uncheck(&mut self) -> u16 {
224 core::ptr::read_volatile(self.regs.idr)
225 }
226
227 pub fn read_input_bits(&mut self) -> u16 {
229 if !self.regs.idr.is_null() {
230 return unsafe { self.read_input_bits_uncheck() } & self.mask;
231 }
232 return 0;
233 }
234}
235
236impl<MODE> embedded_hal::digital::ErrorType for Port<MODE> {
237 type Error = core::convert::Infallible;
238}
239
240impl embedded_hal::digital::OutputPin for Port<OutputPort> {
241 #[inline(always)]
242 fn set_high(&mut self) -> Result<(), Self::Error> {
243 self.set_bits(self.mask);
244 Ok(())
245 }
246
247 #[inline(always)]
248 fn set_low(&mut self) -> Result<(), Self::Error> {
249 self.clr_bits(self.mask);
250 Ok(())
251 }
252}
253
254impl embedded_hal::digital::StatefulOutputPin for Port<OutputPort> {
255 #[inline(always)]
256 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
257 Ok(self.read_output_bits() > 0)
258 }
259
260 #[inline(always)]
261 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
262 Ok(self.read_output_bits() == 0)
263 }
264}
265
266impl embedded_hal::digital::InputPin for Port<InputPort> {
267 #[inline(always)]
268 fn is_high(&mut self) -> Result<bool, Self::Error> {
269 Ok(self.read_input_bits() > 0)
270 }
271
272 #[inline(always)]
273 fn is_low(&mut self) -> Result<bool, Self::Error> {
274 Ok(self.read_input_bits() == 0)
275 }
276}
277
278impl embedded_hal::digital::InputPin for Port<OutputPort> {
279 #[inline(always)]
280 fn is_high(&mut self) -> Result<bool, Self::Error> {
281 Ok(self.read_input_bits() > 0)
282 }
283
284 #[inline(always)]
285 fn is_low(&mut self) -> Result<bool, Self::Error> {
286 Ok(self.read_input_bits() == 0)
287 }
288}