stm32/i2c: use new_pin! macro

This commit is contained in:
Jan Špaček 2024-05-26 15:40:42 +02:00
parent ca3c15658d
commit 41711195e3
3 changed files with 58 additions and 43 deletions

View File

@ -9,16 +9,16 @@ use core::future::Future;
use core::iter; use core::iter;
use core::marker::PhantomData; use core::marker::PhantomData;
use embassy_hal_internal::{into_ref, Peripheral}; use embassy_hal_internal::{Peripheral, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
#[cfg(feature = "time")] #[cfg(feature = "time")]
use embassy_time::{Duration, Instant}; use embassy_time::{Duration, Instant};
use crate::dma::ChannelAndRequest; use crate::dma::ChannelAndRequest;
use crate::gpio::{AFType, Pull}; use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed};
use crate::interrupt::typelevel::Interrupt; use crate::interrupt::typelevel::Interrupt;
use crate::mode::{Async, Blocking, Mode}; use crate::mode::{Async, Blocking, Mode};
use crate::rcc::{self, RccInfo, SealedRccPeripheral}; use crate::rcc::{RccInfo, SealedRccPeripheral};
use crate::time::Hertz; use crate::time::Hertz;
use crate::{interrupt, peripherals}; use crate::{interrupt, peripherals};
@ -72,11 +72,29 @@ impl Default for Config {
} }
} }
impl Config {
fn scl_pull_mode(&self) -> Pull {
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,
}
}
}
/// I2C driver. /// I2C driver.
pub struct I2c<'d, M: Mode> { pub struct I2c<'d, M: Mode> {
info: &'static Info, info: &'static Info,
state: &'static State, state: &'static State,
kernel_clock: Hertz, kernel_clock: Hertz,
scl: Option<PeripheralRef<'d, AnyPin>>,
sda: Option<PeripheralRef<'d, AnyPin>>,
tx_dma: Option<ChannelAndRequest<'d>>, tx_dma: Option<ChannelAndRequest<'d>>,
rx_dma: Option<ChannelAndRequest<'d>>, rx_dma: Option<ChannelAndRequest<'d>>,
#[cfg(feature = "time")] #[cfg(feature = "time")]
@ -98,7 +116,15 @@ impl<'d> I2c<'d, Async> {
freq: Hertz, freq: Hertz,
config: Config, config: Config,
) -> Self { ) -> Self {
Self::new_inner(peri, scl, sda, new_dma!(tx_dma), new_dma!(rx_dma), freq, config) 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_dma!(tx_dma),
new_dma!(rx_dma),
freq,
config,
)
} }
} }
@ -111,7 +137,15 @@ impl<'d> I2c<'d, Blocking> {
freq: Hertz, freq: Hertz,
config: Config, config: Config,
) -> Self { ) -> Self {
Self::new_inner(peri, scl, sda, None, None, freq, config) 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()),
None,
None,
freq,
config,
)
} }
} }
@ -119,34 +153,13 @@ impl<'d, M: Mode> I2c<'d, M> {
/// Create a new I2C driver. /// Create a new I2C driver.
fn new_inner<T: Instance>( fn new_inner<T: Instance>(
_peri: impl Peripheral<P = T> + 'd, _peri: impl Peripheral<P = T> + 'd,
scl: impl Peripheral<P = impl SclPin<T>> + 'd, scl: Option<PeripheralRef<'d, AnyPin>>,
sda: impl Peripheral<P = impl SdaPin<T>> + 'd, sda: Option<PeripheralRef<'d, AnyPin>>,
tx_dma: Option<ChannelAndRequest<'d>>, tx_dma: Option<ChannelAndRequest<'d>>,
rx_dma: Option<ChannelAndRequest<'d>>, rx_dma: Option<ChannelAndRequest<'d>>,
freq: Hertz, freq: Hertz,
config: Config, config: Config,
) -> Self { ) -> Self {
into_ref!(scl, sda);
rcc::enable_and_reset::<T>();
scl.set_as_af_pull(
scl.af_num(),
AFType::OutputOpenDrain,
match config.scl_pullup {
true => Pull::Up,
false => Pull::None,
},
);
sda.set_as_af_pull(
sda.af_num(),
AFType::OutputOpenDrain,
match config.sda_pullup {
true => Pull::Up,
false => Pull::None,
},
);
unsafe { T::EventInterrupt::enable() }; unsafe { T::EventInterrupt::enable() };
unsafe { T::ErrorInterrupt::enable() }; unsafe { T::ErrorInterrupt::enable() };
@ -154,18 +167,23 @@ impl<'d, M: Mode> I2c<'d, M> {
info: T::info(), info: T::info(),
state: T::state(), state: T::state(),
kernel_clock: T::frequency(), kernel_clock: T::frequency(),
scl,
sda,
tx_dma, tx_dma,
rx_dma, rx_dma,
#[cfg(feature = "time")] #[cfg(feature = "time")]
timeout: config.timeout, timeout: config.timeout,
_phantom: PhantomData, _phantom: PhantomData,
}; };
this.enable_and_init(freq, config);
this.init(freq, config);
this this
} }
fn enable_and_init(&mut self, freq: Hertz, config: Config) {
self.info.rcc.enable_and_reset();
self.init(freq, config);
}
fn timeout(&self) -> Timeout { fn timeout(&self) -> Timeout {
Timeout { Timeout {
#[cfg(feature = "time")] #[cfg(feature = "time")]
@ -174,6 +192,15 @@ impl<'d, M: Mode> I2c<'d, M> {
} }
} }
impl<'d, M: Mode> Drop for I2c<'d, M> {
fn drop(&mut self) {
self.scl.as_ref().map(|x| x.set_as_disconnected());
self.sda.as_ref().map(|x| x.set_as_disconnected());
self.info.rcc.disable()
}
}
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
struct Timeout { struct Timeout {
#[cfg(feature = "time")] #[cfg(feature = "time")]

View File

@ -700,12 +700,6 @@ impl<'d> I2c<'d, Async> {
} }
} }
impl<'d, M: PeriMode> Drop for I2c<'d, M> {
fn drop(&mut self) {
self.info.rcc.disable()
}
}
enum Mode { enum Mode {
Fast, Fast,
Standard, Standard,

View File

@ -671,12 +671,6 @@ impl<'d> I2c<'d, Async> {
} }
} }
impl<'d, M: Mode> Drop for I2c<'d, M> {
fn drop(&mut self) {
self.info.rcc.disable();
}
}
/// I2C Stop Configuration /// I2C Stop Configuration
/// ///
/// Peripheral options for generating the STOP condition /// Peripheral options for generating the STOP condition