mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-25 00:02:28 +00:00
Merge pull request #2895 from qwerty19106/fix_uart_half_fifo_flush
Fix uart::flush with FIFO at Half-Duplex mode
This commit is contained in:
commit
4b5026e197
@ -359,16 +359,32 @@ impl<'d, T: BasicInstance> UartTx<'d, T, Async> {
|
||||
|
||||
/// Initiate an asynchronous UART write
|
||||
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
|
||||
let r = T::regs();
|
||||
|
||||
// Disable Receiver for Half-Duplex mode
|
||||
if r.cr3().read().hdsel() {
|
||||
r.cr1().modify(|reg| reg.set_re(false));
|
||||
}
|
||||
|
||||
let ch = self.tx_dma.as_mut().unwrap();
|
||||
T::regs().cr3().modify(|reg| {
|
||||
r.cr3().modify(|reg| {
|
||||
reg.set_dmat(true);
|
||||
});
|
||||
// If we don't assign future to a variable, the data register pointer
|
||||
// is held across an await and makes the future non-Send.
|
||||
let transfer = unsafe { ch.write(buffer, tdr(T::regs()), Default::default()) };
|
||||
let transfer = unsafe { ch.write(buffer, tdr(r), Default::default()) };
|
||||
transfer.await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn flush_inner() -> Result<(), Error> {
|
||||
Self::blocking_flush_inner()
|
||||
}
|
||||
|
||||
/// Wait until transmission complete
|
||||
pub async fn flush(&mut self) -> Result<(), Error> {
|
||||
Self::flush_inner().await
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: BasicInstance> UartTx<'d, T, Blocking> {
|
||||
@ -436,6 +452,12 @@ impl<'d, T: BasicInstance, M: Mode> UartTx<'d, T, M> {
|
||||
/// Perform a blocking UART write
|
||||
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
|
||||
let r = T::regs();
|
||||
|
||||
// Disable Receiver for Half-Duplex mode
|
||||
if r.cr3().read().hdsel() {
|
||||
r.cr1().modify(|reg| reg.set_re(false));
|
||||
}
|
||||
|
||||
for &b in buffer {
|
||||
while !sr(r).read().txe() {}
|
||||
unsafe { tdr(r).write_volatile(b) };
|
||||
@ -443,12 +465,21 @@ impl<'d, T: BasicInstance, M: Mode> UartTx<'d, T, M> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Block until transmission complete
|
||||
pub fn blocking_flush(&mut self) -> Result<(), Error> {
|
||||
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
|
||||
pub fn blocking_flush(&mut self) -> Result<(), Error> {
|
||||
Self::blocking_flush_inner()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: BasicInstance> UartRx<'d, T, Async> {
|
||||
@ -502,6 +533,11 @@ impl<'d, T: BasicInstance> UartRx<'d, T, Async> {
|
||||
) -> Result<ReadCompletionEvent, Error> {
|
||||
let r = T::regs();
|
||||
|
||||
// Call flush for Half-Duplex mode. It prevents reading of bytes which have just been written.
|
||||
if r.cr3().read().hdsel() {
|
||||
UartTx::<'d, T, Async>::flush_inner().await?;
|
||||
}
|
||||
|
||||
// make sure USART state is restored to neutral state when this future is dropped
|
||||
let on_drop = OnDrop::new(move || {
|
||||
// defmt::trace!("Clear all USART interrupts and DMA Read Request");
|
||||
@ -825,6 +861,12 @@ impl<'d, T: BasicInstance, M: Mode> UartRx<'d, T, M> {
|
||||
/// Perform a blocking read into `buffer`
|
||||
pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
|
||||
let r = T::regs();
|
||||
|
||||
// Call flush for Half-Duplex mode. It prevents reading of bytes which have just been written.
|
||||
if r.cr3().read().hdsel() {
|
||||
UartTx::<'d, T, M>::blocking_flush_inner()?;
|
||||
}
|
||||
|
||||
for b in buffer {
|
||||
while !self.check_rx_flags()? {}
|
||||
unsafe { *b = rdr(r).read_volatile() }
|
||||
|
Loading…
Reference in New Issue
Block a user