Skip to content

Commit

Permalink
Merge #359
Browse files Browse the repository at this point in the history
359: Convert ResetMode to own witness pin and track past pin mode r=richardeoin a=jg2562

Previously when resetting it would assume the pin was in the ORIG pin mode and try to convert it to the ORIG pin mode, which the if statements in mode blocked. Now by tracking the witness pin and the original MODE the reset can properly set the mode register bits.

By fixing ResetMode it allows for the `with_<mode>` methods to work and set the MODER bits. Fixes #358.

Since I've fairly new to heavy generics and microcontroller level optimization, it would be really great if someone could double-check that this doesn't break anything the previous implementation upheld! Thank you!

Co-authored-by: Jack Garrard <jg2562@nau.edu>
Co-authored-by: Richard Meadows <962920+richardeoin@users.noreply.github.com>
  • Loading branch information
3 people authored Apr 24, 2022
2 parents 216835d + 738d6ed commit 96b64ab
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 10 deletions.
58 changes: 58 additions & 0 deletions examples/gpio_with_input.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//! Demonstrates the use of the GPIO method `with_input` (and similar methods)
//!
//! https://docs.rs/stm32h7xx-hal/latest/stm32h7xx_hal/gpio/struct.Pin.html#method.with_input
#![deny(warnings)]
#![no_main]
#![no_std]

use cortex_m_rt::entry;

use stm32h7xx_hal::{pac, prelude::*};

use log::info;

#[macro_use]
mod utilities;

#[entry]
fn main() -> ! {
utilities::logger::init();
let cp = cortex_m::Peripherals::take().unwrap();
let dp = pac::Peripherals::take().unwrap();

// Constrain and Freeze power
info!("Setup PWR... ");
let pwr = dp.PWR.constrain();
let pwrcfg = example_power!(pwr).freeze();

// Constrain and Freeze clock
info!("Setup RCC... ");
let rcc = dp.RCC.constrain();
let ccdr = rcc.sys_ck(100.MHz()).freeze(pwrcfg, &dp.SYSCFG);

info!("");
info!("stm32h7xx-hal example - GPIO with_input");
info!("");

let gpioe = dp.GPIOE.split(ccdr.peripheral.GPIOE);

// Configure PE1 as output.
let mut led = gpioe.pe1.into_push_pull_output();

// Get the delay provider.
let mut delay = cp.SYST.delay(ccdr.clocks);

loop {
loop {
led.set_high();
delay.delay_ms(100_u16);

led.set_low();
delay.delay_ms(100_u16);

let is_high = led.with_input(|x| x.is_high());
info!("LED pin high? {}", is_high);
}
}
}
29 changes: 19 additions & 10 deletions src/gpio/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,15 +318,13 @@ where
M: PinMode,
F: FnOnce(&mut Pin<P, N, M>) -> R,
{
self.mode::<M>();
self.mode::<M>(); // change physical mode, without changing typestate

// This will reset the pin back to the original mode when dropped.
// (so either when `with_mode` returns or when `f` unwinds)
let _resetti = ResetMode { pin: self };

let mut witness = Pin::new();
let mut resetti = ResetMode::<P, N, M, MODE>::new();

f(&mut witness)
f(&mut resetti.pin)
}

/// Temporarily configures this pin as a input.
Expand Down Expand Up @@ -410,12 +408,23 @@ where
}
}

struct ResetMode<'a, const P: char, const N: u8, ORIG: PinMode> {
pin: &'a mut Pin<P, N, ORIG>,
/// Wrapper around a pin that transitions the pin to mode ORIG when dropped
struct ResetMode<const P: char, const N: u8, CURRENT: PinMode, ORIG: PinMode> {
pub pin: Pin<P, N, CURRENT>,
_mode: PhantomData<ORIG>,
}

impl<'a, const P: char, const N: u8, ORIG: PinMode> Drop
for ResetMode<'a, P, N, ORIG>
impl<const P: char, const N: u8, CURRENT: PinMode, ORIG: PinMode>
ResetMode<P, N, CURRENT, ORIG>
{
fn new() -> Self {
Self {
pin: Pin::new(),
_mode: PhantomData,
}
}
}
impl<const P: char, const N: u8, CURRENT: PinMode, ORIG: PinMode> Drop
for ResetMode<P, N, CURRENT, ORIG>
{
fn drop(&mut self) {
self.pin.mode::<ORIG>();
Expand Down

0 comments on commit 96b64ab

Please sign in to comment.