aboutsummaryrefslogtreecommitdiff
path: root/embassy-nrf
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-02-21 23:23:04 +0100
committerDario Nieuwenhuis <[email protected]>2024-02-21 23:23:04 +0100
commit2feed96c91e2bd3846452e87b575b3d57ae3cde8 (patch)
tree65209179b4dfa14ae7a5637e23d5d54704225248 /embassy-nrf
parent4fbe18f82134567af4766d161e8385c7dd919a0b (diff)
nrf/uart: Add support for rx-only or tx-only BufferedUart.
Diffstat (limited to 'embassy-nrf')
-rw-r--r--embassy-nrf/src/buffered_uarte.rs361
-rw-r--r--embassy-nrf/src/uarte.rs2
2 files changed, 255 insertions, 108 deletions
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs
index 18416483f..b04c96e09 100644
--- a/embassy-nrf/src/buffered_uarte.rs
+++ b/embassy-nrf/src/buffered_uarte.rs
@@ -27,7 +27,7 @@ use crate::ppi::{
27 self, AnyConfigurableChannel, AnyGroup, Channel, ConfigurableChannel, Event, Group, Ppi, PpiGroup, Task, 27 self, AnyConfigurableChannel, AnyGroup, Channel, ConfigurableChannel, Event, Group, Ppi, PpiGroup, Task,
28}; 28};
29use crate::timer::{Instance as TimerInstance, Timer}; 29use crate::timer::{Instance as TimerInstance, Timer};
30use crate::uarte::{apply_workaround_for_enable_anomaly, drop_tx_rx, Config, Instance as UarteInstance}; 30use crate::uarte::{configure, drop_tx_rx, Config, Instance as UarteInstance};
31use crate::{interrupt, pac, Peripheral}; 31use crate::{interrupt, pac, Peripheral};
32 32
33mod sealed { 33mod sealed {
@@ -238,7 +238,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
238 rx_buffer: &'d mut [u8], 238 rx_buffer: &'d mut [u8],
239 tx_buffer: &'d mut [u8], 239 tx_buffer: &'d mut [u8],
240 ) -> Self { 240 ) -> Self {
241 into_ref!(rxd, txd, ppi_ch1, ppi_ch2, ppi_group); 241 into_ref!(uarte, timer, rxd, txd, ppi_ch1, ppi_ch2, ppi_group);
242 Self::new_inner( 242 Self::new_inner(
243 uarte, 243 uarte,
244 timer, 244 timer,
@@ -275,7 +275,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
275 rx_buffer: &'d mut [u8], 275 rx_buffer: &'d mut [u8],
276 tx_buffer: &'d mut [u8], 276 tx_buffer: &'d mut [u8],
277 ) -> Self { 277 ) -> Self {
278 into_ref!(rxd, txd, cts, rts, ppi_ch1, ppi_ch2, ppi_group); 278 into_ref!(uarte, timer, rxd, txd, cts, rts, ppi_ch1, ppi_ch2, ppi_group);
279 Self::new_inner( 279 Self::new_inner(
280 uarte, 280 uarte,
281 timer, 281 timer,
@@ -293,8 +293,8 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
293 } 293 }
294 294
295 fn new_inner( 295 fn new_inner(
296 peri: impl Peripheral<P = U> + 'd, 296 peri: PeripheralRef<'d, U>,
297 timer: impl Peripheral<P = T> + 'd, 297 timer: PeripheralRef<'d, T>,
298 ppi_ch1: PeripheralRef<'d, AnyConfigurableChannel>, 298 ppi_ch1: PeripheralRef<'d, AnyConfigurableChannel>,
299 ppi_ch2: PeripheralRef<'d, AnyConfigurableChannel>, 299 ppi_ch2: PeripheralRef<'d, AnyConfigurableChannel>,
300 ppi_group: PeripheralRef<'d, AnyGroup>, 300 ppi_group: PeripheralRef<'d, AnyGroup>,
@@ -306,114 +306,17 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
306 rx_buffer: &'d mut [u8], 306 rx_buffer: &'d mut [u8],
307 tx_buffer: &'d mut [u8], 307 tx_buffer: &'d mut [u8],
308 ) -> Self { 308 ) -> Self {
309 into_ref!(peri, timer); 309 configure(U::regs(), config, cts.is_some());
310
311 assert!(rx_buffer.len() % 2 == 0);
312
313 let r = U::regs();
314
315 let hwfc = cts.is_some();
316
317 rxd.conf().write(|w| w.input().connect().drive().h0h1());
318 r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) });
319
320 txd.set_high();
321 txd.conf().write(|w| w.dir().output().drive().h0h1());
322 r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) });
323
324 if let Some(pin) = &cts {
325 pin.conf().write(|w| w.input().connect().drive().h0h1());
326 }
327 r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) });
328
329 if let Some(pin) = &rts {
330 pin.set_high();
331 pin.conf().write(|w| w.dir().output().drive().h0h1());
332 }
333 r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) });
334
335 // Initialize state
336 let s = U::buffered_state();
337 s.tx_count.store(0, Ordering::Relaxed);
338 s.rx_started_count.store(0, Ordering::Relaxed);
339 s.rx_ended_count.store(0, Ordering::Relaxed);
340 s.rx_started.store(false, Ordering::Relaxed);
341 let len = tx_buffer.len();
342 unsafe { s.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
343 let len = rx_buffer.len();
344 unsafe { s.rx_buf.init(rx_buffer.as_mut_ptr(), len) };
345
346 // Configure
347 r.config.write(|w| {
348 w.hwfc().bit(hwfc);
349 w.parity().variant(config.parity);
350 w
351 });
352 r.baudrate.write(|w| w.baudrate().variant(config.baudrate));
353
354 // clear errors
355 let errors = r.errorsrc.read().bits();
356 r.errorsrc.write(|w| unsafe { w.bits(errors) });
357
358 r.events_rxstarted.reset();
359 r.events_txstarted.reset();
360 r.events_error.reset();
361 r.events_endrx.reset();
362 r.events_endtx.reset();
363
364 // Enable interrupts
365 r.intenclr.write(|w| unsafe { w.bits(!0) });
366 r.intenset.write(|w| {
367 w.endtx().set();
368 w.rxstarted().set();
369 w.error().set();
370 w.endrx().set();
371 w
372 });
373 310
374 // Enable UARTE instance 311 let tx = BufferedUarteTx::new_innerer(unsafe { peri.clone_unchecked() }, txd, cts, tx_buffer);
375 apply_workaround_for_enable_anomaly(r); 312 let rx = BufferedUarteRx::new_innerer(peri, timer, ppi_ch1, ppi_ch2, ppi_group, rxd, rts, rx_buffer);
376 r.enable.write(|w| w.enable().enabled());
377
378 // Configure byte counter.
379 let timer = Timer::new_counter(timer);
380 timer.cc(1).write(rx_buffer.len() as u32 * 2);
381 timer.cc(1).short_compare_clear();
382 timer.clear();
383 timer.start();
384
385 let mut ppi_ch1 = Ppi::new_one_to_one(ppi_ch1, Event::from_reg(&r.events_rxdrdy), timer.task_count());
386 ppi_ch1.enable();
387
388 s.rx_ppi_ch.store(ppi_ch2.number() as u8, Ordering::Relaxed);
389 let mut ppi_group = PpiGroup::new(ppi_group);
390 let mut ppi_ch2 = Ppi::new_one_to_two(
391 ppi_ch2,
392 Event::from_reg(&r.events_endrx),
393 Task::from_reg(&r.tasks_startrx),
394 ppi_group.task_disable_all(),
395 );
396 ppi_ch2.disable();
397 ppi_group.add_channel(&ppi_ch2);
398 313
399 U::Interrupt::pend(); 314 U::Interrupt::pend();
400 unsafe { U::Interrupt::enable() }; 315 unsafe { U::Interrupt::enable() };
401 316
402 let s = U::state(); 317 U::state().tx_rx_refcount.store(2, Ordering::Relaxed);
403 s.tx_rx_refcount.store(2, Ordering::Relaxed);
404 318
405 Self { 319 Self { tx, rx }
406 tx: BufferedUarteTx {
407 _peri: unsafe { peri.clone_unchecked() },
408 },
409 rx: BufferedUarteRx {
410 _peri: peri,
411 timer,
412 _ppi_ch1: ppi_ch1,
413 _ppi_ch2: ppi_ch2,
414 _ppi_group: ppi_group,
415 },
416 }
417 } 320 }
418 321
419 /// Adjust the baud rate to the provided value. 322 /// Adjust the baud rate to the provided value.
@@ -469,6 +372,88 @@ pub struct BufferedUarteTx<'d, U: UarteInstance> {
469} 372}
470 373
471impl<'d, U: UarteInstance> BufferedUarteTx<'d, U> { 374impl<'d, U: UarteInstance> BufferedUarteTx<'d, U> {
375 /// Create a new BufferedUarteTx without hardware flow control.
376 pub fn new(
377 uarte: impl Peripheral<P = U> + 'd,
378 _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
379 txd: impl Peripheral<P = impl GpioPin> + 'd,
380 config: Config,
381 tx_buffer: &'d mut [u8],
382 ) -> Self {
383 into_ref!(uarte, txd);
384 Self::new_inner(uarte, txd.map_into(), None, config, tx_buffer)
385 }
386
387 /// Create a new BufferedUarte with hardware flow control (RTS/CTS)
388 ///
389 /// # Panics
390 ///
391 /// Panics if `rx_buffer.len()` is odd.
392 pub fn new_with_cts(
393 uarte: impl Peripheral<P = U> + 'd,
394 _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
395 txd: impl Peripheral<P = impl GpioPin> + 'd,
396 cts: impl Peripheral<P = impl GpioPin> + 'd,
397 config: Config,
398 tx_buffer: &'d mut [u8],
399 ) -> Self {
400 into_ref!(uarte, txd, cts);
401 Self::new_inner(uarte, txd.map_into(), Some(cts.map_into()), config, tx_buffer)
402 }
403
404 fn new_inner(
405 peri: PeripheralRef<'d, U>,
406 txd: PeripheralRef<'d, AnyPin>,
407 cts: Option<PeripheralRef<'d, AnyPin>>,
408 config: Config,
409 tx_buffer: &'d mut [u8],
410 ) -> Self {
411 configure(U::regs(), config, cts.is_some());
412
413 let this = Self::new_innerer(peri, txd, cts, tx_buffer);
414
415 U::Interrupt::pend();
416 unsafe { U::Interrupt::enable() };
417
418 U::state().tx_rx_refcount.store(1, Ordering::Relaxed);
419
420 this
421 }
422
423 fn new_innerer(
424 peri: PeripheralRef<'d, U>,
425 txd: PeripheralRef<'d, AnyPin>,
426 cts: Option<PeripheralRef<'d, AnyPin>>,
427 tx_buffer: &'d mut [u8],
428 ) -> Self {
429 let r = U::regs();
430
431 txd.set_high();
432 txd.conf().write(|w| w.dir().output().drive().h0h1());
433 r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) });
434
435 if let Some(pin) = &cts {
436 pin.conf().write(|w| w.input().connect().drive().h0h1());
437 }
438 r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) });
439
440 // Initialize state
441 let s = U::buffered_state();
442 s.tx_count.store(0, Ordering::Relaxed);
443 let len = tx_buffer.len();
444 unsafe { s.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
445
446 r.events_txstarted.reset();
447
448 // Enable interrupts
449 r.intenset.write(|w| {
450 w.endtx().set();
451 w
452 });
453
454 Self { _peri: peri }
455 }
456
472 /// Write a buffer into this writer, returning how many bytes were written. 457 /// Write a buffer into this writer, returning how many bytes were written.
473 pub async fn write(&mut self, buf: &[u8]) -> Result<usize, Error> { 458 pub async fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
474 poll_fn(move |cx| { 459 poll_fn(move |cx| {
@@ -548,6 +533,168 @@ pub struct BufferedUarteRx<'d, U: UarteInstance, T: TimerInstance> {
548} 533}
549 534
550impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'d, U, T> { 535impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'d, U, T> {
536 /// Create a new BufferedUarte without hardware flow control.
537 ///
538 /// # Panics
539 ///
540 /// Panics if `rx_buffer.len()` is odd.
541 pub fn new(
542 uarte: impl Peripheral<P = U> + 'd,
543 timer: impl Peripheral<P = T> + 'd,
544 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd,
545 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd,
546 ppi_group: impl Peripheral<P = impl Group> + 'd,
547 _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
548 rxd: impl Peripheral<P = impl GpioPin> + 'd,
549 config: Config,
550 rx_buffer: &'d mut [u8],
551 ) -> Self {
552 into_ref!(uarte, timer, rxd, ppi_ch1, ppi_ch2, ppi_group);
553 Self::new_inner(
554 uarte,
555 timer,
556 ppi_ch1.map_into(),
557 ppi_ch2.map_into(),
558 ppi_group.map_into(),
559 rxd.map_into(),
560 None,
561 config,
562 rx_buffer,
563 )
564 }
565
566 /// Create a new BufferedUarte with hardware flow control (RTS/CTS)
567 ///
568 /// # Panics
569 ///
570 /// Panics if `rx_buffer.len()` is odd.
571 pub fn new_with_rts(
572 uarte: impl Peripheral<P = U> + 'd,
573 timer: impl Peripheral<P = T> + 'd,
574 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd,
575 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd,
576 ppi_group: impl Peripheral<P = impl Group> + 'd,
577 _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
578 rxd: impl Peripheral<P = impl GpioPin> + 'd,
579 rts: impl Peripheral<P = impl GpioPin> + 'd,
580 config: Config,
581 rx_buffer: &'d mut [u8],
582 ) -> Self {
583 into_ref!(uarte, timer, rxd, rts, ppi_ch1, ppi_ch2, ppi_group);
584 Self::new_inner(
585 uarte,
586 timer,
587 ppi_ch1.map_into(),
588 ppi_ch2.map_into(),
589 ppi_group.map_into(),
590 rxd.map_into(),
591 Some(rts.map_into()),
592 config,
593 rx_buffer,
594 )
595 }
596
597 fn new_inner(
598 peri: PeripheralRef<'d, U>,
599 timer: PeripheralRef<'d, T>,
600 ppi_ch1: PeripheralRef<'d, AnyConfigurableChannel>,
601 ppi_ch2: PeripheralRef<'d, AnyConfigurableChannel>,
602 ppi_group: PeripheralRef<'d, AnyGroup>,
603 rxd: PeripheralRef<'d, AnyPin>,
604 rts: Option<PeripheralRef<'d, AnyPin>>,
605 config: Config,
606 rx_buffer: &'d mut [u8],
607 ) -> Self {
608 configure(U::regs(), config, rts.is_some());
609
610 let this = Self::new_innerer(peri, timer, ppi_ch1, ppi_ch2, ppi_group, rxd, rts, rx_buffer);
611
612 U::Interrupt::pend();
613 unsafe { U::Interrupt::enable() };
614
615 U::state().tx_rx_refcount.store(1, Ordering::Relaxed);
616
617 this
618 }
619
620 fn new_innerer(
621 peri: PeripheralRef<'d, U>,
622 timer: PeripheralRef<'d, T>,
623 ppi_ch1: PeripheralRef<'d, AnyConfigurableChannel>,
624 ppi_ch2: PeripheralRef<'d, AnyConfigurableChannel>,
625 ppi_group: PeripheralRef<'d, AnyGroup>,
626 rxd: PeripheralRef<'d, AnyPin>,
627 rts: Option<PeripheralRef<'d, AnyPin>>,
628 rx_buffer: &'d mut [u8],
629 ) -> Self {
630 assert!(rx_buffer.len() % 2 == 0);
631
632 let r = U::regs();
633
634 rxd.conf().write(|w| w.input().connect().drive().h0h1());
635 r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) });
636
637 if let Some(pin) = &rts {
638 pin.set_high();
639 pin.conf().write(|w| w.dir().output().drive().h0h1());
640 }
641 r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) });
642
643 // Initialize state
644 let s = U::buffered_state();
645 s.rx_started_count.store(0, Ordering::Relaxed);
646 s.rx_ended_count.store(0, Ordering::Relaxed);
647 s.rx_started.store(false, Ordering::Relaxed);
648 let len = rx_buffer.len();
649 unsafe { s.rx_buf.init(rx_buffer.as_mut_ptr(), len) };
650
651 // clear errors
652 let errors = r.errorsrc.read().bits();
653 r.errorsrc.write(|w| unsafe { w.bits(errors) });
654
655 r.events_rxstarted.reset();
656 r.events_error.reset();
657 r.events_endrx.reset();
658
659 // Enable interrupts
660 r.intenset.write(|w| {
661 w.endtx().set();
662 w.rxstarted().set();
663 w.error().set();
664 w.endrx().set();
665 w
666 });
667
668 // Configure byte counter.
669 let timer = Timer::new_counter(timer);
670 timer.cc(1).write(rx_buffer.len() as u32 * 2);
671 timer.cc(1).short_compare_clear();
672 timer.clear();
673 timer.start();
674
675 let mut ppi_ch1 = Ppi::new_one_to_one(ppi_ch1, Event::from_reg(&r.events_rxdrdy), timer.task_count());
676 ppi_ch1.enable();
677
678 s.rx_ppi_ch.store(ppi_ch2.number() as u8, Ordering::Relaxed);
679 let mut ppi_group = PpiGroup::new(ppi_group);
680 let mut ppi_ch2 = Ppi::new_one_to_two(
681 ppi_ch2,
682 Event::from_reg(&r.events_endrx),
683 Task::from_reg(&r.tasks_startrx),
684 ppi_group.task_disable_all(),
685 );
686 ppi_ch2.disable();
687 ppi_group.add_channel(&ppi_ch2);
688
689 Self {
690 _peri: peri,
691 timer,
692 _ppi_ch1: ppi_ch1,
693 _ppi_ch2: ppi_ch2,
694 _ppi_group: ppi_group,
695 }
696 }
697
551 /// Pull some bytes from this source into the specified buffer, returning how many bytes were read. 698 /// Pull some bytes from this source into the specified buffer, returning how many bytes were read.
552 pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { 699 pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
553 let data = self.fill_buf().await?; 700 let data = self.fill_buf().await?;
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs
index cd14c718a..7fd34453a 100644
--- a/embassy-nrf/src/uarte.rs
+++ b/embassy-nrf/src/uarte.rs
@@ -299,7 +299,7 @@ impl<'d, T: Instance> Uarte<'d, T> {
299 } 299 }
300} 300}
301 301
302fn configure(r: &RegisterBlock, config: Config, hardware_flow_control: bool) { 302pub(crate) fn configure(r: &RegisterBlock, config: Config, hardware_flow_control: bool) {
303 r.config.write(|w| { 303 r.config.write(|w| {
304 w.hwfc().bit(hardware_flow_control); 304 w.hwfc().bit(hardware_flow_control);
305 w.parity().variant(config.parity); 305 w.parity().variant(config.parity);