1//! Control register
2
3/// Control register
4#[derive(Clone, Copy, Debug)]
5pub struct Control {
6 bits: u32,
7}
8
9impl Control {
10 /// Creates a `Control` value from raw bits.
11 #[inline]
12 pub fn from_bits(bits: u32) -> Self {
13 Self { bits }
14 }
15
16 /// Returns the contents of the register as raw bits
17 #[inline]
18 pub fn bits(self) -> u32 {
19 self.bits
20 }
21
22 /// Thread mode privilege level
23 #[inline]
24 pub fn npriv(self) -> Npriv {
25 if self.bits & (1 << 0) == (1 << 0) {
26 Npriv::Unprivileged
27 } else {
28 Npriv::Privileged
29 }
30 }
31
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
42 /// Currently active stack pointer
43 #[inline]
44 pub fn spsel(self) -> Spsel {
45 if self.bits & (1 << 1) == (1 << 1) {
46 Spsel::Psp
47 } else {
48 Spsel::Msp
49 }
50 }
51
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
62 /// Whether context floating-point is currently active
63 #[inline]
64 pub fn fpca(self) -> Fpca {
65 if self.bits & (1 << 2) == (1 << 2) {
66 Fpca::Active
67 } else {
68 Fpca::NotActive
69 }
70 }
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 }
81}
82
83/// Thread mode privilege level
84#[derive(Clone, Copy, Debug, Eq, PartialEq)]
85pub enum Npriv {
86 /// Privileged
87 Privileged,
88 /// Unprivileged
89 Unprivileged,
90}
91
92impl Npriv {
93 /// Is in privileged thread mode?
94 #[inline]
95 pub fn is_privileged(self) -> bool {
96 self == Npriv::Privileged
97 }
98
99 /// Is in unprivileged thread mode?
100 #[inline]
101 pub fn is_unprivileged(self) -> bool {
102 self == Npriv::Unprivileged
103 }
104}
105
106/// Currently active stack pointer
107#[derive(Clone, Copy, Debug, Eq, PartialEq)]
108pub enum Spsel {
109 /// MSP is the current stack pointer
110 Msp,
111 /// PSP is the current stack pointer
112 Psp,
113}
114
115impl Spsel {
116 /// Is MSP the current stack pointer?
117 #[inline]
118 pub fn is_msp(self) -> bool {
119 self == Spsel::Msp
120 }
121
122 /// Is PSP the current stack pointer?
123 #[inline]
124 pub fn is_psp(self) -> bool {
125 self == Spsel::Psp
126 }
127}
128
129/// Whether context floating-point is currently active
130#[derive(Clone, Copy, Debug, Eq, PartialEq)]
131pub enum Fpca {
132 /// Floating-point context active.
133 Active,
134 /// No floating-point context active
135 NotActive,
136}
137
138impl Fpca {
139 /// Is a floating-point context active?
140 #[inline]
141 pub fn is_active(self) -> bool {
142 self == Fpca::Active
143 }
144
145 /// Is a floating-point context not active?
146 #[inline]
147 pub fn is_not_active(self) -> bool {
148 self == Fpca::NotActive
149 }
150}
151
152/// Reads the CPU register
153#[inline]
154pub fn read() -> Control {
155 let bits: u32 = call_asm!(__control_r() -> u32);
156 Control { bits }
157}
158
159/// Writes to the CPU register.
160#[inline]
161pub unsafe fn write(control: Control) {
162 let control: u32 = control.bits();
163 call_asm!(__control_w(control: u32));
164}
165