diff options
| author | Andres Vahter <[email protected]> | 2024-01-09 14:47:30 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2024-01-20 00:15:39 +0100 |
| commit | c936d66934225db8ddd283d7da2d7a158686df71 (patch) | |
| tree | 92d3a5e08658df7b7aa788581c2c4b47cc1dbddb | |
| parent | 17d6e4eefeb9bdc9d7c3776afb815298be5b468c (diff) | |
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.
| -rw-r--r-- | embassy-stm32/src/usart/buffered.rs | 27 |
1 files changed, 9 insertions, 18 deletions
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 211091c38..52740c13e 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs | |||
| @@ -62,10 +62,9 @@ impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for Interrupt | |||
| 62 | state.rx_waker.wake(); | 62 | state.rx_waker.wake(); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | // With `usart_v4` hardware FIFO is enabled, making `state.tx_buf` insufficient | 65 | // With `usart_v4` hardware FIFO is enabled and Transmission complete (TC) |
| 66 | // to determine if all bytes are sent out. | 66 | // indicates that all bytes are pushed out from the FIFO. |
| 67 | // Transmission complete (TC) interrupt here indicates that all bytes are pushed out from the FIFO. | 67 | // For other usart variants it shows that last byte from the buffer was just sent. |
| 68 | #[cfg(usart_v4)] | ||
| 69 | if sr_val.tc() { | 68 | if sr_val.tc() { |
| 70 | r.cr1().modify(|w| { | 69 | r.cr1().modify(|w| { |
| 71 | w.set_tcie(false); | 70 | w.set_tcie(false); |
| @@ -83,17 +82,15 @@ impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for Interrupt | |||
| 83 | w.set_txeie(true); | 82 | w.set_txeie(true); |
| 84 | }); | 83 | }); |
| 85 | 84 | ||
| 86 | #[cfg(usart_v4)] | 85 | // Enable transmission complete interrupt when last byte is going to be sent out. |
| 87 | r.cr1().modify(|w| { | 86 | if buf.len() == 1 { |
| 88 | w.set_tcie(true); | 87 | r.cr1().modify(|w| { |
| 89 | }); | 88 | w.set_tcie(true); |
| 89 | }); | ||
| 90 | } | ||
| 90 | 91 | ||
| 91 | tdr(r).write_volatile(buf[0].into()); | 92 | tdr(r).write_volatile(buf[0].into()); |
| 92 | tx_reader.pop_done(1); | 93 | tx_reader.pop_done(1); |
| 93 | |||
| 94 | // Notice that in case of `usart_v4` waker is called when TC interrupt happens. | ||
| 95 | #[cfg(not(usart_v4))] | ||
| 96 | state.tx_waker.wake(); | ||
| 97 | } else { | 94 | } else { |
| 98 | // Disable interrupt until we have something to transmit again. | 95 | // Disable interrupt until we have something to transmit again. |
| 99 | r.cr1().modify(|w| { | 96 | r.cr1().modify(|w| { |
| @@ -418,16 +415,10 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> { | |||
| 418 | poll_fn(move |cx| { | 415 | poll_fn(move |cx| { |
| 419 | let state = T::buffered_state(); | 416 | let state = T::buffered_state(); |
| 420 | 417 | ||
| 421 | #[cfg(usart_v4)] | ||
| 422 | if !state.tx_done.load(Ordering::Acquire) { | 418 | if !state.tx_done.load(Ordering::Acquire) { |
| 423 | state.tx_waker.register(cx.waker()); | 419 | state.tx_waker.register(cx.waker()); |
| 424 | return Poll::Pending; | 420 | return Poll::Pending; |
| 425 | } | 421 | } |
| 426 | #[cfg(not(usart_v4))] | ||
| 427 | if !state.tx_buf.is_empty() { | ||
| 428 | state.tx_waker.register(cx.waker()); | ||
| 429 | return Poll::Pending; | ||
| 430 | } | ||
| 431 | 422 | ||
| 432 | Poll::Ready(Ok(())) | 423 | Poll::Ready(Ok(())) |
| 433 | }) | 424 | }) |
