Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New MECALL backend #10

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions hifive1-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,20 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
riscv-slic = {path = "../riscv-slic", features = ["clint-backend"]}
e310x = { git = "https://github.com/greenlsi/e310x.git", branch = "master"}
hifive1 = { git = "https://github.com/romancardenas/hifive1.git", branch = "master", features = ["board-redv"] }
riscv-slic = { path = "../riscv-slic" }
riscv-rt = { git = "https://github.com/rust-embedded/riscv", branch = "riscv-pac-only" } # TODO use crates.io
hifive1 = { git = "https://github.com/greenlsi/hifive1.git", branch = "master", features = ["board-redv"] } # TODO use crates.io
bare-metal = "0.2"
riscv-rt = "0.12.0"
panic-halt = "0.2.0"

[features]
clint = ["riscv-slic/clint-backend"]
mecall = ["riscv-slic/mecall-backend"]

[[example]]
name = "clint"
required-features = ["clint"]

[[example]]
name = "mecall"
required-features = ["mecall"]
58 changes: 27 additions & 31 deletions hifive1-test/examples/clint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,30 @@
#![no_main]

extern crate panic_halt;
use e310x::CLINT;
use hifive1::hal::prelude::*;
use hifive1::hal::DeviceResources;
use hifive1::{pin, sprintln};

use riscv_rt::entry;
extern crate riscv_slic;

use hifive1::{
hal::{
e310x::{self, CLINT},
prelude::*,
DeviceResources,
},
pin, sprintln,
};

// generate SLIC code for this example
riscv_slic::codegen!(
pac = e310x,
swi = [SoftLow, SoftMedium, SoftHigh],
backend = [hart_id = HART0]
backend = [hart_id = H0]
);

use slic::Interrupt as SoftInterrupt; // Re-export of automatically generated enum of interrupts in previous macro
use slic::SoftwareInterrupt; // Re-export of automatically generated enum of interrupts in previous macro

