From 1044becc8de4deb5fe667e0782c6cf34c3cff8fb Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Wed, 2 Mar 2022 19:42:16 +0300 Subject: [PATCH] PinMode on MODE --- CHANGELOG.md | 2 + src/gpio.rs | 220 ++++++++++++++++++--------------------------------- 2 files changed, 79 insertions(+), 143 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5286a830..6df90557 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +- `gpio`: port and pin generics first, then mode, `PinMode` for modes instead of pins + ## [v0.9.0] - 2022-03-02 ### Added diff --git a/src/gpio.rs b/src/gpio.rs index 3e5da2f7..eb9fee9c 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -107,8 +107,8 @@ pub trait PinExt { /// Allow setting of the slew rate of an IO pin /// /// Initially all pins are set to the maximum slew rate -pub trait OutputSpeed { - fn set_speed(&mut self, cr: &mut CR, speed: IOPinSpeed); +pub trait OutputSpeed { + fn set_speed(&mut self, cr: &mut Cr, speed: IOPinSpeed); } /// Extension trait to split a GPIO peripheral in independent pins and registers @@ -181,8 +181,10 @@ mod sealed { pub trait Interruptable {} pub trait PinMode { - type CR; - fn set_mode(cr: &mut Self::CR) -> Self; + const CNF: u32; + const MODE: u32; + const PULL: Option = None; + fn new() -> Self; } } use sealed::PinMode; @@ -809,8 +811,7 @@ macro_rules! impl_temp_input { impl Pin where - MODE: Active, - Self: PinMode>, + MODE: Active + PinMode, { impl_temp_output!( as_push_pull_output, @@ -827,7 +828,7 @@ where impl_temp_input!(as_pull_down_input, Input); } -impl OutputSpeed> +impl OutputSpeed for Pin> { fn set_speed(&mut self, _cr: &mut Cr, speed: IOPinSpeed) { @@ -844,7 +845,7 @@ impl OutputSpeed> } } -impl OutputSpeed> +impl OutputSpeed for Pin> { fn set_speed(&mut self, _cr: &mut Cr, speed: IOPinSpeed) { @@ -896,167 +897,100 @@ impl Pin { } } -macro_rules! mode { - ($gpio:ident, $bits:ident) => { - if H { - $gpio.crh.modify(|r, w| unsafe { - w.bits((r.bits() & !(0b1111 << Self::OFFSET)) | ($bits << Self::OFFSET)) - }); - } else { - $gpio.crl.modify(|r, w| unsafe { - w.bits((r.bits() & !(0b1111 << Self::OFFSET)) | ($bits << Self::OFFSET)) - }); - } - }; +impl PinMode for Input { + const CNF: u32 = 0b01; + const MODE: u32 = 0b00; + fn new() -> Self { + Self::_new() + } } -impl PinMode for Pin> { - type CR = Cr; - - fn set_mode(_cr: &mut Self::CR) -> Self { - // Floating input - const CNF: u32 = 0b01; - // Input mode - const MODE: u32 = 0b00; - const BITS: u32 = (CNF << 2) | MODE; - - // input mode - let gpio = unsafe { &(*Gpio::

::ptr()) }; - mode!(gpio, BITS); - - Self::new(Input::_new()) +impl PinMode for Input { + const CNF: u32 = 0b10; + const MODE: u32 = 0b00; + const PULL: Option = Some(false); + fn new() -> Self { + Self::_new() } } -impl PinMode for Pin> { - type CR = Cr; - - fn set_mode(_cr: &mut Self::CR) -> Self { - // Pull up/down input - const CNF: u32 = 0b10; - // Input mode - const MODE: u32 = 0b00; - const BITS: u32 = (CNF << 2) | MODE; - - let gpio = unsafe { &(*Gpio::

::ptr()) }; - //pull down: - // NOTE(unsafe) atomic write to a stateless register - gpio.bsrr.write(|w| unsafe { w.bits(1 << (16 + N)) }); - - // input mode - mode!(gpio, BITS); - - Self::new(Input::_new()) +impl PinMode for Input { + const CNF: u32 = 0b10; + const MODE: u32 = 0b00; + const PULL: Option = Some(true); + fn new() -> Self { + Self::_new() } } -impl PinMode for Pin> { - type CR = Cr; - - fn set_mode(_cr: &mut Self::CR) -> Self { - // Pull up/down input - const CNF: u32 = 0b10; - // Input mode - const MODE: u32 = 0b00; - const BITS: u32 = (CNF << 2) | MODE; - - let gpio = unsafe { &(*Gpio::

