11//! System Control Block
22
3+ #[ cfg( any( armv7m, armv8m) ) ]
4+ use core:: arch:: asm;
35use core:: ptr;
6+ #[ cfg( any( armv7m, armv8m) ) ]
7+ use core:: sync:: atomic:: { Ordering , compiler_fence} ;
48
59use volatile_register:: RW ;
610
@@ -304,6 +308,7 @@ impl SCB {
304308 ///
305309 /// This operation first invalidates the entire I-cache.
306310 #[ inline]
311+ #[ cortex_m_macros:: asm_cfg( any( armv7m, armv7em, armv8m) ) ]
307312 pub fn enable_icache ( & mut self ) {
308313 // Don't do anything if I-cache is already enabled
309314 if Self :: icache_enabled ( ) {
@@ -318,10 +323,25 @@ impl SCB {
318323
319324 // NOTE(unsafe): The asm routine manages exclusive access to the SCB
320325 // registers and applies the proper barriers; it is technically safe on
321- // its own, and is only `unsafe` here because it's `extern "C"` .
326+ // its own, and is only `unsafe` here because it's asm .
322327 unsafe {
323- crate :: asm:: inner:: __enable_icache ( ) ;
324- }
328+ asm ! (
329+ "ldr {0}, =0xE000ED14" , // CCR
330+ "mrs {2}, PRIMASK" , // save critical nesting info
331+ "cpsid i" , // mask interrupts
332+ "ldr {1}, [{0}]" , // read CCR
333+ "orr.w {1}, {1}, #(1 << 17)" , // Set bit 17, IC
334+ "str {1}, [{0}]" , // write it back
335+ "dsb" , // ensure store completes
336+ "isb" , // synchronize pipeline
337+ "msr PRIMASK, {2}" , // unnest critical section
338+ out( reg) _,
339+ out( reg) _,
340+ out( reg) _,
341+ options( nostack) ,
342+ )
343+ } ;
344+ compiler_fence ( Ordering :: SeqCst ) ;
325345 }
326346
327347 /// Disables I-cache if currently enabled.
@@ -360,6 +380,7 @@ impl SCB {
360380
361381 /// Invalidates the entire I-cache.
362382 #[ inline]
383+ #[ cortex_m_macros:: asm_cfg( any( armv6m, armv7m, armv7em, armv8m) ) ]
363384 pub fn invalidate_icache ( & mut self ) {
364385 // NOTE(unsafe): No races as all CBP registers are write-only and stateless
365386 let mut cbp = unsafe { CBP :: new ( ) } ;
@@ -376,6 +397,7 @@ impl SCB {
376397 /// This operation first invalidates the entire D-cache, ensuring it does
377398 /// not contain stale values before being enabled.
378399 #[ inline]
400+ #[ cortex_m_macros:: asm_cfg( any( armv6m, armv7m, armv7em, armv8m) ) ]
379401 pub fn enable_dcache ( & mut self , cpuid : & mut CPUID ) {
380402 // Don't do anything if D-cache is already enabled
381403 if Self :: dcache_enabled ( ) {
@@ -387,10 +409,26 @@ impl SCB {
387409
388410 // NOTE(unsafe): The asm routine manages exclusive access to the SCB
389411 // registers and applies the proper barriers; it is technically safe on
390- // its own, and is only `unsafe` here because it's `extern "C"` .
412+ // its own, and is only `unsafe` here because it's asm .
391413 unsafe {
392- crate :: asm:: inner:: __enable_dcache ( ) ;
393- }
414+ asm ! (
415+ // Should this be replaced with a register modify?
416+ "ldr {0}, =0xE000ED14" , // CCR
417+ "mrs {2}, PRIMASK" , // save critical nesting info
418+ "cpsid i" , // mask interrupts
419+ "ldr {1}, [{0}]" , // read CCR
420+ "orr.w {1}, {1}, #(1 << 16)" , // Set bit 16, DC
421+ "str {1}, [{0}]" , // write it back
422+ "dsb" , // ensure store completes
423+ "isb" , // synchronize pipeline
424+ "msr PRIMASK, {2}" , // unnest critical section
425+ out( reg) _,
426+ out( reg) _,
427+ out( reg) _,
428+ options( nostack) ,
429+ )
430+ } ;
431+ compiler_fence ( Ordering :: SeqCst ) ;
394432 }
395433
396434 /// Disables D-cache if currently enabled.
@@ -429,6 +467,7 @@ impl SCB {
429467 ///
430468 /// It's used immediately before enabling the dcache, but not exported publicly.
431469 #[ inline]
470+ #[ cfg( cortex_m) ]
432471 unsafe fn invalidate_dcache ( & mut self , cpuid : & mut CPUID ) {
433472 unsafe {
434473 // NOTE(unsafe): No races as all CBP registers are write-only and stateless
0 commit comments