Skip to content

Commit f812b5f

Browse files
Allow writing to the CONTROL register
1 parent 97c7aab commit f812b5f

9 files changed

+74
-5
lines changed

asm.s

Lines changed: 11 additions & 3 deletions
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

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ pub struct Control {
77
}
88

99
impl Control {
10+
/// Creates a `Control` value from raw bits.
11+
pub fn from_bits(bits: u32) -> Self {
12+
Self { bits }
13+
}
14+
1015
/// Returns the contents of the register as raw bits
1116
pub fn bits(&self) -> u32 {
1217
self.bits
@@ -21,6 +26,15 @@ impl Control {
2126
}
2227
}
2328

29+
/// Sets the thread mode privilege level value (nPRIV).
30+
pub fn set_npriv(&mut self, npriv: Npriv) {
31+
let mask = 1 << 0;
32+
match npriv {
33+
Npriv::Unprivileged => self.bits |= mask,
34+
Npriv::Privileged => self.bits &= !mask,
35+
}
36+
}
37+
2438
/// Currently active stack pointer
2539
pub fn spsel(&self) -> Spsel {
2640
if self.bits & (1 << 1) == (1 << 1) {
@@ -30,6 +44,15 @@ impl Control {
3044
}
3145
}
3246

47+
/// Sets the SPSEL value.
48+
pub fn set_spsel(&mut self, spsel: Spsel) {
49+
let mask = 1 << 1;
50+
match spsel {
51+
Spsel::Psp => self.bits |= mask,
52+
Spsel::Msp => self.bits &= !mask,
53+
}
54+
}
55+
3356
/// Whether context floating-point is currently active
3457
pub fn fpca(&self) -> Fpca {
3558
if self.bits & (1 << 2) == (1 << 2) {
@@ -38,6 +61,15 @@ impl Control {
3861
Fpca::NotActive
3962
}
4063
}
64+
65+
/// Sets the FPCA value.
66+
pub fn set_fpca(&mut self, fpca: Fpca) {
67+
let mask = 1 << 2;
68+
match fpca {
69+
Fpca::Active => self.bits |= mask,
70+
Fpca::NotActive => self.bits &= !mask,
71+
}
72+
}
4173
}
4274

4375
/// Thread mode privilege level
@@ -120,10 +152,10 @@ pub fn read() -> Control {
120152
#[cfg(not(feature = "inline-asm"))]
121153
() => unsafe {
122154
extern "C" {
123-
fn __control() -> u32;
155+
fn __control_r() -> u32;
124156
}
125157

126-
__control()
158+
__control_r()
127159
},
128160
};
129161

@@ -134,3 +166,32 @@ pub fn read() -> Control {
134166
() => unimplemented!(),
135167
}
136168
}
169+
170+
/// Writes to the CPU register.
171+
#[inline]
172+
pub unsafe fn write(_control: Control) {
173+
match () {
174+
#[cfg(cortex_m)]
175+
() => {
176+
let r = match () {
177+
#[cfg(feature = "inline-asm")]
178+
() => {
179+
let control = _control.bits();
180+
unsafe { asm!("msr CONTROL, $0" :: "r"(control) : "memory" : "volatile") }
181+
}
182+
183+
#[cfg(not(feature = "inline-asm"))]
184+
() => unsafe {
185+
extern "C" {
186+
fn __control_w() -> u32;
187+
}
188+
189+
__control_w(_control.bits())
190+
},
191+
};
192+
}
193+
194+
#[cfg(not(cortex_m))]
195+
() => unimplemented!(),
196+
}
197+
}

0 commit comments

Comments
 (0)