stm32 uart: fix flush
for non usart_v4 variants
Byte was written to TDR and right after that waker was called. This means `flush` would see that `tx_buf` is empty and can return Ready although actually hardware was still writing this last byte to the wire. With this change non `usart_v4 ` variants would also use TC interrupt to check when last byte was sent out.
This commit is contained in:
parent
17d6e4eefe
commit
c936d66934
1 changed files with 9 additions and 18 deletions
|
@ -62,10 +62,9 @@ impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for Interrupt
|
|||
state.rx_waker.wake();
|
||||
}
|
||||
|
||||
// With `usart_v4` hardware FIFO is enabled, making `state.tx_buf` insufficient
|
||||
// to determine if all bytes are sent out.
|
||||
// Transmission complete (TC) interrupt here indicates that all bytes are pushed out from the FIFO.
|
||||
#[cfg(usart_v4)]
|
||||
// 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() {
|
||||
r.cr1().modify(|w| {
|
||||
w.set_tcie(false);
|
||||
|
@ -83,17 +82,15 @@ impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for Interrupt
|
|||
w.set_txeie(true);
|
||||
});
|
||||
|
||||
#[cfg(usart_v4)]
|
||||
r.cr1().modify(|w| {
|
||||
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);
|
||||
|
||||
// Notice that in case of `usart_v4` waker is called when TC interrupt happens.
|
||||
#[cfg(not(usart_v4))]
|
||||
state.tx_waker.wake();
|
||||
} else {
|
||||
// Disable interrupt until we have something to transmit again.
|
||||
r.cr1().modify(|w| {
|
||||
|
@ -418,16 +415,10 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> {
|
|||
poll_fn(move |cx| {
|
||||
let state = T::buffered_state();
|
||||
|
||||
#[cfg(usart_v4)]
|
||||
if !state.tx_done.load(Ordering::Acquire) {
|
||||
state.tx_waker.register(cx.waker());
|
||||
return Poll::Pending;
|
||||
}
|
||||
#[cfg(not(usart_v4))]
|
||||
if !state.tx_buf.is_empty() {
|
||||
state.tx_waker.register(cx.waker());
|
||||
return Poll::Pending;
|
||||
}
|
||||
|
||||
Poll::Ready(Ok(()))
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue