From ee242b44b284dedadddb89a6a16bf4c4581af38d Mon Sep 17 00:00:00 2001 From: WangRunji Date: Sun, 8 Jul 2018 01:03:33 +0800 Subject: [PATCH] Timer interrupt --- crate/riscv | 2 +- src/arch/riscv32/interrupt.rs | 19 +++++++++++++++++-- src/arch/riscv32/mod.rs | 4 ++-- src/arch/riscv32/timer.rs | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 src/arch/riscv32/timer.rs diff --git a/crate/riscv b/crate/riscv index a3d2a13..ef046c8 160000 --- a/crate/riscv +++ b/crate/riscv @@ -1 +1 @@ -Subproject commit a3d2a13c0e656936631c6f420a393c2c0038ecc8 +Subproject commit ef046c88fdb7ed0f416f29e034d4679f0e7a2573 diff --git a/src/arch/riscv32/interrupt.rs b/src/arch/riscv32/interrupt.rs index 95f7028..591a591 100644 --- a/src/arch/riscv32/interrupt.rs +++ b/src/arch/riscv32/interrupt.rs @@ -7,12 +7,27 @@ pub fn init() { // Enable interrupt sstatus::set_sie(); } + println!("interrupt: init end"); } #[no_mangle] pub extern fn rust_trap(tf: &mut TrapFrame) { - println!("Trap:\n{:#x?}", tf); - loop {} + use super::riscv::register::scause::{Trap, Interrupt, Exception}; + match tf.scause.cause() { + Trap::Interrupt(SupervisorTimer) => timer(), + _ => panic!("Unhandled interrupt: {:?}\n{:#x?}", tf.scause.cause(), tf), + } +} + +fn timer() { + static mut TICK: usize = 0; + unsafe { + TICK += 1; + if TICK % 100 == 0 { + println!("timer"); + } + } + super::timer::set_next(); } #[derive(Debug, Clone)] diff --git a/src/arch/riscv32/mod.rs b/src/arch/riscv32/mod.rs index c5d2faf..256c764 100644 --- a/src/arch/riscv32/mod.rs +++ b/src/arch/riscv32/mod.rs @@ -3,11 +3,11 @@ extern crate bbl; pub mod serial; pub mod interrupt; +pub mod timer; pub fn init() { println!("Hello RISCV! {}", 123); interrupt::init(); - // Trigger interrupt - unsafe { asm!("mret"); } + timer::init(); loop {} } \ No newline at end of file diff --git a/src/arch/riscv32/timer.rs b/src/arch/riscv32/timer.rs new file mode 100644 index 0000000..962ca2c --- /dev/null +++ b/src/arch/riscv32/timer.rs @@ -0,0 +1,33 @@ +use super::riscv::register::*; +use super::bbl::sbi; + +#[cfg(target_pointer_width = "64")] +pub fn get_cycle() -> u64 { + time::read() as u64 +} + +#[cfg(target_pointer_width = "32")] +pub fn get_cycle() -> u64 { + loop { + let hi = timeh::read(); + let lo = time::read(); + let tmp = timeh::read(); + if hi == tmp { + return ((hi as u64) << 32) | (lo as u64); + } + } +} + +pub fn init() { + // Enable supervisor timer interrupt + unsafe { sie::set_stimer(); } + + set_next(); + println!("timer: init end"); +} + +pub fn set_next() { + // 100Hz @ QEMU + let timebase = 100000; + sbi::set_timer(get_cycle() + timebase); +} \ No newline at end of file