From 8c9fe0c5e9deafef514b1ddd94aeb9d37f95ba65 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Sat, 27 Jul 2024 11:55:53 +0300 Subject: [PATCH] use GPIO pac fields instead of raw write --- CHANGELOG.md | 1 + src/gpio.rs | 56 ++++++++++++++++++++++++++++++--------------- src/gpio/convert.rs | 52 ++++++++++++++++++----------------------- 3 files changed, 60 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e07e4638..a983a0e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed - Use `stm32f4-staging` until `stm32f4` is released [#706] + - use GPIO pac fields instead of raw write - RTIC2 monotonics fix: CC1 instead of CC3 - Allow different lengths of buffers in hal_1 SpiBus impl [#566] - Clean SPI write impls diff --git a/src/gpio.rs b/src/gpio.rs index 2fa1a4a0..f01f38f3 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -56,6 +56,7 @@ use core::marker::PhantomData; +use crate::pac; pub mod alt; mod convert; pub use convert::PinMode; @@ -115,7 +116,7 @@ pub struct Alternate(PhantomData); pub struct Input; /// Pull setting for an input. -#[derive(Debug, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Pull { /// Floating @@ -126,6 +127,16 @@ pub enum Pull { Down = 2, } +impl From for pac::gpioa::pupdr::PUPDR0 { + fn from(value: Pull) -> Self { + match value { + Pull::Down => Self::PullDown, + Pull::Up => Self::PullUp, + Pull::None => Self::Floating, + } + } +} + /// Open drain input or output (type state) #[derive(Debug, Default)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -195,6 +206,17 @@ pub enum Speed { VeryHigh = 3, } +impl From for pac::gpioa::ospeedr::OSPEEDR0 { + fn from(value: Speed) -> Self { + match value { + Speed::Low => Self::LowSpeed, + Speed::Medium => Self::MediumSpeed, + Speed::High => Self::HighSpeed, + Speed::VeryHigh => Self::VeryHighSpeed, + } + } +} + /// GPIO interrupt trigger edge selection #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -318,13 +340,9 @@ where { /// Set pin speed pub fn set_speed(&mut self, speed: Speed) { - let offset = 2 * { N }; - - unsafe { - (*gpiox::

()) - .ospeedr() - .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | ((speed as u32) << offset))); - } + unsafe { &(*gpiox::

()) } + .ospeedr() + .modify(|_, w| w.ospeedr(N).variant(speed.into())); } /// Set pin speed @@ -350,13 +368,9 @@ where { /// Set the internal pull-up and pull-down resistor pub fn set_internal_resistor(&mut self, resistor: Pull) { - let offset = 2 * { N }; - let value = resistor as u32; - unsafe { - (*gpiox::

()) - .pupdr() - .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); - } + unsafe { &(*gpiox::

()) } + .pupdr() + .modify(|_, w| w.pupdr(N).variant(resistor.into())); } /// Set the internal pull-up and pull-down resistor @@ -435,22 +449,26 @@ impl Pin { #[inline(always)] fn _set_high(&mut self) { // NOTE(unsafe) atomic write to a stateless register - unsafe { (*gpiox::

()).bsrr().write(|w| w.bits(1 << N)) } + let gpio = unsafe { &(*gpiox::

()) }; + gpio.bsrr().write(|w| w.bs(N).set_bit()) } #[inline(always)] fn _set_low(&mut self) { // NOTE(unsafe) atomic write to a stateless register - unsafe { (*gpiox::

()).bsrr().write(|w| w.bits(1 << (16 + N))) } + let gpio = unsafe { &(*gpiox::

()) }; + gpio.bsrr().write(|w| w.br(N).set_bit()) } #[inline(always)] fn _is_set_low(&self) -> bool { // NOTE(unsafe) atomic read with no side effects - unsafe { (*gpiox::

