stm32/gpio: refactor AfType

This commit is contained in:
Jan Špaček 2024-06-01 18:16:40 +02:00
parent 1a2c8cecde
commit 94007ce6e0
31 changed files with 667 additions and 581 deletions

View File

@ -18,7 +18,7 @@ pub use super::common::{BufferedCanReceiver, BufferedCanSender};
use super::frame::{Envelope, Frame};
use super::util;
use crate::can::enums::{BusError, TryReadError};
use crate::gpio::AFType;
use crate::gpio::{AfType, OutputType, Pull, Speed};
use crate::interrupt::typelevel::Interrupt;
use crate::rcc::{self, RccPeripheral};
use crate::{interrupt, peripherals, Peripheral};
@ -188,8 +188,8 @@ impl<'d> Can<'d> {
let info = T::info();
let regs = &T::info().regs;
rx.set_as_af(rx.af_num(), AFType::Input);
tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
rx.set_as_af(rx.af_num(), AfType::input(Pull::None));
tx.set_as_af(tx.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
rcc::enable_and_reset::<T>();
@ -223,8 +223,8 @@ impl<'d> Can<'d> {
info.sce_interrupt.enable();
}
rx.set_as_af(rx.af_num(), AFType::Input);
tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
rx.set_as_af(rx.af_num(), AfType::input(Pull::None));
tx.set_as_af(tx.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
Registers(T::regs()).leave_init_mode();

View File

@ -10,7 +10,7 @@ use embassy_sync::channel::{Channel, DynamicReceiver, DynamicSender};
use embassy_sync::waitqueue::AtomicWaker;
use crate::can::fd::peripheral::Registers;
use crate::gpio::AFType;
use crate::gpio::{AfType, OutputType, Pull, Speed};
use crate::interrupt::typelevel::Interrupt;
use crate::rcc::{self, RccPeripheral};
use crate::{interrupt, peripherals, Peripheral};
@ -184,8 +184,8 @@ impl<'d> CanConfigurator<'d> {
) -> CanConfigurator<'d> {
into_ref!(_peri, rx, tx);
rx.set_as_af(rx.af_num(), AFType::Input);
tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
rx.set_as_af(rx.af_num(), AfType::input(Pull::None));
tx.set_as_af(tx.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
rcc::enable_and_reset::<T>();
@ -193,8 +193,8 @@ impl<'d> CanConfigurator<'d> {
config.timestamp_source = TimestampSource::Prescaler(TimestampPrescaler::_1);
T::registers().into_config_mode(config);
rx.set_as_af(rx.af_num(), AFType::Input);
tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
rx.set_as_af(rx.af_num(), AfType::input(Pull::None));
tx.set_as_af(tx.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
unsafe {
T::IT0Interrupt::unpend(); // Not unsafe

View File

@ -7,7 +7,7 @@ use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker;
use crate::dma::Transfer;
use crate::gpio::{AFType, Speed};
use crate::gpio::{AfType, Pull};
use crate::interrupt::typelevel::Interrupt;
use crate::{interrupt, rcc, Peripheral};
@ -109,8 +109,7 @@ macro_rules! config_pins {
into_ref!($($pin),*);
critical_section::with(|_| {
$(
$pin.set_as_af($pin.af_num(), AFType::Input);
$pin.set_speed(Speed::VeryHigh);
$pin.set_as_af($pin.af_num(), AfType::input(Pull::None));
)*
})
};

View File

@ -5,7 +5,7 @@ use core::marker::PhantomData;
use embassy_hal_internal::{into_ref, PeripheralRef};
//use crate::gpio::{AnyPin, SealedPin};
use crate::gpio::{AFType, AnyPin, Pull, Speed};
use crate::gpio::{AfType, AnyPin, OutputType, Speed};
use crate::rcc::{self, RccPeripheral};
use crate::{peripherals, Peripheral};
@ -80,8 +80,7 @@ impl<'d, T: Instance> DsiHost<'d, T> {
rcc::enable_and_reset::<T>();
// Set Tearing Enable pin according to CubeMx example
te.set_as_af_pull(te.af_num(), AFType::OutputPushPull, Pull::None);
te.set_speed(Speed::Low);
te.set_as_af(te.af_num(), AfType::output(OutputType::PushPull, Speed::Low));
/*
T::regs().wcr().modify(|w| {
w.set_dsien(true);

View File

@ -12,7 +12,9 @@ use stm32_metapac::eth::vals::{Apcs, Cr, Dm, DmaomrSr, Fes, Ftf, Ifg, MbProgress
pub(crate) use self::rx_desc::{RDes, RDesRing};
pub(crate) use self::tx_desc::{TDes, TDesRing};
use super::*;
use crate::gpio::{AFType, AnyPin, SealedPin};
#[cfg(eth_v1a)]
use crate::gpio::Pull;
use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed};
use crate::interrupt::InterruptExt;
#[cfg(eth_v1a)]
use crate::pac::AFIO;
@ -61,7 +63,7 @@ macro_rules! config_in_pins {
critical_section::with(|_| {
$(
// TODO properly create a set_as_input function
$pin.set_as_af($pin.af_num(), AFType::Input);
$pin.set_as_af($pin.af_num(), AfType::input(Pull::None));
)*
})
}
@ -72,8 +74,7 @@ macro_rules! config_af_pins {
($($pin:ident),*) => {
critical_section::with(|_| {
$(
// We are lucky here, this configures to max speed (50MHz)
$pin.set_as_af($pin.af_num(), AFType::OutputPushPull);
$pin.set_as_af($pin.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
)*
})
};
@ -84,8 +85,7 @@ macro_rules! config_pins {
($($pin:ident),*) => {
critical_section::with(|_| {
$(
$pin.set_as_af($pin.af_num(), AFType::OutputPushPull);
$pin.set_speed(crate::gpio::Speed::VeryHigh);
$pin.set_as_af($pin.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
)*
})
};

View File

@ -8,7 +8,7 @@ use stm32_metapac::syscfg::vals::EthSelPhy;
pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing};
use super::*;
use crate::gpio::{AFType, AnyPin, SealedPin as _, Speed};
use crate::gpio::{AfType, AnyPin, OutputType, SealedPin as _, Speed};
use crate::interrupt::InterruptExt;
use crate::pac::ETH;
use crate::rcc::SealedRccPeripheral;
@ -56,8 +56,8 @@ macro_rules! config_pins {
($($pin:ident),*) => {
critical_section::with(|_| {
$(
$pin.set_as_af($pin.af_num(), AFType::OutputPushPull);
$pin.set_speed(Speed::VeryHigh);
// TODO: shouldn't some pins be configured as inputs?
$pin.set_as_af($pin.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
)*
})
};

View File

@ -3,7 +3,7 @@ use core::marker::PhantomData;
use embassy_hal_internal::into_ref;
use crate::gpio::{AFType, Pull, Speed};
use crate::gpio::{AfType, OutputType, Pull, Speed};
use crate::{rcc, Peripheral};
/// FMC driver
@ -76,8 +76,7 @@ macro_rules! config_pins {
($($pin:ident),*) => {
into_ref!($($pin),*);
$(
$pin.set_as_af_pull($pin.af_num(), AFType::OutputPushPull, Pull::Up);
$pin.set_speed(Speed::VeryHigh);
$pin.set_as_af($pin.af_num(), AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up));
)*
};
}

View File

@ -32,7 +32,9 @@ impl<'d> Flex<'d> {
}
/// Put the pin into input mode.
#[inline]
///
/// The internal weak pull-up and pull-down resistors will be enabled according to `pull`.
#[inline(never)]
pub fn set_as_input(&mut self, pull: Pull) {
critical_section::with(|_| {
let r = self.pin.block();
@ -51,35 +53,35 @@ impl<'d> Flex<'d> {
Pull::None => vals::CnfIn::FLOATING,
};
let crlh = if n < 8 { 0 } else { 1 };
r.cr(crlh).modify(|w| {
r.cr(n / 8).modify(|w| {
w.set_mode(n % 8, vals::Mode::INPUT);
w.set_cnf_in(n % 8, cnf);
});
}
#[cfg(gpio_v2)]
{
r.pupdr().modify(|w| w.set_pupdr(n, pull.into()));
r.pupdr().modify(|w| w.set_pupdr(n, pull.to_pupdr()));
r.otyper().modify(|w| w.set_ot(n, vals::Ot::PUSHPULL));
r.moder().modify(|w| w.set_moder(n, vals::Moder::INPUT));
}
});
}
/// Put the pin into output mode.
/// Put the pin into push-pull output mode.
///
/// The pin level will be whatever was set before (or low by default). If you want it to begin
/// at a specific level, call `set_high`/`set_low` on the pin first.
#[inline]
///
/// The internal weak pull-up and pull-down resistors will be disabled.
#[inline(never)]
pub fn set_as_output(&mut self, speed: Speed) {
critical_section::with(|_| {
let r = self.pin.block();
let n = self.pin.pin() as usize;
#[cfg(gpio_v1)]
{
let crlh = if n < 8 { 0 } else { 1 };
r.cr(crlh).modify(|w| {
w.set_mode(n % 8, speed.into());
r.cr(n / 8).modify(|w| {
w.set_mode(n % 8, speed.to_mode());
w.set_cnf_out(n % 8, vals::CnfOut::PUSHPULL);
});
}
@ -87,44 +89,50 @@ impl<'d> Flex<'d> {
{
r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING));
r.otyper().modify(|w| w.set_ot(n, vals::Ot::PUSHPULL));
self.pin.set_speed(speed);
r.ospeedr().modify(|w| w.set_ospeedr(n, speed.to_ospeedr()));
r.moder().modify(|w| w.set_moder(n, vals::Moder::OUTPUT));
}
});
}
/// Put the pin into input + output mode.
/// Put the pin into input + open-drain output mode.
///
/// This is commonly used for "open drain" mode.
/// the hardware will drive the line low if you set it to low, and will leave it floating if you set
/// The hardware will drive the line low if you set it to low, and will leave it floating if you set
/// it to high, in which case you can read the input to figure out whether another device
/// is driving the line low.
///
/// The pin level will be whatever was set before (or low by default). If you want it to begin
/// at a specific level, call `set_high`/`set_low` on the pin first.
#[inline]
pub fn set_as_input_output(&mut self, speed: Speed, pull: Pull) {
///
/// The internal weak pull-up and pull-down resistors will be disabled.
#[inline(never)]
pub fn set_as_input_output(&mut self, speed: Speed) {
#[cfg(gpio_v1)]
critical_section::with(|_| {
let r = self.pin.block();
let n = self.pin.pin() as usize;
#[cfg(gpio_v1)]
{
let crlh = if n < 8 { 0 } else { 1 };
match pull {
Pull::Up => r.bsrr().write(|w| w.set_bs(n, true)),
Pull::Down => r.bsrr().write(|w| w.set_br(n, true)),
Pull::None => {}
}
r.cr(crlh).modify(|w| w.set_mode(n % 8, speed.into()));
r.cr(crlh).modify(|w| w.set_cnf_out(n % 8, vals::CnfOut::OPENDRAIN));
}
#[cfg(gpio_v2)]
{
r.pupdr().modify(|w| w.set_pupdr(n, pull.into()));
r.otyper().modify(|w| w.set_ot(n, vals::Ot::OPENDRAIN));
self.pin.set_speed(speed);
r.moder().modify(|w| w.set_moder(n, vals::Moder::OUTPUT));
}
r.cr(n / 8).modify(|w| w.set_mode(n % 8, speed.to_mode()));
r.cr(n / 8).modify(|w| w.set_cnf_out(n % 8, vals::CnfOut::OPENDRAIN));
});
#[cfg(gpio_v2)]
self.set_as_input_output_pull(speed, Pull::None);
}
/// Put the pin into input + open-drain output mode with internal pullup or pulldown.
///
/// This works like [`Self::set_as_input_output()`], but it also allows to enable the internal
/// weak pull-up or pull-down resistors.
#[inline(never)]
#[cfg(gpio_v2)]
pub fn set_as_input_output_pull(&mut self, speed: Speed, pull: Pull) {
critical_section::with(|_| {
let r = self.pin.block();
let n = self.pin.pin() as usize;
r.pupdr().modify(|w| w.set_pupdr(n, pull.to_pupdr()));
r.otyper().modify(|w| w.set_ot(n, vals::Ot::OPENDRAIN));
r.ospeedr().modify(|w| w.set_ospeedr(n, speed.to_ospeedr()));
r.moder().modify(|w| w.set_moder(n, vals::Moder::OUTPUT));
});
}
@ -134,18 +142,18 @@ impl<'d> Flex<'d> {
/// as the mode change is handled by the driver.
#[inline]
pub fn set_as_analog(&mut self) {
// TODO: does this also need a critical section, like other methods?
self.pin.set_as_analog();
}
/// Put the pin into AF mode, unchecked.
///
/// This puts the pin into the AF mode, with the requested number, pull and speed. This is
/// This puts the pin into the AF mode, with the requested number and AF type. This is
/// completely unchecked, it can attach the pin to literally any peripheral, so use with care.
#[inline]
pub fn set_as_af_unchecked(&mut self, af_num: u8, af_type: AFType, pull: Pull, speed: Speed) {
pub fn set_as_af_unchecked(&mut self, af_num: u8, af_type: AfType) {
critical_section::with(|_| {
self.pin.set_as_af_pull(af_num, af_type, pull);
self.pin.set_speed(speed);
self.pin.set_as_af(af_num, af_type);
});
}
@ -223,21 +231,7 @@ impl<'d> Drop for Flex<'d> {
#[inline]
fn drop(&mut self) {
critical_section::with(|_| {
let r = self.pin.block();
let n = self.pin.pin() as usize;
#[cfg(gpio_v1)]
{
let crlh = if n < 8 { 0 } else { 1 };
r.cr(crlh).modify(|w| {
w.set_mode(n % 8, vals::Mode::INPUT);
w.set_cnf_in(n % 8, vals::CnfIn::FLOATING);
});
}
#[cfg(gpio_v2)]
{
r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING));
r.moder().modify(|w| w.set_moder(n, vals::Moder::INPUT));
}
self.pin.set_as_disconnected();
});
}
}
@ -254,57 +248,56 @@ pub enum Pull {
Down,
}
#[cfg(gpio_v2)]
impl From<Pull> for vals::Pupdr {
fn from(pull: Pull) -> Self {
use Pull::*;
match pull {
None => vals::Pupdr::FLOATING,
Up => vals::Pupdr::PULLUP,
Down => vals::Pupdr::PULLDOWN,
impl Pull {
#[cfg(gpio_v2)]
const fn to_pupdr(self) -> vals::Pupdr {
match self {
Pull::None => vals::Pupdr::FLOATING,
Pull::Up => vals::Pupdr::PULLUP,
Pull::Down => vals::Pupdr::PULLDOWN,
}
}
}
/// Speed settings
/// Speed setting for an output.
///
/// These vary depending on the chip, check the reference manual or datasheet for details.
#[allow(missing_docs)]
/// These vary depending on the chip, check the reference manual and datasheet ("I/O port
/// characteristics") for details.
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Speed {
#[cfg_attr(gpio_v1, doc = "Output speed OUTPUT2MHZ")]
#[cfg_attr(gpio_v2, doc = "Output speed 00")]
Low,
#[cfg_attr(gpio_v1, doc = "Output speed OUTPUT10MHZ")]
#[cfg_attr(gpio_v2, doc = "Output speed 01")]
Medium,
#[cfg(not(any(syscfg_f0, gpio_v1)))]
#[cfg_attr(gpio_v2, doc = "Output speed 10")]
#[cfg(not(any(gpio_v1, syscfg_f0)))]
High,
#[cfg_attr(gpio_v1, doc = "Output speed OUTPUT50MHZ")]
#[cfg_attr(gpio_v2, doc = "Output speed 10")]
VeryHigh,
}
#[cfg(gpio_v1)]
impl From<Speed> for vals::Mode {
fn from(speed: Speed) -> Self {
use Speed::*;
match speed {
Low => vals::Mode::OUTPUT2MHZ,
Medium => vals::Mode::OUTPUT10MHZ,
VeryHigh => vals::Mode::OUTPUT50MHZ,
impl Speed {
#[cfg(gpio_v1)]
const fn to_mode(self) -> vals::Mode {
match self {
Speed::Low => vals::Mode::OUTPUT2MHZ,
Speed::Medium => vals::Mode::OUTPUT10MHZ,
Speed::VeryHigh => vals::Mode::OUTPUT50MHZ,
}
}
}
#[cfg(gpio_v2)]
impl From<Speed> for vals::Ospeedr {
fn from(speed: Speed) -> Self {
use Speed::*;
match speed {
Low => vals::Ospeedr::LOWSPEED,
Medium => vals::Ospeedr::MEDIUMSPEED,
#[cfg(gpio_v2)]
const fn to_ospeedr(self: Speed) -> vals::Ospeedr {
match self {
Speed::Low => vals::Ospeedr::LOWSPEED,
Speed::Medium => vals::Ospeedr::MEDIUMSPEED,
#[cfg(not(syscfg_f0))]
High => vals::Ospeedr::HIGHSPEED,
VeryHigh => vals::Ospeedr::VERYHIGHSPEED,
Speed::High => vals::Ospeedr::HIGHSPEED,
Speed::VeryHigh => vals::Ospeedr::VERYHIGHSPEED,
}
}
}
@ -445,17 +438,29 @@ pub struct OutputOpenDrain<'d> {
}
impl<'d> OutputOpenDrain<'d> {
/// Create a new GPIO open drain output driver for a [Pin] with the provided [Level] and [Speed], [Pull] configuration.
/// Create a new GPIO open drain output driver for a [Pin] with the provided [Level] and [Speed].
#[inline]
pub fn new(pin: impl Peripheral<P = impl Pin> + 'd, initial_output: Level, speed: Speed, pull: Pull) -> Self {
pub fn new(pin: impl Peripheral<P = impl Pin> + 'd, initial_output: Level, speed: Speed) -> Self {
let mut pin = Flex::new(pin);
match initial_output {
Level::High => pin.set_high(),
Level::Low => pin.set_low(),
}
pin.set_as_input_output(speed);
Self { pin }
}
pin.set_as_input_output(speed, pull);
/// Create a new GPIO open drain output driver for a [Pin] with the provided [Level], [Speed]
/// and [Pull].
#[inline]
#[cfg(gpio_v2)]
pub fn new_pull(pin: impl Peripheral<P = impl Pin> + 'd, initial_output: Level, speed: Speed, pull: Pull) -> Self {
let mut pin = Flex::new(pin);
match initial_output {
Level::High => pin.set_high(),
Level::Low => pin.set_low(),
}
pin.set_as_input_output_pull(speed, pull);
Self { pin }
}
@ -521,6 +526,8 @@ impl<'d> OutputOpenDrain<'d> {
}
/// GPIO output type
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum OutputType {
/// Drive the pin both high or low.
PushPull,
@ -528,25 +535,170 @@ pub enum OutputType {
OpenDrain,
}
impl From<OutputType> for AFType {
fn from(value: OutputType) -> Self {
match value {
OutputType::OpenDrain => AFType::OutputOpenDrain,
OutputType::PushPull => AFType::OutputPushPull,
impl OutputType {
#[cfg(gpio_v1)]
const fn to_cnf_out(self) -> vals::CnfOut {
match self {
OutputType::PushPull => vals::CnfOut::ALTPUSHPULL,
OutputType::OpenDrain => vals::CnfOut::ALTOPENDRAIN,
}
}
#[cfg(gpio_v2)]
const fn to_ot(self) -> vals::Ot {
match self {
OutputType::PushPull => vals::Ot::PUSHPULL,
OutputType::OpenDrain => vals::Ot::OPENDRAIN,
}
}
}
/// Alternate function type settings
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum AFType {
/// Input
Input,
/// Output, drive the pin both high or low.
OutputPushPull,
/// Output, drive the pin low, or don't drive it at all if the output level is high.
OutputOpenDrain,
/// Alternate function type settings.
#[derive(Copy, Clone)]
#[cfg(gpio_v1)]
pub struct AfType {
mode: vals::Mode,
cnf: u8,
pull: Pull,
}
#[cfg(gpio_v1)]
impl AfType {
/// Input with optional pullup or pulldown.
pub const fn input(pull: Pull) -> Self {
let cnf_in = match pull {
Pull::Up | Pull::Down => vals::CnfIn::PULL,
Pull::None => vals::CnfIn::FLOATING,
};
Self {
mode: vals::Mode::INPUT,
cnf: cnf_in.to_bits(),
pull,
}
}
/// Output with output type and speed and no pull-up or pull-down.
pub const fn output(output_type: OutputType, speed: Speed) -> Self {
Self {
mode: speed.to_mode(),
cnf: output_type.to_cnf_out().to_bits(),
pull: Pull::None,
}
}
}
#[inline(never)]
#[cfg(gpio_v1)]
fn set_as_af(pin_port: u8, _af_num: u8, af_type: AfType) {
let pin = unsafe { AnyPin::steal(pin_port) };
let r = pin.block();
let n = pin._pin() as usize;
r.cr(n / 8).modify(|w| {
w.set_mode(n % 8, af_type.mode);
// note that we are writing the CNF field, which is exposed as both `cnf_in` and `cnf_out`
// in the PAC. the choice of `cnf_in` instead of `cnf_out` in this code is arbitrary and
// does not affect the result.
w.set_cnf_in(n % 8, vals::CnfIn::from_bits(af_type.cnf));
});
match af_type.pull {
Pull::Up => r.bsrr().write(|w| w.set_bs(n, true)),
Pull::Down => r.bsrr().write(|w| w.set_br(n, true)),
Pull::None => {}
}
}
/// Alternate function type settings.
#[derive(Copy, Clone)]
#[cfg(gpio_v2)]
pub struct AfType {
pupdr: vals::Pupdr,
ot: vals::Ot,
ospeedr: vals::Ospeedr,
}
#[cfg(gpio_v2)]
impl AfType {
/// Input with optional pullup or pulldown.
pub const fn input(pull: Pull) -> Self {
Self {
pupdr: pull.to_pupdr(),
ot: vals::Ot::PUSHPULL,
ospeedr: vals::Ospeedr::LOWSPEED,
}
}
/// Output with output type and speed and no pull-up or pull-down.
pub const fn output(output_type: OutputType, speed: Speed) -> Self {
Self::output_pull(output_type, speed, Pull::None)
}
/// Output with output type, speed and pull-up or pull-down;
pub const fn output_pull(output_type: OutputType, speed: Speed, pull: Pull) -> Self {
Self {
pupdr: pull.to_pupdr(),
ot: output_type.to_ot(),
ospeedr: speed.to_ospeedr(),
}
}
}
#[inline(never)]
#[cfg(gpio_v2)]
fn set_as_af(pin_port: u8, af_num: u8, af_type: AfType) {
let pin = unsafe { AnyPin::steal(pin_port) };
let r = pin.block();
let n = pin._pin() as usize;
r.afr(n / 8).modify(|w| w.set_afr(n % 8, af_num));
r.pupdr().modify(|w| w.set_pupdr(n, af_type.pupdr));
r.otyper().modify(|w| w.set_ot(n, af_type.ot));
r.ospeedr().modify(|w| w.set_ospeedr(n, af_type.ospeedr));
r.moder().modify(|w| w.set_moder(n, vals::Moder::ALTERNATE));
}
#[inline(never)]
fn set_as_analog(pin_port: u8) {
let pin = unsafe { AnyPin::steal(pin_port) };
let r = pin.block();
let n = pin._pin() as usize;
#[cfg(gpio_v1)]
r.cr(n / 8).modify(|w| {
w.set_mode(n % 8, vals::Mode::INPUT);
w.set_cnf_in(n % 8, vals::CnfIn::ANALOG);
});
#[cfg(gpio_v2)]
r.moder().modify(|w| w.set_moder(n, vals::Moder::ANALOG));
}
#[inline(never)]
fn get_pull(pin_port: u8) -> Pull {
let pin = unsafe { AnyPin::steal(pin_port) };
let r = pin.block();
let n = pin._pin() as usize;
#[cfg(gpio_v1)]
return match r.cr(n / 8).read().mode(n % 8) {
vals::Mode::INPUT => match r.cr(n / 8).read().cnf_in(n % 8) {
vals::CnfIn::PULL => match r.odr().read().odr(n) {
vals::Odr::LOW => Pull::Down,
vals::Odr::HIGH => Pull::Up,
},
_ => Pull::None,
},
_ => Pull::None,
};
#[cfg(gpio_v2)]
return match r.pupdr().read().pupdr(n) {
vals::Pupdr::FLOATING => Pull::None,
vals::Pupdr::PULLDOWN => Pull::Down,
vals::Pupdr::PULLUP => Pull::Up,
vals::Pupdr::_RESERVED_3 => Pull::None,
};
}
pub(crate) trait SealedPin {
@ -556,6 +708,7 @@ pub(crate) trait SealedPin {
fn _pin(&self) -> u8 {
self.pin_port() % 16
}
#[inline]
fn _port(&self) -> u8 {
self.pin_port() / 16
@ -581,146 +734,31 @@ pub(crate) trait SealedPin {
}
#[inline]
fn set_as_af(&self, af_num: u8, af_type: AFType) {
self.set_as_af_pull(af_num, af_type, Pull::None);
}
#[cfg(gpio_v1)]
#[inline]
fn set_as_af_pull(&self, _af_num: u8, af_type: AFType, pull: Pull) {
// F1 uses the AFIO register for remapping.
// For now, this is not implemented, so af_num is ignored
// _af_num should be zero here, since it is not set by stm32-data
let r = self.block();
let n = self._pin() as usize;
let crlh = if n < 8 { 0 } else { 1 };
match af_type {
AFType::Input => {
let cnf = match pull {
Pull::Up => {
r.bsrr().write(|w| w.set_bs(n, true));
vals::CnfIn::PULL
}
Pull::Down => {
r.bsrr().write(|w| w.set_br(n, true));
vals::CnfIn::PULL
}
Pull::None => vals::CnfIn::FLOATING,
};
r.cr(crlh).modify(|w| {
w.set_mode(n % 8, vals::Mode::INPUT);
w.set_cnf_in(n % 8, cnf);
});
}
AFType::OutputPushPull => {
r.cr(crlh).modify(|w| {
w.set_mode(n % 8, vals::Mode::OUTPUT50MHZ);
w.set_cnf_out(n % 8, vals::CnfOut::ALTPUSHPULL);
});
}
AFType::OutputOpenDrain => {
r.cr(crlh).modify(|w| {
w.set_mode(n % 8, vals::Mode::OUTPUT50MHZ);
w.set_cnf_out(n % 8, vals::CnfOut::ALTOPENDRAIN);
});
}
}
}
#[cfg(gpio_v2)]
#[inline]
fn set_as_af_pull(&self, af_num: u8, af_type: AFType, pull: Pull) {
let pin = self._pin() as usize;
let block = self.block();
block.afr(pin / 8).modify(|w| w.set_afr(pin % 8, af_num));
match af_type {
AFType::Input => {}
AFType::OutputPushPull => block.otyper().modify(|w| w.set_ot(pin, vals::Ot::PUSHPULL)),
AFType::OutputOpenDrain => block.otyper().modify(|w| w.set_ot(pin, vals::Ot::OPENDRAIN)),
}
block.pupdr().modify(|w| w.set_pupdr(pin, pull.into()));
block.moder().modify(|w| w.set_moder(pin, vals::Moder::ALTERNATE));
fn set_as_af(&self, af_num: u8, af_type: AfType) {
set_as_af(self.pin_port(), af_num, af_type)
}
#[inline]
fn set_as_analog(&self) {
let pin = self._pin() as usize;
let block = self.block();
#[cfg(gpio_v1)]
{
let crlh = if pin < 8 { 0 } else { 1 };
block.cr(crlh).modify(|w| {
w.set_mode(pin % 8, vals::Mode::INPUT);
w.set_cnf_in(pin % 8, vals::CnfIn::ANALOG);
});
}
#[cfg(gpio_v2)]
block.moder().modify(|w| w.set_moder(pin, vals::Moder::ANALOG));
set_as_analog(self.pin_port());
}
/// Set the pin as "disconnected", ie doing nothing and consuming the lowest
/// amount of power possible.
///
/// This is currently the same as set_as_analog but is semantically different really.
/// Drivers should set_as_disconnected pins when dropped.
/// This is currently the same as [`Self::set_as_analog()`] but is semantically different
/// really. Drivers should `set_as_disconnected()` pins when dropped.
///
/// Note that this also disables the internal weak pull-up and pull-down resistors.
#[inline]
fn set_as_disconnected(&self) {
self.set_as_analog();
}
/// Sets the speed of the output pin.
///
/// This should never be called for AFType::Input on the STM32F1 series, since MODE and
/// CNF bits are not independent. If the CNF bits are altered afterwards as well, this
/// will put the pin into output mode.
#[inline]
fn set_speed(&self, speed: Speed) {
let pin = self._pin() as usize;
#[cfg(gpio_v1)]
{
let crlh = if pin < 8 { 0 } else { 1 };
self.block().cr(crlh).modify(|w| {
w.set_mode(pin % 8, speed.into());
});
}
#[cfg(gpio_v2)]
self.block().ospeedr().modify(|w| w.set_ospeedr(pin, speed.into()));
}
/// Get the pull-up configuration.
#[inline]
fn pull(&self) -> Pull {
critical_section::with(|_| {
let r = self.block();
let n = self._pin() as usize;
#[cfg(gpio_v1)]
{
let crlh = if n < 8 { 0 } else { 1 };
match r.cr(crlh).read().mode(n % 8) {
vals::Mode::INPUT => match r.cr(crlh).read().cnf_in(n % 8) {
vals::CnfIn::PULL => match r.odr().read().odr(n) {
vals::Odr::LOW => Pull::Down,
vals::Odr::HIGH => Pull::Up,
},
_ => Pull::None,
},
_ => Pull::None,
}
}
#[cfg(gpio_v2)]
{
match r.pupdr().read().pupdr(n) {
vals::Pupdr::FLOATING => Pull::None,
vals::Pupdr::PULLDOWN => Pull::Down,
vals::Pupdr::PULLUP => Pull::Up,
vals::Pupdr::_RESERVED_3 => Pull::None,
}
}
})
critical_section::with(|_| get_pull(self.pin_port()))
}
}

View File

@ -7,7 +7,7 @@ use core::marker::PhantomData;
use embassy_hal_internal::{into_ref, PeripheralRef};
pub use traits::Instance;
use crate::gpio::{AFType, AnyPin};
use crate::gpio::{AfType, AnyPin, OutputType, Speed};
use crate::time::Hertz;
use crate::{rcc, Peripheral};
@ -80,9 +80,10 @@ macro_rules! advanced_channel_impl {
into_ref!(pin);
critical_section::with(|_| {
pin.set_low();
pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
#[cfg(gpio_v2)]
pin.set_speed(crate::gpio::Speed::VeryHigh);
pin.set_as_af(
pin.af_num(),
AfType::output(OutputType::PushPull, Speed::VeryHigh),
);
});
PwmPin {
_pin: pin.map_into(),
@ -97,9 +98,10 @@ macro_rules! advanced_channel_impl {
into_ref!(pin);
critical_section::with(|_| {
pin.set_low();
pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
#[cfg(gpio_v2)]
pin.set_speed(crate::gpio::Speed::VeryHigh);
pin.set_as_af(
pin.af_num(),
AfType::output(OutputType::PushPull, Speed::VeryHigh),
);
});
ComplementaryPwmPin {
_pin: pin.map_into(),

View File

@ -15,7 +15,9 @@ use embassy_sync::waitqueue::AtomicWaker;
use embassy_time::{Duration, Instant};
use crate::dma::ChannelAndRequest;
use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed};
#[cfg(gpio_v2)]
use crate::gpio::Pull;
use crate::gpio::{AfType, AnyPin, OutputType, SealedPin as _, Speed};
use crate::interrupt::typelevel::Interrupt;
use crate::mode::{Async, Blocking, Mode};
use crate::rcc::{RccInfo, SealedRccPeripheral};
@ -50,11 +52,13 @@ pub struct Config {
///
/// Using external pullup resistors is recommended for I2C. If you do
/// have external pullups you should not enable this.
#[cfg(gpio_v2)]
pub sda_pullup: bool,
/// Enable internal pullup on SCL.
///
/// Using external pullup resistors is recommended for I2C. If you do
/// have external pullups you should not enable this.
#[cfg(gpio_v2)]
pub scl_pullup: bool,
/// Timeout.
#[cfg(feature = "time")]
@ -64,7 +68,9 @@ pub struct Config {
impl Default for Config {
fn default() -> Self {
Self {
#[cfg(gpio_v2)]
sda_pullup: false,
#[cfg(gpio_v2)]
scl_pullup: false,
#[cfg(feature = "time")]
timeout: embassy_time::Duration::from_millis(1000),
@ -73,18 +79,32 @@ impl Default for Config {
}
impl Config {
fn scl_pull_mode(&self) -> Pull {
match self.scl_pullup {
true => Pull::Up,
false => Pull::Down,
}
fn scl_af(&self) -> AfType {
#[cfg(gpio_v1)]
return AfType::output(OutputType::OpenDrain, Speed::Medium);
#[cfg(gpio_v2)]
return AfType::output_pull(
OutputType::OpenDrain,
Speed::Medium,
match self.scl_pullup {
true => Pull::Up,
false => Pull::Down,
},
);
}
fn sda_pull_mode(&self) -> Pull {
match self.sda_pullup {
true => Pull::Up,
false => Pull::Down,
}
fn sda_af(&self) -> AfType {
#[cfg(gpio_v1)]
return AfType::output(OutputType::OpenDrain, Speed::Medium);
#[cfg(gpio_v2)]
return AfType::output_pull(
OutputType::OpenDrain,
Speed::Medium,
match self.sda_pullup {
true => Pull::Up,
false => Pull::Down,
},
);
}
}
@ -118,8 +138,8 @@ impl<'d> I2c<'d, Async> {
) -> Self {
Self::new_inner(
peri,
new_pin!(scl, AFType::OutputOpenDrain, Speed::Medium, config.scl_pull_mode()),
new_pin!(sda, AFType::OutputOpenDrain, Speed::Medium, config.sda_pull_mode()),
new_pin!(scl, config.scl_af()),
new_pin!(sda, config.sda_af()),
new_dma!(tx_dma),
new_dma!(rx_dma),
freq,
@ -139,8 +159,8 @@ impl<'d> I2c<'d, Blocking> {
) -> Self {
Self::new_inner(
peri,
new_pin!(scl, AFType::OutputOpenDrain, Speed::Medium, config.scl_pull_mode()),
new_pin!(sda, AFType::OutputOpenDrain, Speed::Medium, config.sda_pull_mode()),
new_pin!(scl, config.scl_af()),
new_pin!(sda, config.sda_af()),
None,
None,
freq,

View File

@ -3,7 +3,7 @@
use embassy_hal_internal::into_ref;
use crate::dma::ChannelAndRequest;
use crate::gpio::{AFType, AnyPin, SealedPin, Speed};
use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed};
use crate::mode::Async;
use crate::pac::spi::vals;
use crate::spi::{Config as SpiConfig, *};
@ -180,7 +180,7 @@ impl<'d> I2S<'d> {
into_ref!(sd);
Self::new_inner(
peri,
new_pin!(sd, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(sd, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
None,
ws,
ck,
@ -209,7 +209,7 @@ impl<'d> I2S<'d> {
Self::new_inner(
peri,
None,
new_pin!(sd, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(sd, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
ws,
ck,
mck,
@ -244,8 +244,8 @@ impl<'d> I2S<'d> {
into_ref!(txsd, rxsd);
Self::new_inner(
peri,
new_pin!(txsd, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(rxsd, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(txsd, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(rxsd, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
ws,
ck,
mck,
@ -292,14 +292,9 @@ impl<'d> I2S<'d> {
) -> Self {
into_ref!(ws, ck, mck);
ws.set_as_af(ws.af_num(), AFType::OutputPushPull);
ws.set_speed(Speed::VeryHigh);
ck.set_as_af(ck.af_num(), AFType::OutputPushPull);
ck.set_speed(Speed::VeryHigh);
mck.set_as_af(mck.af_num(), AFType::OutputPushPull);
mck.set_speed(Speed::VeryHigh);
ws.set_as_af(ws.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
ck.set_as_af(ck.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
mck.set_as_af(mck.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
let mut spi_cfg = SpiConfig::default();
spi_cfg.frequency = freq;

View File

@ -62,11 +62,10 @@ impl<'d, T: Instance> Ltdc<'d, T> {
rcc::enable_and_reset::<T>();
//new_pin!(clk, AFType::OutputPushPull, Speed::VeryHigh, Pull::None);
//new_pin!(clk, AfType::output(OutputType::PushPull, Speed::VeryHigh));
// Set Tearing Enable pin according to CubeMx example
//te.set_as_af_pull(te.af_num(), AFType::OutputPushPull, Pull::None);
//te.set_speed(Speed::Low);
//te.set_as_af_pull(te.af_num(), AfType::output(OutputType::PushPull, Speed::Low));
/*
T::regs().wcr().modify(|w| {
w.set_dsien(true);

View File

@ -97,23 +97,9 @@ macro_rules! new_dma {
}
macro_rules! new_pin {
($name:ident, $aftype:expr) => {{
new_pin!($name, $aftype, crate::gpio::Speed::Medium, crate::gpio::Pull::None)
}};
($name:ident, $aftype:expr, $speed:expr) => {
new_pin!($name, $aftype, $speed, crate::gpio::Pull::None)
};
($name:ident, $aftype:expr, $speed:expr, $pull:expr) => {{
($name:ident, $af_type:expr) => {{
let pin = $name.into_ref();
pin.set_as_af_pull(pin.af_num(), $aftype, $pull);
// Do not call set_speed on AFType::Input, as MODE and CNF bits are not independent
// for gpio_v1
match $aftype {
crate::gpio::AFType::Input => {}
_ => {
pin.set_speed($speed);
}
};
pin.set_as_af(pin.af_num(), $af_type);
Some(pin.map_into())
}};
}

View File

@ -13,7 +13,7 @@ pub use enums::*;
use stm32_metapac::octospi::vals::{PhaseMode, SizeInBits};
use crate::dma::{word, ChannelAndRequest};
use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed};
use crate::gpio::{AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed};
use crate::mode::{Async, Blocking, Mode as PeriMode};
use crate::pac::octospi::{vals, Octospi as Regs};
use crate::rcc::{self, RccPeripheral};
@ -548,16 +548,19 @@ impl<'d, T: Instance> Ospi<'d, T, Blocking> {
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d1, AFType::Input, Speed::VeryHigh),
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::input(Pull::None)),
None,
None,
None,
None,
None,
None,
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
new_pin!(sck, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(
nss,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
None,
config,
@ -577,16 +580,19 @@ impl<'d, T: Instance> Ospi<'d, T, Blocking> {
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
None,
None,
None,
None,
None,
None,
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
new_pin!(sck, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(
nss,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
None,
config,
@ -608,16 +614,19 @@ impl<'d, T: Instance> Ospi<'d, T, Blocking> {
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
None,
None,
None,
None,
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
new_pin!(sck, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(
nss,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
None,
config,
@ -643,16 +652,19 @@ impl<'d, T: Instance> Ospi<'d, T, Blocking> {
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d4, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d5, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d6, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d7, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d4, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d5, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d6, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d7, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(sck, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(
nss,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
None,
config,
@ -678,16 +690,19 @@ impl<'d, T: Instance> Ospi<'d, T, Blocking> {
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d4, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d5, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d6, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d7, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d4, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d5, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d6, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d7, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(sck, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(
nss,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
None,
config,
@ -710,16 +725,19 @@ impl<'d, T: Instance> Ospi<'d, T, Async> {
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d1, AFType::Input, Speed::VeryHigh),
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::input(Pull::None)),
None,
None,
None,
None,
None,
None,
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
new_pin!(sck, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(
nss,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
new_dma!(dma),
config,
@ -740,16 +758,19 @@ impl<'d, T: Instance> Ospi<'d, T, Async> {
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
None,
None,
None,
None,
None,
None,
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
new_pin!(sck, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(
nss,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
new_dma!(dma),
config,
@ -772,16 +793,19 @@ impl<'d, T: Instance> Ospi<'d, T, Async> {
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
None,
None,
None,
None,
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
new_pin!(sck, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(
nss,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
new_dma!(dma),
config,
@ -808,16 +832,19 @@ impl<'d, T: Instance> Ospi<'d, T, Async> {
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d4, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d5, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d6, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d7, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d4, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d5, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d6, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d7, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(sck, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(
nss,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
new_dma!(dma),
config,
@ -844,16 +871,19 @@ impl<'d, T: Instance> Ospi<'d, T, Async> {
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d4, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d5, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d6, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d7, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d4, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d5, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d6, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d7, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(sck, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(
nss,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
new_dma!(dma),
config,

View File

@ -10,7 +10,7 @@ use embassy_hal_internal::{into_ref, PeripheralRef};
use enums::*;
use crate::dma::ChannelAndRequest;
use crate::gpio::{AFType, AnyPin, Pull, Speed};
use crate::gpio::{AfType, AnyPin, OutputType, Pull, Speed};
use crate::mode::{Async, Blocking, Mode as PeriMode};
use crate::pac::quadspi::Quadspi as Regs;
use crate::rcc::{self, RccPeripheral};
@ -248,12 +248,15 @@ impl<'d, T: Instance> Qspi<'d, T, Blocking> {
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(sck, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(
nss,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
config,
FlashSelection::Flash1,
@ -273,12 +276,15 @@ impl<'d, T: Instance> Qspi<'d, T, Blocking> {
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(sck, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(
nss,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
config,
FlashSelection::Flash2,
@ -301,12 +307,15 @@ impl<'d, T: Instance> Qspi<'d, T, Async> {
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(sck, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(
nss,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
new_dma!(dma),
config,
FlashSelection::Flash1,
@ -327,12 +336,15 @@ impl<'d, T: Instance> Qspi<'d, T, Async> {
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(sck, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(
nss,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
new_dma!(dma),
config,
FlashSelection::Flash2,

View File

@ -2,7 +2,7 @@ use core::marker::PhantomData;
use embassy_hal_internal::into_ref;
use crate::gpio::{AFType, Speed};
use crate::gpio::{AfType, OutputType, Speed};
#[cfg(not(any(stm32f1, rcc_f0v1, rcc_f3v1, rcc_f37)))]
pub use crate::pac::rcc::vals::Mcopre as McoPrescaler;
#[cfg(not(any(
@ -101,8 +101,7 @@ impl<'d, T: McoInstance> Mco<'d, T> {
critical_section::with(|_| unsafe {
T::_apply_clock_settings(source, prescaler);
pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
pin.set_speed(Speed::VeryHigh);
pin.set_as_af(pin.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
});
Self { phantom: PhantomData }

View File

@ -9,7 +9,7 @@ use embassy_hal_internal::{into_ref, PeripheralRef};
pub use crate::dma::word;
#[cfg(not(gpdma))]
use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer};
use crate::gpio::{AFType, AnyPin, SealedPin as _};
use crate::gpio::{AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed};
use crate::pac::sai::{vals, Sai as Regs};
use crate::rcc::{self, RccPeripheral};
use crate::{peripherals, Peripheral};
@ -656,17 +656,17 @@ fn dr<W: word::Word>(w: crate::pac::sai::Sai, sub_block: WhichSubBlock) -> *mut
}
// return the type for (sd, sck)
fn get_af_types(mode: Mode, tx_rx: TxRx) -> (AFType, AFType) {
fn get_af_types(mode: Mode, tx_rx: TxRx) -> (AfType, AfType) {
(
//sd is defined by tx/rx mode
match tx_rx {
TxRx::Transmitter => AFType::OutputPushPull,
TxRx::Receiver => AFType::Input,
TxRx::Transmitter => AfType::output(OutputType::PushPull, Speed::VeryHigh),
TxRx::Receiver => AfType::input(Pull::None),
},
//clocks (mclk, sck and fs) are defined by master/slave
match mode {
Mode::Master => AFType::OutputPushPull,
Mode::Slave => AFType::Input,
Mode::Master => AfType::output(OutputType::PushPull, Speed::VeryHigh),
Mode::Slave => AfType::input(Pull::None),
},
)
}
@ -768,9 +768,7 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> {
into_ref!(mclk);
let (_sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx);
mclk.set_as_af(mclk.af_num(), ck_af_type);
mclk.set_speed(crate::gpio::Speed::VeryHigh);
if config.master_clock_divider == MasterClockDivider::MasterClockDisabled {
config.master_clock_divider = MasterClockDivider::Div1;
@ -796,12 +794,8 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> {
let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx);
sd.set_as_af(sd.af_num(), sd_af_type);
sd.set_speed(crate::gpio::Speed::VeryHigh);
sck.set_as_af(sck.af_num(), ck_af_type);
sck.set_speed(crate::gpio::Speed::VeryHigh);
fs.set_as_af(fs.af_num(), ck_af_type);
fs.set_speed(crate::gpio::Speed::VeryHigh);
let sub_block = S::WHICH;
let request = dma.request();
@ -834,9 +828,7 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> {
into_ref!(dma, peri, sd);
let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx);
sd.set_as_af(sd.af_num(), sd_af_type);
sd.set_speed(crate::gpio::Speed::VeryHigh);
let sub_block = S::WHICH;
let request = dma.request();

View File

@ -13,7 +13,9 @@ use embassy_sync::waitqueue::AtomicWaker;
use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR};
use crate::dma::NoDma;
use crate::gpio::{AFType, AnyPin, Pull, SealedPin, Speed};
#[cfg(gpio_v2)]
use crate::gpio::Pull;
use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed};
use crate::interrupt::typelevel::Interrupt;
use crate::pac::sdmmc::Sdmmc as RegBlock;
use crate::rcc::{self, RccPeripheral};
@ -292,6 +294,13 @@ pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> {
card: Option<Card>,
}
const CLK_AF: AfType = AfType::output(OutputType::PushPull, Speed::VeryHigh);
#[cfg(gpio_v1)]
const CMD_AF: AfType = AfType::output(OutputType::PushPull, Speed::VeryHigh);
#[cfg(gpio_v2)]
const CMD_AF: AfType = AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up);
const DATA_AF: AfType = CMD_AF;
#[cfg(sdmmc_v1)]
impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
/// Create a new SDMMC driver, with 1 data lane.
@ -307,13 +316,9 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
into_ref!(clk, cmd, d0);
critical_section::with(|_| {
clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None);
cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up);
d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up);
clk.set_speed(Speed::VeryHigh);
cmd.set_speed(Speed::VeryHigh);
d0.set_speed(Speed::VeryHigh);
clk.set_as_af(clk.af_num(), CLK_AF);
cmd.set_as_af(cmd.af_num(), CMD_AF);
d0.set_as_af(d0.af_num(), DATA_AF);
});
Self::new_inner(
@ -345,19 +350,12 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
into_ref!(clk, cmd, d0, d1, d2, d3);
critical_section::with(|_| {
clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None);
cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up);
d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up);
d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::Up);
d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::Up);
d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::Up);
clk.set_speed(Speed::VeryHigh);
cmd.set_speed(Speed::VeryHigh);
d0.set_speed(Speed::VeryHigh);
d1.set_speed(Speed::VeryHigh);
d2.set_speed(Speed::VeryHigh);
d3.set_speed(Speed::VeryHigh);
clk.set_as_af(clk.af_num(), CLK_AF);
cmd.set_as_af(cmd.af_num(), CMD_AF);
d0.set_as_af(d0.af_num(), DATA_AF);
d1.set_as_af(d1.af_num(), DATA_AF);
d2.set_as_af(d2.af_num(), DATA_AF);
d3.set_as_af(d3.af_num(), DATA_AF);
});
Self::new_inner(
@ -388,13 +386,9 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
into_ref!(clk, cmd, d0);
critical_section::with(|_| {
clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None);
cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up);
d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up);
clk.set_speed(Speed::VeryHigh);
cmd.set_speed(Speed::VeryHigh);
d0.set_speed(Speed::VeryHigh);
clk.set_as_af(clk.af_num(), CLK_AF);
cmd.set_as_af(cmd.af_num(), CMD_AF);
d0.set_as_af(d0.af_num(), DATA_AF);
});
Self::new_inner(
@ -425,19 +419,12 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
into_ref!(clk, cmd, d0, d1, d2, d3);
critical_section::with(|_| {
clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None);
cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up);
d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up);
d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::Up);
d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::Up);
d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::Up);
clk.set_speed(Speed::VeryHigh);
cmd.set_speed(Speed::VeryHigh);
d0.set_speed(Speed::VeryHigh);
d1.set_speed(Speed::VeryHigh);
d2.set_speed(Speed::VeryHigh);
d3.set_speed(Speed::VeryHigh);
clk.set_as_af(clk.af_num(), CLK_AF);
cmd.set_as_af(cmd.af_num(), CMD_AF);
d0.set_as_af(d0.af_num(), DATA_AF);
d1.set_as_af(d1.af_num(), DATA_AF);
d2.set_as_af(d2.af_num(), DATA_AF);
d3.set_as_af(d3.af_num(), DATA_AF);
});
Self::new_inner(

View File

@ -10,7 +10,7 @@ use embassy_hal_internal::PeripheralRef;
pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
use crate::dma::{word, ChannelAndRequest};
use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed};
use crate::gpio::{AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed};
use crate::mode::{Async, Blocking, Mode as PeriMode};
use crate::pac::spi::{regs, vals, Spi as Regs};
use crate::rcc::{RccInfo, SealedRccPeripheral};
@ -90,11 +90,21 @@ impl Config {
}
}
fn sck_pull_mode(&self) -> Pull {
match self.mode.polarity {
Polarity::IdleLow => Pull::Down,
Polarity::IdleHigh => Pull::Up,
}
#[cfg(gpio_v1)]
fn sck_af(&self) -> AfType {
AfType::output(OutputType::PushPull, Speed::VeryHigh)
}
#[cfg(gpio_v2)]
fn sck_af(&self) -> AfType {
AfType::output_pull(
OutputType::PushPull,
Speed::VeryHigh,
match self.mode.polarity {
Polarity::IdleLow => Pull::Down,
Polarity::IdleHigh => Pull::Up,
},
)
}
}
/// SPI driver.
@ -453,9 +463,9 @@ impl<'d> Spi<'d, Blocking> {
) -> Self {
Self::new_inner(
peri,
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()),
new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(miso, AFType::Input, Speed::VeryHigh, config.miso_pull),
new_pin!(sck, config.sck_af()),
new_pin!(mosi, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(miso, AfType::input(config.miso_pull)),
None,
None,
config,
@ -471,9 +481,9 @@ impl<'d> Spi<'d, Blocking> {
) -> Self {
Self::new_inner(
peri,
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()),
new_pin!(sck, config.sck_af()),
None,
new_pin!(miso, AFType::Input, Speed::VeryHigh, config.miso_pull),
new_pin!(miso, AfType::input(config.miso_pull)),
None,
None,
config,
@ -489,8 +499,8 @@ impl<'d> Spi<'d, Blocking> {
) -> Self {
Self::new_inner(
peri,
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()),
new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(sck, config.sck_af()),
new_pin!(mosi, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
None,
None,
None,
@ -509,7 +519,7 @@ impl<'d> Spi<'d, Blocking> {
Self::new_inner(
peri,
None,
new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(mosi, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
None,
None,
None,
@ -531,9 +541,9 @@ impl<'d> Spi<'d, Async> {
) -> Self {
Self::new_inner(
peri,
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()),
new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(miso, AFType::Input, Speed::VeryHigh),
new_pin!(sck, config.sck_af()),
new_pin!(mosi, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(miso, AfType::input(config.miso_pull)),
new_dma!(tx_dma),
new_dma!(rx_dma),
config,
@ -551,9 +561,9 @@ impl<'d> Spi<'d, Async> {
) -> Self {
Self::new_inner(
peri,
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()),
new_pin!(sck, config.sck_af()),
None,
new_pin!(miso, AFType::Input, Speed::VeryHigh),
new_pin!(miso, AfType::input(config.miso_pull)),
#[cfg(any(spi_v1, spi_f1, spi_v2))]
new_dma!(tx_dma),
#[cfg(any(spi_v3, spi_v4, spi_v5))]
@ -573,8 +583,8 @@ impl<'d> Spi<'d, Async> {
) -> Self {
Self::new_inner(
peri,
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()),
new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(sck, config.sck_af()),
new_pin!(mosi, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
None,
new_dma!(tx_dma),
None,
@ -594,7 +604,7 @@ impl<'d> Spi<'d, Async> {
Self::new_inner(
peri,
None,
new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
new_pin!(mosi, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
None,
new_dma!(tx_dma),
None,

View File

@ -32,9 +32,10 @@ macro_rules! complementary_channel_impl {
into_ref!(pin);
critical_section::with(|_| {
pin.set_low();
pin.set_as_af(pin.af_num(), output_type.into());
#[cfg(gpio_v2)]
pin.set_speed(crate::gpio::Speed::VeryHigh);
pin.set_as_af(
pin.af_num(),
crate::gpio::AfType::output(output_type, crate::gpio::Speed::VeryHigh),
);
});
ComplementaryPwmPin {
_pin: pin.map_into(),

View File

@ -12,7 +12,7 @@ use super::{
CaptureCompareInterruptHandler, Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin,
GeneralInstance4Channel,
};
use crate::gpio::{AFType, AnyPin, Pull};
use crate::gpio::{AfType, AnyPin, Pull};
use crate::interrupt::typelevel::{Binding, Interrupt};
use crate::time::Hertz;
use crate::Peripheral;
@ -38,11 +38,9 @@ macro_rules! channel_impl {
($new_chx:ident, $channel:ident, $pin_trait:ident) => {
impl<'d, T: GeneralInstance4Channel> CapturePin<'d, T, $channel> {
#[doc = concat!("Create a new ", stringify!($channel), " capture pin instance.")]
pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, pull_type: Pull) -> Self {
pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, pull: Pull) -> Self {
into_ref!(pin);
pin.set_as_af_pull(pin.af_num(), AFType::Input, pull_type);
pin.set_as_af(pin.af_num(), AfType::input(pull));
CapturePin {
_pin: pin.map_into(),
phantom: PhantomData,

View File

@ -4,7 +4,7 @@ use embassy_hal_internal::into_ref;
use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource};
use super::{Channel, Channel1Pin, Channel2Pin, GeneralInstance4Channel};
use crate::gpio::{AFType, Pull};
use crate::gpio::{AfType, Pull};
use crate::time::Hertz;
use crate::Peripheral;
@ -19,12 +19,12 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
pub fn new(
tim: impl Peripheral<P = T> + 'd,
pin: impl Peripheral<P = impl Channel1Pin<T>> + 'd,
pull_type: Pull,
pull: Pull,
freq: Hertz,
) -> Self {
into_ref!(pin);
pin.set_as_af_pull(pin.af_num(), AFType::Input, pull_type);
pin.set_as_af(pin.af_num(), AfType::input(pull));
Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2)
}
@ -33,12 +33,12 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
pub fn new_alt(
tim: impl Peripheral<P = T> + 'd,
pin: impl Peripheral<P = impl Channel2Pin<T>> + 'd,
pull_type: Pull,
pull: Pull,
freq: Hertz,
) -> Self {
into_ref!(pin);
pin.set_as_af_pull(pin.af_num(), AFType::Input, pull_type);
pin.set_as_af(pin.af_num(), AfType::input(pull));
Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1)
}

View File

@ -7,7 +7,7 @@ use stm32_metapac::timer::vals;
use super::low_level::Timer;
use super::{Channel1Pin, Channel2Pin, GeneralInstance4Channel};
use crate::gpio::{AFType, AnyPin};
use crate::gpio::{AfType, AnyPin, Pull};
use crate::Peripheral;
/// Counting direction
@ -37,9 +37,7 @@ macro_rules! channel_impl {
into_ref!(pin);
critical_section::with(|_| {
pin.set_low();
pin.set_as_af(pin.af_num(), AFType::Input);
#[cfg(gpio_v2)]
pin.set_speed(crate::gpio::Speed::VeryHigh);
pin.set_as_af(pin.af_num(), AfType::input(Pull::None));
});
QeiPin {
_pin: pin.map_into(),

View File

@ -6,7 +6,7 @@ use embassy_hal_internal::{into_ref, PeripheralRef};
use super::low_level::{CountingMode, OutputCompareMode, OutputPolarity, Timer};
use super::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance4Channel};
use crate::gpio::{AnyPin, OutputType};
use crate::gpio::{AfType, AnyPin, OutputType, Speed};
use crate::time::Hertz;
use crate::Peripheral;
@ -35,9 +35,7 @@ macro_rules! channel_impl {
into_ref!(pin);
critical_section::with(|_| {
pin.set_low();
pin.set_as_af(pin.af_num(), output_type.into());
#[cfg(gpio_v2)]
pin.set_speed(crate::gpio::Speed::VeryHigh);
pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh));
});
PwmPin {
_pin: pin.map_into(),

View File

@ -70,7 +70,7 @@ use core::marker::PhantomData;
use embassy_hal_internal::{into_ref, PeripheralRef};
pub use enums::*;
use crate::gpio::{AFType, AnyPin};
use crate::gpio::{AfType, AnyPin, OutputType, Speed};
use crate::pac::tsc::Tsc as Regs;
use crate::rcc::{self, RccPeripheral};
use crate::{peripherals, Peripheral};
@ -371,11 +371,14 @@ macro_rules! group_impl {
pin.set_low();
pin.set_as_af(
pin.af_num(),
match role {
PinType::Channel => AFType::OutputPushPull,
PinType::Sample => AFType::OutputOpenDrain,
PinType::Shield => AFType::OutputPushPull,
},
AfType::output(
match role {
PinType::Channel => OutputType::PushPull,
PinType::Sample => OutputType::OpenDrain,
PinType::Shield => OutputType::PushPull,
},
Speed::VeryHigh,
),
);
self.d1 = Some(TscPin {
_pin: pin.map_into(),
@ -392,11 +395,14 @@ macro_rules! group_impl {
pin.set_low();
pin.set_as_af(
pin.af_num(),
match role {
PinType::Channel => AFType::OutputPushPull,
PinType::Sample => AFType::OutputOpenDrain,
PinType::Shield => AFType::OutputPushPull,
},
AfType::output(
match role {
PinType::Channel => OutputType::PushPull,
PinType::Sample => OutputType::OpenDrain,
PinType::Shield => OutputType::PushPull,
},
Speed::VeryHigh,
),
);
self.d2 = Some(TscPin {
_pin: pin.map_into(),
@ -413,11 +419,14 @@ macro_rules! group_impl {
pin.set_low();
pin.set_as_af(
pin.af_num(),
match role {
PinType::Channel => AFType::OutputPushPull,
PinType::Sample => AFType::OutputOpenDrain,
PinType::Shield => AFType::OutputPushPull,
},
AfType::output(
match role {
PinType::Channel => OutputType::PushPull,
PinType::Sample => OutputType::OpenDrain,
PinType::Shield => OutputType::PushPull,
},
Speed::VeryHigh,
),
);
self.d3 = Some(TscPin {
_pin: pin.map_into(),
@ -434,11 +443,14 @@ macro_rules! group_impl {
pin.set_low();
pin.set_as_af(
pin.af_num(),
match role {
PinType::Channel => AFType::OutputPushPull,
PinType::Sample => AFType::OutputOpenDrain,
PinType::Shield => AFType::OutputPushPull,
},
AfType::output(
match role {
PinType::Channel => OutputType::PushPull,
PinType::Sample => OutputType::OpenDrain,
PinType::Shield => OutputType::PushPull,
},
Speed::VeryHigh,
),
);
self.d4 = Some(TscPin {
_pin: pin.map_into(),

View File

@ -15,7 +15,7 @@ use super::{
clear_interrupt_flags, configure, rdr, reconfigure, sr, tdr, Config, ConfigError, CtsPin, Error, Info, Instance,
Regs, RtsPin, RxPin, TxPin,
};
use crate::gpio::{AFType, AnyPin, SealedPin as _};
use crate::gpio::{AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed};
use crate::interrupt::{self, InterruptExt};
use crate::time::Hertz;
@ -210,8 +210,8 @@ impl<'d> BufferedUart<'d> {
) -> Result<Self, ConfigError> {
Self::new_inner(
peri,
new_pin!(rx, AFType::Input),
new_pin!(tx, AFType::OutputPushPull),
new_pin!(rx, AfType::input(Pull::None)),
new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)),
None,
None,
None,
@ -235,10 +235,10 @@ impl<'d> BufferedUart<'d> {
) -> Result<Self, ConfigError> {
Self::new_inner(
peri,
new_pin!(rx, AFType::Input),
new_pin!(tx, AFType::OutputPushPull),
new_pin!(rts, AFType::OutputPushPull),
new_pin!(cts, AFType::Input),
new_pin!(rx, AfType::input(Pull::None)),
new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)),
new_pin!(rts, AfType::output(OutputType::PushPull, Speed::Medium)),
new_pin!(cts, AfType::input(Pull::None)),
None,
tx_buffer,
rx_buffer,
@ -260,11 +260,11 @@ impl<'d> BufferedUart<'d> {
) -> Result<Self, ConfigError> {
Self::new_inner(
peri,
new_pin!(rx, AFType::Input),
new_pin!(tx, AFType::OutputPushPull),
new_pin!(rx, AfType::input(Pull::None)),
new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)),
None,
None,
new_pin!(de, AFType::OutputPushPull),
new_pin!(de, AfType::output(OutputType::PushPull, Speed::Medium)),
tx_buffer,
rx_buffer,
config,

View File

@ -14,7 +14,7 @@ use embassy_sync::waitqueue::AtomicWaker;
use futures_util::future::{select, Either};
use crate::dma::ChannelAndRequest;
use crate::gpio::{AFType, AnyPin, SealedPin as _};
use crate::gpio::{AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed};
use crate::interrupt::typelevel::Interrupt as _;
use crate::interrupt::{self, Interrupt, InterruptExt};
use crate::mode::{Async, Blocking, Mode};
@ -159,11 +159,11 @@ pub struct Config {
#[cfg(any(usart_v3, usart_v4))]
pub swap_rx_tx: bool,
/// Set this to true to invert TX pin signal values (V<sub>DD</sub> =0/mark, Gnd = 1/idle).
/// Set this to true to invert TX pin signal values (V<sub>DD</sub> = 0/mark, Gnd = 1/idle).
#[cfg(any(usart_v3, usart_v4))]
pub invert_tx: bool,
/// Set this to true to invert RX pin signal values (V<sub>DD</sub> =0/mark, Gnd = 1/idle).
/// Set this to true to invert RX pin signal values (V<sub>DD</sub> = 0/mark, Gnd = 1/idle).
#[cfg(any(usart_v3, usart_v4))]
pub invert_rx: bool,
@ -172,19 +172,20 @@ pub struct Config {
}
impl Config {
fn tx_af(&self) -> AFType {
fn tx_af(&self) -> AfType {
#[cfg(any(usart_v3, usart_v4))]
if self.swap_rx_tx {
return AFType::Input;
return AfType::input(Pull::None);
};
AFType::OutputPushPull
AfType::output(OutputType::PushPull, Speed::Medium)
}
fn rx_af(&self) -> AFType {
fn rx_af(&self) -> AfType {
#[cfg(any(usart_v3, usart_v4))]
if self.swap_rx_tx {
return AFType::OutputPushPull;
return AfType::output(OutputType::PushPull, Speed::Medium);
};
AFType::Input
AfType::input(Pull::None)
}
}
@ -342,7 +343,7 @@ impl<'d> UartTx<'d, Async> {
) -> Result<Self, ConfigError> {
Self::new_inner(
peri,
new_pin!(tx, AFType::OutputPushPull),
new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)),
None,
new_dma!(tx_dma),
config,
@ -359,8 +360,8 @@ impl<'d> UartTx<'d, Async> {
) -> Result<Self, ConfigError> {
Self::new_inner(
peri,
new_pin!(tx, AFType::OutputPushPull),
new_pin!(cts, AFType::Input),
new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)),
new_pin!(cts, AfType::input(Pull::None)),
new_dma!(tx_dma),
config,
)
@ -401,7 +402,13 @@ impl<'d> UartTx<'d, Blocking> {
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
config: Config,
) -> Result<Self, ConfigError> {
Self::new_inner(peri, new_pin!(tx, AFType::OutputPushPull), None, None, config)
Self::new_inner(
peri,
new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)),
None,
None,
config,
)
}
/// Create a new blocking tx-only UART with a clear-to-send pin
@ -413,8 +420,8 @@ impl<'d> UartTx<'d, Blocking> {
) -> Result<Self, ConfigError> {
Self::new_inner(
peri,
new_pin!(tx, AFType::OutputPushPull),
new_pin!(cts, AFType::Input),
new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)),
new_pin!(cts, AfType::input(Pull::None)),
None,
config,
)
@ -508,7 +515,13 @@ impl<'d> UartRx<'d, Async> {
rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
config: Config,
) -> Result<Self, ConfigError> {
Self::new_inner(peri, new_pin!(rx, AFType::Input), None, new_dma!(rx_dma), config)
Self::new_inner(
peri,
new_pin!(rx, AfType::input(Pull::None)),
None,
new_dma!(rx_dma),
config,
)
}
/// Create a new rx-only UART with a request-to-send pin
@ -522,8 +535,8 @@ impl<'d> UartRx<'d, Async> {
) -> Result<Self, ConfigError> {
Self::new_inner(
peri,
new_pin!(rx, AFType::Input),
new_pin!(rts, AFType::OutputPushPull),
new_pin!(rx, AfType::input(Pull::None)),
new_pin!(rts, AfType::output(OutputType::PushPull, Speed::Medium)),
new_dma!(rx_dma),
config,
)
@ -751,7 +764,7 @@ impl<'d> UartRx<'d, Blocking> {
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
config: Config,
) -> Result<Self, ConfigError> {
Self::new_inner(peri, new_pin!(rx, AFType::Input), None, None, config)
Self::new_inner(peri, new_pin!(rx, AfType::input(Pull::None)), None, None, config)
}
/// Create a new rx-only UART with a request-to-send pin
@ -763,8 +776,8 @@ impl<'d> UartRx<'d, Blocking> {
) -> Result<Self, ConfigError> {
Self::new_inner(
peri,
new_pin!(rx, AFType::Input),
new_pin!(rts, AFType::OutputPushPull),
new_pin!(rx, AfType::input(Pull::None)),
new_pin!(rts, AfType::output(OutputType::PushPull, Speed::Medium)),
None,
config,
)
@ -968,8 +981,8 @@ impl<'d> Uart<'d, Async> {
peri,
new_pin!(rx, config.rx_af()),
new_pin!(tx, config.tx_af()),
new_pin!(rts, AFType::OutputPushPull),
new_pin!(cts, AFType::Input),
new_pin!(rts, AfType::output(OutputType::PushPull, Speed::Medium)),
new_pin!(cts, AfType::input(Pull::None)),
None,
new_dma!(tx_dma),
new_dma!(rx_dma),
@ -995,7 +1008,7 @@ impl<'d> Uart<'d, Async> {
new_pin!(tx, config.tx_af()),
None,
None,
new_pin!(de, AFType::OutputPushPull),
new_pin!(de, AfType::output(OutputType::PushPull, Speed::Medium)),
new_dma!(tx_dma),
new_dma!(rx_dma),
config,
@ -1030,7 +1043,7 @@ impl<'d> Uart<'d, Async> {
Self::new_inner(
peri,
None,
new_pin!(tx, AFType::OutputPushPull),
new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)),
None,
None,
None,
@ -1066,7 +1079,7 @@ impl<'d> Uart<'d, Async> {
peri,
None,
None,
new_pin!(rx, AFType::OutputPushPull),
new_pin!(rx, AfType::output(OutputType::PushPull, Speed::Medium)),
None,
None,
new_dma!(tx_dma),
@ -1125,8 +1138,8 @@ impl<'d> Uart<'d, Blocking> {
peri,
new_pin!(rx, config.rx_af()),
new_pin!(tx, config.tx_af()),
new_pin!(rts, AFType::OutputPushPull),
new_pin!(cts, AFType::Input),
new_pin!(rts, AfType::output(OutputType::PushPull, Speed::Medium)),
new_pin!(cts, AfType::input(Pull::None)),
None,
None,
None,
@ -1149,7 +1162,7 @@ impl<'d> Uart<'d, Blocking> {
new_pin!(tx, config.tx_af()),
None,
None,
new_pin!(de, AFType::OutputPushPull),
new_pin!(de, AfType::output(OutputType::PushPull, Speed::Medium)),
None,
None,
config,
@ -1181,7 +1194,7 @@ impl<'d> Uart<'d, Blocking> {
Self::new_inner(
peri,
None,
new_pin!(tx, AFType::OutputPushPull),
new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)),
None,
None,
None,
@ -1214,7 +1227,7 @@ impl<'d> Uart<'d, Blocking> {
peri,
None,
None,
new_pin!(rx, AFType::OutputPushPull),
new_pin!(rx, AfType::output(OutputType::PushPull, Speed::Medium)),
None,
None,
None,

View File

@ -10,7 +10,7 @@ use embassy_usb_synopsys_otg::{
PhyType, State,
};
use crate::gpio::AFType;
use crate::gpio::{AfType, OutputType, Speed};
use crate::interrupt;
use crate::interrupt::typelevel::Interrupt;
use crate::rcc::{self, RccPeripheral};
@ -39,9 +39,7 @@ macro_rules! config_ulpi_pins {
into_ref!($($pin),*);
critical_section::with(|_| {
$(
$pin.set_as_af($pin.af_num(), AFType::OutputPushPull);
#[cfg(gpio_v2)]
$pin.set_speed(crate::gpio::Speed::VeryHigh);
$pin.set_as_af($pin.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
)*
})
};
@ -77,8 +75,8 @@ impl<'d, T: Instance> Driver<'d, T> {
) -> Self {
into_ref!(dp, dm);
dp.set_as_af(dp.af_num(), AFType::OutputPushPull);
dm.set_as_af(dm.af_num(), AFType::OutputPushPull);
dp.set_as_af(dp.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
dm.set_as_af(dm.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
let regs = T::regs();

View File

@ -277,8 +277,9 @@ impl<'d, T: Instance> Driver<'d, T> {
#[cfg(not(stm32l1))]
{
dp.set_as_af(dp.af_num(), crate::gpio::AFType::OutputPushPull);
dm.set_as_af(dm.af_num(), crate::gpio::AFType::OutputPushPull);
use crate::gpio::{AfType, OutputType, Speed};
dp.set_as_af(dp.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
dm.set_as_af(dm.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
}
#[cfg(stm32l1)]
let _ = (dp, dm); // suppress "unused" warnings.

View File

@ -3,7 +3,7 @@
use defmt::*;
use embassy_executor::Spawner;
use embassy_stm32::gpio::{AFType, Flex, Pull, Speed};
use embassy_stm32::gpio::{AfType, Flex, OutputType, Speed};
use embassy_stm32::time::{khz, Hertz};
use embassy_stm32::timer::low_level::{OutputCompareMode, Timer as LLTimer};
use embassy_stm32::timer::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance32bit4Channel};
@ -83,10 +83,10 @@ impl<'d, T: GeneralInstance32bit4Channel> SimplePwm32<'d, T> {
let mut ch2 = Flex::new(ch2);
let mut ch3 = Flex::new(ch3);
let mut ch4 = Flex::new(ch4);
ch1.set_as_af_unchecked(af1, AFType::OutputPushPull, Pull::None, Speed::VeryHigh);
ch2.set_as_af_unchecked(af2, AFType::OutputPushPull, Pull::None, Speed::VeryHigh);
ch3.set_as_af_unchecked(af3, AFType::OutputPushPull, Pull::None, Speed::VeryHigh);
ch4.set_as_af_unchecked(af4, AFType::OutputPushPull, Pull::None, Speed::VeryHigh);
ch1.set_as_af_unchecked(af1, AfType::output(OutputType::PushPull, Speed::VeryHigh));
ch2.set_as_af_unchecked(af2, AfType::output(OutputType::PushPull, Speed::VeryHigh));
ch3.set_as_af_unchecked(af3, AfType::output(OutputType::PushPull, Speed::VeryHigh));
ch4.set_as_af_unchecked(af4, AfType::output(OutputType::PushPull, Speed::VeryHigh));
let mut this = Self {
tim: LLTimer::new(tim),

View File

@ -112,7 +112,7 @@ async fn main(_spawner: Spawner) {
let b = Input::new(&mut b, Pull::Down);
// no pull, the status is undefined
let mut a = OutputOpenDrain::new(&mut a, Level::Low, Speed::Low, Pull::None);
let mut a = OutputOpenDrain::new(&mut a, Level::Low, Speed::Low);
delay();
assert!(b.is_low());
a.set_high(); // High-Z output
@ -203,7 +203,7 @@ async fn main(_spawner: Spawner) {
let mut a = Flex::new(&mut a);
a.set_low();
a.set_as_input_output(Speed::Low, Pull::None);
a.set_as_input_output(Speed::Low);
delay();
assert!(b.is_low());
a.set_high(); // High-Z output