Chapter3: power2/3/5 & sleep test worked on k210/qemu based on timer.

ch3-dev
Yifan Wu 4 years ago
parent 4590f233b5
commit 63aaa9d0a1

@ -8,4 +8,8 @@ edition = "2018"
[dependencies]
riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] }
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
[features]
board_qemu = []
board_k210 = []

@ -29,7 +29,7 @@ $(KERNEL_BIN): kernel
kernel:
@cd ../user && make build
@cargo build --release
@cargo build --release --features "board_$(BOARD)"
clean:
@cargo clean

@ -2,4 +2,10 @@ pub const USER_STACK_SIZE: usize = 4096 * 2;
pub const KERNEL_STACK_SIZE: usize = 4096 * 2;
pub const MAX_APP_NUM: usize = 4;
pub const APP_BASE_ADDRESS: usize = 0x80100000;
pub const APP_SIZE_LIMIT: usize = 0x20000;
pub const APP_SIZE_LIMIT: usize = 0x20000;
#[cfg(feature = "board_k210")]
pub const CPU_FREQ: usize = 10000000;
#[cfg(feature = "board_qemu")]
pub const CPU_FREQ: usize = 12500000;

@ -14,6 +14,7 @@ mod trap;
mod loader;
mod config;
mod task;
mod timer;
global_asm!(include_str!("entry.asm"));
global_asm!(include_str!("link_app.S"));
@ -34,6 +35,9 @@ pub fn rust_main() -> ! {
println!("[kernel] Hello, world!");
trap::init();
loader::load_apps();
trap::enable_interrupt();
trap::enable_timer_interrupt();
timer::set_next_trigger();
task::run_first_task();
panic!("Unreachable in rust_main!");
}

@ -24,6 +24,10 @@ fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
ret
}
pub fn set_timer(timer: usize) {
sbi_call(SBI_SET_TIMER, timer, 0, 0);
}
pub fn console_putchar(c: usize) {
sbi_call(SBI_CONSOLE_PUTCHAR, c, 0, 0);
}

@ -1,7 +1,7 @@
const SYSCALL_WRITE: usize = 64;
const SYSCALL_EXIT: usize = 93;
const SYSCALL_YIELD: usize = 124;
//const SYSCALL_GET_TIME: usize = 169;
const SYSCALL_GET_TIME: usize = 169;
mod fs;
mod process;
@ -14,6 +14,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),
}
}

@ -1,18 +1,20 @@
use crate::task::{
mark_current_suspended,
mark_current_exited,
run_next_task
suspend_current_and_run_next,
exit_current_and_run_next,
};
use crate::timer::get_time;
pub fn sys_exit(xstate: i32) -> ! {
println!("[kernel] Application exited with code {}", xstate);
mark_current_exited();
run_next_task();
exit_current_and_run_next();
panic!("Unreachable in sys_exit!");
}
pub fn sys_yield() -> isize {
mark_current_suspended();
run_next_task();
suspend_current_and_run_next();
0
}
pub fn sys_get_time() -> isize {
get_time() as isize
}

