From f0ecbb66c763586777768adb0a147bee9eb1bffd Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Sat, 24 Jul 2021 18:33:56 +0300 Subject: [PATCH] pin docs --- CHANGELOG.md | 1 + src/gpio.rs | 54 ++++++++++++++++++++++++++++++++++-- src/gpio/erased.rs | 28 +++++++++++-------- src/gpio/partially_erased.rs | 27 ++++++++++-------- 4 files changed, 84 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 34a698f4..efeff89e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added +- Simple doc in gpio. - Weaker constrains for examples. - Deprecate `stm32` alias. - Temporary change pin mode diff --git a/src/gpio.rs b/src/gpio.rs index 1a4dec82..9d868329 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -1,4 +1,48 @@ //! General Purpose Input / Output +//! +//! The GPIO pins are organised into groups of 16 pins 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 [split](trait.GpioExt.html#tymethod.split) function. +//! ```rust +//! // Acquire the GPIOC peripheral +//! // NOTE: `dp` is the device peripherals from the `PAC` crate +//! let mut gpioa = dp.GPIOA.split(); +//! ``` +//! +//! This gives you a struct containing all the pins `px0..px15`. +//! By default pins are in floating input mode. You can change their modes. +//! For example, to set `pa5` high, you would call +//! +//! ```rust +//! let output = gpioa.pa5.into_push_pull_output(); +//! output.set_high(); +//! ``` +//! +//! ## Modes +//! +//! Each GPIO pin can be set to various modes: +//! +//! - **Alternate**: Pin mode required when the pin is driven by other peripherals +//! - **AlternateOD**: Pin mode required when the pin is driven by other peripherals and has open drain +//! - **Analog**: Analog input to be used with ADC. +//! - 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 +//! +//! ## Changing modes +//! The simplest way to change the pin mode is to use the `into_` 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_` functions for +//! ownership reasons, you can use the `as_` functions to temporarily change the pin type, do +//! some output or input, and then have it change back once done. use core::convert::Infallible; use core::marker::PhantomData; @@ -10,9 +54,9 @@ use crate::syscfg::SysCfg; mod convert; mod partially_erased; -pub use partially_erased::PEPin; +pub use partially_erased::{PEPin, PartiallyErasedPin}; mod erased; -pub use erased::EPin; +pub use erased::{EPin, ErasedPin}; /// A filler pin type pub struct NoPin; @@ -219,7 +263,11 @@ where } } -/// Pin +/// Generic pin type +/// +/// - `MODE` is one of the pin modes (see [Modes](crate::gpio#modes) section). +/// - `P` is port name: `A` for GPIOA, `B` for GPIOB, etc. +/// - `N` is pin number: from `0` to `15`. pub struct Pin { _mode: PhantomData, } diff --git a/src/gpio/erased.rs b/src/gpio/erased.rs index c33979ae..f6416c63 100644 --- a/src/gpio/erased.rs +++ b/src/gpio/erased.rs @@ -1,13 +1,17 @@ use super::*; +pub type EPin = ErasedPin; + /// Fully erased pin -pub struct EPin { +/// +/// `MODE` is one of the pin modes (see [Modes](crate::gpio#modes) section). +pub struct ErasedPin { // Bits 0-3: Pin, Bits 4-7: Port pin_port: u8, _mode: PhantomData, } -impl PinExt for EPin { +impl PinExt for ErasedPin { type Mode = MODE; #[inline(always)] @@ -20,7 +24,7 @@ impl PinExt for EPin { } } -impl EPin { +impl ErasedPin { pub(crate) fn new(port: u8, pin: u8) -> Self { Self { pin_port: port << 4 | pin, @@ -36,7 +40,7 @@ impl EPin { // - GPIOA register is available on all chips // - all gpio register blocks have the same layout // - consecutive gpio register blocks have the same offset between them, namely 0x0400 - // - EPin::new was called with a valid port + // - ErasedPin::new was called with a valid port // FIXME could be calculated after const_raw_ptr_to_usize_cast stabilization #51910 const GPIO_REGISTER_OFFSET: usize = 0x0400; @@ -49,7 +53,7 @@ impl EPin { } } -impl EPin> { +impl ErasedPin> { #[inline(always)] pub fn set_high(&mut self) { // NOTE(unsafe) atomic write to a stateless register @@ -103,7 +107,7 @@ impl EPin> { } } -impl OutputPin for EPin> { +impl OutputPin for ErasedPin> { type Error = core::convert::Infallible; #[inline(always)] @@ -119,7 +123,7 @@ impl OutputPin for EPin> { } } -impl StatefulOutputPin for EPin> { +impl StatefulOutputPin for ErasedPin> { #[inline(always)] fn is_set_high(&self) -> Result { Ok(self.is_set_high()) @@ -131,7 +135,7 @@ impl StatefulOutputPin for EPin> { } } -impl ToggleableOutputPin for EPin> { +impl ToggleableOutputPin for ErasedPin> { type Error = Infallible; #[inline(always)] @@ -141,7 +145,7 @@ impl ToggleableOutputPin for EPin> { } } -impl EPin> { +impl ErasedPin> { #[inline(always)] pub fn is_high(&self) -> bool { !self.is_low() @@ -153,7 +157,7 @@ impl EPin> { } } -impl InputPin for EPin> { +impl InputPin for ErasedPin> { type Error = core::convert::Infallible; #[inline(always)] @@ -167,7 +171,7 @@ impl InputPin for EPin> { } } -impl EPin> { +impl ErasedPin> { #[inline(always)] pub fn is_high(&self) -> bool { !self.is_low() @@ -179,7 +183,7 @@ impl EPin> { } } -impl InputPin for EPin> { +impl InputPin for ErasedPin> { type Error = core::convert::Infallible; #[inline(always)] diff --git a/src/gpio/partially_erased.rs b/src/gpio/partially_erased.rs index fecf76a3..79f344c1 100644 --- a/src/gpio/partially_erased.rs +++ b/src/gpio/partially_erased.rs @@ -1,12 +1,17 @@ use super::*; +pub type PEPin = PartiallyErasedPin; + /// Partially erased pin -pub struct PEPin { +/// +/// - `MODE` is one of the pin modes (see [Modes](crate::gpio#modes) section). +/// - `P` is port name: `A` for GPIOA, `B` for GPIOB, etc. +pub struct PartiallyErasedPin { i: u8, _mode: PhantomData, } -impl PEPin { +impl PartiallyErasedPin { pub(crate) fn new(i: u8) -> Self { Self { i, @@ -15,7 +20,7 @@ impl PEPin { } } -impl PinExt for PEPin { +impl PinExt for PartiallyErasedPin { type Mode = MODE; #[inline(always)] @@ -28,7 +33,7 @@ impl PinExt for PEPin { } } -impl PEPin, P> { +impl PartiallyErasedPin, P> { #[inline(always)] pub fn set_high(&mut self) { // NOTE(unsafe) atomic write to a stateless register @@ -83,7 +88,7 @@ impl PEPin, P> { } } -impl OutputPin for PEPin, P> { +impl OutputPin for PartiallyErasedPin, P> { type Error = Infallible; #[inline(always)] @@ -99,7 +104,7 @@ impl OutputPin for PEPin, P> { } } -impl StatefulOutputPin for PEPin, P> { +impl StatefulOutputPin for PartiallyErasedPin, P> { #[inline(always)] fn is_set_high(&self) -> Result { Ok(self.is_set_high()) @@ -111,7 +116,7 @@ impl StatefulOutputPin for PEPin, P> { } } -impl ToggleableOutputPin for PEPin, P> { +impl ToggleableOutputPin for PartiallyErasedPin, P> { type Error = Infallible; #[inline(always)] @@ -121,7 +126,7 @@ impl ToggleableOutputPin for PEPin, P> { } } -impl PEPin, P> { +impl PartiallyErasedPin, P> { #[inline(always)] pub fn is_high(&self) -> bool { !self.is_low() @@ -134,7 +139,7 @@ impl PEPin, P> { } } -impl InputPin for PEPin, P> { +impl InputPin for PartiallyErasedPin, P> { type Error = Infallible; #[inline(always)] @@ -148,7 +153,7 @@ impl InputPin for PEPin, P> { } } -impl PEPin, P> { +impl PartiallyErasedPin, P> { #[inline(always)] pub fn is_high(&self) -> bool { !self.is_low() @@ -161,7 +166,7 @@ impl PEPin, P> { } } -impl InputPin for PEPin, P> { +impl InputPin for PartiallyErasedPin, P> { type Error = Infallible; #[inline(always)]