aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndres Vahter <[email protected]>2024-01-09 14:47:30 +0200
committerDario Nieuwenhuis <[email protected]>2024-01-20 00:15:39 +0100
commitc936d66934225db8ddd283d7da2d7a158686df71 (patch)
tree92d3a5e08658df7b7aa788581c2c4b47cc1dbddb
parent17d6e4eefeb9bdc9d7c3776afb815298be5b468c (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.rs27
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 })