aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/usart/buffered.rs34
-rw-r--r--embassy-stm32/src/usart/mod.rs402
-rw-r--r--examples/stm32f3/src/bin/usart_dma.rs4
-rw-r--r--examples/stm32f4/src/bin/usart.rs4
-rw-r--r--examples/stm32f4/src/bin/usart_buffered.rs15
-rw-r--r--examples/stm32f4/src/bin/usart_dma.rs4
-rw-r--r--examples/stm32f7/src/bin/usart_dma.rs4
-rw-r--r--examples/stm32h7/src/bin/usart.rs4
-rw-r--r--examples/stm32h7/src/bin/usart_dma.rs4
-rw-r--r--examples/stm32h7/src/bin/usart_split.rs4
-rw-r--r--examples/stm32l0/src/bin/usart_dma.rs4
-rw-r--r--examples/stm32l0/src/bin/usart_irq.rs12
-rw-r--r--examples/stm32l4/src/bin/usart.rs4
-rw-r--r--examples/stm32l4/src/bin/usart_dma.rs4
-rw-r--r--tests/stm32/src/bin/usart.rs17
-rw-r--r--tests/stm32/src/bin/usart_dma.rs48
16 files changed, 500 insertions, 68 deletions
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs
index c30bbc20a..3be0677bd 100644
--- a/embassy-stm32/src/usart/buffered.rs
+++ b/embassy-stm32/src/usart/buffered.rs
@@ -46,16 +46,44 @@ impl<'d, T: BasicInstance> Unpin for BufferedUart<'d, T> {}
46impl<'d, T: BasicInstance> BufferedUart<'d, T> { 46impl<'d, T: BasicInstance> BufferedUart<'d, T> {
47 pub fn new( 47 pub fn new(
48 state: &'d mut State<'d, T>, 48 state: &'d mut State<'d, T>,
49 _uart: Uart<'d, T, NoDma, NoDma>, 49 _peri: impl Peripheral<P = T> + 'd,
50 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
51 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
50 irq: impl Peripheral<P = T::Interrupt> + 'd, 52 irq: impl Peripheral<P = T::Interrupt> + 'd,
51 tx_buffer: &'d mut [u8], 53 tx_buffer: &'d mut [u8],
52 rx_buffer: &'d mut [u8], 54 rx_buffer: &'d mut [u8],
55 config: Config,
53 ) -> BufferedUart<'d, T> { 56 ) -> BufferedUart<'d, T> {
54 into_ref!(irq); 57 into_ref!(_peri, rx, tx, irq);
58
59 T::enable();
60 T::reset();
55 61
56 let r = T::regs(); 62 let r = T::regs();
63
64 configure(r, &config, T::frequency(), T::MULTIPLIER);
65
57 unsafe { 66 unsafe {
58 r.cr1().modify(|w| { 67 rx.set_as_af(rx.af_num(), AFType::Input);
68 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
69
70 r.cr2().write(|_w| {});
71 r.cr3().write(|_w| {});
72 r.cr1().write(|w| {
73 w.set_ue(true);
74 w.set_te(true);
75 w.set_re(true);
76 w.set_m0(if config.parity != Parity::ParityNone {
77 vals::M0::BIT9
78 } else {
79 vals::M0::BIT8
80 });
81 w.set_pce(config.parity != Parity::ParityNone);
82 w.set_ps(match config.parity {
83 Parity::ParityOdd => vals::Ps::ODD,
84 Parity::ParityEven => vals::Ps::EVEN,
85 _ => vals::Ps::EVEN,
86 });
59 w.set_rxneie(true); 87 w.set_rxneie(true);
60 w.set_idleie(true); 88 w.set_idleie(true);
61 }); 89 });
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index 3f5b99523..dee466b21 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -1,7 +1,11 @@
1#![macro_use] 1#![macro_use]
2 2
3use core::future::poll_fn;
3use core::marker::PhantomData; 4use core::marker::PhantomData;
5use core::task::Poll;
4 6
7use atomic_polyfill::{compiler_fence, Ordering};
8use embassy_cortex_m::interrupt::InterruptExt;
5use embassy_hal_common::{into_ref, PeripheralRef}; 9use embassy_hal_common::{into_ref, PeripheralRef};
6 10
7use crate::dma::NoDma; 11use crate::dma::NoDma;
@@ -10,6 +14,7 @@ use crate::gpio::sealed::AFType;
10use crate::pac::lpuart::{regs, vals, Lpuart as Regs}; 14use crate::pac::lpuart::{regs, vals, Lpuart as Regs};
11#[cfg(not(any(lpuart_v1, lpuart_v2)))] 15#[cfg(not(any(lpuart_v1, lpuart_v2)))]
12use crate::pac::usart::{regs, vals, Usart as Regs}; 16use crate::pac::usart::{regs, vals, Usart as Regs};
17use crate::time::Hertz;
13use crate::{peripherals, Peripheral}; 18use crate::{peripherals, Peripheral};
14 19
15#[derive(Clone, Copy, PartialEq, Eq, Debug)] 20#[derive(Clone, Copy, PartialEq, Eq, Debug)]
@@ -44,6 +49,10 @@ pub struct Config {
44 pub data_bits: DataBits, 49 pub data_bits: DataBits,
45 pub stop_bits: StopBits, 50 pub stop_bits: StopBits,
46 pub parity: Parity, 51 pub parity: Parity,
52 /// if true, on read-like method, if there is a latent error pending,
53 /// read will abort, the error reported and cleared
54 /// if false, the error is ignored and cleared
55 pub detect_previous_overrun: bool,
47} 56}
48 57
49impl Default for Config { 58impl Default for Config {
@@ -53,6 +62,8 @@ impl Default for Config {
53 data_bits: DataBits::DataBits8, 62 data_bits: DataBits::DataBits8,
54 stop_bits: StopBits::STOP1, 63 stop_bits: StopBits::STOP1,
55 parity: Parity::ParityNone, 64 parity: Parity::ParityNone,
65 // historical behavior
66 detect_previous_overrun: false,
56 } 67 }
57 } 68 }
58} 69}
@@ -70,10 +81,11 @@ pub enum Error {
70 Overrun, 81 Overrun,
71 /// Parity check error 82 /// Parity check error
72 Parity, 83 Parity,
84 /// Buffer too large for DMA
85 BufferTooLong,
73} 86}
74 87
75pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> { 88pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> {
76 phantom: PhantomData<&'d mut T>,
77 tx: UartTx<'d, T, TxDma>, 89 tx: UartTx<'d, T, TxDma>,
78 rx: UartRx<'d, T, RxDma>, 90 rx: UartRx<'d, T, RxDma>,
79} 91}
@@ -84,8 +96,9 @@ pub struct UartTx<'d, T: BasicInstance, TxDma = NoDma> {
84} 96}
85 97
86pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> { 98pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> {
87 phantom: PhantomData<&'d mut T>, 99 _peri: PeripheralRef<'d, T>,
88 rx_dma: PeripheralRef<'d, RxDma>, 100 rx_dma: PeripheralRef<'d, RxDma>,
101 detect_previous_overrun: bool,
89} 102}
90 103
91impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { 104impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
@@ -135,10 +148,112 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
135} 148}
136 149
137impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { 150impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
138 fn new(rx_dma: PeripheralRef<'d, RxDma>) -> Self { 151 /// usefull if you only want Uart Rx. It saves 1 pin and consumes a little less power
152 pub fn new(
153 peri: impl Peripheral<P = T> + 'd,
154 irq: impl Peripheral<P = T::Interrupt> + 'd,
155 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
156 rx_dma: impl Peripheral<P = RxDma> + 'd,
157 config: Config,
158 ) -> Self {
159 into_ref!(peri, irq, rx, rx_dma);
160
161 T::enable();
162 T::reset();
163
164 let r = T::regs();
165
166 configure(r, &config, T::frequency(), T::MULTIPLIER);
167
168 unsafe {
169 rx.set_as_af(rx.af_num(), AFType::Input);
170
171 r.cr2().write(|_w| {});
172 r.cr3().write(|w| {
173 // enable Error Interrupt: (Frame error, Noise error, Overrun error)
174 w.set_eie(true);
175 });
176 r.cr1().write(|w| {
177 // enable uart
178 w.set_ue(true);
179 // enable receiver
180 w.set_re(true);
181 // configure word size
182 w.set_m0(if config.parity != Parity::ParityNone {
183 vals::M0::BIT9
184 } else {
185 vals::M0::BIT8
186 });
187 // configure parity
188 w.set_pce(config.parity != Parity::ParityNone);
189 w.set_ps(match config.parity {
190 Parity::ParityOdd => vals::Ps::ODD,
191 Parity::ParityEven => vals::Ps::EVEN,
192 _ => vals::Ps::EVEN,
193 });
194 });
195 }
196
197 irq.set_handler(Self::on_interrupt);
198 irq.unpend();
199 irq.enable();
200
201 // create state once!
202 let _s = T::state();
203
139 Self { 204 Self {
205 _peri: peri,
140 rx_dma, 206 rx_dma,
141 phantom: PhantomData, 207 detect_previous_overrun: config.detect_previous_overrun,
208 }
209 }
210
211 fn on_interrupt(_: *mut ()) {
212 let r = T::regs();
213 let s = T::state();
214
215 let (sr, cr1, cr3) = unsafe { (sr(r).read(), r.cr1().read(), r.cr3().read()) };
216
217 let has_errors = (sr.pe() && cr1.peie()) || ((sr.fe() || sr.ne() || sr.ore()) && cr3.eie());
218
219 if has_errors {
220 // clear all interrupts and DMA Rx Request
221 unsafe {
222 r.cr1().modify(|w| {
223 // disable RXNE interrupt
224 w.set_rxneie(false);
225 // disable parity interrupt
226 w.set_peie(false);
227 // disable idle line interrupt
228 w.set_idleie(false);
229 });
230 r.cr3().modify(|w| {
231 // disable Error Interrupt: (Frame error, Noise error, Overrun error)
232 w.set_eie(false);
233 // disable DMA Rx Request
234 w.set_dmar(false);
235 });
236 }
237
238 compiler_fence(Ordering::SeqCst);
239
240 s.rx_waker.wake();
241 } else if cr1.idleie() && sr.idle() {
242 // IDLE detected: no more data will come
243 unsafe {
244 r.cr1().modify(|w| {
245 // disable idle line detection
246 w.set_idleie(false);
247 });
248
249 r.cr3().modify(|w| {
250 // disable DMA Rx Request
251 w.set_dmar(false);
252 });
253 }
254 compiler_fence(Ordering::SeqCst);
255
256 s.rx_waker.wake();
142 } 257 }
143 } 258 }
144 259
@@ -146,17 +261,8 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
146 where 261 where
147 RxDma: crate::usart::RxDma<T>, 262 RxDma: crate::usart::RxDma<T>,
148 { 263 {
149 let ch = &mut self.rx_dma; 264 self.inner_read(buffer, false).await?;
150 let request = ch.request(); 265
151 unsafe {
152 T::regs().cr3().modify(|reg| {
153 reg.set_dmar(true);
154 });
155 }
156 // If we don't assign future to a variable, the data register pointer
157 // is held across an await and makes the future non-Send.
158 let transfer = crate::dma::read(ch, request, rdr(T::regs()), buffer);
159 transfer.await;
160 Ok(()) 266 Ok(())
161 } 267 }
162 268
@@ -211,13 +317,202 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
211 } 317 }
212 Ok(()) 318 Ok(())
213 } 319 }
320
321 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error>
322 where
323 RxDma: crate::usart::RxDma<T>,
324 {
325 self.inner_read(buffer, true).await
326 }
327
328 async fn inner_read(&mut self, buffer: &mut [u8], enable_idle_line_detection: bool) -> Result<usize, Error>
329 where
330 RxDma: crate::usart::RxDma<T>,
331 {
332 if buffer.is_empty() {
333 return Ok(0);
334 } else if buffer.len() > 0xFFFF {
335 return Err(Error::BufferTooLong);
336 }
337
338 let r = T::regs();
339
340 let buffer_len = buffer.len();
341
342 let ch = &mut self.rx_dma;
343 let request = ch.request();
344
345 // SAFETY: The only way we might have a problem is using split rx and tx
346 // here we only modify or read Rx related flags, interrupts and DMA channel
347 unsafe {
348 // Start USART DMA
349 // will not do anything yet because DMAR is not yet set
350 ch.start_read(request, rdr(r), buffer, Default::default());
351
352 // clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer
353 if !self.detect_previous_overrun {
354 let sr = sr(r).read();
355 // This read also clears the error and idle interrupt flags on v1.
356 rdr(r).read_volatile();
357 clear_interrupt_flags(r, sr);
358 }
359
360 r.cr1().modify(|w| {
361 // disable RXNE interrupt
362 w.set_rxneie(false);
363 // enable parity interrupt if not ParityNone
364 w.set_peie(w.pce());
365 });
366
367 r.cr3().modify(|w| {
368 // enable Error Interrupt: (Frame error, Noise error, Overrun error)
369 w.set_eie(true);
370 // enable DMA Rx Request
371 w.set_dmar(true);
372 });
373
374 compiler_fence(Ordering::SeqCst);
375
376 // In case of errors already pending when reception started, interrupts may have already been raised
377 // and lead to reception abortion (Overrun error for instance). In such a case, all interrupts
378 // have been disabled in interrupt handler and DMA Rx Request has been disabled.
379
380 let cr3 = r.cr3().read();
381
382 if !cr3.dmar() {
383 // something went wrong
384 // because the only way to get this flag cleared is to have an interrupt
385
386 // abort DMA transfer
387 ch.request_stop();
388 while ch.is_running() {}
389
390 let sr = sr(r).read();
391 // This read also clears the error and idle interrupt flags on v1.
392 rdr(r).read_volatile();
393 clear_interrupt_flags(r, sr);
394
395 if sr.pe() {
396 return Err(Error::Parity);
397 }
398 if sr.fe() {
399 return Err(Error::Framing);
400 }
401 if sr.ne() {
402 return Err(Error::Noise);
403 }
404 if sr.ore() {
405 return Err(Error::Overrun);
406 }
407
408 unreachable!();
409 }
410
411 // clear idle flag
412 if enable_idle_line_detection {
413 let sr = sr(r).read();
414 // This read also clears the error and idle interrupt flags on v1.
415 rdr(r).read_volatile();
416 clear_interrupt_flags(r, sr);
417
418 // enable idle interrupt
419 r.cr1().modify(|w| {
420 w.set_idleie(true);
421 });
422 }
423 }
424
425 compiler_fence(Ordering::SeqCst);
426
427 let res = poll_fn(move |cx| {
428 let s = T::state();
429
430 ch.set_waker(cx.waker());
431 s.rx_waker.register(cx.waker());
432
433 // SAFETY: read only and we only use Rx related flags
434 let sr = unsafe { sr(r).read() };
435
436 // SAFETY: only clears Rx related flags
437 unsafe {
438 // This read also clears the error and idle interrupt flags on v1.
439 rdr(r).read_volatile();
440 clear_interrupt_flags(r, sr);
441 }
442
443 compiler_fence(Ordering::SeqCst);
444
445 let has_errors = sr.pe() || sr.fe() || sr.ne() || sr.ore();
446
447 if has_errors {
448 // all Rx interrupts and Rx DMA Request have already been cleared in interrupt handler
449
450 // stop dma transfer
451 ch.request_stop();
452 while ch.is_running() {}
453
454 if sr.pe() {
455 return Poll::Ready(Err(Error::Parity));
456 }
457 if sr.fe() {
458 return Poll::Ready(Err(Error::Framing));
459 }
460 if sr.ne() {
461 return Poll::Ready(Err(Error::Noise));
462 }
463 if sr.ore() {
464 return Poll::Ready(Err(Error::Overrun));
465 }
466 }
467
468 if sr.idle() {
469 // Idle line
470
471 // stop dma transfer
472 ch.request_stop();
473 while ch.is_running() {}
474
475 let n = buffer_len - (ch.remaining_transfers() as usize);
476
477 return Poll::Ready(Ok(n));
478 } else if !ch.is_running() {
479 // DMA complete
480 return Poll::Ready(Ok(buffer_len));
481 }
482
483 Poll::Pending
484 })
485 .await;
486
487 // clear all interrupts and DMA Rx Request
488 // SAFETY: only clears Rx related flags
489 unsafe {
490 r.cr1().modify(|w| {
491 // disable RXNE interrupt
492 w.set_rxneie(false);
493 // disable parity interrupt
494 w.set_peie(false);
495 // disable idle line interrupt
496 w.set_idleie(false);
497 });
498 r.cr3().modify(|w| {
499 // disable Error Interrupt: (Frame error, Noise error, Overrun error)
500 w.set_eie(false);
501 // disable DMA Rx Request
502 w.set_dmar(false);
503 });
504 }
505
506 res
507 }
214} 508}
215 509
216impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { 510impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
217 pub fn new( 511 pub fn new(
218 _inner: impl Peripheral<P = T> + 'd, 512 peri: impl Peripheral<P = T> + 'd,
219 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 513 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
220 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 514 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
515 irq: impl Peripheral<P = T::Interrupt> + 'd,
221 tx_dma: impl Peripheral<P = TxDma> + 'd, 516 tx_dma: impl Peripheral<P = TxDma> + 'd,
222 rx_dma: impl Peripheral<P = RxDma> + 'd, 517 rx_dma: impl Peripheral<P = RxDma> + 'd,
223 config: Config, 518 config: Config,
@@ -225,13 +520,14 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
225 T::enable(); 520 T::enable();
226 T::reset(); 521 T::reset();
227 522
228 Self::new_inner(_inner, rx, tx, tx_dma, rx_dma, config) 523 Self::new_inner(peri, rx, tx, irq, tx_dma, rx_dma, config)
229 } 524 }
230 525
231 pub fn new_with_rtscts( 526 pub fn new_with_rtscts(
232 _inner: impl Peripheral<P = T> + 'd, 527 peri: impl Peripheral<P = T> + 'd,
233 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 528 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
234 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 529 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
530 irq: impl Peripheral<P = T::Interrupt> + 'd,
235 rts: impl Peripheral<P = impl RtsPin<T>> + 'd, 531 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
236 cts: impl Peripheral<P = impl CtsPin<T>> + 'd, 532 cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
237 tx_dma: impl Peripheral<P = TxDma> + 'd, 533 tx_dma: impl Peripheral<P = TxDma> + 'd,
@@ -251,32 +547,29 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
251 w.set_ctse(true); 547 w.set_ctse(true);
252 }); 548 });
253 } 549 }
254 Self::new_inner(_inner, rx, tx, tx_dma, rx_dma, config) 550 Self::new_inner(peri, rx, tx, irq, tx_dma, rx_dma, config)
255 } 551 }
256 552
257 fn new_inner( 553 fn new_inner(
258 _inner: impl Peripheral<P = T> + 'd, 554 peri: impl Peripheral<P = T> + 'd,
259 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 555 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
260 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 556 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
557 irq: impl Peripheral<P = T::Interrupt> + 'd,
261 tx_dma: impl Peripheral<P = TxDma> + 'd, 558 tx_dma: impl Peripheral<P = TxDma> + 'd,
262 rx_dma: impl Peripheral<P = RxDma> + 'd, 559 rx_dma: impl Peripheral<P = RxDma> + 'd,
263 config: Config, 560 config: Config,
264 ) -> Self { 561 ) -> Self {
265 into_ref!(_inner, rx, tx, tx_dma, rx_dma); 562 into_ref!(peri, rx, tx, irq, tx_dma, rx_dma);
266
267 let pclk_freq = T::frequency();
268
269 // TODO: better calculation, including error checking and OVER8 if possible.
270 let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate * T::MULTIPLIER;
271 563
272 let r = T::regs(); 564 let r = T::regs();
273 565
566 configure(r, &config, T::frequency(), T::MULTIPLIER);
567
274 unsafe { 568 unsafe {
275 rx.set_as_af(rx.af_num(), AFType::Input); 569 rx.set_as_af(rx.af_num(), AFType::Input);
276 tx.set_as_af(tx.af_num(), AFType::OutputPushPull); 570 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
277 571
278 r.cr2().write(|_w| {}); 572 r.cr2().write(|_w| {});
279 r.brr().write_value(regs::Brr(div));
280 r.cr1().write(|w| { 573 r.cr1().write(|w| {
281 w.set_ue(true); 574 w.set_ue(true);
282 w.set_te(true); 575 w.set_te(true);
@@ -295,10 +588,20 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
295 }); 588 });
296 } 589 }
297 590
591 irq.set_handler(UartRx::<T, RxDma>::on_interrupt);
592 irq.unpend();
593 irq.enable();
594
595 // create state once!
596 let _s = T::state();
597
298 Self { 598 Self {
299 tx: UartTx::new(tx_dma), 599 tx: UartTx::new(tx_dma),
300 rx: UartRx::new(rx_dma), 600 rx: UartRx {
301 phantom: PhantomData {}, 601 _peri: peri,
602 rx_dma,
603 detect_previous_overrun: config.detect_previous_overrun,
604 },
302 } 605 }
303 } 606 }
304 607
@@ -332,6 +635,13 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
332 self.rx.blocking_read(buffer) 635 self.rx.blocking_read(buffer)
333 } 636 }
334 637
638 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error>
639 where
640 RxDma: crate::usart::RxDma<T>,
641 {
642 self.rx.read_until_idle(buffer).await
643 }
644
335 /// Split the Uart into a transmitter and receiver, which is 645 /// Split the Uart into a transmitter and receiver, which is
336 /// particuarly useful when having two tasks correlating to 646 /// particuarly useful when having two tasks correlating to
337 /// transmitting and receiving. 647 /// transmitting and receiving.
@@ -340,6 +650,15 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
340 } 650 }
341} 651}
342 652
653fn configure(r: Regs, config: &Config, pclk_freq: Hertz, multiplier: u32) {
654 // TODO: better calculation, including error checking and OVER8 if possible.
655 let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate * multiplier;
656
657 unsafe {
658 r.brr().write_value(regs::Brr(div));
659 }
660}
661
343mod eh02 { 662mod eh02 {
344 use super::*; 663 use super::*;
345 664
@@ -389,6 +708,7 @@ mod eh1 {
389 Self::Noise => embedded_hal_1::serial::ErrorKind::Noise, 708 Self::Noise => embedded_hal_1::serial::ErrorKind::Noise,
390 Self::Overrun => embedded_hal_1::serial::ErrorKind::Overrun, 709 Self::Overrun => embedded_hal_1::serial::ErrorKind::Overrun,
391 Self::Parity => embedded_hal_1::serial::ErrorKind::Parity, 710 Self::Parity => embedded_hal_1::serial::ErrorKind::Parity,
711 Self::BufferTooLong => embedded_hal_1::serial::ErrorKind::Other,
392 } 712 }
393 } 713 }
394 } 714 }
@@ -573,13 +893,30 @@ unsafe fn clear_interrupt_flags(r: Regs, sr: regs::Isr) {
573} 893}
574 894
575pub(crate) mod sealed { 895pub(crate) mod sealed {
896 use embassy_sync::waitqueue::AtomicWaker;
897
576 use super::*; 898 use super::*;
577 899
900 pub struct State {
901 pub rx_waker: AtomicWaker,
902 pub tx_waker: AtomicWaker,
903 }
904
905 impl State {
906 pub const fn new() -> Self {
907 Self {
908 rx_waker: AtomicWaker::new(),
909 tx_waker: AtomicWaker::new(),
910 }
911 }
912 }
913
578 pub trait BasicInstance: crate::rcc::RccPeripheral { 914 pub trait BasicInstance: crate::rcc::RccPeripheral {
579 const MULTIPLIER: u32; 915 const MULTIPLIER: u32;
580 type Interrupt: crate::interrupt::Interrupt; 916 type Interrupt: crate::interrupt::Interrupt;
581 917
582 fn regs() -> Regs; 918 fn regs() -> Regs;
919 fn state() -> &'static State;
583 } 920 }
584 921
585 pub trait FullInstance: BasicInstance { 922 pub trait FullInstance: BasicInstance {
@@ -587,7 +924,7 @@ pub(crate) mod sealed {
587 } 924 }
588} 925}
589 926
590pub trait BasicInstance: sealed::BasicInstance {} 927pub trait BasicInstance: Peripheral<P = Self> + sealed::BasicInstance + 'static + Send {}
591 928
592pub trait FullInstance: sealed::FullInstance {} 929pub trait FullInstance: sealed::FullInstance {}
593 930
@@ -609,6 +946,11 @@ macro_rules! impl_lpuart {
609 fn regs() -> Regs { 946 fn regs() -> Regs {
610 Regs(crate::pac::$inst.0) 947 Regs(crate::pac::$inst.0)
611 } 948 }
949
950 fn state() -> &'static crate::usart::sealed::State {
951 static STATE: crate::usart::sealed::State = crate::usart::sealed::State::new();
952 &STATE
953 }
612 } 954 }
613 955
614 impl BasicInstance for peripherals::$inst {} 956 impl BasicInstance for peripherals::$inst {}
diff --git a/examples/stm32f3/src/bin/usart_dma.rs b/examples/stm32f3/src/bin/usart_dma.rs
index 3bc5a287f..47121acf1 100644
--- a/examples/stm32f3/src/bin/usart_dma.rs
+++ b/examples/stm32f3/src/bin/usart_dma.rs
@@ -7,6 +7,7 @@ use core::fmt::Write;
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::dma::NoDma; 9use embassy_stm32::dma::NoDma;
10use embassy_stm32::interrupt;
10use embassy_stm32::usart::{Config, Uart}; 11use embassy_stm32::usart::{Config, Uart};
11use heapless::String; 12use heapless::String;
12use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
@@ -17,7 +18,8 @@ async fn main(_spawner: Spawner) {
17 info!("Hello World!"); 18 info!("Hello World!");
18 19
19 let config = Config::default(); 20 let config = Config::default();
20 let mut usart = Uart::new(p.USART1, p.PE1, p.PE0, p.DMA1_CH4, NoDma, config); 21 let irq = interrupt::take!(USART1);
22 let mut usart = Uart::new(p.USART1, p.PE1, p.PE0, irq, p.DMA1_CH4, NoDma, config);
21 23
22 for n in 0u32.. { 24 for n in 0u32.. {
23 let mut s: String<128> = String::new(); 25 let mut s: String<128> = String::new();
diff --git a/examples/stm32f4/src/bin/usart.rs b/examples/stm32f4/src/bin/usart.rs
index 90ad882b8..8f41bb6c4 100644
--- a/examples/stm32f4/src/bin/usart.rs
+++ b/examples/stm32f4/src/bin/usart.rs
@@ -5,6 +5,7 @@
5use cortex_m_rt::entry; 5use cortex_m_rt::entry;
6use defmt::*; 6use defmt::*;
7use embassy_stm32::dma::NoDma; 7use embassy_stm32::dma::NoDma;
8use embassy_stm32::interrupt;
8use embassy_stm32::usart::{Config, Uart}; 9use embassy_stm32::usart::{Config, Uart};
9use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
10 11
@@ -15,7 +16,8 @@ fn main() -> ! {
15 let p = embassy_stm32::init(Default::default()); 16 let p = embassy_stm32::init(Default::default());
16 17
17 let config = Config::default(); 18 let config = Config::default();
18 let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, NoDma, NoDma, config); 19 let irq = interrupt::take!(USART3);
20 let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, irq, NoDma, NoDma, config);
19 21
20 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); 22 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
21 info!("wrote Hello, starting echo"); 23 info!("wrote Hello, starting echo");
diff --git a/examples/stm32f4/src/bin/usart_buffered.rs b/examples/stm32f4/src/bin/usart_buffered.rs
index 7bcecbd26..dd171fe13 100644
--- a/examples/stm32f4/src/bin/usart_buffered.rs
+++ b/examples/stm32f4/src/bin/usart_buffered.rs
@@ -4,9 +4,8 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::dma::NoDma;
8use embassy_stm32::interrupt; 7use embassy_stm32::interrupt;
9use embassy_stm32::usart::{BufferedUart, Config, State, Uart}; 8use embassy_stm32::usart::{BufferedUart, Config, State};
10use embedded_io::asynch::BufRead; 9use embedded_io::asynch::BufRead;
11use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
12 11
@@ -16,13 +15,21 @@ async fn main(_spawner: Spawner) {
16 info!("Hello World!"); 15 info!("Hello World!");
17 16
18 let config = Config::default(); 17 let config = Config::default();
19 let usart = Uart::new(p.USART3, p.PD9, p.PD8, NoDma, NoDma, config);
20 18
21 let mut state = State::new(); 19 let mut state = State::new();
22 let irq = interrupt::take!(USART3); 20 let irq = interrupt::take!(USART3);
23 let mut tx_buf = [0u8; 32]; 21 let mut tx_buf = [0u8; 32];
24 let mut rx_buf = [0u8; 32]; 22 let mut rx_buf = [0u8; 32];
25 let mut buf_usart = BufferedUart::new(&mut state, usart, irq, &mut tx_buf, &mut rx_buf); 23 let mut buf_usart = BufferedUart::new(
24 &mut state,
25 p.USART3,
26 p.PD9,
27 p.PD8,
28 irq,
29 &mut tx_buf,
30 &mut rx_buf,
31 config,
32 );
26 33
27 loop { 34 loop {
28 let buf = buf_usart.fill_buf().await.unwrap(); 35 let buf = buf_usart.fill_buf().await.unwrap();
diff --git a/examples/stm32f4/src/bin/usart_dma.rs b/examples/stm32f4/src/bin/usart_dma.rs
index bb41b8b4f..78baeaa0d 100644
--- a/examples/stm32f4/src/bin/usart_dma.rs
+++ b/examples/stm32f4/src/bin/usart_dma.rs
@@ -7,6 +7,7 @@ use core::fmt::Write;
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::dma::NoDma; 9use embassy_stm32::dma::NoDma;
10use embassy_stm32::interrupt;
10use embassy_stm32::usart::{Config, Uart}; 11use embassy_stm32::usart::{Config, Uart};
11use heapless::String; 12use heapless::String;
12use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
@@ -17,7 +18,8 @@ async fn main(_spawner: Spawner) {
17 info!("Hello World!"); 18 info!("Hello World!");
18 19
19 let config = Config::default(); 20 let config = Config::default();
20 let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, p.DMA1_CH3, NoDma, config); 21 let irq = interrupt::take!(USART3);
22 let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, irq, p.DMA1_CH3, NoDma, config);
21 23
22 for n in 0u32.. { 24 for n in 0u32.. {
23 let mut s: String<128> = String::new(); 25 let mut s: String<128> = String::new();
diff --git a/examples/stm32f7/src/bin/usart_dma.rs b/examples/stm32f7/src/bin/usart_dma.rs
index 07270479c..4827c52ae 100644
--- a/examples/stm32f7/src/bin/usart_dma.rs
+++ b/examples/stm32f7/src/bin/usart_dma.rs
@@ -7,6 +7,7 @@ use core::fmt::Write;
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::dma::NoDma; 9use embassy_stm32::dma::NoDma;
10use embassy_stm32::interrupt;
10use embassy_stm32::usart::{Config, Uart}; 11use embassy_stm32::usart::{Config, Uart};
11use heapless::String; 12use heapless::String;
12use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
@@ -15,7 +16,8 @@ use {defmt_rtt as _, panic_probe as _};
15async fn main(_spawner: Spawner) { 16async fn main(_spawner: Spawner) {
16 let p = embassy_stm32::init(Default::default()); 17 let p = embassy_stm32::init(Default::default());
17 let config = Config::default(); 18 let config = Config::default();
18 let mut usart = Uart::new(p.UART7, p.PA8, p.PA15, p.DMA1_CH1, NoDma, config); 19 let irq = interrupt::take!(UART7);
20 let mut usart = Uart::new(p.UART7, p.PA8, p.PA15, irq, p.DMA1_CH1, NoDma, config);
19 21
20 for n in 0u32.. { 22 for n in 0u32.. {
21 let mut s: String<128> = String::new(); 23 let mut s: String<128> = String::new();
diff --git a/examples/stm32h7/src/bin/usart.rs b/examples/stm32h7/src/bin/usart.rs
index 87c2b1253..405f18ec7 100644
--- a/examples/stm32h7/src/bin/usart.rs
+++ b/examples/stm32h7/src/bin/usart.rs
@@ -6,6 +6,7 @@ use cortex_m_rt::entry;
6use defmt::*; 6use defmt::*;
7use embassy_executor::Executor; 7use embassy_executor::Executor;
8use embassy_stm32::dma::NoDma; 8use embassy_stm32::dma::NoDma;
9use embassy_stm32::interrupt;
9use embassy_stm32::usart::{Config, Uart}; 10use embassy_stm32::usart::{Config, Uart};
10use static_cell::StaticCell; 11use static_cell::StaticCell;
11use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
@@ -15,7 +16,8 @@ async fn main_task() {
15 let p = embassy_stm32::init(Default::default()); 16 let p = embassy_stm32::init(Default::default());
16 17
17 let config = Config::default(); 18 let config = Config::default();
18 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, NoDma, NoDma, config); 19 let irq = interrupt::take!(UART7);
20 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, NoDma, NoDma, config);
19 21
20 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); 22 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
21 info!("wrote Hello, starting echo"); 23 info!("wrote Hello, starting echo");
diff --git a/examples/stm32h7/src/bin/usart_dma.rs b/examples/stm32h7/src/bin/usart_dma.rs
index 3adffcbeb..6e3491e55 100644
--- a/examples/stm32h7/src/bin/usart_dma.rs
+++ b/examples/stm32h7/src/bin/usart_dma.rs
@@ -8,6 +8,7 @@ use cortex_m_rt::entry;
8use defmt::*; 8use defmt::*;
9use embassy_executor::Executor; 9use embassy_executor::Executor;
10use embassy_stm32::dma::NoDma; 10use embassy_stm32::dma::NoDma;
11use embassy_stm32::interrupt;
11use embassy_stm32::usart::{Config, Uart}; 12use embassy_stm32::usart::{Config, Uart};
12use heapless::String; 13use heapless::String;
13use static_cell::StaticCell; 14use static_cell::StaticCell;
@@ -18,7 +19,8 @@ async fn main_task() {
18 let p = embassy_stm32::init(Default::default()); 19 let p = embassy_stm32::init(Default::default());
19 20
20 let config = Config::default(); 21 let config = Config::default();
21 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, p.DMA1_CH0, NoDma, config); 22 let irq = interrupt::take!(UART7);
23 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, p.DMA1_CH0, NoDma, config);
22 24
23 for n in 0u32.. { 25 for n in 0u32.. {
24 let mut s: String<128> = String::new(); 26 let mut s: String<128> = String::new();
diff --git a/examples/stm32h7/src/bin/usart_split.rs b/examples/stm32h7/src/bin/usart_split.rs
index df2b600f8..f97176ecb 100644
--- a/examples/stm32h7/src/bin/usart_split.rs
+++ b/examples/stm32h7/src/bin/usart_split.rs
@@ -5,6 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::dma::NoDma; 7use embassy_stm32::dma::NoDma;
8use embassy_stm32::interrupt;
8use embassy_stm32::peripherals::{DMA1_CH1, UART7}; 9use embassy_stm32::peripherals::{DMA1_CH1, UART7};
9use embassy_stm32::usart::{Config, Uart, UartRx}; 10use embassy_stm32::usart::{Config, Uart, UartRx};
10use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; 11use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
@@ -31,7 +32,8 @@ async fn main(spawner: Spawner) -> ! {
31 info!("Hello World!"); 32 info!("Hello World!");
32 33
33 let config = Config::default(); 34 let config = Config::default();
34 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, p.DMA1_CH0, p.DMA1_CH1, config); 35 let irq = interrupt::take!(UART7);
36 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, p.DMA1_CH0, p.DMA1_CH1, config);
35 unwrap!(usart.blocking_write(b"Type 8 chars to echo!\r\n")); 37 unwrap!(usart.blocking_write(b"Type 8 chars to echo!\r\n"));
36 38
37 let (mut tx, rx) = usart.split(); 39 let (mut tx, rx) = usart.split();
diff --git a/examples/stm32l0/src/bin/usart_dma.rs b/examples/stm32l0/src/bin/usart_dma.rs
index 66657d0f0..c307f857a 100644
--- a/examples/stm32l0/src/bin/usart_dma.rs
+++ b/examples/stm32l0/src/bin/usart_dma.rs
@@ -4,13 +4,15 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::interrupt;
7use embassy_stm32::usart::{Config, Uart}; 8use embassy_stm32::usart::{Config, Uart};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
10#[embassy_executor::main] 11#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 12async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 13 let p = embassy_stm32::init(Default::default());
13 let mut usart = Uart::new(p.USART1, p.PB7, p.PB6, p.DMA1_CH2, p.DMA1_CH3, Config::default()); 14 let irq = interrupt::take!(USART1);
15 let mut usart = Uart::new(p.USART1, p.PB7, p.PB6, irq, p.DMA1_CH2, p.DMA1_CH3, Config::default());
14 16
15 usart.write(b"Hello Embassy World!\r\n").await.unwrap(); 17 usart.write(b"Hello Embassy World!\r\n").await.unwrap();
16 info!("wrote Hello, starting echo"); 18 info!("wrote Hello, starting echo");
diff --git a/examples/stm32l0/src/bin/usart_irq.rs b/examples/stm32l0/src/bin/usart_irq.rs
index 0e2237388..8e84cd092 100644
--- a/examples/stm32l0/src/bin/usart_irq.rs
+++ b/examples/stm32l0/src/bin/usart_irq.rs
@@ -4,9 +4,8 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::dma::NoDma;
8use embassy_stm32::interrupt; 7use embassy_stm32::interrupt;
9use embassy_stm32::usart::{BufferedUart, Config, State, Uart}; 8use embassy_stm32::usart::{BufferedUart, Config, State};
10use embedded_io::asynch::{Read, Write}; 9use embedded_io::asynch::{Read, Write};
11use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
12 11
@@ -21,15 +20,18 @@ async fn main(_spawner: Spawner) {
21 let mut config = Config::default(); 20 let mut config = Config::default();
22 config.baudrate = 9600; 21 config.baudrate = 9600;
23 22
24 let usart = Uart::new(p.USART2, p.PA3, p.PA2, NoDma, NoDma, config);
25 let mut state = State::new(); 23 let mut state = State::new();
24 let irq = interrupt::take!(USART2);
26 let mut usart = unsafe { 25 let mut usart = unsafe {
27 BufferedUart::new( 26 BufferedUart::new(
28 &mut state, 27 &mut state,
29 usart, 28 p.USART2,
30 interrupt::take!(USART2), 29 p.PA3,
30 p.PA2,
31 irq,
31 &mut TX_BUFFER, 32 &mut TX_BUFFER,
32 &mut RX_BUFFER, 33 &mut RX_BUFFER,
34 config,
33 ) 35 )
34 }; 36 };
35 37
diff --git a/examples/stm32l4/src/bin/usart.rs b/examples/stm32l4/src/bin/usart.rs
index 4a4b46c53..7d874d9d7 100644
--- a/examples/stm32l4/src/bin/usart.rs
+++ b/examples/stm32l4/src/bin/usart.rs
@@ -4,6 +4,7 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_stm32::dma::NoDma; 6use embassy_stm32::dma::NoDma;
7use embassy_stm32::interrupt;
7use embassy_stm32::usart::{Config, Uart}; 8use embassy_stm32::usart::{Config, Uart};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
@@ -14,7 +15,8 @@ fn main() -> ! {
14 let p = embassy_stm32::init(Default::default()); 15 let p = embassy_stm32::init(Default::default());
15 16
16 let config = Config::default(); 17 let config = Config::default();
17 let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, NoDma, NoDma, config); 18 let irq = interrupt::take!(UART4);
19 let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, irq, NoDma, NoDma, config);
18 20
19 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); 21 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
20 info!("wrote Hello, starting echo"); 22 info!("wrote Hello, starting echo");
diff --git a/examples/stm32l4/src/bin/usart_dma.rs b/examples/stm32l4/src/bin/usart_dma.rs
index 728906897..452bede30 100644
--- a/examples/stm32l4/src/bin/usart_dma.rs
+++ b/examples/stm32l4/src/bin/usart_dma.rs
@@ -7,6 +7,7 @@ use core::fmt::Write;
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::dma::NoDma; 9use embassy_stm32::dma::NoDma;
10use embassy_stm32::interrupt;
10use embassy_stm32::usart::{Config, Uart}; 11use embassy_stm32::usart::{Config, Uart};
11use heapless::String; 12use heapless::String;
12use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
@@ -17,7 +18,8 @@ async fn main(_spawner: Spawner) {
17 info!("Hello World!"); 18 info!("Hello World!");
18 19
19 let config = Config::default(); 20 let config = Config::default();
20 let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, p.DMA1_CH3, NoDma, config); 21 let irq = interrupt::take!(UART4);
22 let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, irq, p.DMA1_CH3, NoDma, config);
21 23
22 for n in 0u32.. { 24 for n in 0u32.. {
23 let mut s: String<128> = String::new(); 25 let mut s: String<128> = String::new();
diff --git a/tests/stm32/src/bin/usart.rs b/tests/stm32/src/bin/usart.rs
index 7673bfe6d..af55867f2 100644
--- a/tests/stm32/src/bin/usart.rs
+++ b/tests/stm32/src/bin/usart.rs
@@ -7,6 +7,7 @@ mod example_common;
7use defmt::assert_eq; 7use defmt::assert_eq;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::dma::NoDma; 9use embassy_stm32::dma::NoDma;
10use embassy_stm32::interrupt;
10use embassy_stm32::usart::{Config, Uart}; 11use embassy_stm32::usart::{Config, Uart};
11use example_common::*; 12use example_common::*;
12 13
@@ -18,22 +19,22 @@ async fn main(_spawner: Spawner) {
18 // Arduino pins D0 and D1 19 // Arduino pins D0 and D1
19 // They're connected together with a 1K resistor. 20 // They're connected together with a 1K resistor.
20 #[cfg(feature = "stm32f103c8")] 21 #[cfg(feature = "stm32f103c8")]
21 let (tx, rx, usart) = (p.PA9, p.PA10, p.USART1); 22 let (tx, rx, usart, irq) = (p.PA9, p.PA10, p.USART1, interrupt::take!(USART1));
22 #[cfg(feature = "stm32g491re")] 23 #[cfg(feature = "stm32g491re")]
23 let (tx, rx, usart) = (p.PC4, p.PC5, p.USART1); 24 let (tx, rx, usart, irq) = (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1));
24 #[cfg(feature = "stm32g071rb")] 25 #[cfg(feature = "stm32g071rb")]
25 let (tx, rx, usart) = (p.PC4, p.PC5, p.USART1); 26 let (tx, rx, usart, irq) = (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1));
26 #[cfg(feature = "stm32f429zi")] 27 #[cfg(feature = "stm32f429zi")]
27 let (tx, rx, usart) = (p.PG14, p.PG9, p.USART6); 28 let (tx, rx, usart, irq) = (p.PG14, p.PG9, p.USART6, interrupt::take!(USART6));
28 #[cfg(feature = "stm32wb55rg")] 29 #[cfg(feature = "stm32wb55rg")]
29 let (tx, rx, usart) = (p.PA2, p.PA3, p.LPUART1); 30 let (tx, rx, usart, irq) = (p.PA2, p.PA3, p.LPUART1, interrupt::take!(LPUART1));
30 #[cfg(feature = "stm32h755zi")] 31 #[cfg(feature = "stm32h755zi")]
31 let (tx, rx, usart) = (p.PB6, p.PB7, p.USART1); 32 let (tx, rx, usart, irq) = (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1));
32 #[cfg(feature = "stm32u585ai")] 33 #[cfg(feature = "stm32u585ai")]
33 let (tx, rx, usart) = (p.PD8, p.PD9, p.USART3); 34 let (tx, rx, usart, irq) = (p.PD8, p.PD9, p.USART3, interrupt::take!(USART3));
34 35
35 let config = Config::default(); 36 let config = Config::default();
36 let mut usart = Uart::new(usart, rx, tx, NoDma, NoDma, config); 37 let mut usart = Uart::new(usart, rx, tx, irq, NoDma, NoDma, config);
37 38
38 // We can't send too many bytes, they have to fit in the FIFO. 39 // We can't send too many bytes, they have to fit in the FIFO.
39 // This is because we aren't sending+receiving at the same time. 40 // This is because we aren't sending+receiving at the same time.
diff --git a/tests/stm32/src/bin/usart_dma.rs b/tests/stm32/src/bin/usart_dma.rs
index e0389446f..d12605a9a 100644
--- a/tests/stm32/src/bin/usart_dma.rs
+++ b/tests/stm32/src/bin/usart_dma.rs
@@ -6,6 +6,7 @@
6mod example_common; 6mod example_common;
7use defmt::assert_eq; 7use defmt::assert_eq;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::interrupt;
9use embassy_stm32::usart::{Config, Uart}; 10use embassy_stm32::usart::{Config, Uart};
10use example_common::*; 11use example_common::*;
11 12
@@ -17,22 +18,53 @@ async fn main(_spawner: Spawner) {
17 // Arduino pins D0 and D1 18 // Arduino pins D0 and D1
18 // They're connected together with a 1K resistor. 19 // They're connected together with a 1K resistor.
19 #[cfg(feature = "stm32f103c8")] 20 #[cfg(feature = "stm32f103c8")]
20 let (tx, rx, usart, tx_dma, rx_dma) = (p.PA9, p.PA10, p.USART1, p.DMA1_CH4, p.DMA1_CH5); 21 let (tx, rx, usart, irq, tx_dma, rx_dma) = (
22 p.PA9,
23 p.PA10,
24 p.USART1,
25 interrupt::take!(USART1),
26 p.DMA1_CH4,
27 p.DMA1_CH5,
28 );
21 #[cfg(feature = "stm32g491re")] 29 #[cfg(feature = "stm32g491re")]
22 let (tx, rx, usart, tx_dma, rx_dma) = (p.PC4, p.PC5, p.USART1, p.DMA1_CH1, p.DMA1_CH2); 30 let (tx, rx, usart, irq, tx_dma, rx_dma) =
31 (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1), p.DMA1_CH1, p.DMA1_CH2);
23 #[cfg(feature = "stm32g071rb")] 32 #[cfg(feature = "stm32g071rb")]
24 let (tx, rx, usart, tx_dma, rx_dma) = (p.PC4, p.PC5, p.USART1, p.DMA1_CH1, p.DMA1_CH2); 33 let (tx, rx, usart, irq, tx_dma, rx_dma) =
34 (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1), p.DMA1_CH1, p.DMA1_CH2);
25 #[cfg(feature = "stm32f429zi")] 35 #[cfg(feature = "stm32f429zi")]
26 let (tx, rx, usart, tx_dma, rx_dma) = (p.PG14, p.PG9, p.USART6, p.DMA2_CH6, p.DMA2_CH1); 36 let (tx, rx, usart, irq, tx_dma, rx_dma) = (
37 p.PG14,
38 p.PG9,
39 p.USART6,
40 interrupt::take!(USART6),
41 p.DMA2_CH6,
42 p.DMA2_CH1,
43 );
27 #[cfg(feature = "stm32wb55rg")] 44 #[cfg(feature = "stm32wb55rg")]
28 let (tx, rx, usart, tx_dma, rx_dma) = (p.PA2, p.PA3, p.LPUART1, p.DMA1_CH1, p.DMA1_CH2); 45 let (tx, rx, usart, irq, tx_dma, rx_dma) = (
46 p.PA2,
47 p.PA3,
48 p.LPUART1,
49 interrupt::take!(LPUART1),
50 p.DMA1_CH1,
51 p.DMA1_CH2,
52 );
29 #[cfg(feature = "stm32h755zi")] 53 #[cfg(feature = "stm32h755zi")]
30 let (tx, rx, usart, tx_dma, rx_dma) = (p.PB6, p.PB7, p.USART1, p.DMA1_CH0, p.DMA1_CH1); 54 let (tx, rx, usart, irq, tx_dma, rx_dma) =
55 (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1), p.DMA1_CH0, p.DMA1_CH1);
31 #[cfg(feature = "stm32u585ai")] 56 #[cfg(feature = "stm32u585ai")]
32 let (tx, rx, usart, tx_dma, rx_dma) = (p.PD8, p.PD9, p.USART3, p.GPDMA1_CH0, p.GPDMA1_CH1); 57 let (tx, rx, usart, irq, tx_dma, rx_dma) = (
58 p.PD8,
59 p.PD9,
60 p.USART3,
61 interrupt::take!(USART3),
62 p.GPDMA1_CH0,
63 p.GPDMA1_CH1,
64 );
33 65
34 let config = Config::default(); 66 let config = Config::default();
35 let mut usart = Uart::new(usart, rx, tx, tx_dma, rx_dma, config); 67 let mut usart = Uart::new(usart, rx, tx, irq, tx_dma, rx_dma, config);
36 68
37 // We can't send too many bytes, they have to fit in the FIFO. 69 // We can't send too many bytes, they have to fit in the FIFO.
38 // This is because we aren't sending+receiving at the same time. 70 // This is because we aren't sending+receiving at the same time.