stm32: Allow for open drain configuration for output pin
This commit is contained in:
parent
e1880a19df
commit
efb3b3a0a8
@ -18,6 +18,31 @@ pub enum Pull {
|
|||||||
Down,
|
Down,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pull setting for an input.
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
pub enum Speed {
|
||||||
|
LowSpeed,
|
||||||
|
MediumSpeed,
|
||||||
|
#[cfg(not(syscfg_f0))]
|
||||||
|
HighSpeed,
|
||||||
|
VeryHighSpeed,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Speed> for vals::Ospeedr {
|
||||||
|
fn from(speed: Speed) -> Self {
|
||||||
|
use Speed::*;
|
||||||
|
|
||||||
|
match speed {
|
||||||
|
LowSpeed => vals::Ospeedr::LOWSPEED,
|
||||||
|
MediumSpeed => vals::Ospeedr::MEDIUMSPEED,
|
||||||
|
#[cfg(not(syscfg_f0))]
|
||||||
|
HighSpeed => vals::Ospeedr::HIGHSPEED,
|
||||||
|
VeryHighSpeed => vals::Ospeedr::VERYHIGHSPEED,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// GPIO input driver.
|
/// GPIO input driver.
|
||||||
pub struct Input<'d, T: Pin> {
|
pub struct Input<'d, T: Pin> {
|
||||||
pub(crate) pin: T,
|
pub(crate) pin: T,
|
||||||
@ -86,7 +111,12 @@ pub struct Output<'d, T: Pin> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Pin> Output<'d, T> {
|
impl<'d, T: Pin> Output<'d, T> {
|
||||||
pub fn new(pin: impl Unborrow<Target = T> + 'd, initial_output: Level) -> Self {
|
pub fn new(
|
||||||
|
pin: impl Unborrow<Target = T> + 'd,
|
||||||
|
initial_output: Level,
|
||||||
|
speed: Speed,
|
||||||
|
open_drain: bool,
|
||||||
|
) -> Self {
|
||||||
unborrow!(pin);
|
unborrow!(pin);
|
||||||
|
|
||||||
match initial_output {
|
match initial_output {
|
||||||
@ -99,6 +129,10 @@ impl<'d, T: Pin> Output<'d, T> {
|
|||||||
let n = pin.pin() as usize;
|
let n = pin.pin() as usize;
|
||||||
r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING));
|
r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING));
|
||||||
r.moder().modify(|w| w.set_moder(n, vals::Moder::OUTPUT));
|
r.moder().modify(|w| w.set_moder(n, vals::Moder::OUTPUT));
|
||||||
|
if open_drain {
|
||||||
|
r.otyper().modify(|w| w.set_ot(n, vals::Ot::OPENDRAIN));
|
||||||
|
}
|
||||||
|
pin.set_speed(speed);
|
||||||
});
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@ -115,6 +149,8 @@ impl<'d, T: Pin> Drop for Output<'d, T> {
|
|||||||
let n = self.pin.pin() as usize;
|
let n = self.pin.pin() as usize;
|
||||||
r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING));
|
r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING));
|
||||||
r.moder().modify(|w| w.set_moder(n, vals::Moder::INPUT));
|
r.moder().modify(|w| w.set_moder(n, vals::Moder::INPUT));
|
||||||
|
r.otyper().modify(|w| w.set_ot(n, vals::Ot::PUSHPULL));
|
||||||
|
self.pin.set_speed(Speed::LowSpeed);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,6 +184,18 @@ impl<'d, T: Pin> StatefulOutputPin for Output<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Pin> InputPin for Output<'d, T> {
|
||||||
|
type Error = Infallible;
|
||||||
|
|
||||||
|
fn is_high(&self) -> Result<bool, Self::Error> {
|
||||||
|
self.is_set_high()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_low(&self) -> Result<bool, Self::Error> {
|
||||||
|
self.is_set_low()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'d, T: Pin> toggleable::Default for Output<'d, T> {}
|
impl<'d, T: Pin> toggleable::Default for Output<'d, T> {}
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
@ -206,6 +254,13 @@ pub(crate) mod sealed {
|
|||||||
.moder()
|
.moder()
|
||||||
.modify(|w| w.set_moder(pin, vals::Moder::ANALOG));
|
.modify(|w| w.set_moder(pin, vals::Moder::ANALOG));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn set_speed(&self, speed: Speed) {
|
||||||
|
let pin = self._pin() as usize;
|
||||||
|
self.block()
|
||||||
|
.ospeedr()
|
||||||
|
.modify(|w| w.set_ospeedr(pin, speed.into()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait OptionalPin {}
|
pub trait OptionalPin {}
|
||||||
|
Loading…
Reference in New Issue
Block a user