2021-11-30 22:29:45 +00:00
//! Async buffered UART
//!
2021-12-12 06:47:38 +00:00
//! WARNING!!! The functionality provided here is intended to be used only
//! in situations where hardware flow control are available i.e. CTS and RTS.
//! This is a problem that should be addressed at a later stage and can be
2022-06-23 10:59:18 +00:00
//! fully explained at <https://github.com/embassy-rs/embassy/issues/536>.
2021-12-12 06:47:38 +00:00
//!
//! Note that discarding a future from a read or write operation may lead to losing
//! data. For example, when using `futures_util::future::select` and completion occurs
//! on the "other" future, you should capture the incomplete future and continue to use
//! it for the next read or write. This pattern is a consideration for all IO, and not
//! just serial communications.
//!
//! Please also see [crate::uarte] to understand when [BufferedUarte] should be used.
2021-11-30 22:29:45 +00:00
2020-09-22 16:03:43 +00:00
use core ::cmp ::min ;
2022-05-04 18:48:37 +00:00
use core ::future ::Future ;
2020-09-22 16:03:43 +00:00
use core ::sync ::atomic ::{ compiler_fence , Ordering } ;
2022-05-04 18:48:37 +00:00
use core ::task ::Poll ;
2022-06-12 20:15:44 +00:00
2022-06-11 03:08:57 +00:00
use embassy_cortex_m ::peripheral ::{ PeripheralMutex , PeripheralState , StateStorage } ;
2021-07-29 11:44:51 +00:00
use embassy_hal_common ::ring_buffer ::RingBuffer ;
2022-07-29 19:58:35 +00:00
use embassy_hal_common ::{ into_ref , PeripheralRef } ;
2022-08-22 19:46:09 +00:00
use embassy_sync ::waitqueue ::WakerRegistration ;
2022-05-04 18:48:37 +00:00
use futures ::future ::poll_fn ;
2022-06-12 20:15:44 +00:00
// Re-export SVD variants to allow user to directly set values
pub use pac ::uarte0 ::{ baudrate ::BAUDRATE_A as Baudrate , config ::PARITY_A as Parity } ;
2020-09-22 16:03:43 +00:00
2022-02-12 00:04:01 +00:00
use crate ::gpio ::Pin as GpioPin ;
2022-06-12 20:15:44 +00:00
use crate ::interrupt ::InterruptExt ;
2021-10-26 07:45:29 +00:00
use crate ::ppi ::{ AnyConfigurableChannel , ConfigurableChannel , Event , Ppi , Task } ;
2022-06-12 20:15:44 +00:00
use crate ::timer ::{ Frequency , Instance as TimerInstance , Timer } ;
2021-12-08 00:40:12 +00:00
use crate ::uarte ::{ apply_workaround_for_enable_anomaly , Config , Instance as UarteInstance } ;
2022-07-23 12:00:19 +00:00
use crate ::{ pac , Peripheral } ;
2020-09-22 16:03:43 +00:00
#[ derive(Copy, Clone, Debug, PartialEq) ]
enum RxState {
Idle ,
Receiving ,
}
2021-01-05 20:14:04 +00:00
2020-09-22 16:03:43 +00:00
#[ derive(Copy, Clone, Debug, PartialEq) ]
enum TxState {
Idle ,
Transmitting ( usize ) ,
}
2022-08-22 08:36:33 +00:00
/// A type for storing the state of the UARTE peripheral that can be stored in a static.
2021-07-29 12:08:32 +00:00
pub struct State < ' d , U : UarteInstance , T : TimerInstance > ( StateStorage < StateInner < ' d , U , T > > ) ;
impl < ' d , U : UarteInstance , T : TimerInstance > State < ' d , U , T > {
2022-08-22 08:36:33 +00:00
/// Create an instance for storing UARTE peripheral state.
2021-07-29 12:08:32 +00:00
pub fn new ( ) -> Self {
Self ( StateStorage ::new ( ) )
}
}
struct StateInner < ' d , U : UarteInstance , T : TimerInstance > {
2022-07-23 13:13:47 +00:00
_peri : PeripheralRef < ' d , U > ,
2021-09-02 10:02:31 +00:00
timer : Timer < ' d , T > ,
2021-10-26 07:45:29 +00:00
_ppi_ch1 : Ppi < ' d , AnyConfigurableChannel , 1 , 2 > ,
_ppi_ch2 : Ppi < ' d , AnyConfigurableChannel , 1 , 1 > ,
2021-01-05 20:14:04 +00:00
2021-03-28 20:41:45 +00:00
rx : RingBuffer < ' d > ,
2021-01-05 20:14:04 +00:00
rx_state : RxState ,
rx_waker : WakerRegistration ,
2021-03-28 20:41:45 +00:00
tx : RingBuffer < ' d > ,
2021-01-05 20:14:04 +00:00
tx_state : TxState ,
tx_waker : WakerRegistration ,
}
2020-09-22 16:03:43 +00:00
/// Interface to a UARTE instance
2021-03-28 20:41:45 +00:00
pub struct BufferedUarte < ' d , U : UarteInstance , T : TimerInstance > {
2021-07-29 12:08:32 +00:00
inner : PeripheralMutex < ' d , StateInner < ' d , U , T > > ,
2020-09-22 16:03:43 +00:00
}
2021-07-29 12:08:32 +00:00
impl < ' d , U : UarteInstance , T : TimerInstance > Unpin for BufferedUarte < ' d , U , T > { }
2021-03-28 20:41:45 +00:00
impl < ' d , U : UarteInstance , T : TimerInstance > BufferedUarte < ' d , U , T > {
2022-08-22 08:36:33 +00:00
/// Create a new instance of a BufferedUarte.
///
/// See the [module documentation](crate::buffered_uarte) for more details about the intended use.
///
/// The BufferedUarte uses the provided state to store the buffers and peripheral state. The timer and ppi channels are used to 'emulate' idle line detection so that read operations
/// can return early if there is no data to receive.
2021-11-30 22:14:24 +00:00
pub fn new (
2021-07-29 12:08:32 +00:00
state : & ' d mut State < ' d , U , T > ,
2022-07-23 13:13:47 +00:00
peri : impl Peripheral < P = U > + ' d ,
2022-07-23 12:00:19 +00:00
timer : impl Peripheral < P = T > + ' d ,
ppi_ch1 : impl Peripheral < P = impl ConfigurableChannel + ' d > + ' d ,
ppi_ch2 : impl Peripheral < P = impl ConfigurableChannel + ' d > + ' d ,
irq : impl Peripheral < P = U ::Interrupt > + ' d ,
rxd : impl Peripheral < P = impl GpioPin > + ' d ,
txd : impl Peripheral < P = impl GpioPin > + ' d ,
cts : impl Peripheral < P = impl GpioPin > + ' d ,
rts : impl Peripheral < P = impl GpioPin > + ' d ,
2021-03-28 20:41:45 +00:00
config : Config ,
rx_buffer : & ' d mut [ u8 ] ,
tx_buffer : & ' d mut [ u8 ] ,
2021-10-18 14:23:39 +00:00
) -> Self {
2022-07-23 13:13:47 +00:00
into_ref! ( peri , ppi_ch1 , ppi_ch2 , irq , rxd , txd , cts , rts ) ;
2020-09-22 16:03:43 +00:00
2021-04-14 14:01:43 +00:00
let r = U ::regs ( ) ;
2021-06-26 07:58:36 +00:00
2021-09-02 10:02:31 +00:00
let mut timer = Timer ::new ( timer ) ;
2020-09-22 16:03:43 +00:00
2021-03-28 20:41:45 +00:00
rxd . conf ( ) . write ( | w | w . input ( ) . connect ( ) . drive ( ) . h0h1 ( ) ) ;
r . psel . rxd . write ( | w | unsafe { w . bits ( rxd . psel_bits ( ) ) } ) ;
2020-09-22 16:03:43 +00:00
2021-03-28 20:41:45 +00:00
txd . set_high ( ) ;
txd . conf ( ) . write ( | w | w . dir ( ) . output ( ) . drive ( ) . h0h1 ( ) ) ;
r . psel . txd . write ( | w | unsafe { w . bits ( txd . psel_bits ( ) ) } ) ;
2020-09-22 16:03:43 +00:00
2022-02-12 00:04:01 +00:00
cts . conf ( ) . write ( | w | w . input ( ) . connect ( ) . drive ( ) . h0h1 ( ) ) ;
2021-03-28 20:41:45 +00:00
r . psel . cts . write ( | w | unsafe { w . bits ( cts . psel_bits ( ) ) } ) ;
2022-02-12 00:04:01 +00:00
rts . set_high ( ) ;
rts . conf ( ) . write ( | w | w . dir ( ) . output ( ) . drive ( ) . h0h1 ( ) ) ;
2021-03-28 20:41:45 +00:00
r . psel . rts . write ( | w | unsafe { w . bits ( rts . psel_bits ( ) ) } ) ;
r . baudrate . write ( | w | w . baudrate ( ) . variant ( config . baudrate ) ) ;
r . config . write ( | w | w . parity ( ) . variant ( config . parity ) ) ;
2020-09-22 16:03:43 +00:00
// Configure
2021-03-28 20:41:45 +00:00
r . config . write ( | w | {
2022-02-12 00:04:01 +00:00
w . hwfc ( ) . bit ( true ) ;
2021-03-28 20:41:45 +00:00
w . parity ( ) . variant ( config . parity ) ;
w
} ) ;
r . baudrate . write ( | w | w . baudrate ( ) . variant ( config . baudrate ) ) ;
2020-09-22 16:03:43 +00:00
2021-03-28 20:41:45 +00:00
// Enable interrupts
r . intenset . write ( | w | w . endrx ( ) . set ( ) . endtx ( ) . set ( ) ) ;
2020-09-22 16:03:43 +00:00
2021-01-05 00:57:05 +00:00
// Disable the irq, let the Registration enable it when everything is set up.
irq . disable ( ) ;
2021-01-03 00:40:40 +00:00
irq . pend ( ) ;
2021-03-28 20:41:45 +00:00
// Enable UARTE instance
2021-12-08 00:40:12 +00:00
apply_workaround_for_enable_anomaly ( & r ) ;
2021-03-28 20:41:45 +00:00
r . enable . write ( | w | w . enable ( ) . enabled ( ) ) ;
2021-01-06 22:36:46 +00:00
// BAUDRATE register values are `baudrate * 2^32 / 16000000`
// source: https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values
//
// We want to stop RX if line is idle for 2 bytes worth of time
// That is 20 bits (each byte is 1 start bit + 8 data bits + 1 stop bit)
// This gives us the amount of 16M ticks for 20 bits.
2021-03-28 20:41:45 +00:00
let timeout = 0x8000_0000 / ( config . baudrate as u32 / 40 ) ;
2021-06-26 07:58:36 +00:00
timer . set_frequency ( Frequency ::F16MHz ) ;
2021-06-29 00:33:41 +00:00
timer . cc ( 0 ) . write ( timeout ) ;
timer . cc ( 0 ) . short_compare_clear ( ) ;
timer . cc ( 0 ) . short_compare_stop ( ) ;
2021-01-06 22:36:46 +00:00
2021-10-18 14:23:39 +00:00
let mut ppi_ch1 = Ppi ::new_one_to_two (
2022-07-23 12:27:45 +00:00
ppi_ch1 . map_into ( ) ,
2021-10-18 14:23:39 +00:00
Event ::from_reg ( & r . events_rxdrdy ) ,
timer . task_clear ( ) ,
timer . task_start ( ) ,
2021-10-26 07:45:29 +00:00
) ;
2021-03-28 20:41:45 +00:00
ppi_ch1 . enable ( ) ;
2021-01-06 22:36:46 +00:00
2021-10-18 14:23:39 +00:00
let mut ppi_ch2 = Ppi ::new_one_to_one (
2022-07-23 12:27:45 +00:00
ppi_ch2 . map_into ( ) ,
2021-10-18 14:23:39 +00:00
timer . cc ( 0 ) . event_compare ( ) ,
Task ::from_reg ( & r . tasks_stoprx ) ,
2021-10-26 07:45:29 +00:00
) ;
2021-03-28 20:41:45 +00:00
ppi_ch2 . enable ( ) ;
2021-01-06 22:36:46 +00:00
2021-10-18 14:23:39 +00:00
Self {
2022-07-23 12:27:45 +00:00
inner : PeripheralMutex ::new ( irq , & mut state . 0 , move | | StateInner {
2022-07-23 13:13:47 +00:00
_peri : peri ,
2022-06-09 19:28:13 +00:00
timer ,
_ppi_ch1 : ppi_ch1 ,
_ppi_ch2 : ppi_ch2 ,
rx : RingBuffer ::new ( rx_buffer ) ,
rx_state : RxState ::Idle ,
rx_waker : WakerRegistration ::new ( ) ,
tx : RingBuffer ::new ( tx_buffer ) ,
tx_state : TxState ::Idle ,
tx_waker : WakerRegistration ::new ( ) ,
} ) ,
2021-10-18 14:23:39 +00:00
}
2020-09-22 16:03:43 +00:00
}
2021-01-05 20:14:04 +00:00
2022-08-22 08:36:33 +00:00
/// Adjust the baud rate to the provided value.
2021-07-29 12:08:32 +00:00
pub fn set_baudrate ( & mut self , baudrate : Baudrate ) {
self . inner . with ( | state | {
2021-04-14 14:01:43 +00:00
let r = U ::regs ( ) ;
2021-03-28 20:41:45 +00:00
2021-01-11 09:40:37 +00:00
let timeout = 0x8000_0000 / ( baudrate as u32 / 40 ) ;
2021-06-29 00:33:41 +00:00
state . timer . cc ( 0 ) . write ( timeout ) ;
2021-06-26 07:58:36 +00:00
state . timer . clear ( ) ;
2021-01-11 09:40:37 +00:00
2021-03-28 20:41:45 +00:00
r . baudrate . write ( | w | w . baudrate ( ) . variant ( baudrate ) ) ;
2021-01-11 09:40:37 +00:00
} ) ;
}
2020-09-22 16:03:43 +00:00
}
2022-05-04 18:48:37 +00:00
impl < ' d , U : UarteInstance , T : TimerInstance > embedded_io ::Io for BufferedUarte < ' d , U , T > {
type Error = core ::convert ::Infallible ;
}
impl < ' d , U : UarteInstance , T : TimerInstance > embedded_io ::asynch ::Read for BufferedUarte < ' d , U , T > {
type ReadFuture < ' a > = impl Future < Output = Result < usize , Self ::Error > >
where
Self : ' a ;
fn read < ' a > ( & ' a mut self , buf : & ' a mut [ u8 ] ) -> Self ::ReadFuture < ' a > {
poll_fn ( move | cx | {
let mut do_pend = false ;
let res = self . inner . with ( | state | {
compiler_fence ( Ordering ::SeqCst ) ;
trace! ( " poll_read " ) ;
// We have data ready in buffer? Return it.
let data = state . rx . pop_buf ( ) ;
if ! data . is_empty ( ) {
trace! ( " got {:?} {:?} " , data . as_ptr ( ) as u32 , data . len ( ) ) ;
2022-05-14 00:20:40 +00:00
let len = data . len ( ) . min ( buf . len ( ) ) ;
2022-05-04 18:48:37 +00:00
buf [ .. len ] . copy_from_slice ( & data [ .. len ] ) ;
state . rx . pop ( len ) ;
do_pend = true ;
return Poll ::Ready ( Ok ( len ) ) ;
}
trace! ( " empty " ) ;
state . rx_waker . register ( cx . waker ( ) ) ;
Poll ::Pending
} ) ;
if do_pend {
self . inner . pend ( ) ;
2021-01-05 20:14:04 +00:00
}
2022-05-04 18:48:37 +00:00
res
2021-01-03 00:40:40 +00:00
} )
2020-09-22 16:03:43 +00:00
}
}
2022-06-12 20:15:44 +00:00
impl < ' d , U : UarteInstance , T : TimerInstance > embedded_io ::asynch ::BufRead for BufferedUarte < ' d , U , T > {
2022-05-26 20:15:06 +00:00
type FillBufFuture < ' a > = impl Future < Output = Result < & ' a [ u8 ] , Self ::Error > >
where
Self : ' a ;
fn fill_buf < ' a > ( & ' a mut self ) -> Self ::FillBufFuture < ' a > {
poll_fn ( move | cx | {
self . inner . with ( | state | {
compiler_fence ( Ordering ::SeqCst ) ;
trace! ( " fill_buf " ) ;
// We have data ready in buffer? Return it.
let buf = state . rx . pop_buf ( ) ;
if ! buf . is_empty ( ) {
trace! ( " got {:?} {:?} " , buf . as_ptr ( ) as u32 , buf . len ( ) ) ;
let buf : & [ u8 ] = buf ;
// Safety: buffer lives as long as uart
let buf : & [ u8 ] = unsafe { core ::mem ::transmute ( buf ) } ;
return Poll ::Ready ( Ok ( buf ) ) ;
}
trace! ( " empty " ) ;
state . rx_waker . register ( cx . waker ( ) ) ;
Poll ::< Result < & [ u8 ] , Self ::Error > > ::Pending
} )
} )
}
fn consume ( & mut self , amt : usize ) {
let signal = self . inner . with ( | state | {
2022-05-26 20:36:25 +00:00
let full = state . rx . is_full ( ) ;
2022-05-26 20:15:06 +00:00
state . rx . pop ( amt ) ;
2022-05-26 20:36:25 +00:00
full
2022-05-26 20:15:06 +00:00
} ) ;
if signal {
self . inner . pend ( ) ;
}
}
}
2022-06-12 20:15:44 +00:00
impl < ' d , U : UarteInstance , T : TimerInstance > embedded_io ::asynch ::Write for BufferedUarte < ' d , U , T > {
2022-05-04 18:48:37 +00:00
type WriteFuture < ' a > = impl Future < Output = Result < usize , Self ::Error > >
where
Self : ' a ;
2020-09-22 16:03:43 +00:00
2022-05-04 18:48:37 +00:00
fn write < ' a > ( & ' a mut self , buf : & ' a [ u8 ] ) -> Self ::WriteFuture < ' a > {
poll_fn ( move | cx | {
let res = self . inner . with ( | state | {
trace! ( " poll_write: {:?} " , buf . len ( ) ) ;
2020-09-22 16:03:43 +00:00
2022-05-04 18:48:37 +00:00
let tx_buf = state . tx . push_buf ( ) ;
if tx_buf . is_empty ( ) {
trace! ( " poll_write: pending " ) ;
state . tx_waker . register ( cx . waker ( ) ) ;
return Poll ::Pending ;
}
2020-09-22 16:03:43 +00:00
2022-05-04 18:48:37 +00:00
let n = min ( tx_buf . len ( ) , buf . len ( ) ) ;
tx_buf [ .. n ] . copy_from_slice ( & buf [ .. n ] ) ;
state . tx . push ( n ) ;
2020-09-22 16:03:43 +00:00
2022-05-04 18:48:37 +00:00
trace! ( " poll_write: queued {:?} " , n ) ;
compiler_fence ( Ordering ::SeqCst ) ;
2021-07-27 07:28:52 +00:00
2022-05-04 18:48:37 +00:00
Poll ::Ready ( Ok ( n ) )
} ) ;
2021-07-27 07:28:52 +00:00
2022-05-04 18:48:37 +00:00
self . inner . pend ( ) ;
res
} )
2020-09-22 16:03:43 +00:00
}
2021-12-10 01:08:00 +00:00
2022-05-04 18:48:37 +00:00
type FlushFuture < ' a > = impl Future < Output = Result < ( ) , Self ::Error > >
where
Self : ' a ;
2021-12-10 01:08:00 +00:00
2022-05-04 18:48:37 +00:00
fn flush < ' a > ( & ' a mut self ) -> Self ::FlushFuture < ' a > {
poll_fn ( move | cx | {
self . inner . with ( | state | {
trace! ( " poll_flush " ) ;
if ! state . tx . is_empty ( ) {
trace! ( " poll_flush: pending " ) ;
state . tx_waker . register ( cx . waker ( ) ) ;
return Poll ::Pending ;
}
2021-12-10 01:08:00 +00:00
2022-05-04 18:48:37 +00:00
Poll ::Ready ( Ok ( ( ) ) )
} )
2021-12-10 01:08:00 +00:00
} )
}
2021-01-03 00:40:40 +00:00
}
2021-07-29 12:08:32 +00:00
impl < ' a , U : UarteInstance , T : TimerInstance > Drop for StateInner < ' a , U , T > {
2021-03-18 01:01:29 +00:00
fn drop ( & mut self ) {
2021-04-14 14:01:43 +00:00
let r = U ::regs ( ) ;
2021-03-28 20:41:45 +00:00
// TODO this probably deadlocks. do like Uarte instead.
2021-06-26 07:58:36 +00:00
self . timer . stop ( ) ;
2021-01-11 09:39:59 +00:00
if let RxState ::Receiving = self . rx_state {
2021-03-28 20:41:45 +00:00
r . tasks_stoprx . write ( | w | unsafe { w . bits ( 1 ) } ) ;
2021-01-11 09:39:59 +00:00
}
if let TxState ::Transmitting ( _ ) = self . tx_state {
2021-03-28 20:41:45 +00:00
r . tasks_stoptx . write ( | w | unsafe { w . bits ( 1 ) } ) ;
2021-01-11 09:39:59 +00:00
}
if let RxState ::Receiving = self . rx_state {
2021-03-28 20:41:45 +00:00
low_power_wait_until ( | | r . events_endrx . read ( ) . bits ( ) = = 1 ) ;
2021-01-11 09:39:59 +00:00
}
if let TxState ::Transmitting ( _ ) = self . tx_state {
2021-03-28 20:41:45 +00:00
low_power_wait_until ( | | r . events_endtx . read ( ) . bits ( ) = = 1 ) ;
2021-01-11 09:39:59 +00:00
}
}
}
2021-07-29 12:08:32 +00:00
impl < ' a , U : UarteInstance , T : TimerInstance > PeripheralState for StateInner < ' a , U , T > {
2021-01-06 21:48:54 +00:00
type Interrupt = U ::Interrupt ;
2020-09-22 16:03:43 +00:00
fn on_interrupt ( & mut self ) {
trace! ( " irq: start " ) ;
2021-04-14 14:01:43 +00:00
let r = U ::regs ( ) ;
2021-03-28 20:41:45 +00:00
2021-01-06 22:36:46 +00:00
loop {
2020-09-22 16:03:43 +00:00
match self . rx_state {
RxState ::Idle = > {
trace! ( " irq_rx: in state idle " ) ;
let buf = self . rx . push_buf ( ) ;
2021-02-14 00:41:36 +00:00
if ! buf . is_empty ( ) {
2020-09-22 16:03:43 +00:00
trace! ( " irq_rx: starting {:?} " , buf . len ( ) ) ;
self . rx_state = RxState ::Receiving ;
// Set up the DMA read
2021-03-28 20:41:45 +00:00
r . rxd . ptr . write ( | w |
2020-09-22 16:03:43 +00:00
// The PTR field is a full 32 bits wide and accepts the full range
// of values.
unsafe { w . ptr ( ) . bits ( buf . as_ptr ( ) as u32 ) } ) ;
2021-03-28 20:41:45 +00:00
r . rxd . maxcnt . write ( | w |
2020-09-22 16:03:43 +00:00
// We're giving it the length of the buffer, so no danger of
// accessing invalid memory. We have verified that the length of the
// buffer fits in an `u8`, so the cast to `u8` is also fine.
//
// The MAXCNT field is at least 8 bits wide and accepts the full
// range of values.
unsafe { w . maxcnt ( ) . bits ( buf . len ( ) as _ ) } ) ;
trace! ( " irq_rx: buf {:?} {:?} " , buf . as_ptr ( ) as u32 , buf . len ( ) ) ;
// Start UARTE Receive transaction
2022-01-13 22:56:25 +00:00
r . tasks_startrx . write ( | w | unsafe { w . bits ( 1 ) } ) ;
2020-09-22 16:03:43 +00:00
}
2021-01-06 22:36:46 +00:00
break ;
2020-09-22 16:03:43 +00:00
}
RxState ::Receiving = > {
trace! ( " irq_rx: in state receiving " ) ;
2021-03-28 20:41:45 +00:00
if r . events_endrx . read ( ) . bits ( ) ! = 0 {
2021-06-26 07:58:36 +00:00
self . timer . stop ( ) ;
2020-09-22 16:03:43 +00:00
2021-03-28 20:41:45 +00:00
let n : usize = r . rxd . amount . read ( ) . amount ( ) . bits ( ) as usize ;
2020-09-22 16:03:43 +00:00
trace! ( " irq_rx: endrx {:?} " , n ) ;
self . rx . push ( n ) ;
2021-03-28 20:41:45 +00:00
r . events_endrx . reset ( ) ;
2020-09-22 16:03:43 +00:00
self . rx_waker . wake ( ) ;
self . rx_state = RxState ::Idle ;
2021-01-06 22:36:46 +00:00
} else {
break ;
2020-09-22 16:03:43 +00:00
}
}
}
}
2021-01-06 22:36:46 +00:00
loop {
2020-09-22 16:03:43 +00:00
match self . tx_state {
TxState ::Idle = > {
trace! ( " irq_tx: in state Idle " ) ;
let buf = self . tx . pop_buf ( ) ;
2021-02-14 00:41:36 +00:00
if ! buf . is_empty ( ) {
2020-09-22 16:03:43 +00:00
trace! ( " irq_tx: starting {:?} " , buf . len ( ) ) ;
self . tx_state = TxState ::Transmitting ( buf . len ( ) ) ;
// Set up the DMA write
2021-03-28 20:41:45 +00:00
r . txd . ptr . write ( | w |
2020-09-22 16:03:43 +00:00
// The PTR field is a full 32 bits wide and accepts the full range
// of values.
unsafe { w . ptr ( ) . bits ( buf . as_ptr ( ) as u32 ) } ) ;
2021-03-28 20:41:45 +00:00
r . txd . maxcnt . write ( | w |
2020-09-22 16:03:43 +00:00
// We're giving it the length of the buffer, so no danger of
// accessing invalid memory. We have verified that the length of the
// buffer fits in an `u8`, so the cast to `u8` is also fine.
//
// The MAXCNT field is 8 bits wide and accepts the full range of
// values.
unsafe { w . maxcnt ( ) . bits ( buf . len ( ) as _ ) } ) ;
// Start UARTE Transmit transaction
2022-01-13 22:56:25 +00:00
r . tasks_starttx . write ( | w | unsafe { w . bits ( 1 ) } ) ;
2020-09-22 16:03:43 +00:00
}
2021-01-06 22:36:46 +00:00
break ;
2020-09-22 16:03:43 +00:00
}
TxState ::Transmitting ( n ) = > {
trace! ( " irq_tx: in state Transmitting " ) ;
2021-03-28 20:41:45 +00:00
if r . events_endtx . read ( ) . bits ( ) ! = 0 {
r . events_endtx . reset ( ) ;
2020-09-22 16:03:43 +00:00
trace! ( " irq_tx: endtx {:?} " , n ) ;
self . tx . pop ( n ) ;
self . tx_waker . wake ( ) ;
self . tx_state = TxState ::Idle ;
2021-01-06 22:36:46 +00:00
} else {
break ;
2020-09-22 16:03:43 +00:00
}
}
}
}
trace! ( " irq: end " ) ;
}
}
2022-07-29 19:58:35 +00:00
/// Low power blocking wait loop using WFE/SEV.
fn low_power_wait_until ( mut condition : impl FnMut ( ) -> bool ) {
while ! condition ( ) {
// WFE might "eat" an event that would have otherwise woken the executor.
cortex_m ::asm ::wfe ( ) ;
}
// Retrigger an event to be transparent to the executor.
cortex_m ::asm ::sev ( ) ;
}