mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-25 08:12:30 +00:00
Merge pull request #3006 from honzasp/harmonize-new
stm32: Make initialization of I2C and USART consistent with SPI
This commit is contained in:
commit
9856d21693
@ -9,16 +9,16 @@ use core::future::Future;
|
||||
use core::iter;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use embassy_hal_internal::{into_ref, Peripheral};
|
||||
use embassy_hal_internal::{Peripheral, PeripheralRef};
|
||||
use embassy_sync::waitqueue::AtomicWaker;
|
||||
#[cfg(feature = "time")]
|
||||
use embassy_time::{Duration, Instant};
|
||||
|
||||
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::mode::{Async, Blocking, Mode};
|
||||
use crate::rcc::{self, RccInfo, SealedRccPeripheral};
|
||||
use crate::rcc::{RccInfo, SealedRccPeripheral};
|
||||
use crate::time::Hertz;
|
||||
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.
|
||||
pub struct I2c<'d, M: Mode> {
|
||||
info: &'static Info,
|
||||
state: &'static State,
|
||||
kernel_clock: Hertz,
|
||||
scl: Option<PeripheralRef<'d, AnyPin>>,
|
||||
sda: Option<PeripheralRef<'d, AnyPin>>,
|
||||
tx_dma: Option<ChannelAndRequest<'d>>,
|
||||
rx_dma: Option<ChannelAndRequest<'d>>,
|
||||
#[cfg(feature = "time")]
|
||||
@ -98,7 +116,15 @@ impl<'d> I2c<'d, Async> {
|
||||
freq: Hertz,
|
||||
config: Config,
|
||||
) -> 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,
|
||||
config: Config,
|
||||
) -> 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.
|
||||
fn new_inner<T: Instance>(
|
||||
_peri: impl Peripheral<P = T> + 'd,
|
||||
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
|
||||
sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
|
||||
scl: Option<PeripheralRef<'d, AnyPin>>,
|
||||
sda: Option<PeripheralRef<'d, AnyPin>>,
|
||||
tx_dma: Option<ChannelAndRequest<'d>>,
|
||||
rx_dma: Option<ChannelAndRequest<'d>>,
|
||||
freq: Hertz,
|
||||
config: Config,
|
||||
) -> 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::ErrorInterrupt::enable() };
|
||||
|
||||
@ -154,18 +167,23 @@ impl<'d, M: Mode> I2c<'d, M> {
|
||||
info: T::info(),
|
||||
state: T::state(),
|
||||
kernel_clock: T::frequency(),
|
||||
scl,
|
||||
sda,
|
||||
tx_dma,
|
||||
rx_dma,
|
||||
#[cfg(feature = "time")]
|
||||
timeout: config.timeout,
|
||||
_phantom: PhantomData,
|
||||
};
|
||||
|
||||
this.init(freq, config);
|
||||
|
||||
this.enable_and_init(freq, config);
|
||||
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 {
|
||||
Timeout {
|
||||
#[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)]
|
||||
struct Timeout {
|
||||
#[cfg(feature = "time")]
|
||||
|
@ -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 {
|
||||
Fast,
|
||||
Standard,
|
||||
|
@ -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
|
||||
///
|
||||
/// Peripheral options for generating the STOP condition
|
||||
|
@ -13,7 +13,7 @@ use crate::dma::{slice_ptr_parts, word, ChannelAndRequest};
|
||||
use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed};
|
||||
use crate::mode::{Async, Blocking, Mode as PeriMode};
|
||||
use crate::pac::spi::{regs, vals, Spi as Regs};
|
||||
use crate::rcc::{self, RccInfo, SealedRccPeripheral};
|
||||
use crate::rcc::{RccInfo, SealedRccPeripheral};
|
||||
use crate::time::Hertz;
|
||||
use crate::Peripheral;
|
||||
|
||||
@ -120,17 +120,30 @@ impl<'d, M: PeriMode> Spi<'d, M> {
|
||||
rx_dma: Option<ChannelAndRequest<'d>>,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
let regs = T::info().regs;
|
||||
let kernel_clock = T::frequency();
|
||||
let br = compute_baud_rate(kernel_clock, config.frequency);
|
||||
let mut this = Self {
|
||||
info: T::info(),
|
||||
kernel_clock: T::frequency(),
|
||||
sck,
|
||||
mosi,
|
||||
miso,
|
||||
tx_dma,
|
||||
rx_dma,
|
||||
current_word_size: <u8 as SealedWord>::CONFIG,
|
||||
_phantom: PhantomData,
|
||||
};
|
||||
this.enable_and_init(config);
|
||||
this
|
||||
}
|
||||
|
||||
fn enable_and_init(&mut self, config: Config) {
|
||||
let br = compute_baud_rate(self.kernel_clock, config.frequency);
|
||||
let cpha = config.raw_phase();
|
||||
let cpol = config.raw_polarity();
|
||||
|
||||
let lsbfirst = config.raw_byte_order();
|
||||
|
||||
rcc::enable_and_reset::<T>();
|
||||
self.info.rcc.enable_and_reset();
|
||||
|
||||
let regs = self.info.regs;
|
||||
#[cfg(any(spi_v1, spi_f1))]
|
||||
{
|
||||
regs.cr2().modify(|w| {
|
||||
@ -209,18 +222,6 @@ impl<'d, M: PeriMode> Spi<'d, M> {
|
||||
w.set_spe(true);
|
||||
});
|
||||
}
|
||||
|
||||
Self {
|
||||
info: T::info(),
|
||||
kernel_clock,
|
||||
sck,
|
||||
mosi,
|
||||
miso,
|
||||
tx_dma,
|
||||
rx_dma,
|
||||
current_word_size: <u8 as SealedWord>::CONFIG,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Reconfigures it with the supplied config.
|
||||
@ -611,7 +612,7 @@ impl<'d> Spi<'d, Async> {
|
||||
// see RM0453 rev 1 section 7.2.13 page 291
|
||||
// The SUBGHZSPI_SCK frequency is obtained by PCLK3 divided by two.
|
||||
// The SUBGHZSPI_SCK clock maximum speed must not exceed 16 MHz.
|
||||
let pclk3_freq = <crate::peripherals::SUBGHZSPI as crate::rcc::SealedRccPeripheral>::frequency().0;
|
||||
let pclk3_freq = <crate::peripherals::SUBGHZSPI as SealedRccPeripheral>::frequency().0;
|
||||
let freq = Hertz(core::cmp::min(pclk3_freq / 2, 16_000_000));
|
||||
let mut config = Config::default();
|
||||
config.mode = MODE_0;
|
||||
|
@ -6,7 +6,7 @@ use core::task::Poll;
|
||||
|
||||
use embassy_embedded_hal::SetConfig;
|
||||
use embassy_hal_internal::atomic_ring_buffer::RingBuffer;
|
||||
use embassy_hal_internal::{into_ref, Peripheral};
|
||||
use embassy_hal_internal::{Peripheral, PeripheralRef};
|
||||
use embassy_sync::waitqueue::AtomicWaker;
|
||||
|
||||
#[cfg(not(any(usart_v1, usart_v2)))]
|
||||
@ -15,10 +15,8 @@ use super::{
|
||||
clear_interrupt_flags, configure, rdr, reconfigure, sr, tdr, Config, ConfigError, CtsPin, Error, Info, Instance,
|
||||
Regs, RtsPin, RxPin, TxPin,
|
||||
};
|
||||
use crate::gpio::AFType;
|
||||
use crate::interrupt::typelevel::Interrupt as _;
|
||||
use crate::gpio::{AFType, AnyPin, SealedPin as _};
|
||||
use crate::interrupt::{self, InterruptExt};
|
||||
use crate::rcc;
|
||||
use crate::time::Hertz;
|
||||
|
||||
/// Interrupt handler.
|
||||
@ -156,7 +154,9 @@ pub struct BufferedUartTx<'d> {
|
||||
info: &'static Info,
|
||||
state: &'static State,
|
||||
kernel_clock: Hertz,
|
||||
_phantom: PhantomData<&'d mut ()>,
|
||||
tx: Option<PeripheralRef<'d, AnyPin>>,
|
||||
cts: Option<PeripheralRef<'d, AnyPin>>,
|
||||
de: Option<PeripheralRef<'d, AnyPin>>,
|
||||
}
|
||||
|
||||
/// Rx-only buffered UART
|
||||
@ -166,7 +166,8 @@ pub struct BufferedUartRx<'d> {
|
||||
info: &'static Info,
|
||||
state: &'static State,
|
||||
kernel_clock: Hertz,
|
||||
_phantom: PhantomData<&'d mut ()>,
|
||||
rx: Option<PeripheralRef<'d, AnyPin>>,
|
||||
rts: Option<PeripheralRef<'d, AnyPin>>,
|
||||
}
|
||||
|
||||
impl<'d> SetConfig for BufferedUart<'d> {
|
||||
@ -207,9 +208,17 @@ impl<'d> BufferedUart<'d> {
|
||||
rx_buffer: &'d mut [u8],
|
||||
config: Config,
|
||||
) -> Result<Self, ConfigError> {
|
||||
rcc::enable_and_reset::<T>();
|
||||
|
||||
Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
|
||||
Self::new_inner(
|
||||
peri,
|
||||
new_pin!(rx, AFType::Input),
|
||||
new_pin!(tx, AFType::OutputPushPull),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
tx_buffer,
|
||||
rx_buffer,
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new bidirectional buffered UART driver with request-to-send and clear-to-send pins
|
||||
@ -224,18 +233,17 @@ impl<'d> BufferedUart<'d> {
|
||||
rx_buffer: &'d mut [u8],
|
||||
config: Config,
|
||||
) -> Result<Self, ConfigError> {
|
||||
into_ref!(cts, rts);
|
||||
|
||||
rcc::enable_and_reset::<T>();
|
||||
|
||||
rts.set_as_af(rts.af_num(), AFType::OutputPushPull);
|
||||
cts.set_as_af(cts.af_num(), AFType::Input);
|
||||
T::info().regs.cr3().write(|w| {
|
||||
w.set_rtse(true);
|
||||
w.set_ctse(true);
|
||||
});
|
||||
|
||||
Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
|
||||
Self::new_inner(
|
||||
peri,
|
||||
new_pin!(rx, AFType::Input),
|
||||
new_pin!(tx, AFType::OutputPushPull),
|
||||
new_pin!(rts, AFType::OutputPushPull),
|
||||
new_pin!(cts, AFType::Input),
|
||||
None,
|
||||
tx_buffer,
|
||||
rx_buffer,
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new bidirectional buffered UART driver with a driver-enable pin
|
||||
@ -250,66 +258,89 @@ impl<'d> BufferedUart<'d> {
|
||||
rx_buffer: &'d mut [u8],
|
||||
config: Config,
|
||||
) -> Result<Self, ConfigError> {
|
||||
into_ref!(de);
|
||||
|
||||
rcc::enable_and_reset::<T>();
|
||||
|
||||
de.set_as_af(de.af_num(), AFType::OutputPushPull);
|
||||
T::info().regs.cr3().write(|w| {
|
||||
w.set_dem(true);
|
||||
});
|
||||
|
||||
Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
|
||||
Self::new_inner(
|
||||
peri,
|
||||
new_pin!(rx, AFType::Input),
|
||||
new_pin!(tx, AFType::OutputPushPull),
|
||||
None,
|
||||
None,
|
||||
new_pin!(de, AFType::OutputPushPull),
|
||||
tx_buffer,
|
||||
rx_buffer,
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
fn new_inner<T: Instance>(
|
||||
_peri: impl Peripheral<P = T> + 'd,
|
||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
||||
rx: Option<PeripheralRef<'d, AnyPin>>,
|
||||
tx: Option<PeripheralRef<'d, AnyPin>>,
|
||||
rts: Option<PeripheralRef<'d, AnyPin>>,
|
||||
cts: Option<PeripheralRef<'d, AnyPin>>,
|
||||
de: Option<PeripheralRef<'d, AnyPin>>,
|
||||
tx_buffer: &'d mut [u8],
|
||||
rx_buffer: &'d mut [u8],
|
||||
config: Config,
|
||||
) -> Result<Self, ConfigError> {
|
||||
into_ref!(_peri, rx, tx);
|
||||
|
||||
let info = T::info();
|
||||
let state = T::buffered_state();
|
||||
let kernel_clock = T::frequency();
|
||||
let len = tx_buffer.len();
|
||||
unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
|
||||
let len = rx_buffer.len();
|
||||
unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) };
|
||||
|
||||
let r = info.regs;
|
||||
rx.set_as_af(rx.af_num(), AFType::Input);
|
||||
tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
|
||||
|
||||
configure(info, kernel_clock, &config, true, true)?;
|
||||
|
||||
r.cr1().modify(|w| {
|
||||
w.set_rxneie(true);
|
||||
w.set_idleie(true);
|
||||
});
|
||||
|
||||
T::Interrupt::unpend();
|
||||
unsafe { T::Interrupt::enable() };
|
||||
|
||||
state.tx_rx_refcount.store(2, Ordering::Relaxed);
|
||||
|
||||
Ok(Self {
|
||||
let mut this = Self {
|
||||
rx: BufferedUartRx {
|
||||
info,
|
||||
state,
|
||||
kernel_clock,
|
||||
_phantom: PhantomData,
|
||||
rx,
|
||||
rts,
|
||||
},
|
||||
tx: BufferedUartTx {
|
||||
info,
|
||||
state,
|
||||
kernel_clock,
|
||||
_phantom: PhantomData,
|
||||
tx,
|
||||
cts,
|
||||
de,
|
||||
},
|
||||
})
|
||||
};
|
||||
this.enable_and_configure(tx_buffer, rx_buffer, &config)?;
|
||||
Ok(this)
|
||||
}
|
||||
|
||||
fn enable_and_configure(
|
||||
&mut self,
|
||||
tx_buffer: &'d mut [u8],
|
||||
rx_buffer: &'d mut [u8],
|
||||
config: &Config,
|
||||
) -> Result<(), ConfigError> {
|
||||
let info = self.rx.info;
|
||||
let state = self.rx.state;
|
||||
state.tx_rx_refcount.store(2, Ordering::Relaxed);
|
||||
|
||||
info.rcc.enable_and_reset();
|
||||
|
||||
let len = tx_buffer.len();
|
||||
unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
|
||||
let len = rx_buffer.len();
|
||||
unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) };
|
||||
|
||||
info.regs.cr3().write(|w| {
|
||||
w.set_rtse(self.rx.rts.is_some());
|
||||
w.set_ctse(self.tx.cts.is_some());
|
||||
#[cfg(not(any(usart_v1, usart_v2)))]
|
||||
w.set_dem(self.tx.de.is_some());
|
||||
});
|
||||
configure(info, self.rx.kernel_clock, &config, true, true)?;
|
||||
|
||||
info.regs.cr1().modify(|w| {
|
||||
w.set_rxneie(true);
|
||||
w.set_idleie(true);
|
||||
});
|
||||
|
||||
info.interrupt.unpend();
|
||||
unsafe { info.interrupt.enable() };
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Split the driver into a Tx and Rx part (useful for sending to separate tasks)
|
||||
@ -516,6 +547,8 @@ impl<'d> Drop for BufferedUartRx<'d> {
|
||||
}
|
||||
}
|
||||
|
||||
self.rx.as_ref().map(|x| x.set_as_disconnected());
|
||||
self.rts.as_ref().map(|x| x.set_as_disconnected());
|
||||
drop_tx_rx(self.info, state);
|
||||
}
|
||||
}
|
||||
@ -533,6 +566,9 @@ impl<'d> Drop for BufferedUartTx<'d> {
|
||||
}
|
||||
}
|
||||
|
||||
self.tx.as_ref().map(|x| x.set_as_disconnected());
|
||||
self.cts.as_ref().map(|x| x.set_as_disconnected());
|
||||
self.de.as_ref().map(|x| x.set_as_disconnected());
|
||||
drop_tx_rx(self.info, state);
|
||||
}
|
||||
}
|
||||
|
@ -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};
|
||||
use crate::gpio::{AFType, AnyPin, SealedPin as _};
|
||||
use crate::interrupt::typelevel::Interrupt as _;
|
||||
use crate::interrupt::{self, Interrupt, InterruptExt};
|
||||
use crate::mode::{Async, Blocking, Mode};
|
||||
@ -28,7 +28,7 @@ use crate::pac::usart::Lpuart as Regs;
|
||||
#[cfg(any(usart_v1, usart_v2))]
|
||||
use crate::pac::usart::Usart as Regs;
|
||||
use crate::pac::usart::{regs, vals};
|
||||
use crate::rcc::{self, RccInfo, SealedRccPeripheral};
|
||||
use crate::rcc::{RccInfo, SealedRccPeripheral};
|
||||
use crate::time::Hertz;
|
||||
use crate::Peripheral;
|
||||
|
||||
@ -429,29 +429,33 @@ impl<'d, M: Mode> UartTx<'d, M> {
|
||||
tx_dma: Option<ChannelAndRequest<'d>>,
|
||||
config: Config,
|
||||
) -> Result<Self, ConfigError> {
|
||||
rcc::enable_and_reset::<T>();
|
||||
|
||||
let info = T::info();
|
||||
let state = T::state();
|
||||
let kernel_clock = T::frequency();
|
||||
let r = info.regs;
|
||||
r.cr3().modify(|w| {
|
||||
w.set_ctse(cts.is_some());
|
||||
});
|
||||
configure(info, kernel_clock, &config, false, true)?;
|
||||
|
||||
state.tx_rx_refcount.store(1, Ordering::Relaxed);
|
||||
|
||||
Ok(Self {
|
||||
info,
|
||||
state,
|
||||
kernel_clock,
|
||||
let mut this = Self {
|
||||
info: T::info(),
|
||||
state: T::state(),
|
||||
kernel_clock: T::frequency(),
|
||||
tx,
|
||||
cts,
|
||||
de: None,
|
||||
tx_dma,
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
};
|
||||
this.enable_and_configure(&config)?;
|
||||
Ok(this)
|
||||
}
|
||||
|
||||
fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||
let info = self.info;
|
||||
let state = self.state;
|
||||
state.tx_rx_refcount.store(1, Ordering::Relaxed);
|
||||
|
||||
info.rcc.enable_and_reset();
|
||||
|
||||
info.regs.cr3().modify(|w| {
|
||||
w.set_ctse(self.cts.is_some());
|
||||
});
|
||||
configure(info, self.kernel_clock, config, false, true)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reconfigure the driver
|
||||
@ -775,34 +779,38 @@ impl<'d, M: Mode> UartRx<'d, M> {
|
||||
rx_dma: Option<ChannelAndRequest<'d>>,
|
||||
config: Config,
|
||||
) -> Result<Self, ConfigError> {
|
||||
rcc::enable_and_reset::<T>();
|
||||
|
||||
let info = T::info();
|
||||
let state = T::state();
|
||||
let kernel_clock = T::frequency();
|
||||
let r = info.regs;
|
||||
r.cr3().write(|w| {
|
||||
w.set_rtse(rts.is_some());
|
||||
});
|
||||
configure(info, kernel_clock, &config, true, false)?;
|
||||
|
||||
T::Interrupt::unpend();
|
||||
unsafe { T::Interrupt::enable() };
|
||||
|
||||
state.tx_rx_refcount.store(1, Ordering::Relaxed);
|
||||
|
||||
Ok(Self {
|
||||
let mut this = Self {
|
||||
_phantom: PhantomData,
|
||||
info,
|
||||
state,
|
||||
kernel_clock,
|
||||
info: T::info(),
|
||||
state: T::state(),
|
||||
kernel_clock: T::frequency(),
|
||||
rx,
|
||||
rts,
|
||||
rx_dma,
|
||||
detect_previous_overrun: config.detect_previous_overrun,
|
||||
#[cfg(any(usart_v1, usart_v2))]
|
||||
buffered_sr: stm32_metapac::usart::regs::Sr(0),
|
||||
})
|
||||
};
|
||||
this.enable_and_configure(&config)?;
|
||||
Ok(this)
|
||||
}
|
||||
|
||||
fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||
let info = self.info;
|
||||
let state = self.state;
|
||||
state.tx_rx_refcount.store(1, Ordering::Relaxed);
|
||||
|
||||
info.rcc.enable_and_reset();
|
||||
|
||||
info.regs.cr3().write(|w| {
|
||||
w.set_rtse(self.rts.is_some());
|
||||
});
|
||||
configure(info, self.kernel_clock, &config, true, false)?;
|
||||
|
||||
info.interrupt.unpend();
|
||||
unsafe { info.interrupt.enable() };
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reconfigure the driver
|
||||
@ -1228,27 +1236,11 @@ impl<'d, M: Mode> Uart<'d, M> {
|
||||
rx_dma: Option<ChannelAndRequest<'d>>,
|
||||
config: Config,
|
||||
) -> Result<Self, ConfigError> {
|
||||
rcc::enable_and_reset::<T>();
|
||||
|
||||
let info = T::info();
|
||||
let state = T::state();
|
||||
let kernel_clock = T::frequency();
|
||||
let r = info.regs;
|
||||
|
||||
r.cr3().write(|w| {
|
||||
w.set_rtse(rts.is_some());
|
||||
w.set_ctse(cts.is_some());
|
||||
#[cfg(not(any(usart_v1, usart_v2)))]
|
||||
w.set_dem(de.is_some());
|
||||
});
|
||||
configure(info, kernel_clock, &config, true, true)?;
|
||||
|
||||
T::Interrupt::unpend();
|
||||
unsafe { T::Interrupt::enable() };
|
||||
|
||||
state.tx_rx_refcount.store(2, Ordering::Relaxed);
|
||||
|
||||
Ok(Self {
|
||||
let mut this = Self {
|
||||
tx: UartTx {
|
||||
_phantom: PhantomData,
|
||||
info,
|
||||
@ -1271,7 +1263,30 @@ impl<'d, M: Mode> Uart<'d, M> {
|
||||
#[cfg(any(usart_v1, usart_v2))]
|
||||
buffered_sr: stm32_metapac::usart::regs::Sr(0),
|
||||
},
|
||||
})
|
||||
};
|
||||
this.enable_and_configure(&config)?;
|
||||
Ok(this)
|
||||
}
|
||||
|
||||
fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||
let info = self.rx.info;
|
||||
let state = self.rx.state;
|
||||
state.tx_rx_refcount.store(2, Ordering::Relaxed);
|
||||
|
||||
info.rcc.enable_and_reset();
|
||||
|
||||
info.regs.cr3().write(|w| {
|
||||
w.set_rtse(self.rx.rts.is_some());
|
||||
w.set_ctse(self.tx.cts.is_some());
|
||||
#[cfg(not(any(usart_v1, usart_v2)))]
|
||||
w.set_dem(self.tx.de.is_some());
|
||||
});
|
||||
configure(info, self.rx.kernel_clock, config, true, true)?;
|
||||
|
||||
info.interrupt.unpend();
|
||||
unsafe { info.interrupt.enable() };
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Perform a blocking write
|
||||
|
@ -4,10 +4,12 @@ use core::sync::atomic::{compiler_fence, Ordering};
|
||||
use core::task::Poll;
|
||||
|
||||
use embassy_embedded_hal::SetConfig;
|
||||
use embassy_hal_internal::PeripheralRef;
|
||||
use futures_util::future::{select, Either};
|
||||
|
||||
use super::{clear_interrupt_flags, rdr, reconfigure, sr, Config, ConfigError, Error, Info, State, UartRx};
|
||||
use crate::dma::ReadableRingBuffer;
|
||||
use crate::gpio::{AnyPin, SealedPin as _};
|
||||
use crate::mode::Async;
|
||||
use crate::time::Hertz;
|
||||
use crate::usart::{Regs, Sr};
|
||||
@ -19,6 +21,8 @@ pub struct RingBufferedUartRx<'d> {
|
||||
info: &'static Info,
|
||||
state: &'static State,
|
||||
kernel_clock: Hertz,
|
||||
rx: Option<PeripheralRef<'d, AnyPin>>,
|
||||
rts: Option<PeripheralRef<'d, AnyPin>>,
|
||||
ring_buf: ReadableRingBuffer<'d, u8>,
|
||||
}
|
||||
|
||||
@ -49,6 +53,8 @@ impl<'d> UartRx<'d, Async> {
|
||||
let state = self.state;
|
||||
let kernel_clock = self.kernel_clock;
|
||||
let ring_buf = unsafe { ReadableRingBuffer::new(rx_dma, request, rdr(info.regs), dma_buf, opts) };
|
||||
let rx = unsafe { self.rx.as_ref().map(|x| x.clone_unchecked()) };
|
||||
let rts = unsafe { self.rts.as_ref().map(|x| x.clone_unchecked()) };
|
||||
|
||||
// Don't disable the clock
|
||||
mem::forget(self);
|
||||
@ -57,6 +63,8 @@ impl<'d> UartRx<'d, Async> {
|
||||
info,
|
||||
state,
|
||||
kernel_clock,
|
||||
rx,
|
||||
rts,
|
||||
ring_buf,
|
||||
}
|
||||
}
|
||||
@ -221,6 +229,8 @@ impl<'d> RingBufferedUartRx<'d> {
|
||||
impl Drop for RingBufferedUartRx<'_> {
|
||||
fn drop(&mut self) {
|
||||
self.teardown_uart();
|
||||
self.rx.as_ref().map(|x| x.set_as_disconnected());
|
||||
self.rts.as_ref().map(|x| x.set_as_disconnected());
|
||||
super::drop_tx_rx(self.info, self.state);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user