diff --git a/.gitignore b/.gitignore index 1c221e876c..7bd11d93d0 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ Cargo.lock third_party /Cargo.toml out/ +Session.vim diff --git a/embassy-stm32/src/can/bxcan/mod.rs b/embassy-stm32/src/can/bxcan/mod.rs index 53b94b9e2c..278c93ff40 100644 --- a/embassy-stm32/src/can/bxcan/mod.rs +++ b/embassy-stm32/src/can/bxcan/mod.rs @@ -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::(); @@ -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(); diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs index f3ad718ae3..c549313f35 100644 --- a/embassy-stm32/src/can/fdcan.rs +++ b/embassy-stm32/src/can/fdcan.rs @@ -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::(); @@ -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 diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs index 858ae49ca0..4ba4e824eb 100644 --- a/embassy-stm32/src/dcmi.rs +++ b/embassy-stm32/src/dcmi.rs @@ -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)); )* }) }; diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index 3f5687a62e..e4a8cef909 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs @@ -17,7 +17,7 @@ mod dmamux; pub(crate) use dmamux::*; mod util; -pub(crate) use util::*; +pub use util::ChannelAndRequest; pub(crate) mod ringbuffer; pub mod word; diff --git a/embassy-stm32/src/dma/util.rs b/embassy-stm32/src/dma/util.rs index 5aaca57c9c..aad2955476 100644 --- a/embassy-stm32/src/dma/util.rs +++ b/embassy-stm32/src/dma/util.rs @@ -3,15 +3,18 @@ use embassy_hal_internal::PeripheralRef; use super::word::Word; use super::{AnyChannel, Request, Transfer, TransferOptions}; -/// Convenience wrapper, contains a channel and a request number. +/// Convenience wrapper, contains a DMA channel and a DMA request number. /// /// Commonly used in peripheral drivers that own DMA channels. -pub(crate) struct ChannelAndRequest<'d> { +pub struct ChannelAndRequest<'d> { + /// DMA channel. pub channel: PeripheralRef<'d, AnyChannel>, + /// DMA request. pub request: Request, } impl<'d> ChannelAndRequest<'d> { + /// See [`Transfer::new_read()`]. pub unsafe fn read<'a, W: Word>( &'a mut self, peri_addr: *mut W, @@ -21,6 +24,7 @@ impl<'d> ChannelAndRequest<'d> { Transfer::new_read(&mut self.channel, self.request, peri_addr, buf, options) } + /// See [`Transfer::new_read_raw()`]. pub unsafe fn read_raw<'a, W: Word>( &'a mut self, peri_addr: *mut W, @@ -30,6 +34,7 @@ impl<'d> ChannelAndRequest<'d> { Transfer::new_read_raw(&mut self.channel, self.request, peri_addr, buf, options) } + /// See [`Transfer::new_write()`]. pub unsafe fn write<'a, W: Word>( &'a mut self, buf: &'a [W], @@ -39,6 +44,7 @@ impl<'d> ChannelAndRequest<'d> { Transfer::new_write(&mut self.channel, self.request, buf, peri_addr, options) } + /// See [`Transfer::new_write_raw()`]. pub unsafe fn write_raw<'a, W: Word>( &'a mut self, buf: *const [W], @@ -48,7 +54,7 @@ impl<'d> ChannelAndRequest<'d> { Transfer::new_write_raw(&mut self.channel, self.request, buf, peri_addr, options) } - #[allow(dead_code)] + /// See [`Transfer::new_write_repeated()`]. pub unsafe fn write_repeated<'a, W: Word>( &'a mut self, repeated: &'a W, diff --git a/embassy-stm32/src/dsihost.rs b/embassy-stm32/src/dsihost.rs index e1fb3b0b08..6271cedcaf 100644 --- a/embassy-stm32/src/dsihost.rs +++ b/embassy-stm32/src/dsihost.rs @@ -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::(); // 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); diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs index 6f0174def2..cce75ece7d 100644 --- a/embassy-stm32/src/eth/v1/mod.rs +++ b/embassy-stm32/src/eth/v1/mod.rs @@ -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)); )* }) }; diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index a19aa42cfe..b26f08cd94 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs @@ -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)); )* }) }; diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs index 82d8089f44..7aea466e86 100644 --- a/embassy-stm32/src/fmc.rs +++ b/embassy-stm32/src/fmc.rs @@ -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)); )* }; } diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index de08127cf9..86bc226a99 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs @@ -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 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 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 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

