diff --git a/hifive1-test/.cargo/config.toml b/hifive1-test/.cargo/config.toml index ba97cf4..4de49ab 100644 --- a/hifive1-test/.cargo/config.toml +++ b/hifive1-test/.cargo/config.toml @@ -1,4 +1,4 @@ -[target.'cfg(all(any(target_arch = "riscv32", target_arch = "riscv64"), target_os = "none"))'] +[target.'cfg(all(target_arch = "riscv32", target_os = "none"))'] runner = "riscv64-unknown-elf-gdb -q -x gdb_init" # runner = "probe-run --chip fe310-g002 --verbose" rustflags = [ diff --git a/hifive1-test/Cargo.toml b/hifive1-test/Cargo.toml index d070ece..8689475 100644 --- a/hifive1-test/Cargo.toml +++ b/hifive1-test/Cargo.toml @@ -7,10 +7,13 @@ edition = "2021" [dependencies] riscv-slic = {path = "../riscv-slic", features = ["clint-backend", "unsafe-assume-single-core"]} -e310x = { git = "https://github.com/greenlsi/e310x.git", branch = "master", features = ["v-extern"]} +e310x = { git = "https://github.com/greenlsi/e310x.git", rev = "f22b4dd"} hifive1 = { git = "https://github.com/greenlsi/hifive1.git", branch = "rtc", features = ["board-redv"] } bare-metal = "0.2" # riscv-rt = "0.11.0" riscv-rt = {git = "https://github.com/rust-embedded/riscv-rt.git", branch = "master"} # riscv-rt = {path = "../../../github/riscv-rt", features = ["atomic-emulation-trap"]} panic-halt = "0.2.0" + +[features] +qemu = [] # feature for running on qemu (CLINT timer is 10MHz instead of 32KHz) diff --git a/hifive1-test/examples/rtc.rs b/hifive1-test/examples/clint.rs similarity index 63% rename from hifive1-test/examples/rtc.rs rename to hifive1-test/examples/clint.rs index f02c48b..f3d0f9a 100644 --- a/hifive1-test/examples/rtc.rs +++ b/hifive1-test/examples/clint.rs @@ -2,14 +2,18 @@ #![no_main] extern crate panic_halt; - -use hifive1::hal::e310x::{Interrupt as ExtInterrupt, Priority, PLIC}; +use e310x::CLINT; use hifive1::hal::prelude::*; use hifive1::hal::DeviceResources; use hifive1::{pin, sprintln}; use riscv_rt::entry; -use riscv_slic; +extern crate riscv_slic; + +#[cfg(feature = "qemu")] +const PERIOD: u64 = 10000000; // 10 MHz in QEMU +#[cfg(not(feature = "qemu"))] +const PERIOD: u64 = 32_768; // 32.768 kHz in HW // generate SLIC code for this example riscv_slic::codegen!( @@ -17,18 +21,17 @@ riscv_slic::codegen!( swi = [SoftLow, SoftMedium, SoftHigh], backend = [hart_id = HART0] ); + use slic::Interrupt as SoftInterrupt; // Re-export of automatically generated enum of interrupts in previous macro -/// HW handler for clearing RTC. -/// We must define a ClearX handler for every bypassed HW interrupt +/// HW handler for MachineTimer interrupts triggered by CLINT. #[allow(non_snake_case)] #[no_mangle] -unsafe fn RTC() { - // increase rtccmp to clear HW interrupt - let rtc = DeviceResources::steal().peripherals.RTC; - let rtccmp = rtc.rtccmp.read().bits(); - sprintln!("--- clear RTC (rtccmp = {}) ---", rtccmp); - rtc.rtccmp.write(|w| w.bits(rtccmp + 65536)); +fn MachineTimer() { + let mtimecmp = CLINT::mtimecmp0(); + let val = mtimecmp.read(); + sprintln!("--- update MTIMECMP (mtimecmp = {}) ---", val); + mtimecmp.write(val + PERIOD); riscv_slic::pend(SoftInterrupt::SoftMedium); } @@ -76,35 +79,12 @@ fn main() -> ! { clocks, ); - // Disable watchdog - let wdg = peripherals.WDOG; - wdg.wdogcfg.modify(|_, w| w.enalways().clear_bit()); - - sprintln!("Configuring PLIC!!!..."); + sprintln!("Configuring CLINT..."); // First, we make sure that all PLIC the interrupts are disabled and set the interrupts priorities - PLIC::disable(); - PLIC::priorities().reset::(); - // Safety: interrupts are disabled - unsafe { PLIC::priorities().set_priority(ExtInterrupt::RTC, Priority::P7) }; - - // Next, we configure the PLIC context for our use case - let ctx = PLIC::ctx0(); - ctx.enables().disable_all::(); - // Safety: we are the only hart running and we have not enabled any interrupts yet - unsafe { - ctx.enables().enable(ExtInterrupt::RTC); - ctx.threshold().set_threshold(Priority::P1); - }; - sprintln!("done!"); - - sprintln!("Configuring RTC..."); - let mut rtc = peripherals.RTC.constrain(); - rtc.disable(); - rtc.set_scale(0); - rtc.set_rtc(0); - rtc.set_rtccmp(10000); - rtc.enable(); - sprintln!("done!"); + CLINT::disable(); + let mtimer = CLINT::mtimer(); + mtimer.mtimecmp0.write(PERIOD); + mtimer.mtime.write(0); sprintln!("Configuring SLIC..."); // make sure that interrupts are off @@ -116,15 +96,15 @@ fn main() -> ! { riscv_slic::set_priority(SoftInterrupt::SoftMedium, 2); // medium priority riscv_slic::set_priority(SoftInterrupt::SoftHigh, 3); // high priority } - sprintln!("Done!"); sprintln!("Enabling interrupts..."); unsafe { riscv_slic::set_interrupts(); - PLIC::enable(); + CLINT::mtimer_enable(); riscv_slic::enable(); } + //let mut delay = CLINT::delay(); loop { sprintln!("Going to sleep!"); unsafe { riscv_slic::riscv::asm::wfi() }; diff --git a/hifive1-test/src/main.rs b/hifive1-test/src/main.rs index 0fc5216..f3d0f9a 100644 --- a/hifive1-test/src/main.rs +++ b/hifive1-test/src/main.rs @@ -2,14 +2,18 @@ #![no_main] extern crate panic_halt; - -use hifive1::hal::e310x::{Interrupt as ExtInterrupt, Priority, PLIC}; +use e310x::CLINT; use hifive1::hal::prelude::*; use hifive1::hal::DeviceResources; use hifive1::{pin, sprintln}; use riscv_rt::entry; -use riscv_slic; +extern crate riscv_slic; + +#[cfg(feature = "qemu")] +const PERIOD: u64 = 10000000; // 10 MHz in QEMU +#[cfg(not(feature = "qemu"))] +const PERIOD: u64 = 32_768; // 32.768 kHz in HW // generate SLIC code for this example riscv_slic::codegen!( @@ -17,18 +21,17 @@ riscv_slic::codegen!( swi = [SoftLow, SoftMedium, SoftHigh], backend = [hart_id = HART0] ); + use slic::Interrupt as SoftInterrupt; // Re-export of automatically generated enum of interrupts in previous macro -/// HW handler for clearing RTC. -/// We must define a ClearX handler for every bypassed HW interrupt +/// HW handler for MachineTimer interrupts triggered by CLINT. #[allow(non_snake_case)] #[no_mangle] -unsafe fn RTC() { - // increase rtccmp to clear HW interrupt - let rtc = DeviceResources::steal().peripherals.RTC; - let rtccmp = rtc.rtccmp.read().bits(); - sprintln!("--- clear RTC (rtccmp = {}) ---", rtccmp); - rtc.rtccmp.write(|w| w.bits(rtccmp + 65536)); +fn MachineTimer() { + let mtimecmp = CLINT::mtimecmp0(); + let val = mtimecmp.read(); + sprintln!("--- update MTIMECMP (mtimecmp = {}) ---", val); + mtimecmp.write(val + PERIOD); riscv_slic::pend(SoftInterrupt::SoftMedium); } @@ -76,35 +79,12 @@ fn main() -> ! { clocks, ); - // Disable watchdog - let wdg = peripherals.WDOG; - wdg.wdogcfg.modify(|_, w| w.enalways().clear_bit()); - - sprintln!("Configuring PLIC!!..."); + sprintln!("Configuring CLINT..."); // First, we make sure that all PLIC the interrupts are disabled and set the interrupts priorities - PLIC::disable(); - PLIC::priorities().reset::(); - // Safety: interrupts are disabled - unsafe { PLIC::priorities().set_priority(ExtInterrupt::RTC, Priority::P7) }; - - // Next, we configure the PLIC context for our use case - let ctx = PLIC::ctx0(); - ctx.enables().disable_all::(); - // Safety: we are the only hart running and we have not enabled any interrupts yet - unsafe { - ctx.enables().enable(ExtInterrupt::RTC); - ctx.threshold().set_threshold(Priority::P1); - }; - sprintln!("done!"); - - sprintln!("Configuring RTC..."); - let mut rtc = peripherals.RTC.constrain(); - rtc.disable(); - rtc.set_scale(0); - rtc.set_rtc(0); - rtc.set_rtccmp(10000); - rtc.enable(); - sprintln!("done!"); + CLINT::disable(); + let mtimer = CLINT::mtimer(); + mtimer.mtimecmp0.write(PERIOD); + mtimer.mtime.write(0); sprintln!("Configuring SLIC..."); // make sure that interrupts are off @@ -116,15 +96,15 @@ fn main() -> ! { riscv_slic::set_priority(SoftInterrupt::SoftMedium, 2); // medium priority riscv_slic::set_priority(SoftInterrupt::SoftHigh, 3); // high priority } - sprintln!("Done!"); sprintln!("Enabling interrupts..."); unsafe { riscv_slic::set_interrupts(); - PLIC::enable(); + CLINT::mtimer_enable(); riscv_slic::enable(); } + //let mut delay = CLINT::delay(); loop { sprintln!("Going to sleep!"); unsafe { riscv_slic::riscv::asm::wfi() };