1use core::marker::PhantomData;
77
78use crate::afio;
79use crate::pac::{EXTI, RCC};
80
81mod partially_erased;
82pub use partially_erased::{PEPin, PartiallyErasedPin};
83mod erased;
84pub use erased::{AnyPin, ErasedPin};
85
86mod impl_hal;
87
88pub enum IOPinSpeed {
92 Mhz10 = 0b01, Mhz2 = 0b10,
96 Mhz50 = 0b11,
98}
99
100impl From<IOPinSpeed> for Mode {
101 fn from(value: IOPinSpeed) -> Self {
102 match value {
103 IOPinSpeed::Mhz10 => Self::Output,
104 IOPinSpeed::Mhz2 => Self::Output2,
105 IOPinSpeed::Mhz50 => Self::Output50,
106 }
107 }
108}
109
110pub trait PinExt {
111 type Mode;
112
113 fn pin_id(&self) -> u8;
115
116 fn port_id(&self) -> u8;
118}
119
120pub trait OutputSpeed: HL {
124 fn set_speed(&mut self, cr: &mut Self::Cr, speed: IOPinSpeed);
125}
126
127pub trait GpioExt {
129 type Parts;
131
132 fn split(self, rcc: &mut RCC) -> Self::Parts;
136
137 unsafe fn split_without_reset(self, rcc: &mut RCC) -> Self::Parts;
142}
143
144pub trait Active {}
146
147pub trait UpMode {}
149impl UpMode for Floating {}
150impl UpMode for PullUp {}
151
152#[derive(Default)]
154pub struct Input<PULL = Floating>(PhantomData<PULL>);
155
156impl<PULL> Active for Input<PULL> {}
157
158#[derive(Default)]
160pub struct Debugger;
161
162#[derive(Default)]
164pub struct Floating;
165
166#[derive(Default)]
168pub struct PullDown;
169
170#[derive(Default)]
172pub struct PullUp;
173
174#[derive(Default)]
176pub struct Output<Otype = PushPull>(PhantomData<Otype>);
177
178impl<MODE> Active for Output<MODE> {}
179
180#[derive(Default)]
182pub struct PushPull;
183
184#[derive(Default)]
186pub struct OpenDrain;
187
188#[derive(Default)]
190pub struct Analog;
191
192impl Active for Analog {}
193
194#[derive(Default)]
196pub struct Alternate<Otype = PushPull>(PhantomData<Otype>);
197
198impl<MODE> Active for Alternate<MODE> {}
199
200pub use embedded_hal::digital::PinState;
202
203#[allow(non_camel_case_types)]
206#[derive(Debug, PartialEq, Eq, Clone, Copy)]
207pub enum Edge {
208 Rising,
209 Falling,
210 RisingFalling,
211}
212
213mod sealed {
214 pub trait Interruptable {}
216
217 pub trait PinMode: Default {
218 const CNF: super::Cnf;
219 const MODE: super::Mode;
220 const PULL: Option<bool> = None;
221 }
222}
223
224use crate::pac::gpioa::crl::{CONFIG as Cnf, MODE as Mode};
225
226use sealed::Interruptable;
227pub(crate) use sealed::PinMode;
228
229impl<MODE> Interruptable for Input<MODE> {}
230impl Interruptable for Dynamic {}
231
232pub trait ExtiPin {
234 fn make_interrupt_source(&mut self, afio: &mut afio::Afio);
235 fn trigger_on_edge(&mut self, exti: &mut EXTI, level: Edge);
236 fn enable_interrupt(&mut self, exti: &mut EXTI);
237 fn disable_interrupt(&mut self, exti: &mut EXTI);
238 fn clear_interrupt_pending_bit(&mut self);
239 fn check_interrupt(&self) -> bool;
240}
241
242impl<PIN> ExtiPin for PIN
243where
244 PIN: PinExt,
245 PIN::Mode: Interruptable,
246{
247 fn make_interrupt_source(&mut self, afio: &mut afio::Afio) {
249 let pin_number = self.pin_id();
250 let port = self.port_id() as u32;
251 let offset = 4 * (pin_number % 4);
252 match pin_number {
253 0..=3 => {
254 afio.exticr1.exticr1().modify(|r, w| unsafe {
255 w.bits((r.bits() & !(0xf << offset)) | (port << offset))
256 });
257 }
258 4..=7 => {
259 afio.exticr2.exticr2().modify(|r, w| unsafe {
260 w.bits((r.bits() & !(0xf << offset)) | (port << offset))
261 });
262 }
263 8..=11 => {
264 afio.exticr3.exticr3().modify(|r, w| unsafe {
265 w.bits((r.bits() & !(0xf << offset)) | (port << offset))
266 });
267 }
268 12..=15 => {
269 afio.exticr4.exticr4().modify(|r, w| unsafe {
270 w.bits((r.bits() & !(0xf << offset)) | (port << offset))
271 });
272 }
273 _ => unreachable!(),
274 }
275 }
276
277 fn trigger_on_edge(&mut self, exti: &mut EXTI, edge: Edge) {
279 let pin_number = self.pin_id();
280 match edge {
281 Edge::Rising => {
282 exti.rtsr()
283 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << pin_number)) });
284 exti.ftsr()
285 .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << pin_number)) });
286 }
287 Edge::Falling => {
288 exti.rtsr()
289 .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << pin_number)) });
290 exti.ftsr()
291 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << pin_number)) });
292 }
293 Edge::RisingFalling => {
294 exti.rtsr()
295 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << pin_number)) });
296 exti.ftsr()
297 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << pin_number)) });
298 }
299 }
300 }
301
302 fn enable_interrupt(&mut self, exti: &mut EXTI) {
304 exti.imr()
305 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.pin_id())) });
306 }
307
308 fn disable_interrupt(&mut self, exti: &mut EXTI) {
310 exti.imr()
311 .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.pin_id())) });
312 }
313
314 fn clear_interrupt_pending_bit(&mut self) {
316 unsafe { (*EXTI::ptr()).pr().write(|w| w.bits(1 << self.pin_id())) };
317 }
318
319 fn check_interrupt(&self) -> bool {
321 unsafe { ((*EXTI::ptr()).pr().read().bits() & (1 << self.pin_id())) != 0 }
322 }
323}
324
325pub enum Dynamic {
327 InputFloating,
328 InputPullUp,
329 InputPullDown,
330 OutputPushPull,
331 OutputOpenDrain,
332}
333
334impl Default for Dynamic {
335 fn default() -> Self {
336 Dynamic::InputFloating
337 }
338}
339
340impl Active for Dynamic {}
341
342#[derive(Debug, PartialEq, Eq)]
343pub enum PinModeError {
344 IncorrectMode,
345}
346
347impl Dynamic {
348 fn is_input(&self) -> bool {
349 use Dynamic::*;
350 match self {
351 InputFloating | InputPullUp | InputPullDown | OutputOpenDrain => true,
352 OutputPushPull => false,
353 }
354 }
355
356 fn is_output(&self) -> bool {
357 use Dynamic::*;
358 match self {
359 InputFloating | InputPullUp | InputPullDown => false,
360 OutputPushPull | OutputOpenDrain => true,
361 }
362 }
363}
364
365macro_rules! gpio {
366 ($GPIOX:ident, $gpiox:ident, $PXx:ident, $port_id:expr, [
367 $($PXi:ident: ($pxi:ident, $pin_number:expr $(, $MODE:ty)?),)+
368 ]) => {
369 pub mod $gpiox {
371 use crate::pac::{$GPIOX, RCC};
372 use crate::rcc::{Enable, Reset};
373 use super::{Active, Floating, GpioExt, Input, PartiallyErasedPin, ErasedPin, Pin, Cr};
374 #[allow(unused)]
375 use super::Debugger;
376
377 pub struct Parts {
379 pub crl: Cr<$port_id, false>,
381 pub crh: Cr<$port_id, true>,
383 $(
384 pub $pxi: $PXi $(<$MODE>)?,
386 )+
387 }
388
389 $(
390 pub type $PXi<MODE = Input<Floating>> = Pin<$port_id, $pin_number, MODE>;
391 )+
392
393 impl GpioExt for $GPIOX {
394 type Parts = Parts;
395
396 fn split(self, rcc: &mut RCC) -> Parts {
397 $GPIOX::enable(rcc);
398 $GPIOX::reset(rcc);
399
400 Parts {
401 crl: Cr::<$port_id, false>,
402 crh: Cr::<$port_id, true>,
403 $(
404 $pxi: $PXi::new(),
405 )+
406 }
407 }
408
409 unsafe fn split_without_reset(self, rcc: &mut RCC) -> Parts {
410 $GPIOX::enable(rcc);
411
412 Parts {
413 crl: Cr::<$port_id, false>,
414 crh: Cr::<$port_id, true>,
415 $(
416 $pxi: $PXi::new(),
417 )+
418 }
419 }
420 }
421
422 impl<MODE> PartiallyErasedPin<$port_id, MODE> {
423 pub fn erase(self) -> ErasedPin<MODE> {
424 ErasedPin::$PXx(self)
425 }
426 }
427
428 impl<const N: u8, MODE> Pin<$port_id, N, MODE>
429 where
430 MODE: Active,
431 {
432 pub fn erase(self) -> ErasedPin<MODE> {
437 self.erase_number().erase()
438 }
439 }
440 }
441
442 pub use $gpiox::{ $($PXi,)+ };
443 }
444}
445
446pub struct Pin<const P: char, const N: u8, MODE = Input<Floating>> {
452 mode: MODE,
453}
454
455pub trait HL {
457 type Cr;
459}
460
461macro_rules! cr {
462 ($cr_is_h:literal: [$($pin_number:literal),+]) => {
463 $(
464 impl<const P: char, MODE> HL for Pin<P, $pin_number, MODE> {
465 type Cr = Cr<P, $cr_is_h>;
466 }
467 )+
468 }
469}
470
471cr!(false: [0, 1, 2, 3, 4, 5, 6, 7]);
472cr!(true: [8, 9, 10, 11, 12, 13, 14, 15]);
473
474impl<const P: char, const N: u8, MODE: Default> Pin<P, N, MODE> {
475 fn new() -> Self {
476 Self {
477 mode: Default::default(),
478 }
479 }
480}
481
482impl<const P: char, const N: u8, MODE> PinExt for Pin<P, N, MODE> {
483 type Mode = MODE;
484
485 #[inline(always)]
486 fn pin_id(&self) -> u8 {
487 N
488 }
489
490 #[inline(always)]
491 fn port_id(&self) -> u8 {
492 P as u8 - b'A'
493 }
494}
495
496impl<const P: char, const N: u8> Pin<P, N, Debugger> {
497 #[allow(dead_code)]
501 pub(crate) unsafe fn activate(self) -> Pin<P, N, Input<Floating>> {
502 Pin::new()
503 }
504}
505
506impl<const P: char, const N: u8, MODE> Pin<P, N, MODE> {
512 #[inline(always)]
519 fn _set_state(&mut self, state: PinState) {
520 match state {
521 PinState::High => self._set_high(),
522 PinState::Low => self._set_low(),
523 }
524 }
525
526 #[inline(always)]
527 fn _set_high(&mut self) {
528 let gpio = unsafe { &(*gpiox::<P>()) };
530 gpio.bsrr().write(|w| w.bs(N).set_bit());
531 }
532
533 #[inline(always)]
534 fn _set_low(&mut self) {
535 let gpio = unsafe { &(*gpiox::<P>()) };
537 gpio.bsrr().write(|w| w.br(N).set_bit());
538 }
539
540 #[inline(always)]
541 fn _is_set_low(&self) -> bool {
542 let gpio = unsafe { &(*gpiox::<P>()) };
544 gpio.odr().read().odr(N).bit_is_clear()
545 }
546
547 #[inline(always)]
548 fn _is_low(&self) -> bool {
549 let gpio = unsafe { &(*gpiox::<P>()) };
551 gpio.idr().read().idr(N).bit_is_clear()
552 }
553}
554
555impl<const P: char, const N: u8, MODE> Pin<P, N, MODE>
556where
557 MODE: Active,
558{
559 #[inline]
561 pub fn erase_number(self) -> PartiallyErasedPin<P, MODE> {
562 PartiallyErasedPin::new(N)
563 }
564}
565
566impl<const P: char, const N: u8, MODE> Pin<P, N, Output<MODE>> {
567 #[inline]
568 pub fn set_high(&mut self) {
569 self._set_high()
570 }
571
572 #[inline]
573 pub fn set_low(&mut self) {
574 self._set_low()
575 }
576
577 #[inline(always)]
578 pub fn get_state(&self) -> PinState {
579 if self._is_set_low() {
580 PinState::Low
581 } else {
582 PinState::High
583 }
584 }
585
586 #[inline(always)]
587 pub fn set_state(&mut self, state: PinState) {
588 self._set_state(state)
589 }
590
591 #[inline]
592 pub fn is_set_high(&self) -> bool {
593 !self._is_set_low()
594 }
595
596 #[inline]
597 pub fn is_set_low(&self) -> bool {
598 self._is_set_low()
599 }
600
601 #[inline]
602 pub fn toggle(&mut self) {
603 if self._is_set_low() {
604 self._set_high()
605 } else {
606 self._set_low()
607 }
608 }
609}
610
611impl<const P: char, const N: u8, MODE> Pin<P, N, Input<MODE>> {
612 #[inline]
613 pub fn is_high(&self) -> bool {
614 !self._is_low()
615 }
616
617 #[inline]
618 pub fn is_low(&self) -> bool {
619 self._is_low()
620 }
621}
622
623impl<const P: char, const N: u8> Pin<P, N, Output<OpenDrain>> {
624 #[inline]
625 pub fn is_high(&self) -> bool {
626 !self._is_low()
627 }
628
629 #[inline]
630 pub fn is_low(&self) -> bool {
631 self._is_low()
632 }
633}
634
635#[non_exhaustive]
637pub struct Cr<const P: char, const H: bool>;
638
639impl<const P: char, const N: u8, MODE> Pin<P, N, MODE>
640where
641 MODE: Active,
642 Self: HL,
643{
644 #[inline]
647 pub fn into_alternate_push_pull(
648 self,
649 cr: &mut <Self as HL>::Cr,
650 ) -> Pin<P, N, Alternate<PushPull>> {
651 self.into_mode(cr)
652 }
653
654 #[inline]
657 pub fn into_alternate_open_drain(
658 self,
659 cr: &mut <Self as HL>::Cr,
660 ) -> Pin<P, N, Alternate<OpenDrain>> {
661 self.into_mode(cr)
662 }
663
664 #[inline]
666 pub fn into_floating_input(self, cr: &mut <Self as HL>::Cr) -> Pin<P, N, Input<Floating>> {
667 self.into_mode(cr)
668 }
669
670 #[inline]
672 pub fn into_pull_down_input(self, cr: &mut <Self as HL>::Cr) -> Pin<P, N, Input<PullDown>> {
673 self.into_mode(cr)
674 }
675
676 #[inline]
678 pub fn into_pull_up_input(self, cr: &mut <Self as HL>::Cr) -> Pin<P, N, Input<PullUp>> {
679 self.into_mode(cr)
680 }
681
682 #[inline]
685 pub fn into_open_drain_output(self, cr: &mut <Self as HL>::Cr) -> Pin<P, N, Output<OpenDrain>> {
686 self.into_open_drain_output_with_state(cr, PinState::Low)
687 }
688
689 #[inline]
692 pub fn into_open_drain_output_with_state(
693 mut self,
694 cr: &mut <Self as HL>::Cr,
695 initial_state: PinState,
696 ) -> Pin<P, N, Output<OpenDrain>> {
697 self._set_state(initial_state);
698 self.into_mode(cr)
699 }
700
701 #[inline]
704 pub fn into_push_pull_output(self, cr: &mut <Self as HL>::Cr) -> Pin<P, N, Output<PushPull>> {
705 self.into_push_pull_output_with_state(cr, PinState::Low)
706 }
707
708 #[inline]
711 pub fn into_push_pull_output_with_state(
712 mut self,
713 cr: &mut <Self as HL>::Cr,
714 initial_state: PinState,
715 ) -> Pin<P, N, Output<PushPull>> {
716 self._set_state(initial_state);
717 self.into_mode(cr)
718 }
719
720 #[inline]
723 pub fn into_push_pull_output_with_current_state(
724 self,
725 cr: &mut <Self as HL>::Cr,
726 ) -> Pin<P, N, Output<PushPull>> {
727 self.into_mode(cr)
728 }
729
730 #[inline]
732 pub fn into_analog(self, cr: &mut <Self as HL>::Cr) -> Pin<P, N, Analog> {
733 self.into_mode(cr)
734 }
735
736 #[inline]
740 pub fn into_dynamic(mut self, cr: &mut <Self as HL>::Cr) -> Pin<P, N, Dynamic> {
741 self.mode::<Input<Floating>>(cr);
742 Pin::new()
743 }
744}
745
746macro_rules! impl_temp_output {
749 ($fn_name:ident, $stateful_fn_name:ident, $mode:ty) => {
750 #[inline]
755 pub fn $fn_name(
756 &mut self,
757 cr: &mut <Self as HL>::Cr,
758 mut f: impl FnMut(&mut Pin<P, N, $mode>),
759 ) {
760 self.mode::<$mode>(cr);
761 let mut temp = Pin::<P, N, $mode>::new();
762 f(&mut temp);
763 self.mode::<$mode>(cr);
764 Self::new();
765 }
766
767 #[inline]
773 pub fn $stateful_fn_name(
774 &mut self,
775 cr: &mut <Self as HL>::Cr,
776 state: PinState,
777 mut f: impl FnMut(&mut Pin<P, N, $mode>),
778 ) {
779 self._set_state(state);
780 self.mode::<$mode>(cr);
781 let mut temp = Pin::<P, N, $mode>::new();
782 f(&mut temp);
783 self.mode::<$mode>(cr);
784 Self::new();
785 }
786 };
787}
788macro_rules! impl_temp_input {
789 ($fn_name:ident, $mode:ty) => {
790 #[inline]
792 pub fn $fn_name(
793 &mut self,
794 cr: &mut <Self as HL>::Cr,
795 mut f: impl FnMut(&mut Pin<P, N, $mode>),
796 ) {
797 self.mode::<$mode>(cr);
798 let mut temp = Pin::<P, N, $mode>::new();
799 f(&mut temp);
800 self.mode::<$mode>(cr);
801 Self::new();
802 }
803 };
804}
805
806impl<const P: char, const N: u8, MODE> Pin<P, N, MODE>
807where
808 MODE: Active + PinMode,
809 Self: HL,
810{
811 impl_temp_output!(
812 as_push_pull_output,
813 as_push_pull_output_with_state,
814 Output<PushPull>
815 );
816 impl_temp_output!(
817 as_open_drain_output,
818 as_open_drain_output_with_state,
819 Output<OpenDrain>
820 );
821 impl_temp_input!(as_floating_input, Input<Floating>);
822 impl_temp_input!(as_pull_up_input, Input<PullUp>);
823 impl_temp_input!(as_pull_down_input, Input<PullDown>);
824}
825
826impl<const P: char, const N: u8, MODE> Pin<P, N, MODE>
827where
828 Self: HL,
829{
830 #[inline(always)]
831 fn _set_speed(&mut self, _cr: &mut <Self as HL>::Cr, speed: IOPinSpeed) {
832 let gpio = unsafe { &(*gpiox::<P>()) };
833
834 match N {
835 0..=7 => {
836 gpio.crl().modify(|_, w| w.mode(N).variant(speed.into()));
837 }
838 8..=15 => {
839 gpio.crh()
840 .modify(|_, w| unsafe { w.mode(N - 8).bits(speed as u8) });
841 }
842 _ => unreachable!(),
843 }
844 }
845}
846
847impl<const P: char, const N: u8, MODE> OutputSpeed for Pin<P, N, Output<MODE>>
848where
849 Self: HL,
850{
851 fn set_speed(&mut self, cr: &mut <Self as HL>::Cr, speed: IOPinSpeed) {
852 self._set_speed(cr, speed)
853 }
854}
855
856impl<const P: char, const N: u8> OutputSpeed for Pin<P, N, Alternate<PushPull>>
857where
858 Self: HL,
859{
860 fn set_speed(&mut self, cr: &mut <Self as HL>::Cr, speed: IOPinSpeed) {
861 self._set_speed(cr, speed)
862 }
863}
864
865impl<const P: char, const N: u8> Pin<P, N, Dynamic>
868where
869 Self: HL,
870{
871 #[inline]
872 pub fn make_pull_up_input(&mut self, cr: &mut <Self as HL>::Cr) {
873 self.mode::<Input<PullUp>>(cr);
875 self.mode = Dynamic::InputPullUp;
876 }
877
878 #[inline]
879 pub fn make_pull_down_input(&mut self, cr: &mut <Self as HL>::Cr) {
880 self.mode::<Input<PullDown>>(cr);
882 self.mode = Dynamic::InputPullDown;
883 }
884
885 #[inline]
886 pub fn make_floating_input(&mut self, cr: &mut <Self as HL>::Cr) {
887 self.mode::<Input<Floating>>(cr);
889 self.mode = Dynamic::InputFloating;
890 }
891
892 #[inline]
893 pub fn make_push_pull_output(&mut self, cr: &mut <Self as HL>::Cr) {
894 self.mode::<Output<PushPull>>(cr);
896 self.mode = Dynamic::OutputPushPull;
897 }
898
899 #[inline]
900 pub fn make_open_drain_output(&mut self, cr: &mut <Self as HL>::Cr) {
901 self.mode::<Output<OpenDrain>>(cr);
903 self.mode = Dynamic::OutputOpenDrain;
904 }
905}
906
907impl PinMode for Analog {
908 const MODE: Mode = Mode::Input;
909 const CNF: Cnf = Cnf::PushPull;
910}
911
912impl PinMode for Input<Floating> {
913 const MODE: Mode = Mode::Input;
914 const CNF: Cnf = Cnf::OpenDrain;
915}
916
917impl PinMode for Input<PullDown> {
918 const MODE: Mode = Mode::Input;
919 const CNF: Cnf = Cnf::AltPushPull;
920 const PULL: Option<bool> = Some(false);
921}
922
923impl PinMode for Input<PullUp> {
924 const MODE: Mode = Mode::Input;
925 const CNF: Cnf = Cnf::AltPushPull;
926 const PULL: Option<bool> = Some(true);
927}
928
929impl PinMode for Output<PushPull> {
930 const MODE: Mode = Mode::Output50;
931 const CNF: Cnf = Cnf::PushPull;
932}
933
934impl PinMode for Output<OpenDrain> {
935 const MODE: Mode = Mode::Output50;
936 const CNF: Cnf = Cnf::OpenDrain;
937}
938
939impl PinMode for Alternate<PushPull> {
940 const MODE: Mode = Mode::Output50;
941 const CNF: Cnf = Cnf::AltPushPull;
942}
943
944impl PinMode for Alternate<OpenDrain> {
945 const MODE: Mode = Mode::Output50;
946 const CNF: Cnf = Cnf::AltOpenDrain;
947}
948
949impl<const P: char, const N: u8, M> Pin<P, N, M>
950where
951 Self: HL,
952{
953 fn mode<MODE: PinMode>(&mut self, _cr: &mut <Self as HL>::Cr) {
954 let gpio = unsafe { &(*gpiox::<P>()) };
955
956 if let Some(pull) = MODE::PULL {
958 gpio.bsrr().write(|w| {
959 if pull {
960 w.bs(N).set_bit()
961 } else {
962 w.br(N).set_bit()
963 }
964 });
965 }
966
967 match N {
968 0..=7 => {
969 gpio.crl()
970 .modify(|_, w| w.mode(N).variant(MODE::MODE).cnf(N).variant(MODE::CNF));
971 }
972 8..=15 => {
973 gpio.crh().modify(|_, w| unsafe {
974 w.mode(N - 8).bits(MODE::MODE as u8);
975 w.cnf(N - 8).bits(MODE::CNF as u8)
976 });
977 }
978 _ => unreachable!(),
979 }
980 }
981
982 #[inline]
983 pub(crate) fn into_mode<MODE: PinMode>(mut self, cr: &mut <Self as HL>::Cr) -> Pin<P, N, MODE> {
984 self.mode::<MODE>(cr);
985 Pin::new()
986 }
987}
988
989impl Analog {
990 pub fn new<const P: char, const N: u8, MODE>(
991 pin: Pin<P, N, MODE>,
992 cr: &mut <Pin<P, N, MODE> as HL>::Cr,
993 ) -> Pin<P, N, Self>
994 where
995 Pin<P, N, MODE>: HL,
996 Self: PinMode,
997 {
998 pin.into_mode(cr)
999 }
1000}
1001
1002impl<PULL> Input<PULL> {
1003 pub fn new<const P: char, const N: u8, MODE>(
1004 pin: Pin<P, N, MODE>,
1005 cr: &mut <Pin<P, N, MODE> as HL>::Cr,
1006 _pull: PULL,
1007 ) -> Pin<P, N, Self>
1008 where
1009 Pin<P, N, MODE>: HL,
1010 Self: PinMode,
1011 {
1012 pin.into_mode(cr)
1013 }
1014}
1015
1016impl<Otype> Output<Otype> {
1017 pub fn new<const P: char, const N: u8, MODE>(
1018 mut pin: Pin<P, N, MODE>,
1019 cr: &mut <Pin<P, N, MODE> as HL>::Cr,
1020 state: PinState,
1021 ) -> Pin<P, N, Self>
1022 where
1023 Pin<P, N, MODE>: HL,
1024 Self: PinMode,
1025 {
1026 pin._set_state(state);
1027 pin.into_mode(cr)
1028 }
1029}
1030
1031impl<Otype> Alternate<Otype> {
1032 pub fn new<const P: char, const N: u8, MODE>(
1033 pin: Pin<P, N, MODE>,
1034 cr: &mut <Pin<P, N, MODE> as HL>::Cr,
1035 ) -> Pin<P, N, Self>
1036 where
1037 Pin<P, N, MODE>: HL,
1038 Self: PinMode,
1039 {
1040 pin.into_mode(cr)
1041 }
1042}
1043
1044gpio!(GPIOA, gpioa, PAx, 'A', [
1045 PA0: (pa0, 0),
1046 PA1: (pa1, 1),
1047 PA2: (pa2, 2),
1048 PA3: (pa3, 3),
1049 PA4: (pa4, 4),
1050 PA5: (pa5, 5),
1051 PA6: (pa6, 6),
1052 PA7: (pa7, 7),
1053 PA8: (pa8, 8),
1054 PA9: (pa9, 9),
1055 PA10: (pa10, 10),
1056 PA11: (pa11, 11),
1057 PA12: (pa12, 12),
1058 PA13: (pa13, 13, Debugger),
1059 PA14: (pa14, 14, Debugger),
1060 PA15: (pa15, 15, Debugger),
1061]);
1062
1063gpio!(GPIOB, gpiob, PBx, 'B', [
1064 PB0: (pb0, 0),
1065 PB1: (pb1, 1),
1066 PB2: (pb2, 2),
1067 PB3: (pb3, 3, Debugger),
1068 PB4: (pb4, 4, Debugger),
1069 PB5: (pb5, 5),
1070 PB6: (pb6, 6),
1071 PB7: (pb7, 7),
1072 PB8: (pb8, 8),
1073 PB9: (pb9, 9),
1074 PB10: (pb10, 10),
1075 PB11: (pb11, 11),
1076 PB12: (pb12, 12),
1077 PB13: (pb13, 13),
1078 PB14: (pb14, 14),
1079 PB15: (pb15, 15),
1080]);
1081
1082gpio!(GPIOC, gpioc, PCx, 'C', [
1083 PC0: (pc0, 0),
1084 PC1: (pc1, 1),
1085 PC2: (pc2, 2),
1086 PC3: (pc3, 3),
1087 PC4: (pc4, 4),
1088 PC5: (pc5, 5),
1089 PC6: (pc6, 6),
1090 PC7: (pc7, 7),
1091 PC8: (pc8, 8),
1092 PC9: (pc9, 9),
1093 PC10: (pc10, 10),
1094 PC11: (pc11, 11),
1095 PC12: (pc12, 12),
1096 PC13: (pc13, 13),
1097 PC14: (pc14, 14),
1098 PC15: (pc15, 15),
1099]);
1100
1101gpio!(GPIOD, gpiod, PDx, 'D', [
1102 PD0: (pd0, 0),
1103 PD1: (pd1, 1),
1104 PD2: (pd2, 2),
1105 PD3: (pd3, 3),
1106 PD4: (pd4, 4),
1107 PD5: (pd5, 5),
1108 PD6: (pd6, 6),
1109 PD7: (pd7, 7),
1110 PD8: (pd8, 8),
1111 PD9: (pd9, 9),
1112 PD10: (pd10, 10),
1113 PD11: (pd11, 11),
1114 PD12: (pd12, 12),
1115 PD13: (pd13, 13),
1116 PD14: (pd14, 14),
1117 PD15: (pd15, 15),
1118]);
1119
1120gpio!(GPIOE, gpioe, PEx, 'E', [
1121 PE0: (pe0, 0),
1122 PE1: (pe1, 1),
1123 PE2: (pe2, 2),
1124 PE3: (pe3, 3),
1125 PE4: (pe4, 4),
1126 PE5: (pe5, 5),
1127 PE6: (pe6, 6),
1128 PE7: (pe7, 7),
1129 PE8: (pe8, 8),
1130 PE9: (pe9, 9),
1131 PE10: (pe10, 10),
1132 PE11: (pe11, 11),
1133 PE12: (pe12, 12),
1134 PE13: (pe13, 13),
1135 PE14: (pe14, 14),
1136 PE15: (pe15, 15),
1137]);
1138
1139#[cfg(any(feature = "xl", feature = "high"))]
1140gpio!(GPIOF, gpiof, PFx, 'F', [
1141 PF0: (pf0, 0),
1142 PF1: (pf1, 1),
1143 PF2: (pf2, 2),
1144 PF3: (pf3, 3),
1145 PF4: (pf4, 4),
1146 PF5: (pf5, 5),
1147 PF6: (pf6, 6),
1148 PF7: (pf7, 7),
1149 PF8: (pf8, 8),
1150 PF9: (pf9, 9),
1151 PF10: (pf10, 10),
1152 PF11: (pf11, 11),
1153 PF12: (pf12, 12),
1154 PF13: (pf13, 13),
1155 PF14: (pf14, 14),
1156 PF15: (pf15, 15),
1157]);
1158
1159#[cfg(any(feature = "xl", feature = "high"))]
1160gpio!(GPIOG, gpiog, PGx, 'G', [
1161 PG0: (pg0, 0),
1162 PG1: (pg1, 1),
1163 PG2: (pg2, 2),
1164 PG3: (pg3, 3),
1165 PG4: (pg4, 4),
1166 PG5: (pg5, 5),
1167 PG6: (pg6, 6),
1168 PG7: (pg7, 7),
1169 PG8: (pg8, 8),
1170 PG9: (pg9, 9),
1171 PG10: (pg10, 10),
1172 PG11: (pg11, 11),
1173 PG12: (pg12, 12),
1174 PG13: (pg13, 13),
1175 PG14: (pg14, 14),
1176 PG15: (pg15, 15),
1177]);
1178
1179const fn gpiox<const P: char>() -> *const crate::pac::gpioa::RegisterBlock {
1180 match P {
1181 'A' => crate::pac::GPIOA::ptr(),
1182 'B' => crate::pac::GPIOB::ptr() as _,
1183 'C' => crate::pac::GPIOC::ptr() as _,
1184 'D' => crate::pac::GPIOD::ptr() as _,
1185 'E' => crate::pac::GPIOE::ptr() as _,
1186 #[cfg(any(feature = "xl", feature = "high"))]
1187 'F' => crate::pac::GPIOF::ptr() as _,
1188 #[cfg(any(feature = "xl", feature = "high"))]
1189 'G' => crate::pac::GPIOG::ptr() as _,
1190 _ => unreachable!(),
1191 }
1192}