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