@@ -196,6 +196,7 @@ where
196
196
self . cr ( ) . modify ( |_, w| w. susp ( ) . not_suspended ( ) ) ;
197
197
}
198
198
199
+ /// Clear all event flags in the FCR register.
199
200
fn clear_all_event_flags ( & self ) {
200
201
self . fcr ( ) . write ( |w| {
201
202
w. tcf ( )
@@ -216,27 +217,30 @@ where
216
217
}
217
218
218
219
#[ inline( always) ]
220
+ /// Checks if the specified transfer event has triggered or if an error has occurred. If an
221
+ /// error has occurred, it is returned. If the event has triggered, `Ok(true)` is returned.
222
+ /// Otherwise, if the event has not triggered, `Ok(false)` is returned.
219
223
fn check_transfer_event (
220
224
& self ,
221
225
event : TransferEvent ,
222
226
) -> Result < bool , Error > {
223
227
let sr = self . sr ( ) . read ( ) ;
224
- check_error ! ( sr) . inspect_err ( |_| self . clear_all_event_flags ( ) ) ?;
228
+ check_error ! ( sr) ?;
225
229
let triggered = match event {
226
230
TransferEvent :: TransferComplete => sr. tcf ( ) . is_trigger ( ) ,
227
231
TransferEvent :: HalfTransferComplete => sr. htf ( ) . is_trigger ( ) ,
228
232
} ;
229
233
230
- if triggered {
231
- // Clear the event flag if it has been triggered
232
- self . fcr ( ) . write ( |w| match event {
233
- TransferEvent :: TransferComplete => w. tcf ( ) . clear ( ) ,
234
- TransferEvent :: HalfTransferComplete => w. htf ( ) . clear ( ) ,
235
- } ) ;
236
- }
237
234
Ok ( triggered)
238
235
}
239
236
237
+ fn clear_transfer_event_flag ( & self , event : TransferEvent ) {
238
+ self . fcr ( ) . write ( |w| match event {
239
+ TransferEvent :: TransferComplete => w. tcf ( ) . clear ( ) ,
240
+ TransferEvent :: HalfTransferComplete => w. htf ( ) . clear ( ) ,
241
+ } ) ;
242
+ }
243
+
240
244
// TODO: Remove clippy allow when FIFO use is implemented
241
245
#[ allow( unused) ]
242
246
#[ inline( always) ]
@@ -482,9 +486,11 @@ pub(super) trait Channel {
482
486
483
487
/// Blocks waiting for a transfer to complete. Reports any errors that occur during a transfer.
484
488
fn wait_for_transfer_complete ( & self ) -> Result < ( ) , Error > ;
489
+
485
490
/// Blocks waiting for a half transfer event to trigger. Reports any errors that occur during a
486
491
/// transfer.
487
492
fn wait_for_half_transfer_complete ( & self ) -> Result < ( ) , Error > ;
493
+
488
494
/// Apply a transfer configuration to the channel
489
495
fn apply_config < T : TransferType , S : Word , D : Word > (
490
496
& self ,
@@ -522,8 +528,13 @@ pub(super) trait Channel {
522
528
/// must be aligned with the source data width.
523
529
fn set_transfer_size_bytes ( & self , size : usize ) ;
524
530
531
+ /// Enable transfer interrupts for the channel. This enables the transfer complete,
532
+ /// half-transfer complete, data transfer error and user setting error interrupts. This is
533
+ /// useful for starting a transfer that will be monitored by an interrupt handler.
525
534
fn enable_transfer_interrupts ( & self ) ;
526
535
536
+ /// Disable transfer interrupts for the channel. It is expected that this will be called from
537
+ /// an interrupt handler after a transfer is completed.
527
538
fn disable_transfer_interrupts ( & self ) ;
528
539
}
529
540
@@ -533,46 +544,36 @@ where
533
544
CH : ChannelRegs ,
534
545
Self : Deref < Target = CH > ,
535
546
{
536
- /// Enable a transfer on the channel
537
547
#[ inline( always) ]
538
548
fn enable ( & self ) {
539
549
self . cr ( ) . modify ( |_, w| w. en ( ) . enabled ( ) ) ;
540
550
}
541
551
542
- /// Checks whether the channel is suspended
543
552
#[ inline( always) ]
544
553
fn is_suspended ( & self ) -> bool {
545
554
self . sr ( ) . read ( ) . suspf ( ) . bit_is_set ( )
546
555
}
547
556
548
- /// Initiates the suspension of a transfer
549
557
fn initiate_suspend ( & self ) {
550
558
if self . is_suspended ( ) {
551
559
return ;
552
560
}
553
561
self . suspend ( ) ;
554
562
}
555
563
556
- /// Resume transfer
557
564
#[ inline( always) ]
558
565
fn initiate_resume ( & self ) {
559
566
self . resume ( ) ;
560
567
}
561
568
562
- /// Checks whether the channel transfer is complete. If the channel indicates an error occurred,
563
- /// during the transaction an `Error`` is returned.
564
569
fn check_transfer_complete ( & self ) -> Result < bool , Error > {
565
570
self . check_transfer_event ( TransferEvent :: TransferComplete )
566
571
}
567
572
568
- /// Checks whether the channel half transfer complete event has triggered. If the channel
569
- /// indicates an error occurred, during the transaction an `Error`` is returned.
570
573
fn check_half_transfer_complete ( & self ) -> Result < bool , Error > {
571
574
self . check_transfer_event ( TransferEvent :: HalfTransferComplete )
572
575
}
573
576
574
- /// Checks whether the channel transfer has started (has transitioned out of the idle state, or
575
- /// the transfer complete event has already triggered if it is idle)
576
577
fn check_transfer_started ( & self ) -> Result < bool , Error > {
577
578
// TODO: Resolve multiple status register reads
578
579
match self . check_idle ( ) {
@@ -584,34 +585,27 @@ where
584
585
}
585
586
}
586
587
587
- /// Return whether or not a transfer is in progress on the channel.
588
588
#[ inline( always) ]
589
589
fn is_running ( & self ) -> bool {
590
590
!self . is_idle ( )
591
591
}
592
592
593
- /// Reset the channel registers and clear status flags so the channel can be reused.
594
593
fn reset_channel ( & self ) {
595
594
self . reset ( ) ;
596
595
self . clear_all_event_flags ( ) ;
597
596
}
598
597
599
- /// Suspend the transfer and blocks until it has been suspended. Reports any that occur while
600
- /// waiting for the transfer to suspend.
601
598
fn suspend_transfer ( & self ) {
602
599
self . initiate_suspend ( ) ;
603
600
while !self . is_suspended ( ) { }
604
601
}
605
602
606
- /// Resumes a suspended transfer and blocks until the channel transitions out of the idle state
607
- /// Reports any errors that occur resuming the transfer.
608
603
fn resume_transfer ( & self ) -> Result < ( ) , Error > {
609
604
self . initiate_resume ( ) ;
610
605
while !self . check_transfer_started ( ) ? { }
611
606
Ok ( ( ) )
612
607
}
613
608
614
- /// Aborts an operation by suspending the transfer and resetting the channel.
615
609
fn abort ( & self ) {
616
610
if !self . is_idle ( ) {
617
611
self . suspend_transfer ( ) ;
@@ -620,35 +614,49 @@ where
620
614
self . reset_channel ( ) ;
621
615
}
622
616
623
- /// Blocks waiting for a transfer to be started (or for it to be idle and complete). Reports any
624
- /// errors that occur while waiting for the transfer to start.
625
617
fn wait_for_transfer_started ( & self ) -> Result < ( ) , Error > {
626
- while !self . check_transfer_started ( ) ? { }
618
+ while !self . check_transfer_started ( ) . inspect_err ( |_| {
619
+ self . clear_all_event_flags ( ) ;
620
+ } ) ? { }
627
621
Ok ( ( ) )
628
622
}
629
623
630
- /// Blocks waiting for a transfer to complete. Reports any errors that occur during a transfer.
631
624
fn wait_for_transfer_complete ( & self ) -> Result < ( ) , Error > {
632
- if !self . is_running ( ) {
633
- return Ok ( ( ) ) ;
625
+ loop {
626
+ match self . check_transfer_complete ( ) {
627
+ Ok ( true ) => {
628
+ self . clear_transfer_event_flag (
629
+ TransferEvent :: TransferComplete ,
630
+ ) ;
631
+ return Ok ( ( ) ) ;
632
+ }
633
+ Ok ( false ) => continue ,
634
+ Err ( error) => {
635
+ self . clear_all_event_flags ( ) ;
636
+ return Err ( error) ;
637
+ }
638
+ }
634
639
}
635
-
636
- while !self . check_transfer_complete ( ) ? { }
637
- Ok ( ( ) )
638
640
}
639
641
640
- /// Blocks waiting for a half transfer event to trigger. Reports any errors that occur during a
641
- /// transfer.
642
642
fn wait_for_half_transfer_complete ( & self ) -> Result < ( ) , Error > {
643
- if !self . is_running ( ) {
644
- return Ok ( ( ) ) ;
643
+ loop {
644
+ match self . check_half_transfer_complete ( ) {
645
+ Ok ( true ) => {
646
+ self . clear_transfer_event_flag (
647
+ TransferEvent :: HalfTransferComplete ,
648
+ ) ;
649
+ return Ok ( ( ) ) ;
650
+ }
651
+ Ok ( false ) => continue ,
652
+ Err ( error) => {
653
+ self . clear_all_event_flags ( ) ;
654
+ return Err ( error) ;
655
+ }
656
+ }
645
657
}
646
-
647
- while !self . check_half_transfer_complete ( ) ? { }
648
- Ok ( ( ) )
649
658
}
650
659
651
- /// Apply a transfer configuration to the channel
652
660
fn apply_config < T : TransferType , S : Word , D : Word > (
653
661
& self ,
654
662
config : DmaConfig < T , S , D > ,
@@ -674,8 +682,6 @@ where
674
682
}
675
683
}
676
684
677
- /// Apply hardware request configuration to the channel. Not relevant to memory-to-memory
678
- /// transfers.
679
685
fn configure_hardware_request < T : HardwareRequest , S : Word , D : Word > (
680
686
& self ,
681
687
config : DmaConfig < T , S , D > ,
@@ -684,8 +690,6 @@ where
684
690
self . set_request_line ( config. transfer_type . request ( ) ) ;
685
691
}
686
692
687
- /// Apply peripheral flow control configuration for transactions where a peripheral is the
688
- /// source
689
693
fn configure_peripheral_flow_control <
690
694
T : PeripheralSource ,
691
695
S : Word ,
@@ -699,7 +703,6 @@ where
699
703
) ;
700
704
}
701
705
702
- /// Apply a data transform to the channel transfer
703
706
fn apply_data_transform ( & self , data_transform : DataTransform ) {
704
707
self . set_source_byte_exchange ( data_transform. source_byte_exchange ) ;
705
708
self . set_padding_alignment_mode ( data_transform. padding_alignment ) ;
@@ -709,36 +712,27 @@ where
709
712
self . set_destination_byte_exchange ( data_transform. dest_byte_exchange ) ;
710
713
}
711
714
712
- /// Set the source address. This sets the source address and data width.
713
715
fn set_source < W : Word > ( & self , ptr : * const W ) {
714
716
self . set_source_address ( ptr as u32 ) ;
715
717
self . set_source_data_width ( core:: mem:: size_of :: < W > ( ) ) ;
716
718
}
717
719
718
- /// Set the destination address. This sets the destination address and data width
719
720
fn set_destination < W : Word > ( & self , ptr : * mut W ) {
720
721
self . set_destination_address ( ptr as u32 ) ;
721
722
self . set_destination_data_width ( core:: mem:: size_of :: < W > ( ) ) ;
722
723
}
723
724
724
- /// Set the transfer size in bytes (not words!). Size must be aligned with destination width if
725
- /// source width is greater than destination width and packing mode is used. Otherwise the size
726
- /// must be aligned with the source data width.
727
725
fn set_transfer_size_bytes ( & self , size : usize ) {
728
726
self . set_block_size ( size as u16 ) ;
729
727
}
730
728
731
- /// Enable transfer interrupts for the channel. This enables the transfer complete,
732
- /// half-transfer complete, data transfer error and user setting error interrupts. This is
733
- /// useful for starting a transfer that will be monitored by an interrupt handler.
734
729
#[ inline( always) ]
735
730
fn enable_transfer_interrupts ( & self ) {
736
731
self . cr ( ) . modify ( |_, w| {
737
732
w. tcie ( ) . enabled ( ) . dteie ( ) . enabled ( ) . useie ( ) . enabled ( )
738
733
} ) ;
739
734
}
740
- /// Disable transfer interrupts for the channel. It is expected that this will be called from
741
- /// an interrupt handler after a transfer is completed.
735
+
742
736
#[ inline( always) ]
743
737
fn disable_transfer_interrupts ( & self ) {
744
738
self . cr ( ) . modify ( |_, w| {
0 commit comments