aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/usart/mod.rs50
1 files changed, 46 insertions, 4 deletions
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index 68899bfff..a6dfbd482 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -359,16 +359,32 @@ impl<'d, T: BasicInstance> UartTx<'d, T, Async> {
359 359
360 /// Initiate an asynchronous UART write 360 /// Initiate an asynchronous UART write
361 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { 361 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
362 let r = T::regs();
363
364 // Disable Receiver for Half-Duplex mode
365 if r.cr3().read().hdsel() {
366 r.cr1().modify(|reg| reg.set_re(false));
367 }
368
362 let ch = self.tx_dma.as_mut().unwrap(); 369 let ch = self.tx_dma.as_mut().unwrap();
363 T::regs().cr3().modify(|reg| { 370 r.cr3().modify(|reg| {
364 reg.set_dmat(true); 371 reg.set_dmat(true);
365 }); 372 });
366 // If we don't assign future to a variable, the data register pointer 373 // If we don't assign future to a variable, the data register pointer
367 // is held across an await and makes the future non-Send. 374 // is held across an await and makes the future non-Send.
368 let transfer = unsafe { ch.write(buffer, tdr(T::regs()), Default::default()) }; 375 let transfer = unsafe { ch.write(buffer, tdr(r), Default::default()) };
369 transfer.await; 376 transfer.await;
370 Ok(()) 377 Ok(())
371 } 378 }
379
380 async fn flush_inner() -> Result<(), Error> {
381 Self::blocking_flush_inner()
382 }
383
384 /// Wait until transmission complete
385 pub async fn flush(&mut self) -> Result<(), Error> {
386 Self::flush_inner().await
387 }
372} 388}
373 389
374impl<'d, T: BasicInstance> UartTx<'d, T, Blocking> { 390impl<'d, T: BasicInstance> UartTx<'d, T, Blocking> {
@@ -436,6 +452,12 @@ impl<'d, T: BasicInstance, M: Mode> UartTx<'d, T, M> {
436 /// Perform a blocking UART write 452 /// Perform a blocking UART write
437 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { 453 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
438 let r = T::regs(); 454 let r = T::regs();
455
456 // Disable Receiver for Half-Duplex mode
457 if r.cr3().read().hdsel() {
458 r.cr1().modify(|reg| reg.set_re(false));
459 }
460
439 for &b in buffer { 461 for &b in buffer {
440 while !sr(r).read().txe() {} 462 while !sr(r).read().txe() {}
441 unsafe { tdr(r).write_volatile(b) }; 463 unsafe { tdr(r).write_volatile(b) };
@@ -443,12 +465,21 @@ impl<'d, T: BasicInstance, M: Mode> UartTx<'d, T, M> {
443 Ok(()) 465 Ok(())
444 } 466 }
445 467
446 /// Block until transmission complete 468 fn blocking_flush_inner() -> Result<(), Error> {
447 pub fn blocking_flush(&mut self) -> Result<(), Error> {
448 let r = T::regs(); 469 let r = T::regs();
449 while !sr(r).read().tc() {} 470 while !sr(r).read().tc() {}
471
472 // Enable Receiver after transmission complete for Half-Duplex mode
473 if r.cr3().read().hdsel() {
474 r.cr1().modify(|reg| reg.set_re(true));
475 }
450 Ok(()) 476 Ok(())
451 } 477 }
478
479 /// Block until transmission complete
480 pub fn blocking_flush(&mut self) -> Result<(), Error> {
481 Self::blocking_flush_inner()
482 }
452} 483}
453 484
454impl<'d, T: BasicInstance> UartRx<'d, T, Async> { 485impl<'d, T: BasicInstance> UartRx<'d, T, Async> {
@@ -502,6 +533,11 @@ impl<'d, T: BasicInstance> UartRx<'d, T, Async> {
502 ) -> Result<ReadCompletionEvent, Error> { 533 ) -> Result<ReadCompletionEvent, Error> {
503 let r = T::regs(); 534 let r = T::regs();
504 535
536 // Call flush for Half-Duplex mode. It prevents reading of bytes which have just been written.
537 if r.cr3().read().hdsel() {
538 UartTx::<'d, T, Async>::flush_inner().await?;
539 }
540
505 // make sure USART state is restored to neutral state when this future is dropped 541 // make sure USART state is restored to neutral state when this future is dropped
506 let on_drop = OnDrop::new(move || { 542 let on_drop = OnDrop::new(move || {
507 // defmt::trace!("Clear all USART interrupts and DMA Read Request"); 543 // defmt::trace!("Clear all USART interrupts and DMA Read Request");
@@ -825,6 +861,12 @@ impl<'d, T: BasicInstance, M: Mode> UartRx<'d, T, M> {
825 /// Perform a blocking read into `buffer` 861 /// Perform a blocking read into `buffer`
826 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 862 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
827 let r = T::regs(); 863 let r = T::regs();
864
865 // Call flush for Half-Duplex mode. It prevents reading of bytes which have just been written.
866 if r.cr3().read().hdsel() {
867 UartTx::<'d, T, M>::blocking_flush_inner()?;
868 }
869
828 for b in buffer { 870 for b in buffer {
829 while !self.check_rx_flags()? {} 871 while !self.check_rx_flags()? {}
830 unsafe { *b = rdr(r).read_volatile() } 872 unsafe { *b = rdr(r).read_volatile() }