Skip to main content

aarch32_cpu/
lib.rs

1//! CPU/peripheral support for Arm AArch32
2#![no_std]
3#![deny(missing_docs)]
4#![deny(unsafe_op_in_unsafe_fn)]
5#![deny(clippy::missing_safety_doc)]
6#![deny(clippy::unnecessary_safety_comment)]
7#![deny(clippy::unnecessary_safety_doc)]
8
9pub mod cache;
10pub mod interrupt;
11pub mod register;
12
13#[cfg(any(doc, armv7_or_higher))]
14#[path = "asmv7.rs"]
15pub mod asm;
16
17#[cfg(not(any(doc, armv7_or_higher)))]
18#[path = "asmv4.rs"]
19pub mod asm;
20
21#[cfg(any(test, doc, arm_architecture = "v7-a", arm_architecture = "v8-r"))]
22pub mod generic_timer;
23
24#[cfg(any(test, arm_profile = "a", arm_profile = "legacy"))]
25pub mod mmu;
26
27#[cfg(any(test, arm_architecture = "v7-r"))]
28pub mod pmsav7;
29
30#[cfg(any(test, arm_architecture = "v8-r"))]
31pub mod pmsav8;
32
33#[cfg(target_arch = "arm")]
34pub mod stacks;
35
36mod critical_section;
37
38/// Generate an SVC call with no parameters.
39///
40/// Puts the first argument in the instruction. Gives you back
41/// the value left in `r0` by the handler.
42///
43/// ```rust,ignore
44/// let value = svc!(0xFF);
45/// ```
46#[macro_export]
47macro_rules! svc {
48    ($num:expr) => { {
49        let retval: u32;
50        unsafe {
51            core::arch::asm!("svc {arg}", arg = const $num, lateout("r0") retval);
52        }
53        retval
54    } }
55}
56
57/// Generate an SVC call with 1 parameters
58///
59/// Puts the first argument in the instruction, and the parameter in r0. Gives you back
60/// the value left in `r0` by the handler.
61///
62/// ```rust,ignore
63/// const SYSCALL_FOO: u32 = 0x100;
64/// let result = svc1!(0x00, SYSCALL_FOO);
65/// ```
66#[macro_export]
67macro_rules! svc1 {
68    ($num:expr, $arg0:expr) => { {
69        let retval: u32;
70        let arg0: u32 = $arg0;
71        unsafe {
72            core::arch::asm!(
73                // Do the SVCall
74                "svc     {arg}",
75                arg = const $num,
76                inout("r0") arg0 => retval);
77        }
78        retval
79    } }
80}
81
82/// Generate an SVC call with 2 parameters
83///
84/// Puts the first argument in the instruction, and the parameters in r0-r1. Gives you back
85/// the value left in `r0` by the handler.
86///
87/// ```rust,ignore
88/// const SYSCALL_FOO: u32 = 0x100;
89/// let result = svc2!(0x00, SYSCALL_FOO, 1);
90/// ```
91#[macro_export]
92macro_rules! svc2 {
93    ($num:expr, $arg0:expr, $arg1:expr) => { {
94        let retval: u32;
95        let arg0: u32 = $arg0;
96        let arg1: u32 = $arg1;
97        unsafe {
98            core::arch::asm!(
99                // Do the SVCall
100                "svc     {arg}",
101                arg = const $num,
102                inout("r0") arg0 => retval,
103                in("r1") arg1);
104        }
105        retval
106    } }
107}
108
109/// Generate an SVC call with 3 parameters
110///
111/// Puts the first argument in the instruction, and the parameters in r0-r2. Gives you back
112/// the value left in `r0` by the handler.
113///
114/// ```rust,ignore
115/// const SYSCALL_FOO: u32 = 0x100;
116/// let result = svc3!(0x00, SYSCALL_FOO, 1, 2);
117/// ```
118#[macro_export]
119macro_rules! svc3 {
120    ($num:expr, $arg0:expr, $arg1:expr, $arg2:expr) => { {
121        let retval: u32;
122        let arg0: u32 = $arg0;
123        let arg1: u32 = $arg1;
124        let arg2: u32 = $arg2;
125        unsafe {
126            core::arch::asm!(
127                // Do the SVCall
128                "svc     {arg}",
129                arg = const $num,
130                inout("r0") arg0 => retval,
131                in("r1") arg1,
132                in("r2") arg2);
133        }
134        retval
135    } }
136}
137
138/// Generate an SVC call with 4 parameters
139///
140/// Puts the first argument in the instruction, and the parameters in r0-r3. Gives you back
141/// the value left in `r0` by the handler.
142///
143/// ```rust,ignore
144/// const SYSCALL_FOO: u32 = 0x100;
145/// let result = svc4!(0x00, SYSCALL_FOO, 1, 2, 3);
146/// ```
147#[macro_export]
148macro_rules! svc4 {
149    ($num:expr, $arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr) => { {
150        let retval: u32;
151        let arg0: u32 = $arg0;
152        let arg1: u32 = $arg1;
153        let arg2: u32 = $arg2;
154        let arg3: u32 = $arg3;
155        unsafe {
156            core::arch::asm!(
157                // Do the SVCall
158                "svc     {arg}",
159                arg = const $num,
160                inout("r0") arg0 => retval,
161                in("r1") arg1,
162                in("r2") arg2,
163                in("r3") arg3);
164        }
165        retval
166    } }
167}
168
169/// Generate an SVC call with 5 parameters
170///
171/// Puts the first argument in the instruction, and the parameters in r0-r4. Gives you back
172/// the value left in `r0` by the handler.
173///
174/// ```rust,ignore
175/// const SYSCALL_FOO: u32 = 0x100;
176/// let result = svc5!(0x00, SYSCALL_FOO, 1, 2, 3, 4);
177/// ```
178#[macro_export]
179macro_rules! svc5 {
180    ($num:expr, $arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr) => { {
181        let retval: u32;
182        let arg0: u32 = $arg0;
183        let arg1: u32 = $arg1;
184        let arg2: u32 = $arg2;
185        let arg3: u32 = $arg3;
186        let arg4: u32 = $arg4;
187        unsafe {
188            core::arch::asm!(
189                // Do the SVCall
190                "svc     {arg}",
191                arg = const $num,
192                inout("r0") arg0 => retval,
193                in("r1") arg1,
194                in("r2") arg2,
195                in("r3") arg3,
196                in("r4") arg4);
197        }
198        retval
199    } }
200}
201
202/// Generate an SVC call with 6 parameters
203///
204/// Puts the first argument in the instruction, and the parameters in r0-r5. Gives you back
205/// the value left in `r0` by the handler.
206///
207/// ```rust,ignore
208/// const SYSCALL_FOO: u32 = 0x100;
209/// let result = svc6!(0x00, SYSCALL_FOO, 1, 2, 3, 4, 5);
210/// ```
211#[macro_export]
212macro_rules! svc6 {
213    ($num:expr, $arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr) => { {
214        let retval: u32;
215        let arg0: u32 = $arg0;
216        let arg1: u32 = $arg1;
217        let arg2: u32 = $arg2;
218        let arg3: u32 = $arg3;
219        let arg4: u32 = $arg4;
220        let arg5: u32 = $arg5;
221        unsafe {
222            core::arch::asm!(
223                // Do the SVCall
224                "svc     {arg}",
225                arg = const $num,
226                inout("r0") arg0 => retval,
227                in("r1") arg1,
228                in("r2") arg2,
229                in("r3") arg3,
230                in("r4") arg4,
231                in("r5") arg5);
232        }
233        retval
234    } }
235}
236
237/// Generate an HVC call with the given argument.
238#[macro_export]
239macro_rules! hvc {
240    ($r0:expr) => {
241        unsafe {
242            core::arch::asm!("hvc {arg}", arg = const $r0);
243        }
244    }
245}
246
247/// Generate an HVC call with 1 parameters
248///
249/// Puts the first argument in the instruction, and the parameter in r0. Gives you back
250/// the value left in `r0` by the handler.
251///
252/// ```rust,ignore
253/// const HYPERCALL_FOO: u32 = 0x100;
254/// let result = hvc1!(0x00, HYPERCALL_FOO);
255/// ```
256#[macro_export]
257macro_rules! hvc1 {
258    ($num:expr, $arg0:expr) => { {
259        let retval: u32;
260        let arg0: u32 = $arg0;
261        unsafe {
262            core::arch::asm!(
263                // Do the Hyper-call
264                "hvc     {arg}",
265                arg = const $num,
266                inout("r0") arg0 => retval);
267        }
268        retval
269    } }
270}
271
272/// Generate an HVC call with 2 parameters
273///
274/// Puts the first argument in the instruction, and the parameters in r0-r1. Gives you back
275/// the value left in `r0` by the handler.
276///
277/// ```rust,ignore
278/// const HYPERCALL_FOO: u32 = 0x100;
279/// let result = hvc2!(0x00, HYPERCALL_FOO, 1);
280/// ```
281#[macro_export]
282macro_rules! hvc2 {
283    ($num:expr, $arg0:expr, $arg1:expr) => { {
284        let retval: u32;
285        let arg0: u32 = $arg0;
286        let arg1: u32 = $arg1;
287        unsafe {
288            core::arch::asm!(
289                // Do the Hyper-call
290                "hvc     {arg}",
291                arg = const $num,
292                inout("r0") arg0 => retval,
293                in("r1") arg1);
294        }
295        retval
296    } }
297}
298
299/// Generate an HVC call with 3 parameters
300///
301/// Puts the first argument in the instruction, and the parameters in r0-r2. Gives you back
302/// the value left in `r0` by the handler.
303///
304/// ```rust,ignore
305/// const HYPERCALL_FOO: u32 = 0x100;
306/// let result = hvc3!(0x00, HYPERCALL_FOO, 1, 2);
307/// ```
308#[macro_export]
309macro_rules! hvc3 {
310    ($num:expr, $arg0:expr, $arg1:expr, $arg2:expr) => { {
311        let retval: u32;
312        let arg0: u32 = $arg0;
313        let arg1: u32 = $arg1;
314        let arg2: u32 = $arg2;
315        unsafe {
316            core::arch::asm!(
317                // Do the Hyper-call
318                "hvc     {arg}",
319                arg = const $num,
320                inout("r0") arg0 => retval,
321                in("r1") arg1,
322                in("r2") arg2);
323        }
324        retval
325    } }
326}
327
328/// Generate an HVC call with 4 parameters
329///
330/// Puts the first argument in the instruction, and the parameters in r0-r3. Gives you back
331/// the value left in `r0` by the handler.
332///
333/// ```rust,ignore
334/// const HYPERCALL_FOO: u32 = 0x100;
335/// let result = hvc4!(0x00, HYPERCALL_FOO, 1, 2, 3);
336/// ```
337#[macro_export]
338macro_rules! hvc4 {
339    ($num:expr, $arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr) => { {
340        let retval: u32;
341        let arg0: u32 = $arg0;
342        let arg1: u32 = $arg1;
343        let arg2: u32 = $arg2;
344        let arg3: u32 = $arg3;
345        unsafe {
346            core::arch::asm!(
347                // Do the Hyper-call
348                "hvc     {arg}",
349                arg = const $num,
350                inout("r0") arg0 => retval,
351                in("r1") arg1,
352                in("r2") arg2,
353                in("r3") arg3);
354        }
355        retval
356    } }
357}
358
359/// Generate an HVC call with 5 parameters
360///
361/// Puts the first argument in the instruction, and the parameters in r0-r4. Gives you back
362/// the value left in `r0` by the handler.
363///
364/// ```rust,ignore
365/// const HYPERCALL_FOO: u32 = 0x100;
366/// let result = hvc5!(0x00, HYPERCALL_FOO, 1, 2, 3, 4);
367/// ```
368#[macro_export]
369macro_rules! hvc5 {
370    ($num:expr, $arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr) => { {
371        let retval: u32;
372        let arg0: u32 = $arg0;
373        let arg1: u32 = $arg1;
374        let arg2: u32 = $arg2;
375        let arg3: u32 = $arg3;
376        let arg4: u32 = $arg4;
377        unsafe {
378            core::arch::asm!(
379                // Do the Hyper-call
380                "hvc     {arg}",
381                arg = const $num,
382                inout("r0") arg0 => retval,
383                in("r1") arg1,
384                in("r2") arg2,
385                in("r3") arg3,
386                in("r4") arg4);
387        }
388        retval
389    } }
390}
391
392/// Generate an HVC call with 6 parameters
393///
394/// Puts the first argument in the instruction, and the parameters in r0-r5. Gives you back
395/// the value left in `r0` by the handler.
396///
397/// ```rust,ignore
398/// const HYPERCALL_FOO: u32 = 0x100;
399/// let result = hvc6!(0x00, HYPERCALL_FOO, 1, 2, 3, 4, 5);
400/// ```
401#[macro_export]
402macro_rules! hvc6 {
403    ($num:expr, $arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr) => { {
404        let retval: u32;
405        let arg0: u32 = $arg0;
406        let arg1: u32 = $arg1;
407        let arg2: u32 = $arg2;
408        let arg3: u32 = $arg3;
409        let arg4: u32 = $arg4;
410        let arg5: u32 = $arg5;
411        unsafe {
412            core::arch::asm!(
413                // Do the Hyper-call
414                "hvc     {arg}",
415                arg = const $num,
416                inout("r0") arg0 => retval,
417                in("r1") arg1,
418                in("r2") arg2,
419                in("r3") arg3,
420                in("r4") arg4,
421                in("r5") arg5);
422        }
423        retval
424    } }
425}