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