Skip to content

Commit ad969d2

Browse files
authored
Merge pull request #777 from stm32-rs/gpio-field-arrays
use GPIO pac fields instead of raw write
2 parents ae82c7b + 8c9fe0c commit ad969d2

File tree

3 files changed

+60
-49
lines changed

3 files changed

+60
-49
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2020

2121
- Bump MSRV to 1.62
2222
- Use `stm32f4-staging` until `stm32f4` is released [#706]
23+
- use GPIO pac fields instead of raw write
2324
- RTIC2 monotonics fix: CC1 instead of CC3
2425
- Allow different lengths of buffers in hal_1 SpiBus impl [#566]
2526
- Clean SPI write impls

src/gpio.rs

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
5757
use core::marker::PhantomData;
5858

59+
use crate::pac;
5960
pub mod alt;
6061
mod convert;
6162
pub use convert::PinMode;
@@ -115,7 +116,7 @@ pub struct Alternate<const A: u8, Otype = PushPull>(PhantomData<Otype>);
115116
pub struct Input;
116117

117118
/// Pull setting for an input.
118-
#[derive(Debug, Eq, PartialEq)]
119+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
119120
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
120121
pub enum Pull {
121122
/// Floating
@@ -126,6 +127,16 @@ pub enum Pull {
126127
Down = 2,
127128
}
128129

130+
impl From<Pull> for pac::gpioa::pupdr::PUPDR0 {
131+
fn from(value: Pull) -> Self {
132+
match value {
133+
Pull::Down => Self::PullDown,
134+
Pull::Up => Self::PullUp,
135+
Pull::None => Self::Floating,
136+
}
137+
}
138+
}
139+
129140
/// Open drain input or output (type state)
130141
#[derive(Debug, Default)]
131142
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -195,6 +206,17 @@ pub enum Speed {
195206
VeryHigh = 3,
196207
}
197208

209+
impl From<Speed> for pac::gpioa::ospeedr::OSPEEDR0 {
210+
fn from(value: Speed) -> Self {
211+
match value {
212+
Speed::Low => Self::LowSpeed,
213+
Speed::Medium => Self::MediumSpeed,
214+
Speed::High => Self::HighSpeed,
215+
Speed::VeryHigh => Self::VeryHighSpeed,
216+
}
217+
}
218+
}
219+
198220
/// GPIO interrupt trigger edge selection
199221
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
200222
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
@@ -318,13 +340,9 @@ where
318340
{
319341
/// Set pin speed
320342
pub fn set_speed(&mut self, speed: Speed) {
321-
let offset = 2 * { N };
322-
323-
unsafe {
324-
(*gpiox::<P>())
325-
.ospeedr()
326-
.modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | ((speed as u32) << offset)));
327-
}
343+
unsafe { &(*gpiox::<P>()) }
344+
.ospeedr()
345+
.modify(|_, w| w.ospeedr(N).variant(speed.into()));
328346
}
329347

330348
/// Set pin speed
@@ -350,13 +368,9 @@ where
350368
{
351369
/// Set the internal pull-up and pull-down resistor
352370
pub fn set_internal_resistor(&mut self, resistor: Pull) {
353-
let offset = 2 * { N };
354-
let value = resistor as u32;
355-
unsafe {
356-
(*gpiox::<P>())
357-
.pupdr()
358-
.modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset)));
359-
}
371+
unsafe { &(*gpiox::<P>()) }
372+
.pupdr()
373+
.modify(|_, w| w.pupdr(N).variant(resistor.into()));
360374
}
361375

362376
/// Set the internal pull-up and pull-down resistor
@@ -435,22 +449,26 @@ impl<const P: char, const N: u8, MODE> Pin<P, N, MODE> {
435449
#[inline(always)]
436450
fn _set_high(&mut self) {
437451
// NOTE(unsafe) atomic write to a stateless register
438-
unsafe { (*gpiox::<P>()).bsrr().write(|w| w.bits(1 << N)) }
452+
let gpio = unsafe { &(*gpiox::<P>()) };
453+
gpio.bsrr().write(|w| w.bs(N).set_bit())
439454
}
440455
#[inline(always)]
441456
fn _set_low(&mut self) {
442457
// NOTE(unsafe) atomic write to a stateless register
443-
unsafe { (*gpiox::<P>()).bsrr().write(|w| w.bits(1 << (16 + N))) }
458+
let gpio = unsafe { &(*gpiox::<P>()) };
459+
gpio.bsrr().write(|w| w.br(N).set_bit())
444460
}
445461
#[inline(always)]
446462
fn _is_set_low(&self) -> bool {
447463
// NOTE(unsafe) atomic read with no side effects
448-
unsafe { (*gpiox::<P>()).odr().read().bits() & (1 << N) == 0 }
464+
let gpio = unsafe { &(*gpiox::<P>()) };
465+
gpio.odr().read().odr(N).bit_is_clear()
449466
}
450467
#[inline(always)]
451468
fn _is_low(&self) -> bool {
452469
// NOTE(unsafe) atomic read with no side effects
453-
unsafe { (*gpiox::<P>()).idr().read().bits() & (1 << N) == 0 }
470+
let gpio = unsafe { &(*gpiox::<P>()) };
471+
gpio.idr().read().idr(N).bit_is_clear()
454472
}
455473
}
456474

