Skip to content

Commit

Permalink
New MECALL backend
Browse files Browse the repository at this point in the history
  • Loading branch information
romancardenas committed Sep 8, 2024
1 parent ea92353 commit 31aac9f
Show file tree
Hide file tree
Showing 15 changed files with 289 additions and 84 deletions.
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

0 comments on commit 31aac9f

Please sign in to comment.