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