@@ -372,6 +372,13 @@ where
372
372
} ,
373
373
)
374
374
}
375
+
376
+ // Split into implementations of embedded_hal::serial traits
377
+ pub fn split ( self ) -> ( UarteTx < T > , UarteRx < T > ) {
378
+ let tx = UarteTx :: new ( ) ;
379
+ let rx = UarteRx :: new ( ) ;
380
+ ( tx, rx)
381
+ }
375
382
}
376
383
377
384
impl < T > fmt:: Write for Uarte < T >
@@ -408,18 +415,240 @@ pub enum Error {
408
415
BufferNotInRAM ,
409
416
}
410
417
411
- pub trait Instance : Deref < Target = uarte0:: RegisterBlock > + sealed:: Sealed { }
418
+ pub trait Instance : Deref < Target = uarte0:: RegisterBlock > + sealed:: Sealed {
419
+ fn ptr ( ) -> * const uarte0:: RegisterBlock ;
420
+ }
412
421
413
422
mod sealed {
414
423
pub trait Sealed { }
415
424
}
416
425
417
426
impl sealed:: Sealed for UARTE0 { }
418
- impl Instance for UARTE0 { }
427
+ impl Instance for UARTE0 {
428
+ fn ptr ( ) -> * const uarte0:: RegisterBlock {
429
+ UARTE0 :: ptr ( )
430
+ }
431
+ }
419
432
420
433
#[ cfg( any( feature = "52833" , feature = "52840" , feature = "9160" ) ) ]
421
434
mod _uarte1 {
422
435
use super :: * ;
423
436
impl sealed:: Sealed for UARTE1 { }
424
- impl Instance for UARTE1 { }
437
+ impl Instance for UARTE1 {
438
+ fn ptr ( ) -> * const uarte0:: RegisterBlock {
439
+ UARTE1 :: ptr ( )
440
+ }
441
+ }
442
+ }
443
+
444
+ /// Interface for the TX part of a UART instance that can be used independently of the RX part.
445
+ pub struct UarteTx < T > {
446
+ _marker : core:: marker:: PhantomData < T > ,
447
+ tx_buf : [ u8 ; 1 ] ,
448
+ }
449
+
450
+ /// Interface for the RX part of a UART instance that can be used independently of the TX part.
451
+ pub struct UarteRx < T > {
452
+ _marker : core:: marker:: PhantomData < T > ,
453
+ rx_buf : [ u8 ; 1 ] ,
454
+ }
455
+
456
+ impl < T > UarteTx < T >
457
+ where
458
+ T : Instance ,
459
+ {
460
+ fn new ( ) -> UarteTx < T > {
461
+ let tx = UarteTx {
462
+ _marker : core:: marker:: PhantomData ,
463
+ tx_buf : [ 0 ; 1 ] ,
464
+ } ;
465
+ tx
466
+ }
467
+ }
468
+
469
+ impl < T > UarteRx < T >
470
+ where
471
+ T : Instance ,
472
+ {
473
+ fn new ( ) -> UarteRx < T > {
474
+ let rx = UarteRx {
475
+ _marker : core:: marker:: PhantomData ,
476
+ rx_buf : [ 0 ; 1 ] ,
477
+ } ;
478
+ rx
479
+ }
480
+ }
481
+
482
+ pub mod serial {
483
+
484
+ ///! Implementation of the embedded_hal::serial::* traits for UartTx and UartRx.
485
+ use super :: * ;
486
+ use embedded_hal:: serial;
487
+ use nb;
488
+
489
+ impl < T > serial:: Write < u8 > for UarteTx < T >
490
+ where
491
+ T : Instance ,
492
+ {
493
+ type Error = Error ;
494
+
495
+ /// Write a single byte non-blocking. Returns nb::Error::WouldBlock if not yet done.
496
+ fn write ( & mut self , b : u8 ) -> nb:: Result < ( ) , Self :: Error > {
497
+ let uarte = unsafe { & * T :: ptr ( ) } ;
498
+
499
+ // If txstarted is set, we are in the process of transmitting.
500
+ let in_progress = uarte. events_txstarted . read ( ) . bits ( ) == 1 ;
501
+
502
+ if in_progress {
503
+ self . flush ( )
504
+ } else {
505
+ // Start a new transmission, copy value into transmit buffer.
506
+
507
+ let tx_buffer = & mut self . tx_buf ;
508
+ tx_buffer[ 0 ] = b;
509
+
510
+ // Conservative compiler fence to prevent optimizations that do not
511
+ // take in to account actions by DMA. The fence has been placed here,
512
+ // before any DMA action has started.
513
+ compiler_fence ( SeqCst ) ;
514
+
515
+ // Reset the events.
516
+ uarte. events_endtx . reset ( ) ;
517
+ uarte. events_txstopped . reset ( ) ;
518
+
519
+ // Set up the DMA write.
520
+ // We're giving the register a pointer to the tx buffer.
521
+ //
522
+ // The PTR field is a full 32 bits wide and accepts the full range
523
+ // of values.
524
+ uarte
525
+ . txd
526
+ . ptr
527
+ . write ( |w| unsafe { w. ptr ( ) . bits ( tx_buffer. as_ptr ( ) as u32 ) } ) ;
528
+
529
+ // We're giving it the length of the buffer, so no danger of
530
+ // accessing invalid memory. We have verified that the length of the
531
+ // buffer fits in an `u8`, so the cast to `u8` is also fine.
532
+ //
533
+ // The MAXCNT field is 8 bits wide and accepts the full range of
534
+ // values.
535
+ uarte
536
+ . txd
537
+ . maxcnt
538
+ . write ( |w| unsafe { w. maxcnt ( ) . bits ( tx_buffer. len ( ) as _ ) } ) ;
539
+
540
+ // Start UARTE Transmit transaction.
541
+ // `1` is a valid value to write to task registers.
542
+ uarte. tasks_starttx . write ( |w| unsafe { w. bits ( 1 ) } ) ;
543
+ Err ( nb:: Error :: WouldBlock )
544
+ }
545
+ }
546
+
547
+ /// Flush the TX buffer non-blocking. Returns nb::Error::WouldBlock if not yet flushed.
548
+ fn flush ( & mut self ) -> nb:: Result < ( ) , Self :: Error > {
549
+ let uarte = unsafe { & * T :: ptr ( ) } ;
550
+
551
+ let in_progress = uarte. events_txstarted . read ( ) . bits ( ) == 1 ;
552
+ let endtx = uarte. events_endtx . read ( ) . bits ( ) != 0 ;
553
+ let txstopped = uarte. events_txstopped . read ( ) . bits ( ) != 0 ;
554
+ if in_progress {
555
+ if endtx || txstopped {
556
+ // We are done, cleanup the state.
557
+ uarte. events_txstarted . reset ( ) ;
558
+ // Conservative compiler fence to prevent optimizations that do not
559
+ // take in to account actions by DMA. The fence has been placed here,
560
+ // after all possible DMA actions have completed.
561
+ compiler_fence ( SeqCst ) ;
562
+
563
+ if txstopped {
564
+ return Err ( nb:: Error :: Other ( Error :: Transmit ) ) ;
565
+ }
566
+
567
+ // Lower power consumption by disabling the transmitter once we're
568
+ // finished.
569
+ // `1` is a valid value to write to task registers.
570
+ uarte. tasks_stoptx . write ( |w| unsafe { w. bits ( 1 ) } ) ;
571
+ Ok ( ( ) )
572
+ } else {
573
+ // Still not done, don't block.
574
+ Err ( nb:: Error :: WouldBlock )
575
+ }
576
+ } else {
577
+ Ok ( ( ) )
578
+ }
579
+ }
580
+ }
581
+
582
+ impl < T > core:: fmt:: Write for UarteTx < T >
583
+ where
584
+ T : Instance ,
585
+ {
586
+ fn write_str ( & mut self , s : & str ) -> fmt:: Result {
587
+ s. as_bytes ( )
588
+ . iter ( )
589
+ . try_for_each ( |c| nb:: block!( self . write( * c) ) )
590
+ . map_err ( |_| core:: fmt:: Error )
591
+ }
592
+ }
593
+
594
+ impl < T > serial:: Read < u8 > for UarteRx < T >
595
+ where
596
+ T : Instance ,
597
+ {
598
+ type Error = Error ;
599
+ fn read ( & mut self ) -> nb:: Result < u8 , Self :: Error > {
600
+ let uarte = unsafe { & * T :: ptr ( ) } ;
601
+
602
+ compiler_fence ( SeqCst ) ;
603
+
604
+ let in_progress = uarte. events_rxstarted . read ( ) . bits ( ) == 1 ;
605
+ if in_progress && uarte. events_endrx . read ( ) . bits ( ) == 0 {
606
+ return Err ( nb:: Error :: WouldBlock ) ;
607
+ }
608
+
609
+ if in_progress {
610
+ let b = self . rx_buf [ 0 ] ;
611
+ uarte. events_rxstarted . write ( |w| w) ;
612
+ uarte. events_endrx . write ( |w| w) ;
613
+
614
+ compiler_fence ( SeqCst ) ;
615
+ if uarte. rxd . amount . read ( ) . bits ( ) != 1 as u32 {
616
+ return Err ( nb:: Error :: Other ( Error :: Receive ) ) ;
617
+ }
618
+ Ok ( b)
619
+ } else {
620
+ let rx_buf = & mut self . rx_buf ;
621
+
622
+ // We're giving the register a pointer to the rx buffer.
623
+ //
624
+ // The PTR field is a full 32 bits wide and accepts the full range
625
+ // of values.
626
+ uarte
627
+ . rxd
628
+ . ptr
629
+ . write ( |w| unsafe { w. ptr ( ) . bits ( rx_buf. as_ptr ( ) as u32 ) } ) ;
630
+
631
+ // We're giving it the length of the buffer, so no danger of
632
+ // accessing invalid memory.
633
+ //
634
+ // The MAXCNT field is at least 8 bits wide and accepts the full
635
+ // range of values.
636
+ uarte
637
+ . rxd
638
+ . maxcnt
639
+ . write ( |w| unsafe { w. maxcnt ( ) . bits ( rx_buf. len ( ) as _ ) } ) ;
640
+
641
+ // Start UARTE Receive transaction.
642
+ // `1` is a valid value to write to task registers.
643
+ uarte. tasks_startrx . write ( |w| unsafe { w. bits ( 1 ) } ) ;
644
+ // Conservative compiler fence to prevent optimizations that do not
645
+ // take in to account actions by DMA. The fence has been placed here,
646
+ // after all possible DMA actions have completed.
647
+
648
+ compiler_fence ( SeqCst ) ;
649
+
650
+ Err ( nb:: Error :: WouldBlock )
651
+ }
652
+ }
653
+ }
425
654
}
0 commit comments