Skip to content

Commit 14e748f

Browse files
committed
Use const control register code instead of magic numbers.
Also fixes the enter_privilged_function, which forgot to the change the mode so we didn't actually start using the PSP.
1 parent a951c1f commit 14e748f

File tree

2 files changed

+46
-5
lines changed

2 files changed

+46
-5
lines changed

cortex-m/src/asm.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,13 @@ pub unsafe fn semihosting_syscall(nr: u32, arg: u32) -> u32 {
195195
#[cfg(cortex_m)]
196196
#[inline(always)]
197197
pub unsafe fn enter_unprivileged_psp(psp: *const u32, entry: extern "C" fn() -> !) -> ! {
198+
use crate::register::control::{Control, Npriv, Spsel};
199+
const CONTROL_FLAGS: u32 = {
200+
Control::from_bits(0)
201+
.with_npriv(Npriv::Unprivileged)
202+
.with_spsel(Spsel::Psp)
203+
.bits()
204+
};
198205
unsafe {
199206
core::arch::asm!(
200207
"msr PSP, {psp}",
@@ -204,7 +211,7 @@ pub unsafe fn enter_unprivileged_psp(psp: *const u32, entry: extern "C" fn() ->
204211
"isb",
205212
"bx {ent}",
206213
tmp = in(reg) 0,
207-
flags = in(reg) 3,
214+
flags = in(reg) CONTROL_FLAGS,
208215
psp = in(reg) psp,
209216
ent = in(reg) entry,
210217
options(noreturn, nostack)
@@ -230,11 +237,23 @@ pub unsafe fn enter_unprivileged_psp(psp: *const u32, entry: extern "C" fn() ->
230237
#[cfg(cortex_m)]
231238
#[inline(always)]
232239
pub unsafe fn enter_privileged_psp(psp: *const u32, entry: extern "C" fn() -> !) -> ! {
240+
use crate::register::control::{Control, Npriv, Spsel};
241+
const CONTROL_FLAGS: u32 = {
242+
Control::from_bits(0)
243+
.with_npriv(Npriv::Privileged)
244+
.with_spsel(Spsel::Psp)
245+
.bits()
246+
};
233247
unsafe {
234248
core::arch::asm!(
235-
"msr PSP, {psp}",
249+
"msr PSP, {psp}",
250+
"mrs {tmp}, CONTROL",
251+
"orrs {tmp}, {flags}",
252+
"msr CONTROL, {tmp}",
236253
"isb",
237-
"bx {ent}",
254+
"bx {ent}",
255+
tmp = in(reg) 0,
256+
flags = in(reg) CONTROL_FLAGS,
238257
psp = in(reg) psp,
239258
ent = in(reg) entry,
240259
options(noreturn, nostack)

cortex-m/src/register/control.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ pub struct Control {
99
impl Control {
1010
/// Creates a `Control` value from raw bits.
1111
#[inline]
12-
pub fn from_bits(bits: u32) -> Self {
12+
pub const fn from_bits(bits: u32) -> Self {
1313
Self { bits }
1414
}
1515

1616
/// Returns the contents of the register as raw bits
1717
#[inline]
18-
pub fn bits(self) -> u32 {
18+
pub const fn bits(self) -> u32 {
1919
self.bits
2020
}
2121

@@ -39,6 +39,17 @@ impl Control {
3939
}
4040
}
4141

42+
/// Sets the thread mode privilege level value (nPRIV).
43+
#[inline]
44+
pub const fn with_npriv(self, npriv: Npriv) -> Self {
45+
let mask = 1 << 0;
46+
let bits = match npriv {
47+
Npriv::Unprivileged => self.bits | mask,
48+
Npriv::Privileged => self.bits & !mask,
49+
};
50+
Self { bits }
51+
}
52+
4253
/// Currently active stack pointer
4354
#[inline]
4455
pub fn spsel(self) -> Spsel {
@@ -59,6 +70,17 @@ impl Control {
5970
}
6071
}
6172

73+
/// Sets the SPSEL value.
74+
#[inline]
75+
pub const fn with_spsel(self, spsel: Spsel) -> Self {
76+
let mask = 1 << 1;
77+
let bits = match spsel {
78+
Spsel::Psp => self.bits | mask,
79+
Spsel::Msp => self.bits & !mask,
80+
};
81+
Self { bits }
82+
}
83+
6284
/// Whether context floating-point is currently active
6385
#[inline]
6486
pub fn fpca(self) -> Fpca {

0 commit comments

Comments
 (0)