66//! All of these functions should be blanket-`unsafe`. `cortex-m` provides safe wrappers where
77//! applicable.
88
9+ use core:: sync:: atomic:: { Ordering , compiler_fence} ;
10+
911#[ inline( always) ]
1012pub unsafe fn __bkpt ( ) {
1113 asm ! ( "bkpt" ) ;
@@ -20,45 +22,58 @@ pub unsafe fn __control_r() -> u32 {
2022
2123#[ inline( always) ]
2224pub unsafe fn __control_w ( w : u32 ) {
23- asm ! ( "msr CONTROL, {}" , in( reg) w) ;
25+ // ISB is required after writing to CONTROL,
26+ // per ARM architectural requirements (see Application Note 321).
27+ asm ! ( "msr CONTROL, {}" , "isb" , in( reg) w) ;
28+
29+ // Ensure instructions are not reordered around the CONTROL update.
30+ compiler_fence ( Ordering :: SeqCst ) ;
2431}
2532
2633#[ inline( always) ]
2734pub unsafe fn __cpsid ( ) {
2835 asm ! ( "cpsid i" ) ;
36+
37+ // Ensure no subsequent instructions are reordered to before interrupts are disabled.
38+ compiler_fence ( Ordering :: SeqCst ) ;
2939}
3040
3141#[ inline( always) ]
3242pub unsafe fn __cpsie ( ) {
43+ // Ensure no preceeding instructions are reordered to after interrupts are enabled.
44+ compiler_fence ( Ordering :: SeqCst ) ;
45+
3346 asm ! ( "cpsie i" ) ;
3447}
3548
3649#[ inline( always) ]
3750pub unsafe fn __delay ( cyc : u32 ) {
38- asm ! ( "
39- 1:
40- nop
41- subs {}, #1
42- bne 1b
43- // Branch to 1 instead of delay does not generate R_ARM_THM_JUMP8 relocation, which breaks
44- // linking on the thumbv6m-none-eabi target
45- " , in ( reg ) cyc ) ;
51+ // Use local labels to avoid R_ARM_THM_JUMP8 relocations which fail on thumbv6m.
52+ asm ! (
53+ "1:" ,
54+ "nop" ,
55+ "subs {}, #1" ,
56+ "bne 1b" ,
57+ in ( reg ) cyc
58+ ) ;
4659}
4760
48- // FIXME do we need compiler fences here or should we expect them in the caller?
4961#[ inline( always) ]
5062pub unsafe fn __dmb ( ) {
51- asm ! ( "dmb 0xF" ) ;
63+ asm ! ( "dmb" ) ;
64+ compiler_fence ( Ordering :: AcqRel ) ;
5265}
5366
5467#[ inline( always) ]
5568pub unsafe fn __dsb ( ) {
56- asm ! ( "dsb 0xF" ) ;
69+ asm ! ( "dsb" ) ;
70+ compiler_fence ( Ordering :: SeqCst ) ;
5771}
5872
5973#[ inline( always) ]
6074pub unsafe fn __isb ( ) {
61- asm ! ( "isb 0xF" ) ;
75+ asm ! ( "isb" ) ;
76+ compiler_fence ( Ordering :: SeqCst ) ;
6277}
6378
6479#[ inline( always) ]
@@ -93,28 +108,28 @@ pub unsafe fn __nop() {
93108#[ inline( always) ]
94109pub unsafe fn __pc_r ( ) -> u32 {
95110 let r;
96- asm ! ( "mov {}, R15 " , out( reg) r) ;
111+ asm ! ( "mov {}, pc " , out( reg) r) ;
97112 r
98113}
99114
100115// NOTE: No FFI shim, this requires inline asm.
101116#[ inline( always) ]
102117pub unsafe fn __pc_w ( val : u32 ) {
103- asm ! ( "mov R15 , {}" , in( reg) val) ;
118+ asm ! ( "mov pc , {}" , in( reg) val) ;
104119}
105120
106121// NOTE: No FFI shim, this requires inline asm.
107122#[ inline( always) ]
108123pub unsafe fn __lr_r ( ) -> u32 {
109124 let r;
110- asm ! ( "mov {}, R14 " , out( reg) r) ;
125+ asm ! ( "mov {}, lr " , out( reg) r) ;
111126 r
112127}
113128
114129// NOTE: No FFI shim, this requires inline asm.
115130#[ inline( always) ]
116131pub unsafe fn __lr_w ( val : u32 ) {
117- asm ! ( "mov R14 , {}" , in( reg) val) ;
132+ asm ! ( "mov lr , {}" , in( reg) val) ;
118133}
119134
120135#[ inline( always) ]
@@ -161,6 +176,8 @@ pub unsafe fn __wfi() {
161176pub use self :: v7m:: * ;
162177#[ cfg( any( armv7m, armv8m_main) ) ]
163178mod v7m {
179+ use core:: sync:: atomic:: { Ordering , compiler_fence} ;
180+
164181 #[ inline( always) ]
165182 pub unsafe fn __basepri_max ( val : u8 ) {
166183 asm ! ( "msr BASEPRI_MAX, {}" , in( reg) val) ;
@@ -185,45 +202,42 @@ mod v7m {
185202 r
186203 }
187204
188- // FIXME: compiler_fences necessary?
189205 #[ inline( always) ]
190206 pub unsafe fn __enable_icache ( ) {
191207 asm ! (
192- "
193- ldr r0, =0xE000ED14 @ CCR
194- mrs r2, PRIMASK @ save critical nesting info
195- cpsid i @ mask interrupts
196- ldr r1, [r0] @ read CCR
197- orr.w r1, r1, #(1 << 17) @ Set bit 17, IC
198- str r1, [r0] @ write it back
199- dsb @ ensure store completes
200- isb @ synchronize pipeline
201- msr PRIMASK, r2 @ unnest critical section
202- " ,
203- out( "r0" ) _,
204- out( "r1" ) _,
205- out( "r2" ) _,
208+ "ldr {0}, =0xE000ED14" , // CCR
209+ "mrs {2}, PRIMASK" , // save critical nesting info
210+ "cpsid i" , // mask interrupts
211+ "ldr {1}, [{0}]" , // read CCR
212+ "orr.w {1}, {1}, #(1 << 17)" , // Set bit 17, IC
213+ "str {1}, [{0}]" , // write it back
214+ "dsb" , // ensure store completes
215+ "isb" , // synchronize pipeline
216+ "msr PRIMASK, {2}" , // unnest critical section
217+ out( reg) _,
218+ out( reg) _,
219+ out( reg) _,
206220 ) ;
221+ compiler_fence ( Ordering :: SeqCst ) ;
207222 }
208223
209224 #[ inline( always) ]
210225 pub unsafe fn __enable_dcache ( ) {
211226 asm ! (
212- "
213- ldr r0, =0xE000ED14 @ CCR
214- mrs r2, PRIMASK @ save critical nesting info
215- cpsid i @ mask interrupts
216- ldr r1, [r0] @ read CCR
217- orr.w r1, r1, #(1 << 16) @ Set bit 16, DC
218- str r1, [r0] @ write it back
219- dsb @ ensure store completes
220- isb @ synchronize pipeline
221- msr PRIMASK, r2 @ unnest critical section
222- " ,
223- out( "r0" ) _,
224- out( "r1" ) _,
225- out( "r2" ) _,
227+ "ldr {0}, =0xE000ED14" , // CCR
228+ "mrs {2}, PRIMASK" , // save critical nesting info
229+ "cpsid i" , // mask interrupts
230+ "ldr {1}, [{0}]" , // read CCR
231+ "orr.w {1}, {1}, #(1 << 16)" , // Set bit 16, DC
232+ "str {1}, [{0}]" , // write it back
233+ "dsb" , // ensure store completes
234+ "isb" , // synchronize pipeline
235+ "msr PRIMASK, {2}" , // unnest critical section
236+ out( reg) _,
237+ out( reg) _,
238+ out( reg) _,
226239 ) ;
240+ compiler_fence ( Ordering :: SeqCst ) ;
227241 }
228242}
229243
@@ -234,34 +248,30 @@ mod v7em {
234248 #[ inline( always) ]
235249 pub unsafe fn __basepri_max_cm7_r0p1 ( val : u8 ) {
236250 asm ! (
237- "
238- mrs r1, PRIMASK
239- cpsid i
240- tst.w r1, #1
241- msr BASEPRI_MAX, {}
242- it ne
243- bxne lr
244- cpsie i
245- " ,
251+ "mrs {1}, PRIMASK" ,
252+ "cpsid i" ,
253+ "tst.w {1}, #1" ,
254+ "msr BASEPRI_MAX, {0}" ,
255+ "it ne" ,
256+ "bxne lr" ,
257+ "cpsie i" ,
246258 in( reg) val,
247- out( "r1" ) _,
259+ out( reg ) _,
248260 ) ;
249261 }
250262
251263 #[ inline( always) ]
252264 pub unsafe fn __basepri_w_cm7_r0p1 ( val : u8 ) {
253265 asm ! (
254- "
255- mrs r1, PRIMASK
256- cpsid i
257- tst.w r1, #1
258- msr BASEPRI, {}
259- it ne
260- bxne lr
261- cpsie i
262- " ,
266+ "mrs {1}, PRIMASK" ,
267+ "cpsid i" ,
268+ "tst.w {1}, #1" ,
269+ "msr BASEPRI, {0}" ,
270+ "it ne" ,
271+ "bxne lr" ,
272+ "cpsie i" ,
263273 in( reg) val,
264- out( "r1" ) _,
274+ out( reg ) _,
265275 ) ;
266276 }
267277}
0 commit comments