6
6
//! All of these functions should be blanket-`unsafe`. `cortex-m` provides safe wrappers where
7
7
//! applicable.
8
8
9
+ use core:: sync:: atomic:: { Ordering , compiler_fence} ;
10
+
9
11
#[ inline( always) ]
10
12
pub unsafe fn __bkpt ( ) {
11
13
asm ! ( "bkpt" ) ;
@@ -20,45 +22,58 @@ pub unsafe fn __control_r() -> u32 {
20
22
21
23
#[ inline( always) ]
22
24
pub 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 ) ;
24
31
}
25
32
26
33
#[ inline( always) ]
27
34
pub unsafe fn __cpsid ( ) {
28
35
asm ! ( "cpsid i" ) ;
36
+
37
+ // Ensure no subsequent instructions are reordered to before interrupts are disabled.
38
+ compiler_fence ( Ordering :: SeqCst ) ;
29
39
}
30
40
31
41
#[ inline( always) ]
32
42
pub unsafe fn __cpsie ( ) {
43
+ // Ensure no preceeding instructions are reordered to after interrupts are enabled.
44
+ compiler_fence ( Ordering :: SeqCst ) ;
45
+
33
46
asm ! ( "cpsie i" ) ;
34
47
}
35
48
36
49
#[ inline( always) ]
37
50
pub 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
+ ) ;
46
59
}
47
60
48
- // FIXME do we need compiler fences here or should we expect them in the caller?
49
61
#[ inline( always) ]
50
62
pub unsafe fn __dmb ( ) {
51
- asm ! ( "dmb 0xF" ) ;
63
+ asm ! ( "dmb" ) ;
64
+ compiler_fence ( Ordering :: AcqRel ) ;
52
65
}
53
66
54
67
#[ inline( always) ]
55
68
pub unsafe fn __dsb ( ) {
56
- asm ! ( "dsb 0xF" ) ;
69
+ asm ! ( "dsb" ) ;
70
+ compiler_fence ( Ordering :: SeqCst ) ;
57
71
}
58
72
59
73
#[ inline( always) ]
60
74
pub unsafe fn __isb ( ) {
61
- asm ! ( "isb 0xF" ) ;
75
+ asm ! ( "isb" ) ;
76
+ compiler_fence ( Ordering :: SeqCst ) ;
62
77
}
63
78
64
79
#[ inline( always) ]
@@ -93,28 +108,28 @@ pub unsafe fn __nop() {
93
108
#[ inline( always) ]
94
109
pub unsafe fn __pc_r ( ) -> u32 {
95
110
let r;
96
- asm ! ( "mov {}, R15 " , out( reg) r) ;
111
+ asm ! ( "mov {}, pc " , out( reg) r) ;
97
112
r
98
113
}
99
114
100
115
// NOTE: No FFI shim, this requires inline asm.
101
116
#[ inline( always) ]
102
117
pub unsafe fn __pc_w ( val : u32 ) {
103
- asm ! ( "mov R15 , {}" , in( reg) val) ;
118
+ asm ! ( "mov pc , {}" , in( reg) val) ;
104
119
}
105
120
106
121
// NOTE: No FFI shim, this requires inline asm.
107
122
#[ inline( always) ]
108
123
pub unsafe fn __lr_r ( ) -> u32 {
109
124
let r;
110
- asm ! ( "mov {}, R14 " , out( reg) r) ;
125
+ asm ! ( "mov {}, lr " , out( reg) r) ;
111
126
r
112
127
}
113
128
114
129
// NOTE: No FFI shim, this requires inline asm.
115
130
#[ inline( always) ]
116
131
pub unsafe fn __lr_w ( val : u32 ) {
117
- asm ! ( "mov R14 , {}" , in( reg) val) ;
132
+ asm ! ( "mov lr , {}" , in( reg) val) ;
118
133
}
119
134
120
135
#[ inline( always) ]
@@ -161,6 +176,8 @@ pub unsafe fn __wfi() {
161
176
pub use self :: v7m:: * ;
162
177
#[ cfg( any( armv7m, armv8m_main) ) ]
163
178
mod v7m {
179
+ use core:: sync:: atomic:: { Ordering , compiler_fence} ;
180
+
164
181
#[ inline( always) ]
165
182
pub unsafe fn __basepri_max ( val : u8 ) {
166
183
asm ! ( "msr BASEPRI_MAX, {}" , in( reg) val) ;
@@ -185,45 +202,42 @@ mod v7m {
185
202
r
186
203
}
187
204
188
- // FIXME: compiler_fences necessary?
189
205
#[ inline( always) ]
190
206
pub unsafe fn __enable_icache ( ) {
191
207
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) _,
206
220
) ;
221
+ compiler_fence ( Ordering :: SeqCst ) ;
207
222
}
208
223
209
224
#[ inline( always) ]
210
225
pub unsafe fn __enable_dcache ( ) {
211
226
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) _,
226
239
) ;
240
+ compiler_fence ( Ordering :: SeqCst ) ;
227
241
}
228
242
}
229
243
@@ -234,34 +248,30 @@ mod v7em {
234
248
#[ inline( always) ]
235
249
pub unsafe fn __basepri_max_cm7_r0p1 ( val : u8 ) {
236
250
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" ,
246
258
in( reg) val,
247
- out( "r1" ) _,
259
+ out( reg ) _,
248
260
) ;
249
261
}
250
262
251
263
#[ inline( always) ]
252
264
pub unsafe fn __basepri_w_cm7_r0p1 ( val : u8 ) {
253
265
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" ,
263
273
in( reg) val,
264
- out( "r1" ) _,
274
+ out( reg ) _,
265
275
) ;
266
276
}
267
277
}
0 commit comments