+ 'd, initial_output: Level, speed: Speed, pull: Pull) -> Self { + pub fn new(pin: impl Peripheral

+ '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

+ '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 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(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, } } } -/// 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, +#[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())) } } diff --git a/embassy-stm32/src/hrtim/mod.rs b/embassy-stm32/src/hrtim/mod.rs index c9d5bff174..13343fc2ae 100644 --- a/embassy-stm32/src/hrtim/mod.rs +++ b/embassy-stm32/src/hrtim/mod.rs @@ -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(), diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 6d12af2cc9..e14d223025 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -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, diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs index f893dd2358..094de2461a 100644 --- a/embassy-stm32/src/i2s.rs +++ b/embassy-stm32/src/i2s.rs @@ -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; diff --git a/embassy-stm32/src/ltdc.rs b/embassy-stm32/src/ltdc.rs index c262e7a0c2..481d778431 100644 --- a/embassy-stm32/src/ltdc.rs +++ b/embassy-stm32/src/ltdc.rs @@ -62,11 +62,10 @@ impl<'d, T: Instance> Ltdc<'d, T> { rcc::enable_and_reset::(); - //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); diff --git a/embassy-stm32/src/macros.rs b/embassy-stm32/src/macros.rs index dcd25cbe9c..cf961b954a 100644 --- a/embassy-stm32/src/macros.rs +++ b/embassy-stm32/src/macros.rs @@ -66,7 +66,7 @@ macro_rules! dma_trait { ($signal:ident, $instance:path$(, $mode:path)?) => { #[doc = concat!(stringify!($signal), " DMA request trait")] pub trait $signal: crate::dma::Channel { - #[doc = concat!("Get the DMA request number needed to use this channel as", stringify!($signal))] + #[doc = concat!("Get the DMA request number needed to use this channel as ", stringify!($signal))] /// Note: in some chips, ST calls this the "channel", and calls channels "streams". /// `embassy-stm32` always uses the "channel" and "request number" names. fn request(&self) -> crate::dma::Request; @@ -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()) }}; } diff --git a/embassy-stm32/src/ospi/mod.rs b/embassy-stm32/src/ospi/mod.rs index 882781cce9..f6eb0d17c9 100644 --- a/embassy-stm32/src/ospi/mod.rs +++ b/embassy-stm32/src/ospi/mod.rs @@ -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, diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index 06c8f48122..308947e994 100644 --- a/embassy-stm32/src/qspi/mod.rs +++ b/embassy-stm32/src/qspi/mod.rs @@ -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, diff --git a/embassy-stm32/src/rcc/mco.rs b/embassy-stm32/src/rcc/mco.rs index 40e963466c..d1ce14c86a 100644 --- a/embassy-stm32/src/rcc/mco.rs +++ b/embassy-stm32/src/rcc/mco.rs @@ -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 } diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index 3faecdc33a..b810029360 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs @@ -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: 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(); diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index 9c14837e19..ee5539518d 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs @@ -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 = NoDma> { card: Option, } +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> Sdmmc<'d, T, Dma> { /// Create a new SDMMC driver, with 1 data lane. @@ -307,13 +316,9 @@ impl<'d, T: Instance, Dma: SdmmcDma> 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> 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( diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 4eaf7777f8..5967cb492b 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -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::{slice_ptr_parts, 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, diff --git a/embassy-stm32/src/timer/bare.rs b/embassy-stm32/src/timer/bare.rs new file mode 100644 index 0000000000..56f06ad872 --- /dev/null +++ b/embassy-stm32/src/timer/bare.rs @@ -0,0 +1,296 @@ +//! Bare register-level timer driver. +//! +//! This module provides the core functionality for type-erased drivers for all STM32 timers. It +//! provides integration with the RCC and direct access to the timer registers. It is intended to +//! serve as a building block for higher level drivers. +use core::marker::PhantomData; + +use embassy_hal_internal::PeripheralRef; + +use super::{AdvancedInstance4Channel, BasicInstance, Channel, CoreInstance, GeneralInstance4Channel, Info, TimerBits}; +use crate::gpio::{AfType, AnyPin, Pin, SealedPin}; +use crate::time::Hertz; +use crate::{dma, into_ref, pac, rcc, Peripheral}; + +trait TimerPinMarkerSealed {} + +/// Trait for marker types that represent all possible timer pins. +#[allow(private_bounds)] +pub trait TimerPinMarker: TimerPinMarkerSealed {} + +/// Timer pin trait. +/// +/// If a pin peripheral implements `TimerPin`, it means that it can be used with timer `T` in +/// the role represented by marker type `M`. For example, `TimerPin` is implemented for +/// all pins that can be used as channel 2 for timer TIM1. +/// +/// This trait is equivalent to the pin-specific traits defined in the [`timer`][super] module; for +/// example `TimerPin` is equivalent to [`timer::Channel1Pin`][super::Channel1Pin]. +pub trait TimerPin: Pin { + /// Get the AF number needed to use this pin with timer `T` as pin `M`. + fn af_num(&self) -> u8; +} + +/// Marker type for channel 1. +pub enum Ch1 {} +/// Marker type for channel 2. +pub enum Ch2 {} +/// Marker type for channel 3. +pub enum Ch3 {} +/// Marker type for channel 4. +pub enum Ch4 {} +/// Marker type for external trigger pin. +pub enum Etr {} +/// Marker type for channel 1 complementary pin. +pub enum Ch1N {} +/// Marker type for channel 2 complementary pin. +pub enum Ch2N {} +/// Marker type for channel 3 complementary pin. +pub enum Ch3N {} +/// Marker type for channel 4 complementary pin. +pub enum Ch4N {} +/// Marker type for break input pin. +pub enum Bkin {} +/// Marker type for break input comparator 1 pin. +pub enum BkinComp1 {} +/// Marker type for break input comparator 2 pin. +pub enum BkinComp2 {} +/// Marker type for break 2 input pin. +pub enum Bkin2 {} +/// Marker type for break 2 input comparator 1 pin. +pub enum Bkin2Comp1 {} +/// Marker type for break 2 input comparator 2 pin. +pub enum Bkin2Comp2 {} + +macro_rules! impl_pin { + ($marker_ty:ident, $t:ident, $pin_trait:path, $peri_trait:ident) => { + impl TimerPinMarkerSealed for $marker_ty {} + impl TimerPinMarker for $marker_ty {} + + impl<$t: $peri_trait, P> TimerPin<$t, $marker_ty> for P + where + P: $pin_trait, + { + fn af_num(&self) -> u8 { +

::af_num(self) + } + } + }; +} + +impl_pin!(Ch1, T, super::Channel1Pin, GeneralInstance4Channel); +impl_pin!(Ch2, T, super::Channel2Pin, GeneralInstance4Channel); +impl_pin!(Ch3, T, super::Channel3Pin, GeneralInstance4Channel); +impl_pin!(Ch4, T, super::Channel4Pin, GeneralInstance4Channel); +impl_pin!(Etr, T, super::ExternalTriggerPin, GeneralInstance4Channel); + +impl_pin!(Ch1N, T, super::Channel1ComplementaryPin, AdvancedInstance4Channel); +impl_pin!(Ch2N, T, super::Channel2ComplementaryPin, AdvancedInstance4Channel); +impl_pin!(Ch3N, T, super::Channel3ComplementaryPin, AdvancedInstance4Channel); +impl_pin!(Ch4N, T, super::Channel4ComplementaryPin, AdvancedInstance4Channel); + +impl_pin!(Bkin, T, super::BreakInputPin, AdvancedInstance4Channel); +impl_pin!( + BkinComp1, + T, + super::BreakInputComparator1Pin, + AdvancedInstance4Channel +); +impl_pin!( + BkinComp2, + T, + super::BreakInputComparator2Pin, + AdvancedInstance4Channel +); + +impl_pin!(Bkin2, T, super::BreakInput2Pin, AdvancedInstance4Channel); +impl_pin!( + Bkin2Comp1, + T, + super::BreakInput2Comparator1Pin, + AdvancedInstance4Channel +); +impl_pin!( + Bkin2Comp2, + T, + super::BreakInput2Comparator2Pin, + AdvancedInstance4Channel +); + +/// Trait for marker types that represent the four channel pins ([`Ch1`], [`Ch2`], [`Ch3`], +/// [`Ch4`]). +pub trait TimerChannelMarker: TimerPinMarker { + /// Representation of the channel number. + const CHANNEL: Channel; +} + +macro_rules! impl_channel { + ($marker_ty:ident, $channel:expr) => { + impl TimerChannelMarker for $marker_ty { + const CHANNEL: Channel = $channel; + } + }; +} + +impl_channel!(Ch1, Channel::Ch1); +impl_channel!(Ch2, Channel::Ch2); +impl_channel!(Ch3, Channel::Ch3); +impl_channel!(Ch4, Channel::Ch4); + +/// Timer channel DMA trait. +/// +/// If a DMA channel implements `TimerChannelDma`, it means that it can be used with the DMA +/// request for channel `C` of timer `T`. For example, `TimerChannelDma` is implemented +/// for DMA channels that can be used with DMA request of channel 1 on timer TIM2. +/// +/// This trait is equivalent to the pin-specific traits defined in the [`timer`][super] module; for +/// example, `TimerChannelDma` is equivalent to [`timer::Ch1Dma`][super::Ch1Dma]. +pub trait TimerChannelDma: dma::Channel { + /// Get the DMA request number needed to use this DMA channel as DMA request for channel `C` of + /// timer peripheral `T`. + /// + /// Note: in some chips, ST calls this the "channel", and calls channels "streams". + /// `embassy-stm32` always uses the "channel" and "request number" names. + fn request(&self) -> dma::Request; +} + +macro_rules! impl_dma { + ($channel_ty:ident, $t:ident, $dma_trait:path) => { + impl<$t: GeneralInstance4Channel, D> TimerChannelDma<$t, $channel_ty> for D + where + D: $dma_trait, + { + fn request(&self) -> dma::Request { + ::request(self) + } + } + }; +} + +impl_dma!(Ch1, T, super::Ch1Dma); +impl_dma!(Ch2, T, super::Ch2Dma); +impl_dma!(Ch3, T, super::Ch3Dma); +impl_dma!(Ch4, T, super::Ch4Dma); + +/// Get type-erased DMA request and channel that can be used as the update DMA for timer `T`. +pub fn up_dma<'d, T>(dma: impl Peripheral

