8
8
//! transfers.
9
9
10
10
use core:: {
11
+ fmt:: { self , Debug , Formatter } ,
11
12
marker:: PhantomData ,
12
13
mem,
13
14
ops:: Not ,
@@ -24,7 +25,7 @@ use traits::{
24
25
} ;
25
26
26
27
/// Errors.
27
- #[ derive( Debug , PartialEq ) ]
28
+ #[ derive( PartialEq ) ]
28
29
pub enum DMAError < T > {
29
30
/// DMA not ready to change buffers.
30
31
NotReady ( T ) ,
@@ -34,6 +35,19 @@ pub enum DMAError<T> {
34
35
Overrun ( T ) ,
35
36
}
36
37
38
+ // Manually implement `Debug`, so we can have debug information even with a buffer `T` that doesn't
39
+ // implement `Debug`. `T` is always a buffer type chosen by the user, because of that the debug
40
+ // information can be helpful even without knowing the inner type
41
+ impl < T > Debug for DMAError < T > {
42
+ fn fmt ( & self , f : & mut Formatter ) -> fmt:: Result {
43
+ match self {
44
+ DMAError :: NotReady ( _) => f. debug_tuple ( "NotReady" ) . finish ( ) ,
45
+ DMAError :: SmallBuffer ( _) => f. debug_tuple ( "SmalBuffer" ) . finish ( ) ,
46
+ DMAError :: Overrun ( _) => f. debug_tuple ( "Overrun" ) . finish ( ) ,
47
+ }
48
+ }
49
+ }
50
+
37
51
/// Possible DMA's directions.
38
52
#[ derive( Debug , Clone , Copy , PartialEq ) ]
39
53
pub enum DmaDirection {
@@ -375,6 +389,13 @@ macro_rules! dma_stream {
375
389
dma. st[ Self :: NUMBER ] . ndtr. write( |w| w. ndt( ) . bits( value) ) ;
376
390
}
377
391
392
+ #[ inline( always) ]
393
+ fn get_number_of_transfers( ) -> u16 {
394
+ //NOTE(unsafe) We only access the registers that belongs to the StreamX
395
+ let dma = unsafe { & * I :: ptr( ) } ;
396
+ dma. st[ Self :: NUMBER ] . ndtr. read( ) . ndt( ) . bits( )
397
+ }
398
+
378
399
#[ inline( always) ]
379
400
unsafe fn enable( & mut self ) {
380
401
//NOTE(unsafe) We only access the registers that belongs to the StreamX
@@ -389,11 +410,23 @@ macro_rules! dma_stream {
389
410
dma. st[ Self :: NUMBER ] . cr. read( ) . en( ) . bit_is_set( )
390
411
}
391
412
392
- #[ inline( always) ]
393
413
fn disable( & mut self ) {
394
- //NOTE(unsafe) We only access the registers that belongs to the StreamX
395
- let dma = unsafe { & * I :: ptr( ) } ;
396
- dma. st[ Self :: NUMBER ] . cr. modify( |_, w| w. en( ) . clear_bit( ) ) ;
414
+ if Self :: is_enabled( ) {
415
+ //NOTE(unsafe) We only access the registers that belongs to the StreamX
416
+ let dma = unsafe { & * I :: ptr( ) } ;
417
+
418
+ // Aborting an on-going transfer might cause interrupts to fire, disable
419
+ // them
420
+ let ( tc, ht, te, dm) = Self :: get_interrupts_enable( ) ;
421
+ self
422
+ . set_interrupts_enable( false , false , false , false ) ;
423
+
424
+ dma. st[ Self :: NUMBER ] . cr. modify( |_, w| w. en( ) . clear_bit( ) ) ;
425
+ while Self :: is_enabled( ) { }
426
+
427
+ self . clear_interrupts( ) ;
428
+ self . set_interrupts_enable( tc, ht, te, dm) ;
429
+ }
397
430
}
398
431
399
432
#[ inline( always) ]
@@ -464,6 +497,15 @@ macro_rules! dma_stream {
464
497
) ;
465
498
}
466
499
500
+ #[ inline( always) ]
501
+ fn get_interrupts_enable( ) -> ( bool , bool , bool , bool ) {
502
+ //NOTE(unsafe) We only access the registers that belongs to the StreamX
503
+ let dma = unsafe { & * I :: ptr( ) } ;
504
+ let cr = dma. st[ Self :: NUMBER ] . cr. read( ) ;
505
+ ( cr. tcie( ) . bit_is_set( ) , cr. htie( ) . bit_is_set( ) ,
506
+ cr. teie( ) . bit_is_set( ) , cr. dmeie( ) . bit_is_set( ) )
507
+ }
508
+
467
509
#[ inline( always) ]
468
510
fn set_transfer_complete_interrupt_enable( & mut self , transfer_complete_interrupt: bool ) {
469
511
//NOTE(unsafe) We only access the registers that belongs to the StreamX
@@ -969,19 +1011,22 @@ where
969
1011
/// Changes the buffer and restarts or continues a double buffer transfer. This must be called
970
1012
/// immediately after a transfer complete event. Returns the old buffer together with its
971
1013
/// `CurrentBuffer`. If an error occurs, this method will return the new buffer with the error.
1014
+ ///
972
1015
/// This method will clear the transfer complete flag on entry, it will also clear it again if
973
1016
/// an overrun occurs during its execution. Moreover, if an overrun occurs, the stream will be
974
- /// disabled and the transfer error flag will be set.
1017
+ /// disabled and the transfer error flag will be set. This method can be called before the end
1018
+ /// of an ongoing transfer only if not using double buffering, in that case, the current
1019
+ /// transfer will be canceled and a new one will be started. A `NotReady` error will be returned
1020
+ /// if this method is called before the end of a transfer while double buffering.
975
1021
pub fn next_transfer (
976
1022
& mut self ,
977
1023
mut new_buf : BUF ,
978
1024
) -> Result < ( BUF , CurrentBuffer ) , DMAError < BUF > > {
979
- if !STREAM :: get_transfer_complete_flag ( ) {
980
- return Err ( DMAError :: NotReady ( new_buf) ) ;
981
- }
982
- self . stream . clear_transfer_complete_interrupt ( ) ;
983
-
984
1025
if self . double_buf . is_some ( ) && DIR :: direction ( ) != DmaDirection :: MemoryToMemory {
1026
+ if !STREAM :: get_transfer_complete_flag ( ) {
1027
+ return Err ( DMAError :: NotReady ( new_buf) ) ;
1028
+ }
1029
+ self . stream . clear_transfer_complete_interrupt ( ) ;
985
1030
// NOTE(unsafe) We now own this buffer and we won't call any &mut methods on it until
986
1031
// the end of the DMA transfer
987
1032
let ( new_buf_ptr, new_buf_len) = unsafe { new_buf. write_buffer ( ) } ;
@@ -993,7 +1038,7 @@ where
993
1038
994
1039
if STREAM :: current_buffer ( ) == CurrentBuffer :: DoubleBuffer {
995
1040
self . stream . set_memory_address ( new_buf_ptr as u32 ) ;
996
- // Check if an overrun occured , the buffer address won't be updated in that case
1041
+ // Check if an overrun occurred , the buffer address won't be updated in that case
997
1042
if self . stream . get_memory_address ( ) != new_buf_ptr as u32 {
998
1043
self . stream . clear_transfer_complete_interrupt ( ) ;
999
1044
return Err ( DMAError :: Overrun ( new_buf) ) ;
@@ -1009,7 +1054,7 @@ where
1009
1054
} else {
1010
1055
self . stream
1011
1056
. set_memory_double_buffer_address ( new_buf_ptr as u32 ) ;
1012
- // Check if an overrun occured , the buffer address won't be updated in that case
1057
+ // Check if an overrun occurred , the buffer address won't be updated in that case
1013
1058
if self . stream . get_memory_double_buffer_address ( ) != new_buf_ptr as u32 {
1014
1059
self . stream . clear_transfer_complete_interrupt ( ) ;
1015
1060
return Err ( DMAError :: Overrun ( new_buf) ) ;
@@ -1025,8 +1070,9 @@ where
1025
1070
}
1026
1071
}
1027
1072
self . stream . disable ( ) ;
1073
+ self . stream . clear_transfer_complete_interrupt ( ) ;
1028
1074
1029
- // "No re-ordering of reads and writes across this point is allowed "
1075
+ // "Subsequent reads and writes cannot be moved ahead of preceding reads. "
1030
1076
compiler_fence ( Ordering :: SeqCst ) ;
1031
1077
1032
1078
// NOTE(unsafe) We now own this buffer and we won't call any &mut methods on it until
@@ -1111,8 +1157,11 @@ where
1111
1157
1112
1158
/// Changes the buffer and restarts or continues a double buffer transfer. This must be called
1113
1159
/// immediately after a transfer complete event. The closure must return `(BUF, T)` where `BUF`
1114
- /// is the new buffer to be used. The closure will not be called if the transfer is not
1115
- /// completed. This method clears the transfer complete flag on entry.
1160
+ /// is the new buffer to be used. This method can be called before the end of an ongoing
1161
+ /// transfer only if not using double buffering, in that case, the current transfer will be
1162
+ /// canceled and a new one will be started. A `NotReady` error will be returned if this method
1163
+ /// is called before the end of a transfer while double buffering and the closure won't be
1164
+ /// executed.
1116
1165
///
1117
1166
/// # Panics
1118
1167
/// This method will panic when double buffering and one or both of the following conditions
@@ -1133,12 +1182,12 @@ where
1133
1182
where
1134
1183
F : FnOnce ( BUF , CurrentBuffer ) -> ( BUF , T ) ,
1135
1184
{
1136
- if !STREAM :: get_transfer_complete_flag ( ) {
1137
- return Err ( DMAError :: NotReady ( ( ) ) ) ;
1138
- }
1139
- self . stream . clear_transfer_complete_interrupt ( ) ;
1140
-
1141
1185
if self . double_buf . is_some ( ) && DIR :: direction ( ) != DmaDirection :: MemoryToMemory {
1186
+ if !STREAM :: get_transfer_complete_flag ( ) {
1187
+ return Err ( DMAError :: NotReady ( ( ) ) ) ;
1188
+ }
1189
+ self . stream . clear_transfer_complete_interrupt ( ) ;
1190
+
1142
1191
let current_buffer = STREAM :: current_buffer ( ) ;
1143
1192
// double buffering, unwrap can never fail
1144
1193
let db = if current_buffer == CurrentBuffer :: DoubleBuffer {
@@ -1170,7 +1219,7 @@ where
1170
1219
if current_buffer == CurrentBuffer :: DoubleBuffer {
1171
1220
self . stream . set_memory_address ( new_buf_ptr as u32 ) ;
1172
1221
1173
- // Check again if an overrun occured , the buffer address won't be updated in that
1222
+ // Check again if an overrun occurred , the buffer address won't be updated in that
1174
1223
// case
1175
1224
if self . stream . get_memory_address ( ) != new_buf_ptr as u32 {
1176
1225
panic ! ( "Overrun" ) ;
@@ -1196,6 +1245,7 @@ where
1196
1245
}
1197
1246
}
1198
1247
self . stream . disable ( ) ;
1248
+ self . stream . clear_transfer_complete_interrupt ( ) ;
1199
1249
1200
1250
// "No re-ordering of reads and writes across this point is allowed"
1201
1251
compiler_fence ( Ordering :: SeqCst ) ;
0 commit comments