Skip to content

Commit cc5a302

Browse files
committed
Use assembly sequences to enable caches.
See rust-embedded#232, which this partially fixes -- there's still the question of taking an interrupt in the midst of these sequences.
1 parent b70c25a commit cc5a302

File tree

2 files changed

+106
-8
lines changed

2 files changed

+106
-8
lines changed

asm-v7.s

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,33 @@ __faultmask:
3939
bx lr
4040
.cfi_endproc
4141
.size __faultmask, . - __faultmask
42+
43+
.section .text.__enable_icache
44+
.global __enable_icache
45+
.thumb_func
46+
.cfi_startproc
47+
__enable_icache:
48+
ldr r0, =0xE000ED14 @ CCR
49+
ldr r1, [r0] @ read CCR
50+
orr.w r1, r1, #(1 << 17) @ Set bit 17, IC
51+
str r1, [r0] @ write it back
52+
dsb @ ensure store completes
53+
isb @ synchronize pipeline
54+
bx lr
55+
.cfi_endproc
56+
.size __enable_icache, . - __enable_icache
57+
58+
.section .text.__enable_dcache
59+
.global __enable_dcache
60+
.thumb_func
61+
.cfi_startproc
62+
__enable_dcache:
63+
ldr r0, =0xE000ED14 @ CCR
64+
ldr r1, [r0] @ read CCR
65+
orr.w r1, r1, #(1 << 16) @ Set bit 16, DC
66+
str r1, [r0] @ write it back
67+
dsb @ ensure store completes
68+
isb @ synchronize pipeline
69+
bx lr
70+
.cfi_endproc
71+
.size __enable_dcache, . - __enable_dcache

src/peripheral/scb.rs

Lines changed: 76 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -331,11 +331,45 @@ impl SCB {
331331
cbp.iciallu();
332332

333333
// Enable I-cache
334-
// NOTE(unsafe): We have synchronised access by &mut self
335-
unsafe { self.ccr.modify(|r| r | SCB_CCR_IC_MASK) };
334+
match () {
335+
#[cfg(not(feature = "inline-asm"))]
336+
() => {
337+
extern "C" {
338+
// see asm-v7m.s
339+
fn __enable_icache();
340+
}
341+
342+
// NOTE(unsafe): Having &mut self means no ISR, for example, is
343+
// going to try to alter this register at the same time. That
344+
// being said, this is still unsafe if not executed in a
345+
// critical section (TODO).
346+
unsafe { __enable_icache(); }
347+
}
348+
#[cfg(feature = "inline-asm")]
349+
() => {
350+
// NOTE(unsafe): Having &mut self means no ISR, for example, is
351+
// going to try to alter this register at the same time. That
352+
// being said, this is still unsafe if not executed in a
353+
// critical section (TODO).
354+
unsafe {
355+
let _unused_ccr_val: u32;
356+
llvm_asm!("
357+
ldr $0, [$1]
358+
orr.w $0, $0, $2
359+
str $0, [$1]
360+
dsb
361+
isb
362+
"
363+
: "=&r"(_unused_ccr_val)
364+
: "r"(&self.ccr),
365+
"c"(SCB_CCR_IC_MASK)
366+
: "memory"
367+
: "volatile"
368+
);
369+
}
370+
}
336371

337-
crate::asm::dsb();
338-
crate::asm::isb();
372+
}
339373
}
340374

341375
/// Disables I-cache if currently enabled.
@@ -401,10 +435,44 @@ impl SCB {
401435

402436
// Now turn on the D-cache
403437
// NOTE(unsafe): We have synchronised access by &mut self
404-
unsafe { self.ccr.modify(|r| r | SCB_CCR_DC_MASK) };
405-
406-
crate::asm::dsb();
407-
crate::asm::isb();
438+
match () {
439+
#[cfg(not(feature = "inline-asm"))]
440+
() => {
441+
extern "C" {
442+
// see asm-v7m.s
443+
fn __enable_dcache();
444+
}
445+
446+
// NOTE(unsafe): Having &mut self means no ISR, for example, is
447+
// going to try to alter this register at the same time. That
448+
// being said, this is still unsafe if not executed in a
449+
// critical section (TODO).
450+
unsafe { __enable_dcache(); }
451+
}
452+
#[cfg(feature = "inline-asm")]
453+
() => {
454+
// NOTE(unsafe): Having &mut self means no ISR, for example, is
455+
// going to try to alter this register at the same time. That
456+
// being said, this is still unsafe if not executed in a
457+
// critical section (TODO).
458+
unsafe {
459+
let _unused_ccr_val: u32;
460+
llvm_asm!("
461+
ldr $0, [$1]
462+
orr.w $0, $0, $2
463+
str $0, [$1]
464+
dsb
465+
isb
466+
"
467+
: "=&r"(_unused_ccr_val)
468+
: "r"(&self.ccr),
469+
"c"(SCB_CCR_DC_MASK)
470+
: "memory"
471+
: "volatile"
472+
);
473+
}
474+
}
475+
}
408476
}
409477

410478
/// Disables D-cache if currently enabled.

0 commit comments

Comments
 (0)