src/gpio/convert.rs

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::*;
2+
use crate::pac::gpioa::{moder::MODER0 as Mode, otyper::OT0 as OutputType};
23

34
impl<const P: char, const N: u8, const A: u8> Pin<P, N, Alternate<A, PushPull>> {
45
/// Turns pin alternate configuration pin into open drain
@@ -110,36 +111,27 @@ impl<const P: char, const N: u8, MODE: PinMode> Pin<P, N, MODE> {
110111

111112
macro_rules! change_mode {
112113
($block:expr, $N:ident) => {
113-
let offset = 2 * $N;
114114
unsafe {
115115
if MODE::OTYPER != M::OTYPER {
116116
if let Some(otyper) = M::OTYPER {
117-
$block
118-
.otyper()
119-
.modify(|r, w| w.bits(r.bits() & !(0b1 << $N) | (otyper << $N)));
117+
$block.otyper().modify(|_, w| w.ot($N).variant(otyper));
120118
}
121119
}
122120

123121
if MODE::AFR != M::AFR {
124122
if let Some(afr) = M::AFR {
125123
if $N < 8 {
126-
let offset2 = 4 * { $N };
127-
$block.afrl().modify(|r, w| {
128-
w.bits((r.bits() & !(0b1111 << offset2)) | (afr << offset2))
129-
});
124+
$block.afrl().modify(|_, w| w.afr($N).bits(afr));
130125
} else {
131-
let offset2 = 4 * { $N - 8 };
132-
$block.afrh().modify(|r, w| {
133-
w.bits((r.bits() & !(0b1111 << offset2)) | (afr << offset2))
134-
});
126+
$block.afrh().modify(|_, w| w.afr($N - 8).bits(afr));
135127
}
136128
}
137129
}
138130

139131
if MODE::MODER != M::MODER {
140-
$block
141-
.moder()
142-
.modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (M::MODER << offset)));
132+
if let Some(mode) = M::MODER {
133+
$block.moder().modify(|_, w| w.moder($N).variant(mode));
134+
}
143135
}
144136
}
145137
};
@@ -300,43 +292,43 @@ pub trait PinMode: crate::Sealed {
300292
// They are not part of public API.
301293

302294
#[doc(hidden)]
303-
const MODER: u32 = u32::MAX;
295+
const MODER: Option<Mode> = None;
304296
#[doc(hidden)]
305-
const OTYPER: Option<u32> = None;
297+
const OTYPER: Option<OutputType> = None;
306298
#[doc(hidden)]
307-
const AFR: Option<u32> = None;
299+
const AFR: Option<u8> = None;
308300
}
309301

310302
impl crate::Sealed for Input {}
311303
impl PinMode for Input {
312-
const MODER: u32 = 0b00;
304+
const MODER: Option<Mode> = Some(Mode::Input);
313305
}
314306

315307
impl crate::Sealed for Analog {}
316308
impl PinMode for Analog {
317-
const MODER: u32 = 0b11;
309+
const MODER: Option<Mode> = Some(Mode::Analog);
318310
}
319311

320312
impl<Otype> crate::Sealed for Output<Otype> {}
321313
impl PinMode for Output<OpenDrain> {
322-
const MODER: u32 = 0b01;
323-
const OTYPER: Option<u32> = Some(0b1);
314+
const MODER: Option<Mode> = Some(Mode::Output);
315+
const OTYPER: Option<OutputType> = Some(OutputType::OpenDrain);
324316
}
325317

326318
impl PinMode for Output<PushPull> {
327-
const MODER: u32 = 0b01;
328-
const OTYPER: Option<u32> = Some(0b0);
319+
const MODER: Option<Mode> = Some(Mode::Output);
320+
const OTYPER: Option<OutputType> = Some(OutputType::PushPull);
329321
}
330322

331323
impl<const A: u8, Otype> crate::Sealed for Alternate<A, Otype> {}
332324
impl<const A: u8> PinMode for Alternate<A, OpenDrain> {
333-
const MODER: u32 = 0b10;
334-
const OTYPER: Option<u32> = Some(0b1);
335-
const AFR: Option<u32> = Some(A as _);
325+
const MODER: Option<Mode> = Some(Mode::Alternate);
326+
const OTYPER: Option<OutputType> = Some(OutputType::OpenDrain);
327+
const AFR: Option<u8> = Some(A);
336328
}
337329

338330
impl<const A: u8> PinMode for Alternate<A, PushPull> {
339-
const MODER: u32 = 0b10;
340-
const OTYPER: Option<u32> = Some(0b0);
341-
const AFR: Option<u32> = Some(A as _);
331+
const MODER: Option<Mode> = Some(Mode::Alternate);
332+
const OTYPER: Option<OutputType> = Some(OutputType::PushPull);
333+
const AFR: Option<u8> = Some(A);
342334
}

0 commit comments

Comments
 (0)