Skip to content

Commit ff3defe

Browse files
committed
Implement Drop trait to ensure DMA is stopped
1 parent a45bd6f commit ff3defe

File tree

1 file changed

+65
-2
lines changed

1 file changed

+65
-2
lines changed

nrf-hal-common/src/uarte.rs

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,13 +447,19 @@ mod _uarte1 {
447447
}
448448

449449
/// Interface for the TX part of a UART instance that can be used independently of the RX part.
450-
pub struct UarteTx<'a, T> {
450+
pub struct UarteTx<'a, T>
451+
where
452+
T: Instance,
453+
{
451454
_marker: core::marker::PhantomData<T>,
452455
tx_buf: &'a mut [u8],
453456
}
454457

455458
/// Interface for the RX part of a UART instance that can be used independently of the TX part.
456-
pub struct UarteRx<'a, T> {
459+
pub struct UarteRx<'a, T>
460+
where
461+
T: Instance,
462+
{
457463
_marker: core::marker::PhantomData<T>,
458464
rx_buf: &'a mut [u8],
459465
}
@@ -492,6 +498,63 @@ where
492498
}
493499
}
494500

501+
impl<'a, T> Drop for UarteTx<'a, T>
502+
where
503+
T: Instance,
504+
{
505+
fn drop(&mut self) {
506+
let uarte = unsafe { &*T::ptr() };
507+
508+
let in_progress = uarte.events_txstarted.read().bits() == 1;
509+
// Stop any ongoing transmission
510+
if in_progress {
511+
uarte.tasks_stoptx.write(|w| unsafe { w.bits(1) });
512+
513+
// Wait for transmitter is stopped.
514+
while uarte.events_txstopped.read().bits() == 0 {}
515+
516+
// Reset events
517+
uarte.events_endtx.reset();
518+
uarte.events_txstopped.reset();
519+
520+
// Ensure the above is done
521+
compiler_fence(SeqCst);
522+
}
523+
}
524+
}
525+
526+
impl<'a, T> Drop for UarteRx<'a, T>
527+
where
528+
T: Instance,
529+
{
530+
fn drop(&mut self) {
531+
let uarte = unsafe { &*T::ptr() };
532+
533+
let in_progress = uarte.events_rxstarted.read().bits() == 1;
534+
// Stop any ongoing reception
535+
if in_progress {
536+
uarte.tasks_stoprx.write(|w| unsafe { w.bits(1) });
537+
538+
// Wait for receive to be done to ensure memory is untouched.
539+
while uarte.events_rxto.read().bits() == 0 {}
540+
541+
uarte.events_rxto.reset();
542+
543+
// Flush DMA
544+
uarte.tasks_flushrx.write(|w| unsafe { w.bits(1) });
545+
546+
// Wait for the flush to complete.
547+
while uarte.events_endrx.read().bits() == 0 {}
548+
549+
// Reset events
550+
uarte.events_endrx.reset();
551+
552+
// Ensure the above is done
553+
compiler_fence(SeqCst);
554+
}
555+
}
556+
}
557+
495558
pub mod serial {
496559

497560
///! Implementation of the embedded_hal::serial::* traits for UartTx and UartRx.

0 commit comments

Comments
 (0)