aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/usart/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32/src/usart/mod.rs')
-rw-r--r--embassy-stm32/src/usart/mod.rs93
1 files changed, 85 insertions, 8 deletions
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index ff211e0c9..d2c361c61 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -4,15 +4,16 @@
4 4
5use core::future::poll_fn; 5use core::future::poll_fn;
6use core::marker::PhantomData; 6use core::marker::PhantomData;
7use core::sync::atomic::{compiler_fence, AtomicU8, Ordering}; 7use core::sync::atomic::{AtomicU8, AtomicUsize, Ordering, compiler_fence};
8use core::task::Poll; 8use core::task::Poll;
9 9
10use embassy_embedded_hal::SetConfig; 10use embassy_embedded_hal::SetConfig;
11use embassy_hal_internal::drop::OnDrop;
12use embassy_hal_internal::PeripheralType; 11use embassy_hal_internal::PeripheralType;
12use embassy_hal_internal::drop::OnDrop;
13use embassy_sync::waitqueue::AtomicWaker; 13use embassy_sync::waitqueue::AtomicWaker;
14use futures_util::future::{select, Either}; 14use futures_util::future::{Either, select};
15 15
16use crate::Peri;
16use crate::dma::ChannelAndRequest; 17use crate::dma::ChannelAndRequest;
17use crate::gpio::{AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed}; 18use crate::gpio::{AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed};
18use crate::interrupt::typelevel::Interrupt as _; 19use crate::interrupt::typelevel::Interrupt as _;
@@ -25,7 +26,6 @@ use crate::pac::usart::Usart as Regs;
25use crate::pac::usart::{regs, vals}; 26use crate::pac::usart::{regs, vals};
26use crate::rcc::{RccInfo, SealedRccPeripheral}; 27use crate::rcc::{RccInfo, SealedRccPeripheral};
27use crate::time::Hertz; 28use crate::time::Hertz;
28use crate::Peri;
29 29
30/// Interrupt handler. 30/// Interrupt handler.
31pub struct InterruptHandler<T: Instance> { 31pub struct InterruptHandler<T: Instance> {
@@ -185,6 +185,12 @@ pub enum ConfigError {
185 RxOrTxNotEnabled, 185 RxOrTxNotEnabled,
186 /// Data bits and parity combination not supported 186 /// Data bits and parity combination not supported
187 DataParityNotSupported, 187 DataParityNotSupported,
188 /// DE assertion time too high
189 #[cfg(not(any(usart_v1, usart_v2)))]
190 DeAssertionTimeTooHigh,
191 /// DE deassertion time too high
192 #[cfg(not(any(usart_v1, usart_v2)))]
193 DeDeassertionTimeTooHigh,
188} 194}
189 195
190#[non_exhaustive] 196#[non_exhaustive]
@@ -206,6 +212,21 @@ pub struct Config {
206 /// If false: the error is ignored and cleared 212 /// If false: the error is ignored and cleared
207 pub detect_previous_overrun: bool, 213 pub detect_previous_overrun: bool,
208 214
215 /// If `None` (the default) then read-like calls on `BufferedUartRx` and `RingBufferedUartRx`
216 /// typically only wake/return after line idle or after the buffer is at least half full
217 /// (for `BufferedUartRx`) or the DMA buffer is written at the half or full positions
218 /// (for `RingBufferedUartRx`), though it may also wake/return earlier in some circumstances.
219 ///
220 /// If `Some(n)` then such reads are also woken/return as soon as at least `n` words are
221 /// available in the buffer, in addition to waking/returning when the conditions described
222 /// above are met. `Some(0)` is treated as `None`. Setting this for `RingBufferedUartRx`
223 /// will trigger an interrupt for every received word to check the buffer level, which may
224 /// impact performance at high data rates.
225 ///
226 /// Has no effect on plain `Uart` or `UartRx` reads, which are specified to either
227 /// return a single word, a full buffer, or after line idle.
228 pub eager_reads: Option<usize>,
229
209 /// Set this to true if the line is considered noise free. 230 /// Set this to true if the line is considered noise free.
210 /// This will increase the receiver’s tolerance to clock deviations, 231 /// This will increase the receiver’s tolerance to clock deviations,
211 /// but will effectively disable noise detection. 232 /// but will effectively disable noise detection.
@@ -239,6 +260,14 @@ pub struct Config {
239 /// Set the pin configuration for the DE pin. 260 /// Set the pin configuration for the DE pin.
240 pub de_config: OutputConfig, 261 pub de_config: OutputConfig,
241 262
263 /// Set DE assertion time before the first start bit, 0-31 16ths of a bit period.
264 #[cfg(not(any(usart_v1, usart_v2)))]
265 pub de_assertion_time: u8,
266
267 /// Set DE deassertion time after the last stop bit, 0-31 16ths of a bit period.
268 #[cfg(not(any(usart_v1, usart_v2)))]
269 pub de_deassertion_time: u8,
270
242 // private: set by new_half_duplex, not by the user. 271 // private: set by new_half_duplex, not by the user.
243 duplex: Duplex, 272 duplex: Duplex,
244} 273}
@@ -270,6 +299,7 @@ impl Default for Config {
270 parity: Parity::ParityNone, 299 parity: Parity::ParityNone,
271 // historical behavior 300 // historical behavior
272 detect_previous_overrun: false, 301 detect_previous_overrun: false,
302 eager_reads: None,
273 #[cfg(not(usart_v1))] 303 #[cfg(not(usart_v1))]
274 assume_noise_free: false, 304 assume_noise_free: false,
275 #[cfg(any(usart_v3, usart_v4))] 305 #[cfg(any(usart_v3, usart_v4))]
@@ -283,6 +313,10 @@ impl Default for Config {
283 tx_config: OutputConfig::PushPull, 313 tx_config: OutputConfig::PushPull,
284 rts_config: OutputConfig::PushPull, 314 rts_config: OutputConfig::PushPull,
285 de_config: OutputConfig::PushPull, 315 de_config: OutputConfig::PushPull,
316 #[cfg(not(any(usart_v1, usart_v2)))]
317 de_assertion_time: 0,
318 #[cfg(not(any(usart_v1, usart_v2)))]
319 de_deassertion_time: 0,
286 duplex: Duplex::Full, 320 duplex: Duplex::Full,
287 } 321 }
288 } 322 }
@@ -457,6 +491,8 @@ impl<'d> UartTx<'d, Async> {
457 491
458 /// Initiate an asynchronous UART write 492 /// Initiate an asynchronous UART write
459 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { 493 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
494 let _scoped_block_stop = self.info.rcc.block_stop();
495
460 let r = self.info.regs; 496 let r = self.info.regs;
461 497
462 half_duplex_set_rx_tx_before_write(&r, self.duplex == Duplex::Half(HalfDuplexReadback::Readback)); 498 half_duplex_set_rx_tx_before_write(&r, self.duplex == Duplex::Half(HalfDuplexReadback::Readback));
@@ -474,6 +510,8 @@ impl<'d> UartTx<'d, Async> {
474 510
475 /// Wait until transmission complete 511 /// Wait until transmission complete
476 pub async fn flush(&mut self) -> Result<(), Error> { 512 pub async fn flush(&mut self) -> Result<(), Error> {
513 let _scoped_block_stop = self.info.rcc.block_stop();
514
477 flush(&self.info, &self.state).await 515 flush(&self.info, &self.state).await
478 } 516 }
479} 517}
@@ -535,7 +573,7 @@ impl<'d, M: Mode> UartTx<'d, M> {
535 let state = self.state; 573 let state = self.state;
536 state.tx_rx_refcount.store(1, Ordering::Relaxed); 574 state.tx_rx_refcount.store(1, Ordering::Relaxed);
537 575
538 info.rcc.enable_and_reset(); 576 info.rcc.enable_and_reset_without_stop();
539 577
540 info.regs.cr3().modify(|w| { 578 info.regs.cr3().modify(|w| {
541 w.set_ctse(self.cts.is_some()); 579 w.set_ctse(self.cts.is_some());
@@ -692,6 +730,8 @@ impl<'d> UartRx<'d, Async> {
692 730
693 /// Initiate an asynchronous UART read 731 /// Initiate an asynchronous UART read
694 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 732 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
733 let _scoped_block_stop = self.info.rcc.block_stop();
734
695 self.inner_read(buffer, false).await?; 735 self.inner_read(buffer, false).await?;
696 736
697 Ok(()) 737 Ok(())
@@ -699,6 +739,8 @@ impl<'d> UartRx<'d, Async> {
699 739
700 /// Initiate an asynchronous read with idle line detection enabled 740 /// Initiate an asynchronous read with idle line detection enabled
701 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { 741 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
742 let _scoped_block_stop = self.info.rcc.block_stop();
743
702 self.inner_read(buffer, true).await 744 self.inner_read(buffer, true).await
703 } 745 }
704 746
@@ -966,8 +1008,11 @@ impl<'d, M: Mode> UartRx<'d, M> {
966 let info = self.info; 1008 let info = self.info;
967 let state = self.state; 1009 let state = self.state;
968 state.tx_rx_refcount.store(1, Ordering::Relaxed); 1010 state.tx_rx_refcount.store(1, Ordering::Relaxed);
1011 state
1012 .eager_reads
1013 .store(config.eager_reads.unwrap_or(0), Ordering::Relaxed);
969 1014
970 info.rcc.enable_and_reset(); 1015 info.rcc.enable_and_reset_without_stop();
971 1016
972 info.regs.cr3().write(|w| { 1017 info.regs.cr3().write(|w| {
973 w.set_rtse(self.rts.is_some()); 1018 w.set_rtse(self.rts.is_some());
@@ -982,6 +1027,9 @@ impl<'d, M: Mode> UartRx<'d, M> {
982 1027
983 /// Reconfigure the driver 1028 /// Reconfigure the driver
984 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { 1029 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
1030 self.state
1031 .eager_reads
1032 .store(config.eager_reads.unwrap_or(0), Ordering::Relaxed);
985 reconfigure(self.info, self.kernel_clock, config) 1033 reconfigure(self.info, self.kernel_clock, config)
986 } 1034 }
987 1035
@@ -1103,7 +1151,7 @@ fn drop_tx_rx(info: &Info, state: &State) {
1103 refcount == 1 1151 refcount == 1
1104 }); 1152 });
1105 if is_last_drop { 1153 if is_last_drop {
1106 info.rcc.disable(); 1154 info.rcc.disable_without_stop();
1107 } 1155 }
1108} 1156}
1109 1157
@@ -1462,8 +1510,11 @@ impl<'d, M: Mode> Uart<'d, M> {
1462 let info = self.rx.info; 1510 let info = self.rx.info;
1463 let state = self.rx.state; 1511 let state = self.rx.state;
1464 state.tx_rx_refcount.store(2, Ordering::Relaxed); 1512 state.tx_rx_refcount.store(2, Ordering::Relaxed);
1513 state
1514 .eager_reads
1515 .store(config.eager_reads.unwrap_or(0), Ordering::Relaxed);
1465 1516
1466 info.rcc.enable_and_reset(); 1517 info.rcc.enable_and_reset_without_stop();
1467 1518
1468 info.regs.cr3().write(|w| { 1519 info.regs.cr3().write(|w| {
1469 w.set_rtse(self.rx.rts.is_some()); 1520 w.set_rtse(self.rx.rts.is_some());
@@ -1690,6 +1741,16 @@ fn configure(
1690 return Err(ConfigError::RxOrTxNotEnabled); 1741 return Err(ConfigError::RxOrTxNotEnabled);
1691 } 1742 }
1692 1743
1744 #[cfg(not(any(usart_v1, usart_v2)))]
1745 let dem = r.cr3().read().dem();
1746
1747 #[cfg(not(any(usart_v1, usart_v2)))]
1748 if config.de_assertion_time > 31 {
1749 return Err(ConfigError::DeAssertionTimeTooHigh);
1750 } else if config.de_deassertion_time > 31 {
1751 return Err(ConfigError::DeDeassertionTimeTooHigh);
1752 }
1753
1693 // UART must be disabled during configuration. 1754 // UART must be disabled during configuration.
1694 r.cr1().modify(|w| { 1755 r.cr1().modify(|w| {
1695 w.set_ue(false); 1756 w.set_ue(false);
@@ -1738,6 +1799,20 @@ fn configure(
1738 w.set_re(enable_rx); 1799 w.set_re(enable_rx);
1739 } 1800 }
1740 1801
1802 #[cfg(not(any(usart_v1, usart_v2)))]
1803 if dem {
1804 w.set_deat(if over8 {
1805 config.de_assertion_time / 2
1806 } else {
1807 config.de_assertion_time
1808 });
1809 w.set_dedt(if over8 {
1810 config.de_assertion_time / 2
1811 } else {
1812 config.de_assertion_time
1813 });
1814 }
1815
1741 // configure word size and parity, since the parity bit is inserted into the MSB position, 1816 // configure word size and parity, since the parity bit is inserted into the MSB position,
1742 // it increases the effective word size 1817 // it increases the effective word size
1743 match (config.parity, config.data_bits) { 1818 match (config.parity, config.data_bits) {
@@ -2022,6 +2097,7 @@ struct State {
2022 rx_waker: AtomicWaker, 2097 rx_waker: AtomicWaker,
2023 tx_waker: AtomicWaker, 2098 tx_waker: AtomicWaker,
2024 tx_rx_refcount: AtomicU8, 2099 tx_rx_refcount: AtomicU8,
2100 eager_reads: AtomicUsize,
2025} 2101}
2026 2102
2027impl State { 2103impl State {
@@ -2030,6 +2106,7 @@ impl State {
2030 rx_waker: AtomicWaker::new(), 2106 rx_waker: AtomicWaker::new(),
2031 tx_waker: AtomicWaker::new(), 2107 tx_waker: AtomicWaker::new(),
2032 tx_rx_refcount: AtomicU8::new(0), 2108 tx_rx_refcount: AtomicU8::new(0),
2109 eager_reads: AtomicUsize::new(0),
2033 } 2110 }
2034 } 2111 }
2035} 2112}