stm32: centralize gpio reg access in the gpio module.

This commit is contained in:
Dario Nieuwenhuis 2022-02-24 02:36:30 +01:00
parent 29aa51a1ad
commit bf80504ac7
9 changed files with 115 additions and 288 deletions

View File

@ -11,9 +11,7 @@ use embassy_hal_common::unborrow;
use embassy_net::{Device, DeviceCapabilities, LinkState, PacketBuf, MTU};
use crate::gpio::sealed::Pin as __GpioPin;
use crate::gpio::Pin as GpioPin;
use crate::gpio::{sealed::AFType, AnyPin, Speed};
use crate::pac::gpio::vals::Ospeedr;
use crate::pac::{ETH, RCC, SYSCFG};
mod descriptors;
@ -308,15 +306,12 @@ impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> Drop
dma.dmaomr().modify(|w| w.set_sr(DmaomrSr::STOPPED));
}
for pin in self.pins.iter_mut() {
// NOTE(unsafe) Exclusive access to the regs
critical_section::with(|_| unsafe {
pin.set_as_analog();
pin.block()
.ospeedr()
.modify(|w| w.set_ospeedr(pin.pin() as usize, Ospeedr::LOWSPEED));
})
}
// NOTE(unsafe) Exclusive access to the regs
critical_section::with(|_| unsafe {
for pin in self.pins.iter_mut() {
pin.set_as_disconnected();
}
})
}
}

View File

@ -304,13 +304,12 @@ impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> Drop
dma.dmacrx_cr().modify(|w| w.set_sr(false));
}
for pin in self.pins.iter_mut() {
// NOTE(unsafe) Exclusive access to the regs
critical_section::with(|_| unsafe {
pin.set_as_analog();
pin.set_speed(Speed::Low);
})
}
// NOTE(unsafe) Exclusive access to the regs
critical_section::with(|_| unsafe {
for pin in self.pins.iter_mut() {
pin.set_as_disconnected();
}
})
}
}

View File

@ -2,9 +2,8 @@ use core::marker::PhantomData;
use embassy::util::Unborrow;
use embassy_hal_common::unborrow;
use crate::gpio::sealed::AFType::OutputPushPull;
use crate::gpio::Speed;
use crate::pac::gpio::vals::Pupdr;
use crate::gpio::sealed::AFType;
use crate::gpio::{Pull, Speed};
mod pins;
pub use pins::*;
@ -41,9 +40,8 @@ macro_rules! config_pins {
($($pin:ident),*) => {
unborrow!($($pin),*);
$(
$pin.set_as_af($pin.af_num(), OutputPushPull);
$pin.set_as_af_pull($pin.af_num(), AFType::OutputPushPull, Pull::Up);
$pin.set_speed(Speed::VeryHigh);
$pin.block().pupdr().modify(|w| w.set_pupdr($pin.pin() as usize, Pupdr::PULLUP));
)*
};
}

View File

