@@ -371,12 +371,12 @@ where
371371 )
372372 }
373373
374- // Split into implementations of embedded_hal::serial traits. The buffers passed here must outlive any DMA transfers
374+ // Split into implementations of embedded_hal::serial traits. The size of the slices passed to this method will determine the size of the DMA transfers performed.
375375 // that are initiated by the UartTx and UartRx.
376376 pub fn split < ' a > (
377377 self ,
378- tx_buf : & ' a mut [ u8 ] ,
379- rx_buf : & ' a mut [ u8 ] ,
378+ tx_buf : & ' static mut [ u8 ] ,
379+ rx_buf : & ' static mut [ u8 ] ,
380380 ) -> Result < ( UarteTx < ' a , T > , UarteRx < ' a , T > ) , Error > {
381381 let tx = UarteTx :: new ( tx_buf) ?;
382382 let rx = UarteRx :: new ( rx_buf) ?;
@@ -453,6 +453,7 @@ where
453453{
454454 _marker : core:: marker:: PhantomData < T > ,
455455 tx_buf : & ' a mut [ u8 ] ,
456+ written : u16 ,
456457}
457458
458459/// Interface for the RX part of a UART instance that can be used independently of the TX part.
@@ -470,14 +471,19 @@ where
470471{
471472 fn new ( tx_buf : & ' a mut [ u8 ] ) -> Result < UarteTx < ' a , T > , Error > {
472473 slice_in_ram_or ( tx_buf, Error :: BufferNotInRAM ) ?;
473- if tx_buf. len ( ) > 0 {
474- Ok ( UarteTx {
475- _marker : core:: marker:: PhantomData ,
476- tx_buf,
477- } )
478- } else {
479- Err ( Error :: TxBufferTooSmall )
474+ if tx_buf. len ( ) == 0 {
475+ return Err ( Error :: TxBufferTooSmall ) ;
480476 }
477+
478+ if tx_buf. len ( ) > EASY_DMA_SIZE {
479+ return Err ( Error :: TxBufferTooLong ) ;
480+ }
481+
482+ Ok ( UarteTx {
483+ _marker : core:: marker:: PhantomData ,
484+ tx_buf,
485+ written : 0 ,
486+ } )
481487 }
482488}
483489
@@ -487,14 +493,18 @@ where
487493{
488494 fn new ( rx_buf : & ' a mut [ u8 ] ) -> Result < UarteRx < ' a , T > , Error > {
489495 slice_in_ram_or ( rx_buf, Error :: BufferNotInRAM ) ?;
490- if rx_buf. len ( ) > 0 {
491- Ok ( UarteRx {
492- _marker : core:: marker:: PhantomData ,
493- rx_buf,
494- } )
495- } else {
496- Err ( Error :: RxBufferTooSmall )
496+ if rx_buf. len ( ) == 0 {
497+ return Err ( Error :: RxBufferTooSmall ) ;
498+ }
499+
500+ if rx_buf. len ( ) > EASY_DMA_SIZE {
501+ return Err ( Error :: RxBufferTooLong ) ;
497502 }
503+
504+ Ok ( UarteRx {
505+ _marker : core:: marker:: PhantomData ,
506+ rx_buf,
507+ } )
498508 }
499509}
500510
@@ -557,8 +567,9 @@ where
557567
558568pub mod serial {
559569
560- ///! Implementation of the embedded_hal::serial::* traits for UartTx and UartRx.
570+ ///! Implementation of the embedded_hal::serial::* and embedded_hal::blocking::serial::* traits for UartTx and UartRx.
561571 use super :: * ;
572+ use embedded_hal:: blocking:: serial as bserial;
562573 use embedded_hal:: serial;
563574 use nb;
564575
@@ -568,48 +579,21 @@ pub mod serial {
568579 {
569580 type Error = Error ;
570581
571- /// Write a single byte non-blocking . Returns nb::Error::WouldBlock if not yet done .
582+ /// Write a single byte to the internal buffer . Returns nb::Error::WouldBlock if buffer is full .
572583 fn write ( & mut self , b : u8 ) -> nb:: Result < ( ) , Self :: Error > {
573584 let uarte = unsafe { & * T :: ptr ( ) } ;
574585
575- // If txstarted is set, we are in the process of transmitting.
576- let in_progress = uarte. events_txstarted . read ( ) . bits ( ) == 1 ;
586+ // Prevent writing to buffer while DMA transfer is in progress.
587+ if uarte. events_txstarted . read ( ) . bits ( ) == 1 {
588+ return Err ( nb:: Error :: WouldBlock ) ;
589+ }
577590
578- if in_progress {
579- self . flush ( )
591+ let written = self . written as usize ;
592+ if written < self . tx_buf . len ( ) {
593+ self . tx_buf [ written] = b;
594+ self . written += 1 ;
595+ Ok ( ( ) )
580596 } else {
581- // Start a new transmission, copy value into transmit buffer.
582-
583- self . tx_buf [ 0 ] = b;
584-
585- // Conservative compiler fence to prevent optimizations that do not
586- // take in to account actions by DMA. The fence has been placed here,
587- // before any DMA action has started.
588- compiler_fence ( SeqCst ) ;
589-
590- // Reset the events.
591- uarte. events_endtx . reset ( ) ;
592- uarte. events_txstopped . reset ( ) ;
593-
594- // Set up the DMA write.
595- // We're giving the register a pointer to the tx buffer.
596- //
597- // The PTR field is a full 32 bits wide and accepts the full range
598- // of values.
599- uarte
600- . txd
601- . ptr
602- . write ( |w| unsafe { w. ptr ( ) . bits ( self . tx_buf . as_ptr ( ) as u32 ) } ) ;
603-
604- // We're giving it a length of 1 to transmit 1 byte at a time.
605- //
606- // The MAXCNT field is 8 bits wide and accepts the full range of
607- // values.
608- uarte. txd . maxcnt . write ( |w| unsafe { w. maxcnt ( ) . bits ( 1 ) } ) ;
609-
610- // Start UARTE Transmit transaction.
611- // `1` is a valid value to write to task registers.
612- uarte. tasks_starttx . write ( |w| unsafe { w. bits ( 1 ) } ) ;
613597 Err ( nb:: Error :: WouldBlock )
614598 }
615599 }
@@ -618,10 +602,12 @@ pub mod serial {
618602 fn flush ( & mut self ) -> nb:: Result < ( ) , Self :: Error > {
619603 let uarte = unsafe { & * T :: ptr ( ) } ;
620604
605+ // If txstarted is set, we are in the process of transmitting.
621606 let in_progress = uarte. events_txstarted . read ( ) . bits ( ) == 1 ;
622- let endtx = uarte. events_endtx . read ( ) . bits ( ) != 0 ;
623- let txstopped = uarte. events_txstopped . read ( ) . bits ( ) != 0 ;
607+
624608 if in_progress {
609+ let endtx = uarte. events_endtx . read ( ) . bits ( ) != 0 ;
610+ let txstopped = uarte. events_txstopped . read ( ) . bits ( ) != 0 ;
625611 if endtx || txstopped {
626612 // We are done, cleanup the state.
627613 uarte. events_txstarted . reset ( ) ;
@@ -644,11 +630,45 @@ pub mod serial {
644630 Err ( nb:: Error :: WouldBlock )
645631 }
646632 } else {
647- Ok ( ( ) )
633+ // Conservative compiler fence to prevent optimizations that do not
634+ // take in to account actions by DMA. The fence has been placed here,
635+ // before any DMA action has started.
636+ compiler_fence ( SeqCst ) ;
637+
638+ // Reset the events.
639+ uarte. events_endtx . reset ( ) ;
640+ uarte. events_txstopped . reset ( ) ;
641+
642+ // Set up the DMA write.
643+ // We're giving the register a pointer to the tx buffer.
644+ //
645+ // The PTR field is a full 32 bits wide and accepts the full range
646+ // of values.
647+ uarte
648+ . txd
649+ . ptr
650+ . write ( |w| unsafe { w. ptr ( ) . bits ( self . tx_buf . as_ptr ( ) as u32 ) } ) ;
651+
652+ // We're giving it a length of the number of bytes written to the buffer.
653+ //
654+ // The MAXCNT field is 8 bits wide and accepts the full range of
655+ // values.
656+ uarte
657+ . txd
658+ . maxcnt
659+ . write ( |w| unsafe { w. maxcnt ( ) . bits ( self . written ) } ) ;
660+
661+ // Start UARTE Transmit transaction.
662+ // `1` is a valid value to write to task registers.
663+ uarte. tasks_starttx . write ( |w| unsafe { w. bits ( 1 ) } ) ;
664+ Err ( nb:: Error :: WouldBlock )
648665 }
649666 }
650667 }
651668
669+ // Auto-implement the blocking variant
670+ impl < ' a , T > bserial:: write:: Default < u8 > for UarteTx < ' a , T > where T : Instance { }
671+
652672 impl < ' a , T > core:: fmt:: Write for UarteTx < ' a , T >
653673 where
654674 T : Instance ,
0 commit comments