Skip to content

Commit

Permalink
pin docs
Browse files Browse the repository at this point in the history
  • Loading branch information
burrbull committed Jul 24, 2021
1 parent cd89a77 commit f0ecbb6
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 26 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
54 changes: 51 additions & 3 deletions src/gpio.rs
Original file line number Diff line number Diff line change
@@ -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_<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.
use core::convert::Infallible;
use core::marker::PhantomData;
Expand All @@ -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;
Expand Down Expand Up @@ -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, const P: char, const N: u8> {
_mode: PhantomData<MODE>,
}
Expand Down
28 changes: 16 additions & 12 deletions src/gpio/erased.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
use super::*;

pub type EPin<MODE> = ErasedPin<MODE>;

/// Fully erased pin
pub struct EPin<MODE> {
///
/// `MODE` is one of the pin modes (see [Modes](crate::gpio#modes) section).
pub struct ErasedPin<MODE> {
// Bits 0-3: Pin, Bits 4-7: Port
pin_port: u8,
_mode: PhantomData<MODE>,
}

impl<MODE> PinExt for EPin<MODE> {
impl<MODE> PinExt for ErasedPin<MODE> {
type Mode = MODE;

#[inline(always)]
Expand All @@ -20,7 +24,7 @@ impl<MODE> PinExt for EPin<MODE> {
}
}

impl<MODE> EPin<MODE> {
impl<MODE> ErasedPin<MODE> {
pub(crate) fn new(port: u8, pin: u8) -> Self {
Self {
pin_port: port << 4 | pin,
Expand All @@ -36,7 +40,7 @@ impl<MODE> EPin<MODE> {
// - 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;
Expand All @@ -49,7 +53,7 @@ impl<MODE> EPin<MODE> {
}
}

impl<MODE> EPin<Output<MODE>> {
impl<MODE> ErasedPin<Output<MODE>> {
#[inline(always)]
pub fn set_high(&mut self) {
// NOTE(unsafe) atomic write to a stateless register
Expand Down Expand Up @@ -103,7 +107,7 @@ impl<MODE> EPin<Output<MODE>> {
}
}

impl<MODE> OutputPin for EPin<Output<MODE>> {
impl<MODE> OutputPin for ErasedPin<Output<MODE>> {
type Error = core::convert::Infallible;

#[inline(always)]
Expand All @@ -119,7 +123,7 @@ impl<MODE> OutputPin for EPin<Output<MODE>> {
}
}

impl<MODE> StatefulOutputPin for EPin<Output<MODE>> {
impl<MODE> StatefulOutputPin for ErasedPin<Output<MODE>> {
#[inline(always)]
fn is_set_high(&self) -> Result<bool, Self::Error> {
Ok(self.is_set_high())
Expand All @@ -131,7 +135,7 @@ impl<MODE> StatefulOutputPin for EPin<Output<MODE>> {
}
}

impl<MODE> ToggleableOutputPin for EPin<Output<MODE>> {
impl<MODE> ToggleableOutputPin for ErasedPin<Output<MODE>> {
type Error = Infallible;

#[inline(always)]
Expand All @@ -141,7 +145,7 @@ impl<MODE> ToggleableOutputPin for EPin<Output<MODE>> {
}
}

impl EPin<Output<OpenDrain>> {
impl ErasedPin<Output<OpenDrain>> {
#[inline(always)]
pub fn is_high(&self) -> bool {
!self.is_low()
Expand All @@ -153,7 +157,7 @@ impl EPin<Output<OpenDrain>> {
}
}

impl InputPin for EPin<Output<OpenDrain>> {
impl InputPin for ErasedPin<Output<OpenDrain>> {
type Error = core::convert::Infallible;

#[inline(always)]
Expand All @@ -167,7 +171,7 @@ impl InputPin for EPin<Output<OpenDrain>> {
}
}

impl<MODE> EPin<Input<MODE>> {
impl<MODE> ErasedPin<Input<MODE>> {
#[inline(always)]
pub fn is_high(&self) -> bool {
!self.is_low()
Expand All @@ -179,7 +183,7 @@ impl<MODE> EPin<Input<MODE>> {
}
}

impl<MODE> InputPin for EPin<Input<MODE>> {
impl<MODE> InputPin for ErasedPin<Input<MODE>> {
type Error = core::convert::Infallible;

#[inline(always)]
Expand Down
27 changes: 16 additions & 11 deletions src/gpio/partially_erased.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
use super::*;

pub type PEPin<MODE, const P: char> = PartiallyErasedPin<MODE, P>;

/// Partially erased pin
pub struct PEPin<MODE, const P: char> {
///
/// - `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<MODE, const P: char> {
i: u8,
_mode: PhantomData<MODE>,
}

impl<MODE, const P: char> PEPin<MODE, P> {
impl<MODE, const P: char> PartiallyErasedPin<MODE, P> {
pub(crate) fn new(i: u8) -> Self {
Self {
i,
Expand All @@ -15,7 +20,7 @@ impl<MODE, const P: char> PEPin<MODE, P> {
}
}

impl<MODE, const P: char> PinExt for PEPin<MODE, P> {
impl<MODE, const P: char> PinExt for PartiallyErasedPin<MODE, P> {
type Mode = MODE;

#[inline(always)]
Expand All @@ -28,7 +33,7 @@ impl<MODE, const P: char> PinExt for PEPin<MODE, P> {
}
}

impl<MODE, const P: char> PEPin<Output<MODE>, P> {
impl<MODE, const P: char> PartiallyErasedPin<Output<MODE>, P> {
#[inline(always)]
pub fn set_high(&mut self) {
// NOTE(unsafe) atomic write to a stateless register
Expand Down Expand Up @@ -83,7 +88,7 @@ impl<MODE, const P: char> PEPin<Output<MODE>, P> {
}
}

impl<MODE, const P: char> OutputPin for PEPin<Output<MODE>, P> {
impl<MODE, const P: char> OutputPin for PartiallyErasedPin<Output<MODE>, P> {
type Error = Infallible;

#[inline(always)]
Expand All @@ -99,7 +104,7 @@ impl<MODE, const P: char> OutputPin for PEPin<Output<MODE>, P> {
}
}

impl<MODE, const P: char> StatefulOutputPin for PEPin<Output<MODE>, P> {
impl<MODE, const P: char> StatefulOutputPin for PartiallyErasedPin<Output<MODE>, P> {
#[inline(always)]
fn is_set_high(&self) -> Result<bool, Self::Error> {
Ok(self.is_set_high())
Expand All @@ -111,7 +116,7 @@ impl<MODE, const P: char> StatefulOutputPin for PEPin<Output<MODE>, P> {
}
}

impl<MODE, const P: char> ToggleableOutputPin for PEPin<Output<MODE>, P> {
impl<MODE, const P: char> ToggleableOutputPin for PartiallyErasedPin<Output<MODE>, P> {
type Error = Infallible;

#[inline(always)]
Expand All @@ -121,7 +126,7 @@ impl<MODE, const P: char> ToggleableOutputPin for PEPin<Output<MODE>, P> {
}
}

impl<const P: char> PEPin<Output<OpenDrain>, P> {
impl<const P: char> PartiallyErasedPin<Output<OpenDrain>, P> {
#[inline(always)]
pub fn is_high(&self) -> bool {
!self.is_low()
Expand All @@ -134,7 +139,7 @@ impl<const P: char> PEPin<Output<OpenDrain>, P> {
}
}

impl<const P: char> InputPin for PEPin<Output<OpenDrain>, P> {
impl<const P: char> InputPin for PartiallyErasedPin<Output<OpenDrain>, P> {
type Error = Infallible;

#[inline(always)]
Expand All @@ -148,7 +153,7 @@ impl<const P: char> InputPin for PEPin<Output<OpenDrain>, P> {
}
}

impl<MODE, const P: char> PEPin<Input<MODE>, P> {
impl<MODE, const P: char> PartiallyErasedPin<Input<MODE>, P> {
#[inline(always)]
pub fn is_high(&self) -> bool {
!self.is_low()
Expand All @@ -161,7 +166,7 @@ impl<MODE, const P: char> PEPin<Input<MODE>, P> {
}
}

impl<MODE, const P: char> InputPin for PEPin<Input<MODE>, P> {
impl<MODE, const P: char> InputPin for PartiallyErasedPin<Input<MODE>, P> {
type Error = Infallible;

#[inline(always)]
Expand Down

0 comments on commit f0ecbb6

Please sign in to comment.