/// HW handler for MachineTimer interrupts triggered by CLINT.
#[allow(non_snake_case)]
#[no_mangle]
fn MachineTimer() {
#[riscv_rt::core_interrupt(CoreInterrupt::MachineTimer)]
fn machine_timer() {
let mtimecmp = CLINT::mtimecmp0();
let val = mtimecmp.read();
sprintln!("--- update MTIMECMP (mtimecmp = {}) ---", val);
mtimecmp.write(val + CLINT::freq() as u64);
riscv_slic::pend(SoftInterrupt::SoftMedium);
mtimecmp.modify(|val| *val += CLINT::freq() as u64);
}

/// Handler for SoftHigh task (high priority).
Expand All @@ -43,9 +41,9 @@ fn SoftHigh() {
#[no_mangle]
fn SoftMedium() {
sprintln!(" start SoftMedium");
riscv_slic::pend(SoftInterrupt::SoftLow);
riscv_slic::pend(SoftwareInterrupt::SoftLow);
sprintln!(" middle SoftMedium");
riscv_slic::pend(SoftInterrupt::SoftHigh);
riscv_slic::pend(SoftwareInterrupt::SoftHigh);
sprintln!(" stop SoftMedium");
}

Expand All @@ -57,7 +55,7 @@ fn SoftLow() {
sprintln!("stop SoftLow");
}

#[entry]
#[riscv_rt::entry]
fn main() -> ! {
let resources = DeviceResources::take().unwrap();
let peripherals = resources.peripherals;
Expand Down Expand Up @@ -87,27 +85,25 @@ fn main() -> ! {
riscv_slic::clear_interrupts();
// Set priorities
unsafe {
riscv_slic::set_priority(SoftInterrupt::SoftLow, 1); // low priority
riscv_slic::set_priority(SoftInterrupt::SoftMedium, 2); // medium priority
riscv_slic::set_priority(SoftInterrupt::SoftHigh, 3); // high priority
riscv_slic::set_priority(SoftwareInterrupt::SoftLow, 1); // low priority
riscv_slic::set_priority(SoftwareInterrupt::SoftMedium, 2); // medium priority
riscv_slic::set_priority(SoftwareInterrupt::SoftHigh, 3); // high priority
}
sprintln!("Done!");

sprintln!("Enabling interrupts...");
unsafe {
riscv_slic::set_interrupts();
CLINT::mtimer_enable();
riscv_slic::enable();
}
//let mut delay = CLINT::delay();

sprintln!("Done!");

loop {
// read stack pointer
let pc: usize;
unsafe {
core::arch::asm!("mv {}, sp", out(reg) pc);
}
sprintln!("Program counter: {:x}", pc);
sprintln!("Going to sleep!");
sprintln!("Waiting for interrupts...");
riscv_slic::riscv::asm::wfi();
sprintln!("Interrupt received!");
riscv_slic::pend(SoftwareInterrupt::SoftMedium);
sprintln!();
}
}
104 changes: 104 additions & 0 deletions hifive1-test/examples/mecall.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#![no_std]
#![no_main]

extern crate panic_halt;
extern crate riscv_slic;

use hifive1::{
hal::{
e310x::{self, CLINT},
prelude::*,
DeviceResources,
},
pin, sprintln,
};

// generate SLIC code for this example
riscv_slic::codegen!(pac = e310x, swi = [SoftLow, SoftMedium, SoftHigh]);
use slic::SoftwareInterrupt; // Re-export of automatically generated enum of interrupts in previous macro

/// HW handler for MachineTimer interrupts triggered by CLINT.
#[riscv_rt::core_interrupt(CoreInterrupt::MachineTimer)]
fn machine_timer() {
let mtimecmp = CLINT::mtimecmp0();
mtimecmp.modify(|val| *val += CLINT::freq() as u64);
}

/// Handler for SoftHigh task (high priority).
#[allow(non_snake_case)]
#[no_mangle]
fn SoftHigh() {
sprintln!(" start SoftHigh");
sprintln!(" stop SoftHigh");
}

/// Handler for SoftMedium task (medium priority). This task pends both SoftLow and SoftHigh.
#[allow(non_snake_case)]
#[no_mangle]
fn SoftMedium() {
sprintln!(" start SoftMedium");
riscv_slic::pend(SoftwareInterrupt::SoftLow);
sprintln!(" middle SoftMedium");
riscv_slic::pend(SoftwareInterrupt::SoftHigh);
sprintln!(" stop SoftMedium");
}

/// Handler for SoftLow task (low priority).
#[allow(non_snake_case)]
#[no_mangle]
fn SoftLow() {
sprintln!("start SoftLow");
sprintln!("stop SoftLow");
}

#[riscv_rt::entry]
fn main() -> ! {
let resources = DeviceResources::take().unwrap();
let peripherals = resources.peripherals;

let clocks = hifive1::configure_clocks(peripherals.PRCI, peripherals.AONCLK, 64.mhz().into());
let gpio = resources.pins;

// Configure UART for stdout
hifive1::stdout::configure(
peripherals.UART0,
pin!(gpio, uart0_tx),
pin!(gpio, uart0_rx),
115_200.bps(),
clocks,
);

sprintln!("Configuring CLINT...");
// First, we make sure that all PLIC the interrupts are disabled and set the interrupts priorities
CLINT::disable();
let mtimer = CLINT::mtimer();
mtimer.mtimecmp0.write(CLINT::freq() as u64);
mtimer.mtime.write(0);

sprintln!("Configuring SLIC...");
// make sure that interrupts are off
riscv_slic::disable();
riscv_slic::clear_interrupts();
// Set priorities
unsafe {
riscv_slic::set_priority(SoftwareInterrupt::SoftLow, 1); // low priority
riscv_slic::set_priority(SoftwareInterrupt::SoftMedium, 2); // medium priority
riscv_slic::set_priority(SoftwareInterrupt::SoftHigh, 3); // high priority
}

sprintln!("Enabling interrupts...");
unsafe {
riscv_slic::set_interrupts();
CLINT::mtimer_enable();
riscv_slic::enable();
}

sprintln!("Done!");

loop {
sprintln!("Waiting for interrupts...");
riscv_slic::riscv::asm::wfi();
sprintln!("Interrupt received!");
riscv_slic::pend(SoftwareInterrupt::SoftMedium);
}
}
47 changes: 27 additions & 20 deletions hifive1-test/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,33 @@
#![no_main]

extern crate panic_halt;
use e310x::CLINT;
use hifive1::hal::prelude::*;
use hifive1::hal::DeviceResources;
use hifive1::{pin, sprintln};

use riscv_rt::entry;
extern crate riscv_slic;

use hifive1::{
hal::{
e310x::{self, CLINT},
prelude::*,
DeviceResources,
},
pin, sprintln,
};

// generate SLIC code for this example
riscv_slic::codegen!(
pac = e310x,
swi = [SoftLow, SoftMedium, SoftHigh],
backend = [hart_id = HART0]
backend = [hart_id = H0]
);

use slic::Interrupt as SoftInterrupt; // Re-export of automatically generated enum of interrupts in previous macro
use slic::SoftwareInterrupt; // Re-export of automatically generated enum of interrupts in previous macro

/// HW handler for MachineTimer interrupts triggered by CLINT.
#[allow(non_snake_case)]
#[no_mangle]
fn MachineTimer() {
#[riscv_rt::core_interrupt(CoreInterrupt::MachineTimer)]
fn machine_timer() {
let mtimecmp = CLINT::mtimecmp0();
let val = mtimecmp.read();
sprintln!("--- update MTIMECMP (mtimecmp = {}) ---", val);
mtimecmp.write(val + CLINT::freq() as u64);
riscv_slic::pend(SoftInterrupt::SoftMedium);
riscv_slic::pend(SoftwareInterrupt::SoftMedium);
}

/// Handler for SoftHigh task (high priority).
Expand All @@ -43,9 +44,9 @@ fn SoftHigh() {
#[no_mangle]
fn SoftMedium() {
sprintln!(" start SoftMedium");
riscv_slic::pend(SoftInterrupt::SoftLow);
riscv_slic::pend(SoftwareInterrupt::SoftLow);
sprintln!(" middle SoftMedium");
riscv_slic::pend(SoftInterrupt::SoftHigh);
riscv_slic::pend(SoftwareInterrupt::SoftHigh);
sprintln!(" stop SoftMedium");
}

Expand All @@ -57,7 +58,7 @@ fn SoftLow() {
sprintln!("stop SoftLow");
}

#[entry]
#[riscv_rt::entry]
fn main() -> ! {
let resources = DeviceResources::take().unwrap();
let peripherals = resources.peripherals;
Expand Down Expand Up @@ -87,9 +88,9 @@ fn main() -> ! {
riscv_slic::clear_interrupts();
// Set priorities
unsafe {
riscv_slic::set_priority(SoftInterrupt::SoftLow, 1); // low priority
riscv_slic::set_priority(SoftInterrupt::SoftMedium, 2); // medium priority
riscv_slic::set_priority(SoftInterrupt::SoftHigh, 3); // high priority
riscv_slic::set_priority(SoftwareInterrupt::SoftLow, 1); // low priority
riscv_slic::set_priority(SoftwareInterrupt::SoftMedium, 2); // medium priority
riscv_slic::set_priority(SoftwareInterrupt::SoftHigh, 3); // high priority
}
sprintln!("Done!");

Expand All @@ -101,7 +102,13 @@ fn main() -> ! {
}
//let mut delay = CLINT::delay();
loop {
// read stack pointer
let sp: usize;
unsafe {
core::arch::asm!("mv {}, sp", out(reg) sp);
}
sprintln!("Stack counter: {:x}", sp);
sprintln!("Going to sleep!");
unsafe { riscv_slic::riscv::asm::wfi() };
riscv_slic::riscv::asm::wfi();
}
}
1 change: 1 addition & 0 deletions riscv-slic-macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ msoft = [] # do not enable this feature directly. Use one of the *-backend featu
ssoft = [] # do not enable this feature directly. Use one of the *-backend features instead

clint-backend = ["msoft"] # enable this feature to use the CLINT peripheral as SWI backend
mecall-backend = [] # enable this feature to use the machine-level ECALL instruction as SWI backend
ssoft-backend = ["ssoft"] # enable this feature to use the supervisor-level software interrupt as SWI backend
27 changes: 17 additions & 10 deletions riscv-slic-macros/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ pub fn api_mod() -> TokenStream {
#[no_mangle]
pub unsafe fn __riscv_slic_set_threshold(thresh: u8) {
critical_section::with(|cs| {
let mut slic = __SLIC.borrow_ref_mut(cs);
slic.set_threshold(thresh);
// trigger a software interrupt if the SLIC is still ready at this point
if slic.is_ready() {
if {
let mut slic = __SLIC.borrow_ref_mut(cs);
slic.set_threshold(thresh);
slic.is_ready()
} {
// trigger a software interrupt if the SLIC is still ready at this point
__riscv_slic_swi_pend();
}
});
Expand All @@ -48,10 +50,13 @@ pub fn api_mod() -> TokenStream {
#[no_mangle]
pub unsafe fn __riscv_slic_raise_threshold(priority: u8) -> Result<u8, ()> {
critical_section::with(|cs| {
let mut slic = __SLIC.borrow_ref_mut(cs);
let res = slic.raise_threshold(priority);
let (res, is_ready) = {
let mut slic = __SLIC.borrow_ref_mut(cs);
let res = slic.raise_threshold(priority);
(res, slic.is_ready())
};
// trigger a software interrupt if the SLIC is still ready at this point
if slic.is_ready() {
if is_ready {
__riscv_slic_swi_pend();
}
res
Expand Down Expand Up @@ -91,9 +96,11 @@ pub fn api_mod() -> TokenStream {
#[no_mangle]
pub unsafe fn __riscv_slic_pend(interrupt: u16) {
critical_section::with(|cs| {
let mut slic = __SLIC.borrow_ref_mut(cs);
slic.pend(interrupt);
if slic.is_ready() {
if {
let mut slic = __SLIC.borrow_ref_mut(cs);
slic.pend(interrupt);
slic.is_ready()
} {
__riscv_slic_swi_pend();
}
});
Expand Down
5 changes: 5 additions & 0 deletions riscv-slic-macros/src/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ mod clint;
#[cfg(feature = "clint-backend")]
pub use clint::{export_quote, ExportBackendInput};

#[cfg(feature = "mecall-backend")]
mod mecall;
#[cfg(feature = "mecall-backend")]
pub use mecall::{export_quote, ExportBackendInput};

#[cfg(feature = "ssoft-backend")]
mod ssoft;
#[cfg(feature = "ssoft-backend")]
Expand Down
Loading
Loading