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,62 @@ 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 ! (
28
+ "msr CONTROL, {}" ,
29
+ "isb" ,
30
+ in( reg) w
31
+ ) ;
32
+
33
+ // Ensure memory accesses are not reordered around the CONTROL update.
34
+ compiler_fence ( Ordering :: SeqCst ) ;
24
35
}
25
36
26
37
#[ inline( always) ]
27
38
pub unsafe fn __cpsid ( ) {
28
39
asm ! ( "cpsid i" ) ;
40
+
41
+ // Ensure no subsequent memory accesses are reordered to before interrupts are disabled.
42
+ compiler_fence ( Ordering :: SeqCst ) ;
29
43
}
30
44
31
45
#[ inline( always) ]
32
46
pub unsafe fn __cpsie ( ) {
47
+ // Ensure no preceeding memory accesses are reordered to after interrupts are enabled.
48
+ compiler_fence ( Ordering :: SeqCst ) ;
49
+
33
50
asm ! ( "cpsie i" ) ;
34
51
}
35
52
36
53
#[ inline( always) ]
37
54
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 ) ;
55
+ // Use local labels to avoid R_ARM_THM_JUMP8 relocations which fail on thumbv6m.
56
+ asm ! (
57
+ "1:" ,
58
+ "nop" ,
59
+ "subs {}, #1" ,
60
+ "bne 1b" ,
61
+ in ( reg ) cyc
62
+ ) ;
46
63
}
47
64
48
- // FIXME do we need compiler fences here or should we expect them in the caller?
49
65
#[ inline( always) ]
50
66
pub unsafe fn __dmb ( ) {
51
- asm ! ( "dmb 0xF" ) ;
67
+ asm ! ( "dmb" ) ;
68
+ compiler_fence ( Ordering :: SeqCst ) ;
52
69
}
53
70
54
71
#[ inline( always) ]
55
72
pub unsafe fn __dsb ( ) {
56
- asm ! ( "dsb 0xF" ) ;
73
+ asm ! ( "dsb" ) ;
74
+ compiler_fence ( Ordering :: SeqCst ) ;
57
75
}
58
76
59
77
#[ inline( always) ]
60
78
pub unsafe fn __isb ( ) {
61
- asm ! ( "isb 0xF" ) ;
79
+ asm ! ( "isb" ) ;
80
+ compiler_fence ( Ordering :: SeqCst ) ;
62
81
}
63
82
64
83
#[ inline( always) ]
@@ -93,28 +112,28 @@ pub unsafe fn __nop() {
93
112
#[ inline( always) ]
94
113
pub unsafe fn __pc_r ( ) -> u32 {
95
114
let r;
96
- asm ! ( "mov {}, R15 " , out( reg) r) ;
115
+ asm ! ( "mov {}, pc " , out( reg) r) ;
97
116
r
98
117
}
99
118
100
119
// NOTE: No FFI shim, this requires inline asm.
101
120
#[ inline( always) ]
102
121
pub unsafe fn __pc_w ( val : u32 ) {
103
- asm ! ( "mov R15 , {}" , in( reg) val) ;
122
+ asm ! ( "mov pc , {}" , in( reg) val) ;
104
123
}
105
124
106
125
// NOTE: No FFI shim, this requires inline asm.
107
126
#[ inline( always) ]
108
127
pub unsafe fn __lr_r ( ) -> u32 {
109
128
let r;
110
- asm ! ( "mov {}, R14 " , out( reg) r) ;
129
+ asm ! ( "mov {}, lr " , out( reg) r) ;
111
130
r
112
131
}
113
132
114
133
// NOTE: No FFI shim, this requires inline asm.
115
134
#[ inline( always) ]
116
135
pub unsafe fn __lr_w ( val : u32 ) {
117
- asm ! ( "mov R14 , {}" , in( reg) val) ;
136
+ asm ! ( "mov lr , {}" , in( reg) val) ;
118
137
}
119
138
120
139
#[ inline( always) ]
@@ -161,6 +180,8 @@ pub unsafe fn __wfi() {
161
180
pub use self :: v7m:: * ;
162
181
#[ cfg( any( armv7m, armv8m_main) ) ]
163
182
mod v7m {
183
+ use core:: sync:: atomic:: { Ordering , compiler_fence} ;
184
+
164
185
#[ inline( always) ]
165
186
pub unsafe fn __basepri_max ( val : u8 ) {
166
187
asm ! ( "msr BASEPRI_MAX, {}" , in( reg) val) ;
@@ -185,45 +206,42 @@ mod v7m {
185
206
r
186
207
}
187
208
188
- // FIXME: compiler_fences necessary?
189
209
#[ inline( always) ]
190
210
pub unsafe fn __enable_icache ( ) {
191
211
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" ) _,
212
+ "ldr {0}, =0xE000ED14" , // CCR
213
+ "mrs {2}, PRIMASK" , // save critical nesting info
214
+ "cpsid i" , // mask interrupts
215
+ "ldr {1}, [{0}]" , // read CCR
216
+ "orr.w {1}, {1}, #(1 << 17)" , // Set bit 17, IC
217
+ "str {1}, [{0}]" , // write it back
218
+ "dsb" , // ensure store completes
219
+ "isb" , // synchronize pipeline
220
+ "msr PRIMASK, {2}" , // unnest critical section
221
+ out( reg) _,
222
+ out( reg) _,
223
+ out( reg) _,
206
224
) ;
225
+ compiler_fence ( Ordering :: SeqCst ) ;
207
226
}
208
227
209
228
#[ inline( always) ]
210
229
pub unsafe fn __enable_dcache ( ) {
211
230
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" ) _,
231
+ "ldr {0}, =0xE000ED14" , // CCR
232
+ "mrs {2}, PRIMASK" , // save critical nesting info
233
+ "cpsid i" , // mask interrupts
234
+ "ldr {1}, [{0}]" , // read CCR
235
+ "orr.w {1}, {1}, #(1 << 16)" , // Set bit 16, DC
236
+ "str {1}, [{0}]" , // write it back
237
+ "dsb" , // ensure store completes
238
+ "isb" , // synchronize pipeline
239
+ "msr PRIMASK, {2}" , // unnest critical section
240
+ out( reg) _,
241
+ out( reg) _,
242
+ out( reg) _,
226
243
) ;
244
+ compiler_fence ( Ordering :: SeqCst ) ;
227
245
}
228
246
}
229
247
@@ -234,34 +252,30 @@ mod v7em {
234
252
#[ inline( always) ]
235
253
pub unsafe fn __basepri_max_cm7_r0p1 ( val : u8 ) {
236
254
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
- " ,
255
+ "mrs {1}, PRIMASK" ,
256
+ "cpsid i" ,
257
+ "tst.w {1}, #1" ,
258
+ "msr BASEPRI_MAX, {0}" ,
259
+ "it ne" ,
260
+ "bxne lr" ,
261
+ "cpsie i" ,
246
262
in( reg) val,
247
- out( "r1" ) _,
263
+ out( reg ) _,
248
264
) ;
249
265
}
250
266
251
267
#[ inline( always) ]
252
268
pub unsafe fn __basepri_w_cm7_r0p1 ( val : u8 ) {
253
269
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
- " ,
270
+ "mrs {1}, PRIMASK" ,
271
+ "cpsid i" ,
272
+ "tst.w {1}, #1" ,
273
+ "msr BASEPRI, {0}" ,
274
+ "it ne" ,
275
+ "bxne lr" ,
276
+ "cpsie i" ,
263
277
in( reg) val,
264
- out( "r1" ) _,
278
+ out( reg ) _,
265
279
) ;
266
280
}
267
281
}
0 commit comments