添加时钟中断处理

ch3
zhangxinyu 2 years ago
parent bfed67715d
commit 1f093dd193

@ -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段

@ -38,3 +38,8 @@ 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);
}

@ -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),
}
}

@ -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) -> ! {
@ -14,3 +15,7 @@ pub fn sys_yield() -> isize {
suspend_current_and_run_next();
0
}
pub fn sys_get_time() -> isize {
get_time_ms() as isize
}

@ -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)
}

@ -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();
}
// 未知错误
_ => {

Loading…
Cancel
Save