Skip to content

Commit

Permalink
Add documentation for GPIO pins
Browse files Browse the repository at this point in the history
  • Loading branch information
TheZoq2 committed May 1, 2020
1 parent 9f063bb commit 874ad37
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 5 deletions.
2 changes: 1 addition & 1 deletion examples/dynamic_gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use nb::block;
use cortex_m_rt::entry;
use cortex_m_semihosting::hprintln;
use embedded_hal::digital::v2::{InputPin, OutputPin};
use stm32f1xx_hal::{gpio::State, pac, prelude::*, timer::Timer};
use stm32f1xx_hal::{pac, prelude::*, timer::Timer};

#[entry]
fn main() -> ! {
Expand Down
67 changes: 63 additions & 4 deletions src/gpio.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,75 @@
//! # General Purpose I/Os
//!
//! The GPIO pins are organised into groups of 16 pins callled which can be accessed through the
//! `gpioa`, `gpiob`... modules. To get access to the pins, you first need to convert them into a
//! HAL designed struct from the `pac` struct using the `spilit` function.
//! ```rust
//! // Acquire the GPIOC peripheral
//! // NOTE: `dp` is the device peripherals from the `PAC` crate
//! let mut gpioa = dp.GPIOA.split(&mut rcc.apb2);
//! ```
//!
//! This gives you a struct containing two control registers `crl` and `crh` and all the pins
//! `px0..px15`. These structs are what you use to interract with the pins to chagne their modes,
//! or their inputs or outputs. For example, to set `pa5` high, you would call
//!
//! ```rust
//! let output = gpioa.pa5.into_push_pull_output(&mut gpioa.crl);
//! output.set_high();
//! ```
//!
//! Each GPIO pin can be set to various modes:
//!
//! - **Alternate**: Pin mode required when the pin is driven by other peripherals
//! - **Dynamic**: Pin mode is selected at runtime. See changing configurations for more details
//! - Input
//! - **PullUp**: Input connected to high with a weak pull up resistor. Will be high when nothing
//! is connected
//! - **PullDown**: Input connected to high with a weak pull up resistor. Will be low when nothing
//! is connected
//! - **Floating**: Input not pulled to high or low. Will be undefined when nothing is connected
//! - Output
//! - **PushPull**: Output which either drives the pin high or low
//! - **OpenDrain**: Output which leaves the gate floating, or pulls it do ground in drain
//! mode. Can be used as an input in the `open` configuration
//! - **Debugger**: Some pins start out being used by the debugger. A pin in this mode can only be
//! used if the debugger has been turned off
//!
//! ## Changing modes
//! The simplest way to change the pin mode is to use the `into_<mode>` functions. These return a
//! new struct with the correct mode that you can use the input or output functions on.
//!
//! If you need a more temporary mode change, and can not use the `into_<mode>` functions for
//! ownership reasons, you can use the `as_<mode>` functions to temporarily change the pin type, do
//! some output or input, and then have it change back once done.
//!
//! ### Dynamic Mode Change
//! The above mode change methods guarantee that you can only call input functions when the pin is
//! in input mode, and output when in output modes, but can lead to some issues. Therefore, there
//! is also a mode where the state is kept track of at runtime, allowing you to change the mode
//! often, and without problems with ownership, or references, at the cost of some performance and
//! the risk of runtime errors.
//!
//! To make a pin dynamic, use the `into_dynamic` function, and then use `make_<mode>` functions to
//! change the mode
//!
//! ## Accessing PA15, PB3, and PB14
//!
//! These pins are used by the JTAG peripheral by default. To use them in your program, you need to
//! disable that peripheral. This is done using the `afio::MAPR::disable_jtag` function
//!
//! # Interfacing with v1 traits
//!
//! `embedded-hal` has two versions of the digital traits, `v2` which is used
//! by this crate and `v1` which is deprecated but still used by a lot of drivers.
//! If you want to use such a driver with this crate, you need to convert the digital pins to the `v1` type.
//! `embedded-hal` has two versions of the digital traits, `v2` which is used by this crate and
//! `v1` which is deprecated but still used by a lot of drivers. If you want to use such a driver
//! with this crate, you need to convert the digital pins to the `v1` type.
//!
//! This is done using `embedded-hal::digital::v1_compat::OldOutputPin`. For example:
//!
//! ```rust
//! let nss = gpioa.pa4.into_push_pull_output(&mut gpioa.crl);
//! let mut mfrc522 = Mfrc522::new(spi, OldOutputPin::from(nss)).unwrap();
//! ```
//!
use core::marker::PhantomData;

Expand Down Expand Up @@ -104,6 +161,8 @@ pub enum Dynamic {
OutputOpenDrain,
}

impl Active for Dynamic {}

#[derive(Debug, PartialEq)]
pub enum PinModeError {
IncorrectMode,
Expand Down

0 comments on commit 874ad37

Please sign in to comment.