aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/usart/mod.rs69
-rw-r--r--tests/rp/.cargo/config.toml1
-rw-r--r--tests/stm32/.cargo/config.toml1
-rw-r--r--tests/stm32/src/bin/usart.rs7
-rw-r--r--tests/stm32/src/bin/usart_dma.rs17
5 files changed, 82 insertions, 13 deletions
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index 6f838cce5..333e01e36 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -69,6 +69,12 @@ unsafe fn on_interrupt(r: Regs, s: &'static State) {
69 // disable idle line detection 69 // disable idle line detection
70 w.set_idleie(false); 70 w.set_idleie(false);
71 }); 71 });
72 } else if cr1.tcie() && sr.tc() {
73 // Transmission complete detected
74 r.cr1().modify(|w| {
75 // disable Transmission complete interrupt
76 w.set_tcie(false);
77 });
72 } else if cr1.rxneie() { 78 } else if cr1.rxneie() {
73 // We cannot check the RXNE flag as it is auto-cleared by the DMA controller 79 // We cannot check the RXNE flag as it is auto-cleared by the DMA controller
74 80
@@ -420,7 +426,7 @@ impl<'d> UartTx<'d, Async> {
420 426
421 /// Wait until transmission complete 427 /// Wait until transmission complete
422 pub async fn flush(&mut self) -> Result<(), Error> { 428 pub async fn flush(&mut self) -> Result<(), Error> {
423 self.blocking_flush() 429 flush(&self.info, &self.state).await
424 } 430 }
425} 431}
426 432
@@ -531,16 +537,40 @@ impl<'d, M: Mode> UartTx<'d, M> {
531 } 537 }
532} 538}
533 539
534fn blocking_flush(info: &Info) -> Result<(), Error> { 540/// Wait until transmission complete
541async fn flush(info: &Info, state: &State) -> Result<(), Error> {
535 let r = info.regs; 542 let r = info.regs;
536 while !sr(r).read().tc() {} 543 if r.cr1().read().te() && !sr(r).read().tc() {
544 r.cr1().modify(|w| {
545 // enable Transmission Complete interrupt
546 w.set_tcie(true);
547 });
548
549 compiler_fence(Ordering::SeqCst);
537 550
538 // Disable Transmitter and enable receiver after transmission complete for Half-Duplex mode 551 // future which completes when Transmission complete is detected
539 if r.cr3().read().hdsel() { 552 let abort = poll_fn(move |cx| {
540 r.cr1().modify(|reg| { 553 state.rx_waker.register(cx.waker());
541 reg.set_te(false); 554
542 reg.set_re(true); 555 let sr = sr(r).read();
556 if sr.tc() {
557 // Transmission complete detected
558 return Poll::Ready(());
559 }
560
561 Poll::Pending
543 }); 562 });
563
564 abort.await;
565 }
566
567 Ok(())
568}
569
570fn blocking_flush(info: &Info) -> Result<(), Error> {
571 let r = info.regs;
572 if r.cr1().read().te() {
573 while !sr(r).read().tc() {}
544 } 574 }
545 575
546 Ok(()) 576 Ok(())
@@ -621,7 +651,13 @@ impl<'d> UartRx<'d, Async> {
621 // Call flush for Half-Duplex mode if some bytes were written and flush was not called. 651 // Call flush for Half-Duplex mode if some bytes were written and flush was not called.
622 // It prevents reading of bytes which have just been written. 652 // It prevents reading of bytes which have just been written.
623 if r.cr3().read().hdsel() && r.cr1().read().te() { 653 if r.cr3().read().hdsel() && r.cr1().read().te() {
624 blocking_flush(self.info)?; 654 flush(&self.info, &self.state).await?;
655
656 // Disable Transmitter and enable Receiver after flush
657 r.cr1().modify(|reg| {
658 reg.set_re(true);
659 reg.set_te(false);
660 });
625 } 661 }
626 662
627 // make sure USART state is restored to neutral state when this future is dropped 663 // make sure USART state is restored to neutral state when this future is dropped
@@ -960,6 +996,12 @@ impl<'d, M: Mode> UartRx<'d, M> {
960 // It prevents reading of bytes which have just been written. 996 // It prevents reading of bytes which have just been written.
961 if r.cr3().read().hdsel() && r.cr1().read().te() { 997 if r.cr3().read().hdsel() && r.cr1().read().te() {
962 blocking_flush(self.info)?; 998 blocking_flush(self.info)?;
999
1000 // Disable Transmitter and enable Receiver after flush
1001 r.cr1().modify(|reg| {
1002 reg.set_re(true);
1003 reg.set_te(false);
1004 });
963 } 1005 }
964 1006
965 for b in buffer { 1007 for b in buffer {
@@ -1155,6 +1197,11 @@ impl<'d> Uart<'d, Async> {
1155 self.tx.write(buffer).await 1197 self.tx.write(buffer).await
1156 } 1198 }
1157 1199
1200 /// Wait until transmission complete
1201 pub async fn flush(&mut self) -> Result<(), Error> {
1202 self.tx.flush().await
1203 }
1204
1158 /// Perform an asynchronous read into `buffer` 1205 /// Perform an asynchronous read into `buffer`
1159 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 1206 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
1160 self.rx.read(buffer).await 1207 self.rx.read(buffer).await
@@ -1733,7 +1780,7 @@ impl embedded_io_async::Write for Uart<'_, Async> {
1733 } 1780 }
1734 1781
1735 async fn flush(&mut self) -> Result<(), Self::Error> { 1782 async fn flush(&mut self) -> Result<(), Self::Error> {
1736 self.blocking_flush() 1783 self.flush().await
1737 } 1784 }
1738} 1785}
1739 1786
@@ -1744,7 +1791,7 @@ impl embedded_io_async::Write for UartTx<'_, Async> {
1744 } 1791 }
1745 1792
1746 async fn flush(&mut self) -> Result<(), Self::Error> { 1793 async fn flush(&mut self) -> Result<(), Self::Error> {
1747 self.blocking_flush() 1794 self.flush().await
1748 } 1795 }
1749} 1796}
1750 1797
diff --git a/tests/rp/.cargo/config.toml b/tests/rp/.cargo/config.toml
index de7bb0e56..4337924cc 100644
--- a/tests/rp/.cargo/config.toml
+++ b/tests/rp/.cargo/config.toml
@@ -11,7 +11,6 @@ runner = "teleprobe client run"
11rustflags = [ 11rustflags = [
12 # Code-size optimizations. 12 # Code-size optimizations.
13 #"-Z", "trap-unreachable=no", 13 #"-Z", "trap-unreachable=no",
14 "-C", "inline-threshold=5",
15 "-C", "no-vectorize-loops", 14 "-C", "no-vectorize-loops",
16] 15]
17 16
diff --git a/tests/stm32/.cargo/config.toml b/tests/stm32/.cargo/config.toml
index 8752da59b..d94342598 100644
--- a/tests/stm32/.cargo/config.toml
+++ b/tests/stm32/.cargo/config.toml
@@ -9,7 +9,6 @@ runner = "teleprobe client run"
9rustflags = [ 9rustflags = [
10 # Code-size optimizations. 10 # Code-size optimizations.
11 #"-Z", "trap-unreachable=no", 11 #"-Z", "trap-unreachable=no",
12 "-C", "inline-threshold=5",
13 "-C", "no-vectorize-loops", 12 "-C", "no-vectorize-loops",
14] 13]
15 14
diff --git a/tests/stm32/src/bin/usart.rs b/tests/stm32/src/bin/usart.rs
index 53da30fff..2f601ad0e 100644
--- a/tests/stm32/src/bin/usart.rs
+++ b/tests/stm32/src/bin/usart.rs
@@ -33,6 +33,13 @@ async fn main(_spawner: Spawner) {
33 let mut buf = [0; 2]; 33 let mut buf = [0; 2];
34 usart.blocking_read(&mut buf).unwrap(); 34 usart.blocking_read(&mut buf).unwrap();
35 assert_eq!(buf, data); 35 assert_eq!(buf, data);
36
37 // Test flush doesn't hang.
38 usart.blocking_write(&data).unwrap();
39 usart.blocking_flush().unwrap();
40
41 // Test flush doesn't hang if there's nothing to flush
42 usart.blocking_flush().unwrap();
36 } 43 }
37 44
38 // Test error handling with with an overflow error 45 // Test error handling with with an overflow error
diff --git a/tests/stm32/src/bin/usart_dma.rs b/tests/stm32/src/bin/usart_dma.rs
index 266b81809..a34498376 100644
--- a/tests/stm32/src/bin/usart_dma.rs
+++ b/tests/stm32/src/bin/usart_dma.rs
@@ -51,6 +51,23 @@ async fn main(_spawner: Spawner) {
51 assert_eq!(tx_buf, rx_buf); 51 assert_eq!(tx_buf, rx_buf);
52 } 52 }
53 53
54 // Test flush doesn't hang. Check multiple combinations of async+blocking.
55 tx.write(&tx_buf).await.unwrap();
56 tx.flush().await.unwrap();
57 tx.flush().await.unwrap();
58
59 tx.write(&tx_buf).await.unwrap();
60 tx.blocking_flush().unwrap();
61 tx.flush().await.unwrap();
62
63 tx.blocking_write(&tx_buf).unwrap();
64 tx.blocking_flush().unwrap();
65 tx.flush().await.unwrap();
66
67 tx.blocking_write(&tx_buf).unwrap();
68 tx.flush().await.unwrap();
69 tx.blocking_flush().unwrap();
70
54 info!("Test OK"); 71 info!("Test OK");
55 cortex_m::asm::bkpt(); 72 cortex_m::asm::bkpt();
56} 73}