@@ -864,9 +864,8 @@ where
864
864
STREAM : Stream ,
865
865
CHANNEL : Channel ,
866
866
DIR : Direction ,
867
- PERIPHERAL : PeriAddress ,
867
+ PERIPHERAL : PeriAddress + DMASet < STREAM , CHANNEL , DIR > ,
868
868
BUF : StaticWriteBuffer < Word = <PERIPHERAL as PeriAddress >:: MemSize > ,
869
- ( STREAM , CHANNEL , PERIPHERAL , DIR ) : DMASet ,
870
869
{
871
870
/// Applies all fields in DmaConfig.
872
871
fn apply_config ( & mut self , config : config:: DmaConfig ) {
@@ -1008,8 +1007,9 @@ where
1008
1007
}
1009
1008
1010
1009
/// Changes the buffer and restarts or continues a double buffer transfer. This must be called
1011
- /// immediately after a transfer complete event. Returns the old buffer together with its
1012
- /// `CurrentBuffer`. If an error occurs, this method will return the new buffer with the error.
1010
+ /// immediately after a transfer complete event if using double buffering, otherwise you might
1011
+ /// lose data. Returns the old buffer together with its `CurrentBuffer`. If an error occurs,
1012
+ /// this method will return the new buffer with the error.
1013
1013
///
1014
1014
/// This method will clear the transfer complete flag on entry, it will also clear it again if
1015
1015
/// an overrun occurs during its execution. Moreover, if an overrun occurs, the stream will be
@@ -1036,7 +1036,10 @@ where
1036
1036
}
1037
1037
1038
1038
if STREAM :: current_buffer ( ) == CurrentBuffer :: DoubleBuffer {
1039
+ // "Preceding reads and writes cannot be moved past subsequent writes"
1040
+ compiler_fence ( Ordering :: Release ) ;
1039
1041
self . stream . set_memory_address ( new_buf_ptr as u32 ) ;
1042
+
1040
1043
// Check if an overrun occurred, the buffer address won't be updated in that case
1041
1044
if self . stream . get_memory_address ( ) != new_buf_ptr as u32 {
1042
1045
self . stream . clear_transfer_complete_interrupt ( ) ;
@@ -1051,8 +1054,11 @@ where
1051
1054
// We always have a buffer, so unwrap can't fail
1052
1055
return Ok ( ( old_buf. unwrap ( ) , CurrentBuffer :: FirstBuffer ) ) ;
1053
1056
} else {
1057
+ // "Preceding reads and writes cannot be moved past subsequent writes"
1058
+ compiler_fence ( Ordering :: Release ) ;
1054
1059
self . stream
1055
1060
. set_memory_double_buffer_address ( new_buf_ptr as u32 ) ;
1061
+
1056
1062
// Check if an overrun occurred, the buffer address won't be updated in that case
1057
1063
if self . stream . get_memory_double_buffer_address ( ) != new_buf_ptr as u32 {
1058
1064
self . stream . clear_transfer_complete_interrupt ( ) ;
@@ -1081,9 +1087,6 @@ where
1081
1087
self . stream . set_number_of_transfers ( buf_len as u16 ) ;
1082
1088
let old_buf = self . buf . replace ( new_buf) ;
1083
1089
1084
- // "Preceding reads and writes cannot be moved past subsequent writes"
1085
- compiler_fence ( Ordering :: Release ) ;
1086
-
1087
1090
unsafe {
1088
1091
self . stream . enable ( ) ;
1089
1092
}
@@ -1155,15 +1158,15 @@ where
1155
1158
}
1156
1159
1157
1160
/// Changes the buffer and restarts or continues a double buffer transfer. This must be called
1158
- /// immediately after a transfer complete event. The closure must return `(BUF, T)` where `BUF`
1159
- /// is the new buffer to be used. This method can be called before the end of an ongoing
1160
- /// transfer only if not using double buffering, in that case, the current transfer will be
1161
- /// canceled and a new one will be started. A `NotReady` error will be returned if this method
1162
- /// is called before the end of a transfer while double buffering and the closure won't be
1163
- /// executed.
1161
+ /// immediately after a transfer complete event if using double buffering, otherwise you might
1162
+ /// lose data. The closure must return `(BUF, T)` where `BUF` is the new buffer to be used. This
1163
+ /// method can be called before the end of an ongoing transfer only if not using double
1164
+ /// buffering, in that case, the current transfer will be canceled and a new one will be
1165
+ /// started. A `NotReady` error will be returned if this method is called before the end of a
1166
+ /// transfer while double buffering and the closure won't be executed.
1164
1167
///
1165
1168
/// # Panics
1166
- /// This method will panic when double buffering and one or both of the following conditions
1169
+ /// This method will panic when double buffering if one or both of the following conditions
1167
1170
/// happen:
1168
1171
///
1169
1172
/// * The new buffer's length is smaller than the one used in the `init` method.
@@ -1173,10 +1176,6 @@ where
1173
1176
///
1174
1177
/// Memory corruption might occur in the previous buffer, the one passed to the closure, if an
1175
1178
/// overrun occurs in double buffering mode.
1176
- ///
1177
- /// # Panics
1178
- ///
1179
- /// This method will panic if an overrun is detected while double buffering.
1180
1179
pub unsafe fn next_transfer_with < F , T > ( & mut self , f : F ) -> Result < T , DMAError < ( ) > >
1181
1180
where
1182
1181
F : FnOnce ( BUF , CurrentBuffer ) -> ( BUF , T ) ,
@@ -1216,6 +1215,8 @@ where
1216
1215
}
1217
1216
1218
1217
if current_buffer == CurrentBuffer :: DoubleBuffer {
1218
+ // "Preceding reads and writes cannot be moved past subsequent writes"
1219
+ compiler_fence ( Ordering :: Release ) ;
1219
1220
self . stream . set_memory_address ( new_buf_ptr as u32 ) ;
1220
1221
1221
1222
// Check again if an overrun occurred, the buffer address won't be updated in that
@@ -1230,8 +1231,11 @@ where
1230
1231
self . buf . replace ( new_buf) ;
1231
1232
return Ok ( r. 1 ) ;
1232
1233
} else {
1234
+ // "Preceding reads and writes cannot be moved past subsequent writes"
1235
+ compiler_fence ( Ordering :: Release ) ;
1233
1236
self . stream
1234
1237
. set_memory_double_buffer_address ( new_buf_ptr as u32 ) ;
1238
+
1235
1239
if self . stream . get_memory_double_buffer_address ( ) != new_buf_ptr as u32 {
1236
1240
panic ! ( "Overrun" ) ;
1237
1241
}
@@ -1259,11 +1263,7 @@ where
1259
1263
self . stream . set_number_of_transfers ( buf_len as u16 ) ;
1260
1264
self . buf . replace ( new_buf) ;
1261
1265
1262
- // "Preceding reads and writes cannot be moved past subsequent writes"
1263
- compiler_fence ( Ordering :: Release ) ;
1264
-
1265
1266
self . stream . enable ( ) ;
1266
-
1267
1267
Ok ( r. 1 )
1268
1268
}
1269
1269
}
0 commit comments