Skip to content

Commit 6a1767e

Browse files
committed
gpio: introduce AfType + unified Pin::set_as_af + Speed::to_mode
Mirrors embassy-stm32 gpio_v1's `AfType` struct and the `set_as_af` method on `SealedPin`. Drivers can now express any pin direction (input-with-pull, output push-pull, output open-drain) as a single `AfType` value built via `AfType::input(pull)` or `AfType::output(output_type, speed)`, and feed it through one `set_as_af()` call instead of juggling `set_as_af_output(AFType, Speed)` + `set_as_input(Pull)` plus a separate `afio_remap()` call. `Speed::to_mode()` is added as a const helper so `AfType::output` can stay `const fn`. The pre-existing `From<Speed> for vals::Mode` now delegates to it. Drops the previous `From<AFType> for vals::Cnf` direction-overloaded constants in favor of the explicit `AfType::output` constructor. The old `set_as_af_output`/`set_as_input` methods remain for backwards compatibility but new code should reach for `set_as_af` via the `new_pin!` / `set_as_af!` macros added in the next commit.
1 parent 817ea75 commit 6a1767e

1 file changed

Lines changed: 66 additions & 12 deletions

File tree

src/gpio.rs

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,29 @@ pub enum Speed {
3333
High = 0b11,
3434
}
3535

36-
#[cfg(any(gpio_v3, gpio_v0))]
37-
impl From<Speed> for vals::Mode {
38-
fn from(value: Speed) -> Self {
39-
use Speed::*;
40-
41-
match value {
42-
Medium => vals::Mode::OUTPUT_10MHZ,
43-
Low => vals::Mode::OUTPUT_2MHZ,
44-
High => vals::Mode::OUTPUT_50MHZ,
36+
impl Speed {
37+
/// Compile-time conversion to the `MODEy` field value, family-aware.
38+
/// gpio_x0 collapses every speed to OUTPUT_50MHZ — its GPIO doesn't
39+
/// expose the slower modes.
40+
#[cfg(any(gpio_v3, gpio_v0))]
41+
pub const fn to_mode(self) -> vals::Mode {
42+
match self {
43+
Speed::Medium => vals::Mode::OUTPUT_10MHZ,
44+
Speed::Low => vals::Mode::OUTPUT_2MHZ,
45+
Speed::High => vals::Mode::OUTPUT_50MHZ,
4546
}
4647
}
48+
49+
#[cfg(gpio_x0)]
50+
pub const fn to_mode(self) -> vals::Mode {
51+
vals::Mode::OUTPUT_50MHZ
52+
}
4753
}
4854

49-
#[cfg(gpio_x0)]
5055
impl From<Speed> for vals::Mode {
51-
fn from(_value: Speed) -> Self {
52-
vals::Mode::OUTPUT_50MHZ
56+
#[inline]
57+
fn from(value: Speed) -> Self {
58+
value.to_mode()
5359
}
5460
}
5561

@@ -459,6 +465,45 @@ impl From<AFType> for vals::Cnf {
459465
}
460466
}
461467

468+
/// Bundle of mode/cnf/pull settings for an alternate-function pin.
469+
///
470+
/// Mirrors embassy-stm32's `gpio_v1::AfType`. Drivers pass a single
471+
/// `AfType` per pin to `Pin::set_as_af()` (via the `new_pin!` /
472+
/// `set_as_af!` macros) instead of juggling separate `set_as_af_output` /
473+
/// `set_as_input` calls. On qingke V0/V3 GPIO the AF concept is the same
474+
/// regardless of direction: input pins set MODE=Input + CNF=Floating/Pull,
475+
/// output pins set MODE=2/10/50MHz + CNF=AF_PushPull/AF_OpenDrain.
476+
#[derive(Copy, Clone)]
477+
pub struct AfType {
478+
mode: vals::Mode,
479+
cnf: vals::Cnf,
480+
pull: Pull,
481+
}
482+
483+
impl AfType {
484+
/// Input AF pin (e.g. UART RX, SPI MISO).
485+
pub const fn input(pull: Pull) -> Self {
486+
let cnf = match pull {
487+
Pull::None => vals::Cnf::FLOATING_IN__OPEN_DRAIN_OUT,
488+
// PULL_IN and AF_PUSH_PULL_OUT share the same CNF encoding (0b10);
489+
// for input mode this means "input with pull-up/down" and pull
490+
// direction comes from ODR via `set_pull` below.
491+
_ => vals::Cnf::PULL_IN__AF_PUSH_PULL_OUT,
492+
};
493+
Self { mode: vals::Mode::INPUT, cnf, pull }
494+
}
495+
496+
/// Output AF pin (e.g. UART TX, SPI MOSI/SCK, I2C SCL/SDA).
497+
pub const fn output(output_type: OutputType, speed: Speed) -> Self {
498+
let cnf = match output_type {
499+
OutputType::PushPull => vals::Cnf::PULL_IN__AF_PUSH_PULL_OUT,
500+
#[cfg(not(gpio_x0))]
501+
OutputType::OpenDrain => vals::Cnf::AF_OPEN_DRAIN_OUT,
502+
};
503+
Self { mode: speed.to_mode(), cnf, pull: Pull::None }
504+
}
505+
}
506+
462507
/// Alternate function type settings, CNF, when MODE>0b00
463508
464509
pub(crate) trait SealedPin {
@@ -569,6 +614,15 @@ pub(crate) trait SealedPin {
569614
self.set_mode_cnf(speed.into(), af_type.into());
570615
}
571616

617+
/// Unified AF configuration — preferred by `new_pin!` / `set_as_af!`.
618+
/// Mirrors embassy-stm32's `Pin::set_as_af` (gpio_v1 signature).
619+
/// `cfg(not(afio))` chips (future H4) will take an extra `af_num: u8`.
620+
#[inline]
621+
fn set_as_af(&self, af_type: AfType) {
622+
self.set_mode_cnf(af_type.mode, af_type.cnf);
623+
self.set_pull(af_type.pull);
624+
}
625+
572626
/// Analog mode, both input and output
573627
#[inline]
574628
fn set_as_analog(&self) {

0 commit comments

Comments
 (0)