1 | //! Universal Synchronous/Asynchronous Receiver Transmitter (USART, UART, LPUART) |
2 | #![macro_use ] |
3 | #![warn (missing_docs)] |
4 | |
5 | use core::future::poll_fn; |
6 | use core::marker::PhantomData; |
7 | use core::sync::atomic::{compiler_fence, AtomicU8, Ordering}; |
8 | use core::task::Poll; |
9 | |
10 | use embassy_embedded_hal::SetConfig; |
11 | use embassy_hal_internal::drop::OnDrop; |
12 | use embassy_hal_internal::PeripheralRef; |
13 | use embassy_sync::waitqueue::AtomicWaker; |
14 | use futures_util::future::{select, Either}; |
15 | |
16 | use crate::dma::ChannelAndRequest; |
17 | use crate::gpio::{self, AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed}; |
18 | use crate::interrupt::typelevel::Interrupt as _; |
19 | use crate::interrupt::{self, Interrupt, InterruptExt}; |
20 | use crate::mode::{Async, Blocking, Mode}; |
21 | #[allow (unused_imports)] |
22 | #[cfg (not(any(usart_v1, usart_v2)))] |
23 | use crate::pac::usart::regs::Isr as Sr; |
24 | #[cfg (any(usart_v1, usart_v2))] |
25 | use crate::pac::usart::regs::Sr; |
26 | #[cfg (not(any(usart_v1, usart_v2)))] |
27 | use crate::pac::usart::Lpuart as Regs; |
28 | #[cfg (any(usart_v1, usart_v2))] |
29 | use crate::pac::usart::Usart as Regs; |
30 | use crate::pac::usart::{regs, vals}; |
31 | use crate::rcc::{RccInfo, SealedRccPeripheral}; |
32 | use crate::time::Hertz; |
33 | use crate::Peripheral; |
34 | |
35 | /// Interrupt handler. |
36 | pub struct InterruptHandler<T: Instance> { |
37 | _phantom: PhantomData<T>, |
38 | } |
39 | |
40 | impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { |
41 | unsafe fn on_interrupt() { |
42 | on_interrupt(T::info().regs, T::state()) |
43 | } |
44 | } |
45 | |
46 | unsafe fn on_interrupt(r: Regs, s: &'static State) { |
47 | let (sr, cr1, cr3) = (sr(r).read(), r.cr1().read(), r.cr3().read()); |
48 | |
49 | let has_errors = (sr.pe() && cr1.peie()) || ((sr.fe() || sr.ne() || sr.ore()) && cr3.eie()); |
50 | if has_errors { |
51 | // clear all interrupts and DMA Rx Request |
52 | r.cr1().modify(|w| { |
53 | // disable RXNE interrupt |
54 | w.set_rxneie(false); |
55 | // disable parity interrupt |
56 | w.set_peie(false); |
57 | // disable idle line interrupt |
58 | w.set_idleie(false); |
59 | }); |
60 | r.cr3().modify(|w| { |
61 | // disable Error Interrupt: (Frame error, Noise error, Overrun error) |
62 | w.set_eie(false); |
63 | // disable DMA Rx Request |
64 | w.set_dmar(false); |
65 | }); |
66 | } else if cr1.idleie() && sr.idle() { |
67 | // IDLE detected: no more data will come |
68 | r.cr1().modify(|w| { |
69 | // disable idle line detection |
70 | w.set_idleie(false); |
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 | }); |
78 | } else if cr1.rxneie() { |
79 | // We cannot check the RXNE flag as it is auto-cleared by the DMA controller |
80 | |
81 | // It is up to the listener to determine if this in fact was a RX event and disable the RXNE detection |
82 | } else { |
83 | return; |
84 | } |
85 | |
86 | compiler_fence(Ordering::SeqCst); |
87 | s.rx_waker.wake(); |
88 | } |
89 | |
90 | #[derive (Clone, Copy, PartialEq, Eq, Debug)] |
91 | #[cfg_attr (feature = "defmt" , derive(defmt::Format))] |
92 | /// Number of data bits |
93 | pub enum DataBits { |
94 | /// 7 Data Bits |
95 | DataBits7, |
96 | /// 8 Data Bits |
97 | DataBits8, |
98 | /// 9 Data Bits |
99 | DataBits9, |
100 | } |
101 | |
102 | #[derive (Clone, Copy, PartialEq, Eq, Debug)] |
103 | #[cfg_attr (feature = "defmt" , derive(defmt::Format))] |
104 | /// Parity |
105 | pub enum Parity { |
106 | /// No parity |
107 | ParityNone, |
108 | /// Even Parity |
109 | ParityEven, |
110 | /// Odd Parity |
111 | ParityOdd, |
112 | } |
113 | |
114 | #[derive (Clone, Copy, PartialEq, Eq, Debug)] |
115 | #[cfg_attr (feature = "defmt" , derive(defmt::Format))] |
116 | /// Number of stop bits |
117 | pub enum StopBits { |
118 | #[doc = "1 stop bit" ] |
119 | STOP1, |
120 | #[doc = "0.5 stop bits" ] |
121 | STOP0P5, |
122 | #[doc = "2 stop bits" ] |
123 | STOP2, |
124 | #[doc = "1.5 stop bits" ] |
125 | STOP1P5, |
126 | } |
127 | |
128 | #[derive (Clone, Copy, PartialEq, Eq, Debug)] |
129 | #[cfg_attr (feature = "defmt" , derive(defmt::Format))] |
130 | /// Enables or disables receiver so written data are read back in half-duplex mode |
131 | pub enum HalfDuplexReadback { |
132 | /// Disables receiver so written data are not read back |
133 | NoReadback, |
134 | /// Enables receiver so written data are read back |
135 | Readback, |
136 | } |
137 | |
138 | #[derive (Clone, Copy, PartialEq, Eq, Debug)] |
139 | #[cfg_attr (feature = "defmt" , derive(defmt::Format))] |
140 | /// Duplex mode |
141 | pub enum Duplex { |
142 | /// Full duplex |
143 | Full, |
144 | /// Half duplex with possibility to read back written data |
145 | Half(HalfDuplexReadback), |
146 | } |
147 | |
148 | impl Duplex { |
149 | /// Returns true if half-duplex |
150 | fn is_half(&self) -> bool { |
151 | matches!(self, Duplex::Half(_)) |
152 | } |
153 | } |
154 | |
155 | #[non_exhaustive ] |
156 | #[derive (Clone, Copy, PartialEq, Eq, Debug)] |
157 | #[cfg_attr (feature = "defmt" , derive(defmt::Format))] |
158 | /// Config Error |
159 | pub enum ConfigError { |
160 | /// Baudrate too low |
161 | BaudrateTooLow, |
162 | /// Baudrate too high |
163 | BaudrateTooHigh, |
164 | /// Rx or Tx not enabled |
165 | RxOrTxNotEnabled, |
166 | /// Data bits and parity combination not supported |
167 | DataParityNotSupported, |
168 | } |
169 | |
170 | #[non_exhaustive ] |
171 | #[derive (Clone, Copy, PartialEq, Eq, Debug)] |
172 | /// Config |
173 | pub struct Config { |
174 | /// Baud rate |
175 | pub baudrate: u32, |
176 | /// Number of data bits |
177 | pub data_bits: DataBits, |
178 | /// Number of stop bits |
179 | pub stop_bits: StopBits, |
180 | /// Parity type |
181 | pub parity: Parity, |
182 | |
183 | /// If true: on a read-like method, if there is a latent error pending, |
184 | /// the read will abort and the error will be reported and cleared |
185 | /// |
186 | /// If false: the error is ignored and cleared |
187 | pub detect_previous_overrun: bool, |
188 | |
189 | /// Set this to true if the line is considered noise free. |
190 | /// This will increase the receiver’s tolerance to clock deviations, |
191 | /// but will effectively disable noise detection. |
192 | #[cfg (not(usart_v1))] |
193 | pub assume_noise_free: bool, |
194 | |
195 | /// Set this to true to swap the RX and TX pins. |
196 | #[cfg (any(usart_v3, usart_v4))] |
197 | pub swap_rx_tx: bool, |
198 | |
199 | /// Set this to true to invert TX pin signal values (V<sub>DD</sub> = 0/mark, Gnd = 1/idle). |
200 | #[cfg (any(usart_v3, usart_v4))] |
201 | pub invert_tx: bool, |
202 | |
203 | /// Set this to true to invert RX pin signal values (V<sub>DD</sub> = 0/mark, Gnd = 1/idle). |
204 | #[cfg (any(usart_v3, usart_v4))] |
205 | pub invert_rx: bool, |
206 | |
207 | /// Set the pull configuration for the RX pin. |
208 | pub rx_pull: Pull, |
209 | |
210 | // private: set by new_half_duplex, not by the user. |
211 | duplex: Duplex, |
212 | } |
213 | |
214 | impl Config { |
215 | fn tx_af(&self) -> AfType { |
216 | #[cfg (any(usart_v3, usart_v4))] |
217 | if self.swap_rx_tx { |
218 | return AfType::input(self.rx_pull); |
219 | }; |
220 | AfType::output(OutputType::PushPull, Speed::Medium) |
221 | } |
222 | |
223 | fn rx_af(&self) -> AfType { |
224 | #[cfg (any(usart_v3, usart_v4))] |
225 | if self.swap_rx_tx { |
226 | return AfType::output(OutputType::PushPull, Speed::Medium); |
227 | }; |
228 | AfType::input(self.rx_pull) |
229 | } |
230 | } |
231 | |
232 | impl Default for Config { |
233 | fn default() -> Self { |
234 | Self { |
235 | baudrate: 115200, |
236 | data_bits: DataBits::DataBits8, |
237 | stop_bits: StopBits::STOP1, |
238 | parity: Parity::ParityNone, |
239 | // historical behavior |
240 | detect_previous_overrun: false, |
241 | #[cfg (not(usart_v1))] |
242 | assume_noise_free: false, |
243 | #[cfg (any(usart_v3, usart_v4))] |
244 | swap_rx_tx: false, |
245 | #[cfg (any(usart_v3, usart_v4))] |
246 | invert_tx: false, |
247 | #[cfg (any(usart_v3, usart_v4))] |
248 | invert_rx: false, |
249 | rx_pull: Pull::None, |
250 | duplex: Duplex::Full, |
251 | } |
252 | } |
253 | } |
254 | |
255 | #[derive (Clone, Copy, PartialEq, Eq, Debug)] |
256 | #[cfg_attr (feature = "defmt" , derive(defmt::Format))] |
257 | /// Half duplex IO mode |
258 | pub enum HalfDuplexConfig { |
259 | /// Push pull allows for faster baudrates, may require series resistor |
260 | PushPull, |
261 | /// Open drain output using external pull up resistor |
262 | OpenDrainExternal, |
263 | #[cfg (not(gpio_v1))] |
264 | /// Open drain output using internal pull up resistor |
265 | OpenDrainInternal, |
266 | } |
267 | |
268 | impl HalfDuplexConfig { |
269 | fn af_type(self) -> gpio::AfType { |
270 | match self { |
271 | HalfDuplexConfig::PushPull => AfType::output(OutputType::PushPull, Speed::Medium), |
272 | HalfDuplexConfig::OpenDrainExternal => AfType::output(OutputType::OpenDrain, Speed::Medium), |
273 | #[cfg (not(gpio_v1))] |
274 | HalfDuplexConfig::OpenDrainInternal => AfType::output_pull(OutputType::OpenDrain, Speed::Medium, Pull::Up), |
275 | } |
276 | } |
277 | } |
278 | |
279 | /// Serial error |
280 | #[derive (Debug, Eq, PartialEq, Copy, Clone)] |
281 | #[cfg_attr (feature = "defmt" , derive(defmt::Format))] |
282 | #[non_exhaustive ] |
283 | pub enum Error { |
284 | /// Framing error |
285 | Framing, |
286 | /// Noise error |
287 | Noise, |
288 | /// RX buffer overrun |
289 | Overrun, |
290 | /// Parity check error |
291 | Parity, |
292 | /// Buffer too large for DMA |
293 | BufferTooLong, |
294 | } |
295 | |
296 | enum ReadCompletionEvent { |
297 | // DMA Read transfer completed first |
298 | DmaCompleted, |
299 | // Idle line detected first |
300 | Idle(usize), |
301 | } |
302 | |
303 | /// Bidirectional UART Driver, which acts as a combination of [`UartTx`] and [`UartRx`]. |
304 | /// |
305 | /// ### Notes on [`embedded_io::Read`] |
306 | /// |
307 | /// `embedded_io::Read` requires guarantees that the base [`UartRx`] cannot provide. |
308 | /// |
309 | /// See [`UartRx`] for more details, and see [`BufferedUart`] and [`RingBufferedUartRx`] |
310 | /// as alternatives that do provide the necessary guarantees for `embedded_io::Read`. |
311 | pub struct Uart<'d, M: Mode> { |
312 | tx: UartTx<'d, M>, |
313 | rx: UartRx<'d, M>, |
314 | } |
315 | |
316 | impl<'d, M: Mode> SetConfig for Uart<'d, M> { |
317 | type Config = Config; |
318 | type ConfigError = ConfigError; |
319 | |
320 | fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> { |
321 | self.tx.set_config(config)?; |
322 | self.rx.set_config(config) |
323 | } |
324 | } |
325 | |
326 | /// Tx-only UART Driver. |
327 | /// |
328 | /// Can be obtained from [`Uart::split`], or can be constructed independently, |
329 | /// if you do not need the receiving half of the driver. |
330 | pub struct UartTx<'d, M: Mode> { |
331 | info: &'static Info, |
332 | state: &'static State, |
333 | kernel_clock: Hertz, |
334 | tx: Option<PeripheralRef<'d, AnyPin>>, |
335 | cts: Option<PeripheralRef<'d, AnyPin>>, |
336 | de: Option<PeripheralRef<'d, AnyPin>>, |
337 | tx_dma: Option<ChannelAndRequest<'d>>, |
338 | duplex: Duplex, |
339 | _phantom: PhantomData<M>, |
340 | } |
341 | |
342 | impl<'d, M: Mode> SetConfig for UartTx<'d, M> { |
343 | type Config = Config; |
344 | type ConfigError = ConfigError; |
345 | |
346 | fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> { |
347 | self.set_config(config) |
348 | } |
349 | } |
350 | |
351 | /// Rx-only UART Driver. |
352 | /// |
353 | /// Can be obtained from [`Uart::split`], or can be constructed independently, |
354 | /// if you do not need the transmitting half of the driver. |
355 | /// |
356 | /// ### Notes on [`embedded_io::Read`] |
357 | /// |
358 | /// `embedded_io::Read` requires guarantees that this struct cannot provide: |
359 | /// |
360 | /// - Any data received between calls to [`UartRx::read`] or [`UartRx::blocking_read`] |
361 | /// will be thrown away, as `UartRx` is unbuffered. |
362 | /// Users of `embedded_io::Read` are likely to not expect this behavior |
363 | /// (for instance if they read multiple small chunks in a row). |
364 | /// - [`UartRx::read`] and [`UartRx::blocking_read`] only return once the entire buffer has been |
365 | /// filled, whereas `embedded_io::Read` requires us to fill the buffer with what we already |
366 | /// received, and only block/wait until the first byte arrived. |
367 | /// <br /> |
368 | /// While [`UartRx::read_until_idle`] does return early, it will still eagerly wait for data until |
369 | /// the buffer is full or no data has been transmitted in a while, |
370 | /// which may not be what users of `embedded_io::Read` expect. |
371 | /// |
372 | /// [`UartRx::into_ring_buffered`] can be called to equip `UartRx` with a buffer, |
373 | /// that it can then use to store data received between calls to `read`, |
374 | /// provided you are using DMA already. |
375 | /// |
376 | /// Alternatively, you can use [`BufferedUartRx`], which is interrupt-based and which can also |
377 | /// store data received between calls. |
378 | /// |
379 | /// Also see [this github comment](https://github.com/embassy-rs/embassy/pull/2185#issuecomment-1810047043). |
380 | pub struct UartRx<'d, M: Mode> { |
381 | info: &'static Info, |
382 | state: &'static State, |
383 | kernel_clock: Hertz, |
384 | rx: Option<PeripheralRef<'d, AnyPin>>, |
385 | rts: Option<PeripheralRef<'d, AnyPin>>, |
386 | rx_dma: Option<ChannelAndRequest<'d>>, |
387 | detect_previous_overrun: bool, |
388 | #[cfg (any(usart_v1, usart_v2))] |
389 | buffered_sr: stm32_metapac::usart::regs::Sr, |
390 | _phantom: PhantomData<M>, |
391 | } |
392 | |
393 | impl<'d, M: Mode> SetConfig for UartRx<'d, M> { |
394 | type Config = Config; |
395 | type ConfigError = ConfigError; |
396 | |
397 | fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> { |
398 | self.set_config(config) |
399 | } |
400 | } |
401 | |
402 | impl<'d> UartTx<'d, Async> { |
403 | /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power. |
404 | pub fn new<T: Instance>( |
405 | peri: impl Peripheral<P = T> + 'd, |
406 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
407 | tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, |
408 | config: Config, |
409 | ) -> Result<Self, ConfigError> { |
410 | Self::new_inner( |
411 | peri, |
412 | new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)), |
413 | None, |
414 | new_dma!(tx_dma), |
415 | config, |
416 | ) |
417 | } |
418 | |
419 | /// Create a new tx-only UART with a clear-to-send pin |
420 | pub fn new_with_cts<T: Instance>( |
421 | peri: impl Peripheral<P = T> + 'd, |
422 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
423 | cts: impl Peripheral<P = impl CtsPin<T>> + 'd, |
424 | tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, |
425 | config: Config, |
426 | ) -> Result<Self, ConfigError> { |
427 | Self::new_inner( |
428 | peri, |
429 | new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)), |
430 | new_pin!(cts, AfType::input(Pull::None)), |
431 | new_dma!(tx_dma), |
432 | config, |
433 | ) |
434 | } |
435 | |
436 | /// Initiate an asynchronous UART write |
437 | pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
438 | let r = self.info.regs; |
439 | |
440 | half_duplex_set_rx_tx_before_write(&r, self.duplex == Duplex::Half(HalfDuplexReadback::Readback)); |
441 | |
442 | let ch = self.tx_dma.as_mut().unwrap(); |
443 | r.cr3().modify(|reg| { |
444 | reg.set_dmat(true); |
445 | }); |
446 | // If we don't assign future to a variable, the data register pointer |
447 | // is held across an await and makes the future non-Send. |
448 | let transfer = unsafe { ch.write(buffer, tdr(r), Default::default()) }; |
449 | transfer.await; |
450 | Ok(()) |
451 | } |
452 | |
453 | /// Wait until transmission complete |
454 | pub async fn flush(&mut self) -> Result<(), Error> { |
455 | flush(&self.info, &self.state).await |
456 | } |
457 | } |
458 | |
459 | impl<'d> UartTx<'d, Blocking> { |
460 | /// Create a new blocking tx-only UART with no hardware flow control. |
461 | /// |
462 | /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power. |
463 | pub fn new_blocking<T: Instance>( |
464 | peri: impl Peripheral<P = T> + 'd, |
465 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
466 | config: Config, |
467 | ) -> Result<Self, ConfigError> { |
468 | Self::new_inner( |
469 | peri, |
470 | new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)), |
471 | None, |
472 | None, |
473 | config, |
474 | ) |
475 | } |
476 | |
477 | /// Create a new blocking tx-only UART with a clear-to-send pin |
478 | pub fn new_blocking_with_cts<T: Instance>( |
479 | peri: impl Peripheral<P = T> + 'd, |
480 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
481 | cts: impl Peripheral<P = impl CtsPin<T>> + 'd, |
482 | config: Config, |
483 | ) -> Result<Self, ConfigError> { |
484 | Self::new_inner( |
485 | peri, |
486 | new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)), |
487 | new_pin!(cts, AfType::input(config.rx_pull)), |
488 | None, |
489 | config, |
490 | ) |
491 | } |
492 | } |
493 | |
494 | impl<'d, M: Mode> UartTx<'d, M> { |
495 | fn new_inner<T: Instance>( |
496 | _peri: impl Peripheral<P = T> + 'd, |
497 | tx: Option<PeripheralRef<'d, AnyPin>>, |
498 | cts: Option<PeripheralRef<'d, AnyPin>>, |
499 | tx_dma: Option<ChannelAndRequest<'d>>, |
500 | config: Config, |
501 | ) -> Result<Self, ConfigError> { |
502 | let mut this = Self { |
503 | info: T::info(), |
504 | state: T::state(), |
505 | kernel_clock: T::frequency(), |
506 | tx, |
507 | cts, |
508 | de: None, |
509 | tx_dma, |
510 | duplex: config.duplex, |
511 | _phantom: PhantomData, |
512 | }; |
513 | this.enable_and_configure(&config)?; |
514 | Ok(this) |
515 | } |
516 | |
517 | fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> { |
518 | let info = self.info; |
519 | let state = self.state; |
520 | state.tx_rx_refcount.store(1, Ordering::Relaxed); |
521 | |
522 | info.rcc.enable_and_reset(); |
523 | |
524 | info.regs.cr3().modify(|w| { |
525 | w.set_ctse(self.cts.is_some()); |
526 | }); |
527 | configure(info, self.kernel_clock, config, false, true)?; |
528 | |
529 | Ok(()) |
530 | } |
531 | |
532 | /// Reconfigure the driver |
533 | pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { |
534 | reconfigure(self.info, self.kernel_clock, config) |
535 | } |
536 | |
537 | /// Perform a blocking UART write |
538 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
539 | let r = self.info.regs; |
540 | |
541 | half_duplex_set_rx_tx_before_write(&r, self.duplex == Duplex::Half(HalfDuplexReadback::Readback)); |
542 | |
543 | for &b in buffer { |
544 | while !sr(r).read().txe() {} |
545 | unsafe { tdr(r).write_volatile(b) }; |
546 | } |
547 | Ok(()) |
548 | } |
549 | |
550 | /// Block until transmission complete |
551 | pub fn blocking_flush(&mut self) -> Result<(), Error> { |
552 | blocking_flush(self.info) |
553 | } |
554 | |
555 | /// Send break character |
556 | pub fn send_break(&self) { |
557 | send_break(&self.info.regs); |
558 | } |
559 | |
560 | /// Set baudrate |
561 | pub fn set_baudrate(&self, baudrate: u32) -> Result<(), ConfigError> { |
562 | set_baudrate(self.info, self.kernel_clock, baudrate) |
563 | } |
564 | } |
565 | |
566 | /// Wait until transmission complete |
567 | async fn flush(info: &Info, state: &State) -> Result<(), Error> { |
568 | let r = info.regs; |
569 | if r.cr1().read().te() && !sr(r).read().tc() { |
570 | r.cr1().modify(|w| { |
571 | // enable Transmission Complete interrupt |
572 | w.set_tcie(true); |
573 | }); |
574 | |
575 | compiler_fence(Ordering::SeqCst); |
576 | |
577 | // future which completes when Transmission complete is detected |
578 | let abort = poll_fn(move |cx| { |
579 | state.rx_waker.register(cx.waker()); |
580 | |
581 | let sr = sr(r).read(); |
582 | if sr.tc() { |
583 | // Transmission complete detected |
584 | return Poll::Ready(()); |
585 | } |
586 | |
587 | Poll::Pending |
588 | }); |
589 | |
590 | abort.await; |
591 | } |
592 | |
593 | Ok(()) |
594 | } |
595 | |
596 | fn blocking_flush(info: &Info) -> Result<(), Error> { |
597 | let r: Lpuart = info.regs; |
598 | if r.cr1().read().te() { |
599 | while !sr(r).read().tc() {} |
600 | } |
601 | |
602 | Ok(()) |
603 | } |
604 | |
605 | /// Send break character |
606 | pub fn send_break(regs: &Regs) { |
607 | // Busy wait until previous break has been sent |
608 | #[cfg (any(usart_v1, usart_v2))] |
609 | while regs.cr1().read().sbk() {} |
610 | #[cfg (any(usart_v3, usart_v4))] |
611 | while regs.isr().read().sbkf() {} |
612 | |
613 | // Send break right after completing the current character transmission |
614 | #[cfg (any(usart_v1, usart_v2))] |
615 | regs.cr1().modify(|w| w.set_sbk(true)); |
616 | #[cfg (any(usart_v3, usart_v4))] |
617 | regs.rqr().write(|w: &mut Rqr| w.set_sbkrq(val:true)); |
618 | } |
619 | |
620 | /// Enable Transmitter and disable Receiver for Half-Duplex mode |
621 | /// In case of readback, keep Receiver enabled |
622 | fn half_duplex_set_rx_tx_before_write(r: &Regs, enable_readback: bool) { |
623 | let mut cr1: Cr1 = r.cr1().read(); |
624 | if r.cr3().read().hdsel() && !cr1.te() { |
625 | cr1.set_te(val:true); |
626 | cr1.set_re(val:enable_readback); |
627 | r.cr1().write_value(val:cr1); |
628 | } |
629 | } |
630 | |
631 | impl<'d> UartRx<'d, Async> { |
632 | /// Create a new rx-only UART with no hardware flow control. |
633 | /// |
634 | /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power. |
635 | pub fn new<T: Instance>( |
636 | peri: impl Peripheral<P = T> + 'd, |
637 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
638 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
639 | rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, |
640 | config: Config, |
641 | ) -> Result<Self, ConfigError> { |
642 | Self::new_inner( |
643 | peri, |
644 | new_pin!(rx, AfType::input(config.rx_pull)), |
645 | None, |
646 | new_dma!(rx_dma), |
647 | config, |
648 | ) |
649 | } |
650 | |
651 | /// Create a new rx-only UART with a request-to-send pin |
652 | pub fn new_with_rts<T: Instance>( |
653 | peri: impl Peripheral<P = T> + 'd, |
654 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
655 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
656 | rts: impl Peripheral<P = impl RtsPin<T>> + 'd, |
657 | rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, |
658 | config: Config, |
659 | ) -> Result<Self, ConfigError> { |
660 | Self::new_inner( |
661 | peri, |
662 | new_pin!(rx, AfType::input(config.rx_pull)), |
663 | new_pin!(rts, AfType::output(OutputType::PushPull, Speed::Medium)), |
664 | new_dma!(rx_dma), |
665 | config, |
666 | ) |
667 | } |
668 | |
669 | /// Initiate an asynchronous UART read |
670 | pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
671 | self.inner_read(buffer, false).await?; |
672 | |
673 | Ok(()) |
674 | } |
675 | |
676 | /// Initiate an asynchronous read with idle line detection enabled |
677 | pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { |
678 | self.inner_read(buffer, true).await |
679 | } |
680 | |
681 | async fn inner_read_run( |
682 | &mut self, |
683 | buffer: &mut [u8], |
684 | enable_idle_line_detection: bool, |
685 | ) -> Result<ReadCompletionEvent, Error> { |
686 | let r = self.info.regs; |
687 | |
688 | // Call flush for Half-Duplex mode if some bytes were written and flush was not called. |
689 | // It prevents reading of bytes which have just been written. |
690 | if r.cr3().read().hdsel() && r.cr1().read().te() { |
691 | flush(&self.info, &self.state).await?; |
692 | |
693 | // Disable Transmitter and enable Receiver after flush |
694 | r.cr1().modify(|reg| { |
695 | reg.set_re(true); |
696 | reg.set_te(false); |
697 | }); |
698 | } |
699 | |
700 | // make sure USART state is restored to neutral state when this future is dropped |
701 | let on_drop = OnDrop::new(move || { |
702 | // defmt::trace!("Clear all USART interrupts and DMA Read Request"); |
703 | // clear all interrupts and DMA Rx Request |
704 | r.cr1().modify(|w| { |
705 | // disable RXNE interrupt |
706 | w.set_rxneie(false); |
707 | // disable parity interrupt |
708 | w.set_peie(false); |
709 | // disable idle line interrupt |
710 | w.set_idleie(false); |
711 | }); |
712 | r.cr3().modify(|w| { |
713 | // disable Error Interrupt: (Frame error, Noise error, Overrun error) |
714 | w.set_eie(false); |
715 | // disable DMA Rx Request |
716 | w.set_dmar(false); |
717 | }); |
718 | }); |
719 | |
720 | let ch = self.rx_dma.as_mut().unwrap(); |
721 | |
722 | let buffer_len = buffer.len(); |
723 | |
724 | // Start USART DMA |
725 | // will not do anything yet because DMAR is not yet set |
726 | // future which will complete when DMA Read request completes |
727 | let transfer = unsafe { ch.read(rdr(r), buffer, Default::default()) }; |
728 | |
729 | // clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer |
730 | if !self.detect_previous_overrun { |
731 | let sr = sr(r).read(); |
732 | // This read also clears the error and idle interrupt flags on v1. |
733 | unsafe { rdr(r).read_volatile() }; |
734 | clear_interrupt_flags(r, sr); |
735 | } |
736 | |
737 | r.cr1().modify(|w| { |
738 | // disable RXNE interrupt |
739 | w.set_rxneie(false); |
740 | // enable parity interrupt if not ParityNone |
741 | w.set_peie(w.pce()); |
742 | }); |
743 | |
744 | r.cr3().modify(|w| { |
745 | // enable Error Interrupt: (Frame error, Noise error, Overrun error) |
746 | w.set_eie(true); |
747 | // enable DMA Rx Request |
748 | w.set_dmar(true); |
749 | }); |
750 | |
751 | compiler_fence(Ordering::SeqCst); |
752 | |
753 | // In case of errors already pending when reception started, interrupts may have already been raised |
754 | // and lead to reception abortion (Overrun error for instance). In such a case, all interrupts |
755 | // have been disabled in interrupt handler and DMA Rx Request has been disabled. |
756 | |
757 | let cr3 = r.cr3().read(); |
758 | |
759 | if !cr3.dmar() { |
760 | // something went wrong |
761 | // because the only way to get this flag cleared is to have an interrupt |
762 | |
763 | // DMA will be stopped when transfer is dropped |
764 | |
765 | let sr = sr(r).read(); |
766 | // This read also clears the error and idle interrupt flags on v1. |
767 | unsafe { rdr(r).read_volatile() }; |
768 | clear_interrupt_flags(r, sr); |
769 | |
770 | if sr.pe() { |
771 | return Err(Error::Parity); |
772 | } |
773 | if sr.fe() { |
774 | return Err(Error::Framing); |
775 | } |
776 | if sr.ne() { |
777 | return Err(Error::Noise); |
778 | } |
779 | if sr.ore() { |
780 | return Err(Error::Overrun); |
781 | } |
782 | |
783 | unreachable!(); |
784 | } |
785 | |
786 | if enable_idle_line_detection { |
787 | // clear idle flag |
788 | let sr = sr(r).read(); |
789 | // This read also clears the error and idle interrupt flags on v1. |
790 | unsafe { rdr(r).read_volatile() }; |
791 | clear_interrupt_flags(r, sr); |
792 | |
793 | // enable idle interrupt |
794 | r.cr1().modify(|w| { |
795 | w.set_idleie(true); |
796 | }); |
797 | } |
798 | |
799 | compiler_fence(Ordering::SeqCst); |
800 | |
801 | // future which completes when idle line or error is detected |
802 | let s = self.state; |
803 | let abort = poll_fn(move |cx| { |
804 | s.rx_waker.register(cx.waker()); |
805 | |
806 | let sr = sr(r).read(); |
807 | |
808 | // This read also clears the error and idle interrupt flags on v1. |
809 | unsafe { rdr(r).read_volatile() }; |
810 | clear_interrupt_flags(r, sr); |
811 | |
812 | if enable_idle_line_detection { |
813 | // enable idle interrupt |
814 | r.cr1().modify(|w| { |
815 | w.set_idleie(true); |
816 | }); |
817 | } |
818 | |
819 | compiler_fence(Ordering::SeqCst); |
820 | |
821 | let has_errors = sr.pe() || sr.fe() || sr.ne() || sr.ore(); |
822 | |
823 | if has_errors { |
824 | // all Rx interrupts and Rx DMA Request have already been cleared in interrupt handler |
825 | |
826 | if sr.pe() { |
827 | return Poll::Ready(Err(Error::Parity)); |
828 | } |
829 | if sr.fe() { |
830 | return Poll::Ready(Err(Error::Framing)); |
831 | } |
832 | if sr.ne() { |
833 | return Poll::Ready(Err(Error::Noise)); |
834 | } |
835 | if sr.ore() { |
836 | return Poll::Ready(Err(Error::Overrun)); |
837 | } |
838 | } |
839 | |
840 | if enable_idle_line_detection && sr.idle() { |
841 | // Idle line detected |
842 | return Poll::Ready(Ok(())); |
843 | } |
844 | |
845 | Poll::Pending |
846 | }); |
847 | |
848 | // wait for the first of DMA request or idle line detected to completes |
849 | // select consumes its arguments |
850 | // when transfer is dropped, it will stop the DMA request |
851 | let r = match select(transfer, abort).await { |
852 | // DMA transfer completed first |
853 | Either::Left(((), _)) => Ok(ReadCompletionEvent::DmaCompleted), |
854 | |
855 | // Idle line detected first |
856 | Either::Right((Ok(()), transfer)) => Ok(ReadCompletionEvent::Idle( |
857 | buffer_len - transfer.get_remaining_transfers() as usize, |
858 | )), |
859 | |
860 | // error occurred |
861 | Either::Right((Err(e), _)) => Err(e), |
862 | }; |
863 | |
864 | drop(on_drop); |
865 | |
866 | r |
867 | } |
868 | |
869 | async fn inner_read(&mut self, buffer: &mut [u8], enable_idle_line_detection: bool) -> Result<usize, Error> { |
870 | if buffer.is_empty() { |
871 | return Ok(0); |
872 | } else if buffer.len() > 0xFFFF { |
873 | return Err(Error::BufferTooLong); |
874 | } |
875 | |
876 | let buffer_len = buffer.len(); |
877 | |
878 | // wait for DMA to complete or IDLE line detection if requested |
879 | let res = self.inner_read_run(buffer, enable_idle_line_detection).await; |
880 | |
881 | match res { |
882 | Ok(ReadCompletionEvent::DmaCompleted) => Ok(buffer_len), |
883 | Ok(ReadCompletionEvent::Idle(n)) => Ok(n), |
884 | Err(e) => Err(e), |
885 | } |
886 | } |
887 | } |
888 | |
889 | impl<'d> UartRx<'d, Blocking> { |
890 | /// Create a new rx-only UART with no hardware flow control. |
891 | /// |
892 | /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power. |
893 | pub fn new_blocking<T: Instance>( |
894 | peri: impl Peripheral<P = T> + 'd, |
895 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
896 | config: Config, |
897 | ) -> Result<Self, ConfigError> { |
898 | Self::new_inner(peri, new_pin!(rx, AfType::input(config.rx_pull)), None, None, config) |
899 | } |
900 | |
901 | /// Create a new rx-only UART with a request-to-send pin |
902 | pub fn new_blocking_with_rts<T: Instance>( |
903 | peri: impl Peripheral<P = T> + 'd, |
904 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
905 | rts: impl Peripheral<P = impl RtsPin<T>> + 'd, |
906 | config: Config, |
907 | ) -> Result<Self, ConfigError> { |
908 | Self::new_inner( |
909 | peri, |
910 | new_pin!(rx, AfType::input(config.rx_pull)), |
911 | new_pin!(rts, AfType::output(OutputType::PushPull, Speed::Medium)), |
912 | None, |
913 | config, |
914 | ) |
915 | } |
916 | } |
917 | |
918 | impl<'d, M: Mode> UartRx<'d, M> { |
919 | fn new_inner<T: Instance>( |
920 | _peri: impl Peripheral<P = T> + 'd, |
921 | rx: Option<PeripheralRef<'d, AnyPin>>, |
922 | rts: Option<PeripheralRef<'d, AnyPin>>, |
923 | rx_dma: Option<ChannelAndRequest<'d>>, |
924 | config: Config, |
925 | ) -> Result<Self, ConfigError> { |
926 | let mut this = Self { |
927 | _phantom: PhantomData, |
928 | info: T::info(), |
929 | state: T::state(), |
930 | kernel_clock: T::frequency(), |
931 | rx, |
932 | rts, |
933 | rx_dma, |
934 | detect_previous_overrun: config.detect_previous_overrun, |
935 | #[cfg (any(usart_v1, usart_v2))] |
936 | buffered_sr: stm32_metapac::usart::regs::Sr(0), |
937 | }; |
938 | this.enable_and_configure(&config)?; |
939 | Ok(this) |
940 | } |
941 | |
942 | fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> { |
943 | let info = self.info; |
944 | let state = self.state; |
945 | state.tx_rx_refcount.store(1, Ordering::Relaxed); |
946 | |
947 | info.rcc.enable_and_reset(); |
948 | |
949 | info.regs.cr3().write(|w| { |
950 | w.set_rtse(self.rts.is_some()); |
951 | }); |
952 | configure(info, self.kernel_clock, &config, true, false)?; |
953 | |
954 | info.interrupt.unpend(); |
955 | unsafe { info.interrupt.enable() }; |
956 | |
957 | Ok(()) |
958 | } |
959 | |
960 | /// Reconfigure the driver |
961 | pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { |
962 | reconfigure(self.info, self.kernel_clock, config) |
963 | } |
964 | |
965 | #[cfg (any(usart_v1, usart_v2))] |
966 | fn check_rx_flags(&mut self) -> Result<bool, Error> { |
967 | let r = self.info.regs; |
968 | loop { |
969 | // Handle all buffered error flags. |
970 | if self.buffered_sr.pe() { |
971 | self.buffered_sr.set_pe(false); |
972 | return Err(Error::Parity); |
973 | } else if self.buffered_sr.fe() { |
974 | self.buffered_sr.set_fe(false); |
975 | return Err(Error::Framing); |
976 | } else if self.buffered_sr.ne() { |
977 | self.buffered_sr.set_ne(false); |
978 | return Err(Error::Noise); |
979 | } else if self.buffered_sr.ore() { |
980 | self.buffered_sr.set_ore(false); |
981 | return Err(Error::Overrun); |
982 | } else if self.buffered_sr.rxne() { |
983 | self.buffered_sr.set_rxne(false); |
984 | return Ok(true); |
985 | } else { |
986 | // No error flags from previous iterations were set: Check the actual status register |
987 | let sr = r.sr().read(); |
988 | if !sr.rxne() { |
989 | return Ok(false); |
990 | } |
991 | |
992 | // Buffer the status register and let the loop handle the error flags. |
993 | self.buffered_sr = sr; |
994 | } |
995 | } |
996 | } |
997 | |
998 | #[cfg (any(usart_v3, usart_v4))] |
999 | fn check_rx_flags(&mut self) -> Result<bool, Error> { |
1000 | let r = self.info.regs; |
1001 | let sr = r.isr().read(); |
1002 | if sr.pe() { |
1003 | r.icr().write(|w| w.set_pe(true)); |
1004 | return Err(Error::Parity); |
1005 | } else if sr.fe() { |
1006 | r.icr().write(|w| w.set_fe(true)); |
1007 | return Err(Error::Framing); |
1008 | } else if sr.ne() { |
1009 | r.icr().write(|w| w.set_ne(true)); |
1010 | return Err(Error::Noise); |
1011 | } else if sr.ore() { |
1012 | r.icr().write(|w| w.set_ore(true)); |
1013 | return Err(Error::Overrun); |
1014 | } |
1015 | Ok(sr.rxne()) |
1016 | } |
1017 | |
1018 | /// Read a single u8 if there is one available, otherwise return WouldBlock |
1019 | pub(crate) fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> { |
1020 | let r = self.info.regs; |
1021 | if self.check_rx_flags()? { |
1022 | Ok(unsafe { rdr(r).read_volatile() }) |
1023 | } else { |
1024 | Err(nb::Error::WouldBlock) |
1025 | } |
1026 | } |
1027 | |
1028 | /// Perform a blocking read into `buffer` |
1029 | pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
1030 | let r = self.info.regs; |
1031 | |
1032 | // Call flush for Half-Duplex mode if some bytes were written and flush was not called. |
1033 | // It prevents reading of bytes which have just been written. |
1034 | if r.cr3().read().hdsel() && r.cr1().read().te() { |
1035 | blocking_flush(self.info)?; |
1036 | |
1037 | // Disable Transmitter and enable Receiver after flush |
1038 | r.cr1().modify(|reg| { |
1039 | reg.set_re(true); |
1040 | reg.set_te(false); |
1041 | }); |
1042 | } |
1043 | |
1044 | for b in buffer { |
1045 | while !self.check_rx_flags()? {} |
1046 | unsafe { *b = rdr(r).read_volatile() } |
1047 | } |
1048 | Ok(()) |
1049 | } |
1050 | |
1051 | /// Set baudrate |
1052 | pub fn set_baudrate(&self, baudrate: u32) -> Result<(), ConfigError> { |
1053 | set_baudrate(self.info, self.kernel_clock, baudrate) |
1054 | } |
1055 | } |
1056 | |
1057 | impl<'d, M: Mode> Drop for UartTx<'d, M> { |
1058 | fn drop(&mut self) { |
1059 | self.tx.as_ref().map(|x: &PeripheralRef<'_, AnyPin>| x.set_as_disconnected()); |
1060 | self.cts.as_ref().map(|x: &PeripheralRef<'_, AnyPin>| x.set_as_disconnected()); |
1061 | self.de.as_ref().map(|x: &PeripheralRef<'_, AnyPin>| x.set_as_disconnected()); |
1062 | drop_tx_rx(self.info, self.state); |
1063 | } |
1064 | } |
1065 | |
1066 | impl<'d, M: Mode> Drop for UartRx<'d, M> { |
1067 | fn drop(&mut self) { |
1068 | self.rx.as_ref().map(|x: &PeripheralRef<'_, AnyPin>| x.set_as_disconnected()); |
1069 | self.rts.as_ref().map(|x: &PeripheralRef<'_, AnyPin>| x.set_as_disconnected()); |
1070 | drop_tx_rx(self.info, self.state); |
1071 | } |
1072 | } |
1073 | |
1074 | fn drop_tx_rx(info: &Info, state: &State) { |
1075 | // We cannot use atomic subtraction here, because it's not supported for all targets |
1076 | let is_last_drop: bool = critical_section::with(|_| { |
1077 | let refcount: u8 = state.tx_rx_refcount.load(order:Ordering::Relaxed); |
1078 | assert!(refcount >= 1); |
1079 | state.tx_rx_refcount.store(val:refcount - 1, order:Ordering::Relaxed); |
1080 | refcount == 1 |
1081 | }); |
1082 | if is_last_drop { |
1083 | info.rcc.disable(); |
1084 | } |
1085 | } |
1086 | |
1087 | impl<'d> Uart<'d, Async> { |
1088 | /// Create a new bidirectional UART |
1089 | pub fn new<T: Instance>( |
1090 | peri: impl Peripheral<P = T> + 'd, |
1091 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
1092 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
1093 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
1094 | tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, |
1095 | rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, |
1096 | config: Config, |
1097 | ) -> Result<Self, ConfigError> { |
1098 | Self::new_inner( |
1099 | peri, |
1100 | new_pin!(rx, config.rx_af()), |
1101 | new_pin!(tx, config.tx_af()), |
1102 | None, |
1103 | None, |
1104 | None, |
1105 | new_dma!(tx_dma), |
1106 | new_dma!(rx_dma), |
1107 | config, |
1108 | ) |
1109 | } |
1110 | |
1111 | /// Create a new bidirectional UART with request-to-send and clear-to-send pins |
1112 | pub fn new_with_rtscts<T: Instance>( |
1113 | peri: impl Peripheral<P = T> + 'd, |
1114 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
1115 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
1116 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
1117 | rts: impl Peripheral<P = impl RtsPin<T>> + 'd, |
1118 | cts: impl Peripheral<P = impl CtsPin<T>> + 'd, |
1119 | tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, |
1120 | rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, |
1121 | config: Config, |
1122 | ) -> Result<Self, ConfigError> { |
1123 | Self::new_inner( |
1124 | peri, |
1125 | new_pin!(rx, config.rx_af()), |
1126 | new_pin!(tx, config.tx_af()), |
1127 | new_pin!(rts, AfType::output(OutputType::PushPull, Speed::Medium)), |
1128 | new_pin!(cts, AfType::input(Pull::None)), |
1129 | None, |
1130 | new_dma!(tx_dma), |
1131 | new_dma!(rx_dma), |
1132 | config, |
1133 | ) |
1134 | } |
1135 | |
1136 | #[cfg (not(any(usart_v1, usart_v2)))] |
1137 | /// Create a new bidirectional UART with a driver-enable pin |
1138 | pub fn new_with_de<T: Instance>( |
1139 | peri: impl Peripheral<P = T> + 'd, |
1140 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
1141 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
1142 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
1143 | de: impl Peripheral<P = impl DePin<T>> + 'd, |
1144 | tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, |
1145 | rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, |
1146 | config: Config, |
1147 | ) -> Result<Self, ConfigError> { |
1148 | Self::new_inner( |
1149 | peri, |
1150 | new_pin!(rx, config.rx_af()), |
1151 | new_pin!(tx, config.tx_af()), |
1152 | None, |
1153 | None, |
1154 | new_pin!(de, AfType::output(OutputType::PushPull, Speed::Medium)), |
1155 | new_dma!(tx_dma), |
1156 | new_dma!(rx_dma), |
1157 | config, |
1158 | ) |
1159 | } |
1160 | |
1161 | /// Create a single-wire half-duplex Uart transceiver on a single Tx pin. |
1162 | /// |
1163 | /// See [`new_half_duplex_on_rx`][`Self::new_half_duplex_on_rx`] if you would prefer to use an Rx pin |
1164 | /// (when it is available for your chip). There is no functional difference between these methods, as both |
1165 | /// allow bidirectional communication. |
1166 | /// |
1167 | /// The TX pin is always released when no data is transmitted. Thus, it acts as a standard |
1168 | /// I/O in idle or in reception. It means that the I/O must be configured so that TX is |
1169 | /// configured as alternate function open-drain with an external pull-up |
1170 | /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict |
1171 | /// on the line must be managed by software (for instance by using a centralized arbiter). |
1172 | #[doc (alias("HDSEL" ))] |
1173 | pub fn new_half_duplex<T: Instance>( |
1174 | peri: impl Peripheral<P = T> + 'd, |
1175 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
1176 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
1177 | tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, |
1178 | rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, |
1179 | mut config: Config, |
1180 | readback: HalfDuplexReadback, |
1181 | half_duplex: HalfDuplexConfig, |
1182 | ) -> Result<Self, ConfigError> { |
1183 | #[cfg (not(any(usart_v1, usart_v2)))] |
1184 | { |
1185 | config.swap_rx_tx = false; |
1186 | } |
1187 | config.duplex = Duplex::Half(readback); |
1188 | |
1189 | Self::new_inner( |
1190 | peri, |
1191 | None, |
1192 | new_pin!(tx, half_duplex.af_type()), |
1193 | None, |
1194 | None, |
1195 | None, |
1196 | new_dma!(tx_dma), |
1197 | new_dma!(rx_dma), |
1198 | config, |
1199 | ) |
1200 | } |
1201 | |
1202 | /// Create a single-wire half-duplex Uart transceiver on a single Rx pin. |
1203 | /// |
1204 | /// See [`new_half_duplex`][`Self::new_half_duplex`] if you would prefer to use an Tx pin. |
1205 | /// There is no functional difference between these methods, as both allow bidirectional communication. |
1206 | /// |
1207 | /// The pin is always released when no data is transmitted. Thus, it acts as a standard |
1208 | /// I/O in idle or in reception. |
1209 | /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict |
1210 | /// on the line must be managed by software (for instance by using a centralized arbiter). |
1211 | #[cfg (not(any(usart_v1, usart_v2)))] |
1212 | #[doc (alias("HDSEL" ))] |
1213 | pub fn new_half_duplex_on_rx<T: Instance>( |
1214 | peri: impl Peripheral<P = T> + 'd, |
1215 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
1216 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
1217 | tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, |
1218 | rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, |
1219 | mut config: Config, |
1220 | readback: HalfDuplexReadback, |
1221 | half_duplex: HalfDuplexConfig, |
1222 | ) -> Result<Self, ConfigError> { |
1223 | config.swap_rx_tx = true; |
1224 | config.duplex = Duplex::Half(readback); |
1225 | |
1226 | Self::new_inner( |
1227 | peri, |
1228 | None, |
1229 | None, |
1230 | new_pin!(rx, half_duplex.af_type()), |
1231 | None, |
1232 | None, |
1233 | new_dma!(tx_dma), |
1234 | new_dma!(rx_dma), |
1235 | config, |
1236 | ) |
1237 | } |
1238 | |
1239 | /// Perform an asynchronous write |
1240 | pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
1241 | self.tx.write(buffer).await |
1242 | } |
1243 | |
1244 | /// Wait until transmission complete |
1245 | pub async fn flush(&mut self) -> Result<(), Error> { |
1246 | self.tx.flush().await |
1247 | } |
1248 | |
1249 | /// Perform an asynchronous read into `buffer` |
1250 | pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
1251 | self.rx.read(buffer).await |
1252 | } |
1253 | |
1254 | /// Perform an an asynchronous read with idle line detection enabled |
1255 | pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { |
1256 | self.rx.read_until_idle(buffer).await |
1257 | } |
1258 | } |
1259 | |
1260 | impl<'d> Uart<'d, Blocking> { |
1261 | /// Create a new blocking bidirectional UART. |
1262 | pub fn new_blocking<T: Instance>( |
1263 | peri: impl Peripheral<P = T> + 'd, |
1264 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
1265 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
1266 | config: Config, |
1267 | ) -> Result<Self, ConfigError> { |
1268 | Self::new_inner( |
1269 | peri, |
1270 | new_pin!(rx, config.rx_af()), |
1271 | new_pin!(tx, config.tx_af()), |
1272 | None, |
1273 | None, |
1274 | None, |
1275 | None, |
1276 | None, |
1277 | config, |
1278 | ) |
1279 | } |
1280 | |
1281 | /// Create a new bidirectional UART with request-to-send and clear-to-send pins |
1282 | pub fn new_blocking_with_rtscts<T: Instance>( |
1283 | peri: impl Peripheral<P = T> + 'd, |
1284 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
1285 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
1286 | rts: impl Peripheral<P = impl RtsPin<T>> + 'd, |
1287 | cts: impl Peripheral<P = impl CtsPin<T>> + 'd, |
1288 | config: Config, |
1289 | ) -> Result<Self, ConfigError> { |
1290 | Self::new_inner( |
1291 | peri, |
1292 | new_pin!(rx, config.rx_af()), |
1293 | new_pin!(tx, config.tx_af()), |
1294 | new_pin!(rts, AfType::output(OutputType::PushPull, Speed::Medium)), |
1295 | new_pin!(cts, AfType::input(Pull::None)), |
1296 | None, |
1297 | None, |
1298 | None, |
1299 | config, |
1300 | ) |
1301 | } |
1302 | |
1303 | #[cfg (not(any(usart_v1, usart_v2)))] |
1304 | /// Create a new bidirectional UART with a driver-enable pin |
1305 | pub fn new_blocking_with_de<T: Instance>( |
1306 | peri: impl Peripheral<P = T> + 'd, |
1307 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
1308 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
1309 | de: impl Peripheral<P = impl DePin<T>> + 'd, |
1310 | config: Config, |
1311 | ) -> Result<Self, ConfigError> { |
1312 | Self::new_inner( |
1313 | peri, |
1314 | new_pin!(rx, config.rx_af()), |
1315 | new_pin!(tx, config.tx_af()), |
1316 | None, |
1317 | None, |
1318 | new_pin!(de, AfType::output(OutputType::PushPull, Speed::Medium)), |
1319 | None, |
1320 | None, |
1321 | config, |
1322 | ) |
1323 | } |
1324 | |
1325 | /// Create a single-wire half-duplex Uart transceiver on a single Tx pin. |
1326 | /// |
1327 | /// See [`new_half_duplex_on_rx`][`Self::new_half_duplex_on_rx`] if you would prefer to use an Rx pin |
1328 | /// (when it is available for your chip). There is no functional difference between these methods, as both |
1329 | /// allow bidirectional communication. |
1330 | /// |
1331 | /// The pin is always released when no data is transmitted. Thus, it acts as a standard |
1332 | /// I/O in idle or in reception. |
1333 | /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict |
1334 | /// on the line must be managed by software (for instance by using a centralized arbiter). |
1335 | #[doc (alias("HDSEL" ))] |
1336 | pub fn new_blocking_half_duplex<T: Instance>( |
1337 | peri: impl Peripheral<P = T> + 'd, |
1338 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
1339 | mut config: Config, |
1340 | readback: HalfDuplexReadback, |
1341 | half_duplex: HalfDuplexConfig, |
1342 | ) -> Result<Self, ConfigError> { |
1343 | #[cfg (not(any(usart_v1, usart_v2)))] |
1344 | { |
1345 | config.swap_rx_tx = false; |
1346 | } |
1347 | config.duplex = Duplex::Half(readback); |
1348 | |
1349 | Self::new_inner( |
1350 | peri, |
1351 | None, |
1352 | new_pin!(tx, half_duplex.af_type()), |
1353 | None, |
1354 | None, |
1355 | None, |
1356 | None, |
1357 | None, |
1358 | config, |
1359 | ) |
1360 | } |
1361 | |
1362 | /// Create a single-wire half-duplex Uart transceiver on a single Rx pin. |
1363 | /// |
1364 | /// See [`new_half_duplex`][`Self::new_half_duplex`] if you would prefer to use an Tx pin. |
1365 | /// There is no functional difference between these methods, as both allow bidirectional communication. |
1366 | /// |
1367 | /// The pin is always released when no data is transmitted. Thus, it acts as a standard |
1368 | /// I/O in idle or in reception. |
1369 | /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict |
1370 | /// on the line must be managed by software (for instance by using a centralized arbiter). |
1371 | #[cfg (not(any(usart_v1, usart_v2)))] |
1372 | #[doc (alias("HDSEL" ))] |
1373 | pub fn new_blocking_half_duplex_on_rx<T: Instance>( |
1374 | peri: impl Peripheral<P = T> + 'd, |
1375 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
1376 | mut config: Config, |
1377 | readback: HalfDuplexReadback, |
1378 | half_duplex: HalfDuplexConfig, |
1379 | ) -> Result<Self, ConfigError> { |
1380 | config.swap_rx_tx = true; |
1381 | config.duplex = Duplex::Half(readback); |
1382 | |
1383 | Self::new_inner( |
1384 | peri, |
1385 | None, |
1386 | None, |
1387 | new_pin!(rx, half_duplex.af_type()), |
1388 | None, |
1389 | None, |
1390 | None, |
1391 | None, |
1392 | config, |
1393 | ) |
1394 | } |
1395 | } |
1396 | |
1397 | impl<'d, M: Mode> Uart<'d, M> { |
1398 | fn new_inner<T: Instance>( |
1399 | _peri: impl Peripheral<P = T> + 'd, |
1400 | rx: Option<PeripheralRef<'d, AnyPin>>, |
1401 | tx: Option<PeripheralRef<'d, AnyPin>>, |
1402 | rts: Option<PeripheralRef<'d, AnyPin>>, |
1403 | cts: Option<PeripheralRef<'d, AnyPin>>, |
1404 | de: Option<PeripheralRef<'d, AnyPin>>, |
1405 | tx_dma: Option<ChannelAndRequest<'d>>, |
1406 | rx_dma: Option<ChannelAndRequest<'d>>, |
1407 | config: Config, |
1408 | ) -> Result<Self, ConfigError> { |
1409 | let info = T::info(); |
1410 | let state = T::state(); |
1411 | let kernel_clock = T::frequency(); |
1412 | |
1413 | let mut this = Self { |
1414 | tx: UartTx { |
1415 | _phantom: PhantomData, |
1416 | info, |
1417 | state, |
1418 | kernel_clock, |
1419 | tx, |
1420 | cts, |
1421 | de, |
1422 | tx_dma, |
1423 | duplex: config.duplex, |
1424 | }, |
1425 | rx: UartRx { |
1426 | _phantom: PhantomData, |
1427 | info, |
1428 | state, |
1429 | kernel_clock, |
1430 | rx, |
1431 | rts, |
1432 | rx_dma, |
1433 | detect_previous_overrun: config.detect_previous_overrun, |
1434 | #[cfg (any(usart_v1, usart_v2))] |
1435 | buffered_sr: stm32_metapac::usart::regs::Sr(0), |
1436 | }, |
1437 | }; |
1438 | this.enable_and_configure(&config)?; |
1439 | Ok(this) |
1440 | } |
1441 | |
1442 | fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> { |
1443 | let info = self.rx.info; |
1444 | let state = self.rx.state; |
1445 | state.tx_rx_refcount.store(2, Ordering::Relaxed); |
1446 | |
1447 | info.rcc.enable_and_reset(); |
1448 | |
1449 | info.regs.cr3().write(|w| { |
1450 | w.set_rtse(self.rx.rts.is_some()); |
1451 | w.set_ctse(self.tx.cts.is_some()); |
1452 | #[cfg (not(any(usart_v1, usart_v2)))] |
1453 | w.set_dem(self.tx.de.is_some()); |
1454 | }); |
1455 | configure(info, self.rx.kernel_clock, config, true, true)?; |
1456 | |
1457 | info.interrupt.unpend(); |
1458 | unsafe { info.interrupt.enable() }; |
1459 | |
1460 | Ok(()) |
1461 | } |
1462 | |
1463 | /// Perform a blocking write |
1464 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
1465 | self.tx.blocking_write(buffer) |
1466 | } |
1467 | |
1468 | /// Block until transmission complete |
1469 | pub fn blocking_flush(&mut self) -> Result<(), Error> { |
1470 | self.tx.blocking_flush() |
1471 | } |
1472 | |
1473 | /// Read a single `u8` or return `WouldBlock` |
1474 | pub(crate) fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> { |
1475 | self.rx.nb_read() |
1476 | } |
1477 | |
1478 | /// Perform a blocking read into `buffer` |
1479 | pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
1480 | self.rx.blocking_read(buffer) |
1481 | } |
1482 | |
1483 | /// Split the Uart into a transmitter and receiver, which is |
1484 | /// particularly useful when having two tasks correlating to |
1485 | /// transmitting and receiving. |
1486 | pub fn split(self) -> (UartTx<'d, M>, UartRx<'d, M>) { |
1487 | (self.tx, self.rx) |
1488 | } |
1489 | |
1490 | /// Split the Uart into a transmitter and receiver by mutable reference, |
1491 | /// which is particularly useful when having two tasks correlating to |
1492 | /// transmitting and receiving. |
1493 | pub fn split_ref(&mut self) -> (&mut UartTx<'d, M>, &mut UartRx<'d, M>) { |
1494 | (&mut self.tx, &mut self.rx) |
1495 | } |
1496 | |
1497 | /// Send break character |
1498 | pub fn send_break(&self) { |
1499 | self.tx.send_break(); |
1500 | } |
1501 | |
1502 | /// Set baudrate |
1503 | pub fn set_baudrate(&self, baudrate: u32) -> Result<(), ConfigError> { |
1504 | self.tx.set_baudrate(baudrate)?; |
1505 | self.rx.set_baudrate(baudrate)?; |
1506 | Ok(()) |
1507 | } |
1508 | } |
1509 | |
1510 | fn reconfigure(info: &Info, kernel_clock: Hertz, config: &Config) -> Result<(), ConfigError> { |
1511 | info.interrupt.disable(); |
1512 | let r: Lpuart = info.regs; |
1513 | |
1514 | let cr: Cr1 = r.cr1().read(); |
1515 | configure(info, kernel_clock, config, enable_rx:cr.re(), enable_tx:cr.te())?; |
1516 | |
1517 | info.interrupt.unpend(); |
1518 | unsafe { info.interrupt.enable() }; |
1519 | |
1520 | Ok(()) |
1521 | } |
1522 | |
1523 | fn calculate_brr(baud: u32, pclk: u32, presc: u32, mul: u32) -> u32 { |
1524 | // The calculation to be done to get the BRR is `mul * pclk / presc / baud` |
1525 | // To do this in 32-bit only we can't multiply `mul` and `pclk` |
1526 | let clock: u32 = pclk / presc; |
1527 | |
1528 | // The mul is applied as the last operation to prevent overflow |
1529 | let brr: u32 = clock / baud * mul; |
1530 | |
1531 | // The BRR calculation will be a bit off because of integer rounding. |
1532 | // Because we multiplied our inaccuracy with mul, our rounding now needs to be in proportion to mul. |
1533 | let rounding: u32 = ((clock % baud) * mul + (baud / 2)) / baud; |
1534 | |
1535 | brr + rounding |
1536 | } |
1537 | |
1538 | fn set_baudrate(info: &Info, kernel_clock: Hertz, baudrate: u32) -> Result<(), ConfigError> { |
1539 | info.interrupt.disable(); |
1540 | |
1541 | set_usart_baudrate(info, kernel_clock, baudrate)?; |
1542 | |
1543 | info.interrupt.unpend(); |
1544 | unsafe { info.interrupt.enable() }; |
1545 | |
1546 | Ok(()) |
1547 | } |
1548 | |
1549 | fn find_and_set_brr(r: Regs, kind: Kind, kernel_clock: Hertz, baudrate: u32) -> Result<bool, ConfigError> { |
1550 | #[cfg (not(usart_v4))] |
1551 | static DIVS: [(u16, ()); 1] = [(1, ())]; |
1552 | |
1553 | #[cfg (usart_v4)] |
1554 | static DIVS: [(u16, vals::Presc); 12] = [ |
1555 | (1, vals::Presc::DIV1), |
1556 | (2, vals::Presc::DIV2), |
1557 | (4, vals::Presc::DIV4), |
1558 | (6, vals::Presc::DIV6), |
1559 | (8, vals::Presc::DIV8), |
1560 | (10, vals::Presc::DIV10), |
1561 | (12, vals::Presc::DIV12), |
1562 | (16, vals::Presc::DIV16), |
1563 | (32, vals::Presc::DIV32), |
1564 | (64, vals::Presc::DIV64), |
1565 | (128, vals::Presc::DIV128), |
1566 | (256, vals::Presc::DIV256), |
1567 | ]; |
1568 | |
1569 | let (mul, brr_min, brr_max) = match kind { |
1570 | #[cfg (any(usart_v3, usart_v4))] |
1571 | Kind::Lpuart => { |
1572 | trace!("USART: Kind::Lpuart" ); |
1573 | (256, 0x300, 0x10_0000) |
1574 | } |
1575 | Kind::Uart => { |
1576 | trace!("USART: Kind::Uart" ); |
1577 | (1, 0x10, 0x1_0000) |
1578 | } |
1579 | }; |
1580 | |
1581 | let mut found_brr = None; |
1582 | #[cfg (not(usart_v1))] |
1583 | let mut over8 = false; |
1584 | #[cfg (usart_v1)] |
1585 | let over8 = false; |
1586 | |
1587 | for &(presc, _presc_val) in &DIVS { |
1588 | let brr = calculate_brr(baudrate, kernel_clock.0, presc as u32, mul); |
1589 | trace!( |
1590 | "USART: presc={}, div=0x{:08x} (mantissa = {}, fraction = {})" , |
1591 | presc, |
1592 | brr, |
1593 | brr >> 4, |
1594 | brr & 0x0F |
1595 | ); |
1596 | |
1597 | if brr < brr_min { |
1598 | #[cfg (not(usart_v1))] |
1599 | if brr * 2 >= brr_min && kind == Kind::Uart && !cfg!(usart_v1) { |
1600 | over8 = true; |
1601 | r.brr().write_value(regs::Brr(((brr << 1) & !0xF) | (brr & 0x07))); |
1602 | #[cfg (usart_v4)] |
1603 | r.presc().write(|w| w.set_prescaler(_presc_val)); |
1604 | found_brr = Some(brr); |
1605 | break; |
1606 | } |
1607 | return Err(ConfigError::BaudrateTooHigh); |
1608 | } |
1609 | |
1610 | if brr < brr_max { |
1611 | r.brr().write_value(regs::Brr(brr)); |
1612 | #[cfg (usart_v4)] |
1613 | r.presc().write(|w| w.set_prescaler(_presc_val)); |
1614 | found_brr = Some(brr); |
1615 | break; |
1616 | } |
1617 | } |
1618 | |
1619 | match found_brr { |
1620 | Some(brr) => { |
1621 | #[cfg (not(usart_v1))] |
1622 | let oversampling = if over8 { "8 bit" } else { "16 bit" }; |
1623 | #[cfg (usart_v1)] |
1624 | let oversampling = "default" ; |
1625 | trace!( |
1626 | "Using {} oversampling, desired baudrate: {}, actual baudrate: {}" , |
1627 | oversampling, |
1628 | baudrate, |
1629 | kernel_clock.0 / brr * mul |
1630 | ); |
1631 | Ok(over8) |
1632 | } |
1633 | None => Err(ConfigError::BaudrateTooLow), |
1634 | } |
1635 | } |
1636 | |
1637 | fn set_usart_baudrate(info: &Info, kernel_clock: Hertz, baudrate: u32) -> Result<(), ConfigError> { |
1638 | let r: Lpuart = info.regs; |
1639 | r.cr1().modify(|w: &mut Cr1| { |
1640 | // disable uart |
1641 | w.set_ue(val:false); |
1642 | }); |
1643 | |
1644 | #[cfg (not(usart_v1))] |
1645 | let over8: bool = find_and_set_brr(r, info.kind, kernel_clock, baudrate)?; |
1646 | #[cfg (usart_v1)] |
1647 | let _over8 = find_and_set_brr(r, info.kind, kernel_clock, baudrate)?; |
1648 | |
1649 | r.cr1().modify(|w: &mut Cr1| { |
1650 | // enable uart |
1651 | w.set_ue(val:true); |
1652 | |
1653 | #[cfg (not(usart_v1))] |
1654 | w.set_over8(val:vals::Over8::from_bits(val:over8 as _)); |
1655 | }); |
1656 | |
1657 | Ok(()) |
1658 | } |
1659 | |
1660 | fn configure( |
1661 | info: &Info, |
1662 | kernel_clock: Hertz, |
1663 | config: &Config, |
1664 | enable_rx: bool, |
1665 | enable_tx: bool, |
1666 | ) -> Result<(), ConfigError> { |
1667 | let r = info.regs; |
1668 | let kind = info.kind; |
1669 | |
1670 | if !enable_rx && !enable_tx { |
1671 | return Err(ConfigError::RxOrTxNotEnabled); |
1672 | } |
1673 | |
1674 | // UART must be disabled during configuration. |
1675 | r.cr1().modify(|w| { |
1676 | w.set_ue(false); |
1677 | }); |
1678 | |
1679 | #[cfg (not(usart_v1))] |
1680 | let over8 = find_and_set_brr(r, kind, kernel_clock, config.baudrate)?; |
1681 | #[cfg (usart_v1)] |
1682 | let _over8 = find_and_set_brr(r, kind, kernel_clock, config.baudrate)?; |
1683 | |
1684 | r.cr2().write(|w| { |
1685 | w.set_stop(match config.stop_bits { |
1686 | StopBits::STOP0P5 => vals::Stop::STOP0P5, |
1687 | StopBits::STOP1 => vals::Stop::STOP1, |
1688 | StopBits::STOP1P5 => vals::Stop::STOP1P5, |
1689 | StopBits::STOP2 => vals::Stop::STOP2, |
1690 | }); |
1691 | |
1692 | #[cfg (any(usart_v3, usart_v4))] |
1693 | { |
1694 | w.set_txinv(config.invert_tx); |
1695 | w.set_rxinv(config.invert_rx); |
1696 | w.set_swap(config.swap_rx_tx); |
1697 | } |
1698 | }); |
1699 | |
1700 | r.cr3().modify(|w| { |
1701 | #[cfg (not(usart_v1))] |
1702 | w.set_onebit(config.assume_noise_free); |
1703 | w.set_hdsel(config.duplex.is_half()); |
1704 | }); |
1705 | |
1706 | r.cr1().write(|w| { |
1707 | // enable uart |
1708 | w.set_ue(true); |
1709 | |
1710 | if config.duplex.is_half() { |
1711 | // The te and re bits will be set by write, read and flush methods. |
1712 | // Receiver should be enabled by default for Half-Duplex. |
1713 | w.set_te(false); |
1714 | w.set_re(true); |
1715 | } else { |
1716 | // enable transceiver |
1717 | w.set_te(enable_tx); |
1718 | // enable receiver |
1719 | w.set_re(enable_rx); |
1720 | } |
1721 | |
1722 | // configure word size and parity, since the parity bit is inserted into the MSB position, |
1723 | // it increases the effective word size |
1724 | match (config.parity, config.data_bits) { |
1725 | (Parity::ParityNone, DataBits::DataBits8) => { |
1726 | trace!("USART: m0: 8 data bits, no parity" ); |
1727 | w.set_m0(vals::M0::BIT8); |
1728 | #[cfg (any(usart_v3, usart_v4))] |
1729 | w.set_m1(vals::M1::M0); |
1730 | w.set_pce(false); |
1731 | } |
1732 | (Parity::ParityNone, DataBits::DataBits9) => { |
1733 | trace!("USART: m0: 9 data bits, no parity" ); |
1734 | w.set_m0(vals::M0::BIT9); |
1735 | #[cfg (any(usart_v3, usart_v4))] |
1736 | w.set_m1(vals::M1::M0); |
1737 | w.set_pce(false); |
1738 | } |
1739 | #[cfg (any(usart_v3, usart_v4))] |
1740 | (Parity::ParityNone, DataBits::DataBits7) => { |
1741 | trace!("USART: m0: 7 data bits, no parity" ); |
1742 | w.set_m0(vals::M0::BIT8); |
1743 | w.set_m1(vals::M1::BIT7); |
1744 | w.set_pce(false); |
1745 | } |
1746 | (Parity::ParityEven, DataBits::DataBits8) => { |
1747 | trace!("USART: m0: 8 data bits, even parity" ); |
1748 | w.set_m0(vals::M0::BIT9); |
1749 | #[cfg (any(usart_v3, usart_v4))] |
1750 | w.set_m1(vals::M1::M0); |
1751 | w.set_pce(true); |
1752 | w.set_ps(vals::Ps::EVEN); |
1753 | } |
1754 | (Parity::ParityEven, DataBits::DataBits7) => { |
1755 | trace!("USART: m0: 7 data bits, even parity" ); |
1756 | w.set_m0(vals::M0::BIT8); |
1757 | #[cfg (any(usart_v3, usart_v4))] |
1758 | w.set_m1(vals::M1::M0); |
1759 | w.set_pce(true); |
1760 | w.set_ps(vals::Ps::EVEN); |
1761 | } |
1762 | (Parity::ParityOdd, DataBits::DataBits8) => { |
1763 | trace!("USART: m0: 8 data bits, odd parity" ); |
1764 | w.set_m0(vals::M0::BIT9); |
1765 | #[cfg (any(usart_v3, usart_v4))] |
1766 | w.set_m1(vals::M1::M0); |
1767 | w.set_pce(true); |
1768 | w.set_ps(vals::Ps::ODD); |
1769 | } |
1770 | (Parity::ParityOdd, DataBits::DataBits7) => { |
1771 | trace!("USART: m0: 7 data bits, odd parity" ); |
1772 | w.set_m0(vals::M0::BIT8); |
1773 | #[cfg (any(usart_v3, usart_v4))] |
1774 | w.set_m1(vals::M1::M0); |
1775 | w.set_pce(true); |
1776 | w.set_ps(vals::Ps::ODD); |
1777 | } |
1778 | _ => { |
1779 | return Err(ConfigError::DataParityNotSupported); |
1780 | } |
1781 | } |
1782 | #[cfg (not(usart_v1))] |
1783 | w.set_over8(vals::Over8::from_bits(over8 as _)); |
1784 | #[cfg (usart_v4)] |
1785 | { |
1786 | trace!("USART: set_fifoen: true (usart_v4)" ); |
1787 | w.set_fifoen(true); |
1788 | } |
1789 | |
1790 | Ok(()) |
1791 | })?; |
1792 | |
1793 | Ok(()) |
1794 | } |
1795 | |
1796 | impl<'d, M: Mode> embedded_hal_02::serial::Read<u8> for UartRx<'d, M> { |
1797 | type Error = Error; |
1798 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { |
1799 | self.nb_read() |
1800 | } |
1801 | } |
1802 | |
1803 | impl<'d, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, M> { |
1804 | type Error = Error; |
1805 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { |
1806 | self.blocking_write(buffer) |
1807 | } |
1808 | fn bflush(&mut self) -> Result<(), Self::Error> { |
1809 | self.blocking_flush() |
1810 | } |
1811 | } |
1812 | |
1813 | impl<'d, M: Mode> embedded_hal_02::serial::Read<u8> for Uart<'d, M> { |
1814 | type Error = Error; |
1815 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { |
1816 | self.nb_read() |
1817 | } |
1818 | } |
1819 | |
1820 | impl<'d, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, M> { |
1821 | type Error = Error; |
1822 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { |
1823 | self.blocking_write(buffer) |
1824 | } |
1825 | fn bflush(&mut self) -> Result<(), Self::Error> { |
1826 | self.blocking_flush() |
1827 | } |
1828 | } |
1829 | |
1830 | impl embedded_hal_nb::serial::Error for Error { |
1831 | fn kind(&self) -> embedded_hal_nb::serial::ErrorKind { |
1832 | match *self { |
1833 | Self::Framing => embedded_hal_nb::serial::ErrorKind::FrameFormat, |
1834 | Self::Noise => embedded_hal_nb::serial::ErrorKind::Noise, |
1835 | Self::Overrun => embedded_hal_nb::serial::ErrorKind::Overrun, |
1836 | Self::Parity => embedded_hal_nb::serial::ErrorKind::Parity, |
1837 | Self::BufferTooLong => embedded_hal_nb::serial::ErrorKind::Other, |
1838 | } |
1839 | } |
1840 | } |
1841 | |
1842 | impl<'d, M: Mode> embedded_hal_nb::serial::ErrorType for Uart<'d, M> { |
1843 | type Error = Error; |
1844 | } |
1845 | |
1846 | impl<'d, M: Mode> embedded_hal_nb::serial::ErrorType for UartTx<'d, M> { |
1847 | type Error = Error; |
1848 | } |
1849 | |
1850 | impl<'d, M: Mode> embedded_hal_nb::serial::ErrorType for UartRx<'d, M> { |
1851 | type Error = Error; |
1852 | } |
1853 | |
1854 | impl<'d, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, M> { |
1855 | fn read(&mut self) -> nb::Result<u8, Self::Error> { |
1856 | self.nb_read() |
1857 | } |
1858 | } |
1859 | |
1860 | impl<'d, M: Mode> embedded_hal_nb::serial::Write for UartTx<'d, M> { |
1861 | fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { |
1862 | self.blocking_write(&[char]).map_err(op:nb::Error::Other) |
1863 | } |
1864 | |
1865 | fn flush(&mut self) -> nb::Result<(), Self::Error> { |
1866 | self.blocking_flush().map_err(op:nb::Error::Other) |
1867 | } |
1868 | } |
1869 | |
1870 | impl<'d, M: Mode> embedded_hal_nb::serial::Read for Uart<'d, M> { |
1871 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { |
1872 | self.nb_read() |
1873 | } |
1874 | } |
1875 | |
1876 | impl<'d, M: Mode> embedded_hal_nb::serial::Write for Uart<'d, M> { |
1877 | fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { |
1878 | self.blocking_write(&[char]).map_err(op:nb::Error::Other) |
1879 | } |
1880 | |
1881 | fn flush(&mut self) -> nb::Result<(), Self::Error> { |
1882 | self.blocking_flush().map_err(op:nb::Error::Other) |
1883 | } |
1884 | } |
1885 | |
1886 | impl embedded_io::Error for Error { |
1887 | fn kind(&self) -> embedded_io::ErrorKind { |
1888 | embedded_io::ErrorKind::Other |
1889 | } |
1890 | } |
1891 | |
1892 | impl<M: Mode> embedded_io::ErrorType for Uart<'_, M> { |
1893 | type Error = Error; |
1894 | } |
1895 | |
1896 | impl<M: Mode> embedded_io::ErrorType for UartTx<'_, M> { |
1897 | type Error = Error; |
1898 | } |
1899 | |
1900 | impl<M: Mode> embedded_io::Write for Uart<'_, M> { |
1901 | fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |
1902 | self.blocking_write(buffer:buf)?; |
1903 | Ok(buf.len()) |
1904 | } |
1905 | |
1906 | fn flush(&mut self) -> Result<(), Self::Error> { |
1907 | self.blocking_flush() |
1908 | } |
1909 | } |
1910 | |
1911 | impl<M: Mode> embedded_io::Write for UartTx<'_, M> { |
1912 | fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |
1913 | self.blocking_write(buffer:buf)?; |
1914 | Ok(buf.len()) |
1915 | } |
1916 | |
1917 | fn flush(&mut self) -> Result<(), Self::Error> { |
1918 | self.blocking_flush() |
1919 | } |
1920 | } |
1921 | |
1922 | impl embedded_io_async::Write for Uart<'_, Async> { |
1923 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |
1924 | self.write(buffer:buf).await?; |
1925 | Ok(buf.len()) |
1926 | } |
1927 | |
1928 | async fn flush(&mut self) -> Result<(), Self::Error> { |
1929 | self.flush().await |
1930 | } |
1931 | } |
1932 | |
1933 | impl embedded_io_async::Write for UartTx<'_, Async> { |
1934 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |
1935 | self.write(buffer:buf).await?; |
1936 | Ok(buf.len()) |
1937 | } |
1938 | |
1939 | async fn flush(&mut self) -> Result<(), Self::Error> { |
1940 | self.flush().await |
1941 | } |
1942 | } |
1943 | |
1944 | pub use buffered::*; |
1945 | |
1946 | pub use crate::usart::buffered::InterruptHandler as BufferedInterruptHandler; |
1947 | mod buffered; |
1948 | |
1949 | #[cfg (not(gpdma))] |
1950 | mod ringbuffered; |
1951 | #[cfg (not(gpdma))] |
1952 | pub use ringbuffered::RingBufferedUartRx; |
1953 | |
1954 | #[cfg (any(usart_v1, usart_v2))] |
1955 | fn tdr(r: crate::pac::usart::Usart) -> *mut u8 { |
1956 | r.dr().as_ptr() as _ |
1957 | } |
1958 | |
1959 | #[cfg (any(usart_v1, usart_v2))] |
1960 | fn rdr(r: crate::pac::usart::Usart) -> *mut u8 { |
1961 | r.dr().as_ptr() as _ |
1962 | } |
1963 | |
1964 | #[cfg (any(usart_v1, usart_v2))] |
1965 | fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Sr, crate::pac::common::RW> { |
1966 | r.sr() |
1967 | } |
1968 | |
1969 | #[cfg (any(usart_v1, usart_v2))] |
1970 | #[allow (unused)] |
1971 | fn clear_interrupt_flags(_r: Regs, _sr: regs::Sr) { |
1972 | // On v1 the flags are cleared implicitly by reads and writes to DR. |
1973 | } |
1974 | |
1975 | #[cfg (any(usart_v3, usart_v4))] |
1976 | fn tdr(r: Regs) -> *mut u8 { |
1977 | r.tdr().as_ptr() as _ |
1978 | } |
1979 | |
1980 | #[cfg (any(usart_v3, usart_v4))] |
1981 | fn rdr(r: Regs) -> *mut u8 { |
1982 | r.rdr().as_ptr() as _ |
1983 | } |
1984 | |
1985 | #[cfg (any(usart_v3, usart_v4))] |
1986 | fn sr(r: Regs) -> crate::pac::common::Reg<regs::Isr, crate::pac::common::R> { |
1987 | r.isr() |
1988 | } |
1989 | |
1990 | #[cfg (any(usart_v3, usart_v4))] |
1991 | #[allow (unused)] |
1992 | fn clear_interrupt_flags(r: Regs, sr: regs::Isr) { |
1993 | r.icr().write(|w: &mut Icr| *w = regs::Icr(sr.0)); |
1994 | } |
1995 | |
1996 | #[derive (Clone, Copy, PartialEq, Eq)] |
1997 | enum Kind { |
1998 | Uart, |
1999 | #[cfg (any(usart_v3, usart_v4))] |
2000 | #[allow (unused)] |
2001 | Lpuart, |
2002 | } |
2003 | |
2004 | struct State { |
2005 | rx_waker: AtomicWaker, |
2006 | tx_rx_refcount: AtomicU8, |
2007 | } |
2008 | |
2009 | impl State { |
2010 | const fn new() -> Self { |
2011 | Self { |
2012 | rx_waker: AtomicWaker::new(), |
2013 | tx_rx_refcount: AtomicU8::new(0), |
2014 | } |
2015 | } |
2016 | } |
2017 | |
2018 | struct Info { |
2019 | regs: Regs, |
2020 | rcc: RccInfo, |
2021 | interrupt: Interrupt, |
2022 | kind: Kind, |
2023 | } |
2024 | |
2025 | #[allow (private_interfaces)] |
2026 | pub(crate) trait SealedInstance: crate::rcc::RccPeripheral { |
2027 | fn info() -> &'static Info; |
2028 | fn state() -> &'static State; |
2029 | fn buffered_state() -> &'static buffered::State; |
2030 | } |
2031 | |
2032 | /// USART peripheral instance trait. |
2033 | #[allow (private_bounds)] |
2034 | pub trait Instance: Peripheral<P = Self> + SealedInstance + 'static + Send { |
2035 | /// Interrupt for this peripheral. |
2036 | type Interrupt: interrupt::typelevel::Interrupt; |
2037 | } |
2038 | |
2039 | pin_trait!(RxPin, Instance); |
2040 | pin_trait!(TxPin, Instance); |
2041 | pin_trait!(CtsPin, Instance); |
2042 | pin_trait!(RtsPin, Instance); |
2043 | pin_trait!(CkPin, Instance); |
2044 | pin_trait!(DePin, Instance); |
2045 | |
2046 | dma_trait!(TxDma, Instance); |
2047 | dma_trait!(RxDma, Instance); |
2048 | |
2049 | macro_rules! impl_usart { |
2050 | ($inst:ident, $irq:ident, $kind:expr) => { |
2051 | #[allow(private_interfaces)] |
2052 | impl SealedInstance for crate::peripherals::$inst { |
2053 | fn info() -> &'static Info { |
2054 | static INFO: Info = Info { |
2055 | regs: unsafe { Regs::from_ptr(crate::pac::$inst.as_ptr()) }, |
2056 | rcc: crate::peripherals::$inst::RCC_INFO, |
2057 | interrupt: crate::interrupt::typelevel::$irq::IRQ, |
2058 | kind: $kind, |
2059 | }; |
2060 | &INFO |
2061 | } |
2062 | |
2063 | fn state() -> &'static State { |
2064 | static STATE: State = State::new(); |
2065 | &STATE |
2066 | } |
2067 | |
2068 | fn buffered_state() -> &'static buffered::State { |
2069 | static BUFFERED_STATE: buffered::State = buffered::State::new(); |
2070 | &BUFFERED_STATE |
2071 | } |
2072 | } |
2073 | |
2074 | impl Instance for crate::peripherals::$inst { |
2075 | type Interrupt = crate::interrupt::typelevel::$irq; |
2076 | } |
2077 | }; |
2078 | } |
2079 | |
2080 | foreach_interrupt!( |
2081 | ($inst:ident, usart, LPUART, $signal_name:ident, $irq:ident) => { |
2082 | impl_usart!($inst, $irq, Kind::Lpuart); |
2083 | }; |
2084 | ($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => { |
2085 | impl_usart!($inst, $irq, Kind::Uart); |
2086 | }; |
2087 | ); |
2088 | |