> + 'd) -> dma::ChannelAndRequest<'d> +where + T: BasicInstance, +{ + into_ref!(dma); + let request = dma.request(); + dma::ChannelAndRequest { + channel: dma.map_into(), + request, + } +} + +/// Get type-erased DMA request and channel that can be used as the DMA for channel `C` of timer `T`. +pub fn channel_dma<'d, T, C>(dma: impl Peripheral

> + 'd) -> dma::ChannelAndRequest<'d> +where + T: GeneralInstance4Channel, + C: TimerChannelMarker, +{ + into_ref!(dma); + let request = dma.request(); + dma::ChannelAndRequest { + channel: dma.map_into(), + request, + } +} + +/// Type-erased timer pin. +/// +/// The only purpose of this struct is to correctly initialize the pin in the constructor and +/// deinitialize it (set it as disconnected) in the constructor. It can be used to implement +/// higher-level pin wrappers, like [`simple_pwm::PwmPin`](super::simple_pwm::PwmPin). +pub struct AnyTimerPin<'d> { + pin: PeripheralRef<'d, AnyPin>, +} + +impl<'d> AnyTimerPin<'d> { + /// Initializes a timer pin `M` for timer instance `T`. + pub fn new( + pin: impl Peripheral

> + 'd, + af_type: AfType, + ) -> Self { + into_ref!(pin); + let af_num = pin.af_num(); + let pin = pin.map_into(); + pin.set_as_af(af_num, af_type); + Self { pin } + } +} + +impl<'d> Drop for AnyTimerPin<'d> { + fn drop(&mut self) { + self.pin.set_as_disconnected(); + } +} + +/// Type-erased bare driver for timers. +/// +/// This driver provides direct access to the timer registers, with the type of the peripheral +/// erased. +pub struct AnyTimer<'d, Regs> { + info: &'d Info, + kernel_clock: Hertz, + _phantom: PhantomData<&'d mut Regs>, +} + +macro_rules! impl_regs { + ($reg_ty:path, $new:ident, $peri_trait:path) => { + impl<'d> AnyTimer<'d, $reg_ty> { + /// Initializes timer instance `T`. + pub fn $new(_tim: impl Peripheral

+ 'd) -> Self { + rcc::enable_and_reset::(); + Self { + info: T::info(), + kernel_clock: T::frequency(), + _phantom: PhantomData, + } + } + + /// Get the registers for this timer. + pub fn regs(&self) -> $reg_ty { + unsafe { <$reg_ty>::from_ptr(self.info.regs) } + } + } + }; +} + +impl_regs!(pac::timer::TimCore, new_core, CoreInstance); +impl_regs!(pac::timer::TimBasicNoCr2, new_basic_no_cr2, super::BasicNoCr2Instance); +impl_regs!(pac::timer::TimBasic, new_basic, super::BasicInstance); +impl_regs!(pac::timer::Tim1ch, new_1ch, super::GeneralInstance1Channel); +impl_regs!(pac::timer::Tim2ch, new_2ch, super::GeneralInstance2Channel); +impl_regs!(pac::timer::TimGp16, new_gp16, GeneralInstance4Channel); +#[cfg(not(timer_l0))] +impl_regs!(pac::timer::TimGp32, new_gp32, super::GeneralInstance32bit4Channel); +#[cfg(not(timer_l0))] +impl_regs!(pac::timer::Tim1chCmp, new_1ch_cmp, super::AdvancedInstance1Channel); +#[cfg(not(timer_l0))] +impl_regs!(pac::timer::Tim2chCmp, new_2ch_cmp, super::AdvancedInstance2Channel); +#[cfg(not(timer_l0))] +impl_regs!(pac::timer::TimAdv, new_advanced, AdvancedInstance4Channel); + +impl<'d, Regs> AnyTimer<'d, Regs> { + /// Get the kernel clock frequency for the timer peripheral. + /// + /// Unless you switch the timer to a different clock source, this is the frequency that is fed + /// into the prescaler to drive the timer. + pub fn clock_frequency(&self) -> Hertz { + self.kernel_clock + } + + /// Get the number of bits in this timer (16 or 32). + pub fn bits(&self) -> TimerBits { + self.info.bits + } +} + +impl<'d, Regs> Drop for AnyTimer<'d, Regs> { + fn drop(&mut self) { + self.info.rcc.disable(); + } +} diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index a892646cf6..46ccbf3df9 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -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(), diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index 0258d4077c..341ac2c042 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs @@ -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

> + 'd, pull_type: Pull) -> Self { + pub fn $new_chx(pin: impl Peripheral

> + '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, diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 25782ee138..046278a1e2 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -4,6 +4,7 @@ use core::marker::PhantomData; use embassy_sync::waitqueue::AtomicWaker; +pub mod bare; #[cfg(not(stm32l0))] pub mod complementary_pwm; pub mod input_capture; @@ -13,7 +14,7 @@ pub mod qei; pub mod simple_pwm; use crate::interrupt; -use crate::rcc::RccPeripheral; +use crate::rcc::{RccInfo, RccPeripheral, SealedRccPeripheral}; /// Timer channel. #[derive(Clone, Copy)] @@ -66,14 +67,23 @@ impl State { } } -trait SealedInstance: RccPeripheral { +struct Info { + regs: *mut (), + rcc: RccInfo, + bits: TimerBits, +} + +unsafe impl Sync for Info {} + +trait SealedInstance { + fn info() -> &'static Info; /// Async state for this timer fn state() -> &'static State; } /// Core timer instance. #[allow(private_bounds)] -pub trait CoreInstance: SealedInstance + 'static { +pub trait CoreInstance: SealedInstance + RccPeripheral + 'static { /// Update Interrupt for this timer. type UpdateInterrupt: interrupt::typelevel::Interrupt; @@ -85,6 +95,7 @@ pub trait CoreInstance: SealedInstance + 'static { /// This is a raw pointer to the register block. The actual register block layout varies depending on the timer type. fn regs() -> *mut (); } + /// Cut-down basic timer instance. pub trait BasicNoCr2Instance: CoreInstance {} /// Basic timer instance. @@ -104,7 +115,7 @@ pub trait GeneralInstance2Channel: GeneralInstance1Channel { // This trait add *extra* methods to GeneralInstance4Channel, // that GeneralInstance4Channel doesn't use, but the "AdvancedInstance"s need. -// And it's a private trait, so it's content won't leak to outer namespace. +// And it's a private trait, so its content won't leak to outer namespace. // // If you want to add a new method to it, please leave a detail comment to explain it. trait General4ChBlankSealed { @@ -171,6 +182,15 @@ dma_trait!(Ch4Dma, GeneralInstance4Channel); macro_rules! impl_core_timer { ($inst:ident, $bits:expr) => { impl SealedInstance for crate::peripherals::$inst { + fn info() -> &'static Info { + static INFO: Info = Info { + regs: crate::pac::$inst.as_ptr(), + rcc: crate::peripherals::$inst::RCC_INFO, + bits: $bits, + }; + &INFO + } + fn state() -> &'static State { static STATE: State = State::new(); &STATE diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs index dcf098a78c..e3eb6042a9 100644 --- a/embassy-stm32/src/timer/pwm_input.rs +++ b/embassy-stm32/src/timer/pwm_input.rs @@ -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

+ 'd, pin: impl Peripheral

> + '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

+ 'd, pin: impl Peripheral

> + '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) } diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs index ab9879be6a..fc5835414c 100644 --- a/embassy-stm32/src/timer/qei.rs +++ b/embassy-stm32/src/timer/qei.rs @@ -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(), diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index b54e9a0d6b..b7771bd642 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -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(), diff --git a/embassy-stm32/src/tsc/mod.rs b/embassy-stm32/src/tsc/mod.rs index 045d6317c9..0fa5c99741 100644 --- a/embassy-stm32/src/tsc/mod.rs +++ b/embassy-stm32/src/tsc/mod.rs @@ -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(), diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index fd79e035e9..33bc009a8c 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -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::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::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::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, diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 53321391a3..5754f783e7 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -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 (VDD =0/mark, Gnd = 1/idle). + /// Set this to true to invert TX pin signal values (VDD = 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 (VDD =0/mark, Gnd = 1/idle). + /// Set this to true to invert RX pin signal values (VDD = 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::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::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

> + 'd, config: Config, ) -> Result { - 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::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

> + 'd, config: Config, ) -> Result { - 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::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

> + 'd, config: Config, ) -> Result { - 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::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, diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs index e5131250ac..8ee8dcc361 100644 --- a/embassy-stm32/src/usb/otg.rs +++ b/embassy-stm32/src/usb/otg.rs @@ -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(); diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index b6c88ac9a2..1d9d19a73e 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs @@ -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. diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs index a95b44b743..b796996eac 100644 --- a/examples/stm32h7/src/bin/low_level_timer_api.rs +++ b/examples/stm32h7/src/bin/low_level_timer_api.rs @@ -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), diff --git a/tests/stm32/src/bin/gpio.rs b/tests/stm32/src/bin/gpio.rs index dfa299ab5b..1d1018c5c4 100644 --- a/tests/stm32/src/bin/gpio.rs +++ b/tests/stm32/src/bin/gpio.rs @@ -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