stm32f7xx_hal/gpio/
convert.rs

1use super::*;
2
3/// Const assert hack
4struct Assert<const L: u8, const R: u8>;
5
6impl<const L: u8, const R: u8> Assert<L, R> {
7    pub const LESS: u8 = R - L - 1;
8}
9
10impl<const P: char, const N: u8, const A: u8, MODE> From<Pin<P, N, Input<MODE>>>
11    for Pin<P, N, Alternate<A, PushPull>>
12{
13    #[inline(always)]
14    fn from(f: Pin<P, N, Input<MODE>>) -> Self {
15        f.into_alternate::<A>()
16    }
17}
18
19impl<const P: char, const N: u8, const A: u8, MODE> From<Pin<P, N, Output<MODE>>>
20    for Pin<P, N, Alternate<A, PushPull>>
21{
22    #[inline(always)]
23    fn from(f: Pin<P, N, Output<MODE>>) -> Self {
24        f.into_alternate::<A>()
25    }
26}
27
28impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Analog>>
29    for Pin<P, N, Alternate<A, PushPull>>
30{
31    #[inline(always)]
32    fn from(f: Pin<P, N, Analog>) -> Self {
33        f.into_alternate::<A>()
34    }
35}
36
37impl<const P: char, const N: u8, const A: u8, const B: u8> From<Pin<P, N, Alternate<B, OpenDrain>>>
38    for Pin<P, N, Alternate<A, PushPull>>
39{
40    #[inline(always)]
41    fn from(f: Pin<P, N, Alternate<B, OpenDrain>>) -> Self {
42        f.into_alternate::<A>()
43    }
44}
45
46impl<const P: char, const N: u8, const A: u8, MODE> From<Pin<P, N, Input<MODE>>>
47    for Pin<P, N, Alternate<A, OpenDrain>>
48{
49    #[inline(always)]
50    fn from(f: Pin<P, N, Input<MODE>>) -> Self {
51        f.into_alternate_open_drain::<A>()
52    }
53}
54
55impl<const P: char, const N: u8, const A: u8, MODE> From<Pin<P, N, Output<MODE>>>
56    for Pin<P, N, Alternate<A, OpenDrain>>
57{
58    #[inline(always)]
59    fn from(f: Pin<P, N, Output<MODE>>) -> Self {
60        f.into_alternate_open_drain::<A>()
61    }
62}
63
64impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Analog>>
65    for Pin<P, N, Alternate<A, OpenDrain>>
66{
67    #[inline(always)]
68    fn from(f: Pin<P, N, Analog>) -> Self {
69        f.into_alternate_open_drain::<A>()
70    }
71}
72
73impl<const P: char, const N: u8, const A: u8, const B: u8> From<Pin<P, N, Alternate<B, PushPull>>>
74    for Pin<P, N, Alternate<A, OpenDrain>>
75{
76    #[inline(always)]
77    fn from(f: Pin<P, N, Alternate<B, PushPull>>) -> Self {
78        f.into_alternate_open_drain::<A>()
79    }
80}
81
82impl<const P: char, const N: u8> From<Pin<P, N, Input<Floating>>> for Pin<P, N, Input<PullDown>> {
83    #[inline(always)]
84    fn from(f: Pin<P, N, Input<Floating>>) -> Self {
85        f.into_pull_down_input()
86    }
87}
88
89impl<const P: char, const N: u8> From<Pin<P, N, Input<PullUp>>> for Pin<P, N, Input<PullDown>> {
90    #[inline(always)]
91    fn from(f: Pin<P, N, Input<PullUp>>) -> Self {
92        f.into_pull_down_input()
93    }
94}
95
96impl<const P: char, const N: u8, MODE> From<Pin<P, N, Output<MODE>>>
97    for Pin<P, N, Input<PullDown>>
98{
99    #[inline(always)]
100    fn from(f: Pin<P, N, Output<MODE>>) -> Self {
101        f.into_pull_down_input()
102    }
103}
104
105impl<const P: char, const N: u8> From<Pin<P, N, Analog>> for Pin<P, N, Input<PullDown>> {
106    #[inline(always)]
107    fn from(f: Pin<P, N, Analog>) -> Self {
108        f.into_pull_down_input()
109    }
110}
111
112impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, PushPull>>>
113    for Pin<P, N, Input<PullDown>>
114{
115    #[inline(always)]
116    fn from(f: Pin<P, N, Alternate<A, PushPull>>) -> Self {
117        f.into_pull_down_input()
118    }
119}
120
121impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, OpenDrain>>>
122    for Pin<P, N, Input<PullDown>>
123{
124    #[inline(always)]
125    fn from(f: Pin<P, N, Alternate<A, OpenDrain>>) -> Self {
126        f.into_pull_down_input()
127    }
128}
129
130impl<const P: char, const N: u8> From<Pin<P, N, Input<Floating>>> for Pin<P, N, Input<PullUp>> {
131    #[inline(always)]
132    fn from(f: Pin<P, N, Input<Floating>>) -> Self {
133        f.into_pull_up_input()
134    }
135}
136
137impl<const P: char, const N: u8> From<Pin<P, N, Input<PullDown>>> for Pin<P, N, Input<PullUp>> {
138    #[inline(always)]
139    fn from(f: Pin<P, N, Input<PullDown>>) -> Self {
140        f.into_pull_up_input()
141    }
142}
143
144impl<const P: char, const N: u8, MODE> From<Pin<P, N, Output<MODE>>> for Pin<P, N, Input<PullUp>> {
145    #[inline(always)]
146    fn from(f: Pin<P, N, Output<MODE>>) -> Self {
147        f.into_pull_up_input()
148    }
149}
150
151impl<const P: char, const N: u8> From<Pin<P, N, Analog>> for Pin<P, N, Input<PullUp>> {
152    #[inline(always)]
153    fn from(f: Pin<P, N, Analog>) -> Self {
154        f.into_pull_up_input()
155    }
156}
157
158impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, PushPull>>>
159    for Pin<P, N, Input<PullUp>>
160{
161    #[inline(always)]
162    fn from(f: Pin<P, N, Alternate<A, PushPull>>) -> Self {
163        f.into_pull_up_input()
164    }
165}
166
167impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, OpenDrain>>>
168    for Pin<P, N, Input<PullUp>>
169{
170    #[inline(always)]
171    fn from(f: Pin<P, N, Alternate<A, OpenDrain>>) -> Self {
172        f.into_pull_up_input()
173    }
174}
175
176impl<const P: char, const N: u8> From<Pin<P, N, Input<PullDown>>> for Pin<P, N, Input<Floating>> {
177    #[inline(always)]
178    fn from(f: Pin<P, N, Input<PullDown>>) -> Self {
179        f.into_floating_input()
180    }
181}
182
183impl<const P: char, const N: u8> From<Pin<P, N, Input<PullUp>>> for Pin<P, N, Input<Floating>> {
184    #[inline(always)]
185    fn from(f: Pin<P, N, Input<PullUp>>) -> Self {
186        f.into_floating_input()
187    }
188}
189
190impl<const P: char, const N: u8, MODE> From<Pin<P, N, Output<MODE>>>
191    for Pin<P, N, Input<Floating>>
192{
193    #[inline(always)]
194    fn from(f: Pin<P, N, Output<MODE>>) -> Self {
195        f.into_floating_input()
196    }
197}
198
199impl<const P: char, const N: u8> From<Pin<P, N, Analog>> for Pin<P, N, Input<Floating>> {
200    #[inline(always)]
201    fn from(f: Pin<P, N, Analog>) -> Self {
202        f.into_floating_input()
203    }
204}
205
206impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, PushPull>>>
207    for Pin<P, N, Input<Floating>>
208{
209    #[inline(always)]
210    fn from(f: Pin<P, N, Alternate<A, PushPull>>) -> Self {
211        f.into_floating_input()
212    }
213}
214
215impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, OpenDrain>>>
216    for Pin<P, N, Input<Floating>>
217{
218    #[inline(always)]
219    fn from(f: Pin<P, N, Alternate<A, OpenDrain>>) -> Self {
220        f.into_floating_input()
221    }
222}
223
224impl<const P: char, const N: u8, MODE> From<Pin<P, N, Input<MODE>>>
225    for Pin<P, N, Output<OpenDrain>>
226{
227    #[inline(always)]
228    fn from(f: Pin<P, N, Input<MODE>>) -> Self {
229        f.into_open_drain_output()
230    }
231}
232
233impl<const P: char, const N: u8> From<Pin<P, N, Output<PushPull>>>
234    for Pin<P, N, Output<OpenDrain>>
235{
236    #[inline(always)]
237    fn from(f: Pin<P, N, Output<PushPull>>) -> Self {
238        f.into_open_drain_output()
239    }
240}
241
242impl<const P: char, const N: u8> From<Pin<P, N, Analog>> for Pin<P, N, Output<OpenDrain>> {
243    #[inline(always)]
244    fn from(f: Pin<P, N, Analog>) -> Self {
245        f.into_open_drain_output()
246    }
247}
248
249impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, PushPull>>>
250    for Pin<P, N, Output<OpenDrain>>
251{
252    #[inline(always)]
253    fn from(f: Pin<P, N, Alternate<A, PushPull>>) -> Self {
254        f.into_open_drain_output()
255    }
256}
257
258impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, OpenDrain>>>
259    for Pin<P, N, Output<OpenDrain>>
260{
261    #[inline(always)]
262    fn from(f: Pin<P, N, Alternate<A, OpenDrain>>) -> Self {
263        f.into_open_drain_output()
264    }
265}
266
267impl<const P: char, const N: u8, MODE> From<Pin<P, N, Input<MODE>>>
268    for Pin<P, N, Output<PushPull>>
269{
270    #[inline(always)]
271    fn from(f: Pin<P, N, Input<MODE>>) -> Self {
272        f.into_push_pull_output()
273    }
274}
275
276impl<const P: char, const N: u8> From<Pin<P, N, Output<OpenDrain>>>
277    for Pin<P, N, Output<PushPull>>
278{
279    #[inline(always)]
280    fn from(f: Pin<P, N, Output<OpenDrain>>) -> Self {
281        f.into_push_pull_output()
282    }
283}
284
285impl<const P: char, const N: u8> From<Pin<P, N, Analog>> for Pin<P, N, Output<PushPull>> {
286    #[inline(always)]
287    fn from(f: Pin<P, N, Analog>) -> Self {
288        f.into_push_pull_output()
289    }
290}
291
292impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, PushPull>>>
293    for Pin<P, N, Output<PushPull>>
294{
295    #[inline(always)]
296    fn from(f: Pin<P, N, Alternate<A, PushPull>>) -> Self {
297        f.into_push_pull_output()
298    }
299}
300
301impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, OpenDrain>>>
302    for Pin<P, N, Output<PushPull>>
303{
304    #[inline(always)]
305    fn from(f: Pin<P, N, Alternate<A, OpenDrain>>) -> Self {
306        f.into_push_pull_output()
307    }
308}
309
310impl<const P: char, const N: u8, MODE> From<Pin<P, N, Input<MODE>>> for Pin<P, N, Analog> {
311    #[inline(always)]
312    fn from(f: Pin<P, N, Input<MODE>>) -> Self {
313        f.into_analog()
314    }
315}
316
317impl<const P: char, const N: u8, MODE> From<Pin<P, N, Output<MODE>>> for Pin<P, N, Analog> {
318    #[inline(always)]
319    fn from(f: Pin<P, N, Output<MODE>>) -> Self {
320        f.into_analog()
321    }
322}
323
324impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, PushPull>>>
325    for Pin<P, N, Analog>
326{
327    #[inline(always)]
328    fn from(f: Pin<P, N, Alternate<A, PushPull>>) -> Self {
329        f.into_analog()
330    }
331}
332
333impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, OpenDrain>>>
334    for Pin<P, N, Analog>
335{
336    #[inline(always)]
337    fn from(f: Pin<P, N, Alternate<A, OpenDrain>>) -> Self {
338        f.into_analog()
339    }
340}
341
342impl<const P: char, const N: u8, MODE> Pin<P, N, MODE> {
343    pub(super) fn set_alternate<const A: u8>(&mut self) {
344        #[allow(path_statements, clippy::no_effect)]
345        {
346            Assert::<A, 16>::LESS;
347        }
348        let offset = 2 * { N };
349        unsafe {
350            if N < 8 {
351                let offset2 = 4 * { N };
352                (*Gpio::<P>::ptr()).afrl.modify(|r, w| {
353                    w.bits((r.bits() & !(0b1111 << offset2)) | ((A as u32) << offset2))
354                });
355            } else {
356                let offset2 = 4 * { N - 8 };
357                (*Gpio::<P>::ptr()).afrh.modify(|r, w| {
358                    w.bits((r.bits() & !(0b1111 << offset2)) | ((A as u32) << offset2))
359                });
360            }
361            (*Gpio::<P>::ptr())
362                .moder
363                .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset)));
364        }
365    }
366    /// Configures the pin to operate alternate mode
367    pub fn into_alternate<const A: u8>(mut self) -> Pin<P, N, Alternate<A, PushPull>> {
368        self.set_alternate::<A>();
369        Pin::new()
370    }
371
372    /// Configures the pin to operate in alternate open drain mode
373    #[allow(path_statements)]
374    pub fn into_alternate_open_drain<const A: u8>(self) -> Pin<P, N, Alternate<A, OpenDrain>> {
375        self.into_alternate::<A>().set_open_drain()
376    }
377
378    /// Configures the pin to operate as a floating input pin
379    pub fn into_floating_input(mut self) -> Pin<P, N, Input<Floating>> {
380        self.mode::<Input<Floating>>();
381        Pin::new()
382    }
383
384    /// Configures the pin to operate as a pulled down input pin
385    pub fn into_pull_down_input(mut self) -> Pin<P, N, Input<PullDown>> {
386        self.mode::<Input<PullDown>>();
387        Pin::new()
388    }
389
390    /// Configures the pin to operate as a pulled up input pin
391    pub fn into_pull_up_input(mut self) -> Pin<P, N, Input<PullUp>> {
392        self.mode::<Input<PullUp>>();
393        Pin::new()
394    }
395
396    /// Configures the pin to operate as an open drain output pin
397    /// Initial state will be low.
398    pub fn into_open_drain_output(mut self) -> Pin<P, N, Output<OpenDrain>> {
399        self.mode::<Output<OpenDrain>>();
400        Pin::new()
401    }
402
403    /// Configures the pin to operate as an open-drain output pin.
404    /// `initial_state` specifies whether the pin should be initially high or low.
405    pub fn into_open_drain_output_in_state(
406        mut self,
407        initial_state: PinState,
408    ) -> Pin<P, N, Output<OpenDrain>> {
409        self._set_state(initial_state);
410        self.mode::<Output<OpenDrain>>();
411        Pin::new()
412    }
413
414    /// Configures the pin to operate as an push pull output pin
415    /// Initial state will be low.
416    pub fn into_push_pull_output(mut self) -> Pin<P, N, Output<PushPull>> {
417        self._set_low();
418        self.mode::<Output<PushPull>>();
419        Pin::new()
420    }
421
422    /// Configures the pin to operate as an push-pull output pin.
423    /// `initial_state` specifies whether the pin should be initially high or low.
424    pub fn into_push_pull_output_in_state(
425        mut self,
426        initial_state: PinState,
427    ) -> Pin<P, N, Output<PushPull>> {
428        self._set_state(initial_state);
429        self.mode::<Output<PushPull>>();
430        Pin::new()
431    }
432
433    /// Configures the pin to operate as an analog input pin
434    pub fn into_analog(mut self) -> Pin<P, N, Analog> {
435        self.mode::<Analog>();
436        Pin::new()
437    }
438
439    /// Configures the pin as a pin that can change between input
440    /// and output without changing the type. It starts out
441    /// as a floating input
442    pub fn into_dynamic(self) -> DynamicPin<P, N> {
443        self.into_floating_input();
444        DynamicPin::new(Dynamic::InputFloating)
445    }
446
447    /// Puts `self` into mode `M`.
448    ///
449    /// This violates the type state constraints from `MODE`, so callers must
450    /// ensure they use this properly.
451    #[inline(always)]
452    pub(super) fn mode<M: PinMode>(&mut self) {
453        let offset = 2 * N;
454        unsafe {
455            (*Gpio::<P>::ptr())
456                .pupdr
457                .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (M::PUPDR << offset)));
458
459            if let Some(otyper) = M::OTYPER {
460                (*Gpio::<P>::ptr())
461                    .otyper
462                    .modify(|r, w| w.bits(r.bits() & !(0b1 << N) | (otyper << N)));
463            }
464
465            (*Gpio::<P>::ptr())
466                .moder
467                .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (M::MODER << offset)));
468        }
469    }
470}
471
472impl<const P: char, const N: u8, MODE> Pin<P, N, MODE>
473where
474    MODE: PinMode,
475{
476    fn with_mode<M, F, R>(&mut self, f: F) -> R
477    where
478        M: PinMode,
479        F: FnOnce(&mut Pin<P, N, M>) -> R,
480    {
481        self.mode::<M>();
482
483        // This will reset the pin back to the original mode when dropped.
484        // (so either when `with_mode` returns or when `f` unwinds)
485        let _resetti = ResetMode { pin: self };
486
487        let mut witness = Pin::new();
488
489        f(&mut witness)
490    }
491
492    /// Temporarily configures this pin as a floating input.
493    ///
494    /// The closure `f` is called with the reconfigured pin. After it returns,
495    /// the pin will be configured back.
496    pub fn with_floating_input<R>(
497        &mut self,
498        f: impl FnOnce(&mut Pin<P, N, Input<Floating>>) -> R,
499    ) -> R {
500        self.with_mode(f)
501    }
502
503    /// Temporarily configures this pin as a pulled-down input.
504    ///
505    /// The closure `f` is called with the reconfigured pin. After it returns,
506    /// the pin will be configured back.
507    pub fn with_pull_down_input<R>(
508        &mut self,
509        f: impl FnOnce(&mut Pin<P, N, Input<PullDown>>) -> R,
510    ) -> R {
511        self.with_mode(f)
512    }
513
514    /// Temporarily configures this pin as a pulled-up input.
515    ///
516    /// The closure `f` is called with the reconfigured pin. After it returns,
517    /// the pin will be configured back.
518    pub fn with_pull_up_input<R>(
519        &mut self,
520        f: impl FnOnce(&mut Pin<P, N, Input<PullUp>>) -> R,
521    ) -> R {
522        self.with_mode(f)
523    }
524
525    /// Temporarily configures this pin as an analog pin.
526    ///
527    /// The closure `f` is called with the reconfigured pin. After it returns,
528    /// the pin will be configured back.
529    pub fn with_analog<R>(&mut self, f: impl FnOnce(&mut Pin<P, N, Analog>) -> R) -> R {
530        self.with_mode(f)
531    }
532
533    /// Temporarily configures this pin as an open drain output.
534    ///
535    /// The closure `f` is called with the reconfigured pin. After it returns,
536    /// the pin will be configured back.
537    /// The value of the pin after conversion is undefined. If you
538    /// want to control it, use `with_open_drain_output_in_state`
539    pub fn with_open_drain_output<R>(
540        &mut self,
541        f: impl FnOnce(&mut Pin<P, N, Output<OpenDrain>>) -> R,
542    ) -> R {
543        self.with_mode(f)
544    }
545
546    /// Temporarily configures this pin as an open drain output .
547    ///
548    /// The closure `f` is called with the reconfigured pin. After it returns,
549    /// the pin will be configured back.
550    /// Note that the new state is set slightly before conversion
551    /// happens. This can cause a short output glitch if switching
552    /// between output modes
553    pub fn with_open_drain_output_in_state<R>(
554        &mut self,
555        state: PinState,
556        f: impl FnOnce(&mut Pin<P, N, Output<OpenDrain>>) -> R,
557    ) -> R {
558        self._set_state(state);
559        self.with_mode(f)
560    }
561
562    /// Temporarily configures this pin as a push-pull output.
563    ///
564    /// The closure `f` is called with the reconfigured pin. After it returns,
565    /// the pin will be configured back.
566    /// The value of the pin after conversion is undefined. If you
567    /// want to control it, use `with_push_pull_output_in_state`
568    pub fn with_push_pull_output<R>(
569        &mut self,
570        f: impl FnOnce(&mut Pin<P, N, Output<PushPull>>) -> R,
571    ) -> R {
572        self.with_mode(f)
573    }
574
575    /// Temporarily configures this pin as a push-pull output.
576    ///
577    /// The closure `f` is called with the reconfigured pin. After it returns,
578    /// the pin will be configured back.
579    /// Note that the new state is set slightly before conversion
580    /// happens. This can cause a short output glitch if switching
581    /// between output modes
582    pub fn with_push_pull_output_in_state<R>(
583        &mut self,
584        state: PinState,
585        f: impl FnOnce(&mut Pin<P, N, Output<PushPull>>) -> R,
586    ) -> R {
587        self._set_state(state);
588        self.with_mode(f)
589    }
590}
591
592struct ResetMode<'a, const P: char, const N: u8, ORIG: PinMode> {
593    pin: &'a mut Pin<P, N, ORIG>,
594}
595
596impl<'a, const P: char, const N: u8, ORIG: PinMode> Drop for ResetMode<'a, P, N, ORIG> {
597    fn drop(&mut self) {
598        self.pin.mode::<ORIG>();
599    }
600}
601
602/// Marker trait for valid pin modes (type state).
603///
604/// It can not be implemented by outside types.
605pub trait PinMode: crate::Sealed {
606    // These constants are used to implement the pin configuration code.
607    // They are not part of public API.
608
609    #[doc(hidden)]
610    const PUPDR: u32;
611    #[doc(hidden)]
612    const MODER: u32;
613    #[doc(hidden)]
614    const OTYPER: Option<u32> = None;
615}
616
617impl crate::Sealed for Input<Floating> {}
618impl PinMode for Input<Floating> {
619    const PUPDR: u32 = 0b00;
620    const MODER: u32 = 0b00;
621}
622
623impl crate::Sealed for Input<PullDown> {}
624impl PinMode for Input<PullDown> {
625    const PUPDR: u32 = 0b10;
626    const MODER: u32 = 0b00;
627}
628
629impl crate::Sealed for Input<PullUp> {}
630impl PinMode for Input<PullUp> {
631    const PUPDR: u32 = 0b01;
632    const MODER: u32 = 0b00;
633}
634
635impl crate::Sealed for Analog {}
636impl PinMode for Analog {
637    const PUPDR: u32 = 0b00;
638    const MODER: u32 = 0b11;
639}
640
641impl crate::Sealed for Output<OpenDrain> {}
642impl PinMode for Output<OpenDrain> {
643    const PUPDR: u32 = 0b00;
644    const MODER: u32 = 0b01;
645    const OTYPER: Option<u32> = Some(0b1);
646}
647
648impl crate::Sealed for Output<PushPull> {}
649impl PinMode for Output<PushPull> {
650    const PUPDR: u32 = 0b00;
651    const MODER: u32 = 0b01;
652    const OTYPER: Option<u32> = Some(0b0);
653}