@ -94,7 +94,7 @@ impl TaskManager {
);
}
} else {
panic!("[kernel] All applications completed!");
panic!("All applications completed!");
}
}
}
@ -103,14 +103,24 @@ pub fn run_first_task() {
TASK_MANAGER.run_first_task();
}
pub fn run_next_task() {
fn run_next_task() {
TASK_MANAGER.run_next_task();
}
pub fn mark_current_suspended() {
fn mark_current_suspended() {
TASK_MANAGER.mark_current_suspended();
}
pub fn mark_current_exited() {
fn mark_current_exited() {
TASK_MANAGER.mark_current_exited();
}
pub fn suspend_current_and_run_next() {
mark_current_suspended();
run_next_task();
}
pub fn exit_current_and_run_next() {
mark_current_exited();
run_next_task();
}

@ -0,0 +1,13 @@
use riscv::register::time;
use crate::sbi::set_timer;
use crate::config::CPU_FREQ;
const TICKS_PER_SEC: usize = 100;
pub fn get_time() -> usize {
time::read()
}
pub fn set_next_trigger() {
set_timer(get_time() + CPU_FREQ / TICKS_PER_SEC);
}

@ -7,10 +7,18 @@ use riscv::register::{
self,
Trap,
Exception,
Interrupt,
},
stval,
sstatus,
sie,
};
use crate::syscall::syscall;
use crate::task::{
exit_current_and_run_next,
suspend_current_and_run_next,
};
use crate::timer::set_next_trigger;
global_asm!(include_str!("trap.S"));
@ -21,6 +29,14 @@ pub fn init() {
}
}
pub fn enable_interrupt() {
unsafe { sstatus::set_sie(); }
}
pub fn enable_timer_interrupt() {
unsafe { sie::set_stimer(); }
}
#[no_mangle]
pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext {
let scause = scause::read();
@ -33,13 +49,15 @@ pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext {
Trap::Exception(Exception::StoreFault) |
Trap::Exception(Exception::StorePageFault) => {
println!("[kernel] PageFault in application, bad addr = {:#x}, bad instruction = {:#x}, core dumped.", stval, cx.sepc);
panic!("[kernel] Cannot continue!");
//run_next_app();
exit_current_and_run_next();
}
Trap::Exception(Exception::IllegalInstruction) => {
println!("[kernel] IllegalInstruction in application, core dumped.");
panic!("[kernel] Cannot continue!");
//run_next_app();
exit_current_and_run_next();
}
Trap::Interrupt(Interrupt::SupervisorTimer) => {
set_next_trigger();
suspend_current_and_run_next();
}
_ => {
panic!("Unsupported trap {:?}, stval = {:#x}!", scause.cause(), stval);

@ -0,0 +1,28 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
const LEN: usize = 100;
#[no_mangle]
fn main() -> i32 {
let p = 3u64;
let m = 998244353u64;
let iter: usize = 100000;
let mut s = [0u64; LEN];
let mut cur = 0usize;
s[cur] = 1;
for i in 1..=iter {
let next = if cur + 1 == LEN { 0 } else { cur + 1 };
s[next] = s[cur] * p % m;
cur = next;
if i % 10000 == 0 {
println!("power_3 [{}/{}]", i, iter);
}
}
println!("{}^{} = {}", p, iter, s[cur]);
println!("Test power_3 OK!");
0
}

@ -1,21 +0,0 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::sys_yield;
const WIDTH: usize = 10;
const HEIGHT: usize = 5;
#[no_mangle]
fn main() -> i32 {
for i in 0..HEIGHT {
for _ in 0..WIDTH { print!("A"); }
println!(" [{}/{}]", i + 1, HEIGHT);
sys_yield();
}
println!("Test write_a OK!");
0
}

@ -0,0 +1,28 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
const LEN: usize = 100;
#[no_mangle]
fn main() -> i32 {
let p = 5u64;
let m = 998244353u64;
let iter: usize = 70000;
let mut s = [0u64; LEN];
let mut cur = 0usize;
s[cur] = 1;
for i in 1..=iter {
let next = if cur + 1 == LEN { 0 } else { cur + 1 };
s[next] = s[cur] * p % m;
cur = next;
if i % 10000 == 0 {
println!("power_5 [{}/{}]", i, iter);
}
}
println!("{}^{} = {}", p, iter, s[cur]);
println!("Test power_5 OK!");
0
}

@ -1,21 +0,0 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::sys_yield;
const WIDTH: usize = 10;
const HEIGHT: usize = 2;
#[no_mangle]
fn main() -> i32 {
for i in 0..HEIGHT {
for _ in 0..WIDTH { print!("B"); }
println!(" [{}/{}]", i + 1, HEIGHT);
sys_yield();
}
println!("Test write_b OK!");
0
}

@ -0,0 +1,28 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
const LEN: usize = 100;
#[no_mangle]
fn main() -> i32 {
let p = 7u64;
let m = 998244353u64;
let iter: usize = 80000;
let mut s = [0u64; LEN];
let mut cur = 0usize;
s[cur] = 1;
for i in 1..=iter {
let next = if cur + 1 == LEN { 0 } else { cur + 1 };
s[next] = s[cur] * p % m;
cur = next;
if i % 10000 == 0 {
println!("power_7 [{}/{}]", i, iter);
}
}
println!("{}^{} = {}", p, iter, s[cur]);
println!("Test power_7 OK!");
0
}

@ -1,21 +0,0 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::sys_yield;
const WIDTH: usize = 10;
const HEIGHT: usize = 3;
#[no_mangle]
fn main() -> i32 {
for i in 0..HEIGHT {
for _ in 0..WIDTH { print!("C"); }
println!(" [{}/{}]", i + 1, HEIGHT);
sys_yield();
}
println!("Test write_c OK!");
0
}

@ -0,0 +1,18 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{sys_get_time, sys_yield};
#[no_mangle]
fn main() -> i32 {
let current_timer = sys_get_time();
let wait_for = current_timer + 10000000;
while sys_get_time() < wait_for {
sys_yield();
}
println!("Test sleep OK!");
0
}
Loading…
Cancel
Save