::ptr()) }; - //pull up: - // NOTE(unsafe) atomic write to a stateless register - gpio.bsrr.write(|w| unsafe { w.bits(1 << N) }); - - // input mode - mode!(gpio, BITS); - - Self::new(Input::_new()) +impl PinMode for Output { + const CNF: u32 = 0b01; + const MODE: u32 = 0b11; + fn new() -> Self { + Self::_new() } } -impl PinMode for Pin> { - type CR = Cr; - - fn set_mode(_cr: &mut Self::CR) -> Self { - // General purpose output open-drain - const CNF: u32 = 0b01; - // Open-Drain Output mode, max speed 50 MHz - const MODE: u32 = 0b11; - const BITS: u32 = (CNF << 2) | MODE; - - let gpio = unsafe { &(*Gpio::

::ptr()) }; - mode!(gpio, BITS); - - Self::new(Output::_new()) +impl PinMode for Output { + const CNF: u32 = 0b00; + const MODE: u32 = 0b11; + fn new() -> Self { + Self::_new() } } -impl PinMode for Pin> { - type CR = Cr; - - fn set_mode(_cr: &mut Self::CR) -> Self { - // General purpose output push-pull - const CNF: u32 = 0b00; - // Output mode, max speed 50 MHz - const MODE: u32 = 0b11; - const BITS: u32 = (CNF << 2) | MODE; - - let gpio = unsafe { &(*Gpio::

::ptr()) }; - mode!(gpio, BITS); - - Self::new(Output::_new()) +impl PinMode for Analog { + const CNF: u32 = 0b00; + const MODE: u32 = 0b00; + fn new() -> Self { + Self {} } } -impl PinMode for Pin { - type CR = Cr; - - fn set_mode(_cr: &mut Self::CR) -> Self { - // Analog input - const CNF: u32 = 0b00; - // Input mode - const MODE: u32 = 0b00; - const BITS: u32 = (CNF << 2) | MODE; - - // analog mode - let gpio = unsafe { &(*Gpio::

::ptr()) }; - mode!(gpio, BITS); - - Self::new(Analog {}) +impl PinMode for Alternate { + const CNF: u32 = 0b10; + const MODE: u32 = 0b11; + fn new() -> Self { + Self::_new() } } -impl PinMode for Pin> { - type CR = Cr; - - fn set_mode(_cr: &mut Self::CR) -> Self { - // Alternate function output push pull - const CNF: u32 = 0b10; - // Output mode, max speed 50 MHz - const MODE: u32 = 0b11; - const BITS: u32 = (CNF << 2) | MODE; - - // input mode - let gpio = unsafe { &(*Gpio::

::ptr()) }; - mode!(gpio, BITS); - - Pin::new(Alternate::_new()) +impl PinMode for Alternate { + const CNF: u32 = 0b11; + const MODE: u32 = 0b11; + fn new() -> Self { + Self::_new() } } -impl PinMode for Pin> { - type CR = Cr; - - fn set_mode(_cr: &mut Self::CR) -> Self { - // Alternate function output open drain - const CNF: u32 = 0b11; - // Output mode, max speed 50 MHz - const MODE: u32 = 0b11; - const BITS: u32 = (CNF << 2) | MODE; - +impl Pin +where + MODE: PinMode, +{ + fn set_mode(_cr: &mut Cr) -> Self { // input mode let gpio = unsafe { &(*Gpio::

::ptr()) }; - mode!(gpio, BITS); + if let Some(pull) = MODE::PULL { + if pull { + gpio.bsrr.write(|w| unsafe { w.bits(1 << N) }); + } else { + gpio.bsrr.write(|w| unsafe { w.bits(1 << (16 + N)) }); + } + } + + let bits = (MODE::CNF << 2) | MODE::MODE; + + if H { + gpio.crh.modify(|r, w| unsafe { + w.bits((r.bits() & !(0b1111 << Self::OFFSET)) | (bits << Self::OFFSET)) + }); + } else { + gpio.crl.modify(|r, w| unsafe { + w.bits((r.bits() & !(0b1111 << Self::OFFSET)) | (bits << Self::OFFSET)) + }); + } - Pin::new(Alternate::_new()) + Pin::new(MODE::new()) } }