@ -48,9 +48,9 @@ impl From<Speed> for vals::Mode {
use Speed::*;
match speed {
Low => vals::Mode::OUTPUT2,
Medium => vals::Mode::OUTPUT,
VeryHigh => vals::Mode::OUTPUT50,
Low => vals::Mode::OUTPUT2MHZ,
Medium => vals::Mode::OUTPUT10MHZ,
VeryHigh => vals::Mode::OUTPUT50MHZ,
}
}
}
@ -85,20 +85,23 @@ impl<'d, T: Pin> Input<'d, T> {
let n = pin.pin() as usize;
#[cfg(gpio_v1)]
{
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,
};
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 => {}
}
if pull == Pull::None {
r.cr(crlh)
.modify(|w| w.set_cnf(n % 8, vals::Cnf::OPENDRAIN));
} else {
r.cr(crlh)
.modify(|w| w.set_cnf(n % 8, vals::Cnf::ALTPUSHPULL));
}
r.cr(crlh).modify(|w| w.set_mode(n % 8, vals::Mode::INPUT));
r.cr(crlh).modify(|w| {
w.set_mode(n % 8, vals::Mode::INPUT);
w.set_cnf_in(n % 8, cnf);
});
}
#[cfg(gpio_v2)]
{
@ -133,7 +136,7 @@ impl<'d, T: Pin> Drop for Input<'d, T> {
{
let crlh = if n < 8 { 0 } else { 1 };
r.cr(crlh)
.modify(|w| w.set_cnf(n % 8, vals::Cnf::OPENDRAIN));
.modify(|w| w.set_cnf_in(n % 8, vals::CnfIn::FLOATING));
}
#[cfg(gpio_v2)]
r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING));
@ -170,8 +173,10 @@ impl<'d, T: Pin> Output<'d, T> {
#[cfg(gpio_v1)]
{
let crlh = if n < 8 { 0 } else { 1 };
r.cr(crlh).modify(|w| w.set_cnf(n % 8, vals::Cnf::PUSHPULL));
r.cr(crlh).modify(|w| w.set_mode(n % 8, speed.into()));
r.cr(crlh).modify(|w| {
w.set_mode(n % 8, speed.into());
w.set_cnf_out(n % 8, vals::CnfOut::PUSHPULL);
});
}
#[cfg(gpio_v2)]
{
@ -227,9 +232,10 @@ impl<'d, T: Pin> Drop for Output<'d, T> {
#[cfg(gpio_v1)]
{
let crlh = if n < 8 { 0 } else { 1 };
r.cr(crlh)
.modify(|w| w.set_cnf(n % 8, vals::Cnf::OPENDRAIN));
r.cr(crlh).modify(|w| w.set_mode(n % 8, vals::Mode::INPUT));
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)]
{
@ -273,7 +279,7 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
}
r.cr(crlh).modify(|w| w.set_mode(n % 8, speed.into()));
r.cr(crlh)
.modify(|w| w.set_cnf(n % 8, vals::Cnf::OPENDRAIN));
.modify(|w| w.set_cnf_out(n % 8, vals::CnfOut::OPENDRAIN));
}
#[cfg(gpio_v2)]
{
@ -338,9 +344,10 @@ impl<'d, T: Pin> Drop for OutputOpenDrain<'d, T> {
#[cfg(gpio_v1)]
{
let crlh = if n < 8 { 0 } else { 1 };
r.cr(crlh)
.modify(|w| w.set_cnf(n % 8, vals::Cnf::OPENDRAIN));
r.cr(crlh).modify(|w| w.set_mode(n % 8, vals::Mode::INPUT));
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)]
{
@ -410,30 +417,34 @@ pub(crate) mod sealed {
AFType::Input => {
r.cr(crlh).modify(|w| {
w.set_mode(n % 8, vals::Mode::INPUT);
w.set_cnf(n % 8, vals::Cnf::OPENDRAIN);
w.set_cnf_in(n % 8, vals::CnfIn::FLOATING);
});
}
AFType::OutputPushPull => {
r.cr(crlh).modify(|w| {
w.set_mode(n % 8, vals::Mode::OUTPUT50);
w.set_cnf(n % 8, vals::Cnf::ALTPUSHPULL);
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::OUTPUT50);
w.set_cnf(n % 8, vals::Cnf::ALTOPENDRAIN);
w.set_mode(n % 8, vals::Mode::OUTPUT50MHZ);
w.set_cnf_out(n % 8, vals::CnfOut::ALTOPENDRAIN);
});
}
}
}
#[cfg(gpio_v2)]
unsafe fn set_as_af(&self, af_num: u8, af_type: AFType) {
self.set_as_af_pull(af_num, af_type, Pull::None);
}
#[cfg(gpio_v2)]
unsafe 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, vals::Afr(af_num)));
block.afr(pin / 8).modify(|w| w.set_afr(pin % 8, af_num));
match af_type {
AFType::Input => {}
AFType::OutputPushPull => {
@ -443,9 +454,7 @@ pub(crate) mod sealed {
.otyper()
.modify(|w| w.set_ot(pin, vals::Ot::OPENDRAIN)),
}
block
.pupdr()
.modify(|w| w.set_pupdr(pin, vals::Pupdr::FLOATING));
block.pupdr().modify(|w| w.set_pupdr(pin, pull.into()));
block
.moder()
@ -458,12 +467,10 @@ pub(crate) mod sealed {
#[cfg(gpio_v1)]
{
let crlh = if pin < 8 { 0 } else { 1 };
block
.cr(crlh)
.modify(|w| w.set_cnf(pin % 8, vals::Cnf::PUSHPULL));
block
.cr(crlh)
.modify(|w| w.set_mode(pin % 8, vals::Mode::INPUT));
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
@ -471,6 +478,15 @@ pub(crate) mod sealed {
.modify(|w| w.set_moder(pin, vals::Moder::ANALOG));
}
/// 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.
unsafe fn set_as_disconnected(&self) {
self.set_as_analog();
}
#[cfg(gpio_v2)]
unsafe fn set_speed(&self, speed: Speed) {
let pin = self._pin() as usize;

View File

@ -1,12 +1,11 @@
use crate::i2c::{Error, Instance, SclPin, SdaPin};
use crate::time::Hertz;
use core::marker::PhantomData;
use embassy::util::Unborrow;
use embassy_hal_common::unborrow;
use crate::gpio::sealed::AFType;
use crate::i2c::{Error, Instance, SclPin, SdaPin};
use crate::pac::i2c;
use crate::gpio::sealed::AFType::OutputOpenDrain;
use crate::time::Hertz;
pub struct I2c<'d, T: Instance> {
phantom: PhantomData<&'d mut T>,
@ -27,8 +26,8 @@ impl<'d, T: Instance> I2c<'d, T> {
T::enable();
unsafe {
scl.set_as_af(scl.af_num(), OutputOpenDrain);
sda.set_as_af(sda.af_num(), OutputOpenDrain);
scl.set_as_af(scl.af_num(), AFType::OutputOpenDrain);
sda.set_as_af(sda.af_num(), AFType::OutputOpenDrain);
}
unsafe {

View File

@ -11,10 +11,9 @@ use embassy_hal_common::unborrow;
use futures::future::poll_fn;
use crate::dma::NoDma;
use crate::gpio::sealed::AFType;
use crate::i2c::{Error, Instance, SclPin, SdaPin};
use crate::pac;
use crate::pac::gpio::vals::{Afr, Moder, Ot};
use crate::pac::gpio::Gpio;
use crate::pac::i2c;
use crate::time::Hertz;
@ -64,8 +63,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
T::enable();
unsafe {
Self::configure_pin(scl.block(), scl.pin() as _, scl.af_num());
Self::configure_pin(sda.block(), sda.pin() as _, sda.af_num());
scl.set_as_af(scl.af_num(), AFType::OutputOpenDrain);
sda.set_as_af(sda.af_num(), AFType::OutputOpenDrain);
}
unsafe {
@ -120,16 +119,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
});
}
unsafe fn configure_pin(block: Gpio, pin: usize, af_num: u8) {
let (afr, n_af) = if pin < 8 { (0, pin) } else { (1, pin - 8) };
block.moder().modify(|w| w.set_moder(pin, Moder::ALTERNATE));
block.afr(afr).modify(|w| w.set_afr(n_af, Afr(af_num)));
block.otyper().modify(|w| w.set_ot(pin, Ot::OPENDRAIN));
//block
//.ospeedr()
//.modify(|w| w.set_ospeedr(pin, crate::pac::gpio::vals::Ospeedr::VERYHIGHSPEED));
}
fn master_stop(&mut self) {
unsafe {
T::regs().cr2().write(|w| w.set_stop(true));

View File

@ -12,9 +12,9 @@ use embassy_hal_common::unborrow;
use futures::future::poll_fn;
use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR};
use crate::gpio::sealed::AFType;
use crate::gpio::{Pull, Speed};
use crate::interrupt::Interrupt;
use crate::pac;
use crate::pac::gpio::Gpio;
use crate::pac::sdmmc::Sdmmc as RegBlock;
use crate::peripherals;
use crate::time::Hertz;
@ -1191,23 +1191,6 @@ where
{
}
/// # Safety
///
/// Access to `block` registers should be exclusive
unsafe fn configure_pin(block: Gpio, n: usize, afr_num: u8, pup: bool) {
use pac::gpio::vals::{Afr, Moder, Ospeedr, Pupdr};
let (afr, n_af) = if n < 8 { (0, n) } else { (1, n - 8) };
block.afr(afr).modify(|w| w.set_afr(n_af, Afr(afr_num)));
block.moder().modify(|w| w.set_moder(n, Moder::ALTERNATE));
if pup {
block.pupdr().modify(|w| w.set_pupdr(n, Pupdr::PULLUP));
}
block
.ospeedr()
.modify(|w| w.set_ospeedr(n, Ospeedr::VERYHIGHSPEED));
}
impl<T, CLK, CMD, D0, D1, D2, D3> Pins<T> for (CLK, CMD, D0, D1, D2, D3)
where
T: Instance,
@ -1224,135 +1207,32 @@ where
let (clk_pin, cmd_pin, d0_pin, d1_pin, d2_pin, d3_pin) = self;
critical_section::with(|_| unsafe {
// clk
let block = clk_pin.block();
let n = clk_pin.pin() as usize;
let afr_num = clk_pin.af_num();
configure_pin(block, n, afr_num, false);
clk_pin.set_as_af_pull(clk_pin.af_num(), AFType::OutputPushPull, Pull::None);
cmd_pin.set_as_af_pull(cmd_pin.af_num(), AFType::OutputPushPull, Pull::Up);
d0_pin.set_as_af_pull(d0_pin.af_num(), AFType::OutputPushPull, Pull::Up);
d1_pin.set_as_af_pull(d1_pin.af_num(), AFType::OutputPushPull, Pull::Up);
d2_pin.set_as_af_pull(d2_pin.af_num(), AFType::OutputPushPull, Pull::Up);
d3_pin.set_as_af_pull(d3_pin.af_num(), AFType::OutputPushPull, Pull::Up);
// cmd
let block = cmd_pin.block();
let n = cmd_pin.pin() as usize;
let afr_num = cmd_pin.af_num();
configure_pin(block, n, afr_num, true);
// d0
let block = d0_pin.block();
let n = d0_pin.pin() as usize;
let afr_num = d0_pin.af_num();
configure_pin(block, n, afr_num, true);
// d1
let block = d1_pin.block();
let n = d1_pin.pin() as usize;
let afr_num = d1_pin.af_num();
configure_pin(block, n, afr_num, true);
// d2
let block = d2_pin.block();
let n = d2_pin.pin() as usize;
let afr_num = d2_pin.af_num();
configure_pin(block, n, afr_num, true);
// d3
let block = d3_pin.block();
let n = d3_pin.pin() as usize;
let afr_num = d3_pin.af_num();
configure_pin(block, n, afr_num, true);
clk_pin.set_speed(Speed::VeryHigh);
cmd_pin.set_speed(Speed::VeryHigh);
d0_pin.set_speed(Speed::VeryHigh);
d1_pin.set_speed(Speed::VeryHigh);
d2_pin.set_speed(Speed::VeryHigh);
d3_pin.set_speed(Speed::VeryHigh);
});
}
fn deconfigure(&mut self) {
use pac::gpio::vals::{Moder, Ospeedr, Pupdr};
let (clk_pin, cmd_pin, d0_pin, d1_pin, d2_pin, d3_pin) = self;
critical_section::with(|_| unsafe {
// clk
let n = clk_pin.pin().into();
clk_pin
.block()
.moder()
.modify(|w| w.set_moder(n, Moder::ANALOG));
clk_pin
.block()
.ospeedr()
.modify(|w| w.set_ospeedr(n, Ospeedr::LOWSPEED));
// cmd
let n = cmd_pin.pin().into();
cmd_pin
.block()
.moder()
.modify(|w| w.set_moder(n, Moder::ANALOG));
cmd_pin
.block()
.ospeedr()
.modify(|w| w.set_ospeedr(n, Ospeedr::LOWSPEED));
cmd_pin
.block()
.pupdr()
.modify(|w| w.set_pupdr(n, Pupdr::FLOATING));
// d0
let n = d0_pin.pin().into();
d0_pin
.block()
.moder()
.modify(|w| w.set_moder(n, Moder::ANALOG));
d0_pin
.block()
.ospeedr()
.modify(|w| w.set_ospeedr(n, Ospeedr::LOWSPEED));
d0_pin
.block()
.pupdr()
.modify(|w| w.set_pupdr(n, Pupdr::FLOATING));
// d1
let n = d1_pin.pin().into();
d1_pin
.block()
.moder()
.modify(|w| w.set_moder(n, Moder::ANALOG));
d1_pin
.block()
.ospeedr()
.modify(|w| w.set_ospeedr(n, Ospeedr::LOWSPEED));
d1_pin
.block()
.pupdr()
.modify(|w| w.set_pupdr(n, Pupdr::FLOATING));
// d2
let n = d2_pin.pin().into();
d2_pin
.block()
.moder()
.modify(|w| w.set_moder(n, Moder::ANALOG));
d2_pin
.block()
.ospeedr()
.modify(|w| w.set_ospeedr(n, Ospeedr::LOWSPEED));
d2_pin
.block()
.pupdr()
.modify(|w| w.set_pupdr(n, Pupdr::FLOATING));
// d3
let n = d3_pin.pin().into();
d3_pin
.block()
.moder()
.modify(|w| w.set_moder(n, Moder::ANALOG));
d3_pin
.block()
.ospeedr()
.modify(|w| w.set_ospeedr(n, Ospeedr::LOWSPEED));
d3_pin
.block()
.pupdr()
.modify(|w| w.set_pupdr(n, Pupdr::FLOATING));
clk_pin.set_as_disconnected();
cmd_pin.set_as_disconnected();
d0_pin.set_as_disconnected();
d1_pin.set_as_disconnected();
d2_pin.set_as_disconnected();
d3_pin.set_as_disconnected();
});
}
}
@ -1370,72 +1250,23 @@ where
let (clk_pin, cmd_pin, d0_pin) = self;
critical_section::with(|_| unsafe {
// clk
let block = clk_pin.block();
let n = clk_pin.pin() as usize;
let afr_num = clk_pin.af_num();
configure_pin(block, n, afr_num, false);
clk_pin.set_as_af_pull(clk_pin.af_num(), AFType::OutputPushPull, Pull::None);
cmd_pin.set_as_af_pull(cmd_pin.af_num(), AFType::OutputPushPull, Pull::Up);
d0_pin.set_as_af_pull(d0_pin.af_num(), AFType::OutputPushPull, Pull::Up);
// cmd
let block = cmd_pin.block();
let n = cmd_pin.pin() as usize;
let afr_num = cmd_pin.af_num();
configure_pin(block, n, afr_num, true);
// d0
let block = d0_pin.block();
let n = d0_pin.pin() as usize;
let afr_num = d0_pin.af_num();
configure_pin(block, n, afr_num, true);
clk_pin.set_speed(Speed::VeryHigh);
cmd_pin.set_speed(Speed::VeryHigh);
d0_pin.set_speed(Speed::VeryHigh);
});
}
fn deconfigure(&mut self) {
use pac::gpio::vals::{Moder, Ospeedr, Pupdr};
let (clk_pin, cmd_pin, d0_pin) = self;
critical_section::with(|_| unsafe {
// clk
let n = clk_pin.pin().into();
clk_pin
.block()
.moder()
.modify(|w| w.set_moder(n, Moder::ANALOG));
clk_pin
.block()
.ospeedr()
.modify(|w| w.set_ospeedr(n, Ospeedr::LOWSPEED));
// cmd
let n = cmd_pin.pin().into();
cmd_pin
.block()
.moder()
.modify(|w| w.set_moder(n, Moder::ANALOG));
cmd_pin
.block()
.ospeedr()
.modify(|w| w.set_ospeedr(n, Ospeedr::LOWSPEED));
cmd_pin
.block()
.pupdr()
.modify(|w| w.set_pupdr(n, Pupdr::FLOATING));
// d0
let n = d0_pin.pin().into();
d0_pin
.block()
.moder()
.modify(|w| w.set_moder(n, Moder::ANALOG));
d0_pin
.block()
.ospeedr()
.modify(|w| w.set_ospeedr(n, Ospeedr::LOWSPEED));
d0_pin
.block()
.pupdr()
.modify(|w| w.set_pupdr(n, Pupdr::FLOATING));
clk_pin.set_as_disconnected();
cmd_pin.set_as_disconnected();
d0_pin.set_as_disconnected();
});
}
}

View File

@ -458,9 +458,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> {
fn drop(&mut self) {
unsafe {
self.sck.as_ref().map(|x| x.set_as_analog());
self.mosi.as_ref().map(|x| x.set_as_analog());
self.miso.as_ref().map(|x| x.set_as_analog());
self.sck.as_ref().map(|x| x.set_as_disconnected());
self.mosi.as_ref().map(|x| x.set_as_disconnected());
self.miso.as_ref().map(|x| x.set_as_disconnected());
}
}
}

@ -1 +1 @@
Subproject commit dbb0ad74f2a4612f0ca168da38e1c443a838a607
Subproject commit 608581a8960b95c4d472f59d0b028b47053d5873