@@ -864,9 +864,8 @@ where
864864 STREAM : Stream ,
865865 CHANNEL : Channel ,
866866 DIR : Direction ,
867- PERIPHERAL : PeriAddress ,
867+ PERIPHERAL : PeriAddress + DMASet < STREAM , CHANNEL , DIR > ,
868868 BUF : StaticWriteBuffer < Word = <PERIPHERAL as PeriAddress >:: MemSize > ,
869- ( STREAM , CHANNEL , PERIPHERAL , DIR ) : DMASet ,
870869{
871870 /// Applies all fields in DmaConfig.
872871 fn apply_config ( & mut self , config : config:: DmaConfig ) {
@@ -1008,8 +1007,9 @@ where
10081007 }
10091008
10101009 /// 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.
10131013 ///
10141014 /// This method will clear the transfer complete flag on entry, it will also clear it again if
10151015 /// an overrun occurs during its execution. Moreover, if an overrun occurs, the stream will be
@@ -1036,7 +1036,10 @@ where
10361036 }
10371037
10381038 if STREAM :: current_buffer ( ) == CurrentBuffer :: DoubleBuffer {
1039+ // "Preceding reads and writes cannot be moved past subsequent writes"
1040+ compiler_fence ( Ordering :: Release ) ;
10391041 self . stream . set_memory_address ( new_buf_ptr as u32 ) ;
1042+
10401043 // Check if an overrun occurred, the buffer address won't be updated in that case
10411044 if self . stream . get_memory_address ( ) != new_buf_ptr as u32 {
10421045 self . stream . clear_transfer_complete_interrupt ( ) ;
@@ -1051,8 +1054,11 @@ where
10511054 // We always have a buffer, so unwrap can't fail
10521055 return Ok ( ( old_buf. unwrap ( ) , CurrentBuffer :: FirstBuffer ) ) ;
10531056 } else {
1057+ // "Preceding reads and writes cannot be moved past subsequent writes"
1058+ compiler_fence ( Ordering :: Release ) ;
10541059 self . stream
10551060 . set_memory_double_buffer_address ( new_buf_ptr as u32 ) ;
1061+
10561062 // Check if an overrun occurred, the buffer address won't be updated in that case
10571063 if self . stream . get_memory_double_buffer_address ( ) != new_buf_ptr as u32 {
10581064 self . stream . clear_transfer_complete_interrupt ( ) ;
@@ -1081,9 +1087,6 @@ where
10811087 self . stream . set_number_of_transfers ( buf_len as u16 ) ;
10821088 let old_buf = self . buf . replace ( new_buf) ;
10831089
1084- // "Preceding reads and writes cannot be moved past subsequent writes"
1085- compiler_fence ( Ordering :: Release ) ;
1086-
10871090 unsafe {
10881091 self . stream . enable ( ) ;
10891092 }
@@ -1155,15 +1158,15 @@ where
11551158 }
11561159
11571160 /// 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.
11641167 ///
11651168 /// # 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
11671170 /// happen:
11681171 ///
11691172 /// * The new buffer's length is smaller than the one used in the `init` method.
@@ -1173,10 +1176,6 @@ where
11731176 ///
11741177 /// Memory corruption might occur in the previous buffer, the one passed to the closure, if an
11751178 /// overrun occurs in double buffering mode.
1176- ///
1177- /// # Panics
1178- ///
1179- /// This method will panic if an overrun is detected while double buffering.
11801179 pub unsafe fn next_transfer_with < F , T > ( & mut self , f : F ) -> Result < T , DMAError < ( ) > >
11811180 where
11821181 F : FnOnce ( BUF , CurrentBuffer ) -> ( BUF , T ) ,
@@ -1216,6 +1215,8 @@ where
12161215 }
12171216
12181217 if current_buffer == CurrentBuffer :: DoubleBuffer {
1218+ // "Preceding reads and writes cannot be moved past subsequent writes"
1219+ compiler_fence ( Ordering :: Release ) ;
12191220 self . stream . set_memory_address ( new_buf_ptr as u32 ) ;
12201221
12211222 // Check again if an overrun occurred, the buffer address won't be updated in that
@@ -1230,8 +1231,11 @@ where
12301231 self . buf . replace ( new_buf) ;
12311232 return Ok ( r. 1 ) ;
12321233 } else {
1234+ // "Preceding reads and writes cannot be moved past subsequent writes"
1235+ compiler_fence ( Ordering :: Release ) ;
12331236 self . stream
12341237 . set_memory_double_buffer_address ( new_buf_ptr as u32 ) ;
1238+
12351239 if self . stream . get_memory_double_buffer_address ( ) != new_buf_ptr as u32 {
12361240 panic ! ( "Overrun" ) ;
12371241 }
@@ -1259,11 +1263,7 @@ where
12591263 self . stream . set_number_of_transfers ( buf_len as u16 ) ;
12601264 self . buf . replace ( new_buf) ;
12611265
1262- // "Preceding reads and writes cannot be moved past subsequent writes"
1263- compiler_fence ( Ordering :: Release ) ;
1264-
12651266 self . stream . enable ( ) ;
1266-
12671267 Ok ( r. 1 )
12681268 }
12691269}
0 commit comments