riscv/
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
27/// Single-core critical section operation
28pub unsafe fn with_interrupts_disabled<F, R>(f: F) -> R
29where
30    F: FnOnce() -> R,
31{
32    // Read the mstatus MIE field and disable machine mode interrupts
33    // atomically
34    //
35    // The result will be the original value of [`mstatus::mie`],
36    // shifted to the proper position in [`mstatus`].
37    let original_mie: usize = CSR
38        .mstatus
39        .read_and_clear_bits(mstatus::mie.mask << mstatus::mie.shift)
40        & mstatus::mie.mask << mstatus::mie.shift;
41
42    // Machine mode interrupts are disabled, execute the (uninterruptible)
43    // function
44    let res = f();
45
46    // If [`mstatus::mie`] was set before, set it again. Otherwise,
47    // this function will be a nop.
48    CSR.mstatus.read_and_set_bits(original_mie);
49
50    res
51}
52
53// Mock implementations for tests on Travis-CI.
54#[cfg(not(any(doc, all(target_arch = "riscv32", target_os = "none"))))]
55/// NOP instruction (mock)
56pub fn nop() {
57    unimplemented!()
58}
59
60#[cfg(not(any(doc, all(target_arch = "riscv32", target_os = "none"))))]
61/// WFI instruction (mock)
62pub unsafe fn wfi() {
63    unimplemented!()
64}