From 1f093dd1935439ac130779710685fa58e2e52477 Mon Sep 17 00:00:00 2001 From: zhangxinyu <840317537@qq.com> Date: Wed, 24 May 2023 16:51:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=97=B6=E9=92=9F=E4=B8=AD?= =?UTF-8?q?=E6=96=AD=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ch3/os/src/main.rs | 15 ++++++++++----- ch3/os/src/sbi.rs | 5 +++++ ch3/os/src/syscall/mod.rs | 2 ++ ch3/os/src/syscall/process.rs | 5 +++++ ch3/os/src/timer.rs | 29 +++++++++++++++++++++++++++++ ch3/os/src/trap/mod.rs | 28 ++++++++++++++++++++-------- 6 files changed, 71 insertions(+), 13 deletions(-) create mode 100644 ch3/os/src/timer.rs diff --git a/ch3/os/src/main.rs b/ch3/os/src/main.rs index 1cf5d04..f6e00d3 100644 --- a/ch3/os/src/main.rs +++ b/ch3/os/src/main.rs @@ -8,13 +8,18 @@ use lang_items::console; pub mod lang_items; pub mod sbi; -// pub mod batch; pub mod sync; pub mod trap; pub mod syscall; pub mod loader; pub mod config; pub mod task; +pub mod timer; + +#[path = "boards/qemu.rs"] +mod board; + + // 汇编脚本引入, 调整内核的内存布局之后, 会跳入到 rust_main中执行 global_asm!(include_str!("entry.asm")); @@ -40,13 +45,13 @@ pub fn rust_main(){ println!("boot_stack_top_bound: {:#x}, boot_stack_lower_bound: {:#x}", boot_stack_top_bound as usize, boot_stack_lower_bound as usize); trap::init(); + loader::load_app(); + trap::enable_timer_interrupt(); // 允许定时器中断 + timer::set_next_trigger(); // 在进入用户态之前, 设置一个时钟中断, 防止第一个用户任务死循环 task::run_first_task(); - // batch::init(); - // batch::run_next_app(); - loop { - } + panic!("Disable run here") } /// ## 初始化bss段 diff --git a/ch3/os/src/sbi.rs b/ch3/os/src/sbi.rs index e954239..f1cf584 100644 --- a/ch3/os/src/sbi.rs +++ b/ch3/os/src/sbi.rs @@ -37,4 +37,9 @@ pub fn console_put_char(c: usize) { pub fn shutdown() -> ! { sbi_call(SRST_EXTENSION, SBI_SHUTDOWN, 0, 0, 0); panic!("It should shutdown!") +} + +// 设置 mtimecmp 的值 +pub fn set_timer(timer: usize) { + sbi_call(SBI_SET_TIMER, timer, 0, 0, 0); } \ No newline at end of file diff --git a/ch3/os/src/syscall/mod.rs b/ch3/os/src/syscall/mod.rs index 4b907ee..f88bcfd 100644 --- a/ch3/os/src/syscall/mod.rs +++ b/ch3/os/src/syscall/mod.rs @@ -1,6 +1,7 @@ const SYSCALL_WRITE: usize = 64; const SYSCALL_EXIT: usize = 93; const SYSCALL_YIELD: usize = 124; +const SYSCALL_GET_TIME: usize = 169; mod fs; mod process; @@ -14,6 +15,7 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { SYSCALL_WRITE => sys_write(args[0], args[1] as *const u8, args[2]), SYSCALL_EXIT => sys_exit(args[0] as i32), SYSCALL_YIELD => sys_yield(), + SYSCALL_GET_TIME => sys_get_time(), _ => panic!("Unsupported syscall_id: {}", syscall_id), } } \ No newline at end of file diff --git a/ch3/os/src/syscall/process.rs b/ch3/os/src/syscall/process.rs index 03fef54..0f9b085 100644 --- a/ch3/os/src/syscall/process.rs +++ b/ch3/os/src/syscall/process.rs @@ -2,6 +2,7 @@ // use crate::batch::run_next_app; use crate::println; use crate::task::{exit_current_and_run_next, suspend_current_and_run_next}; +use crate::timer::get_time_ms; /// 任务退出, 并立即切换任务 pub fn sys_exit(exit_code: i32) -> ! { @@ -13,4 +14,8 @@ pub fn sys_exit(exit_code: i32) -> ! { pub fn sys_yield() -> isize { suspend_current_and_run_next(); 0 +} + +pub fn sys_get_time() -> isize { + get_time_ms() as isize } \ No newline at end of file diff --git a/ch3/os/src/timer.rs b/ch3/os/src/timer.rs new file mode 100644 index 0000000..2325a61 --- /dev/null +++ b/ch3/os/src/timer.rs @@ -0,0 +1,29 @@ + +use riscv::register::time; +use crate::config::CLOCK_FREQ; +use crate::sbi::set_timer; + +const TICKS_PER_SEC: usize = 100; +const MICRO_PER_SEC: usize = 1_000_000; +const MSEC_PER_SEC: usize = 1_000; + +// +pub fn get_time() -> usize { + time::read() +} + +// 读取mtime的值, 然后使用 (当前每秒的频率 / TICKS_PER_SEC 100) = 得到 10ms的数值的增量, 相加得到下一个下10ms 后mtime应该属于的值 +// 并设置mtimecmp, 这样在10ms后就会发出一个S特权的时钟中断 +pub fn set_next_trigger() { + set_timer(get_time() + CLOCK_FREQ / TICKS_PER_SEC); +} + +// 以微秒为单位, 返回当前计数器经过的微秒 +// 当前 (计时器的值的总数 / 频率) = 计时器中经过了多少秒, (计时器的值的总数 / 频率) * 1_000_000 得到微秒(1秒有1_000_000微秒) +pub fn get_time_us() -> usize { + time::read() / (CLOCK_FREQ / MICRO_PER_SEC) +} + +pub fn get_time_ms() -> usize { + time::read() / (CLOCK_FREQ / MSEC_PER_SEC) +} diff --git a/ch3/os/src/trap/mod.rs b/ch3/os/src/trap/mod.rs index a9c43b2..7eadd5c 100644 --- a/ch3/os/src/trap/mod.rs +++ b/ch3/os/src/trap/mod.rs @@ -1,15 +1,14 @@ mod context; use core::arch::global_asm; -use riscv::register::{ - mtvec::TrapMode, - scause::{self, Exception, Trap}, - stval, stvec, -}; +use riscv::register::{mtvec::TrapMode, scause::{self, Exception, Trap}, sie, stval, stvec}; +use riscv::register::scause::Interrupt; + pub use context::TrapContext; -// use crate::batch::run_next_app; use crate::println; use crate::syscall::syscall; +use crate::task::{exit_current_and_run_next, suspend_current_and_run_next}; +use crate::timer::set_next_trigger; @@ -26,6 +25,12 @@ pub fn init() { } } +// 设置riscv 允许定时器中断 +pub fn enable_timer_interrupt() { + unsafe { + sie::set_stimer(); + } +} // 这个函数是 trap.S 中__alltraps 保存完所有寄存器在内核栈 之后会进入到这里 #[no_mangle] @@ -43,12 +48,19 @@ pub fn trap_handler(trap_context: &mut TrapContext) -> &mut TrapContext { // 访问不允许的内存 Trap::Exception(Exception::StoreFault) | Trap::Exception(Exception::StorePageFault) => { println!("[kernel] PageFault in application, kernel killed it."); - // run_next_app(); + exit_current_and_run_next(); } // 非法指令 Trap::Exception(Exception::IllegalInstruction) => { println!("[kernel] IllegalInstruction in application, kernel killed it."); - // run_next_app(); + exit_current_and_run_next(); + } + Trap::Interrupt(Interrupt::SupervisorTimer) => { + println!("Clock interrupt Clock interrupt Clock interrupt Clock interrupt"); + // 发生时钟中断之后, 继续设置下一个时钟中断的发起时间 + set_next_trigger(); + // 暂停当前任务, 切换新的任务 + suspend_current_and_run_next(); } // 未知错误 _ => {