1use core::marker::PhantomData;
4
5pub trait GpioExt {
7 type Parts;
9
10 fn split(self) -> Self::Parts;
12}
13
14pub struct Input<MODE> {
16 _mode: PhantomData<MODE>,
17}
18
19pub struct Floating;
21
22pub struct PullDown;
24
25pub struct PullUp;
27
28pub struct OpenDrain;
30
31pub struct Analog;
33
34pub struct Output<MODE> {
36 _mode: PhantomData<MODE>,
37}
38
39pub struct PushPull;
41
42pub enum Speed {
44 Low = 0,
45 Medium = 1,
46 High = 2,
47 VeryHigh = 3,
48}
49
50#[allow(dead_code)]
51pub(crate) enum AltMode {
52 SYSTEM = 0,
53 TIM2 = 1,
54 TIM3_5 = 2,
55 TIM9_11 = 3,
56 I2C = 4,
57 SPI1_2 = 5,
58 SPI3 = 6,
59 USART1_3 = 7,
60 UART4_5 = 8,
61 USB = 10,
62 LCD = 11,
63 FSMC = 12,
64 RI = 14,
65 EVENTOUT = 15,
66}
67
68macro_rules! gpio {
69 ($GPIOX:ident, $gpiox:ident, $iopxenr:ident, $PXx:ident, [
70 $($PXi:ident: ($pxi:ident, $i:expr, $MODE:ty),)+
71 ]) => {
72 pub mod $gpiox {
74 use core::marker::PhantomData;
75 use core::convert::Infallible;
76
77 use hal::digital::v2::{toggleable, InputPin, OutputPin, StatefulOutputPin};
78 use crate::stm32::$GPIOX;
79 use crate::stm32::RCC;
80 use super::{
81 Floating, GpioExt, Input, OpenDrain, Output, Speed,
82 PullDown, PullUp, PushPull, AltMode, Analog
83 };
84
85 pub struct Parts {
87 $(
88 pub $pxi: $PXi<$MODE>,
90 )+
91 }
92
93 impl GpioExt for $GPIOX {
94 type Parts = Parts;
95
96 fn split(self) -> Parts {
97 let rcc = unsafe { &(*RCC::ptr()) };
99 rcc.ahbenr.modify(|_, w| w.$iopxenr().set_bit());
100
101 Parts {
102 $(
103 $pxi: $PXi { _mode: PhantomData },
104 )+
105 }
106 }
107 }
108
109 pub struct $PXx<MODE> {
111 i: u8,
112 _mode: PhantomData<MODE>,
113 }
114
115 impl<MODE> OutputPin for $PXx<Output<MODE>> {
116 type Error = Infallible;
117
118 fn set_high(&mut self) -> Result<(), Self::Error> {
119 Ok(unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << self.i)) })
121 }
122
123 fn set_low(&mut self) -> Result<(), Self::Error> {
124 Ok(unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (self.i + 16))) })
126 }
127 }
128
129 impl<MODE> StatefulOutputPin for $PXx<Output<MODE>> {
130 fn is_set_high(&self) -> Result<bool, Self::Error> {
131 self.is_set_low().map(|v| !v)
132 }
133
134 fn is_set_low(&self) -> Result<bool, Self::Error> {
135 Ok(unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << self.i) == 0 })
137 }
138 }
139
140 impl<MODE> toggleable::Default for $PXx<Output<MODE>> {}
141
142 impl<MODE> InputPin for $PXx<Output<MODE>> {
143 type Error = Infallible;
144
145 fn is_high(&self) -> Result<bool, Self::Error> {
146 self.is_low().map(|v| !v)
147 }
148
149 fn is_low(&self) -> Result<bool, Self::Error> {
150 Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 })
152 }
153 }
154
155 impl<MODE> InputPin for $PXx<Input<MODE>> {
156 type Error = Infallible;
157
158 fn is_high(&self) -> Result<bool, Self::Error> {
159 self.is_low().map(|v| !v)
160 }
161
162 fn is_low(&self) -> Result<bool, Self::Error> {
163 Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 })
165 }
166 }
167
168 $(
169 pub struct $PXi<MODE> {
171 _mode: PhantomData<MODE>,
172 }
173
174 impl<MODE> $PXi<MODE> {
175 pub fn into_floating_input(
177 self,
178 ) -> $PXi<Input<Floating>> {
179 let offset = 2 * $i;
180 unsafe {
181 &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
182 w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
183 });
184 &(*$GPIOX::ptr()).moder.modify(|r, w| {
185 w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
186 })
187 };
188 $PXi { _mode: PhantomData }
189 }
190
191 pub fn into_pull_down_input(
193 self,
194 ) -> $PXi<Input<PullDown>> {
195 let offset = 2 * $i;
196 unsafe {
197 &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
198 w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))
199 });
200 &(*$GPIOX::ptr()).moder.modify(|r, w| {
201 w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
202 })
203 };
204 $PXi { _mode: PhantomData }
205 }
206
207 pub fn into_pull_up_input(
209 self,
210 ) -> $PXi<Input<PullUp>> {
211 let offset = 2 * $i;
212 unsafe {
213 &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
214 w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))
215 });
216 &(*$GPIOX::ptr()).moder.modify(|r, w| {
217 w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
218 })
219 };
220 $PXi { _mode: PhantomData }
221 }
222
223 pub fn into_analog(
225 self,
226 ) -> $PXi<Analog> {
227 let offset = 2 * $i;
228 unsafe {
229 &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
230 w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
231 });
232 &(*$GPIOX::ptr()).moder.modify(|r, w| {
233 w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))
234 });
235 }
236 $PXi { _mode: PhantomData }
237 }
238
239 pub fn into_open_drain_output(
241 self,
242 ) -> $PXi<Output<OpenDrain>> {
243 let offset = 2 * $i;
244 unsafe {
245 &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
246 w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
247 });
248 &(*$GPIOX::ptr()).otyper.modify(|r, w| {
249 w.bits(r.bits() | (0b1 << $i))
250 });
251 &(*$GPIOX::ptr()).moder.modify(|r, w| {
252 w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))
253 })
254 };
255 $PXi { _mode: PhantomData }
256 }
257
258 pub fn into_push_pull_output(
260 self,
261 ) -> $PXi<Output<PushPull>> {
262 let offset = 2 * $i;
263 unsafe {
264 &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
265 w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
266 });
267 &(*$GPIOX::ptr()).otyper.modify(|r, w| {
268 w.bits(r.bits() & !(0b1 << $i))
269 });
270 &(*$GPIOX::ptr()).moder.modify(|r, w| {
271 w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))
272 })
273 };
274 $PXi { _mode: PhantomData }
275 }
276
277 pub fn set_speed(self, speed: Speed) -> Self {
279 let offset = 2 * $i;
280 unsafe {
281 &(*$GPIOX::ptr()).ospeedr.modify(|r, w| {
282 w.bits((r.bits() & !(0b11 << offset)) | ((speed as u32) << offset))
283 })
284 };
285 self
286 }
287
288 #[allow(dead_code)]
289 pub(crate) fn set_alt_mode(&self, mode: AltMode) {
290 let mode = mode as u32;
291 let offset = 2 * $i;
292 let offset2 = 4 * $i;
293 unsafe {
294 if offset2 < 32 {
295 &(*$GPIOX::ptr()).afrl.modify(|r, w| {
296 w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2))
297 });
298 } else {
299 let offset2 = offset2 - 32;
300 &(*$GPIOX::ptr()).afrh.modify(|r, w| {
301 w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2))
302 });
303 }
304 &(*$GPIOX::ptr()).moder.modify(|r, w| {
305 w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))
306 });
307 }
308 }
309 }
310
311 impl<MODE> $PXi<Output<MODE>> {
312 pub fn downgrade(self) -> $PXx<Output<MODE>> {
317 $PXx {
318 i: $i,
319 _mode: self._mode,
320 }
321 }
322 }
323
324 impl<MODE> OutputPin for $PXi<Output<MODE>> {
325 type Error = Infallible;
326
327 fn set_high(&mut self) -> Result<(), Self::Error> {
328 Ok(unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i)) })
330 }
331
332 fn set_low(&mut self) -> Result<(), Self::Error> {
333 Ok(unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << ($i + 16))) })
335 }
336 }
337
338 impl<MODE> StatefulOutputPin for $PXi<Output<MODE>> {
339 fn is_set_high(&self) -> Result<bool, Self::Error> {
340 self.is_set_low().map(|v| !v)
341 }
342
343 fn is_set_low(&self) -> Result<bool, Self::Error> {
344 Ok(unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << $i) == 0 })
346 }
347 }
348
349 impl<MODE> toggleable::Default for $PXi<Output<MODE>> {}
350
351 impl<MODE> InputPin for $PXi<Output<MODE>> {
352 type Error = Infallible;
353
354 fn is_high(&self) -> Result<bool, Self::Error> {
355 self.is_low().map(|v| !v)
356 }
357
358 fn is_low(&self) -> Result<bool, Self::Error> {
359 Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 })
361 }
362 }
363
364 impl<MODE> $PXi<Input<MODE>> {
365 pub fn downgrade(self) -> $PXx<Input<MODE>> {
370 $PXx {
371 i: $i,
372 _mode: self._mode,
373 }
374 }
375 }
376
377 impl<MODE> InputPin for $PXi<Input<MODE>> {
378 type Error = Infallible;
379
380 fn is_high(&self) -> Result<bool, Self::Error> {
381 self.is_low().map(|v| !v)
382 }
383
384 fn is_low(&self) -> Result<bool, Self::Error> {
385 Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 })
387 }
388 }
389 )+
390
391 impl<TYPE> $PXx<TYPE> {
392 pub fn get_id (&self) -> u8
393 {
394 self.i
395 }
396 }
397 }
398 }
399}
400
401gpio!(GPIOA, gpioa, gpiopaen, PA, [
402 PA0: (pa0, 0, Input<Floating>),
403 PA1: (pa1, 1, Input<Floating>),
404 PA2: (pa2, 2, Input<Floating>),
405 PA3: (pa3, 3, Input<Floating>),
406 PA4: (pa4, 4, Input<Floating>),
407 PA5: (pa5, 5, Input<Floating>),
408 PA6: (pa6, 6, Input<Floating>),
409 PA7: (pa7, 7, Input<Floating>),
410 PA8: (pa8, 8, Input<Floating>),
411 PA9: (pa9, 9, Input<Floating>),
412 PA10: (pa10, 10, Input<Floating>),
413 PA11: (pa11, 11, Input<Floating>),
414 PA12: (pa12, 12, Input<Floating>),
415 PA13: (pa13, 13, Input<Floating>),
416 PA14: (pa14, 14, Input<Floating>),
417 PA15: (pa15, 15, Input<Floating>),
418]);
419
420gpio!(GPIOB, gpiob, gpiopben, PB, [
421 PB0: (pb0, 0, Input<Floating>),
422 PB1: (pb1, 1, Input<Floating>),
423 PB2: (pb2, 2, Input<Floating>),
424 PB3: (pb3, 3, Input<Floating>),
425 PB4: (pb4, 4, Input<Floating>),
426 PB5: (pb5, 5, Input<Floating>),
427 PB6: (pb6, 6, Input<Floating>),
428 PB7: (pb7, 7, Input<Floating>),
429 PB8: (pb8, 8, Input<Floating>),
430 PB9: (pb9, 9, Input<Floating>),
431 PB10: (pb10, 10, Input<Floating>),
432 PB11: (pb11, 11, Input<Floating>),
433 PB12: (pb12, 12, Input<Floating>),
434 PB13: (pb13, 13, Input<Floating>),
435 PB14: (pb14, 14, Input<Floating>),
436 PB15: (pb15, 15, Input<Floating>),
437]);
438
439gpio!(GPIOC, gpioc, gpiopcen, PC, [
440 PC0: (pc0, 0, Input<Floating>),
441 PC1: (pc1, 1, Input<Floating>),
442 PC2: (pc2, 2, Input<Floating>),
443 PC3: (pc3, 3, Input<Floating>),
444 PC4: (pc4, 4, Input<Floating>),
445 PC5: (pc5, 5, Input<Floating>),
446 PC6: (pc6, 6, Input<Floating>),
447 PC7: (pc7, 7, Input<Floating>),
448 PC8: (pc8, 8, Input<Floating>),
449 PC9: (pc9, 9, Input<Floating>),
450 PC10: (pc10, 10, Input<Floating>),
451 PC11: (pc11, 11, Input<Floating>),
452 PC12: (pc12, 12, Input<Floating>),
453 PC13: (pc13, 13, Input<Floating>),
454 PC14: (pc14, 14, Input<Floating>),
455 PC15: (pc15, 15, Input<Floating>),
456]);
457
458gpio!(GPIOD, gpiod, gpiopden, PD, [
459 PD0: (pd0, 0, Input<Floating>),
460 PD1: (pd1, 1, Input<Floating>),
461 PD2: (pd2, 2, Input<Floating>),
462 PD3: (pd3, 3, Input<Floating>),
463 PD4: (pd4, 4, Input<Floating>),
464 PD5: (pd5, 5, Input<Floating>),
465 PD6: (pd6, 6, Input<Floating>),
466 PD7: (pd7, 7, Input<Floating>),
467 PD8: (pd8, 8, Input<Floating>),
468 PD9: (pd9, 9, Input<Floating>),
469 PD10: (pd10, 10, Input<Floating>),
470 PD11: (pd11, 11, Input<Floating>),
471 PD12: (pd12, 12, Input<Floating>),
472 PD13: (pd13, 13, Input<Floating>),
473 PD14: (pd14, 14, Input<Floating>),
474 PD15: (pd15, 15, Input<Floating>),
475]);
476
477#[cfg(any(feature = "stm32l151", feature = "stm32l152", feature = "stm32l162"))]
478gpio!(GPIOE, gpioe, gpiopeen, PE, [
479 PE0: (pe0, 0, Input<Floating>),
480 PE1: (pe1, 1, Input<Floating>),
481 PE2: (pe2, 2, Input<Floating>),
482 PE3: (pe3, 3, Input<Floating>),
483 PE4: (pe4, 4, Input<Floating>),
484 PE5: (pe5, 5, Input<Floating>),
485 PE6: (pe6, 6, Input<Floating>),
486 PE7: (pe7, 7, Input<Floating>),
487 PE8: (pe8, 8, Input<Floating>),
488 PE9: (pe9, 9, Input<Floating>),
489 PE10: (pe10, 10, Input<Floating>),
490 PE11: (pe11, 11, Input<Floating>),
491 PE12: (pe12, 12, Input<Floating>),
492 PE13: (pe13, 13, Input<Floating>),
493 PE14: (pe14, 14, Input<Floating>),
494 PE15: (pe15, 15, Input<Floating>),
495]);
496
497#[cfg(any(feature = "stm32l151", feature = "stm32l152", feature = "stm32l162"))]
498gpio!(GPIOF, gpiof, gpiopfen, PF, [
499 PF0: (pf0, 0, Input<Floating>),
500 PF1: (pf1, 1, Input<Floating>),
501 PF2: (pf2, 2, Input<Floating>),
502 PF3: (pf3, 3, Input<Floating>),
503 PF4: (pf4, 4, Input<Floating>),
504 PF5: (pf5, 5, Input<Floating>),
505 PF6: (pf6, 6, Input<Floating>),
506 PF7: (pf7, 7, Input<Floating>),
507 PF8: (pf8, 8, Input<Floating>),
508 PF9: (pf9, 9, Input<Floating>),
509 PF10: (pf10, 10, Input<Floating>),
510 PF11: (pf11, 11, Input<Floating>),
511 PF12: (pf12, 12, Input<Floating>),
512 PF13: (pf13, 13, Input<Floating>),
513 PF14: (pf14, 14, Input<Floating>),
514 PF15: (pf15, 15, Input<Floating>),
515]);
516
517#[cfg(any(feature = "stm32l151", feature = "stm32l152", feature = "stm32l162"))]
518gpio!(GPIOG, gpiog, gpiopgen, PG, [
519 PG0: (pg0, 0, Input<Floating>),
520 PG1: (pg1, 1, Input<Floating>),
521 PG2: (pg2, 2, Input<Floating>),
522 PG3: (pg3, 3, Input<Floating>),
523 PG4: (pg4, 4, Input<Floating>),
524 PG5: (pg5, 5, Input<Floating>),
525 PG6: (pg6, 6, Input<Floating>),
526 PG7: (pg7, 7, Input<Floating>),
527 PG8: (pg8, 8, Input<Floating>),
528 PG9: (pg9, 9, Input<Floating>),
529 PG10: (pg10, 10, Input<Floating>),
530 PG11: (pg11, 11, Input<Floating>),
531 PG12: (pg12, 12, Input<Floating>),
532 PG13: (pg13, 13, Input<Floating>),
533 PG14: (pg14, 14, Input<Floating>),
534 PG15: (pg15, 15, Input<Floating>),
535]);
536
537#[cfg(any(feature = "stm32l151", feature = "stm32l152", feature = "stm32l162"))]
538gpio!(GPIOH, gpioh, gpiophen, PH, [
539 PH0: (ph0, 0, Input<Floating>),
540 PH1: (ph1, 1, Input<Floating>),
541 PH2: (ph2, 2, Input<Floating>),
542 PH3: (ph3, 3, Input<Floating>),
543 PH4: (ph4, 4, Input<Floating>),
544 PH5: (ph5, 5, Input<Floating>),
545 PH6: (ph6, 6, Input<Floating>),
546 PH7: (ph7, 7, Input<Floating>),
547 PH8: (ph8, 8, Input<Floating>),
548 PH9: (ph9, 9, Input<Floating>),
549 PH10: (ph10, 10, Input<Floating>),
550 PH11: (ph11, 11, Input<Floating>),
551 PH12: (ph12, 12, Input<Floating>),
552 PH13: (ph13, 13, Input<Floating>),
553 PH14: (ph14, 14, Input<Floating>),
554 PH15: (ph15, 15, Input<Floating>),
555]);