Merge pull request #2836 from honzasp/usart-nogeneric

stm32/usart: Remove BasicInstance generic
This commit is contained in:
Dario Nieuwenhuis 2024-05-23 17:04:52 +00:00 committed by GitHub
commit 8226904b34
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 470 additions and 434 deletions

View File

@ -387,7 +387,6 @@ fn main() {
struct ClockGen<'a> { struct ClockGen<'a> {
rcc_registers: &'a PeripheralRegisters, rcc_registers: &'a PeripheralRegisters,
chained_muxes: HashMap<&'a str, &'a PeripheralRccRegister>, chained_muxes: HashMap<&'a str, &'a PeripheralRccRegister>,
force_refcount: HashSet<&'a str>,
refcount_statics: BTreeSet<Ident>, refcount_statics: BTreeSet<Ident>,
clock_names: BTreeSet<String>, clock_names: BTreeSet<String>,
@ -397,7 +396,6 @@ fn main() {
let mut clock_gen = ClockGen { let mut clock_gen = ClockGen {
rcc_registers, rcc_registers,
chained_muxes: HashMap::new(), chained_muxes: HashMap::new(),
force_refcount: HashSet::from(["usart"]),
refcount_statics: BTreeSet::new(), refcount_statics: BTreeSet::new(),
clock_names: BTreeSet::new(), clock_names: BTreeSet::new(),
@ -542,7 +540,6 @@ fn main() {
None => (TokenStream::new(), TokenStream::new()), None => (TokenStream::new(), TokenStream::new()),
}; };
let ptype = if let Some(reg) = &p.registers { reg.kind } else { "" };
let pname = format_ident!("{}", p.name); let pname = format_ident!("{}", p.name);
let en_reg = format_ident!("{}", en.register.to_ascii_lowercase()); let en_reg = format_ident!("{}", en.register.to_ascii_lowercase());
let set_en_field = format_ident!("set_{}", en.field.to_ascii_lowercase()); let set_en_field = format_ident!("set_{}", en.field.to_ascii_lowercase());
@ -570,8 +567,7 @@ fn main() {
}; };
let en_bit_offs: u8 = en_bit_offs.offset.try_into().unwrap(); let en_bit_offs: u8 = en_bit_offs.offset.try_into().unwrap();
let refcount = let refcount = *rcc_field_count.get(&(en.register, en.field)).unwrap() > 1;
clock_gen.force_refcount.contains(ptype) || *rcc_field_count.get(&(en.register, en.field)).unwrap() > 1;
let (before_enable, before_disable) = if refcount { let (before_enable, before_disable) = if refcount {
let refcount_static = let refcount_static =
format_ident!("{}_{}", en.register.to_ascii_uppercase(), en.field.to_ascii_uppercase()); format_ident!("{}_{}", en.register.to_ascii_uppercase(), en.field.to_ascii_uppercase());

View File

@ -1,7 +1,7 @@
use core::future::poll_fn; use core::future::poll_fn;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::slice; use core::slice;
use core::sync::atomic::{AtomicBool, Ordering}; use core::sync::atomic::{AtomicBool, AtomicU8, Ordering};
use core::task::Poll; use core::task::Poll;
use embassy_embedded_hal::SetConfig; use embassy_embedded_hal::SetConfig;
@ -12,154 +12,163 @@ use embassy_sync::waitqueue::AtomicWaker;
#[cfg(not(any(usart_v1, usart_v2)))] #[cfg(not(any(usart_v1, usart_v2)))]
use super::DePin; use super::DePin;
use super::{ use super::{
clear_interrupt_flags, configure, rdr, reconfigure, sr, tdr, BasicInstance, Config, ConfigError, CtsPin, Error, clear_interrupt_flags, configure, rdr, reconfigure, sr, tdr, Config, ConfigError, CtsPin, Error, Info, Instance,
RtsPin, RxPin, TxPin, Regs, RtsPin, RxPin, TxPin,
}; };
use crate::gpio::AFType; use crate::gpio::AFType;
use crate::interrupt; use crate::interrupt::typelevel::Interrupt as _;
use crate::interrupt::typelevel::Interrupt; use crate::interrupt::{self, InterruptExt};
use crate::time::Hertz;
/// Interrupt handler. /// Interrupt handler.
pub struct InterruptHandler<T: BasicInstance> { pub struct InterruptHandler<T: Instance> {
_phantom: PhantomData<T>, _phantom: PhantomData<T>,
} }
impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
unsafe fn on_interrupt() { unsafe fn on_interrupt() {
let r = T::regs(); on_interrupt(T::info().regs, T::buffered_state())
let state = T::buffered_state(); }
}
// RX unsafe fn on_interrupt(r: Regs, state: &'static State) {
let sr_val = sr(r).read(); // RX
// On v1 & v2, reading DR clears the rxne, error and idle interrupt let sr_val = sr(r).read();
// flags. Keep this close to the SR read to reduce the chance of a // On v1 & v2, reading DR clears the rxne, error and idle interrupt
// flag being set in-between. // flags. Keep this close to the SR read to reduce the chance of a
let dr = if sr_val.rxne() || cfg!(any(usart_v1, usart_v2)) && (sr_val.ore() || sr_val.idle()) { // flag being set in-between.
Some(rdr(r).read_volatile()) let dr = if sr_val.rxne() || cfg!(any(usart_v1, usart_v2)) && (sr_val.ore() || sr_val.idle()) {
Some(rdr(r).read_volatile())
} else {
None
};
clear_interrupt_flags(r, sr_val);
if sr_val.pe() {
warn!("Parity error");
}
if sr_val.fe() {
warn!("Framing error");
}
if sr_val.ne() {
warn!("Noise error");
}
if sr_val.ore() {
warn!("Overrun error");
}
if sr_val.rxne() {
let mut rx_writer = state.rx_buf.writer();
let buf = rx_writer.push_slice();
if !buf.is_empty() {
if let Some(byte) = dr {
buf[0] = byte;
rx_writer.push_done(1);
}
} else { } else {
None // FIXME: Should we disable any further RX interrupts when the buffer becomes full.
};
clear_interrupt_flags(r, sr_val);
if sr_val.pe() {
warn!("Parity error");
}
if sr_val.fe() {
warn!("Framing error");
}
if sr_val.ne() {
warn!("Noise error");
}
if sr_val.ore() {
warn!("Overrun error");
}
if sr_val.rxne() {
let mut rx_writer = state.rx_buf.writer();
let buf = rx_writer.push_slice();
if !buf.is_empty() {
if let Some(byte) = dr {
buf[0] = byte;
rx_writer.push_done(1);
}
} else {
// FIXME: Should we disable any further RX interrupts when the buffer becomes full.
}
if !state.rx_buf.is_empty() {
state.rx_waker.wake();
}
} }
if sr_val.idle() { if !state.rx_buf.is_empty() {
state.rx_waker.wake(); state.rx_waker.wake();
} }
}
// With `usart_v4` hardware FIFO is enabled and Transmission complete (TC) if sr_val.idle() {
// indicates that all bytes are pushed out from the FIFO. state.rx_waker.wake();
// For other usart variants it shows that last byte from the buffer was just sent. }
if sr_val.tc() {
// For others it is cleared above with `clear_interrupt_flags`.
#[cfg(any(usart_v1, usart_v2))]
sr(r).modify(|w| w.set_tc(false));
// With `usart_v4` hardware FIFO is enabled and Transmission complete (TC)
// indicates that all bytes are pushed out from the FIFO.
// For other usart variants it shows that last byte from the buffer was just sent.
if sr_val.tc() {
// For others it is cleared above with `clear_interrupt_flags`.
#[cfg(any(usart_v1, usart_v2))]
sr(r).modify(|w| w.set_tc(false));
r.cr1().modify(|w| {
w.set_tcie(false);
});
state.tx_done.store(true, Ordering::Release);
state.tx_waker.wake();
}
// TX
if sr(r).read().txe() {
let mut tx_reader = state.tx_buf.reader();
let buf = tx_reader.pop_slice();
if !buf.is_empty() {
r.cr1().modify(|w| { r.cr1().modify(|w| {
w.set_tcie(false); w.set_txeie(true);
}); });
state.tx_done.store(true, Ordering::Release); // Enable transmission complete interrupt when last byte is going to be sent out.
state.tx_waker.wake(); if buf.len() == 1 {
}
// TX
if sr(r).read().txe() {
let mut tx_reader = state.tx_buf.reader();
let buf = tx_reader.pop_slice();
if !buf.is_empty() {
r.cr1().modify(|w| { r.cr1().modify(|w| {
w.set_txeie(true); w.set_tcie(true);
});
// Enable transmission complete interrupt when last byte is going to be sent out.
if buf.len() == 1 {
r.cr1().modify(|w| {
w.set_tcie(true);
});
}
tdr(r).write_volatile(buf[0].into());
tx_reader.pop_done(1);
} else {
// Disable interrupt until we have something to transmit again.
r.cr1().modify(|w| {
w.set_txeie(false);
}); });
} }
tdr(r).write_volatile(buf[0].into());
tx_reader.pop_done(1);
} else {
// Disable interrupt until we have something to transmit again.
r.cr1().modify(|w| {
w.set_txeie(false);
});
} }
} }
} }
pub(crate) struct State { pub(super) struct State {
pub(crate) rx_waker: AtomicWaker, rx_waker: AtomicWaker,
pub(crate) rx_buf: RingBuffer, rx_buf: RingBuffer,
pub(crate) tx_waker: AtomicWaker, tx_waker: AtomicWaker,
pub(crate) tx_buf: RingBuffer, tx_buf: RingBuffer,
pub(crate) tx_done: AtomicBool, tx_done: AtomicBool,
tx_rx_refcount: AtomicU8,
} }
impl State { impl State {
/// Create new state pub(super) const fn new() -> Self {
pub(crate) const fn new() -> Self {
Self { Self {
rx_buf: RingBuffer::new(), rx_buf: RingBuffer::new(),
tx_buf: RingBuffer::new(), tx_buf: RingBuffer::new(),
rx_waker: AtomicWaker::new(), rx_waker: AtomicWaker::new(),
tx_waker: AtomicWaker::new(), tx_waker: AtomicWaker::new(),
tx_done: AtomicBool::new(true), tx_done: AtomicBool::new(true),
tx_rx_refcount: AtomicU8::new(0),
} }
} }
} }
/// Bidirectional buffered UART /// Bidirectional buffered UART
pub struct BufferedUart<'d, T: BasicInstance> { pub struct BufferedUart<'d> {
rx: BufferedUartRx<'d, T>, rx: BufferedUartRx<'d>,
tx: BufferedUartTx<'d, T>, tx: BufferedUartTx<'d>,
} }
/// Tx-only buffered UART /// Tx-only buffered UART
/// ///
/// Created with [BufferedUart::split] /// Created with [BufferedUart::split]
pub struct BufferedUartTx<'d, T: BasicInstance> { pub struct BufferedUartTx<'d> {
phantom: PhantomData<&'d mut T>, info: &'static Info,
state: &'static State,
kernel_clock: Hertz,
_phantom: PhantomData<&'d mut ()>,
} }
/// Rx-only buffered UART /// Rx-only buffered UART
/// ///
/// Created with [BufferedUart::split] /// Created with [BufferedUart::split]
pub struct BufferedUartRx<'d, T: BasicInstance> { pub struct BufferedUartRx<'d> {
phantom: PhantomData<&'d mut T>, info: &'static Info,
state: &'static State,
kernel_clock: Hertz,
_phantom: PhantomData<&'d mut ()>,
} }
impl<'d, T: BasicInstance> SetConfig for BufferedUart<'d, T> { impl<'d> SetConfig for BufferedUart<'d> {
type Config = Config; type Config = Config;
type ConfigError = ConfigError; type ConfigError = ConfigError;
@ -168,7 +177,7 @@ impl<'d, T: BasicInstance> SetConfig for BufferedUart<'d, T> {
} }
} }
impl<'d, T: BasicInstance> SetConfig for BufferedUartRx<'d, T> { impl<'d> SetConfig for BufferedUartRx<'d> {
type Config = Config; type Config = Config;
type ConfigError = ConfigError; type ConfigError = ConfigError;
@ -177,7 +186,7 @@ impl<'d, T: BasicInstance> SetConfig for BufferedUartRx<'d, T> {
} }
} }
impl<'d, T: BasicInstance> SetConfig for BufferedUartTx<'d, T> { impl<'d> SetConfig for BufferedUartTx<'d> {
type Config = Config; type Config = Config;
type ConfigError = ConfigError; type ConfigError = ConfigError;
@ -186,9 +195,9 @@ impl<'d, T: BasicInstance> SetConfig for BufferedUartTx<'d, T> {
} }
} }
impl<'d, T: BasicInstance> BufferedUart<'d, T> { impl<'d> BufferedUart<'d> {
/// Create a new bidirectional buffered UART driver /// Create a new bidirectional buffered UART driver
pub fn new( pub fn new<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
@ -197,15 +206,13 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
rx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8],
config: Config, config: Config,
) -> Result<Self, ConfigError> { ) -> Result<Self, ConfigError> {
// UartRx and UartTx have one refcount ea.
T::enable_and_reset();
T::enable_and_reset(); T::enable_and_reset();
Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
} }
/// Create a new bidirectional buffered UART driver with request-to-send and clear-to-send pins /// Create a new bidirectional buffered UART driver with request-to-send and clear-to-send pins
pub fn new_with_rtscts( pub fn new_with_rtscts<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
@ -218,13 +225,11 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
) -> Result<Self, ConfigError> { ) -> Result<Self, ConfigError> {
into_ref!(cts, rts); into_ref!(cts, rts);
// UartRx and UartTx have one refcount ea.
T::enable_and_reset();
T::enable_and_reset(); T::enable_and_reset();
rts.set_as_af(rts.af_num(), AFType::OutputPushPull); rts.set_as_af(rts.af_num(), AFType::OutputPushPull);
cts.set_as_af(cts.af_num(), AFType::Input); cts.set_as_af(cts.af_num(), AFType::Input);
T::regs().cr3().write(|w| { T::info().regs.cr3().write(|w| {
w.set_rtse(true); w.set_rtse(true);
w.set_ctse(true); w.set_ctse(true);
}); });
@ -234,7 +239,7 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
/// Create a new bidirectional buffered UART driver with a driver-enable pin /// Create a new bidirectional buffered UART driver with a driver-enable pin
#[cfg(not(any(usart_v1, usart_v2)))] #[cfg(not(any(usart_v1, usart_v2)))]
pub fn new_with_de( pub fn new_with_de<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
@ -246,19 +251,17 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
) -> Result<Self, ConfigError> { ) -> Result<Self, ConfigError> {
into_ref!(de); into_ref!(de);
// UartRx and UartTx have one refcount ea.
T::enable_and_reset();
T::enable_and_reset(); T::enable_and_reset();
de.set_as_af(de.af_num(), AFType::OutputPushPull); de.set_as_af(de.af_num(), AFType::OutputPushPull);
T::regs().cr3().write(|w| { T::info().regs.cr3().write(|w| {
w.set_dem(true); w.set_dem(true);
}); });
Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
} }
fn new_inner( fn new_inner<T: Instance>(
_peri: impl Peripheral<P = T> + 'd, _peri: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
tx: impl Peripheral<P = impl TxPin<T>> + 'd, tx: impl Peripheral<P = impl TxPin<T>> + 'd,
@ -268,17 +271,19 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
) -> Result<Self, ConfigError> { ) -> Result<Self, ConfigError> {
into_ref!(_peri, rx, tx); into_ref!(_peri, rx, tx);
let info = T::info();
let state = T::buffered_state(); let state = T::buffered_state();
let kernel_clock = T::frequency();
let len = tx_buffer.len(); let len = tx_buffer.len();
unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), len) }; unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
let len = rx_buffer.len(); let len = rx_buffer.len();
unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) }; unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) };
let r = T::regs(); let r = info.regs;
rx.set_as_af(rx.af_num(), AFType::Input); rx.set_as_af(rx.af_num(), AFType::Input);
tx.set_as_af(tx.af_num(), AFType::OutputPushPull); tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
configure(r, &config, T::frequency(), T::KIND, true, true)?; configure(info, kernel_clock, &config, true, true)?;
r.cr1().modify(|w| { r.cr1().modify(|w| {
w.set_rxneie(true); w.set_rxneie(true);
@ -288,22 +293,34 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
T::Interrupt::unpend(); T::Interrupt::unpend();
unsafe { T::Interrupt::enable() }; unsafe { T::Interrupt::enable() };
state.tx_rx_refcount.store(2, Ordering::Relaxed);
Ok(Self { Ok(Self {
rx: BufferedUartRx { phantom: PhantomData }, rx: BufferedUartRx {
tx: BufferedUartTx { phantom: PhantomData }, info,
state,
kernel_clock,
_phantom: PhantomData,
},
tx: BufferedUartTx {
info,
state,
kernel_clock,
_phantom: PhantomData,
},
}) })
} }
/// Split the driver into a Tx and Rx part (useful for sending to separate tasks) /// Split the driver into a Tx and Rx part (useful for sending to separate tasks)
pub fn split(self) -> (BufferedUartTx<'d, T>, BufferedUartRx<'d, T>) { pub fn split(self) -> (BufferedUartTx<'d>, BufferedUartRx<'d>) {
(self.tx, self.rx) (self.tx, self.rx)
} }
/// Reconfigure the driver /// Reconfigure the driver
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
reconfigure::<T>(config)?; reconfigure(self.rx.info, self.rx.kernel_clock, config)?;
T::regs().cr1().modify(|w| { self.rx.info.regs.cr1().modify(|w| {
w.set_rxneie(true); w.set_rxneie(true);
w.set_idleie(true); w.set_idleie(true);
}); });
@ -312,10 +329,10 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
} }
} }
impl<'d, T: BasicInstance> BufferedUartRx<'d, T> { impl<'d> BufferedUartRx<'d> {
async fn read(&self, buf: &mut [u8]) -> Result<usize, Error> { async fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
poll_fn(move |cx| { poll_fn(move |cx| {
let state = T::buffered_state(); let state = self.state;
let mut rx_reader = unsafe { state.rx_buf.reader() }; let mut rx_reader = unsafe { state.rx_buf.reader() };
let data = rx_reader.pop_slice(); let data = rx_reader.pop_slice();
@ -327,7 +344,7 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> {
rx_reader.pop_done(len); rx_reader.pop_done(len);
if do_pend { if do_pend {
T::Interrupt::pend(); self.info.interrupt.pend();
} }
return Poll::Ready(Ok(len)); return Poll::Ready(Ok(len));
@ -341,7 +358,7 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> {
fn blocking_read(&self, buf: &mut [u8]) -> Result<usize, Error> { fn blocking_read(&self, buf: &mut [u8]) -> Result<usize, Error> {
loop { loop {
let state = T::buffered_state(); let state = self.state;
let mut rx_reader = unsafe { state.rx_buf.reader() }; let mut rx_reader = unsafe { state.rx_buf.reader() };
let data = rx_reader.pop_slice(); let data = rx_reader.pop_slice();
@ -353,7 +370,7 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> {
rx_reader.pop_done(len); rx_reader.pop_done(len);
if do_pend { if do_pend {
T::Interrupt::pend(); self.info.interrupt.pend();
} }
return Ok(len); return Ok(len);
@ -363,7 +380,7 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> {
async fn fill_buf(&self) -> Result<&[u8], Error> { async fn fill_buf(&self) -> Result<&[u8], Error> {
poll_fn(move |cx| { poll_fn(move |cx| {
let state = T::buffered_state(); let state = self.state;
let mut rx_reader = unsafe { state.rx_buf.reader() }; let mut rx_reader = unsafe { state.rx_buf.reader() };
let (p, n) = rx_reader.pop_buf(); let (p, n) = rx_reader.pop_buf();
if n == 0 { if n == 0 {
@ -378,20 +395,20 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> {
} }
fn consume(&self, amt: usize) { fn consume(&self, amt: usize) {
let state = T::buffered_state(); let state = self.state;
let mut rx_reader = unsafe { state.rx_buf.reader() }; let mut rx_reader = unsafe { state.rx_buf.reader() };
let full = state.rx_buf.is_full(); let full = state.rx_buf.is_full();
rx_reader.pop_done(amt); rx_reader.pop_done(amt);
if full { if full {
T::Interrupt::pend(); self.info.interrupt.pend();
} }
} }
/// Reconfigure the driver /// Reconfigure the driver
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
reconfigure::<T>(config)?; reconfigure(self.info, self.kernel_clock, config)?;
T::regs().cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_rxneie(true); w.set_rxneie(true);
w.set_idleie(true); w.set_idleie(true);
}); });
@ -400,10 +417,10 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> {
} }
} }
impl<'d, T: BasicInstance> BufferedUartTx<'d, T> { impl<'d> BufferedUartTx<'d> {
async fn write(&self, buf: &[u8]) -> Result<usize, Error> { async fn write(&self, buf: &[u8]) -> Result<usize, Error> {
poll_fn(move |cx| { poll_fn(move |cx| {
let state = T::buffered_state(); let state = self.state;
state.tx_done.store(false, Ordering::Release); state.tx_done.store(false, Ordering::Release);
let empty = state.tx_buf.is_empty(); let empty = state.tx_buf.is_empty();
@ -420,7 +437,7 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> {
tx_writer.push_done(n); tx_writer.push_done(n);
if empty { if empty {
T::Interrupt::pend(); self.info.interrupt.pend();
} }
Poll::Ready(Ok(n)) Poll::Ready(Ok(n))
@ -430,7 +447,7 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> {
async fn flush(&self) -> Result<(), Error> { async fn flush(&self) -> Result<(), Error> {
poll_fn(move |cx| { poll_fn(move |cx| {
let state = T::buffered_state(); let state = self.state;
if !state.tx_done.load(Ordering::Acquire) { if !state.tx_done.load(Ordering::Acquire) {
state.tx_waker.register(cx.waker()); state.tx_waker.register(cx.waker());
@ -444,7 +461,7 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> {
fn blocking_write(&self, buf: &[u8]) -> Result<usize, Error> { fn blocking_write(&self, buf: &[u8]) -> Result<usize, Error> {
loop { loop {
let state = T::buffered_state(); let state = self.state;
let empty = state.tx_buf.is_empty(); let empty = state.tx_buf.is_empty();
let mut tx_writer = unsafe { state.tx_buf.writer() }; let mut tx_writer = unsafe { state.tx_buf.writer() };
@ -455,7 +472,7 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> {
tx_writer.push_done(n); tx_writer.push_done(n);
if empty { if empty {
T::Interrupt::pend(); self.info.interrupt.pend();
} }
return Ok(n); return Ok(n);
@ -465,7 +482,7 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> {
fn blocking_flush(&self) -> Result<(), Error> { fn blocking_flush(&self) -> Result<(), Error> {
loop { loop {
let state = T::buffered_state(); let state = self.state;
if state.tx_buf.is_empty() { if state.tx_buf.is_empty() {
return Ok(()); return Ok(());
} }
@ -474,9 +491,9 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> {
/// Reconfigure the driver /// Reconfigure the driver
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
reconfigure::<T>(config)?; reconfigure(self.info, self.kernel_clock, config)?;
T::regs().cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_rxneie(true); w.set_rxneie(true);
w.set_idleie(true); w.set_idleie(true);
}); });
@ -485,65 +502,78 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> {
} }
} }
impl<'d, T: BasicInstance> Drop for BufferedUartRx<'d, T> { impl<'d> Drop for BufferedUartRx<'d> {
fn drop(&mut self) { fn drop(&mut self) {
let state = T::buffered_state(); let state = self.state;
unsafe { unsafe {
state.rx_buf.deinit(); state.rx_buf.deinit();
// TX is inactive if the the buffer is not available. // TX is inactive if the the buffer is not available.
// We can now unregister the interrupt handler // We can now unregister the interrupt handler
if state.tx_buf.len() == 0 { if state.tx_buf.len() == 0 {
T::Interrupt::disable(); self.info.interrupt.disable();
} }
} }
T::disable(); drop_tx_rx(self.info, state);
} }
} }
impl<'d, T: BasicInstance> Drop for BufferedUartTx<'d, T> { impl<'d> Drop for BufferedUartTx<'d> {
fn drop(&mut self) { fn drop(&mut self) {
let state = T::buffered_state(); let state = self.state;
unsafe { unsafe {
state.tx_buf.deinit(); state.tx_buf.deinit();
// RX is inactive if the the buffer is not available. // RX is inactive if the the buffer is not available.
// We can now unregister the interrupt handler // We can now unregister the interrupt handler
if state.rx_buf.len() == 0 { if state.rx_buf.len() == 0 {
T::Interrupt::disable(); self.info.interrupt.disable();
} }
} }
T::disable(); drop_tx_rx(self.info, state);
} }
} }
impl<'d, T: BasicInstance> embedded_io_async::ErrorType for BufferedUart<'d, T> { fn drop_tx_rx(info: &Info, state: &State) {
// We cannot use atomic subtraction here, because it's not supported for all targets
let is_last_drop = critical_section::with(|_| {
let refcount = state.tx_rx_refcount.load(Ordering::Relaxed);
assert!(refcount >= 1);
state.tx_rx_refcount.store(refcount - 1, Ordering::Relaxed);
refcount == 1
});
if is_last_drop {
info.enable_bit.disable();
}
}
impl<'d> embedded_io_async::ErrorType for BufferedUart<'d> {
type Error = Error; type Error = Error;
} }
impl<'d, T: BasicInstance> embedded_io_async::ErrorType for BufferedUartRx<'d, T> { impl<'d> embedded_io_async::ErrorType for BufferedUartRx<'d> {
type Error = Error; type Error = Error;
} }
impl<'d, T: BasicInstance> embedded_io_async::ErrorType for BufferedUartTx<'d, T> { impl<'d> embedded_io_async::ErrorType for BufferedUartTx<'d> {
type Error = Error; type Error = Error;
} }
impl<'d, T: BasicInstance> embedded_io_async::Read for BufferedUart<'d, T> { impl<'d> embedded_io_async::Read for BufferedUart<'d> {
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
self.rx.read(buf).await self.rx.read(buf).await
} }
} }
impl<'d, T: BasicInstance> embedded_io_async::Read for BufferedUartRx<'d, T> { impl<'d> embedded_io_async::Read for BufferedUartRx<'d> {
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
Self::read(self, buf).await Self::read(self, buf).await
} }
} }
impl<'d, T: BasicInstance> embedded_io_async::BufRead for BufferedUart<'d, T> { impl<'d> embedded_io_async::BufRead for BufferedUart<'d> {
async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
self.rx.fill_buf().await self.rx.fill_buf().await
} }
@ -553,7 +583,7 @@ impl<'d, T: BasicInstance> embedded_io_async::BufRead for BufferedUart<'d, T> {
} }
} }
impl<'d, T: BasicInstance> embedded_io_async::BufRead for BufferedUartRx<'d, T> { impl<'d> embedded_io_async::BufRead for BufferedUartRx<'d> {
async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
Self::fill_buf(self).await Self::fill_buf(self).await
} }
@ -563,7 +593,7 @@ impl<'d, T: BasicInstance> embedded_io_async::BufRead for BufferedUartRx<'d, T>
} }
} }
impl<'d, T: BasicInstance> embedded_io_async::Write for BufferedUart<'d, T> { impl<'d> embedded_io_async::Write for BufferedUart<'d> {
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.tx.write(buf).await self.tx.write(buf).await
} }
@ -573,7 +603,7 @@ impl<'d, T: BasicInstance> embedded_io_async::Write for BufferedUart<'d, T> {
} }
} }
impl<'d, T: BasicInstance> embedded_io_async::Write for BufferedUartTx<'d, T> { impl<'d> embedded_io_async::Write for BufferedUartTx<'d> {
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
Self::write(self, buf).await Self::write(self, buf).await
} }
@ -583,19 +613,19 @@ impl<'d, T: BasicInstance> embedded_io_async::Write for BufferedUartTx<'d, T> {
} }
} }
impl<'d, T: BasicInstance> embedded_io::Read for BufferedUart<'d, T> { impl<'d> embedded_io::Read for BufferedUart<'d> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
self.rx.blocking_read(buf) self.rx.blocking_read(buf)
} }
} }
impl<'d, T: BasicInstance> embedded_io::Read for BufferedUartRx<'d, T> { impl<'d> embedded_io::Read for BufferedUartRx<'d> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
self.blocking_read(buf) self.blocking_read(buf)
} }
} }
impl<'d, T: BasicInstance> embedded_io::Write for BufferedUart<'d, T> { impl<'d> embedded_io::Write for BufferedUart<'d> {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.tx.blocking_write(buf) self.tx.blocking_write(buf)
} }
@ -605,7 +635,7 @@ impl<'d, T: BasicInstance> embedded_io::Write for BufferedUart<'d, T> {
} }
} }
impl<'d, T: BasicInstance> embedded_io::Write for BufferedUartTx<'d, T> { impl<'d> embedded_io::Write for BufferedUartTx<'d> {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
Self::blocking_write(self, buf) Self::blocking_write(self, buf)
} }
@ -615,11 +645,11 @@ impl<'d, T: BasicInstance> embedded_io::Write for BufferedUartTx<'d, T> {
} }
} }
impl<'d, T: BasicInstance> embedded_hal_02::serial::Read<u8> for BufferedUartRx<'d, T> { impl<'d> embedded_hal_02::serial::Read<u8> for BufferedUartRx<'d> {
type Error = Error; type Error = Error;
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
let r = T::regs(); let r = self.info.regs;
unsafe { unsafe {
let sr = sr(r).read(); let sr = sr(r).read();
if sr.pe() { if sr.pe() {
@ -643,7 +673,7 @@ impl<'d, T: BasicInstance> embedded_hal_02::serial::Read<u8> for BufferedUartRx<
} }
} }
impl<'d, T: BasicInstance> embedded_hal_02::blocking::serial::Write<u8> for BufferedUartTx<'d, T> { impl<'d> embedded_hal_02::blocking::serial::Write<u8> for BufferedUartTx<'d> {
type Error = Error; type Error = Error;
fn bwrite_all(&mut self, mut buffer: &[u8]) -> Result<(), Self::Error> { fn bwrite_all(&mut self, mut buffer: &[u8]) -> Result<(), Self::Error> {
@ -662,7 +692,7 @@ impl<'d, T: BasicInstance> embedded_hal_02::blocking::serial::Write<u8> for Buff
} }
} }
impl<'d, T: BasicInstance> embedded_hal_02::serial::Read<u8> for BufferedUart<'d, T> { impl<'d> embedded_hal_02::serial::Read<u8> for BufferedUart<'d> {
type Error = Error; type Error = Error;
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
@ -670,7 +700,7 @@ impl<'d, T: BasicInstance> embedded_hal_02::serial::Read<u8> for BufferedUart<'d
} }
} }
impl<'d, T: BasicInstance> embedded_hal_02::blocking::serial::Write<u8> for BufferedUart<'d, T> { impl<'d> embedded_hal_02::blocking::serial::Write<u8> for BufferedUart<'d> {
type Error = Error; type Error = Error;
fn bwrite_all(&mut self, mut buffer: &[u8]) -> Result<(), Self::Error> { fn bwrite_all(&mut self, mut buffer: &[u8]) -> Result<(), Self::Error> {
@ -689,25 +719,25 @@ impl<'d, T: BasicInstance> embedded_hal_02::blocking::serial::Write<u8> for Buff
} }
} }
impl<'d, T: BasicInstance> embedded_hal_nb::serial::ErrorType for BufferedUart<'d, T> { impl<'d> embedded_hal_nb::serial::ErrorType for BufferedUart<'d> {
type Error = Error; type Error = Error;
} }
impl<'d, T: BasicInstance> embedded_hal_nb::serial::ErrorType for BufferedUartTx<'d, T> { impl<'d> embedded_hal_nb::serial::ErrorType for BufferedUartTx<'d> {
type Error = Error; type Error = Error;
} }
impl<'d, T: BasicInstance> embedded_hal_nb::serial::ErrorType for BufferedUartRx<'d, T> { impl<'d> embedded_hal_nb::serial::ErrorType for BufferedUartRx<'d> {
type Error = Error; type Error = Error;
} }
impl<'d, T: BasicInstance> embedded_hal_nb::serial::Read for BufferedUartRx<'d, T> { impl<'d> embedded_hal_nb::serial::Read for BufferedUartRx<'d> {
fn read(&mut self) -> nb::Result<u8, Self::Error> { fn read(&mut self) -> nb::Result<u8, Self::Error> {
embedded_hal_02::serial::Read::read(self) embedded_hal_02::serial::Read::read(self)
} }
} }
impl<'d, T: BasicInstance> embedded_hal_nb::serial::Write for BufferedUartTx<'d, T> { impl<'d> embedded_hal_nb::serial::Write for BufferedUartTx<'d> {
fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
self.blocking_write(&[char]).map(drop).map_err(nb::Error::Other) self.blocking_write(&[char]).map(drop).map_err(nb::Error::Other)
} }
@ -717,13 +747,13 @@ impl<'d, T: BasicInstance> embedded_hal_nb::serial::Write for BufferedUartTx<'d,
} }
} }
impl<'d, T: BasicInstance> embedded_hal_nb::serial::Read for BufferedUart<'d, T> { impl<'d> embedded_hal_nb::serial::Read for BufferedUart<'d> {
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
embedded_hal_02::serial::Read::read(&mut self.rx) embedded_hal_02::serial::Read::read(&mut self.rx)
} }
} }
impl<'d, T: BasicInstance> embedded_hal_nb::serial::Write for BufferedUart<'d, T> { impl<'d> embedded_hal_nb::serial::Write for BufferedUart<'d> {
fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
self.tx.blocking_write(&[char]).map(drop).map_err(nb::Error::Other) self.tx.blocking_write(&[char]).map(drop).map_err(nb::Error::Other)
} }

View File

@ -4,7 +4,7 @@
use core::future::poll_fn; use core::future::poll_fn;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::sync::atomic::{compiler_fence, Ordering}; use core::sync::atomic::{compiler_fence, AtomicU8, Ordering};
use core::task::Poll; use core::task::Poll;
use embassy_embedded_hal::SetConfig; use embassy_embedded_hal::SetConfig;
@ -15,7 +15,8 @@ use futures_util::future::{select, Either};
use crate::dma::ChannelAndRequest; use crate::dma::ChannelAndRequest;
use crate::gpio::{AFType, AnyPin, SealedPin}; use crate::gpio::{AFType, AnyPin, SealedPin};
use crate::interrupt::typelevel::Interrupt; use crate::interrupt::typelevel::Interrupt as _;
use crate::interrupt::{self, Interrupt, InterruptExt};
use crate::mode::{Async, Blocking, Mode}; use crate::mode::{Async, Blocking, Mode};
#[allow(unused_imports)] #[allow(unused_imports)]
#[cfg(not(any(usart_v1, usart_v2)))] #[cfg(not(any(usart_v1, usart_v2)))]
@ -27,57 +28,59 @@ use crate::pac::usart::Lpuart as Regs;
#[cfg(any(usart_v1, usart_v2))] #[cfg(any(usart_v1, usart_v2))]
use crate::pac::usart::Usart as Regs; use crate::pac::usart::Usart as Regs;
use crate::pac::usart::{regs, vals}; use crate::pac::usart::{regs, vals};
use crate::rcc::{ClockEnableBit, SealedRccPeripheral};
use crate::time::Hertz; use crate::time::Hertz;
use crate::{interrupt, peripherals, Peripheral}; use crate::Peripheral;
/// Interrupt handler. /// Interrupt handler.
pub struct InterruptHandler<T: BasicInstance> { pub struct InterruptHandler<T: Instance> {
_phantom: PhantomData<T>, _phantom: PhantomData<T>,
} }
impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
unsafe fn on_interrupt() { unsafe fn on_interrupt() {
let r = T::regs(); on_interrupt(T::info().regs, T::state())
let s = T::state();
let (sr, cr1, cr3) = (sr(r).read(), r.cr1().read(), r.cr3().read());
let has_errors = (sr.pe() && cr1.peie()) || ((sr.fe() || sr.ne() || sr.ore()) && cr3.eie());
if has_errors {
// clear all interrupts and DMA Rx Request
r.cr1().modify(|w| {
// disable RXNE interrupt
w.set_rxneie(false);
// disable parity interrupt
w.set_peie(false);
// disable idle line interrupt
w.set_idleie(false);
});
r.cr3().modify(|w| {
// disable Error Interrupt: (Frame error, Noise error, Overrun error)
w.set_eie(false);
// disable DMA Rx Request
w.set_dmar(false);
});
} else if cr1.idleie() && sr.idle() {
// IDLE detected: no more data will come
r.cr1().modify(|w| {
// disable idle line detection
w.set_idleie(false);
});
} else if cr1.rxneie() {
// We cannot check the RXNE flag as it is auto-cleared by the DMA controller
// It is up to the listener to determine if this in fact was a RX event and disable the RXNE detection
} else {
return;
}
compiler_fence(Ordering::SeqCst);
s.rx_waker.wake();
} }
} }
unsafe fn on_interrupt(r: Regs, s: &'static State) {
let (sr, cr1, cr3) = (sr(r).read(), r.cr1().read(), r.cr3().read());
let has_errors = (sr.pe() && cr1.peie()) || ((sr.fe() || sr.ne() || sr.ore()) && cr3.eie());
if has_errors {
// clear all interrupts and DMA Rx Request
r.cr1().modify(|w| {
// disable RXNE interrupt
w.set_rxneie(false);
// disable parity interrupt
w.set_peie(false);
// disable idle line interrupt
w.set_idleie(false);
});
r.cr3().modify(|w| {
// disable Error Interrupt: (Frame error, Noise error, Overrun error)
w.set_eie(false);
// disable DMA Rx Request
w.set_dmar(false);
});
} else if cr1.idleie() && sr.idle() {
// IDLE detected: no more data will come
r.cr1().modify(|w| {
// disable idle line detection
w.set_idleie(false);
});
} else if cr1.rxneie() {
// We cannot check the RXNE flag as it is auto-cleared by the DMA controller
// It is up to the listener to determine if this in fact was a RX event and disable the RXNE detection
} else {
return;
}
compiler_fence(Ordering::SeqCst);
s.rx_waker.wake();
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)] #[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
/// Number of data bits /// Number of data bits
@ -239,12 +242,12 @@ enum ReadCompletionEvent {
/// ///
/// See [`UartRx`] for more details, and see [`BufferedUart`] and [`RingBufferedUartRx`] /// See [`UartRx`] for more details, and see [`BufferedUart`] and [`RingBufferedUartRx`]
/// as alternatives that do provide the necessary guarantees for `embedded_io::Read`. /// as alternatives that do provide the necessary guarantees for `embedded_io::Read`.
pub struct Uart<'d, T: BasicInstance, M: Mode> { pub struct Uart<'d, M: Mode> {
tx: UartTx<'d, T, M>, tx: UartTx<'d, M>,
rx: UartRx<'d, T, M>, rx: UartRx<'d, M>,
} }
impl<'d, T: BasicInstance, M: Mode> SetConfig for Uart<'d, T, M> { impl<'d, M: Mode> SetConfig for Uart<'d, M> {
type Config = Config; type Config = Config;
type ConfigError = ConfigError; type ConfigError = ConfigError;
@ -258,15 +261,18 @@ impl<'d, T: BasicInstance, M: Mode> SetConfig for Uart<'d, T, M> {
/// ///
/// Can be obtained from [`Uart::split`], or can be constructed independently, /// Can be obtained from [`Uart::split`], or can be constructed independently,
/// if you do not need the receiving half of the driver. /// if you do not need the receiving half of the driver.
pub struct UartTx<'d, T: BasicInstance, M: Mode> { pub struct UartTx<'d, M: Mode> {
_phantom: PhantomData<(T, M)>, info: &'static Info,
state: &'static State,
kernel_clock: Hertz,
tx: Option<PeripheralRef<'d, AnyPin>>, tx: Option<PeripheralRef<'d, AnyPin>>,
cts: Option<PeripheralRef<'d, AnyPin>>, cts: Option<PeripheralRef<'d, AnyPin>>,
de: Option<PeripheralRef<'d, AnyPin>>, de: Option<PeripheralRef<'d, AnyPin>>,
tx_dma: Option<ChannelAndRequest<'d>>, tx_dma: Option<ChannelAndRequest<'d>>,
_phantom: PhantomData<M>,
} }
impl<'d, T: BasicInstance, M: Mode> SetConfig for UartTx<'d, T, M> { impl<'d, M: Mode> SetConfig for UartTx<'d, M> {
type Config = Config; type Config = Config;
type ConfigError = ConfigError; type ConfigError = ConfigError;
@ -304,17 +310,20 @@ impl<'d, T: BasicInstance, M: Mode> SetConfig for UartTx<'d, T, M> {
/// store data received between calls. /// store data received between calls.
/// ///
/// Also see [this github comment](https://github.com/embassy-rs/embassy/pull/2185#issuecomment-1810047043). /// Also see [this github comment](https://github.com/embassy-rs/embassy/pull/2185#issuecomment-1810047043).
pub struct UartRx<'d, T: BasicInstance, M: Mode> { pub struct UartRx<'d, M: Mode> {
_phantom: PhantomData<(T, M)>, info: &'static Info,
state: &'static State,
kernel_clock: Hertz,
rx: Option<PeripheralRef<'d, AnyPin>>, rx: Option<PeripheralRef<'d, AnyPin>>,
rts: Option<PeripheralRef<'d, AnyPin>>, rts: Option<PeripheralRef<'d, AnyPin>>,
rx_dma: Option<ChannelAndRequest<'d>>, rx_dma: Option<ChannelAndRequest<'d>>,
detect_previous_overrun: bool, detect_previous_overrun: bool,
#[cfg(any(usart_v1, usart_v2))] #[cfg(any(usart_v1, usart_v2))]
buffered_sr: stm32_metapac::usart::regs::Sr, buffered_sr: stm32_metapac::usart::regs::Sr,
_phantom: PhantomData<M>,
} }
impl<'d, T: BasicInstance, M: Mode> SetConfig for UartRx<'d, T, M> { impl<'d, M: Mode> SetConfig for UartRx<'d, M> {
type Config = Config; type Config = Config;
type ConfigError = ConfigError; type ConfigError = ConfigError;
@ -323,9 +332,9 @@ impl<'d, T: BasicInstance, M: Mode> SetConfig for UartRx<'d, T, M> {
} }
} }
impl<'d, T: BasicInstance> UartTx<'d, T, Async> { impl<'d> UartTx<'d, Async> {
/// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power. /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power.
pub fn new( pub fn new<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
tx: impl Peripheral<P = impl TxPin<T>> + 'd, tx: impl Peripheral<P = impl TxPin<T>> + 'd,
tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
@ -341,7 +350,7 @@ impl<'d, T: BasicInstance> UartTx<'d, T, Async> {
} }
/// Create a new tx-only UART with a clear-to-send pin /// Create a new tx-only UART with a clear-to-send pin
pub fn new_with_cts( pub fn new_with_cts<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
tx: impl Peripheral<P = impl TxPin<T>> + 'd, tx: impl Peripheral<P = impl TxPin<T>> + 'd,
cts: impl Peripheral<P = impl CtsPin<T>> + 'd, cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
@ -359,7 +368,7 @@ impl<'d, T: BasicInstance> UartTx<'d, T, Async> {
/// Initiate an asynchronous UART write /// Initiate an asynchronous UART write
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
let r = T::regs(); let r = self.info.regs;
// Disable Receiver for Half-Duplex mode // Disable Receiver for Half-Duplex mode
if r.cr3().read().hdsel() { if r.cr3().read().hdsel() {
@ -377,21 +386,17 @@ impl<'d, T: BasicInstance> UartTx<'d, T, Async> {
Ok(()) Ok(())
} }
async fn flush_inner() -> Result<(), Error> {
Self::blocking_flush_inner()
}
/// Wait until transmission complete /// Wait until transmission complete
pub async fn flush(&mut self) -> Result<(), Error> { pub async fn flush(&mut self) -> Result<(), Error> {
Self::flush_inner().await self.blocking_flush()
} }
} }
impl<'d, T: BasicInstance> UartTx<'d, T, Blocking> { impl<'d> UartTx<'d, Blocking> {
/// Create a new blocking tx-only UART with no hardware flow control. /// Create a new blocking tx-only UART with no hardware flow control.
/// ///
/// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power. /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power.
pub fn new_blocking( pub fn new_blocking<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
tx: impl Peripheral<P = impl TxPin<T>> + 'd, tx: impl Peripheral<P = impl TxPin<T>> + 'd,
config: Config, config: Config,
@ -400,7 +405,7 @@ impl<'d, T: BasicInstance> UartTx<'d, T, Blocking> {
} }
/// Create a new blocking tx-only UART with a clear-to-send pin /// Create a new blocking tx-only UART with a clear-to-send pin
pub fn new_blocking_with_cts( pub fn new_blocking_with_cts<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
tx: impl Peripheral<P = impl TxPin<T>> + 'd, tx: impl Peripheral<P = impl TxPin<T>> + 'd,
cts: impl Peripheral<P = impl CtsPin<T>> + 'd, cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
@ -416,8 +421,8 @@ impl<'d, T: BasicInstance> UartTx<'d, T, Blocking> {
} }
} }
impl<'d, T: BasicInstance, M: Mode> UartTx<'d, T, M> { impl<'d, M: Mode> UartTx<'d, M> {
fn new_inner( fn new_inner<T: Instance>(
_peri: impl Peripheral<P = T> + 'd, _peri: impl Peripheral<P = T> + 'd,
tx: Option<PeripheralRef<'d, AnyPin>>, tx: Option<PeripheralRef<'d, AnyPin>>,
cts: Option<PeripheralRef<'d, AnyPin>>, cts: Option<PeripheralRef<'d, AnyPin>>,
@ -426,16 +431,21 @@ impl<'d, T: BasicInstance, M: Mode> UartTx<'d, T, M> {
) -> Result<Self, ConfigError> { ) -> Result<Self, ConfigError> {
T::enable_and_reset(); T::enable_and_reset();
let r = T::regs(); let info = T::info();
let state = T::state();
let kernel_clock = T::frequency();
let r = info.regs;
r.cr3().modify(|w| { r.cr3().modify(|w| {
w.set_ctse(cts.is_some()); w.set_ctse(cts.is_some());
}); });
configure(r, &config, T::frequency(), T::KIND, false, true)?; configure(info, kernel_clock, &config, false, true)?;
// create state once! state.tx_rx_refcount.store(1, Ordering::Relaxed);
let _s = T::state();
Ok(Self { Ok(Self {
info,
state,
kernel_clock,
tx, tx,
cts, cts,
de: None, de: None,
@ -446,12 +456,12 @@ impl<'d, T: BasicInstance, M: Mode> UartTx<'d, T, M> {
/// Reconfigure the driver /// Reconfigure the driver
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
reconfigure::<T>(config) reconfigure(self.info, self.kernel_clock, config)
} }
/// Perform a blocking UART write /// Perform a blocking UART write
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
let r = T::regs(); let r = self.info.regs;
// Disable Receiver for Half-Duplex mode // Disable Receiver for Half-Duplex mode
if r.cr3().read().hdsel() { if r.cr3().read().hdsel() {
@ -465,28 +475,29 @@ impl<'d, T: BasicInstance, M: Mode> UartTx<'d, T, M> {
Ok(()) Ok(())
} }
fn blocking_flush_inner() -> Result<(), Error> {
let r = T::regs();
while !sr(r).read().tc() {}
// Enable Receiver after transmission complete for Half-Duplex mode
if r.cr3().read().hdsel() {
r.cr1().modify(|reg| reg.set_re(true));
}
Ok(())
}
/// Block until transmission complete /// Block until transmission complete
pub fn blocking_flush(&mut self) -> Result<(), Error> { pub fn blocking_flush(&mut self) -> Result<(), Error> {
Self::blocking_flush_inner() blocking_flush(self.info)
} }
} }
impl<'d, T: BasicInstance> UartRx<'d, T, Async> { fn blocking_flush(info: &Info) -> Result<(), Error> {
let r = info.regs;
while !sr(r).read().tc() {}
// Enable Receiver after transmission complete for Half-Duplex mode
if r.cr3().read().hdsel() {
r.cr1().modify(|reg| reg.set_re(true));
}
Ok(())
}
impl<'d> UartRx<'d, Async> {
/// Create a new rx-only UART with no hardware flow control. /// Create a new rx-only UART with no hardware flow control.
/// ///
/// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power. /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power.
pub fn new( pub fn new<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
@ -497,7 +508,7 @@ impl<'d, T: BasicInstance> UartRx<'d, T, Async> {
} }
/// Create a new rx-only UART with a request-to-send pin /// Create a new rx-only UART with a request-to-send pin
pub fn new_with_rts( pub fn new_with_rts<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
@ -531,11 +542,11 @@ impl<'d, T: BasicInstance> UartRx<'d, T, Async> {
buffer: &mut [u8], buffer: &mut [u8],
enable_idle_line_detection: bool, enable_idle_line_detection: bool,
) -> Result<ReadCompletionEvent, Error> { ) -> Result<ReadCompletionEvent, Error> {
let r = T::regs(); let r = self.info.regs;
// Call flush for Half-Duplex mode. It prevents reading of bytes which have just been written. // Call flush for Half-Duplex mode. It prevents reading of bytes which have just been written.
if r.cr3().read().hdsel() { if r.cr3().read().hdsel() {
UartTx::<'d, T, Async>::flush_inner().await?; blocking_flush(self.info)?;
} }
// make sure USART state is restored to neutral state when this future is dropped // make sure USART state is restored to neutral state when this future is dropped
@ -565,7 +576,7 @@ impl<'d, T: BasicInstance> UartRx<'d, T, Async> {
// Start USART DMA // Start USART DMA
// will not do anything yet because DMAR is not yet set // will not do anything yet because DMAR is not yet set
// future which will complete when DMA Read request completes // future which will complete when DMA Read request completes
let transfer = unsafe { ch.read(rdr(T::regs()), buffer, Default::default()) }; let transfer = unsafe { ch.read(rdr(r), buffer, Default::default()) };
// clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer // clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer
if !self.detect_previous_overrun { if !self.detect_previous_overrun {
@ -640,9 +651,8 @@ impl<'d, T: BasicInstance> UartRx<'d, T, Async> {
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
// future which completes when idle line or error is detected // future which completes when idle line or error is detected
let s = self.state;
let abort = poll_fn(move |cx| { let abort = poll_fn(move |cx| {
let s = T::state();
s.rx_waker.register(cx.waker()); s.rx_waker.register(cx.waker());
let sr = sr(r).read(); let sr = sr(r).read();
@ -728,11 +738,11 @@ impl<'d, T: BasicInstance> UartRx<'d, T, Async> {
} }
} }
impl<'d, T: BasicInstance> UartRx<'d, T, Blocking> { impl<'d> UartRx<'d, Blocking> {
/// Create a new rx-only UART with no hardware flow control. /// Create a new rx-only UART with no hardware flow control.
/// ///
/// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power. /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power.
pub fn new_blocking( pub fn new_blocking<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
config: Config, config: Config,
@ -741,7 +751,7 @@ impl<'d, T: BasicInstance> UartRx<'d, T, Blocking> {
} }
/// Create a new rx-only UART with a request-to-send pin /// Create a new rx-only UART with a request-to-send pin
pub fn new_blocking_with_rts( pub fn new_blocking_with_rts<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
rts: impl Peripheral<P = impl RtsPin<T>> + 'd, rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
@ -757,8 +767,8 @@ impl<'d, T: BasicInstance> UartRx<'d, T, Blocking> {
} }
} }
impl<'d, T: BasicInstance, M: Mode> UartRx<'d, T, M> { impl<'d, M: Mode> UartRx<'d, M> {
fn new_inner( fn new_inner<T: Instance>(
_peri: impl Peripheral<P = T> + 'd, _peri: impl Peripheral<P = T> + 'd,
rx: Option<PeripheralRef<'d, AnyPin>>, rx: Option<PeripheralRef<'d, AnyPin>>,
rts: Option<PeripheralRef<'d, AnyPin>>, rts: Option<PeripheralRef<'d, AnyPin>>,
@ -767,20 +777,25 @@ impl<'d, T: BasicInstance, M: Mode> UartRx<'d, T, M> {
) -> Result<Self, ConfigError> { ) -> Result<Self, ConfigError> {
T::enable_and_reset(); T::enable_and_reset();
let r = T::regs(); let info = T::info();
let state = T::state();
let kernel_clock = T::frequency();
let r = info.regs;
r.cr3().write(|w| { r.cr3().write(|w| {
w.set_rtse(rts.is_some()); w.set_rtse(rts.is_some());
}); });
configure(r, &config, T::frequency(), T::KIND, true, false)?; configure(info, kernel_clock, &config, true, false)?;
T::Interrupt::unpend(); T::Interrupt::unpend();
unsafe { T::Interrupt::enable() }; unsafe { T::Interrupt::enable() };
// create state once! state.tx_rx_refcount.store(1, Ordering::Relaxed);
let _s = T::state();
Ok(Self { Ok(Self {
_phantom: PhantomData, _phantom: PhantomData,
info,
state,
kernel_clock,
rx, rx,
rts, rts,
rx_dma, rx_dma,
@ -792,12 +807,12 @@ impl<'d, T: BasicInstance, M: Mode> UartRx<'d, T, M> {
/// Reconfigure the driver /// Reconfigure the driver
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
reconfigure::<T>(config) reconfigure(self.info, self.kernel_clock, config)
} }
#[cfg(any(usart_v1, usart_v2))] #[cfg(any(usart_v1, usart_v2))]
fn check_rx_flags(&mut self) -> Result<bool, Error> { fn check_rx_flags(&mut self) -> Result<bool, Error> {
let r = T::regs(); let r = self.info.regs;
loop { loop {
// Handle all buffered error flags. // Handle all buffered error flags.
if self.buffered_sr.pe() { if self.buffered_sr.pe() {
@ -830,7 +845,7 @@ impl<'d, T: BasicInstance, M: Mode> UartRx<'d, T, M> {
#[cfg(any(usart_v3, usart_v4))] #[cfg(any(usart_v3, usart_v4))]
fn check_rx_flags(&mut self) -> Result<bool, Error> { fn check_rx_flags(&mut self) -> Result<bool, Error> {
let r = T::regs(); let r = self.info.regs;
let sr = r.isr().read(); let sr = r.isr().read();
if sr.pe() { if sr.pe() {
r.icr().write(|w| w.set_pe(true)); r.icr().write(|w| w.set_pe(true));
@ -850,7 +865,7 @@ impl<'d, T: BasicInstance, M: Mode> UartRx<'d, T, M> {
/// Read a single u8 if there is one available, otherwise return WouldBlock /// Read a single u8 if there is one available, otherwise return WouldBlock
pub(crate) fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> { pub(crate) fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
let r = T::regs(); let r = self.info.regs;
if self.check_rx_flags()? { if self.check_rx_flags()? {
Ok(unsafe { rdr(r).read_volatile() }) Ok(unsafe { rdr(r).read_volatile() })
} else { } else {
@ -860,11 +875,11 @@ impl<'d, T: BasicInstance, M: Mode> UartRx<'d, T, M> {
/// Perform a blocking read into `buffer` /// Perform a blocking read into `buffer`
pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
let r = T::regs(); let r = self.info.regs;
// Call flush for Half-Duplex mode. It prevents reading of bytes which have just been written. // Call flush for Half-Duplex mode. It prevents reading of bytes which have just been written.
if r.cr3().read().hdsel() { if r.cr3().read().hdsel() {
UartTx::<'d, T, M>::blocking_flush_inner()?; blocking_flush(self.info)?;
} }
for b in buffer { for b in buffer {
@ -875,26 +890,39 @@ impl<'d, T: BasicInstance, M: Mode> UartRx<'d, T, M> {
} }
} }
impl<'d, T: BasicInstance, M: Mode> Drop for UartTx<'d, T, M> { impl<'d, M: Mode> Drop for UartTx<'d, M> {
fn drop(&mut self) { fn drop(&mut self) {
self.tx.as_ref().map(|x| x.set_as_disconnected()); self.tx.as_ref().map(|x| x.set_as_disconnected());
self.cts.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()); self.de.as_ref().map(|x| x.set_as_disconnected());
T::disable(); drop_tx_rx(self.info, self.state);
} }
} }
impl<'d, T: BasicInstance, M: Mode> Drop for UartRx<'d, T, M> { impl<'d, M: Mode> Drop for UartRx<'d, M> {
fn drop(&mut self) { fn drop(&mut self) {
self.rx.as_ref().map(|x| x.set_as_disconnected()); self.rx.as_ref().map(|x| x.set_as_disconnected());
self.rts.as_ref().map(|x| x.set_as_disconnected()); self.rts.as_ref().map(|x| x.set_as_disconnected());
T::disable(); drop_tx_rx(self.info, self.state);
} }
} }
impl<'d, T: BasicInstance> Uart<'d, T, Async> { fn drop_tx_rx(info: &Info, state: &State) {
// We cannot use atomic subtraction here, because it's not supported for all targets
let is_last_drop = critical_section::with(|_| {
let refcount = state.tx_rx_refcount.load(Ordering::Relaxed);
assert!(refcount >= 1);
state.tx_rx_refcount.store(refcount - 1, Ordering::Relaxed);
refcount == 1
});
if is_last_drop {
info.enable_bit.disable();
}
}
impl<'d> Uart<'d, Async> {
/// Create a new bidirectional UART /// Create a new bidirectional UART
pub fn new( pub fn new<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
tx: impl Peripheral<P = impl TxPin<T>> + 'd, tx: impl Peripheral<P = impl TxPin<T>> + 'd,
@ -917,7 +945,7 @@ impl<'d, T: BasicInstance> Uart<'d, T, Async> {
} }
/// Create a new bidirectional UART with request-to-send and clear-to-send pins /// Create a new bidirectional UART with request-to-send and clear-to-send pins
pub fn new_with_rtscts( pub fn new_with_rtscts<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
tx: impl Peripheral<P = impl TxPin<T>> + 'd, tx: impl Peripheral<P = impl TxPin<T>> + 'd,
@ -943,7 +971,7 @@ impl<'d, T: BasicInstance> Uart<'d, T, Async> {
#[cfg(not(any(usart_v1, usart_v2)))] #[cfg(not(any(usart_v1, usart_v2)))]
/// Create a new bidirectional UART with a driver-enable pin /// Create a new bidirectional UART with a driver-enable pin
pub fn new_with_de( pub fn new_with_de<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
tx: impl Peripheral<P = impl TxPin<T>> + 'd, tx: impl Peripheral<P = impl TxPin<T>> + 'd,
@ -977,7 +1005,7 @@ impl<'d, T: BasicInstance> Uart<'d, T, Async> {
/// Apart from this, the communication protocol is similar to normal USART mode. Any conflict /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict
/// on the line must be managed by software (for instance by using a centralized arbiter). /// on the line must be managed by software (for instance by using a centralized arbiter).
#[doc(alias("HDSEL"))] #[doc(alias("HDSEL"))]
pub fn new_half_duplex( pub fn new_half_duplex<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
tx: impl Peripheral<P = impl TxPin<T>> + 'd, tx: impl Peripheral<P = impl TxPin<T>> + 'd,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
@ -1015,7 +1043,7 @@ impl<'d, T: BasicInstance> Uart<'d, T, Async> {
/// on the line must be managed by software (for instance by using a centralized arbiter). /// on the line must be managed by software (for instance by using a centralized arbiter).
#[cfg(not(any(usart_v1, usart_v2)))] #[cfg(not(any(usart_v1, usart_v2)))]
#[doc(alias("HDSEL"))] #[doc(alias("HDSEL"))]
pub fn new_half_duplex_on_rx( pub fn new_half_duplex_on_rx<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
@ -1055,9 +1083,9 @@ impl<'d, T: BasicInstance> Uart<'d, T, Async> {
} }
} }
impl<'d, T: BasicInstance> Uart<'d, T, Blocking> { impl<'d> Uart<'d, Blocking> {
/// Create a new blocking bidirectional UART. /// Create a new blocking bidirectional UART.
pub fn new_blocking( pub fn new_blocking<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
tx: impl Peripheral<P = impl TxPin<T>> + 'd, tx: impl Peripheral<P = impl TxPin<T>> + 'd,
@ -1077,7 +1105,7 @@ impl<'d, T: BasicInstance> Uart<'d, T, Blocking> {
} }
/// Create a new bidirectional UART with request-to-send and clear-to-send pins /// Create a new bidirectional UART with request-to-send and clear-to-send pins
pub fn new_blocking_with_rtscts( pub fn new_blocking_with_rtscts<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
tx: impl Peripheral<P = impl TxPin<T>> + 'd, tx: impl Peripheral<P = impl TxPin<T>> + 'd,
@ -1100,7 +1128,7 @@ impl<'d, T: BasicInstance> Uart<'d, T, Blocking> {
#[cfg(not(any(usart_v1, usart_v2)))] #[cfg(not(any(usart_v1, usart_v2)))]
/// Create a new bidirectional UART with a driver-enable pin /// Create a new bidirectional UART with a driver-enable pin
pub fn new_blocking_with_de( pub fn new_blocking_with_de<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
tx: impl Peripheral<P = impl TxPin<T>> + 'd, tx: impl Peripheral<P = impl TxPin<T>> + 'd,
@ -1131,7 +1159,7 @@ impl<'d, T: BasicInstance> Uart<'d, T, Blocking> {
/// Apart from this, the communication protocol is similar to normal USART mode. Any conflict /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict
/// on the line must be managed by software (for instance by using a centralized arbiter). /// on the line must be managed by software (for instance by using a centralized arbiter).
#[doc(alias("HDSEL"))] #[doc(alias("HDSEL"))]
pub fn new_blocking_half_duplex( pub fn new_blocking_half_duplex<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
tx: impl Peripheral<P = impl TxPin<T>> + 'd, tx: impl Peripheral<P = impl TxPin<T>> + 'd,
mut config: Config, mut config: Config,
@ -1166,7 +1194,7 @@ impl<'d, T: BasicInstance> Uart<'d, T, Blocking> {
/// on the line must be managed by software (for instance by using a centralized arbiter). /// on the line must be managed by software (for instance by using a centralized arbiter).
#[cfg(not(any(usart_v1, usart_v2)))] #[cfg(not(any(usart_v1, usart_v2)))]
#[doc(alias("HDSEL"))] #[doc(alias("HDSEL"))]
pub fn new_blocking_half_duplex_on_rx( pub fn new_blocking_half_duplex_on_rx<T: Instance>(
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
mut config: Config, mut config: Config,
@ -1188,8 +1216,8 @@ impl<'d, T: BasicInstance> Uart<'d, T, Blocking> {
} }
} }
impl<'d, T: BasicInstance, M: Mode> Uart<'d, T, M> { impl<'d, M: Mode> Uart<'d, M> {
fn new_inner( fn new_inner<T: Instance>(
_peri: impl Peripheral<P = T> + 'd, _peri: impl Peripheral<P = T> + 'd,
rx: Option<PeripheralRef<'d, AnyPin>>, rx: Option<PeripheralRef<'d, AnyPin>>,
tx: Option<PeripheralRef<'d, AnyPin>>, tx: Option<PeripheralRef<'d, AnyPin>>,
@ -1200,11 +1228,12 @@ impl<'d, T: BasicInstance, M: Mode> Uart<'d, T, M> {
rx_dma: Option<ChannelAndRequest<'d>>, rx_dma: Option<ChannelAndRequest<'d>>,
config: Config, config: Config,
) -> Result<Self, ConfigError> { ) -> Result<Self, ConfigError> {
// UartRx and UartTx have one refcount each.
T::enable_and_reset();
T::enable_and_reset(); T::enable_and_reset();
let r = T::regs(); let info = T::info();
let state = T::state();
let kernel_clock = T::frequency();
let r = info.regs;
r.cr3().write(|w| { r.cr3().write(|w| {
w.set_rtse(rts.is_some()); w.set_rtse(rts.is_some());
@ -1212,17 +1241,19 @@ impl<'d, T: BasicInstance, M: Mode> Uart<'d, T, M> {
#[cfg(not(any(usart_v1, usart_v2)))] #[cfg(not(any(usart_v1, usart_v2)))]
w.set_dem(de.is_some()); w.set_dem(de.is_some());
}); });
configure(r, &config, T::frequency(), T::KIND, true, true)?; configure(info, kernel_clock, &config, true, true)?;
T::Interrupt::unpend(); T::Interrupt::unpend();
unsafe { T::Interrupt::enable() }; unsafe { T::Interrupt::enable() };
// create state once! state.tx_rx_refcount.store(2, Ordering::Relaxed);
let _s = T::state();
Ok(Self { Ok(Self {
tx: UartTx { tx: UartTx {
_phantom: PhantomData, _phantom: PhantomData,
info,
state,
kernel_clock,
tx, tx,
cts, cts,
de, de,
@ -1230,6 +1261,9 @@ impl<'d, T: BasicInstance, M: Mode> Uart<'d, T, M> {
}, },
rx: UartRx { rx: UartRx {
_phantom: PhantomData, _phantom: PhantomData,
info,
state,
kernel_clock,
rx, rx,
rts, rts,
rx_dma, rx_dma,
@ -1263,32 +1297,34 @@ impl<'d, T: BasicInstance, M: Mode> Uart<'d, T, M> {
/// Split the Uart into a transmitter and receiver, which is /// Split the Uart into a transmitter and receiver, which is
/// particularly useful when having two tasks correlating to /// particularly useful when having two tasks correlating to
/// transmitting and receiving. /// transmitting and receiving.
pub fn split(self) -> (UartTx<'d, T, M>, UartRx<'d, T, M>) { pub fn split(self) -> (UartTx<'d, M>, UartRx<'d, M>) {
(self.tx, self.rx) (self.tx, self.rx)
} }
} }
fn reconfigure<T: BasicInstance>(config: &Config) -> Result<(), ConfigError> { fn reconfigure(info: &Info, kernel_clock: Hertz, config: &Config) -> Result<(), ConfigError> {
T::Interrupt::disable(); info.interrupt.disable();
let r = T::regs(); let r = info.regs;
let cr = r.cr1().read(); let cr = r.cr1().read();
configure(r, config, T::frequency(), T::KIND, cr.re(), cr.te())?; configure(info, kernel_clock, config, cr.re(), cr.te())?;
T::Interrupt::unpend(); info.interrupt.unpend();
unsafe { T::Interrupt::enable() }; unsafe { info.interrupt.enable() };
Ok(()) Ok(())
} }
fn configure( fn configure(
r: Regs, info: &Info,
kernel_clock: Hertz,
config: &Config, config: &Config,
pclk_freq: Hertz,
kind: Kind,
enable_rx: bool, enable_rx: bool,
enable_tx: bool, enable_tx: bool,
) -> Result<(), ConfigError> { ) -> Result<(), ConfigError> {
let r = info.regs;
let kind = info.kind;
if !enable_rx && !enable_tx { if !enable_rx && !enable_tx {
return Err(ConfigError::RxOrTxNotEnabled); return Err(ConfigError::RxOrTxNotEnabled);
} }
@ -1348,7 +1384,7 @@ fn configure(
let mut over8 = false; let mut over8 = false;
let mut found_brr = None; let mut found_brr = None;
for &(presc, _presc_val) in &DIVS { for &(presc, _presc_val) in &DIVS {
let brr = calculate_brr(config.baudrate, pclk_freq.0, presc as u32, mul); let brr = calculate_brr(config.baudrate, kernel_clock.0, presc as u32, mul);
trace!( trace!(
"USART: presc={}, div=0x{:08x} (mantissa = {}, fraction = {})", "USART: presc={}, div=0x{:08x} (mantissa = {}, fraction = {})",
presc, presc,
@ -1389,7 +1425,7 @@ fn configure(
"Using {} oversampling, desired baudrate: {}, actual baudrate: {}", "Using {} oversampling, desired baudrate: {}, actual baudrate: {}",
oversampling, oversampling,
config.baudrate, config.baudrate,
pclk_freq.0 / brr * mul kernel_clock.0 / brr * mul
); );
r.cr2().write(|w| { r.cr2().write(|w| {
@ -1458,14 +1494,14 @@ fn configure(
Ok(()) Ok(())
} }
impl<'d, T: BasicInstance, M: Mode> embedded_hal_02::serial::Read<u8> for UartRx<'d, T, M> { impl<'d, M: Mode> embedded_hal_02::serial::Read<u8> for UartRx<'d, M> {
type Error = Error; type Error = Error;
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
self.nb_read() self.nb_read()
} }
} }
impl<'d, T: BasicInstance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, T, M> { impl<'d, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, M> {
type Error = Error; type Error = Error;
fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
self.blocking_write(buffer) self.blocking_write(buffer)
@ -1475,14 +1511,14 @@ impl<'d, T: BasicInstance, M: Mode> embedded_hal_02::blocking::serial::Write<u8>
} }
} }
impl<'d, T: BasicInstance, M: Mode> embedded_hal_02::serial::Read<u8> for Uart<'d, T, M> { impl<'d, M: Mode> embedded_hal_02::serial::Read<u8> for Uart<'d, M> {
type Error = Error; type Error = Error;
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
self.nb_read() self.nb_read()
} }
} }
impl<'d, T: BasicInstance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, T, M> { impl<'d, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, M> {
type Error = Error; type Error = Error;
fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
self.blocking_write(buffer) self.blocking_write(buffer)
@ -1504,25 +1540,25 @@ impl embedded_hal_nb::serial::Error for Error {
} }
} }
impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::ErrorType for Uart<'d, T, M> { impl<'d, M: Mode> embedded_hal_nb::serial::ErrorType for Uart<'d, M> {
type Error = Error; type Error = Error;
} }
impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::ErrorType for UartTx<'d, T, M> { impl<'d, M: Mode> embedded_hal_nb::serial::ErrorType for UartTx<'d, M> {
type Error = Error; type Error = Error;
} }
impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::ErrorType for UartRx<'d, T, M> { impl<'d, M: Mode> embedded_hal_nb::serial::ErrorType for UartRx<'d, M> {
type Error = Error; type Error = Error;
} }
impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, T, M> { impl<'d, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, M> {
fn read(&mut self) -> nb::Result<u8, Self::Error> { fn read(&mut self) -> nb::Result<u8, Self::Error> {
self.nb_read() self.nb_read()
} }
} }
impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::Write for UartTx<'d, T, M> { impl<'d, M: Mode> embedded_hal_nb::serial::Write for UartTx<'d, M> {
fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
self.blocking_write(&[char]).map_err(nb::Error::Other) self.blocking_write(&[char]).map_err(nb::Error::Other)
} }
@ -1532,13 +1568,13 @@ impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::Write for UartTx<'d
} }
} }
impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::Read for Uart<'d, T, M> { impl<'d, M: Mode> embedded_hal_nb::serial::Read for Uart<'d, M> {
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
self.nb_read() self.nb_read()
} }
} }
impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::Write for Uart<'d, T, M> { impl<'d, M: Mode> embedded_hal_nb::serial::Write for Uart<'d, M> {
fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
self.blocking_write(&[char]).map_err(nb::Error::Other) self.blocking_write(&[char]).map_err(nb::Error::Other)
} }
@ -1554,24 +1590,15 @@ impl embedded_io::Error for Error {
} }
} }
impl<T, M: Mode> embedded_io::ErrorType for Uart<'_, T, M> impl<M: Mode> embedded_io::ErrorType for Uart<'_, M> {
where
T: BasicInstance,
{
type Error = Error; type Error = Error;
} }
impl<T, M: Mode> embedded_io::ErrorType for UartTx<'_, T, M> impl<M: Mode> embedded_io::ErrorType for UartTx<'_, M> {
where
T: BasicInstance,
{
type Error = Error; type Error = Error;
} }
impl<T, M: Mode> embedded_io::Write for Uart<'_, T, M> impl<M: Mode> embedded_io::Write for Uart<'_, M> {
where
T: BasicInstance,
{
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.blocking_write(buf)?; self.blocking_write(buf)?;
Ok(buf.len()) Ok(buf.len())
@ -1582,10 +1609,7 @@ where
} }
} }
impl<T, M: Mode> embedded_io::Write for UartTx<'_, T, M> impl<M: Mode> embedded_io::Write for UartTx<'_, M> {
where
T: BasicInstance,
{
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.blocking_write(buf)?; self.blocking_write(buf)?;
Ok(buf.len()) Ok(buf.len())
@ -1596,10 +1620,7 @@ where
} }
} }
impl<T> embedded_io_async::Write for Uart<'_, T, Async> impl embedded_io_async::Write for Uart<'_, Async> {
where
T: BasicInstance,
{
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.write(buf).await?; self.write(buf).await?;
Ok(buf.len()) Ok(buf.len())
@ -1610,10 +1631,7 @@ where
} }
} }
impl<T> embedded_io_async::Write for UartTx<'_, T, Async> impl embedded_io_async::Write for UartTx<'_, Async> {
where
T: BasicInstance,
{
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.write(buf).await?; self.write(buf).await?;
Ok(buf.len()) Ok(buf.len())
@ -1686,72 +1704,75 @@ enum Kind {
struct State { struct State {
rx_waker: AtomicWaker, rx_waker: AtomicWaker,
tx_rx_refcount: AtomicU8,
} }
impl State { impl State {
const fn new() -> Self { const fn new() -> Self {
Self { Self {
rx_waker: AtomicWaker::new(), rx_waker: AtomicWaker::new(),
tx_rx_refcount: AtomicU8::new(0),
} }
} }
} }
trait SealedBasicInstance: crate::rcc::RccPeripheral { struct Info {
const KIND: Kind; regs: Regs,
enable_bit: ClockEnableBit,
interrupt: Interrupt,
kind: Kind,
}
fn regs() -> Regs; #[allow(private_interfaces)]
pub(crate) trait SealedInstance: crate::rcc::RccPeripheral {
fn info() -> &'static Info;
fn state() -> &'static State; fn state() -> &'static State;
fn buffered_state() -> &'static buffered::State; fn buffered_state() -> &'static buffered::State;
} }
trait SealedFullInstance: SealedBasicInstance { /// USART peripheral instance trait.
#[allow(unused)]
fn regs_uart() -> crate::pac::usart::Usart;
}
/// Basic UART driver instance
#[allow(private_bounds)] #[allow(private_bounds)]
pub trait BasicInstance: Peripheral<P = Self> + SealedBasicInstance + 'static + Send { pub trait Instance: Peripheral<P = Self> + SealedInstance + 'static + Send {
/// Interrupt for this instance. /// Interrupt for this peripheral.
type Interrupt: interrupt::typelevel::Interrupt; type Interrupt: interrupt::typelevel::Interrupt;
} }
/// Full UART driver instance pin_trait!(RxPin, Instance);
#[allow(private_bounds)] pin_trait!(TxPin, Instance);
pub trait FullInstance: SealedFullInstance {} pin_trait!(CtsPin, Instance);
pin_trait!(RtsPin, Instance);
pin_trait!(CkPin, Instance);
pin_trait!(DePin, Instance);
pin_trait!(RxPin, BasicInstance); dma_trait!(TxDma, Instance);
pin_trait!(TxPin, BasicInstance); dma_trait!(RxDma, Instance);
pin_trait!(CtsPin, BasicInstance);
pin_trait!(RtsPin, BasicInstance);
pin_trait!(CkPin, BasicInstance);
pin_trait!(DePin, BasicInstance);
dma_trait!(TxDma, BasicInstance);
dma_trait!(RxDma, BasicInstance);
macro_rules! impl_usart { macro_rules! impl_usart {
($inst:ident, $irq:ident, $kind:expr) => { ($inst:ident, $irq:ident, $kind:expr) => {
impl SealedBasicInstance for crate::peripherals::$inst { #[allow(private_interfaces)]
const KIND: Kind = $kind; impl SealedInstance for crate::peripherals::$inst {
fn info() -> &'static Info {
fn regs() -> Regs { static INFO: Info = Info {
unsafe { Regs::from_ptr(crate::pac::$inst.as_ptr()) } regs: unsafe { Regs::from_ptr(crate::pac::$inst.as_ptr()) },
enable_bit: crate::peripherals::$inst::ENABLE_BIT,
interrupt: crate::interrupt::typelevel::$irq::IRQ,
kind: $kind,
};
&INFO
} }
fn state() -> &'static crate::usart::State { fn state() -> &'static State {
static STATE: crate::usart::State = crate::usart::State::new(); static STATE: State = State::new();
&STATE &STATE
} }
fn buffered_state() -> &'static buffered::State { fn buffered_state() -> &'static buffered::State {
static STATE: buffered::State = buffered::State::new(); static BUFFERED_STATE: buffered::State = buffered::State::new();
&STATE &BUFFERED_STATE
} }
} }
impl BasicInstance for peripherals::$inst { impl Instance for crate::peripherals::$inst {
type Interrupt = crate::interrupt::typelevel::$irq; type Interrupt = crate::interrupt::typelevel::$irq;
} }
}; };
@ -1761,16 +1782,7 @@ foreach_interrupt!(
($inst:ident, usart, LPUART, $signal_name:ident, $irq:ident) => { ($inst:ident, usart, LPUART, $signal_name:ident, $irq:ident) => {
impl_usart!($inst, $irq, Kind::Lpuart); impl_usart!($inst, $irq, Kind::Lpuart);
}; };
($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => { ($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => {
impl_usart!($inst, $irq, Kind::Uart); impl_usart!($inst, $irq, Kind::Uart);
impl SealedFullInstance for peripherals::$inst {
fn regs_uart() -> crate::pac::usart::Usart {
crate::pac::$inst
}
}
impl FullInstance for peripherals::$inst {}
}; };
); );

View File

@ -1,5 +1,4 @@
use core::future::poll_fn; use core::future::poll_fn;
use core::marker::PhantomData;
use core::mem; use core::mem;
use core::sync::atomic::{compiler_fence, Ordering}; use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll; use core::task::Poll;
@ -7,20 +6,23 @@ use core::task::Poll;
use embassy_embedded_hal::SetConfig; use embassy_embedded_hal::SetConfig;
use futures_util::future::{select, Either}; use futures_util::future::{select, Either};
use super::{clear_interrupt_flags, rdr, reconfigure, sr, BasicInstance, Config, ConfigError, Error, UartRx}; use super::{clear_interrupt_flags, rdr, reconfigure, sr, Config, ConfigError, Error, Info, State, UartRx};
use crate::dma::ReadableRingBuffer; use crate::dma::ReadableRingBuffer;
use crate::mode::Async; use crate::mode::Async;
use crate::time::Hertz;
use crate::usart::{Regs, Sr}; use crate::usart::{Regs, Sr};
/// Rx-only Ring-buffered UART Driver /// Rx-only Ring-buffered UART Driver
/// ///
/// Created with [UartRx::into_ring_buffered] /// Created with [UartRx::into_ring_buffered]
pub struct RingBufferedUartRx<'d, T: BasicInstance> { pub struct RingBufferedUartRx<'d> {
_phantom: PhantomData<T>, info: &'static Info,
state: &'static State,
kernel_clock: Hertz,
ring_buf: ReadableRingBuffer<'d, u8>, ring_buf: ReadableRingBuffer<'d, u8>,
} }
impl<'d, T: BasicInstance> SetConfig for RingBufferedUartRx<'d, T> { impl<'d> SetConfig for RingBufferedUartRx<'d> {
type Config = Config; type Config = Config;
type ConfigError = ConfigError; type ConfigError = ConfigError;
@ -29,11 +31,11 @@ impl<'d, T: BasicInstance> SetConfig for RingBufferedUartRx<'d, T> {
} }
} }
impl<'d, T: BasicInstance> UartRx<'d, T, Async> { impl<'d> UartRx<'d, Async> {
/// Turn the `UartRx` into a buffered uart which can continously receive in the background /// Turn the `UartRx` into a buffered uart which can continously receive in the background
/// without the possibility of losing bytes. The `dma_buf` is a buffer registered to the /// without the possibility of losing bytes. The `dma_buf` is a buffer registered to the
/// DMA controller, and must be large enough to prevent overflows. /// DMA controller, and must be large enough to prevent overflows.
pub fn into_ring_buffered(mut self, dma_buf: &'d mut [u8]) -> RingBufferedUartRx<'d, T> { pub fn into_ring_buffered(mut self, dma_buf: &'d mut [u8]) -> RingBufferedUartRx<'d> {
assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
let opts = Default::default(); let opts = Default::default();
@ -43,19 +45,24 @@ impl<'d, T: BasicInstance> UartRx<'d, T, Async> {
let request = rx_dma.request; let request = rx_dma.request;
let rx_dma = unsafe { rx_dma.channel.clone_unchecked() }; let rx_dma = unsafe { rx_dma.channel.clone_unchecked() };
let ring_buf = unsafe { ReadableRingBuffer::new(rx_dma, request, rdr(T::regs()), dma_buf, opts) }; let info = self.info;
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) };
// Don't disable the clock // Don't disable the clock
mem::forget(self); mem::forget(self);
RingBufferedUartRx { RingBufferedUartRx {
_phantom: PhantomData, info,
state,
kernel_clock,
ring_buf, ring_buf,
} }
} }
} }
impl<'d, T: BasicInstance> RingBufferedUartRx<'d, T> { impl<'d> RingBufferedUartRx<'d> {
/// Clear the ring buffer and start receiving in the background /// Clear the ring buffer and start receiving in the background
pub fn start(&mut self) -> Result<(), Error> { pub fn start(&mut self) -> Result<(), Error> {
// Clear the ring buffer so that it is ready to receive data // Clear the ring buffer so that it is ready to receive data
@ -74,7 +81,7 @@ impl<'d, T: BasicInstance> RingBufferedUartRx<'d, T> {
/// Reconfigure the driver /// Reconfigure the driver
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
reconfigure::<T>(config) reconfigure(self.info, self.kernel_clock, config)
} }
/// Start uart background receive /// Start uart background receive
@ -85,7 +92,7 @@ impl<'d, T: BasicInstance> RingBufferedUartRx<'d, T> {
// start the dma controller // start the dma controller
self.ring_buf.start(); self.ring_buf.start();
let r = T::regs(); let r = self.info.regs;
// clear all interrupts and DMA Rx Request // clear all interrupts and DMA Rx Request
r.cr1().modify(|w| { r.cr1().modify(|w| {
// disable RXNE interrupt // disable RXNE interrupt
@ -107,7 +114,7 @@ impl<'d, T: BasicInstance> RingBufferedUartRx<'d, T> {
fn teardown_uart(&mut self) { fn teardown_uart(&mut self) {
self.ring_buf.request_stop(); self.ring_buf.request_stop();
let r = T::regs(); let r = self.info.regs;
// clear all interrupts and DMA Rx Request // clear all interrupts and DMA Rx Request
r.cr1().modify(|w| { r.cr1().modify(|w| {
// disable RXNE interrupt // disable RXNE interrupt
@ -136,14 +143,14 @@ impl<'d, T: BasicInstance> RingBufferedUartRx<'d, T> {
/// Receive in the background is terminated if an error is returned. /// Receive in the background is terminated if an error is returned.
/// It must then manually be started again by calling `start()` or by re-calling `read()`. /// It must then manually be started again by calling `start()` or by re-calling `read()`.
pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
let r = T::regs(); let r = self.info.regs;
// Start background receive if it was not already started // Start background receive if it was not already started
if !r.cr3().read().dmar() { if !r.cr3().read().dmar() {
self.start()?; self.start()?;
} }
check_for_errors(clear_idle_flag(T::regs()))?; check_for_errors(clear_idle_flag(r))?;
loop { loop {
match self.ring_buf.read(buf) { match self.ring_buf.read(buf) {
@ -184,15 +191,15 @@ impl<'d, T: BasicInstance> RingBufferedUartRx<'d, T> {
}); });
// Future which completes when idle line is detected // Future which completes when idle line is detected
let s = self.state;
let uart = poll_fn(|cx| { let uart = poll_fn(|cx| {
let s = T::state();
s.rx_waker.register(cx.waker()); s.rx_waker.register(cx.waker());
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
// Critical section is needed so that IDLE isn't set after // Critical section is needed so that IDLE isn't set after
// our read but before we clear it. // our read but before we clear it.
let sr = critical_section::with(|_| clear_idle_flag(T::regs())); let sr = critical_section::with(|_| clear_idle_flag(self.info.regs));
check_for_errors(sr)?; check_for_errors(sr)?;
@ -211,13 +218,13 @@ impl<'d, T: BasicInstance> RingBufferedUartRx<'d, T> {
} }
} }
impl<T: BasicInstance> Drop for RingBufferedUartRx<'_, T> { impl Drop for RingBufferedUartRx<'_> {
fn drop(&mut self) { fn drop(&mut self) {
self.teardown_uart(); self.teardown_uart();
super::drop_tx_rx(self.info, self.state);
T::disable();
} }
} }
/// Return an error result if the Sr register has errors /// Return an error result if the Sr register has errors
fn check_for_errors(s: Sr) -> Result<(), Error> { fn check_for_errors(s: Sr) -> Result<(), Error> {
if s.pe() { if s.pe() {
@ -248,17 +255,11 @@ fn clear_idle_flag(r: Regs) -> Sr {
sr sr
} }
impl<T> embedded_io_async::ErrorType for RingBufferedUartRx<'_, T> impl embedded_io_async::ErrorType for RingBufferedUartRx<'_> {
where
T: BasicInstance,
{
type Error = Error; type Error = Error;
} }
impl<T> embedded_io_async::Read for RingBufferedUartRx<'_, T> impl embedded_io_async::Read for RingBufferedUartRx<'_> {
where
T: BasicInstance,
{
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
self.read(buf).await self.read(buf).await
} }

View File

@ -4,7 +4,6 @@
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::mode::Async; use embassy_stm32::mode::Async;
use embassy_stm32::peripherals::UART7;
use embassy_stm32::usart::{Config, Uart, UartRx}; use embassy_stm32::usart::{Config, Uart, UartRx};
use embassy_stm32::{bind_interrupts, peripherals, usart}; use embassy_stm32::{bind_interrupts, peripherals, usart};
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
@ -38,7 +37,7 @@ async fn main(spawner: Spawner) -> ! {
} }
#[embassy_executor::task] #[embassy_executor::task]
async fn reader(mut rx: UartRx<'static, UART7, Async>) { async fn reader(mut rx: UartRx<'static, Async>) {
let mut buf = [0; 8]; let mut buf = [0; 8];
loop { loop {
info!("reading..."); info!("reading...");

View File

@ -4,7 +4,6 @@
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::mode::Async; use embassy_stm32::mode::Async;
use embassy_stm32::peripherals::UART7;
use embassy_stm32::usart::{Config, Uart, UartRx}; use embassy_stm32::usart::{Config, Uart, UartRx};
use embassy_stm32::{bind_interrupts, peripherals, usart}; use embassy_stm32::{bind_interrupts, peripherals, usart};
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
@ -38,7 +37,7 @@ async fn main(spawner: Spawner) -> ! {
} }
#[embassy_executor::task] #[embassy_executor::task]
async fn reader(mut rx: UartRx<'static, UART7, Async>) { async fn reader(mut rx: UartRx<'static, Async>) {
let mut buf = [0; 8]; let mut buf = [0; 8];
loop { loop {
info!("reading..."); info!("reading...");

View File

@ -4,7 +4,6 @@
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::mode::Async; use embassy_stm32::mode::Async;
use embassy_stm32::peripherals::UART7;
use embassy_stm32::usart::{Config, Uart, UartRx}; use embassy_stm32::usart::{Config, Uart, UartRx};
use embassy_stm32::{bind_interrupts, peripherals, usart}; use embassy_stm32::{bind_interrupts, peripherals, usart};
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
@ -38,7 +37,7 @@ async fn main(spawner: Spawner) -> ! {
} }
#[embassy_executor::task] #[embassy_executor::task]
async fn reader(mut rx: UartRx<'static, UART7, Async>) { async fn reader(mut rx: UartRx<'static, Async>) {
let mut buf = [0; 8]; let mut buf = [0; 8];
loop { loop {
info!("reading..."); info!("reading...");

View File

@ -52,7 +52,7 @@ async fn main(spawner: Spawner) {
} }
#[embassy_executor::task] #[embassy_executor::task]
async fn transmit_task(mut tx: UartTx<'static, peris::UART, Async>) { async fn transmit_task(mut tx: UartTx<'static, Async>) {
// workaround https://github.com/embassy-rs/embassy/issues/1426 // workaround https://github.com/embassy-rs/embassy/issues/1426
Timer::after_millis(100).await; Timer::after_millis(100).await;
@ -75,7 +75,7 @@ async fn transmit_task(mut tx: UartTx<'static, peris::UART, Async>) {
} }
#[embassy_executor::task] #[embassy_executor::task]
async fn receive_task(mut rx: RingBufferedUartRx<'static, peris::UART>) { async fn receive_task(mut rx: RingBufferedUartRx<'static>) {
info!("Ready to receive..."); info!("Ready to receive...");
let mut rng = ChaCha8Rng::seed_from_u64(1337); let mut rng = ChaCha8Rng::seed_from_u64(1337);