cortexm/
scb.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! ARM System Control Block
6//!
7//! <http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0553a/CIHFDJCA.html>
8
9use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
10use kernel::utilities::registers::{register_bitfields, register_structs, ReadOnly, ReadWrite};
11use kernel::utilities::StaticRef;
12
13register_structs! {
14    /// In an ARMv7-M processor, a System Control Block (SCB) in the SCS
15    /// provides key status information and control features for the processor.
16    ScbRegisters {
17        /// CPUID Base Register
18        (0x00 => cpuid: ReadOnly<u32, CpuId::Register>),
19
20        /// Interrupt Control and State Register
21        (0x04 => icsr: ReadWrite<u32, InterruptControlAndState::Register>),
22
23        /// Vector Table Offset Register
24        (0x08 => vtor: ReadWrite<u32, VectorTableOffset::Register>),
25
26        /// Application Interrupt and Reset Control Register
27        (0x0c => aircr: ReadWrite<u32, ApplicationInterruptAndReset::Register>),
28
29        /// System Control Register
30        (0x10 => scr: ReadWrite<u32, SystemControl::Register>),
31
32        /// Configuration and Control Register
33        (0x14 => ccr: ReadWrite<u32, ConfigurationAndControl::Register>),
34
35        /// System Handler Priority Register (1-4)
36        (0x18 => shp: [ReadWrite<u32, SystemHandlerPriority::Register>; 3]),
37
38        /// System Handler Control and State Register
39        (0x24 => shcsr: ReadWrite<u32, SystemHandlerControlAndState::Register>),
40
41        /// Configurable Fault Status Register
42        (0x28 => cfsr: ReadWrite<u32, ConfigurableFaultStatus::Register>),
43
44        /// HardFault Status Register
45        (0x2c => hfsr: ReadWrite<u32, HardFaultStatus::Register>),
46
47        /// Debug Fault Status Register
48        (0x30 => dfsr: ReadWrite<u32, DebugFaultStatus::Register>),
49
50        /// MemManage Fault Address Register
51        (0x34 => mmfar: ReadWrite<u32, FaultAddress::Register>),
52
53        /// BusFault Address Register
54        (0x38 => bfar: ReadWrite<u32, FaultAddress::Register>),
55
56        /// Auxiliary Fault Status Register
57        (0x3c => afsr: ReadWrite<u32, FaultAddress::Register>),
58
59        /// 0xE000ED40-7C, Reserved for CPUID registers.
60        (0x40 => _reserved0),
61
62        /// 0xE000ED80-84, Reserved.
63        (0x80 => _reserved1),
64
65        /// Coprocessor Access Control Register
66        (0x88 => cpacr: ReadWrite<u32, CoprocessorAccessControl::Register>),
67
68        /// 0xE000ED8C, Reserved.
69        (0x8c => _reserved2),
70
71        (0x90 => @END),
72    }
73}
74
75register_bitfields![u32,
76    CpuId [
77        /// Implementer code assigned by ARM. ARM implementations are 0x41.
78        IMPLEMENTER     OFFSET(24)  NUMBITS(8),
79
80        /// Implementer-defined variant number.
81        VARIANT         OFFSET(20)  NUMBITS(4),
82
83        /// Archtiecture always reads as 0xF for Cortex-M
84        ARCHITECTURE    OFFSET(16)  NUMBITS(4),
85
86        /// Implementer-defined part number.
87        PARTNO          OFFSET(4)   NUMBITS(12),
88
89        /// Implementer-defined revision number.
90        REVISION        OFFSET(0)   NUMBITS(4)
91    ],
92
93    InterruptControlAndState [
94        /// Non-Maskable Interrupt.
95        /// Write 0 is no-op, write 1 triggers. Read returns whether NMI is active.
96        /// RW.
97        NMIPENDSET      OFFSET(31)  NUMBITS(1),
98
99        /// Pendable SerVice.
100        /// Write 0 is no-op, write 1 triggers. Read returns whether PendSV is active.
101        /// RW.
102        PENDSVSET       OFFSET(28)  NUMBITS(1),
103
104        /// Write 1 to clear PendSV.
105        /// WO.
106        PENDSVCLR       OFFSET(27)  NUMBITS(1),
107
108        /// Pendable SysTick.
109        /// Write 0 is no-op, write 1 triggers. Read returns whether PendST is active.
110        /// RW.
111        PENDSTSET       OFFSET(26)  NUMBITS(1),
112
113        /// Write 1 to clear PendST.
114        /// WO.
115        PENDSTCLR       OFFSET(25)  NUMBITS(1),
116
117        /// Whether an exception will be serviced when existing debug state.
118        /// RO.
119        ISRPREEMPT      OFFSET(23)  NUMBITS(1),
120
121        /// Whether an external interrupt (from NVIC) is pending.
122        /// RO.
123        ISRPENDING      OFFSET(22)  NUMBITS(1),
124
125        /// Highest pending exception. Zero if none pending.
126        /// RO.
127        VECTACTIVE      OFFSET(0)   NUMBITS(9)
128    ],
129
130    /// Note: Software can write all 1s to `TBLOFF` and read result to learn
131    /// maximum supported value.
132    VectorTableOffset [
133        /// Bits [31:7] of the vector table address
134        /// n.b. bits [6:0] are always 0.
135        TBLOFF          OFFSET(7)   NUMBITS(25)
136    ],
137
138    ApplicationInterruptAndReset [
139        /// Key field. Must write 0x05FA or write is ignored. Reads as 0xFA05.
140        /// RW.
141        VECTKEY         OFFSET(16)  NUMBITS(16),
142
143        /// 0=Little endian, 1=Big endian.
144        /// RO.
145        ENDIANNESS      OFFSET(15)  NUMBITS(1),
146
147        /// Binary point position for priority grouping. Defaults to 0b000.
148        /// RW.
149        PRIGROUP        OFFSET(8)   NUMBITS(3),
150
151        /// Writing 1 to this bit requests a Local reset. Cleared to 0b0 on reset.
152        /// RW.
153        SYSRESETREQ     OFFSET(2)   NUMBITS(1),
154
155        /// Writing 1 clears all state information for exceptions.
156        /// WARN: Writing this bit when not in a Debug halt is UNPREDICTABLE.
157        /// WO.
158        VECTCLRACTIVE   OFFSET(1)   NUMBITS(1),
159
160        /// Writing 1 causes a local system reset.
161        /// WARN: Writing this bit when not in a Debug halt is UNPREDICTABLE.
162        /// WARN: Writing this and `SYSRESETREQ` is UNPREDICTABLE.
163        /// WO.
164        VECTRESET       OFFSET(0)   NUMBITS(1)
165    ],
166
167    SystemControl [
168        SEVONPEND       OFFSET(4)   NUMBITS(1),
169        SLEEPDEEP       OFFSET(2)   NUMBITS(1),
170        SLEEPONEXIT     OFFSET(1)   NUMBITS(1)
171    ],
172
173    ConfigurationAndControl [
174        STKALIGN        OFFSET(9)   NUMBITS(1),
175        BFHFNMIGN       OFFSET(8)   NUMBITS(1),
176        DIV_0_TRAP      OFFSET(4)   NUMBITS(1),
177        UNALIGN_TRP     OFFSET(3)   NUMBITS(1),
178        USERSETMPEND    OFFSET(1)   NUMBITS(1),
179        NONBASETHRDENA  OFFSET(0)   NUMBITS(1)
180    ],
181
182    // Note: Simplified
183    SystemHandlerPriority [
184        PRI_N3          OFFSET(24)  NUMBITS(4),
185        PRI_N2          OFFSET(16)  NUMBITS(4),
186        PRI_N1          OFFSET(8)   NUMBITS(4),
187        PRI_N0          OFFSET(0)   NUMBITS(4)
188    ],
189
190    SystemHandlerControlAndState [
191        USGFAULTENA     OFFSET(18)  NUMBITS(1),
192        BUSFAULTENA     OFFSET(17)  NUMBITS(1),
193        MEMFAULTENA     OFFSET(16)  NUMBITS(1),
194        SVCALLPENDED    OFFSET(15)  NUMBITS(1),
195        BUSFAULTPENDED  OFFSET(14)  NUMBITS(1),
196        MEMFAULTPENDED  OFFSET(14)  NUMBITS(1),
197        USGFAULTPENDED  OFFSET(14)  NUMBITS(1),
198        SYSTICKACT      OFFSET(11)  NUMBITS(1),
199        PENDSVACT       OFFSET(10)  NUMBITS(1),
200        MONITORACT      OFFSET(8)   NUMBITS(1),
201        SVCALLACT       OFFSET(7)   NUMBITS(1),
202        USGFAULTACT     OFFSET(3)   NUMBITS(1),
203        BUSFAULTACT     OFFSET(1)   NUMBITS(1),
204        MEMFAULTACT     OFFSET(0)   NUMBITS(1)
205    ],
206
207    ConfigurableFaultStatus [
208        UsageFault      OFFSET(16)  NUMBITS(16),
209        BusFault        OFFSET(8)   NUMBITS(8),
210        MemManage       OFFSET(0)   NUMBITS(8)
211    ],
212
213    MemManageStatus [
214        MMARVALID       OFFSET(7)   NUMBITS(1),
215        MLSPERR         OFFSET(5)   NUMBITS(1),
216        MSTKERR         OFFSET(4)   NUMBITS(1),
217        MUNSTKERR       OFFSET(3)   NUMBITS(1),
218        DACCVIOL        OFFSET(1)   NUMBITS(1),
219        IACCVIOL        OFFSET(1)   NUMBITS(1)
220    ],
221
222    BusFaultStatus [
223        BFARVALID       OFFSET(7)   NUMBITS(1),
224        LSPERR          OFFSET(5)   NUMBITS(1),
225        STKERR          OFFSET(4)   NUMBITS(1),
226        UNSTKERR        OFFSET(3)   NUMBITS(1),
227        IMPRECISERR     OFFSET(2)   NUMBITS(1),
228        PRECISERR       OFFSET(1)   NUMBITS(1),
229        IBUSERR         OFFSET(0)   NUMBITS(1)
230    ],
231
232    UsageFaultStatus [
233        DIVBYZERO       OFFSET(9)   NUMBITS(1),
234        UNALIGNED       OFFSET(8)   NUMBITS(1),
235        NOCP            OFFSET(3)   NUMBITS(1),
236        INVPC           OFFSET(2)   NUMBITS(1),
237        INVSTATE        OFFSET(1)   NUMBITS(1),
238        UNDEFINSTR      OFFSET(0)   NUMBITS(1)
239    ],
240
241    HardFaultStatus [
242        DEBUGEVT        OFFSET(31)  NUMBITS(1),
243        FORCED          OFFSET(30)  NUMBITS(1),
244        VECTTBL         OFFSET(1)   NUMBITS(1)
245    ],
246
247    DebugFaultStatus [
248        EXTERNAL        OFFSET(4)   NUMBITS(1),
249        VCATCH          OFFSET(3)   NUMBITS(1),
250        DWTTRAP         OFFSET(2)   NUMBITS(1),
251        BKPT            OFFSET(1)   NUMBITS(1),
252        HALTED          OFFSET(0)   NUMBITS(1)
253    ],
254
255    FaultAddress [
256        ADDRESS         OFFSET(0)   NUMBITS(32)
257    ],
258
259    CoprocessorAccessControl [
260        CP11            OFFSET(22)  NUMBITS(2),
261        CP10            OFFSET(20)  NUMBITS(2),
262        CP7             OFFSET(14)  NUMBITS(2),
263        CP6             OFFSET(12)  NUMBITS(2),
264        CP5             OFFSET(10)  NUMBITS(2),
265        CP4             OFFSET(8)  NUMBITS(2),
266        CP3             OFFSET(6)  NUMBITS(2),
267        CP2             OFFSET(4)  NUMBITS(2),
268        CP1             OFFSET(2)  NUMBITS(2),
269        CP0             OFFSET(0)  NUMBITS(2)
270    ]
271];
272
273const SCB: StaticRef<ScbRegisters> = unsafe { StaticRef::new(0xE000ED00 as *const ScbRegisters) };
274
275/// Allow the core to go into deep sleep on WFI.
276///
277/// The specific definition of "deep sleep" is chip specific.
278#[cfg(any(doc, all(target_arch = "arm", target_os = "none")))]
279pub unsafe fn set_sleepdeep() {
280    use core::arch::asm;
281
282    SCB.scr.modify(SystemControl::SLEEPDEEP::SET);
283
284    asm!("dsb", "isb", options(nomem, nostack, preserves_flags));
285}
286
287// Mock implementation for tests on Travis-CI.
288#[cfg(not(any(doc, all(target_arch = "arm", target_os = "none"))))]
289pub unsafe fn set_sleepdeep() {
290    // Dummy operation to satisfy the `Writable` trait import on
291    // non-ARM platforms.
292    SCB.scr.modify(SystemControl::SLEEPDEEP::SET);
293
294    unimplemented!()
295}
296
297/// Do not allow the core to go into deep sleep on WFI.
298///
299/// The specific definition of "deep sleep" is chip specific.
300pub unsafe fn unset_sleepdeep() {
301    SCB.scr.modify(SystemControl::SLEEPDEEP::CLEAR);
302}
303
304/// Software reset using the ARM System Control Block
305pub unsafe fn reset() {
306    SCB.aircr.modify(
307        ApplicationInterruptAndReset::VECTKEY.val(0x05FA)
308            + ApplicationInterruptAndReset::PRIGROUP.val(0b111)
309            + ApplicationInterruptAndReset::SYSRESETREQ::SET,
310    );
311}
312
313/// relocate interrupt vector table
314pub unsafe fn set_vector_table_offset(offset: *const ()) {
315    SCB.vtor.set(offset as u32);
316}
317
318/// Disable the FPU
319#[cfg(any(doc, all(target_arch = "arm", target_os = "none")))]
320pub unsafe fn disable_fpca() {
321    use core::arch::asm;
322    SCB.cpacr
323        .modify(CoprocessorAccessControl::CP10::CLEAR + CoprocessorAccessControl::CP11::CLEAR);
324
325    asm!("dsb", "isb", options(nomem, nostack, preserves_flags));
326
327    if SCB.cpacr.read(CoprocessorAccessControl::CP10) != 0
328        || SCB.cpacr.read(CoprocessorAccessControl::CP11) != 0
329    {
330        panic!("Unable to disable FPU");
331    }
332}
333
334// Mock implementation for tests on Travis-CI.
335#[cfg(not(any(doc, all(target_arch = "arm", target_os = "none"))))]
336pub unsafe fn disable_fpca() {
337    // Dummy read register, to satisfy the `Readable` trait import on
338    // non-ARM platforms.
339    let _ = SCB.cpacr.read(CoprocessorAccessControl::CP10);
340
341    unimplemented!()
342}