Skip to content

Commit

Permalink
m-mode as default
Browse files Browse the repository at this point in the history
  • Loading branch information
romancardenas committed Dec 29, 2023
1 parent e70afe4 commit 297aa6e
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 113 deletions.
9 changes: 4 additions & 5 deletions riscv-semihosting/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@ edition = "2021"
rust-version = "1.60.0"

[features]
default = ["jlink-quirks"]
machine-mode = []
user-mode = []
u-mode = []
jlink-quirks = []
no-semihosting = []
default = ["jlink-quirks"]

[dependencies]
riscv = "0.8.0"
cfg-if = "1.0.0"
critical-section = "1.0.0"
riscv = {path = "../riscv", version = "0.10.1"}
9 changes: 9 additions & 0 deletions riscv-semihosting/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use std::env;

fn main() {
let target = env::var("TARGET").unwrap();

if target.starts_with("riscv") {
println!("cargo:rustc-cfg=riscv");
}
}
16 changes: 7 additions & 9 deletions riscv-semihosting/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,14 @@
//! ```no_run
//! use riscv_semihosting::debug::{self, EXIT_SUCCESS, EXIT_FAILURE};
//!
//! fn main() {
//! if 2 == 2 {
//! // report success
//! debug::exit(EXIT_SUCCESS);
//! } else {
//! // report failure
//! debug::exit(EXIT_FAILURE);
//! }
//! if 2 == 2 {
//! // report success
//! debug::exit(EXIT_SUCCESS);
//! } else {
//! // report failure
//! debug::exit(EXIT_FAILURE);
//! }
//!
//!```
/// This values are taken from section 5.5.2 of
/// ADS Debug Target Guide (DUI0058).
Expand Down
186 changes: 92 additions & 94 deletions riscv-semihosting/src/export.rs
Original file line number Diff line number Diff line change
@@ -1,105 +1,103 @@
//! IMPLEMENTATION DETAILS USED BY MACROS
use crate::hio::{self, HostStream};
use core::fmt::{self, Write};

#[cfg(feature = "machine-mode")]
use riscv::interrupt;
static mut HSTDOUT: Option<HostStream> = None;

use crate::hio::{self, HostStream};
static mut HSTDERR: Option<HostStream> = None;

static mut HSTDOUT: Option<HostStream> = None;
#[cfg(not(feature = "u-mode"))]
mod machine {
use super::*;

pub fn hstdout_str(s: &str) {
let _result = critical_section::with(|_| unsafe {
if HSTDOUT.is_none() {
HSTDOUT = Some(hio::hstdout()?);
}

HSTDOUT.as_mut().unwrap().write_str(s).map_err(drop)
});
}

pub fn hstdout_fmt(args: fmt::Arguments) {
let _result = critical_section::with(|_| unsafe {
if HSTDOUT.is_none() {
HSTDOUT = Some(hio::hstdout()?);
}

HSTDOUT.as_mut().unwrap().write_fmt(args).map_err(drop)
});
}

pub fn hstderr_str(s: &str) {
let _result = critical_section::with(|_| unsafe {
if HSTDERR.is_none() {
HSTDERR = Some(hio::hstderr()?);
}

HSTDERR.as_mut().unwrap().write_str(s).map_err(drop)
});
}

pub fn hstderr_fmt(args: fmt::Arguments) {
let _result = critical_section::with(|_| unsafe {
if HSTDERR.is_none() {
HSTDERR = Some(hio::hstderr()?);
}

HSTDERR.as_mut().unwrap().write_fmt(args).map_err(drop)
});
}
}
#[cfg(not(feature = "u-mode"))]
pub use machine::*;

