3434#![ allow( unused_braces) ]
3535
3636use core:: marker:: PhantomData ;
37- use core:: sync:: atomic;
3837
3938use atsamd_hal_macros:: { hal_cfg, hal_macro_helper} ;
4039
@@ -271,10 +270,7 @@ impl<Id: ChId, S: Status> Channel<Id, S> {
271270 /// Enable the transfer, and emit a compiler fence.
272271 #[ inline]
273272 fn _enable_private ( & mut self ) {
274- // Prevent the compiler from re-ordering read/write
275- // operations beyond this fence.
276- // (see https://docs.rust-embedded.org/embedonomicon/dma.html#compiler-misoptimizations)
277- atomic:: fence ( atomic:: Ordering :: Release ) ; // ▲
273+ release_fence ( ) ; // ▲
278274 self . regs . chctrla . modify ( |_, w| w. enable ( ) . set_bit ( ) ) ;
279275 }
280276
@@ -288,10 +284,7 @@ impl<Id: ChId, S: Status> Channel<Id, S> {
288284 core:: hint:: spin_loop ( ) ;
289285 }
290286
291- // Prevent the compiler from re-ordering read/write
292- // operations beyond this fence.
293- // (see https://docs.rust-embedded.org/embedonomicon/dma.html#compiler-misoptimizations)
294- atomic:: fence ( atomic:: Ordering :: Acquire ) ; // ▼
287+ acquire_fence ( ) ; // ▼
295288 }
296289
297290 /// Returns whether or not the transfer is complete.
@@ -882,3 +875,33 @@ pub(crate) unsafe fn write_descriptor<Src: Buffer, Dst: Buffer<Beat = Src::Beat>
882875 btctrl,
883876 } ;
884877}
878+
879+ /// Prevent the compiler from re-ordering read/write
880+ /// operations beyond this function.
881+ /// (see https://docs.rust-embedded.org/embedonomicon/dma.html#compiler-misoptimizations)
882+ #[ inline( always) ]
883+ pub ( super ) fn acquire_fence ( ) {
884+ // TODO: Seems like compiler fences aren't enough to guarantee memory accesses won't be reordered.
885+ // (see https://users.rust-lang.org/t/compiler-fence-dma/132027)
886+ // core::sync::atomic::fence(core::sync::atomic::Ordering::Acquire); // ▼
887+
888+ // Apparently, the only truly foolproof way to prevent reordering is with inline asm
889+ unsafe {
890+ core:: arch:: asm!( "dmb" ) ;
891+ }
892+ }
893+
894+ /// Prevent the compiler from re-ordering read/write
895+ /// operations beyond this function.
896+ /// (see https://docs.rust-embedded.org/embedonomicon/dma.html#compiler-misoptimizations)
897+ #[ inline( always) ]
898+ pub ( super ) fn release_fence ( ) {
899+ // TODO: Seems like compiler fences aren't enough to guarantee memory accesses won't be reordered.
900+ // (see https://users.rust-lang.org/t/compiler-fence-dma/132027)
901+ // core::sync::atomic::fence(atomic::Ordering::Release); // ▲
902+
903+ // Apparently, the only truly foolproof way to prevent reordering is with inline asm
904+ unsafe {
905+ core:: arch:: asm!( "dmb" ) ;
906+ }
907+ }
0 commit comments