11//! # General Purpose I/Os
22//!
3+ //! The GPIO pins are organised into groups of 16 pins which can be accessed through the
4+ //! `gpioa`, `gpiob`... modules. To get access to the pins, you first need to convert them into a
5+ //! HAL designed struct from the `pac` struct using the `spilit` function.
6+ //! ```rust
7+ //! // Acquire the GPIOC peripheral
8+ //! // NOTE: `dp` is the device peripherals from the `PAC` crate
9+ //! let mut gpioa = dp.GPIOA.split(&mut rcc.apb2);
10+ //! ```
11+ //!
12+ //! This gives you a struct containing two control registers `crl` and `crh`, and all the pins
13+ //! `px0..px15`. These structs are what you use to interract with the pins to change their modes,
14+ //! or their inputs or outputs. For example, to set `pa5` high, you would call
15+ //!
16+ //! ```rust
17+ //! let output = gpioa.pa5.into_push_pull_output(&mut gpioa.crl);
18+ //! output.set_high();
19+ //! ```
20+ //!
21+ //! Each GPIO pin can be set to various modes:
22+ //!
23+ //! - **Alternate**: Pin mode required when the pin is driven by other peripherals
24+ //! - **Dynamic**: Pin mode is selected at runtime. See changing configurations for more details
25+ //! - Input
26+ //! - **PullUp**: Input connected to high with a weak pull up resistor. Will be high when nothing
27+ //! is connected
28+ //! - **PullDown**: Input connected to high with a weak pull up resistor. Will be low when nothing
29+ //! is connected
30+ //! - **Floating**: Input not pulled to high or low. Will be undefined when nothing is connected
31+ //! - Output
32+ //! - **PushPull**: Output which either drives the pin high or low
33+ //! - **OpenDrain**: Output which leaves the gate floating, or pulls it do ground in drain
34+ //! mode. Can be used as an input in the `open` configuration
35+ //! - **Debugger**: Some pins start out being used by the debugger. A pin in this mode can only be
36+ //! used if the [JTAG peripheral has been turned off](#accessing-pa15-pb3-and-pb14).
37+ //!
38+ //! ## Changing modes
39+ //! The simplest way to change the pin mode is to use the `into_<mode>` functions. These return a
40+ //! new struct with the correct mode that you can use the input or output functions on.
41+ //!
42+ //! If you need a more temporary mode change, and can not use the `into_<mode>` functions for
43+ //! ownership reasons, you can use the `as_<mode>` functions to temporarily change the pin type, do
44+ //! some output or input, and then have it change back once done.
45+ //!
46+ //! ### Dynamic Mode Change
47+ //! The above mode change methods guarantee that you can only call input functions when the pin is
48+ //! in input mode, and output when in output modes, but can lead to some issues. Therefore, there
49+ //! is also a mode where the state is kept track of at runtime, allowing you to change the mode
50+ //! often, and without problems with ownership, or references, at the cost of some performance and
51+ //! the risk of runtime errors.
52+ //!
53+ //! To make a pin dynamic, use the `into_dynamic` function, and then use the `make_<mode>` functions to
54+ //! change the mode
55+ //!
56+ //! ## Accessing PA15, PB3, and PB14
57+ //!
58+ //! These pins are used by the JTAG peripheral by default. To use them in your program, you need to
59+ //! disable that peripheral. This is done using the [afio::MAPR::disable_jtag](../afio/struct.MAPR.html#method.disable_jtag) function
60+ //!
361//! # Interfacing with v1 traits
462//!
5- //! `embedded-hal` has two versions of the digital traits, `v2` which is used
6- //! by this crate and `v1` which is deprecated but still used by a lot of drivers.
7- //! If you want to use such a driver with this crate, you need to convert the digital pins to the `v1` type.
63+ //! `embedded-hal` has two versions of the digital traits, `v2` which is used by this crate and
64+ //! `v1` which is deprecated but still used by a lot of drivers. If you want to use such a driver
65+ //! with this crate, you need to convert the digital pins to the `v1` type.
866//!
967//! This is done using `embedded-hal::digital::v1_compat::OldOutputPin`. For example:
1068//!
1169//! ```rust
1270//! let nss = gpioa.pa4.into_push_pull_output(&mut gpioa.crl);
1371//! let mut mfrc522 = Mfrc522::new(spi, OldOutputPin::from(nss)).unwrap();
1472//! ```
15- //!
1673
1774use core:: marker:: PhantomData ;
1875
@@ -96,6 +153,7 @@ pub trait ExtiPin {
96153 fn check_interrupt ( & mut self ) -> bool ;
97154}
98155
156+ /// Tracks the current pin state for dynamic pins
99157pub enum Dynamic {
100158 InputFloating ,
101159 InputPullUp ,
@@ -104,6 +162,8 @@ pub enum Dynamic {
104162 OutputOpenDrain ,
105163}
106164
165+ impl Active for Dynamic { }
166+
107167#[ derive( Debug , PartialEq ) ]
108168pub enum PinModeError {
109169 IncorrectMode ,
@@ -134,22 +194,22 @@ pub trait PinMode<CR> {
134194
135195// These impls are needed because a macro can not brace initialise a ty token
136196impl < MODE > Input < MODE > {
137- fn _new ( ) -> Self {
197+ const fn _new ( ) -> Self {
138198 Self { _mode : PhantomData }
139199 }
140200}
141201impl < MODE > Output < MODE > {
142- fn _new ( ) -> Self {
202+ const fn _new ( ) -> Self {
143203 Self { _mode : PhantomData }
144204 }
145205}
146206impl < MODE > Alternate < MODE > {
147- fn _new ( ) -> Self {
207+ const fn _new ( ) -> Self {
148208 Self { _mode : PhantomData }
149209 }
150210}
151211impl Debugger {
152- fn _new ( ) -> Self {
212+ const fn _new ( ) -> Self {
153213 Self { }
154214 }
155215}
@@ -516,7 +576,6 @@ macro_rules! gpio {
516576 }
517577 }
518578
519-
520579 /// Configures the pin to operate as an analog input pin
521580 pub fn into_analog( self , cr: & mut $CR) -> $PXi<Analog > {
522581 unsafe {
@@ -533,6 +592,8 @@ macro_rules! gpio {
533592 }
534593 }
535594
595+ // These macros are defined here instead of at the top level in order
596+ // to be able to refer to macro variables from the outer layers.
536597 macro_rules! impl_temp_output {
537598 (
538599 $fn_name: ident,
@@ -626,7 +687,6 @@ macro_rules! gpio {
626687 ) ;
627688 }
628689
629-
630690 impl <MODE > $PXi<MODE > where MODE : Active {
631691 /// Erases the pin number from the type
632692 fn into_generic( self ) -> Generic <MODE > {
0 commit comments