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