#[cfg(feature = "u-mode")]
mod user {
use super::*;
pub fn hstdout_str(s: &str) {
let _result = unsafe {
if HSTDOUT.is_none() {
HSTDOUT = Some(hio::hstdout().unwrap());
}

HSTDOUT.as_mut().unwrap().write_str(s).map_err(drop)
};
}

#[cfg(not(feature = "no-semihosting"))]
cfg_if::cfg_if! {
if #[cfg(feature="machine-mode")] {
pub fn hstdout_str(s: &str) {
let _result = interrupt::free(|_| unsafe {
if HSTDOUT.is_none() {
HSTDOUT = Some(hio::hstdout()?);
}

HSTDOUT.as_mut().unwrap().write_str(s).map_err(drop)
});
}

pub fn hstdout_fmt(args: fmt::Arguments) {
let _result = interrupt::free(|_| unsafe {
if HSTDOUT.is_none() {
HSTDOUT = Some(hio::hstdout()?);
}

HSTDOUT.as_mut().unwrap().write_fmt(args).map_err(drop)
});
}

static mut HSTDERR: Option<HostStream> = None;

pub fn hstderr_str(s: &str) {
let _result = interrupt::free(|_| unsafe {
if HSTDERR.is_none() {
HSTDERR = Some(hio::hstderr()?);
}

HSTDERR.as_mut().unwrap().write_str(s).map_err(drop)
});
}

pub fn hstderr_fmt(args: fmt::Arguments) {
let _result = interrupt::free(|_| unsafe {
if HSTDERR.is_none() {
HSTDERR = Some(hio::hstderr()?);
}

HSTDERR.as_mut().unwrap().write_fmt(args).map_err(drop)
});
}
pub fn hstdout_fmt(args: fmt::Arguments) {
let _result = unsafe {
if HSTDOUT.is_none() {
HSTDOUT = Some(hio::hstdout().unwrap());
}

HSTDOUT.as_mut().unwrap().write_fmt(args).map_err(drop)
};
}
else if #[cfg(feature = "user-mode")] {
pub fn hstdout_str(s: &str) {
let _result = unsafe {
if HSTDOUT.is_none() {
HSTDOUT = Some(hio::hstdout().unwrap());
}

HSTDOUT.as_mut().unwrap().write_str(s).map_err(drop)
};
}

pub fn hstdout_fmt(args: fmt::Arguments) {
let _result = unsafe {
if HSTDOUT.is_none() {
HSTDOUT = Some(hio::hstdout().unwrap());
}

HSTDOUT.as_mut().unwrap().write_fmt(args).map_err(drop)
};
}

static mut HSTDERR: Option<HostStream> = None;

pub fn hstderr_str(s: &str) {
let _result = unsafe {
if HSTDERR.is_none() {
HSTDERR = Some(hio::hstderr().unwrap());
}

HSTDERR.as_mut().unwrap().write_str(s).map_err(drop)
};
}

pub fn hstderr_fmt(args: fmt::Arguments) {
let _result = unsafe {
if HSTDERR.is_none() {
HSTDERR = Some(hio::hstderr().unwrap());
}

HSTDERR.as_mut().unwrap().write_fmt(args).map_err(drop)
};
}

static mut HSTDERR: Option<HostStream> = None;

pub fn hstderr_str(s: &str) {
let _result = unsafe {
if HSTDERR.is_none() {
HSTDERR = Some(hio::hstderr().unwrap());
}

HSTDERR.as_mut().unwrap().write_str(s).map_err(drop)
};
}
else {
compile_error!("A privilege level has not been selected. Enable either \
the machine-mode or user-mode features as appropriate \
for your use case.");

pub fn hstderr_fmt(args: fmt::Arguments) {
let _result = unsafe {
if HSTDERR.is_none() {
HSTDERR = Some(hio::hstderr().unwrap());
}

HSTDERR.as_mut().unwrap().write_fmt(args).map_err(drop)
};
}
}
#[cfg(feature = "u-mode")]
pub use user::*;
3 changes: 3 additions & 0 deletions riscv-semihosting/src/hio.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
//! Host I/O
// Fixing this lint requires a breaking change that does not add much value
#![allow(clippy::result_unit_err)]

use crate::nr;
use core::{fmt, slice};

Expand Down
22 changes: 17 additions & 5 deletions riscv-semihosting/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@
#![deny(missing_docs)]
#![no_std]

#[cfg(all(riscv, not(feature = "no-semihosting")))]
use core::arch::asm;

#[macro_use]
Expand All @@ -192,23 +193,33 @@ pub mod hio;
pub mod nr;

/// Performs a semihosting operation, takes a pointer to an argument block
///
/// # Safety
///
/// The syscall number must be a valid [semihosting operation],
/// and the arguments must be valid for the associated operation.
///
/// [semihosting operation]: https://developer.arm.com/documentation/dui0471/i/semihosting/semihosting-operations?lang=en
#[inline(always)]
pub unsafe fn syscall<T>(nr: usize, arg: &T) -> usize {
syscall1(nr, arg as *const T as usize)
}

/// Performs a semihosting operation, takes one integer as an argument
///
/// # Safety
///
/// Same as [`syscall`].
#[inline(always)]
pub unsafe fn syscall1(_nr: usize, _arg: usize) -> usize {
match () {
#[cfg(not(feature = "no-semihosting"))]
#[cfg(all(riscv, not(feature = "no-semihosting")))]
() => {
let mut nr = _nr;
// The instructions below must always be uncompressed, otherwise
// it will be treated as a regular break, hence the norvc option.
//
// See https://github.com/riscv/riscv-semihosting-spec for more
// details.
// See https://github.com/riscv/riscv-semihosting-spec for more details.
asm!("
.option push
.option norvc
Expand All @@ -222,8 +233,9 @@ pub unsafe fn syscall1(_nr: usize, _arg: usize) -> usize {
);
nr
}

#[cfg(feature = "no-semihosting")]
#[cfg(all(riscv, feature = "no-semihosting"))]
() => 0,
#[cfg(not(riscv))]
() => unimplemented!(),
}
}

0 comments on commit 297aa6e

Please sign in to comment.