stm32f1xx_hal/
afio.rs

1//! # Alternate Function I/Os
2use crate::pac::{self, afio, AFIO, RCC};
3
4use crate::rcc::{Enable, Reset};
5
6use crate::gpio::{self, Alternate, Cr, Debugger, Floating, Input, OpenDrain, PushPull};
7use crate::sealed::Sealed;
8
9pub trait AfioExt {
10    fn constrain(self, rcc: &mut RCC) -> Parts;
11}
12
13impl AfioExt for AFIO {
14    fn constrain(self, rcc: &mut RCC) -> Parts {
15        AFIO::enable(rcc);
16        AFIO::reset(rcc);
17
18        Parts {
19            evcr: EVCR,
20            mapr: MAPR { jtag_enabled: true },
21            exticr1: EXTICR1,
22            exticr2: EXTICR2,
23            exticr3: EXTICR3,
24            exticr4: EXTICR4,
25            mapr2: MAPR2,
26        }
27    }
28}
29
30/// HAL wrapper around the AFIO registers
31///
32/// Aquired by calling [constrain](trait.AfioExt.html#constrain) on the [AFIO
33/// registers](../pac/struct.AFIO.html)
34///
35/// ```rust
36/// let p = pac::Peripherals::take().unwrap();
37/// let mut rcc = p.RCC.constrain();
38/// let mut afio = p.AFIO.constrain(&mut rcc);
39pub struct Parts {
40    pub evcr: EVCR,
41    pub mapr: MAPR,
42    pub exticr1: EXTICR1,
43    pub exticr2: EXTICR2,
44    pub exticr3: EXTICR3,
45    pub exticr4: EXTICR4,
46    pub mapr2: MAPR2,
47}
48
49#[non_exhaustive]
50pub struct EVCR;
51
52impl EVCR {
53    pub fn evcr(&mut self) -> &afio::EVCR {
54        unsafe { (*AFIO::ptr()).evcr() }
55    }
56}
57
58/// AF remap and debug I/O configuration register (MAPR)
59///
60/// Aquired through the [Parts](struct.Parts.html) struct.
61///
62/// ```rust
63/// let dp = pac::Peripherals::take().unwrap();
64/// let mut rcc = dp.RCC.constrain();
65/// let mut afio = dp.AFIO.constrain(&mut rcc);
66/// function_using_mapr(&mut afio.mapr);
67/// ```
68#[non_exhaustive]
69pub struct MAPR {
70    jtag_enabled: bool,
71}
72
73impl MAPR {
74    fn mapr(&mut self) -> &afio::MAPR {
75        unsafe { (*AFIO::ptr()).mapr() }
76    }
77
78    pub fn modify_mapr<F>(&mut self, mod_fn: F)
79    where
80        F: for<'w> FnOnce(&afio::mapr::R, &'w mut afio::mapr::W) -> &'w mut afio::mapr::W,
81    {
82        let debug_bits = if self.jtag_enabled { 0b000 } else { 0b010 };
83        self.mapr()
84            .modify(unsafe { |r, w| mod_fn(r, w).swj_cfg().bits(debug_bits) });
85    }
86
87    /// Disables the JTAG to free up pa15, pb3 and pb4 for normal use
88    #[allow(clippy::redundant_field_names, clippy::type_complexity)]
89    pub fn disable_jtag(
90        &mut self,
91        pa15: gpio::PA15<Debugger>,
92        pb3: gpio::PB3<Debugger>,
93        pb4: gpio::PB4<Debugger>,
94    ) -> (gpio::PA15, gpio::PB3, gpio::PB4) {
95        self.jtag_enabled = false;
96        // Avoid duplicating swj_cfg write code
97        self.modify_mapr(|_, w| w);
98
99        // NOTE(unsafe) The pins are now in the good state.
100        unsafe { (pa15.activate(), pb3.activate(), pb4.activate()) }
101    }
102}
103
104#[non_exhaustive]
105pub struct EXTICR1;
106
107impl EXTICR1 {
108    pub fn exticr1(&mut self) -> &afio::EXTICR1 {
109        unsafe { (*AFIO::ptr()).exticr1() }
110    }
111}
112
113#[non_exhaustive]
114pub struct EXTICR2;
115
116impl EXTICR2 {
117    pub fn exticr2(&mut self) -> &afio::EXTICR2 {
118        unsafe { (*AFIO::ptr()).exticr2() }
119    }
120}
121
122#[non_exhaustive]
123pub struct EXTICR3;
124
125impl EXTICR3 {
126    pub fn exticr3(&mut self) -> &afio::EXTICR3 {
127        unsafe { (*AFIO::ptr()).exticr3() }
128    }
129}
130
131#[non_exhaustive]
132pub struct EXTICR4;
133
134impl EXTICR4 {
135    pub fn exticr4(&mut self) -> &afio::EXTICR4 {
136        unsafe { (*AFIO::ptr()).exticr4() }
137    }
138}
139
140#[non_exhaustive]
141pub struct MAPR2;
142
143impl MAPR2 {
144    pub fn mapr2(&mut self) -> &afio::MAPR2 {
145        unsafe { (*AFIO::ptr()).mapr2() }
146    }
147
148    pub fn modify_mapr<F>(&mut self, mod_fn: F)
149    where
150        F: for<'w> FnOnce(&afio::mapr2::R, &'w mut afio::mapr2::W) -> &'w mut afio::mapr2::W,
151    {
152        self.mapr2().modify(|r, w| mod_fn(r, w));
153    }
154}
155
156pub trait Remap: Sealed + Sized {
157    type Mapr;
158    #[doc(hidden)]
159    fn rmp(mapr: &mut Self::Mapr, to: u8);
160    fn remap<const R: u8>(self, mapr: &mut Self::Mapr) -> Rmp<Self, R> {
161        Self::rmp(mapr, R);
162        Rmp(self)
163    }
164}
165
166macro_rules! remap {
167    ($(
168        $PER:ty: $MAPR:ident, $w:ident: $field:ident $(, { $allowed:pat })?;
169    )+) => {
170        $(
171            remap!($PER: $MAPR, $w: $field $(, { $allowed })?);
172        )+
173    };
174    ($PER:ty: $MAPR:ident, bool: $field:ident) => {
175        impl Remap for $PER {
176            type Mapr = $MAPR;
177            fn rmp(mapr: &mut Self::Mapr, to: u8) {
178                assert!(matches!(to, 0 | 1));
179                mapr.modify_mapr(|_, w| w.$field().bit(to != 0));
180            }
181        }
182    };
183    ($PER:ty: $MAPR:ident, u8: $field:ident $(, {$allowed:pat })?) => {
184        impl Remap for $PER {
185            type Mapr = $MAPR;
186            fn rmp(mapr: &mut Self::Mapr, to: u8) {
187                $(assert!(matches!(to, $allowed)))?;
188                mapr.modify_mapr(|_, w| unsafe { w.$field().bits(to) });
189            }
190        }
191    };
192}
193use remap;
194
195remap! {
196    pac::SPI1: MAPR, bool: spi1_remap;
197    pac::I2C1: MAPR, bool: i2c1_remap;
198    pac::USART1: MAPR, bool: usart1_remap;
199    pac::USART2: MAPR, bool: usart2_remap;
200    pac::USART3: MAPR, u8: usart3_remap, { 0 | 1 | 3 };
201    pac::TIM2: MAPR, u8: tim2_remap, { 0..=3 };
202    pac::TIM3: MAPR, u8: tim3_remap, { 0 | 2 | 3 };
203}
204
205#[cfg(feature = "medium")]
206remap! {
207    pac::TIM4: MAPR, bool: tim4_remap;
208}
209
210#[cfg(any(feature = "stm32f100", feature = "stm32f103", feature = "connectivity"))]
211remap! {
212    pac::TIM1: MAPR, u8: tim1_remap, { 0 | 1 | 3 };
213}
214
215#[cfg(feature = "stm32f103")]
216remap! {
217    pac::CAN: MAPR, u8: can_remap, { 0 | 2 | 3 };
218}
219
220#[cfg(feature = "connectivity")]
221remap! {
222    pac::CAN1: MAPR, u8: can1_remap, { 0 | 2 | 3 };
223    //pac::ETHERNET_MAC: MAPR, bool: eth_remap;
224    pac::CAN2: MAPR, bool: can2_remap;
225    pac::SPI3: MAPR, bool: spi3_remap;
226}
227
228#[cfg(feature = "xl")]
229remap! {
230    pac::TIM9: MAPR2, bool: tim9_remap;
231    pac::TIM10: MAPR2, bool: tim10_remap;
232    pac::TIM11: MAPR2, bool: tim11_remap;
233}
234#[cfg(any(feature = "xl", all(feature = "stm32f100", feature = "high")))]
235remap! {
236    pac::TIM13: MAPR2, bool: tim13_remap;
237    pac::TIM14: MAPR2, bool: tim14_remap;
238}
239
240pub struct Rmp<T, const R: u8>(pub(crate) T);
241
242impl<T> From<T> for Rmp<T, 0> {
243    fn from(value: T) -> Self {
244        Self(value)
245    }
246}
247
248pub trait RFrom<T, const R: u8> {
249    fn rfrom(value: T) -> Self;
250}
251
252impl<T, const R: u8> RFrom<T, R> for T {
253    fn rfrom(value: T) -> Self {
254        value
255    }
256}
257
258pub trait RInto<T, const R: u8> {
259    fn rinto(self) -> T;
260}
261
262impl<S, T, const R: u8> RInto<T, R> for S
263where
264    T: RFrom<Self, R>,
265{
266    fn rinto(self) -> T {
267        T::rfrom(self)
268    }
269}
270
271// REMAPPING, see: https://www.st.com/content/ccc/resource/technical/document/reference_manual/59/b9/ba/7f/11/af/43/d5/CD00171190.pdf/files/CD00171190.pdf/jcr:content/translations/en.CD00171190.pdf
272// Section 9.3
273
274/// CAN pins
275pub trait CanCommon {
276    /// Transmit
277    ///
278    /// Alternate function push-pull
279    type Tx;
280    /// Receive
281    ///
282    /// Input floating / Input pull-up
283    type Rx<PULL>;
284}
285
286#[cfg(feature = "has-can")]
287pub mod can1 {
288    use super::*;
289
290    pin! {
291        <Tx, Alternate<PushPull>> for [
292            PA12: [0],
293            PB9:  [2],
294            PD1:  [3],
295        ],
296    }
297    pin! {
298        <Rx, Input> default:Floating for [
299            PA11: [0],
300            PB8:  [2],
301            PD0:  [3],
302        ],
303    }
304
305    #[cfg(not(feature = "connectivity"))]
306    use pac::CAN as CAN1;
307    #[cfg(feature = "connectivity")]
308    use pac::CAN1;
309    impl CanCommon for CAN1 {
310        type Tx = Tx;
311        type Rx<PULL> = Rx<PULL>;
312    }
313}
314
315#[cfg(feature = "connectivity")]
316pub mod can2 {
317    use super::*;
318
319    pin! {
320        <Tx, Alternate<PushPull>> for [
321            PB13: [0],
322            PB6:  [1],
323        ],
324    }
325    pin! {
326        <Rx, Input> default:Floating for [
327            PB12: [0],
328            PB5:  [1],
329        ],
330    }
331
332    impl CanCommon for pac::CAN2 {
333        type Tx = Tx;
334        type Rx<PULL> = Rx<PULL>;
335    }
336}
337
338/// I2C pins
339pub trait I2cCommon {
340    /// Serial Clock
341    ///
342    /// Alternate function open drain
343    type Scl;
344    /// Serial Data
345    ///
346    /// Alternate function open drain
347    type Sda;
348    /// SMBus
349    type Smba;
350}
351
352pub mod i2c1 {
353    use super::*;
354
355    pin! {
356        <Scl, Alternate<OpenDrain>> for [
357            PB6: [0],
358            PB8: [1],
359        ],
360        <Sda, Alternate<OpenDrain>> for [
361            PB7: [0],
362            PB9: [1],
363        ],
364        <Smba, Alternate<OpenDrain>> for [
365            PB5: [0, 1],
366        ],
367    }
368
369    impl I2cCommon for pac::I2C1 {
370        type Scl = Scl;
371        type Sda = Sda;
372        type Smba = Smba;
373    }
374}
375pub mod i2c2 {
376    use super::*;
377
378    pin! {
379        <Scl, Alternate<OpenDrain>> for [
380            PB10: [0],
381        ],
382        <Sda, Alternate<OpenDrain>> for [
383            PB11: [0],
384        ],
385        <Smba, Alternate<OpenDrain>> for [
386            PB12: [0],
387        ],
388    }
389
390    impl I2cCommon for pac::I2C2 {
391        type Scl = Scl;
392        type Sda = Sda;
393        type Smba = Smba;
394    }
395}
396
397/// SPI pins
398pub trait SpiCommon {
399    /// Master Serial Clock
400    ///
401    /// Alternate function push-pull
402    type MSck;
403    /// Slave Serial Clock
404    ///
405    /// Input floating
406    type SSck;
407    /// Master In
408    ///
409    /// Input floating / Input pull-up
410    type Mi<PULL>;
411    /// Slave Out
412    ///
413    /// Alternate function push-pull / open drain
414    type So<Otype>;
415    /// Master Out
416    ///
417    /// Alternate function push-pull
418    type Mo;
419    /// Slave In
420    ///
421    /// Input floating / Input pull-up
422    type Si<PULL>;
423    /// HW Slave Select (output)
424    ///
425    /// Alternate function push-pull
426    type Nss;
427    /// HW Slave Select (input)
428    ///
429    /// Input floating/ Input pull-up / Input pull-down
430    type Ss<PULL>;
431}
432
433pub mod spi1 {
434    use super::*;
435
436    pin! {
437        <Si, Input> default:Floating && <Mo, Alternate<PushPull>> for [
438            PA7: [0],
439            PB5: [1],
440        ],
441        <Ss, Input> default:Floating && <Nss, Alternate<PushPull>>  for [
442            PA4: [0],
443            PA15: [1],
444        ],
445    }
446    pin! {
447        <SSck, Input<Floating>> && <MSck, Alternate<PushPull>> for [
448            PA5: [0],
449            PB3: [1],
450        ],
451    }
452    pin! {
453        <Mi, Input> default:Floating && <So, Alternate> default:PushPull for [
454            PA6: [0],
455            PB4: [1],
456        ],
457    }
458
459    impl SpiCommon for pac::SPI1 {
460        type MSck = MSck;
461        type SSck = SSck;
462        type Mi<PULL> = Mi<PULL>;
463        type So<Otype> = So<Otype>;
464        type Mo = Mo;
465        type Si<PULL> = Si<PULL>;
466        type Nss = Nss;
467        type Ss<PULL> = Ss<PULL>;
468    }
469}
470
471pub mod spi2 {
472    use super::*;
473
474    pin! {
475        <Si, Input> default:Floating && <Mo, Alternate<PushPull>> for [
476            PB15: [0],
477        ],
478        <Ss, Input> default:Floating && <Nss, Alternate<PushPull>> for [
479            PB12: [0],
480        ],
481    }
482    pin! {
483        <SSck, Input<Floating>> && <MSck, Alternate<PushPull>> for [
484            PB13: [0],
485        ],
486    }
487    pin! {
488        <Mi, Input> default:Floating && <So, Alternate> default:PushPull for [
489            PB14: [0],
490        ],
491    }
492
493    impl SpiCommon for pac::SPI2 {
494        type MSck = MSck;
495        type SSck = SSck;
496        type Mi<PULL> = Mi<PULL>;
497        type So<Otype> = So<Otype>;
498        type Mo = Mo;
499        type Si<PULL> = Si<PULL>;
500        type Nss = Nss;
501        type Ss<PULL> = Ss<PULL>;
502    }
503}
504#[cfg(any(feature = "high", feature = "connectivity"))]
505pub mod spi3 {
506    use super::*;
507
508    #[cfg(not(feature = "connectivity"))]
509    pin! {
510        <Si, Input> default:Floating && <Mo, Alternate<PushPull>> for [
511            PB5: [0],
512        ],
513        <Ss, Input> default:Floating && <Nss, Alternate<PushPull>> for [
514            PA15: [0],
515        ],
516    }
517    #[cfg(not(feature = "connectivity"))]
518    pin! {
519        <SSck, Input<Floating>> && <MSck, Alternate<PushPull>> for [
520            PB3: [0],
521        ],
522    }
523    #[cfg(not(feature = "connectivity"))]
524    pin! {
525        <Mi, Input> default:Floating && <So, Alternate> default:PushPull for [
526            PB4: [0],
527        ],
528    }
529
530    #[cfg(feature = "connectivity")]
531    pin! {
532        <Si, Input> default:Floating && <Mo, Alternate<PushPull>> for [
533            PB5: [0],
534            PC12: [1],
535        ],
536        <Ss, Input> default:Floating && <Nss, Alternate<PushPull>> for [
537            PA15: [0],
538            PA4: [1],
539        ],
540    }
541    #[cfg(feature = "connectivity")]
542    pin! {
543        <SSck, Input<Floating>> && <MSck, Alternate<PushPull>> for [
544            PB3: [0],
545            PC10: [1],
546        ],
547    }
548    #[cfg(feature = "connectivity")]
549    pin! {
550        <Mi, Input> default:Floating && <So, Alternate> default:PushPull for [
551            PB4: [0],
552            PC11: [1],
553        ],
554    }
555
556    impl SpiCommon for pac::SPI3 {
557        type MSck = MSck;
558        type SSck = SSck;
559        type Mi<PULL> = Mi<PULL>;
560        type So<Otype> = So<Otype>;
561        type Mo = Mo;
562        type Si<PULL> = Si<PULL>;
563        type Nss = Nss;
564        type Ss<PULL> = Ss<PULL>;
565    }
566}
567
568// Serial pins
569pub trait SerialAsync {
570    /// Receive
571    ///
572    /// Input floating / Input pull-up
573    type Rx<PULL>;
574    /// Transmit
575    ///
576    /// Alternate function push-pull / open drain
577    type Tx<Otype>;
578}
579/// Synchronous mode
580///
581/// Alternate function push-pull
582pub trait SerialSync {
583    type Ck;
584}
585/// Hardware flow control (RS232)
586pub trait SerialFlowControl {
587    /// "Clear To Send" blocks the data transmission at the end of the current transfer when high
588    ///
589    /// Input floating/ Input pull-up
590    type Cts<PULL>;
591    /// "Request to send" indicates that the USART is ready to receive a data (when low)
592    ///
593    /// Alternate function push-pull
594    type Rts;
595}
596
597pub mod usart1 {
598    use super::*;
599
600    pin! {
601        <Tx, Alternate> default:PushPull for [
602            PA9: [0],
603            PB6: [1],
604        ],
605    }
606    pin! {
607        <Rx, Input> default:Floating for [
608            PA10: [0],
609            PB7:  [1],
610        ],
611        <Cts, Input> default:Floating for [
612            PA11: [0, 1],
613        ],
614    }
615
616    pin! {
617        <Ck, Alternate<PushPull>> for [
618            PA8: [0, 1],
619        ],
620        <Rts, Alternate<PushPull>> for [
621            PA12: [0, 1],
622        ],
623    }
624
625    impl SerialAsync for pac::USART1 {
626        type Rx<PULL> = Rx<PULL>;
627        type Tx<Otype> = Tx<Otype>;
628    }
629
630    impl SerialSync for pac::USART1 {
631        type Ck = Ck;
632    }
633
634    impl SerialFlowControl for pac::USART1 {
635        type Cts<PULL> = Cts<PULL>;
636        type Rts = Rts;
637    }
638}
639
640pub mod usart2 {
641    use super::*;
642
643    pin! {
644        <Tx, Alternate> default:PushPull for [
645            PA2: [0],
646            PD5: [1],
647        ],
648    }
649    pin! {
650        <Rx, Input> default:Floating for [
651            PA3: [0],
652            PD6:  [1],
653        ],
654        <Cts, Input> default:Floating for [
655            PA0: [0],
656            PD3: [1],
657        ],
658    }
659
660    pin! {
661        <Ck, Alternate<PushPull>> for [
662            PA4: [0],
663            PD7: [1],
664        ],
665        <Rts, Alternate<PushPull>> for [
666            PA1: [0],
667            PD4:  [1],
668        ],
669    }
670
671    impl SerialAsync for pac::USART2 {
672        type Rx<PULL> = Rx<PULL>;
673        type Tx<Otype> = Tx<Otype>;
674    }
675
676    impl SerialSync for pac::USART2 {
677        type Ck = Ck;
678    }
679
680    impl SerialFlowControl for pac::USART2 {
681        type Cts<PULL> = Cts<PULL>;
682        type Rts = Rts;
683    }
684}
685
686pub mod usart3 {
687    use super::*;
688
689    pin! {
690        <Tx, Alternate> default:PushPull for [
691            PB10: [0],
692            PC10: [1],
693            PD8:  [3],
694        ],
695    }
696    pin! {
697        <Rx, Input> default:Floating for [
698            PB11: [0],
699            PC11: [1],
700            PD9:  [3],
701        ],
702        <Cts, Input> default:Floating for [
703            PB13: [0, 1],
704            PD11: [3],
705        ],
706    }
707
708    pin! {
709        <Ck, Alternate<PushPull>> for [
710            PB12: [0],
711            PC12: [1],
712            PD10: [3],
713        ],
714        <Rts, Alternate<PushPull>> for [
715            PB14: [0, 1],
716            PD12: [3],
717        ],
718    }
719
720    impl SerialAsync for pac::USART3 {
721        type Rx<PULL> = Rx<PULL>;
722        type Tx<Otype> = Tx<Otype>;
723    }
724
725    impl SerialSync for pac::USART3 {
726        type Ck = Ck;
727    }
728
729    impl SerialFlowControl for pac::USART3 {
730        type Cts<PULL> = Cts<PULL>;
731        type Rts = Rts;
732    }
733}
734
735#[cfg(any(all(feature = "stm32f103", feature = "high"), feature = "connectivity"))]
736pub mod uart4 {
737    use super::*;
738
739    pin! {
740        <Tx, Alternate> default:PushPull for [
741            PC10: [0],
742        ],
743    }
744    pin! {
745        <Rx, Input> default:Floating for [
746            PC11: [0],
747        ],
748    }
749
750    impl SerialAsync for pac::UART4 {
751        type Rx<PULL> = Rx<PULL>;
752        type Tx<Otype> = Tx<Otype>;
753    }
754}
755
756#[cfg(any(all(feature = "stm32f103", feature = "high"), feature = "connectivity"))]
757pub mod uart5 {
758    use super::*;
759
760    pin! {
761        <Tx, Alternate> default:PushPull for [
762            PC12: [0],
763        ],
764    }
765    pin! {
766        <Rx, Input> default:Floating for [
767            PD2: [0],
768        ],
769    }
770
771    impl SerialAsync for pac::UART5 {
772        type Rx<PULL> = Rx<PULL>;
773        type Tx<Otype> = Tx<Otype>;
774    }
775}
776
777/// Input capture / Output compare channel `C`
778pub trait TimC<const C: u8> {
779    /// Input capture channel
780    ///
781    /// Input floating
782    type In;
783    /// Output compare channel
784    ///
785    /// Alternate function push-pull
786    type Out;
787}
788
789/// Complementary output channel `C`
790///
791/// Alternate function push-pull
792pub trait TimNC<const C: u8> {
793    type ChN;
794}
795
796/// Break input
797///
798/// Input floating
799pub trait TimBkin {
800    type Bkin;
801}
802
803/// External trigger timer input
804///
805/// Input floating
806pub trait TimEtr {
807    type Etr;
808}
809
810pub mod tim1 {
811    use super::*;
812
813    pin! {
814        <Etr, Input<Floating>> for [
815            PA12: [0, 1],
816            PE7:  [3],
817        ],
818        <Bkin, Input<Floating>> for [
819            PB12: [0],
820            PA6:  [1],
821            PE15: [3],
822        ],
823    }
824    pin! {
825        <Ch1In, Input<Floating>> && <Ch1Out, Alternate<PushPull>> for [
826            PA8:  [0, 1],
827            PE9:  [3],
828        ],
829        <Ch2In, Input<Floating>> && <Ch2Out, Alternate<PushPull>> for [
830            PA9:  [0, 1],
831            PE11: [3],
832        ],
833        <Ch3In, Input<Floating>> && <Ch3Out, Alternate<PushPull>> for [
834            PA10: [0, 1],
835            PE13: [3],
836        ],
837        <Ch4In, Input<Floating>> && <Ch4Out, Alternate<PushPull>> for [
838            PA11: [0, 1],
839            PE14: [3],
840        ],
841    }
842
843    pin! {
844        <Ch1N, Alternate<PushPull>> for [
845            PB13: [0],
846            PA7:  [1],
847            PE8:  [3],
848        ],
849        <Ch2N, Alternate<PushPull>> for [
850            PB14: [0],
851            PB0:  [1],
852            PE10: [3],
853        ],
854        <Ch3N, Alternate<PushPull>> for [
855            PB15: [0],
856            PB1:  [1],
857            PE12: [3],
858        ],
859    }
860
861    use pac::TIM1 as TIM;
862    impl TimEtr for TIM {
863        type Etr = Etr;
864    }
865    impl TimBkin for TIM {
866        type Bkin = Bkin;
867    }
868    impl TimC<0> for TIM {
869        type In = Ch1In;
870        type Out = Ch1Out;
871    }
872    impl TimC<1> for TIM {
873        type In = Ch2In;
874        type Out = Ch2Out;
875    }
876    impl TimC<2> for TIM {
877        type In = Ch3In;
878        type Out = Ch3Out;
879    }
880    impl TimC<3> for TIM {
881        type In = Ch4In;
882        type Out = Ch4Out;
883    }
884    impl TimNC<0> for TIM {
885        type ChN = Ch1N;
886    }
887    impl TimNC<1> for TIM {
888        type ChN = Ch2N;
889    }
890    impl TimNC<2> for TIM {
891        type ChN = Ch3N;
892    }
893}
894
895pub mod tim2 {
896    use super::*;
897
898    pin! {
899        <Etr, Input<Floating>> for [
900            PA0:  [0, 2],
901            PA15: [1, 3],
902        ],
903    }
904    pin! {
905        <Ch1In, Input<Floating>> && <Ch1Out, Alternate<PushPull>> for [
906            PA0:  [0, 2],
907            PA15: [1, 3],
908        ],
909        <Ch2In, Input<Floating>> && <Ch2Out, Alternate<PushPull>> for [
910            PA1:  [0, 2],
911            PB3:  [1, 3],
912        ],
913        <Ch3In, Input<Floating>> && <Ch3Out, Alternate<PushPull>> for [
914            PA2:  [0, 1],
915            PB10: [2, 3],
916        ],
917        <Ch4In, Input<Floating>> && <Ch4Out, Alternate<PushPull>> for [
918            PA3:  [0, 1],
919            PB11: [2, 3],
920        ],
921    }
922
923    use pac::TIM2 as TIM;
924    impl TimEtr for TIM {
925        type Etr = Etr;
926    }
927    impl TimC<0> for TIM {
928        type In = Ch1In;
929        type Out = Ch1Out;
930    }
931    impl TimC<1> for TIM {
932        type In = Ch2In;
933        type Out = Ch2Out;
934    }
935    impl TimC<2> for TIM {
936        type In = Ch3In;
937        type Out = Ch3Out;
938    }
939    impl TimC<3> for TIM {
940        type In = Ch4In;
941        type Out = Ch4Out;
942    }
943}
944
945pub mod tim3 {
946    use super::*;
947
948    pin! {
949        <Etr, Input<Floating>> for [
950            PD2:  [0, 2, 3],
951        ],
952    }
953    pin! {
954        <Ch1In, Input<Floating>> && <Ch1Out, Alternate<PushPull>> for [
955            PA6:  [0],
956            PB4:  [2],
957            PC6:  [3],
958        ],
959        <Ch2In, Input<Floating>> && <Ch2Out, Alternate<PushPull>> for [
960            PA7:  [0],
961            PB5:  [2],
962            PC7:  [3],
963        ],
964        <Ch3In, Input<Floating>> && <Ch3Out, Alternate<PushPull>> for [
965            PB0:  [0, 2],
966            PC8:  [3],
967        ],
968        <Ch4In, Input<Floating>> && <Ch4Out, Alternate<PushPull>> for [
969            PB1:  [0, 2],
970            PC9:  [3],
971        ],
972    }
973
974    use pac::TIM3 as TIM;
975    impl TimEtr for TIM {
976        type Etr = Etr;
977    }
978    impl TimC<0> for TIM {
979        type In = Ch1In;
980        type Out = Ch1Out;
981    }
982    impl TimC<1> for TIM {
983        type In = Ch2In;
984        type Out = Ch2Out;
985    }
986    impl TimC<2> for TIM {
987        type In = Ch3In;
988        type Out = Ch3Out;
989    }
990    impl TimC<3> for TIM {
991        type In = Ch4In;
992        type Out = Ch4Out;
993    }
994}
995
996pub mod tim4 {
997    use super::*;
998
999    pin! {
1000        <Etr, Input<Floating>> for [
1001            PE0:  [0, 1],
1002        ],
1003    }
1004    pin! {
1005        <Ch1In, Input<Floating>> && <Ch1Out, Alternate<PushPull>> for [
1006            PB6:  [0],
1007            PD12: [1],
1008        ],
1009        <Ch2In, Input<Floating>> && <Ch2Out, Alternate<PushPull>> for [
1010            PB7:  [0],
1011            PD13: [1],
1012        ],
1013        <Ch3In, Input<Floating>> && <Ch3Out, Alternate<PushPull>> for [
1014            PB8:  [0],
1015            PD14: [1],
1016        ],
1017        <Ch4In, Input<Floating>> && <Ch4Out, Alternate<PushPull>> for [
1018            PB9:  [0],
1019            PD15: [1],
1020        ],
1021    }
1022
1023    use pac::TIM4 as TIM;
1024    impl TimEtr for TIM {
1025        type Etr = Etr;
1026    }
1027    impl TimC<0> for TIM {
1028        type In = Ch1In;
1029        type Out = Ch1Out;
1030    }
1031    impl TimC<1> for TIM {
1032        type In = Ch2In;
1033        type Out = Ch2Out;
1034    }
1035    impl TimC<2> for TIM {
1036        type In = Ch3In;
1037        type Out = Ch3Out;
1038    }
1039    impl TimC<3> for TIM {
1040        type In = Ch4In;
1041        type Out = Ch4Out;
1042    }
1043}
1044
1045macro_rules! pin_mode {
1046    ( $($(#[$docs:meta])* <$name:ident, $MODE:ty> for [$(
1047        $PX:ident: [$($remap:literal),+],
1048    )*],)*) => {
1049        $(
1050            //#[derive(Debug)]
1051            $(#[$docs])*
1052            pub enum $name {
1053                $(
1054                    $PX(gpio::$PX<$MODE>),
1055                )*
1056            }
1057
1058            impl crate::Sealed for $name { }
1059
1060            $(
1061                $(
1062                    impl RFrom<gpio::$PX<$MODE>, $remap> for $name {
1063                        fn rfrom(p: gpio::$PX<$MODE>) -> Self {
1064                            Self::$PX(p)
1065                        }
1066                    }
1067                )+
1068
1069                impl<MODE> TryFrom<$name> for gpio::$PX<MODE>
1070                where
1071                    MODE: $crate::gpio::PinMode,
1072                    $MODE: $crate::gpio::PinMode,
1073                {
1074                    type Error = ();
1075
1076                    fn try_from(a: $name) -> Result<Self, Self::Error> {
1077                        #[allow(irrefutable_let_patterns)]
1078                        if let $name::$PX(p) = a {
1079                            Ok(p.into_mode(&mut Cr))
1080                        } else {
1081                            Err(())
1082                        }
1083                    }
1084                }
1085            )*
1086        )*
1087    };
1088}
1089use pin_mode;
1090
1091macro_rules! pin_default_mode {
1092    ( $($(#[$docs:meta])* <$name:ident, $M:ident> default:$DefaultMode:ident for [$(
1093        $PX:ident: [$($remap:literal),+],
1094    )*],)*) => {
1095        $(
1096            //#[derive(Debug)]
1097            $(#[$docs])*
1098            pub enum $name<MODE = $DefaultMode> {
1099                $(
1100                    $PX(gpio::$PX<$M<MODE>>),
1101                )*
1102            }
1103
1104            impl<MODE> crate::Sealed for $name<MODE> { }
1105
1106            $(
1107                $(
1108                    impl<MODE> RFrom<gpio::$PX<$M<MODE>>, $remap> for $name<MODE> {
1109                        fn rfrom(p: gpio::$PX<$M<MODE>>) -> Self {
1110                            Self::$PX(p)
1111                        }
1112                    }
1113                )+
1114
1115                impl<OUTMODE> TryFrom<$name> for gpio::$PX<OUTMODE>
1116                where
1117                    OUTMODE: $crate::gpio::PinMode,
1118                {
1119                    type Error = ();
1120
1121                    fn try_from(a: $name) -> Result<Self, Self::Error> {
1122                        #[allow(irrefutable_let_patterns)]
1123                        if let $name::$PX(p) = a {
1124                            Ok(p.into_mode(&mut Cr))
1125                        } else {
1126                            Err(())
1127                        }
1128                    }
1129                }
1130            )*
1131        )*
1132    };
1133}
1134use pin_default_mode;
1135
1136macro_rules! pin {
1137    ( $($(#[$docs:meta])* <$name:ident, Input<$MODE:ident>> && <$name2:ident, Alternate<$MODE2:ident>> for [$(
1138        $PX:ident: [$($remap:literal),+],
1139    )*],)*) => {
1140        pin! {
1141            $($(#[$docs])* <$name, Input<$MODE>> for [$(
1142                $PX: [$($remap),+],
1143            )*],)*
1144        }
1145        pin! {
1146            $($(#[$docs])* <$name2, Alternate<$MODE2>> for [$(
1147                $PX: [$($remap),+],
1148            )*],)*
1149        }
1150    };
1151
1152    ( $($(#[$docs:meta])* <$name:ident, Input> default:$DefaultMode:ident && <$name2:ident, Alternate<$MODE2:ident>> for [$(
1153        $PX:ident: [$($remap:literal),+],
1154    )*],)*) => {
1155        pin! {
1156            $($(#[$docs])* <$name, Input> default:$DefaultMode for [$(
1157                $PX: [$($remap),+],
1158            )*],)*
1159        }
1160        pin! {
1161            $($(#[$docs])* <$name2, Alternate<$MODE2>> for [$(
1162                $PX: [$($remap),+],
1163            )*],)*
1164        }
1165    };
1166
1167    ( $($(#[$docs:meta])* <$name:ident, Input> default:$DefaultMode:ident && <$name2:ident, Alternate> default:$DefaultMode2:ident for [$(
1168        $PX:ident: [$($remap:literal),+],
1169    )*],)*) => {
1170        pin! {
1171            $($(#[$docs])* <$name, Input> default:$DefaultMode for [$(
1172                $PX: [$($remap),+],
1173            )*],)*
1174        }
1175        pin! {
1176            $($(#[$docs])* <$name2, Alternate> default:$DefaultMode2 for [$(
1177                $PX: [$($remap),+],
1178            )*],)*
1179        }
1180    };
1181
1182    ( $($(#[$docs:meta])* <$name:ident, Input<$MODE:ident>> for [$(
1183        $PX:ident: [$($remap:literal),+],
1184    )*],)*) => {
1185        pin_mode! {
1186            $($(#[$docs])* <$name, Input<$MODE>> for [$(
1187                $PX: [$($remap),+],
1188            )*],)*
1189        }
1190    };
1191    ( $($(#[$docs:meta])* <$name:ident, Alternate<$MODE:ident>> for [$(
1192        $PX:ident: [$($remap:literal),+],
1193    )*],)*) => {
1194        pin_mode! {
1195            $($(#[$docs])* <$name, Alternate<$MODE>> for [$(
1196                $PX: [$($remap),+],
1197            )*],)*
1198        }
1199
1200        $(
1201            $(
1202                $(
1203                    impl RFrom<gpio::$PX, $remap> for $name {
1204                        fn rfrom(p: gpio::$PX) -> Self {
1205                            Self::$PX(p.into_mode(&mut Cr))
1206                        }
1207                    }
1208                )+
1209            )*
1210        )*
1211    };
1212    ( $($(#[$docs:meta])* <$name:ident, Input> default:$DefaultMode:ident for [$(
1213        $PX:ident: [$($remap:literal),+],
1214    )*],)*) => {
1215        pin_default_mode! {
1216            $($(#[$docs])* <$name, Input> default:$DefaultMode for [$(
1217                $PX: [$($remap),+],
1218            )*],)*
1219        }
1220    };
1221    ( $($(#[$docs:meta])* <$name:ident, Alternate> default:$DefaultMode:ident for [$(
1222        $PX:ident: [$($remap:literal),+],
1223    )*],)*) => {
1224        pin_default_mode! {
1225            $($(#[$docs])* <$name, Alternate> default:$DefaultMode for [$(
1226                $PX: [$($remap),+],
1227            )*],)*
1228        }
1229        $(
1230            $(
1231                $(
1232                    impl<MODE> RFrom<gpio::$PX, $remap> for $name<MODE>
1233                    where Alternate<MODE>: $crate::gpio::PinMode,
1234                    {
1235                        fn rfrom(p: gpio::$PX) -> Self {
1236                            Self::$PX(p.into_mode(&mut Cr))
1237                        }
1238                    }
1239                )+
1240            )*
1241        )*
1242    };
1243}
1244use pin;