stm32f0xx_hal/
gpio.rs

1//! General Purpose Input / Output
2
3use core::convert::Infallible;
4use core::marker::PhantomData;
5
6use crate::rcc::Rcc;
7
8/// Extension trait to split a GPIO peripheral in independent pins and registers
9pub trait GpioExt {
10    /// The parts to split the GPIO into
11    type Parts;
12
13    /// Splits the GPIO block into independent pins and registers
14    fn split(self, rcc: &mut Rcc) -> Self::Parts;
15}
16
17trait GpioRegExt {
18    fn is_low(&self, pos: u8) -> bool;
19    fn is_set_low(&self, pos: u8) -> bool;
20    fn set_high(&self, pos: u8);
21    fn set_low(&self, pos: u8);
22}
23
24/// Alternate function 0
25pub struct AF0;
26/// Alternate function 1
27pub struct AF1;
28/// Alternate function 2
29pub struct AF2;
30/// Alternate function 3
31pub struct AF3;
32/// Alternate function 4
33pub struct AF4;
34/// Alternate function 5
35pub struct AF5;
36/// Alternate function 6
37pub struct AF6;
38/// Alternate function 7
39pub struct AF7;
40
41/// Alternate function mode (type state)
42pub struct Alternate<AF> {
43    _mode: PhantomData<AF>,
44}
45
46/// Input mode (type state)
47pub struct Input<MODE> {
48    _mode: PhantomData<MODE>,
49}
50
51/// Floating input (type state)
52pub struct Floating;
53
54/// Pulled down input (type state)
55pub struct PullDown;
56
57/// Pulled up input (type state)
58pub struct PullUp;
59
60/// Open drain input or output (type state)
61pub struct OpenDrain;
62
63/// Analog mode (type state)
64pub struct Analog;
65
66/// Output mode (type state)
67pub struct Output<MODE> {
68    _mode: PhantomData<MODE>,
69}
70
71/// Push pull output (type state)
72pub struct PushPull;
73
74use embedded_hal::digital::v2::{toggleable, InputPin, OutputPin, StatefulOutputPin};
75
76/// Fully erased pin
77pub struct Pin<MODE> {
78    i: u8,
79    port: *const dyn GpioRegExt,
80    _mode: PhantomData<MODE>,
81}
82
83// NOTE(unsafe) The only write acess is to BSRR, which is thread safe
84unsafe impl<MODE> Sync for Pin<MODE> {}
85// NOTE(unsafe) this only enables read access to the same pin from multiple
86// threads
87unsafe impl<MODE> Send for Pin<MODE> {}
88
89impl<MODE> StatefulOutputPin for Pin<Output<MODE>> {
90    #[inline(always)]
91    fn is_set_high(&self) -> Result<bool, Self::Error> {
92        self.is_set_low().map(|v| !v)
93    }
94
95    #[inline(always)]
96    fn is_set_low(&self) -> Result<bool, Self::Error> {
97        Ok(unsafe { (*self.port).is_set_low(self.i) })
98    }
99}
100
101impl<MODE> OutputPin for Pin<Output<MODE>> {
102    type Error = Infallible;
103
104    #[inline(always)]
105    fn set_high(&mut self) -> Result<(), Self::Error> {
106        unsafe { (*self.port).set_high(self.i) };
107        Ok(())
108    }
109
110    #[inline(always)]
111    fn set_low(&mut self) -> Result<(), Self::Error> {
112        unsafe { (*self.port).set_low(self.i) }
113        Ok(())
114    }
115}
116
117impl<MODE> toggleable::Default for Pin<Output<MODE>> {}
118
119impl InputPin for Pin<Output<OpenDrain>> {
120    type Error = Infallible;
121
122    #[inline(always)]
123    fn is_high(&self) -> Result<bool, Self::Error> {
124        self.is_low().map(|v| !v)
125    }
126
127    #[inline(always)]
128    fn is_low(&self) -> Result<bool, Self::Error> {
129        Ok(unsafe { (*self.port).is_low(self.i) })
130    }
131}
132
133impl<MODE> InputPin for Pin<Input<MODE>> {
134    type Error = Infallible;
135
136    #[inline(always)]
137    fn is_high(&self) -> Result<bool, Self::Error> {
138        self.is_low().map(|v| !v)
139    }
140
141    #[inline(always)]
142    fn is_low(&self) -> Result<bool, Self::Error> {
143        Ok(unsafe { (*self.port).is_low(self.i) })
144    }
145}
146
147macro_rules! gpio_trait {
148    ($gpiox:ident) => {
149        impl GpioRegExt for crate::pac::$gpiox::RegisterBlock {
150            fn is_low(&self, pos: u8) -> bool {
151                // NOTE(unsafe) atomic read with no side effects
152                self.idr.read().bits() & (1 << pos) == 0
153            }
154
155            fn is_set_low(&self, pos: u8) -> bool {
156                // NOTE(unsafe) atomic read with no side effects
157                self.odr.read().bits() & (1 << pos) == 0
158            }
159
160            fn set_high(&self, pos: u8) {
161                // NOTE(unsafe) atomic write to a stateless register
162                unsafe { self.bsrr.write(|w| w.bits(1 << pos)) }
163            }
164
165            fn set_low(&self, pos: u8) {
166                // NOTE(unsafe) atomic write to a stateless register
167                unsafe { self.bsrr.write(|w| w.bits(1 << (pos + 16))) }
168            }
169        }
170    };
171}
172
173gpio_trait!(gpioa);
174gpio_trait!(gpiof);
175
176macro_rules! gpio {
177    ([$($GPIOX:ident, $gpiox:ident, $iopxenr:ident, $PXx:ident, $gate:meta => [
178        $($PXi:ident: ($pxi:ident, $i:expr, $MODE:ty),)+
179    ]),+]) => {
180        $(
181            /// GPIO
182             #[cfg($gate)]
183            pub mod $gpiox {
184                use core::marker::PhantomData;
185                use core::convert::Infallible;
186
187                use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, toggleable};
188                use crate::{
189                    rcc::Rcc,
190                    pac::$GPIOX
191                };
192
193                use cortex_m::interrupt::CriticalSection;
194
195                use super::{
196                    Alternate, Analog, Floating, GpioExt, Input, OpenDrain, Output,
197                    PullDown, PullUp, PushPull, AF0, AF1, AF2, AF3, AF4, AF5, AF6, AF7,
198                    Pin, GpioRegExt,
199                };
200
201                /// GPIO parts
202                pub struct Parts {
203                    $(
204                        /// Pin
205                        pub $pxi: $PXi<$MODE>,
206                    )+
207                }
208
209                impl GpioExt for $GPIOX {
210                    type Parts = Parts;
211
212                    fn split(self, rcc: &mut Rcc) -> Parts {
213                        rcc.regs.ahbenr.modify(|_, w| w.$iopxenr().set_bit());
214
215                        Parts {
216                            $(
217                                $pxi: $PXi { _mode: PhantomData },
218                            )+
219                        }
220                    }
221                }
222
223                fn _set_alternate_mode (index:usize, mode: u32)
224                {
225                    let offset = 2 * index;
226                    let offset2 = 4 * index;
227                    unsafe {
228                        let reg = &(*$GPIOX::ptr());
229                        if offset2 < 32 {
230                            reg.afrl.modify(|r, w| {
231                                w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2))
232                            });
233                        } else {
234                            let offset2 = offset2 - 32;
235                            reg.afrh.modify(|r, w| {
236                                w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2))
237                            });
238                        }
239                        reg.moder.modify(|r, w| {
240                            w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))
241                        });
242                    }
243                }
244
245                $(
246                    /// Pin
247                    pub struct $PXi<MODE> {
248                        _mode: PhantomData<MODE>,
249                    }
250
251                    impl<MODE> $PXi<MODE> {
252                        /// Configures the pin to operate in AF0 mode
253                        pub fn into_alternate_af0(
254                            self, _cs: &CriticalSection
255                        ) -> $PXi<Alternate<AF0>> {
256                            _set_alternate_mode($i, 0);
257                            $PXi { _mode: PhantomData }
258                        }
259
260                        /// Configures the pin to operate in AF1 mode
261                        pub fn into_alternate_af1(
262                            self, _cs: &CriticalSection
263                        ) -> $PXi<Alternate<AF1>> {
264                            _set_alternate_mode($i, 1);
265                            $PXi { _mode: PhantomData }
266                        }
267
268                        /// Configures the pin to operate in AF2 mode
269                        pub fn into_alternate_af2(
270                            self, _cs: &CriticalSection
271                        ) -> $PXi<Alternate<AF2>> {
272                            _set_alternate_mode($i, 2);
273                            $PXi { _mode: PhantomData }
274                        }
275
276                        /// Configures the pin to operate in AF3 mode
277                        pub fn into_alternate_af3(
278                            self, _cs: &CriticalSection
279                        ) -> $PXi<Alternate<AF3>> {
280                            _set_alternate_mode($i, 3);
281                            $PXi { _mode: PhantomData }
282                        }
283
284                        /// Configures the pin to operate in AF4 mode
285                        pub fn into_alternate_af4(
286                            self, _cs: &CriticalSection
287                        ) -> $PXi<Alternate<AF4>> {
288                            _set_alternate_mode($i, 4);
289                            $PXi { _mode: PhantomData }
290                        }
291
292                        /// Configures the pin to operate in AF5 mode
293                        pub fn into_alternate_af5(
294                            self, _cs: &CriticalSection
295                        ) -> $PXi<Alternate<AF5>> {
296                            _set_alternate_mode($i, 5);
297                            $PXi { _mode: PhantomData }
298                        }
299
300                        /// Configures the pin to operate in AF6 mode
301                        pub fn into_alternate_af6(
302                            self, _cs: &CriticalSection
303                        ) -> $PXi<Alternate<AF6>> {
304                            _set_alternate_mode($i, 6);
305                            $PXi { _mode: PhantomData }
306                        }
307
308                        /// Configures the pin to operate in AF7 mode
309                        pub fn into_alternate_af7(
310                            self, _cs: &CriticalSection
311                        ) -> $PXi<Alternate<AF7>> {
312                            _set_alternate_mode($i, 7);
313                            $PXi { _mode: PhantomData }
314                        }
315
316                        /// Configures the pin to operate as a floating input pin
317                        pub fn into_floating_input(
318                            self, _cs: &CriticalSection
319                        ) -> $PXi<Input<Floating>> {
320                            let offset = 2 * $i;
321                            unsafe {
322                                let reg = &(*$GPIOX::ptr());
323                                reg.pupdr.modify(|r, w| {
324                                    w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
325                                });
326                                reg.moder.modify(|r, w| {
327                                    w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
328                                });
329                            }
330                            $PXi { _mode: PhantomData }
331                        }
332
333                        /// Configures the pin to operate as a pulled down input pin
334                        pub fn into_pull_down_input(
335                            self, _cs: &CriticalSection
336                            ) -> $PXi<Input<PullDown>> {
337                            let offset = 2 * $i;
338                            unsafe {
339                                let reg = &(*$GPIOX::ptr());
340                                reg.pupdr.modify(|r, w| {
341                                    w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))
342                                });
343                                reg.moder.modify(|r, w| {
344                                    w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
345                                });
346                            }
347                            $PXi { _mode: PhantomData }
348                        }
349
350                        /// Configures the pin to operate as a pulled up input pin
351                        pub fn into_pull_up_input(
352                            self, _cs: &CriticalSection
353                        ) -> $PXi<Input<PullUp>> {
354                            let offset = 2 * $i;
355                            unsafe {
356                                let reg = &(*$GPIOX::ptr());
357                                reg.pupdr.modify(|r, w| {
358                                    w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))
359                                });
360                                reg.moder.modify(|r, w| {
361                                    w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
362                                });
363                            }
364                            $PXi { _mode: PhantomData }
365                        }
366
367                        /// Configures the pin to operate as an analog pin
368                        pub fn into_analog(
369                            self, _cs: &CriticalSection
370                        ) -> $PXi<Analog> {
371                            let offset = 2 * $i;
372                            unsafe {
373                                let reg = &(*$GPIOX::ptr());
374                                reg.pupdr.modify(|r, w| {
375                                    w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
376                                });
377                                reg.moder.modify(|r, w| {
378                                    w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))
379                                });
380                            }
381                            $PXi { _mode: PhantomData }
382                        }
383
384                        /// Configures the pin to operate as an open drain output pin
385                        pub fn into_open_drain_output(
386                            self, _cs: &CriticalSection
387                        ) -> $PXi<Output<OpenDrain>> {
388                            let offset = 2 * $i;
389                            unsafe {
390                                let reg = &(*$GPIOX::ptr());
391                                reg.pupdr.modify(|r, w| {
392                                    w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
393                                });
394                                reg.otyper.modify(|r, w| {
395                                    w.bits(r.bits() | (0b1 << $i))
396                                });
397                                reg.moder.modify(|r, w| {
398                                    w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))
399                                });
400                            }
401                            $PXi { _mode: PhantomData }
402                        }
403
404                        /// Configures the pin to operate as an push pull output pin
405                        pub fn into_push_pull_output(
406                            self, _cs: &CriticalSection
407                        ) -> $PXi<Output<PushPull>> {
408                            let offset = 2 * $i;
409                            unsafe {
410                                let reg = &(*$GPIOX::ptr());
411                                reg.pupdr.modify(|r, w| {
412                                    w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
413                                });
414                                reg.otyper.modify(|r, w| {
415                                    w.bits(r.bits() & !(0b1 << $i))
416                                });
417                                reg.moder.modify(|r, w| {
418                                    w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))
419                                });
420                            }
421                            $PXi { _mode: PhantomData }
422                        }
423
424                        /// Configures the pin to operate as an push pull output pin with quick fall
425                        /// and rise times
426                        pub fn into_push_pull_output_hs(
427                            self, _cs: &CriticalSection
428                        ) -> $PXi<Output<PushPull>> {
429                            let offset = 2 * $i;
430                            unsafe {
431                                let reg = &(*$GPIOX::ptr());
432                                reg.pupdr.modify(|r, w| {
433                                    w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
434                                });
435                                reg.otyper.modify(|r, w| {
436                                    w.bits(r.bits() & !(0b1 << $i))
437                                });
438                                reg.ospeedr.modify(|r, w| {
439                                    w.bits(r.bits() & !(0b1 << $i))
440                                });
441                                reg.moder.modify(|r, w| {
442                                    w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))
443                                });
444                            }
445                            $PXi { _mode: PhantomData }
446                        }
447                    }
448
449                    impl $PXi<Output<OpenDrain>> {
450                        /// Enables / disables the internal pull up
451                        pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) {
452                            let offset = 2 * $i;
453                            let value = if on { 0b01 } else { 0b00 };
454                            unsafe {
455                                let reg = &(*$GPIOX::ptr());
456                                reg.pupdr.modify(|r, w| {
457                                    w.bits((r.bits() & !(0b11 << offset)) | (value << offset))
458                                });
459                            }
460                        }
461                    }
462
463                    impl<AF> $PXi<Alternate<AF>> {
464                        /// Enables / disables the internal pull up
465                        pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self {
466                            let offset = 2 * $i;
467                            let value = if on { 0b01 } else { 0b00 };
468                            unsafe {
469                                let reg = &(*$GPIOX::ptr());
470                                reg.pupdr.modify(|r, w| {
471                                    w.bits((r.bits() & !(0b11 << offset)) | (value << offset))
472                                });
473                            }
474                            self
475                        }
476                    }
477
478                    impl<AF> $PXi<Alternate<AF>> {
479                        /// Turns pin alternate configuration pin into open drain
480                        pub fn set_open_drain(self, _cs: &CriticalSection) -> Self {
481                            let offset = $i;
482                            unsafe {
483                                let reg = &(*$GPIOX::ptr());
484                                reg.otyper.modify(|r, w| {
485                                    w.bits(r.bits() | (1 << offset))
486                                });
487                            }
488                            self
489                        }
490                    }
491
492                    impl<MODE> $PXi<Output<MODE>> {
493                        /// Erases the pin number from the type
494                        ///
495                        /// This is useful when you want to collect the pins into an array where you
496                        /// need all the elements to have the same type
497                        pub fn downgrade(self) -> Pin<Output<MODE>> {
498                            Pin {
499                                i: $i,
500                                port: $GPIOX::ptr() as *const dyn GpioRegExt,
501                                _mode: self._mode,
502                            }
503                        }
504                    }
505
506                    impl<MODE> StatefulOutputPin for $PXi<Output<MODE>> {
507                        fn is_set_high(&self) -> Result<bool, Self::Error> {
508                            self.is_set_low().map(|v| !v)
509                        }
510
511                        fn is_set_low(&self) -> Result<bool, Self::Error> {
512                            Ok(unsafe { (*$GPIOX::ptr()).is_set_low($i) })
513                        }
514                    }
515
516                    impl<MODE> OutputPin for $PXi<Output<MODE>> {
517                        type Error = Infallible;
518
519                        fn set_high(&mut self) -> Result<(), Self::Error> {
520                            Ok(unsafe { (*$GPIOX::ptr()).set_high($i) })
521                        }
522
523                        fn set_low(&mut self) -> Result<(), Self::Error> {
524                            Ok(unsafe { (*$GPIOX::ptr()).set_low($i) })
525                        }
526                    }
527
528                    impl<MODE> toggleable::Default for $PXi<Output<MODE>> {}
529
530                    impl InputPin for $PXi<Output<OpenDrain>> {
531                        type Error = Infallible;
532
533                        fn is_high(&self) -> Result<bool, Self::Error> {
534                            self.is_low().map(|v| !v)
535                        }
536
537                        fn is_low(&self) -> Result<bool, Self::Error> {
538                            Ok(unsafe { (*$GPIOX::ptr()).is_low($i) })
539                        }
540                    }
541
542                    impl<MODE> $PXi<Input<MODE>> {
543                        /// Erases the pin number from the type
544                        ///
545                        /// This is useful when you want to collect the pins into an array where you
546                        /// need all the elements to have the same type
547                        pub fn downgrade(self) -> Pin<Input<MODE>> {
548                            Pin {
549                                i: $i,
550                                port: $GPIOX::ptr() as *const dyn GpioRegExt,
551                                _mode: self._mode,
552                            }
553                        }
554                    }
555
556                    impl<MODE> InputPin for $PXi<Input<MODE>> {
557                        type Error = Infallible;
558
559                        fn is_high(&self) -> Result<bool, Self::Error> {
560                            self.is_low().map(|v| !v)
561                        }
562
563                        fn is_low(&self) -> Result<bool, Self::Error> {
564                            Ok(unsafe { (*$GPIOX::ptr()).is_low($i) })
565                        }
566                    }
567                )+
568            }
569        )+
570    }
571}
572
573gpio!([
574    GPIOA, gpioa, iopaen, PA, any(
575        feature = "device-selected"
576    ) => [
577        PA0: (pa0, 0, Input<Floating>),
578        PA1: (pa1, 1, Input<Floating>),
579        PA2: (pa2, 2, Input<Floating>),
580        PA3: (pa3, 3, Input<Floating>),
581        PA4: (pa4, 4, Input<Floating>),
582        PA5: (pa5, 5, Input<Floating>),
583        PA6: (pa6, 6, Input<Floating>),
584        PA7: (pa7, 7, Input<Floating>),
585        PA8: (pa8, 8, Input<Floating>),
586        PA9: (pa9, 9, Input<Floating>),
587        PA10: (pa10, 10, Input<Floating>),
588        PA11: (pa11, 11, Input<Floating>),
589        PA12: (pa12, 12, Input<Floating>),
590        PA13: (pa13, 13, Input<Floating>),
591        PA14: (pa14, 14, Input<Floating>),
592        PA15: (pa15, 15, Input<Floating>),
593    ],
594    GPIOB, gpiob, iopben, PB, any(
595        feature = "device-selected"
596    ) => [
597        PB0: (pb0, 0, Input<Floating>),
598        PB1: (pb1, 1, Input<Floating>),
599        PB2: (pb2, 2, Input<Floating>),
600        PB3: (pb3, 3, Input<Floating>),
601        PB4: (pb4, 4, Input<Floating>),
602        PB5: (pb5, 5, Input<Floating>),
603        PB6: (pb6, 6, Input<Floating>),
604        PB7: (pb7, 7, Input<Floating>),
605        PB8: (pb8, 8, Input<Floating>),
606        PB9: (pb9, 9, Input<Floating>),
607        PB10: (pb10, 10, Input<Floating>),
608        PB11: (pb11, 11, Input<Floating>),
609        PB12: (pb12, 12, Input<Floating>),
610        PB13: (pb13, 13, Input<Floating>),
611        PB14: (pb14, 14, Input<Floating>),
612        PB15: (pb15, 15, Input<Floating>),
613    ],
614    GPIOC, gpioc, iopcen, PC, any(
615        feature = "stm32f031",
616        feature = "stm32f038",
617        feature = "stm32f042",
618        feature = "stm32f048"
619    ) => [
620        PC13: (pc13, 13, Input<Floating>),
621        PC14: (pc14, 14, Input<Floating>),
622        PC15: (pc15, 15, Input<Floating>),
623    ],
624    GPIOC, gpioc, iopcen, PC, any(
625        feature = "stm32f030",
626        feature = "stm32f051",
627        feature = "stm32f058",
628        feature = "stm32f070",
629        feature = "stm32f071",
630        feature = "stm32f072",
631        feature = "stm32f078",
632        feature = "stm32f091",
633        feature = "stm32f098"
634    ) => [
635        PC0: (pc0, 0, Input<Floating>),
636        PC1: (pc1, 1, Input<Floating>),
637        PC2: (pc2, 2, Input<Floating>),
638        PC3: (pc3, 3, Input<Floating>),
639        PC4: (pc4, 4, Input<Floating>),
640        PC5: (pc5, 5, Input<Floating>),
641        PC6: (pc6, 6, Input<Floating>),
642        PC7: (pc7, 7, Input<Floating>),
643        PC8: (pc8, 8, Input<Floating>),
644        PC9: (pc9, 9, Input<Floating>),
645        PC10: (pc10, 10, Input<Floating>),
646        PC11: (pc11, 11, Input<Floating>),
647        PC12: (pc12, 12, Input<Floating>),
648        PC13: (pc13, 13, Input<Floating>),
649        PC14: (pc14, 14, Input<Floating>),
650        PC15: (pc15, 15, Input<Floating>),
651    ],
652    GPIOD, gpiod, iopden, PD, any(
653        feature = "stm32f030",
654        feature = "stm32f051",
655        feature = "stm32f058",
656        feature = "stm32f070"
657    ) => [
658        PD2: (pd2, 2, Input<Floating>),
659    ],
660    GPIOD, gpiod, iopden, PD, any(
661        feature = "stm32f071",
662        feature = "stm32f072",
663        feature = "stm32f078",
664        feature = "stm32f091",
665        feature = "stm32f098"
666    ) => [
667        PD0: (pd0, 0, Input<Floating>),
668        PD1: (pd1, 1, Input<Floating>),
669        PD2: (pd2, 2, Input<Floating>),
670        PD3: (pd3, 3, Input<Floating>),
671        PD4: (pd4, 4, Input<Floating>),
672        PD5: (pd5, 5, Input<Floating>),
673        PD6: (pd6, 6, Input<Floating>),
674        PD7: (pd7, 7, Input<Floating>),
675        PD8: (pd8, 8, Input<Floating>),
676        PD9: (pd9, 9, Input<Floating>),
677        PD10: (pd10, 10, Input<Floating>),
678        PD11: (pd11, 11, Input<Floating>),
679        PD12: (pd12, 12, Input<Floating>),
680        PD13: (pd13, 13, Input<Floating>),
681        PD14: (pd14, 14, Input<Floating>),
682        PD15: (pd15, 15, Input<Floating>),
683    ],
684    GPIOE, gpioe, iopeen, PE, any(
685        feature = "stm32f071",
686        feature = "stm32f072",
687        feature = "stm32f078",
688        feature = "stm32f091",
689        feature = "stm32f098"
690    ) => [
691        PE0: (pe0, 0, Input<Floating>),
692        PE1: (pe1, 1, Input<Floating>),
693        PE2: (pe2, 2, Input<Floating>),
694        PE3: (pe3, 3, Input<Floating>),
695        PE4: (pe4, 4, Input<Floating>),
696        PE5: (pe5, 5, Input<Floating>),
697        PE6: (pe6, 6, Input<Floating>),
698        PE7: (pe7, 7, Input<Floating>),
699        PE8: (pe8, 8, Input<Floating>),
700        PE9: (pe9, 9, Input<Floating>),
701        PE10: (pe10, 10, Input<Floating>),
702        PE11: (pe11, 11, Input<Floating>),
703        PE12: (pe12, 12, Input<Floating>),
704        PE13: (pe13, 13, Input<Floating>),
705        PE14: (pe14, 14, Input<Floating>),
706        PE15: (pe15, 15, Input<Floating>),
707    ],
708    GPIOF, gpiof, iopfen, PF, any(
709        feature = "stm32f030x4",
710        feature = "stm32f030x6",
711        feature = "stm32f030x8",
712        feature = "stm32f051",
713        feature = "stm32f058",
714    ) => [
715        PF0: (pf0, 0, Input<Floating>),
716        PF1: (pf1, 1, Input<Floating>),
717        PF4: (pf4, 4, Input<Floating>),
718        PF5: (pf5, 5, Input<Floating>),
719        PF6: (pf6, 6, Input<Floating>),
720        PF7: (pf7, 7, Input<Floating>),
721    ],
722    GPIOF, gpiof, iopfen, PF, any(
723        feature = "stm32f030xc",
724        feature = "stm32f070"
725    ) => [
726        PF0: (pf0, 0, Input<Floating>),
727        PF1: (pf1, 1, Input<Floating>),
728    ],
729    GPIOF, gpiof, iopfen, PF, any(
730        feature = "stm32f031",
731        feature = "stm32f038"
732    ) => [
733        PF0: (pf0, 0, Input<Floating>),
734        PF1: (pf1, 1, Input<Floating>),
735        PF6: (pf6, 6, Input<Floating>),
736        PF7: (pf7, 7, Input<Floating>),
737    ],
738    GPIOF, gpiof, iopfen, PF, any(
739        feature = "stm32f042",
740        feature = "stm32f048"
741    ) => [
742        PF0: (pf0, 0, Input<Floating>),
743        PF1: (pf1, 1, Input<Floating>),
744        PF11: (pf11, 11, Input<Floating>),
745    ],
746    GPIOF, gpiof, iopfen, PF, any(
747        feature = "stm32f071",
748        feature = "stm32f072",
749        feature = "stm32f078",
750        feature = "stm32f091",
751        feature = "stm32f098",
752    ) => [
753        PF0: (pf0, 0, Input<Floating>),
754        PF1: (pf1, 1, Input<Floating>),
755        PF2: (pf2, 2, Input<Floating>),
756        PF3: (pf3, 3, Input<Floating>),
757        PF6: (pf6, 6, Input<Floating>),
758        PF9: (pf9, 9, Input<Floating>),
759        PF10: (pf10, 10, Input<Floating>),
760    ]
761    ]);