()).odr().read().bits() & (1 << N) == 0 } + let gpio = unsafe { &(*gpiox::

()) }; + gpio.odr().read().odr(N).bit_is_clear() } #[inline(always)] fn _is_low(&self) -> bool { // NOTE(unsafe) atomic read with no side effects - unsafe { (*gpiox::

()).idr().read().bits() & (1 << N) == 0 } + let gpio = unsafe { &(*gpiox::

()) }; + gpio.idr().read().idr(N).bit_is_clear() } } diff --git a/src/gpio/convert.rs b/src/gpio/convert.rs index caa3a5e9..eaf303f9 100644 --- a/src/gpio/convert.rs +++ b/src/gpio/convert.rs @@ -1,4 +1,5 @@ use super::*; +use crate::pac::gpioa::{moder::MODER0 as Mode, otyper::OT0 as OutputType}; impl Pin> { /// Turns pin alternate configuration pin into open drain @@ -110,36 +111,27 @@ impl Pin { macro_rules! change_mode { ($block:expr, $N:ident) => { - let offset = 2 * $N; unsafe { if MODE::OTYPER != M::OTYPER { if let Some(otyper) = M::OTYPER { - $block - .otyper() - .modify(|r, w| w.bits(r.bits() & !(0b1 << $N) | (otyper << $N))); + $block.otyper().modify(|_, w| w.ot($N).variant(otyper)); } } if MODE::AFR != M::AFR { if let Some(afr) = M::AFR { if $N < 8 { - let offset2 = 4 * { $N }; - $block.afrl().modify(|r, w| { - w.bits((r.bits() & !(0b1111 << offset2)) | (afr << offset2)) - }); + $block.afrl().modify(|_, w| w.afr($N).bits(afr)); } else { - let offset2 = 4 * { $N - 8 }; - $block.afrh().modify(|r, w| { - w.bits((r.bits() & !(0b1111 << offset2)) | (afr << offset2)) - }); + $block.afrh().modify(|_, w| w.afr($N - 8).bits(afr)); } } } if MODE::MODER != M::MODER { - $block - .moder() - .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (M::MODER << offset))); + if let Some(mode) = M::MODER { + $block.moder().modify(|_, w| w.moder($N).variant(mode)); + } } } }; @@ -300,43 +292,43 @@ pub trait PinMode: crate::Sealed { // They are not part of public API. #[doc(hidden)] - const MODER: u32 = u32::MAX; + const MODER: Option = None; #[doc(hidden)] - const OTYPER: Option = None; + const OTYPER: Option = None; #[doc(hidden)] - const AFR: Option = None; + const AFR: Option = None; } impl crate::Sealed for Input {} impl PinMode for Input { - const MODER: u32 = 0b00; + const MODER: Option = Some(Mode::Input); } impl crate::Sealed for Analog {} impl PinMode for Analog { - const MODER: u32 = 0b11; + const MODER: Option = Some(Mode::Analog); } impl crate::Sealed for Output {} impl PinMode for Output { - const MODER: u32 = 0b01; - const OTYPER: Option = Some(0b1); + const MODER: Option = Some(Mode::Output); + const OTYPER: Option = Some(OutputType::OpenDrain); } impl PinMode for Output { - const MODER: u32 = 0b01; - const OTYPER: Option = Some(0b0); + const MODER: Option = Some(Mode::Output); + const OTYPER: Option = Some(OutputType::PushPull); } impl crate::Sealed for Alternate {} impl PinMode for Alternate { - const MODER: u32 = 0b10; - const OTYPER: Option = Some(0b1); - const AFR: Option = Some(A as _); + const MODER: Option = Some(Mode::Alternate); + const OTYPER: Option = Some(OutputType::OpenDrain); + const AFR: Option = Some(A); } impl PinMode for Alternate { - const MODER: u32 = 0b10; - const OTYPER: Option = Some(0b0); - const AFR: Option = Some(A as _); + const MODER: Option = Some(Mode::Alternate); + const OTYPER: Option = Some(OutputType::PushPull); + const AFR: Option = Some(A); }