From 0b900b6f03dab94a0926ddba0e9d460af4f36521 Mon Sep 17 00:00:00 2001 From: lcy1996 <992195697@qq.com> Date: Thu, 8 Nov 2018 19:40:28 +0800 Subject: [PATCH] Code Transplanting: Blocking getchar --- kernel/src/arch/riscv32/interrupt.rs | 7 ++++++ kernel/src/console.rs | 32 +++++++++++++++++++++++++++- kernel/src/trap.rs | 8 +++++-- riscv-pk/machine/uart16550.c | 2 ++ 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/kernel/src/arch/riscv32/interrupt.rs b/kernel/src/arch/riscv32/interrupt.rs index 0d054d0..b1d291e 100644 --- a/kernel/src/arch/riscv32/interrupt.rs +++ b/kernel/src/arch/riscv32/interrupt.rs @@ -22,6 +22,8 @@ pub fn init() { stvec::write(__alltraps as usize, stvec::TrapMode::Direct); // Enable IPI sie::set_ssoft(); + // Enable serial interrupt + sie::set_sext(); } info!("interrupt: init end"); } @@ -72,6 +74,7 @@ pub extern fn rust_trap(tf: &mut TrapFrame) { use super::riscv::register::scause::{Trap, Interrupt as I, Exception as E}; trace!("Interrupt: {:?}", tf.scause.cause()); match tf.scause.cause() { + Trap::Interrupt(I::SupervisorExternal) => serial(), Trap::Interrupt(I::SupervisorTimer) => timer(), Trap::Exception(E::IllegalInstruction) => illegal_inst(tf), Trap::Exception(E::UserEnvCall) => syscall(tf), @@ -83,6 +86,10 @@ pub extern fn rust_trap(tf: &mut TrapFrame) { trace!("Interrupt end"); } +fn serial() { + ::trap::serial(super::io::getchar()); +} + fn ipi() { debug!("IPI"); super::bbl::sbi::clear_ipi(); diff --git a/kernel/src/console.rs b/kernel/src/console.rs index 9f6efbd..c4106f5 100644 --- a/kernel/src/console.rs +++ b/kernel/src/console.rs @@ -1,11 +1,14 @@ use core::ops::Deref; use alloc::string::String; use arch::io::getchar; +use alloc::collections::VecDeque; +use sync::Condvar; +use sync::SpinNoIrqLock as Mutex; pub fn get_line() -> String { let mut s = String::new(); loop { - let c = getchar(); + let c = get_char(); match c { '\u{7f}' /* '\b' */ => { if s.pop().is_some() { @@ -23,4 +26,31 @@ pub fn get_line() -> String { _ => {} } } +} + + #[derive(Default)] +pub struct InputQueue { + buf: Mutex>, + pushed: Condvar, +} + impl InputQueue { + pub fn push(&self, c: char) { + self.buf.lock().push_back(c); + self.pushed.notify_one(); + } + pub fn pop(&self) -> char { + loop { + let ret = self.buf.lock().pop_front(); + match ret { + Some(c) => return c, + None => self.pushed._wait(), + } + } + } +} + lazy_static! { + pub static ref CONSOLE_INPUT: InputQueue = InputQueue::default(); +} + pub fn get_char() -> char { + CONSOLE_INPUT.pop() } \ No newline at end of file diff --git a/kernel/src/trap.rs b/kernel/src/trap.rs index d6e8ddd..0e59548 100644 --- a/kernel/src/trap.rs +++ b/kernel/src/trap.rs @@ -5,10 +5,10 @@ use arch::cpu; pub static mut TICK: usize = 0; pub fn timer() { - processor().tick(); if cpu::id() == 0 { unsafe { TICK += 1; } } + processor().tick(); //info!("finish before return!"); } @@ -20,4 +20,8 @@ pub fn error(tf: &TrapFrame) -> ! { processor().manager().exit(pid, 0x100); processor().yield_now(); unreachable!(); -} \ No newline at end of file +} + +pub fn serial(c: char) { + ::console::CONSOLE_INPUT.push(c); +} \ No newline at end of file diff --git a/riscv-pk/machine/uart16550.c b/riscv-pk/machine/uart16550.c index fe1ba99..93fbb43 100644 --- a/riscv-pk/machine/uart16550.c +++ b/riscv-pk/machine/uart16550.c @@ -57,6 +57,8 @@ static void uart16550_done(const struct fdt_scan_node *node, void *extra) uart16550[1] = 0x00; // (hi byte) uart16550[3] = 0x03; // 8 bits, no parity, one stop bit uart16550[2] = 0xC7; // Enable FIFO, clear them, with 14-byte threshold + uart16550[4] = 0x0B; + uart16550[1] = 0x01; // Enable interrupt } void query_uart16550(uintptr_t fdt)