@@ -651,20 +651,35 @@ pub(crate) mod async_dma {
651
651
use super :: * ;
652
652
653
653
/// Perform a SERCOM DMA read with a provided `&mut [T]`
654
- pub ( in super :: super ) async fn read_dma < T : Beat , S : Sercom > (
654
+ #[ inline]
655
+ pub ( in super :: super ) async fn read_dma < T , B , S > (
655
656
channel : & mut impl AnyChannel < Status = ReadyFuture > ,
656
657
sercom_ptr : SercomPtr < T > ,
657
- words : & mut [ T ] ,
658
- ) -> Result < ( ) , Error > {
659
- read_dma_buffer :: < _ , _ , S > ( channel, sercom_ptr, words) . await
658
+ buf : & mut B ,
659
+ ) -> Result < ( ) , Error >
660
+ where
661
+ B : Buffer < Beat = T > ,
662
+ T : Beat ,
663
+ S : Sercom ,
664
+ {
665
+ unsafe { read_dma_linked :: < _ , _ , S > ( channel, sercom_ptr, buf, None ) . await }
660
666
}
661
667
662
- /// Perform a SERCOM DMA read with a provided [`Buffer`]
668
+ /// Perform a SERCOM DMA read with a provided [`Buffer`], and add an
669
+ /// optional link to a next [`DmacDescriptor`] to support linked
670
+ /// transfers.
671
+ ///
672
+ /// # Safety
673
+ ///
674
+ /// You **must** guarantee that the DMA transfer is either stopped or
675
+ /// completed before giving back control of `channel` AND `buf`.
676
+ #[ inline]
663
677
#[ hal_macro_helper]
664
- pub ( in super :: super ) async fn read_dma_buffer < T , B , S > (
678
+ pub ( in super :: super ) async unsafe fn read_dma_linked < T , B , S > (
665
679
channel : & mut impl AnyChannel < Status = ReadyFuture > ,
666
- sercom_ptr : SercomPtr < T > ,
667
- buf : B ,
680
+ mut sercom_ptr : SercomPtr < T > ,
681
+ buf : & mut B ,
682
+ next : Option < & mut DmacDescriptor > ,
668
683
) -> Result < ( ) , Error >
669
684
where
670
685
T : Beat ,
@@ -677,35 +692,54 @@ pub(crate) mod async_dma {
677
692
#[ hal_cfg( any( "dmac-d11" , "dmac-d21" ) ) ]
678
693
let trigger_action = TriggerAction :: Beat ;
679
694
695
+ // Safety: It is safe to bypass the buffer length check because `SercomPtr`
696
+ // always has a buffer length of 1.
680
697
channel
681
698
. as_mut ( )
682
- . transfer_future ( sercom_ptr, buf, S :: DMA_RX_TRIGGER , trigger_action)
699
+ . transfer_future_linked (
700
+ & mut sercom_ptr,
701
+ buf,
702
+ S :: DMA_RX_TRIGGER ,
703
+ trigger_action,
704
+ next,
705
+ )
683
706
. await
684
707
}
685
708
686
709
/// Perform a SERCOM DMA write with a provided `&[T]`
687
- pub ( in super :: super ) async fn write_dma < T : Beat , S : Sercom > (
710
+ #[ inline]
711
+ pub ( in super :: super ) async fn write_dma < T , B , S > (
688
712
channel : & mut impl AnyChannel < Status = ReadyFuture > ,
689
713
sercom_ptr : SercomPtr < T > ,
690
- words : & [ T ] ,
691
- ) -> Result < ( ) , Error > {
692
- // SAFETY: Using ImmutableSlice is safe because we hold on
693
- // to words as long as the transfer hasn't completed.
694
- let words = SharedSliceBuffer :: from_slice ( words) ;
695
-
696
- write_dma_buffer :: < _ , _ , S > ( channel, sercom_ptr, words) . await
714
+ buf : & mut B ,
715
+ ) -> Result < ( ) , Error >
716
+ where
717
+ B : Buffer < Beat = T > ,
718
+ T : Beat ,
719
+ S : Sercom ,
720
+ {
721
+ unsafe { write_dma_linked :: < _ , _ , S > ( channel, sercom_ptr, buf, None ) . await }
697
722
}
698
723
699
- /// Perform a SERCOM DMA write with a provided [`Buffer`]
724
+ /// Perform a SERCOM DMA write with a provided [`Buffer`], and add an
725
+ /// optional link to a next [`DmacDescriptor`] to support linked
726
+ /// transfers.
727
+ ///
728
+ /// # Safety
729
+ ///
730
+ /// You **must** guarantee that the DMA transfer is either stopped or
731
+ /// completed before giving back control of `channel` AND `buf`.
732
+ #[ inline]
700
733
#[ hal_macro_helper]
701
- pub ( in super :: super ) async fn write_dma_buffer < T , B , S > (
734
+ pub ( in super :: super ) async unsafe fn write_dma_linked < T , B , S > (
702
735
channel : & mut impl AnyChannel < Status = ReadyFuture > ,
703
- sercom_ptr : SercomPtr < T > ,
704
- buf : B ,
736
+ mut sercom_ptr : SercomPtr < T > ,
737
+ buf : & mut B ,
738
+ next : Option < & mut DmacDescriptor > ,
705
739
) -> Result < ( ) , Error >
706
740
where
707
- T : Beat ,
708
741
B : Buffer < Beat = T > ,
742
+ T : Beat ,
709
743
S : Sercom ,
710
744
{
711
745
#[ hal_cfg( "dmac-d5x" ) ]
@@ -714,9 +748,17 @@ pub(crate) mod async_dma {
714
748
#[ hal_cfg( any( "dmac-d11" , "dmac-d21" ) ) ]
715
749
let trigger_action = TriggerAction :: Beat ;
716
750
751
+ // Safety: It is safe to bypass the buffer length check because `SercomPtr`
752
+ // always has a buffer length of 1.
717
753
channel
718
754
. as_mut ( )
719
- . transfer_future ( buf, sercom_ptr, S :: DMA_TX_TRIGGER , trigger_action)
755
+ . transfer_future_linked (
756
+ buf,
757
+ & mut sercom_ptr,
758
+ S :: DMA_TX_TRIGGER ,
759
+ trigger_action,
760
+ next,
761
+ )
720
762
. await
721
763
}
722
764
}
0 commit comments