rv32i/
support.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//! Core low-level operations.
6
7use crate::csr::{mstatus::mstatus, CSR};
8
9#[cfg(any(doc, all(target_arch = "riscv32", target_os = "none")))]
10#[inline(always)]
11/// NOP instruction
12pub fn nop() {
13    use core::arch::asm;
14    unsafe {
15        asm!("nop", options(nomem, nostack, preserves_flags));
16    }
17}
18
19#[cfg(any(doc, all(target_arch = "riscv32", target_os = "none")))]
20#[inline(always)]
21/// WFI instruction
22pub unsafe fn wfi() {
23    use core::arch::asm;
24    asm!("wfi", options(nomem, nostack));
25}
26
27pub unsafe fn atomic<F, R>(f: F) -> R
28where
29    F: FnOnce() -> R,
30{
31    // Read the mstatus MIE field and disable machine mode interrupts
32    // atomically
33    //
34    // The result will be the original value of [`mstatus::mie`],
35    // shifted to the proper position in [`mstatus`].
36    let original_mie: usize = CSR
37        .mstatus
38        .read_and_clear_bits(mstatus::mie.mask << mstatus::mie.shift)
39        & mstatus::mie.mask << mstatus::mie.shift;
40
41    // Machine mode interrupts are disabled, execute the atomic
42    // (uninterruptible) function
43    let res = f();
44
45    // If [`mstatus::mie`] was set before, set it again. Otherwise,
46    // this function will be a nop.
47    CSR.mstatus.read_and_set_bits(original_mie);
48
49    res
50}
51
52// Mock implementations for tests on Travis-CI.
53#[cfg(not(any(doc, all(target_arch = "riscv32", target_os = "none"))))]
54/// NOP instruction (mock)
55pub fn nop() {
56    unimplemented!()
57}
58
59#[cfg(not(any(doc, all(target_arch = "riscv32", target_os = "none"))))]
60/// WFI instruction (mock)
61pub unsafe fn wfi() {
62    unimplemented!()
63}