1use core::marker::PhantomData;
4
5pub trait GpioExt {
7 type Parts;
9
10 fn split(self) -> Self::Parts;
12}
13
14pub struct AF0;
15pub struct AF1;
16pub struct AF2;
17pub struct AF3;
18pub struct AF4;
19pub struct AF5;
20pub struct AF6;
21pub struct AF7;
22
23pub struct Alternate<MODE> {
24 _mode: PhantomData<MODE>,
25}
26
27pub struct Input<MODE> {
29 _mode: PhantomData<MODE>,
30}
31
32pub struct Floating;
34
35pub struct PullDown;
37
38pub struct PullUp;
40
41pub struct OpenDrain;
43
44pub struct Output<MODE> {
46 _mode: PhantomData<MODE>,
47}
48
49pub struct PushPull;
51
52use hal::digital::{InputPin, OutputPin, StatefulOutputPin};
53use stm32;
54
55pub struct Pin<MODE> {
58 i: u8,
59 port: *const stm32::gpioa::RegisterBlock,
60 _mode: PhantomData<MODE>,
61}
62
63impl<MODE> StatefulOutputPin for Pin<Output<MODE>> {
64 fn is_set_high(&self) -> bool {
65 !self.is_set_low()
66 }
67
68 fn is_set_low(&self) -> bool {
69 unsafe { (*self.port).odr.read().bits() & (1 << self.i) == 0 }
71 }
72}
73
74impl<MODE> OutputPin for Pin<Output<MODE>> {
75 fn set_high(&mut self) {
76 unsafe { (*self.port).bsrr.write(|w| w.bits(1 << self.i)) }
78 }
79
80 fn set_low(&mut self) {
81 unsafe { (*self.port).bsrr.write(|w| w.bits(1 << (self.i + 16))) }
83 }
84}
85
86impl InputPin for Pin<Output<OpenDrain>> {
87 fn is_high(&self) -> bool {
88 !self.is_low()
89 }
90
91 fn is_low(&self) -> bool {
92 unsafe { (*self.port).idr.read().bits() & (1 << self.i) == 0 }
94 }
95}
96
97impl<MODE> InputPin for Pin<Input<MODE>> {
98 fn is_high(&self) -> bool {
99 !self.is_low()
100 }
101
102 fn is_low(&self) -> bool {
103 unsafe { (*self.port).idr.read().bits() & (1 << self.i) == 0 }
105 }
106}
107
108macro_rules! gpio {
109 ($GPIOX:ident, $gpiox:ident, $iopxenr:ident, $PXx:ident, [
110 $($PXi:ident: ($pxi:ident, $i:expr, $MODE:ty),)+
111 ]) => {
112 pub mod $gpiox {
114 use core::marker::PhantomData;
115
116 use hal::digital::{InputPin, OutputPin, StatefulOutputPin};
117 use stm32::$GPIOX;
118
119 use stm32::RCC;
120 use super::{
121 Alternate, Floating, GpioExt, Input, OpenDrain, Output,
122 PullDown, PullUp, PushPull, AF0, AF1, AF2, AF3, AF4, AF5, AF6, AF7, Pin
123 };
124
125 pub struct Parts {
127 $(
128 pub $pxi: $PXi<$MODE>,
130 )+
131 }
132
133 impl GpioExt for $GPIOX {
134 type Parts = Parts;
135
136 fn split(self) -> Parts {
137 let rcc = unsafe { &(*RCC::ptr()) };
139 rcc.ahbenr.modify(|_, w| w.$iopxenr().set_bit());
140
141 Parts {
142 $(
143 $pxi: $PXi { _mode: PhantomData },
144 )+
145 }
146 }
147 }
148
149 pub struct $PXx<MODE> {
151 i: u8,
152 _mode: PhantomData<MODE>,
153 }
154
155 impl<MODE> StatefulOutputPin for $PXx<Output<MODE>> {
156 fn is_set_high(&self) -> bool {
157 !self.is_set_low()
158 }
159
160 fn is_set_low(&self) -> bool {
161 unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << self.i) == 0 }
163 }
164 }
165
166 impl<MODE> OutputPin for $PXx<Output<MODE>> {
167 fn set_high(&mut self) {
168 unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << self.i)) }
170 }
171
172 fn set_low(&mut self) {
173 unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (self.i + 16))) }
175 }
176 }
177
178 impl InputPin for $PXx<Output<OpenDrain>> {
179 fn is_high(&self) -> bool {
180 !self.is_low()
181 }
182
183 fn is_low(&self) -> bool {
184 unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 }
186 }
187 }
188
189 impl<MODE> InputPin for $PXx<Input<MODE>> {
190 fn is_high(&self) -> bool {
191 !self.is_low()
192 }
193
194 fn is_low(&self) -> bool {
195 unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 }
197 }
198 }
199
200 fn _set_alternate_mode (index:usize, mode: u32)
201 {
202 let offset = 2 * index;
203 let offset2 = 4 * index;
204 unsafe {
205 if offset2 < 32 {
206 &(*$GPIOX::ptr()).afrl.modify(|r, w| {
207 w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2))
208 });
209 } else
210 {
211 let offset2 = offset2 - 32;
212 &(*$GPIOX::ptr()).afrh.modify(|r, w| {
213 w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2))
214 });
215 }
216 &(*$GPIOX::ptr()).moder.modify(|r, w| {
217 w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))
218 });
219 }
220 }
221
222 impl<MODE> $PXx<Input<MODE>> {
223 pub fn downgrade(self) -> Pin<Input<MODE>> {
228 use stm32::gpioa;
229 use core::intrinsics::transmute;
230 Pin {
231 i: self.i,
232 port: unsafe{ transmute::<_, *const gpioa::RegisterBlock>($GPIOX::ptr())},
233 _mode: self._mode,
234 }
235 }
236 }
237
238 impl<MODE> $PXx<Output<MODE>> {
239 pub fn downgrade(self) -> Pin<Output<MODE>> {
244 use stm32::gpioa;
245 use core::intrinsics::transmute;
246 Pin {
247 i: self.i,
248 port: unsafe{ transmute::<_, *const gpioa::RegisterBlock>($GPIOX::ptr())},
249 _mode: self._mode,
250 }
251 }
252 }
253
254 $(
255 pub struct $PXi<MODE> {
257 _mode: PhantomData<MODE>,
258 }
259
260 impl<MODE> $PXi<MODE> {
261 pub fn into_alternate_af0(
263 self,
264 ) -> $PXi<Alternate<AF0>> {
265 _set_alternate_mode($i, 0);
266 $PXi { _mode: PhantomData }
267 }
268
269 pub fn into_alternate_af1(
271 self,
272 ) -> $PXi<Alternate<AF1>> {
273 _set_alternate_mode($i, 1);
274 $PXi { _mode: PhantomData }
275 }
276
277 pub fn into_alternate_af2(
279 self,
280 ) -> $PXi<Alternate<AF2>> {
281 _set_alternate_mode($i, 2);
282 $PXi { _mode: PhantomData }
283 }
284
285 pub fn into_alternate_af3(
287 self,
288 ) -> $PXi<Alternate<AF3>> {
289 _set_alternate_mode($i, 3);
290 $PXi { _mode: PhantomData }
291 }
292
293 pub fn into_alternate_af4(
295 self,
296 ) -> $PXi<Alternate<AF4>> {
297 _set_alternate_mode($i, 4);
298 $PXi { _mode: PhantomData }
299 }
300
301 pub fn into_alternate_af5(
303 self,
304 ) -> $PXi<Alternate<AF5>> {
305 _set_alternate_mode($i, 5);
306 $PXi { _mode: PhantomData }
307 }
308
309 pub fn into_alternate_af6(
311 self,
312 ) -> $PXi<Alternate<AF6>> {
313 _set_alternate_mode($i, 6);
314 $PXi { _mode: PhantomData }
315 }
316
317 pub fn into_alternate_af7(
319 self,
320 ) -> $PXi<Alternate<AF7>> {
321 _set_alternate_mode($i, 7);
322 $PXi { _mode: PhantomData }
323 }
324
325 pub fn into_floating_input(
327 self,
328 ) -> $PXi<Input<Floating>> {
329 let offset = 2 * $i;
330 unsafe {
331 &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
332 w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
333 });
334 &(*$GPIOX::ptr()).moder.modify(|r, w| {
335 w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
336 });
337 }
338 $PXi { _mode: PhantomData }
339 }
340
341 pub fn into_pull_down_input(
343 self,
344 ) -> $PXi<Input<PullDown>> {
345 let offset = 2 * $i;
346 unsafe {
347 &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
348 w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))
349 });
350 &(*$GPIOX::ptr()).moder.modify(|r, w| {
351 w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
352 });
353 }
354 $PXi { _mode: PhantomData }
355 }
356
357 pub fn into_pull_up_input(
359 self,
360 ) -> $PXi<Input<PullUp>> {
361 let offset = 2 * $i;
362 unsafe {
363 &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
364 w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))
365 });
366 &(*$GPIOX::ptr()).moder.modify(|r, w| {
367 w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
368 });
369 }
370 $PXi { _mode: PhantomData }
371 }
372
373 pub fn into_open_drain_output(
375 self,
376 ) -> $PXi<Output<OpenDrain>> {
377 let offset = 2 * $i;
378 unsafe {
379 &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
380 w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
381 });
382 &(*$GPIOX::ptr()).otyper.modify(|r, w| {
383 w.bits(r.bits() | (0b1 << $i))
384 });
385 &(*$GPIOX::ptr()).moder.modify(|r, w| {
386 w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))
387 });
388 }
389 $PXi { _mode: PhantomData }
390 }
391
392 pub fn into_push_pull_output(
394 self,
395 ) -> $PXi<Output<PushPull>> {
396 let offset = 2 * $i;
397
398 unsafe {
399 &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
400 w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
401 });
402 &(*$GPIOX::ptr()).otyper.modify(|r, w| {
403 w.bits(r.bits() & !(0b1 << $i))
404 });
405 &(*$GPIOX::ptr()).moder.modify(|r, w| {
406 w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))
407 });
408 }
409 $PXi { _mode: PhantomData }
410 }
411
412 pub fn into_push_pull_output_hs(
415 self,
416 ) -> $PXi<Output<PushPull>> {
417 let offset = 2 * $i;
418
419 unsafe {
420 &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
421 w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
422 });
423 &(*$GPIOX::ptr()).otyper.modify(|r, w| {
424 w.bits(r.bits() & !(0b1 << $i))
425 });
426 &(*$GPIOX::ptr()).ospeedr.modify(|r, w| {
427 w.bits(r.bits() & !(0b1 << $i))
428 });
429 &(*$GPIOX::ptr()).moder.modify(|r, w| {
430 w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))
431 });
432 }
433
434 $PXi { _mode: PhantomData }
435 }
436 }
437
438 impl $PXi<Output<OpenDrain>> {
439 pub fn internal_pull_up(&mut self, on: bool) {
441 let offset = 2 * $i;
442 let value = if on { 0b01 } else { 0b00 };
443 unsafe {
444 &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
445 w.bits((r.bits() & !(0b11 << offset)) | (value << offset))
446 })};
447 }
448 }
449
450 impl InputPin for $PXi<Output<OpenDrain>> {
451 fn is_high(&self) -> bool {
452 !self.is_low()
453 }
454
455 fn is_low(&self) -> bool {
456 unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 }
458 }
459 }
460
461 impl<MODE> $PXi<Alternate<MODE>> {
462 pub fn internal_pull_up(&mut self, on: bool) {
464 let offset = 2 * $i;
465 let value = if on { 0b01 } else { 0b00 };
466 unsafe {
467 &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
468 w.bits((r.bits() & !(0b11 << offset)) | (value << offset))
469 })};
470 }
471 }
472
473 impl<MODE> $PXi<Alternate<MODE>> {
474 pub fn set_open_drain(self) -> Self {
476 let offset = $i;
477 unsafe {
478 &(*$GPIOX::ptr()).otyper.modify(|r, w| {
479 w.bits(r.bits() | (1 << offset))
480 })};
481
482 self
483 }
484 }
485
486 impl<MODE> $PXi<Output<MODE>> {
487 pub fn downgrade(self) -> $PXx<Output<MODE>> {
492 $PXx {
493 i: $i,
494 _mode: self._mode,
495 }
496 }
497 }
498
499 impl<MODE> StatefulOutputPin for $PXi<Output<MODE>> {
500 fn is_set_high(&self) -> bool {
501 !self.is_set_low()
502 }
503
504 fn is_set_low(&self) -> bool {
505 unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << $i) == 0 }
507 }
508 }
509
510 impl<MODE> OutputPin for $PXi<Output<MODE>> {
511 fn set_high(&mut self) {
512 unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i)) }
514 }
515
516 fn set_low(&mut self) {
517 unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << ($i + 16))) }
519 }
520 }
521
522 impl<MODE> $PXi<Input<MODE>> {
523 pub fn downgrade(self) -> $PXx<Input<MODE>> {
528 $PXx {
529 i: $i,
530 _mode: self._mode,
531 }
532 }
533 }
534
535 impl<MODE> InputPin for $PXi<Input<MODE>> {
536 fn is_high(&self) -> bool {
537 !self.is_low()
538 }
539
540 fn is_low(&self) -> bool {
541 unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 }
543 }
544 }
545 )+
546 impl<TYPE> $PXx<TYPE> {
548 pub fn get_id (&self) -> u8
549 {
550 self.i
551 }
552 }
553 }
554 }
555}
556
557#[cfg(any(feature = "stm32f030f4"))]
559gpio!(GPIOA, gpioa, iopaen, PA, [
560 PA0: (pa0, 0, Input<Floating>),
561 PA1: (pa1, 1, Input<Floating>),
562 PA2: (pa2, 2, Input<Floating>),
563 PA3: (pa3, 3, Input<Floating>),
564 PA4: (pa4, 4, Input<Floating>),
565 PA5: (pa5, 5, Input<Floating>),
566 PA6: (pa6, 6, Input<Floating>),
567 PA7: (pa7, 7, Input<Floating>),
568 PA9: (pa9, 9, Input<Floating>),
569 PA10: (pa10, 10, Input<Floating>),
570 PA13: (pa13, 13, Input<Floating>),
571 PA14: (pa14, 14, Input<Floating>),
572]);
573
574#[cfg(any(
576 feature = "stm32f030k6",
577 feature = "stm32f030c6",
578 feature = "stm32f030c8",
579 feature = "stm32f030cc",
580 feature = "stm32f030r8",
581 feature = "stm32f030rc"
582))]
583gpio!(GPIOA, gpioa, iopaen, PA, [
584 PA0: (pa0, 0, Input<Floating>),
585 PA1: (pa1, 1, Input<Floating>),
586 PA2: (pa2, 2, Input<Floating>),
587 PA3: (pa3, 3, Input<Floating>),
588 PA4: (pa4, 4, Input<Floating>),
589 PA5: (pa5, 5, Input<Floating>),
590 PA6: (pa6, 6, Input<Floating>),
591 PA7: (pa7, 7, Input<Floating>),
592 PA8: (pa8, 8, Input<Floating>),
593 PA9: (pa9, 9, Input<Floating>),
594 PA10: (pa10, 10, Input<Floating>),
595 PA11: (pa11, 11, Input<Floating>),
596 PA12: (pa12, 12, Input<Floating>),
597 PA13: (pa13, 13, Input<Floating>),
598 PA14: (pa14, 14, Input<Floating>),
599 PA15: (pa15, 15, Input<Floating>),
600]);
601
602#[cfg(any(feature = "stm32f030x4"))]
604gpio!(GPIOB, gpiob, iopben, PB, [
605 PB1: (pb1, 1, Input<Floating>),
606]);
607
608#[cfg(any(feature = "stm32f030k6"))]
610gpio!(GPIOB, gpiob, iopben, PB, [
611 PB0: (pb0, 0, Input<Floating>),
612 PB1: (pb1, 1, Input<Floating>),
613 PB3: (pb3, 3, Input<Floating>),
614 PB4: (pb4, 4, Input<Floating>),
615 PB5: (pb5, 5, Input<Floating>),
616 PB6: (pb6, 6, Input<Floating>),
617 PB7: (pb7, 7, Input<Floating>),
618]);
619
620#[cfg(any(
622 feature = "stm32f030c6",
623 feature = "stm32f030c8",
624 feature = "stm32f030cc",
625 feature = "stm32f030r8",
626 feature = "stm32f030rc"
627))]
628gpio!(GPIOB, gpiob, iopben, PB, [
629 PB0: (pb0, 0, Input<Floating>),
630 PB1: (pb1, 1, Input<Floating>),
631 PB2: (pb2, 2, Input<Floating>),
632 PB3: (pb3, 3, Input<Floating>),
633 PB4: (pb4, 4, Input<Floating>),
634 PB5: (pb5, 5, Input<Floating>),
635 PB6: (pb6, 6, Input<Floating>),
636 PB7: (pb7, 7, Input<Floating>),
637 PB8: (pb8, 8, Input<Floating>),
638 PB9: (pb9, 9, Input<Floating>),
639 PB10: (pb10, 10, Input<Floating>),
640 PB11: (pb11, 11, Input<Floating>),
641 PB12: (pb12, 12, Input<Floating>),
642 PB13: (pb13, 13, Input<Floating>),
643 PB14: (pb14, 14, Input<Floating>),
644 PB15: (pb15, 15, Input<Floating>),
645]);
646
647#[cfg(any(
649 feature = "stm32f030c6",
650 feature = "stm32f030c8",
651 feature = "stm32f030cc",
652))]
653gpio!(GPIOC, gpioc, iopcen, PC, [
654 PC13: (pb13, 13, Input<Floating>),
655 PC14: (pb14, 14, Input<Floating>),
656 PC15: (pb15, 15, Input<Floating>),
657]);
658
659#[cfg(any(feature = "stm32f030r8", feature = "stm32f030rc"))]
661gpio!(GPIOC, gpioc, iopcen, PC, [
662 PC0: (pb0, 0, Input<Floating>),
663 PC1: (pb1, 1, Input<Floating>),
664 PC2: (pb2, 2, Input<Floating>),
665 PC3: (pb3, 3, Input<Floating>),
666 PC4: (pb4, 4, Input<Floating>),
667 PC5: (pb5, 5, Input<Floating>),
668 PC6: (pb6, 6, Input<Floating>),
669 PC7: (pb7, 7, Input<Floating>),
670 PC8: (pb8, 8, Input<Floating>),
671 PC9: (pb9, 9, Input<Floating>),
672 PC10: (pb10, 10, Input<Floating>),
673 PC11: (pb11, 11, Input<Floating>),
674 PC12: (pb12, 12, Input<Floating>),
675 PC13: (pb13, 13, Input<Floating>),
676 PC14: (pb14, 14, Input<Floating>),
677 PC15: (pb15, 15, Input<Floating>),
678]);
679
680#[cfg(any(
690 feature = "stm32f030f4",
691 feature = "stm32f030k6",
692 feature = "stm32f030cc",
693 feature = "stm32f030rc"
694))]
695gpio!(GPIOF, gpiof, iopfen, PF, [
696 PF0: (pf0, 0, Input<Floating>),
697 PF1: (pf1, 1, Input<Floating>),
698]);
699
700#[cfg(any(feature = "stm32f030c6", feature = "stm32f030c8",))]
702gpio!(GPIOF, gpiof, iopfen, PF, [
703 PF0: (pf0, 0, Input<Floating>),
704 PF1: (pf1, 1, Input<Floating>),
705 PF6: (pf5, 5, Input<Floating>),
707 PF7: (pf5, 5, Input<Floating>),
708]);
709
710#[cfg(feature = "stm32f030r8")]
713gpio!(GPIOF, gpiof, iopfen, PF, [
714 PF0: (pf0, 0, Input<Floating>),
715 PF1: (pf1, 1, Input<Floating>),
716 PF4: (pf4, 4, Input<Floating>),
718 PF5: (pf5, 5, Input<Floating>),
719 PF6: (pf5, 5, Input<Floating>),
720 PF7: (pf5, 5, Input<Floating>),
721]);