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