stm32f7x7_hal/
gpio.rs

1//! General Purpose Input / Output
2
3use core::marker::PhantomData;
4
5use crate::stm32::{EXTI, SYSCFG};
6
7/// Extension trait to split a GPIO peripheral in independent pins and registers
8pub trait GpioExt {
9    /// The parts to split the GPIO into
10    type Parts;
11
12    /// Splits the GPIO block into independent pins and registers
13    fn split(self) -> Self::Parts;
14}
15
16pub struct AF0;
17pub struct AF1;
18pub struct AF2;
19pub struct AF3;
20pub struct AF4;
21pub struct AF5;
22pub struct AF6;
23pub struct AF7;
24pub struct AF8;
25pub struct AF9;
26pub struct AF10;
27pub struct AF11;
28pub struct AF12;
29pub struct AF13;
30pub struct AF14;
31pub struct AF15;
32
33pub struct Alternate<MODE> {
34    _mode: PhantomData<MODE>,
35}
36
37/// Input mode (type state)
38pub struct Input<MODE> {
39    _mode: PhantomData<MODE>,
40}
41
42/// Floating input (type state)
43pub struct Floating;
44
45/// Pulled down input (type state)
46pub struct PullDown;
47
48/// Pulled up input (type state)
49pub struct PullUp;
50
51/// Open drain input or output (type state)
52pub struct OpenDrain;
53
54/// Output mode (type state)
55pub struct Output<MODE> {
56    _mode: PhantomData<MODE>,
57}
58
59/// Push pull output (type state)
60pub struct PushPull;
61
62/// Analog mode (type state)
63pub struct Analog;
64
65/// GPIO Pin speed selection
66pub enum Speed {
67    Low = 0,
68    Medium = 1,
69    High = 2,
70    VeryHigh = 3,
71}
72
73#[derive(Debug, PartialEq)]
74pub enum Edge {
75    RISING,
76    FALLING,
77    RISING_FALLING,
78}
79
80/// External Interrupt Pin
81pub trait ExtiPin {
82    fn make_interrupt_source(&mut self, syscfg: &mut SYSCFG);
83    fn trigger_on_edge(&mut self, exti: &mut EXTI, level: Edge);
84    fn enable_interrupt(&mut self, exti: &mut EXTI);
85    fn disable_interrupt(&mut self, exti: &mut EXTI);
86    fn clear_interrupt_pending_bit(&mut self, exti: &mut EXTI);
87}
88
89macro_rules! gpio {
90    ($GPIOX:ident, $gpiox:ident, $iopxenr:ident, $PXx:ident, $extigpionr:expr, [
91        $($PXi:ident: ($pxi:ident, $i:expr, $MODE:ty, $exticri:ident),)+
92    ]) => {
93        /// GPIO
94        pub mod $gpiox {
95            use core::marker::PhantomData;
96
97            use embedded_hal::digital::{InputPin, OutputPin, StatefulOutputPin, toggleable};
98            use crate::stm32::$GPIOX;
99
100            use crate::stm32::{RCC, EXTI, SYSCFG};
101            use super::{
102                Alternate, Floating, GpioExt, Input, OpenDrain, Output, Speed,
103                PullDown, PullUp, PushPull, AF0, AF1, AF2, AF3, AF4, AF5, AF6, AF7, AF8, AF9, AF10,
104                AF11, AF12, AF13, AF14, AF15, Analog, Edge, ExtiPin,
105            };
106
107            /// GPIO parts
108            pub struct Parts {
109                $(
110                    /// Pin
111                    pub $pxi: $PXi<$MODE>,
112                )+
113            }
114
115            impl GpioExt for $GPIOX {
116                type Parts = Parts;
117
118                fn split(self) -> Parts {
119                    // NOTE(unsafe) This executes only during initialisation
120                    let rcc = unsafe { &(*RCC::ptr()) };
121                    rcc.ahb1enr.modify(|_, w| w.$iopxenr().set_bit());
122
123                    Parts {
124                        $(
125                            $pxi: $PXi { _mode: PhantomData },
126                        )+
127                    }
128                }
129            }
130
131            /// Partially erased pin
132            pub struct $PXx<MODE> {
133                i: u8,
134                _mode: PhantomData<MODE>,
135            }
136
137            impl<MODE> $PXx<MODE> {
138                pub fn get_id(&self) -> u8 {
139                    self.i
140                }
141            }
142
143            impl<MODE> OutputPin for $PXx<Output<MODE>> {
144                fn set_high(&mut self) {
145                    // NOTE(unsafe) atomic write to a stateless register
146                    unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << self.i)) }
147                }
148
149                fn set_low(&mut self) {
150                    // NOTE(unsafe) atomic write to a stateless register
151                    unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (self.i + 16))) }
152                }
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                    // NOTE(unsafe) atomic read with no side effects
162                    unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << self.i) == 0 }
163                }
164            }
165
166            impl<MODE> toggleable::Default for $PXx<Output<MODE>> {}
167
168            impl<MODE> InputPin for $PXx<Output<MODE>> {
169                fn is_high(&self) -> bool {
170                    !self.is_low()
171                }
172
173                fn is_low(&self) -> bool {
174                    // NOTE(unsafe) atomic read with no side effects
175                    unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 }
176                }
177            }
178
179            impl<MODE> InputPin for $PXx<Input<MODE>> {
180                fn is_high(&self) -> bool {
181                    !self.is_low()
182                }
183
184                fn is_low(&self) -> bool {
185                    // NOTE(unsafe) atomic read with no side effects
186                    unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 }
187                }
188            }
189
190            impl<MODE> ExtiPin for $PXx<Input<MODE>> {
191                /// Make corresponding EXTI line sensitive to this pin
192                fn make_interrupt_source(&mut self, syscfg: &mut SYSCFG) {
193                    let offset = 4 * (self.i % 4);
194                    match self.i {
195                        0...3 => {
196                            syscfg.exticr1.modify(|r, w| unsafe {
197                                w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
198                            });
199                        },
200                        4...7 => {
201                            syscfg.exticr2.modify(|r, w| unsafe {
202                                w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
203                            });
204                        },
205                        8...11 => {
206                            syscfg.exticr3.modify(|r, w| unsafe {
207                                w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
208                            });
209                        },
210                        12...15 => {
211                            syscfg.exticr4.modify(|r, w| unsafe {
212                                w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
213                            });
214                        },
215                        _ => {}
216                    }
217                }
218
219                /// Generate interrupt on rising edge, falling edge or both
220                fn trigger_on_edge(&mut self, exti: &mut EXTI, edge: Edge) {
221                    match edge {
222                        Edge::RISING => {
223                            exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
224                            exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) });
225                        },
226                        Edge::FALLING => {
227                            exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
228                            exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) });
229                        },
230                        Edge::RISING_FALLING => {
231                            exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
232                            exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
233                        }
234                    }
235                }
236
237                /// Enable external interrupts from this pin.
238                fn enable_interrupt(&mut self, exti: &mut EXTI) {
239                    exti.imr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
240                }
241
242                /// Disable external interrupts from this pin
243                fn disable_interrupt(&mut self, exti: &mut EXTI) {
244                    exti.imr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) });
245                }
246
247                /// Clear the interrupt pending bit for this pin
248                fn clear_interrupt_pending_bit(&mut self, exti: &mut EXTI) {
249                    exti.pr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
250                }
251            }
252
253            fn _set_alternate_mode (index: usize, mode: u32)
254            {
255                let offset = 2 * index;
256                let offset2 = 4 * index;
257                unsafe {
258                    if offset2 < 32 {
259                        &(*$GPIOX::ptr()).afrl.modify(|r, w| {
260                            w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2))
261                        });
262                    } else {
263                        let offset2 = offset2 - 32;
264                        &(*$GPIOX::ptr()).afrh.modify(|r, w| {
265                            w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2))
266                        });
267                    }
268                    &(*$GPIOX::ptr()).moder.modify(|r, w| {
269                        w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))
270                    });
271                }
272            }
273
274            $(
275                /// Pin
276                pub struct $PXi<MODE> {
277                    _mode: PhantomData<MODE>,
278                }
279
280                impl<MODE> $PXi<MODE> {
281                    /// Configures the pin to operate in AF0 mode
282                    pub fn into_alternate_af0(self) -> $PXi<Alternate<AF0>> {
283                        _set_alternate_mode($i, 0);
284                        $PXi { _mode: PhantomData }
285                    }
286
287                    /// Configures the pin to operate in AF1 mode
288                    pub fn into_alternate_af1(self) -> $PXi<Alternate<AF1>> {
289                        _set_alternate_mode($i, 1);
290                        $PXi { _mode: PhantomData }
291                    }
292
293                    /// Configures the pin to operate in AF2 mode
294                    pub fn into_alternate_af2(self) -> $PXi<Alternate<AF2>> {
295                        _set_alternate_mode($i, 2);
296                        $PXi { _mode: PhantomData }
297                    }
298
299                    /// Configures the pin to operate in AF3 mode
300                    pub fn into_alternate_af3(self) -> $PXi<Alternate<AF3>> {
301                        _set_alternate_mode($i, 3);
302                        $PXi { _mode: PhantomData }
303                    }
304
305                    /// Configures the pin to operate in AF4 mode
306                    pub fn into_alternate_af4(self) -> $PXi<Alternate<AF4>> {
307                        _set_alternate_mode($i, 4);
308                        $PXi { _mode: PhantomData }
309                    }
310
311                    /// Configures the pin to operate in AF5 mode
312                    pub fn into_alternate_af5(self) -> $PXi<Alternate<AF5>> {
313                        _set_alternate_mode($i, 5);
314                        $PXi { _mode: PhantomData }
315                    }
316
317                    /// Configures the pin to operate in AF6 mode
318                    pub fn into_alternate_af6(self) -> $PXi<Alternate<AF6>> {
319                        _set_alternate_mode($i, 6);
320                        $PXi { _mode: PhantomData }
321                    }
322
323                    /// Configures the pin to operate in AF7 mode
324                    pub fn into_alternate_af7(self) -> $PXi<Alternate<AF7>> {
325                        _set_alternate_mode($i, 7);
326                        $PXi { _mode: PhantomData }
327                    }
328
329                    /// Configures the pin to operate in AF8 mode
330                    pub fn into_alternate_af8(self) -> $PXi<Alternate<AF8>> {
331                        _set_alternate_mode($i, 8);
332                        $PXi { _mode: PhantomData }
333                    }
334
335                    /// Configures the pin to operate in AF9 mode
336                    pub fn into_alternate_af9(self) -> $PXi<Alternate<AF9>> {
337                        _set_alternate_mode($i, 9);
338                        $PXi { _mode: PhantomData }
339                    }
340
341                    /// Configures the pin to operate in AF10 mode
342                    pub fn into_alternate_af10(self) -> $PXi<Alternate<AF10>> {
343                        _set_alternate_mode($i, 10);
344                        $PXi { _mode: PhantomData }
345                    }
346
347                    /// Configures the pin to operate in AF11 mode
348                    pub fn into_alternate_af11(self) -> $PXi<Alternate<AF11>> {
349                        _set_alternate_mode($i, 11);
350                        $PXi { _mode: PhantomData }
351                    }
352
353                    /// Configures the pin to operate in AF12 mode
354                    pub fn into_alternate_af12(self) -> $PXi<Alternate<AF12>> {
355                        _set_alternate_mode($i, 12);
356                        $PXi { _mode: PhantomData }
357                    }
358
359                    /// Configures the pin to operate in AF13 mode
360                    pub fn into_alternate_af13(self) -> $PXi<Alternate<AF13>> {
361                        _set_alternate_mode($i, 13);
362                        $PXi { _mode: PhantomData }
363                    }
364
365                    /// Configures the pin to operate in AF14 mode
366                    pub fn into_alternate_af14(self) -> $PXi<Alternate<AF14>> {
367                        _set_alternate_mode($i, 14);
368                        $PXi { _mode: PhantomData }
369                    }
370
371                    /// Configures the pin to operate in AF15 mode
372                    pub fn into_alternate_af15(self) -> $PXi<Alternate<AF15>> {
373                        _set_alternate_mode($i, 15);
374                        $PXi { _mode: PhantomData }
375                    }
376
377                    /// Configures the pin to operate as a floating input pin
378                    pub fn into_floating_input(self) -> $PXi<Input<Floating>> {
379                        let offset = 2 * $i;
380                        unsafe {
381                            &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
382                                w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
383                            });
384                            &(*$GPIOX::ptr()).moder.modify(|r, w| {
385                                w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
386                            })
387                        };
388
389                        $PXi { _mode: PhantomData }
390                    }
391
392                    /// Configures the pin to operate as a pulled down input pin
393                    pub fn into_pull_down_input(self) -> $PXi<Input<PullDown>> {
394                        let offset = 2 * $i;
395                        unsafe {
396                            &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
397                                w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))
398                            });
399                            &(*$GPIOX::ptr()).moder.modify(|r, w| {
400                                w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
401                            })
402                        };
403
404                        $PXi { _mode: PhantomData }
405                    }
406
407                    /// Configures the pin to operate as a pulled up input pin
408                    pub fn into_pull_up_input(self) -> $PXi<Input<PullUp>> {
409                        let offset = 2 * $i;
410                        unsafe {
411                            &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
412                                w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))
413                            });
414                            &(*$GPIOX::ptr()).moder.modify(|r, w| {
415                                w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
416                            }
417                        )};
418
419                        $PXi { _mode: PhantomData }
420                    }
421
422                    /// Configures the pin to operate as an open drain output pin
423                    pub fn into_open_drain_output(self) -> $PXi<Output<OpenDrain>> {
424                        let offset = 2 * $i;
425                        unsafe {
426                            &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
427                                w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
428                            });
429                            &(*$GPIOX::ptr()).otyper.modify(|r, w| {
430                                w.bits(r.bits() | (0b1 << $i))
431                            });
432                            &(*$GPIOX::ptr()).moder.modify(|r, w| {
433                                w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))
434                            })
435                        };
436
437                        $PXi { _mode: PhantomData }
438                    }
439
440                    /// Configures the pin to operate as an push pull output pin
441                    pub fn into_push_pull_output(self) -> $PXi<Output<PushPull>> {
442                        let offset = 2 * $i;
443
444                        unsafe {
445                            &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
446                                w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
447                            });
448                            &(*$GPIOX::ptr()).otyper.modify(|r, w| {
449                                w.bits(r.bits() & !(0b1 << $i))
450                            });
451                            &(*$GPIOX::ptr()).moder.modify(|r, w| {
452                                w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))
453                            })
454                        };
455
456                        $PXi { _mode: PhantomData }
457                    }
458
459                    /// Configures the pin to operate as an analog input pin
460                    pub fn into_analog(self) -> $PXi<Analog> {
461                        let offset = 2 * $i;
462
463                        unsafe {
464                            &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
465                                w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
466                            });
467                            &(*$GPIOX::ptr()).moder.modify(|r, w| {
468                                w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))
469                            }
470                        )};
471
472                        $PXi { _mode: PhantomData }
473                    }
474                }
475
476                impl<MODE> $PXi<Output<MODE>> {
477                    /// Set pin speed
478                    pub fn set_speed(self, speed: Speed) -> Self {
479                        let offset = 2 * $i;
480
481                        unsafe {
482                            &(*$GPIOX::ptr()).ospeedr.modify(|r, w| {
483                                w.bits((r.bits() & !(0b11 << offset)) | ((speed as u32) << offset))
484                            })
485                        };
486
487                        self
488                    }
489                }
490
491                impl $PXi<Output<OpenDrain>> {
492                    /// Enables / disables the internal pull up
493                    pub fn internal_pull_up(&mut self, on: bool) {
494                        let offset = 2 * $i;
495                        let value = if on { 0b01 } else { 0b00 };
496                        unsafe {
497                            &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
498                                w.bits((r.bits() & !(0b11 << offset)) | (value << offset))
499                            })
500                        };
501                    }
502                }
503
504                impl<MODE> $PXi<Alternate<MODE>> {
505                    /// Set pin speed
506                    pub fn set_speed(self, speed: Speed) -> Self {
507                        let offset = 2 * $i;
508
509                        unsafe {
510                            &(*$GPIOX::ptr()).ospeedr.modify(|r, w| {
511                                w.bits((r.bits() & !(0b11 << offset)) | ((speed as u32) << offset))
512                            })
513                        };
514
515                        self
516                    }
517
518                    /// Enables / disables the internal pull up
519                    pub fn internal_pull_up(self, on: bool) -> Self {
520                        let offset = 2 * $i;
521                        let value = if on { 0b01 } else { 0b00 };
522                        unsafe {
523                            &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
524                                w.bits((r.bits() & !(0b11 << offset)) | (value << offset))
525                            })
526                        };
527
528                        self
529                    }
530                }
531
532                impl<MODE> $PXi<Alternate<MODE>> {
533                    /// Turns pin alternate configuration pin into open drain
534                    pub fn set_open_drain(self) -> Self {
535                        let offset = $i;
536                        unsafe {
537                            &(*$GPIOX::ptr()).otyper.modify(|r, w| {
538                                w.bits(r.bits() | (1 << offset))
539                            })
540                        };
541
542                        self
543                    }
544                }
545
546                impl<MODE> $PXi<MODE> {
547                    /// Erases the pin number from the type
548                    ///
549                    /// This is useful when you want to collect the pins into an array where you
550                    /// need all the elements to have the same type
551                    pub fn downgrade(self) -> $PXx<MODE> {
552                        $PXx {
553                            i: $i,
554                            _mode: self._mode,
555                        }
556                    }
557                }
558
559                impl<MODE> OutputPin for $PXi<Output<MODE>> {
560                    fn set_high(&mut self) {
561                        // NOTE(unsafe) atomic write to a stateless register
562                        unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i)) }
563                    }
564
565                    fn set_low(&mut self) {
566                        // NOTE(unsafe) atomic write to a stateless register
567                        unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << ($i + 16))) }
568                    }
569                }
570
571                impl<MODE> StatefulOutputPin for $PXi<Output<MODE>> {
572                    fn is_set_high(&self) -> bool {
573                        !self.is_set_low()
574                    }
575
576                    fn is_set_low(&self) -> bool {
577                        // NOTE(unsafe) atomic read with no side effects
578                        unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << $i) == 0 }
579                    }
580                }
581
582                impl<MODE> toggleable::Default for $PXi<Output<MODE>> {}
583
584                impl<MODE> InputPin for $PXi<Output<MODE>> {
585                    fn is_high(&self) -> bool {
586                        !self.is_low()
587                    }
588
589                    fn is_low(&self) -> bool {
590                        // NOTE(unsafe) atomic read with no side effects
591                        unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 }
592                    }
593                }
594
595                impl<MODE> InputPin for $PXi<Input<MODE>> {
596                    fn is_high(&self) -> bool {
597                        !self.is_low()
598                    }
599
600                    fn is_low(&self) -> bool {
601                        // NOTE(unsafe) atomic read with no side effects
602                        unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 }
603                    }
604                }
605
606                impl<MODE> ExtiPin for $PXi<Input<MODE>> {
607                    /// Configure EXTI Line $i to trigger from this pin.
608                    fn make_interrupt_source(&mut self, syscfg: &mut SYSCFG) {
609                        let offset = 4 * ($i % 4);
610                        syscfg.$exticri.modify(|r, w| unsafe {
611                            let mut exticr = r.bits();
612                            exticr = (exticr & !(0xf << offset)) | ($extigpionr << offset);
613                            w.bits(exticr)
614                        });
615                    }
616
617                    /// Generate interrupt on rising edge, falling edge or both
618                    fn trigger_on_edge(&mut self, exti: &mut EXTI, edge: Edge) {
619                        match edge {
620                            Edge::RISING => {
621                                exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
622                                exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) });
623                            },
624                            Edge::FALLING => {
625                                exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
626                                exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) });
627                            },
628                            Edge::RISING_FALLING => {
629                                exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
630                                exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
631                            }
632                        }
633                    }
634
635                    /// Enable external interrupts from this pin.
636                    fn enable_interrupt(&mut self, exti: &mut EXTI) {
637                        exti.imr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
638                    }
639
640                    /// Disable external interrupts from this pin
641                    fn disable_interrupt(&mut self, exti: &mut EXTI) {
642                        exti.imr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) });
643                    }
644
645                    /// Clear the interrupt pending bit for this pin
646                    fn clear_interrupt_pending_bit(&mut self, exti: &mut EXTI) {
647                        exti.pr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
648                    }
649                }
650
651            )+
652        }
653    }
654}
655
656gpio!(GPIOA, gpioa, gpioaen, PA, 0, [
657    PA0: (pa0, 0, Input<Floating>, exticr1),
658    PA1: (pa1, 1, Input<Floating>, exticr1),
659    PA2: (pa2, 2, Input<Floating>, exticr1),
660    PA3: (pa3, 3, Input<Floating>, exticr1),
661    PA4: (pa4, 4, Input<Floating>, exticr2),
662    PA5: (pa5, 5, Input<Floating>, exticr2),
663    PA6: (pa6, 6, Input<Floating>, exticr2),
664    PA7: (pa7, 7, Input<Floating>, exticr2),
665    PA8: (pa8, 8, Input<Floating>, exticr3),
666    PA9: (pa9, 9, Input<Floating>, exticr3),
667    PA10: (pa10, 10, Input<Floating>, exticr3),
668    PA11: (pa11, 11, Input<Floating>, exticr3),
669    PA12: (pa12, 12, Input<Floating>, exticr4),
670    PA13: (pa13, 13, Input<Floating>, exticr4),
671    PA14: (pa14, 14, Input<Floating>, exticr4),
672    PA15: (pa15, 15, Input<Floating>, exticr4),
673]);
674
675gpio!(GPIOB, gpiob, gpioben, PB, 1, [
676    PB0: (pb0, 0, Input<Floating>, exticr1),
677    PB1: (pb1, 1, Input<Floating>, exticr1),
678    PB2: (pb2, 2, Input<Floating>, exticr1),
679    PB3: (pb3, 3, Input<Floating>, exticr1),
680    PB4: (pb4, 4, Input<Floating>, exticr2),
681    PB5: (pb5, 5, Input<Floating>, exticr2),
682    PB6: (pb6, 6, Input<Floating>, exticr2),
683    PB7: (pb7, 7, Input<Floating>, exticr2),
684    PB8: (pb8, 8, Input<Floating>, exticr3),
685    PB9: (pb9, 9, Input<Floating>, exticr3),
686    PB10: (pb10, 10, Input<Floating>, exticr3),
687    PB11: (pb11, 11, Input<Floating>, exticr3),
688    PB12: (pb12, 12, Input<Floating>, exticr4),
689    PB13: (pb13, 13, Input<Floating>, exticr4),
690    PB14: (pb14, 14, Input<Floating>, exticr4),
691    PB15: (pb15, 15, Input<Floating>, exticr4),
692]);
693
694gpio!(GPIOC, gpioc, gpiocen, PC, 2, [
695    PC0: (pc0, 0, Input<Floating>, exticr1),
696    PC1: (pc1, 1, Input<Floating>, exticr1),
697    PC2: (pc2, 2, Input<Floating>, exticr1),
698    PC3: (pc3, 3, Input<Floating>, exticr1),
699    PC4: (pc4, 4, Input<Floating>, exticr2),
700    PC5: (pc5, 5, Input<Floating>, exticr2),
701    PC6: (pc6, 6, Input<Floating>, exticr2),
702    PC7: (pc7, 7, Input<Floating>, exticr2),
703    PC8: (pc8, 8, Input<Floating>, exticr3),
704    PC9: (pc9, 9, Input<Floating>, exticr3),
705    PC10: (pc10, 10, Input<Floating>, exticr3),
706    PC11: (pc11, 11, Input<Floating>, exticr3),
707    PC12: (pc12, 12, Input<Floating>, exticr4),
708    PC13: (pc13, 13, Input<Floating>, exticr4),
709    PC14: (pc14, 14, Input<Floating>, exticr4),
710    PC15: (pc15, 15, Input<Floating>, exticr4),
711]);
712
713gpio!(GPIOD, gpiod, gpioden, PD, 3, [
714    PD0: (pd0, 0, Input<Floating>, exticr1),
715    PD1: (pd1, 1, Input<Floating>, exticr1),
716    PD2: (pd2, 2, Input<Floating>, exticr1),
717    PD3: (pd3, 3, Input<Floating>, exticr1),
718    PD4: (pd4, 4, Input<Floating>, exticr2),
719    PD5: (pd5, 5, Input<Floating>, exticr2),
720    PD6: (pd6, 6, Input<Floating>, exticr2),
721    PD7: (pd7, 7, Input<Floating>, exticr2),
722    PD8: (pd8, 8, Input<Floating>, exticr3),
723    PD9: (pd9, 9, Input<Floating>, exticr3),
724    PD10: (pd10, 10, Input<Floating>, exticr3),
725    PD11: (pd11, 11, Input<Floating>, exticr3),
726    PD12: (pd12, 12, Input<Floating>, exticr4),
727    PD13: (pd13, 13, Input<Floating>, exticr4),
728    PD14: (pd14, 14, Input<Floating>, exticr4),
729    PD15: (pd15, 15, Input<Floating>, exticr4),
730]);
731
732gpio!(GPIOE, gpioe, gpioeen, PE, 4, [
733    PE0: (pe0, 0, Input<Floating>, exticr1),
734    PE1: (pe1, 1, Input<Floating>, exticr1),
735    PE2: (pe2, 2, Input<Floating>, exticr1),
736    PE3: (pe3, 3, Input<Floating>, exticr1),
737    PE4: (pe4, 4, Input<Floating>, exticr2),
738    PE5: (pe5, 5, Input<Floating>, exticr2),
739    PE6: (pe6, 6, Input<Floating>, exticr2),
740    PE7: (pe7, 7, Input<Floating>, exticr2),
741    PE8: (pe8, 8, Input<Floating>, exticr3),
742    PE9: (pe9, 9, Input<Floating>, exticr3),
743    PE10: (pe10, 10, Input<Floating>, exticr3),
744    PE11: (pe11, 11, Input<Floating>, exticr3),
745    PE12: (pe12, 12, Input<Floating>, exticr4),
746    PE13: (pe13, 13, Input<Floating>, exticr4),
747    PE14: (pe14, 14, Input<Floating>, exticr4),
748    PE15: (pe15, 15, Input<Floating>, exticr4),
749]);
750
751gpio!(GPIOF, gpiof, gpiofen, PF, 5, [
752    PF0: (pf0, 0, Input<Floating>, exticr1),
753    PF1: (pf1, 1, Input<Floating>, exticr1),
754    PF2: (pf2, 2, Input<Floating>, exticr1),
755    PF3: (pf3, 3, Input<Floating>, exticr1),
756    PF4: (pf4, 4, Input<Floating>, exticr2),
757    PF5: (pf5, 5, Input<Floating>, exticr2),
758    PF6: (pf6, 6, Input<Floating>, exticr2),
759    PF7: (pf7, 7, Input<Floating>, exticr2),
760    PF8: (pf8, 8, Input<Floating>, exticr3),
761    PF9: (pf9, 9, Input<Floating>, exticr3),
762    PF10: (pf10, 10, Input<Floating>, exticr3),
763    PF11: (pf11, 11, Input<Floating>, exticr3),
764    PF12: (pf12, 12, Input<Floating>, exticr4),
765    PF13: (pf13, 13, Input<Floating>, exticr4),
766    PF14: (pf14, 14, Input<Floating>, exticr4),
767    PF15: (pf15, 15, Input<Floating>, exticr4),
768]);
769
770gpio!(GPIOG, gpiog, gpiogen, PG, 6, [
771    PG0: (pg0, 0, Input<Floating>, exticr1),
772    PG1: (pg1, 1, Input<Floating>, exticr1),
773    PG2: (pg2, 2, Input<Floating>, exticr1),
774    PG3: (pg3, 3, Input<Floating>, exticr1),
775    PG4: (pg4, 4, Input<Floating>, exticr2),
776    PG5: (pg5, 5, Input<Floating>, exticr2),
777    PG6: (pg6, 6, Input<Floating>, exticr2),
778    PG7: (pg7, 7, Input<Floating>, exticr2),
779    PG8: (pg8, 8, Input<Floating>, exticr3),
780    PG9: (pg9, 9, Input<Floating>, exticr3),
781    PG10: (pg10, 10, Input<Floating>, exticr3),
782    PG11: (pg11, 11, Input<Floating>, exticr3),
783    PG12: (pg12, 12, Input<Floating>, exticr4),
784    PG13: (pg13, 13, Input<Floating>, exticr4),
785    PG14: (pg14, 14, Input<Floating>, exticr4),
786    PG15: (pg15, 15, Input<Floating>, exticr4),
787]);
788
789gpio!(GPIOH, gpioh, gpiohen, PH, 7, [
790    PH0: (ph0, 0, Input<Floating>, exticr1),
791    PH1: (ph1, 1, Input<Floating>, exticr1),
792    PH2: (ph2, 2, Input<Floating>, exticr1),
793    PH3: (ph3, 3, Input<Floating>, exticr1),
794    PH4: (ph4, 4, Input<Floating>, exticr2),
795    PH5: (ph5, 5, Input<Floating>, exticr2),
796    PH6: (ph6, 6, Input<Floating>, exticr2),
797    PH7: (ph7, 7, Input<Floating>, exticr2),
798    PH8: (ph8, 8, Input<Floating>, exticr3),
799    PH9: (ph9, 9, Input<Floating>, exticr3),
800    PH10: (ph10, 10, Input<Floating>, exticr3),
801    PH11: (ph11, 11, Input<Floating>, exticr3),
802    PH12: (ph12, 12, Input<Floating>, exticr4),
803    PH13: (ph13, 13, Input<Floating>, exticr4),
804    PH14: (ph14, 14, Input<Floating>, exticr4),
805    PH15: (ph15, 15, Input<Floating>, exticr4),
806]);
807
808gpio!(GPIOI, gpioi, gpioien, PI, 8, [
809    PI0: (pi0, 0, Input<Floating>, exticr1),
810    PI1: (pi1, 1, Input<Floating>, exticr1),
811    PI2: (pi2, 2, Input<Floating>, exticr1),
812    PI3: (pi3, 3, Input<Floating>, exticr1),
813    PI4: (pi4, 4, Input<Floating>, exticr2),
814    PI5: (pi5, 5, Input<Floating>, exticr2),
815    PI6: (pi6, 6, Input<Floating>, exticr2),
816    PI7: (pi7, 7, Input<Floating>, exticr2),
817    PI8: (pi8, 8, Input<Floating>, exticr3),
818    PI9: (pi9, 9, Input<Floating>, exticr3),
819    PI10: (pi10, 10, Input<Floating>, exticr3),
820    PI11: (pi11, 11, Input<Floating>, exticr3),
821    PI12: (pi12, 12, Input<Floating>, exticr4),
822    PI13: (pi13, 13, Input<Floating>, exticr4),
823    PI14: (pi14, 14, Input<Floating>, exticr4),
824    PI15: (pi15, 15, Input<Floating>, exticr4),
825]);
826
827gpio!(GPIOJ, gpioj, gpiojen, PJ, 9, [
828    PJ0: (pj0, 0, Input<Floating>, exticr1),
829    PJ1: (pj1, 1, Input<Floating>, exticr1),
830    PJ2: (pj2, 2, Input<Floating>, exticr1),
831    PJ3: (pj3, 3, Input<Floating>, exticr1),
832    PJ4: (pj4, 4, Input<Floating>, exticr2),
833    PJ5: (pj5, 5, Input<Floating>, exticr2),
834    PJ6: (pj6, 6, Input<Floating>, exticr2),
835    PJ7: (pj7, 7, Input<Floating>, exticr2),
836    PJ8: (pj8, 8, Input<Floating>, exticr3),
837    PJ9: (pj9, 9, Input<Floating>, exticr3),
838    PJ10: (pj10, 10, Input<Floating>, exticr3),
839    PJ11: (pj11, 11, Input<Floating>, exticr3),
840    PJ12: (pj12, 12, Input<Floating>, exticr4),
841    PJ13: (pj13, 13, Input<Floating>, exticr4),
842    PJ14: (pj14, 14, Input<Floating>, exticr4),
843    PJ15: (pj15, 15, Input<Floating>, exticr4),
844]);
845
846gpio!(GPIOK, gpiok, gpioken, PK, 10, [
847    PK0: (pk0, 0, Input<Floating>, exticr1),
848    PK1: (pk1, 1, Input<Floating>, exticr1),
849    PK2: (pk2, 2, Input<Floating>, exticr1),
850    PK3: (pk3, 3, Input<Floating>, exticr1),
851    PK4: (pk4, 4, Input<Floating>, exticr2),
852    PK5: (pk5, 5, Input<Floating>, exticr2),
853    PK6: (pk6, 6, Input<Floating>, exticr2),
854    PK7: (pk7, 7, Input<Floating>, exticr2),
855]);