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