Skip to content

Commit 718cd17

Browse files
Merge #164
164: Allow writing to the CONTROL register r=adamgreig a=jonas-schievink This allows entering unprivileged mode. Part of #58 Co-authored-by: Jonas Schievink <[email protected]>
2 parents b4d2e9e + 3d1fd33 commit 718cd17

9 files changed

+86
-5
lines changed

asm.s

+11-3
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,21 @@ __bkpt:
55
bkpt
66
bx lr
77

8-
.section .text.__control
9-
.global __control
8+
.section .text.__control_r
9+
.global __control_r
1010
.thumb_func
11-
__control:
11+
__control_r:
1212
mrs r0, CONTROL
1313
bx lr
1414

15+
.section .text.__control_w
16+
.global __control_w
17+
.thumb_func
18+
__control_w:
19+
msr CONTROL, r0
20+
bx lr
21+
22+
1523
.section .text.__cpsid
1624
.global __cpsid
1725
.thumb_func

bin/thumbv6m-none-eabi.a

150 Bytes
Binary file not shown.

bin/thumbv7em-none-eabi.a

150 Bytes
Binary file not shown.

bin/thumbv7em-none-eabihf.a

150 Bytes
Binary file not shown.

bin/thumbv7m-none-eabi.a

150 Bytes
Binary file not shown.

bin/thumbv8m.base-none-eabi.a

150 Bytes
Binary file not shown.

bin/thumbv8m.main-none-eabi.a

150 Bytes
Binary file not shown.

bin/thumbv8m.main-none-eabihf.a

150 Bytes
Binary file not shown.

src/register/control.rs

+75-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,20 @@ pub struct Control {
77
}
88

99
impl Control {
10+
/// Creates a `Control` value from raw bits.
11+
#[inline]
12+
pub fn from_bits(bits: u32) -> Self {
13+
Self { bits }
14+
}
15+
1016
/// Returns the contents of the register as raw bits
17+
#[inline]
1118
pub fn bits(&self) -> u32 {
1219
self.bits
1320
}
1421

1522
/// Thread mode privilege level
23+
#[inline]
1624
pub fn npriv(&self) -> Npriv {
1725
if self.bits & (1 << 0) == (1 << 0) {
1826
Npriv::Unprivileged
@@ -21,7 +29,18 @@ impl Control {
2129
}
2230
}
2331

32+
/// Sets the thread mode privilege level value (nPRIV).
33+
#[inline]
34+
pub fn set_npriv(&mut self, npriv: Npriv) {
35+
let mask = 1 << 0;
36+
match npriv {
37+
Npriv::Unprivileged => self.bits |= mask,
38+
Npriv::Privileged => self.bits &= !mask,
39+
}
40+
}
41+
2442
/// Currently active stack pointer
43+
#[inline]
2544
pub fn spsel(&self) -> Spsel {
2645
if self.bits & (1 << 1) == (1 << 1) {
2746
Spsel::Psp
@@ -30,14 +49,35 @@ impl Control {
3049
}
3150
}
3251

52+
/// Sets the SPSEL value.
53+
#[inline]
54+
pub fn set_spsel(&mut self, spsel: Spsel) {
55+
let mask = 1 << 1;
56+
match spsel {
57+
Spsel::Psp => self.bits |= mask,
58+
Spsel::Msp => self.bits &= !mask,
59+
}
60+
}
61+
3362
/// Whether context floating-point is currently active
63+
#[inline]
3464
pub fn fpca(&self) -> Fpca {
3565
if self.bits & (1 << 2) == (1 << 2) {
3666
Fpca::Active
3767
} else {
3868
Fpca::NotActive
3969
}
4070
}
71+
72+
/// Sets the FPCA value.
73+
#[inline]
74+
pub fn set_fpca(&mut self, fpca: Fpca) {
75+
let mask = 1 << 2;
76+
match fpca {
77+
Fpca::Active => self.bits |= mask,
78+
Fpca::NotActive => self.bits &= !mask,
79+
}
80+
}
4181
}
4282

4383
/// Thread mode privilege level
@@ -51,11 +91,13 @@ pub enum Npriv {
5191

5292
impl Npriv {
5393
/// Is in privileged thread mode?
94+
#[inline]
5495
pub fn is_privileged(&self) -> bool {
5596
*self == Npriv::Privileged
5697
}
5798

5899
/// Is in unprivileged thread mode?
100+
#[inline]
59101
pub fn is_unprivileged(&self) -> bool {
60102
*self == Npriv::Unprivileged
61103
}
@@ -72,11 +114,13 @@ pub enum Spsel {
72114

73115
impl Spsel {
74116
/// Is MSP the current stack pointer?
117+
#[inline]
75118
pub fn is_msp(&self) -> bool {
76119
*self == Spsel::Msp
77120
}
78121

79122
/// Is PSP the current stack pointer?
123+
#[inline]
80124
pub fn is_psp(&self) -> bool {
81125
*self == Spsel::Psp
82126
}
@@ -93,11 +137,13 @@ pub enum Fpca {
93137

94138
impl Fpca {
95139
/// Is a floating-point context active?
140+
#[inline]
96141
pub fn is_active(&self) -> bool {
97142
*self == Fpca::Active
98143
}
99144

100145
/// Is a floating-point context not active?
146+
#[inline]
101147
pub fn is_not_active(&self) -> bool {
102148
*self == Fpca::NotActive
103149
}
@@ -120,10 +166,10 @@ pub fn read() -> Control {
120166
#[cfg(not(feature = "inline-asm"))]
121167
() => unsafe {
122168
extern "C" {
123-
fn __control() -> u32;
169+
fn __control_r() -> u32;
124170
}
125171

126-
__control()
172+
__control_r()
127173
},
128174
};
129175

@@ -134,3 +180,30 @@ pub fn read() -> Control {
134180
() => unimplemented!(),
135181
}
136182
}
183+
184+
/// Writes to the CPU register.
185+
#[inline]
186+
pub unsafe fn write(_control: Control) {
187+
match () {
188+
#[cfg(cortex_m)]
189+
() => match () {
190+
#[cfg(feature = "inline-asm")]
191+
() => {
192+
let control = _control.bits();
193+
asm!("msr CONTROL, $0" :: "r"(control) : "memory" : "volatile");
194+
}
195+
196+
#[cfg(not(feature = "inline-asm"))]
197+
() => {
198+
extern "C" {
199+
fn __control_w(bits: u32);
200+
}
201+
202+
__control_w(_control.bits());
203+
}
204+
},
205+
206+
#[cfg(not(cortex_m))]
207+
() => unimplemented!(),
208+
}
209+
}

0 commit comments

Comments
 (0)