diff options
| author | Роман Кривенков <[email protected]> | 2024-04-30 15:42:11 +0400 |
|---|---|---|
| committer | Роман Кривенков <[email protected]> | 2024-05-02 15:59:42 +0400 |
| commit | d5f0bceb7ce33c4ac761daad7aed052ae646e36a (patch) | |
| tree | 410716d88cbcc643c517ee7723f579df17bcda55 /embassy-stm32 | |
| parent | 56a7b10064b830b1be1933085a5845d0d6be5f2e (diff) | |
Clear Receiver enable flag before write in Half-Duplex mode
Diffstat (limited to 'embassy-stm32')
| -rw-r--r-- | embassy-stm32/src/usart/mod.rs | 50 |
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 | ||
| 374 | impl<'d, T: BasicInstance> UartTx<'d, T, Blocking> { | 390 | impl<'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 | ||
| 454 | impl<'d, T: BasicInstance> UartRx<'d, T, Async> { | 485 | impl<'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() } |
