Chapter3: power2/3/5 & sleep test worked on k210/qemu based on timer.
This commit is contained in:
parent
adbe671fe1
commit
1cef77eac7
17 changed files with 183 additions and 82 deletions
|
@ -9,3 +9,7 @@ edition = "2018"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] }
|
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:
|
kernel:
|
||||||
@cd ../user && make build
|
@cd ../user && make build
|
||||||
@cargo build --release
|
@cargo build --release --features "board_$(BOARD)"
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@cargo clean
|
@cargo clean
|
||||||
|
|
|
@ -3,3 +3,9 @@ pub const KERNEL_STACK_SIZE: usize = 4096 * 2;
|
||||||
pub const MAX_APP_NUM: usize = 4;
|
pub const MAX_APP_NUM: usize = 4;
|
||||||
pub const APP_BASE_ADDRESS: usize = 0x80100000;
|
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 loader;
|
||||||
mod config;
|
mod config;
|
||||||
mod task;
|
mod task;
|
||||||
|
mod timer;
|
||||||
|
|
||||||
global_asm!(include_str!("entry.asm"));
|
global_asm!(include_str!("entry.asm"));
|
||||||
global_asm!(include_str!("link_app.S"));
|
global_asm!(include_str!("link_app.S"));
|
||||||
|
@ -34,6 +35,9 @@ pub fn rust_main() -> ! {
|
||||||
println!("[kernel] Hello, world!");
|
println!("[kernel] Hello, world!");
|
||||||
trap::init();
|
trap::init();
|
||||||
loader::load_apps();
|
loader::load_apps();
|
||||||
|
trap::enable_interrupt();
|
||||||
|
trap::enable_timer_interrupt();
|
||||||
|
timer::set_next_trigger();
|
||||||
task::run_first_task();
|
task::run_first_task();
|
||||||
panic!("Unreachable in rust_main!");
|
panic!("Unreachable in rust_main!");
|
||||||
}
|
}
|
|
@ -24,6 +24,10 @@ fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_timer(timer: usize) {
|
||||||
|
sbi_call(SBI_SET_TIMER, timer, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn console_putchar(c: usize) {
|
pub fn console_putchar(c: usize) {
|
||||||
sbi_call(SBI_CONSOLE_PUTCHAR, c, 0, 0);
|
sbi_call(SBI_CONSOLE_PUTCHAR, c, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const SYSCALL_WRITE: usize = 64;
|
const SYSCALL_WRITE: usize = 64;
|
||||||
const SYSCALL_EXIT: usize = 93;
|
const SYSCALL_EXIT: usize = 93;
|
||||||
const SYSCALL_YIELD: usize = 124;
|
const SYSCALL_YIELD: usize = 124;
|
||||||
//const SYSCALL_GET_TIME: usize = 169;
|
const SYSCALL_GET_TIME: usize = 169;
|
||||||
|
|
||||||
mod fs;
|
mod fs;
|
||||||
mod process;
|
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_WRITE => sys_write(args[0], args[1] as *const u8, args[2]),
|
||||||
SYSCALL_EXIT => sys_exit(args[0] as i32),
|
SYSCALL_EXIT => sys_exit(args[0] as i32),
|
||||||
SYSCALL_YIELD => sys_yield(),
|
SYSCALL_YIELD => sys_yield(),
|
||||||
|
SYSCALL_GET_TIME => sys_get_time(),
|
||||||
_ => panic!("Unsupported syscall_id: {}", syscall_id),
|
_ => panic!("Unsupported syscall_id: {}", syscall_id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,20 @@
|
||||||
use crate::task::{
|
use crate::task::{
|
||||||
mark_current_suspended,
|
suspend_current_and_run_next,
|
||||||
mark_current_exited,
|
exit_current_and_run_next,
|
||||||
run_next_task
|
|
||||||
};
|
};
|
||||||
|
use crate::timer::get_time;
|
||||||
|
|
||||||
pub fn sys_exit(xstate: i32) -> ! {
|
pub fn sys_exit(xstate: i32) -> ! {
|
||||||
println!("[kernel] Application exited with code {}", xstate);
|
println!("[kernel] Application exited with code {}", xstate);
|
||||||
mark_current_exited();
|
exit_current_and_run_next();
|
||||||
run_next_task();
|
|
||||||
panic!("Unreachable in sys_exit!");
|
panic!("Unreachable in sys_exit!");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sys_yield() -> isize {
|
pub fn sys_yield() -> isize {
|
||||||
mark_current_suspended();
|
suspend_current_and_run_next();
|
||||||
run_next_task();
|
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sys_get_time() -> isize {
|
||||||
|
get_time() as isize
|
||||||
|
}
|
|
@ -94,7 +94,7 @@ impl TaskManager {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic!("[kernel] All applications completed!");
|
panic!("All applications completed!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,14 +103,24 @@ pub fn run_first_task() {
|
||||||
TASK_MANAGER.run_first_task();
|
TASK_MANAGER.run_first_task();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_next_task() {
|
fn run_next_task() {
|
||||||
TASK_MANAGER.run_next_task();
|
TASK_MANAGER.run_next_task();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mark_current_suspended() {
|
fn mark_current_suspended() {
|
||||||
TASK_MANAGER.mark_current_suspended();
|
TASK_MANAGER.mark_current_suspended();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mark_current_exited() {
|
fn mark_current_exited() {
|
||||||
TASK_MANAGER.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();
|
||||||
|
}
|
13
os/src/timer.rs
Normal file
13
os/src/timer.rs
Normal file
|
@ -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,
|
self,
|
||||||
Trap,
|
Trap,
|
||||||
Exception,
|
Exception,
|
||||||
|
Interrupt,
|
||||||
},
|
},
|
||||||
stval,
|
stval,
|
||||||
|
sstatus,
|
||||||
|
sie,
|
||||||
};
|
};
|
||||||
use crate::syscall::syscall;
|
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"));
|
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]
|
#[no_mangle]
|
||||||
pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext {
|
pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext {
|
||||||
let scause = scause::read();
|
let scause = scause::read();
|
||||||
|
@ -33,13 +49,15 @@ pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext {
|
||||||
Trap::Exception(Exception::StoreFault) |
|
Trap::Exception(Exception::StoreFault) |
|
||||||
Trap::Exception(Exception::StorePageFault) => {
|
Trap::Exception(Exception::StorePageFault) => {
|
||||||
println!("[kernel] PageFault in application, bad addr = {:#x}, bad instruction = {:#x}, core dumped.", stval, cx.sepc);
|
println!("[kernel] PageFault in application, bad addr = {:#x}, bad instruction = {:#x}, core dumped.", stval, cx.sepc);
|
||||||
panic!("[kernel] Cannot continue!");
|
exit_current_and_run_next();
|
||||||
//run_next_app();
|
|
||||||
}
|
}
|
||||||
Trap::Exception(Exception::IllegalInstruction) => {
|
Trap::Exception(Exception::IllegalInstruction) => {
|
||||||
println!("[kernel] IllegalInstruction in application, core dumped.");
|
println!("[kernel] IllegalInstruction in application, core dumped.");
|
||||||
panic!("[kernel] Cannot continue!");
|
exit_current_and_run_next();
|
||||||
//run_next_app();
|
}
|
||||||
|
Trap::Interrupt(Interrupt::SupervisorTimer) => {
|
||||||
|
set_next_trigger();
|
||||||
|
suspend_current_and_run_next();
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
panic!("Unsupported trap {:?}, stval = {:#x}!", scause.cause(), stval);
|
panic!("Unsupported trap {:?}, stval = {:#x}!", scause.cause(), stval);
|
||||||
|
|
28
user/src/bin/00power_3.rs
Normal file
28
user/src/bin/00power_3.rs
Normal file
|
@ -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
|
|
||||||
}
|
|
28
user/src/bin/01power_5.rs
Normal file
28
user/src/bin/01power_5.rs
Normal file
|
@ -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
|
|
||||||
}
|
|
28
user/src/bin/02power_7.rs
Normal file
28
user/src/bin/02power_7.rs
Normal file
|
@ -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
|
|
||||||
}
|
|
18
user/src/bin/03sleep.rs
Normal file
18
user/src/bin/03sleep.rs
Normal file
|
@ -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…
Add table
Add a link
Reference in a new issue