mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-22 08:06:17 +04:00
Use uart16550 as serial in riscv as well
This commit is contained in:
parent
548495a149
commit
b3f86cc3d1
@ -1,5 +1,5 @@
|
||||
pub mod consts;
|
||||
#[path = "../../../../drivers/serial/16550_reg.rs"]
|
||||
#[path = "../../../../drivers/serial/uart16550.rs"]
|
||||
pub mod serial;
|
||||
|
||||
/// Device tree bytes
|
||||
|
@ -2,6 +2,7 @@ pub use self::context::*;
|
||||
use crate::drivers::IRQ_MANAGER;
|
||||
use log::*;
|
||||
use riscv::register::*;
|
||||
use riscv::register::{scause::Scause, sscratch, stvec};
|
||||
use trapframe::UserContext;
|
||||
|
||||
pub mod consts;
|
||||
@ -33,7 +34,7 @@ pub unsafe fn restore(flags: usize) {
|
||||
///
|
||||
/// This function is called from `trap.asm`.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rust_trap(tf: &mut TrapFrame) {
|
||||
pub extern "C" fn trap_handler(scause: Scause, stval: usize, tf: &mut TrapFrame) {
|
||||
use self::scause::{Exception as E, Interrupt as I, Trap};
|
||||
trace!(
|
||||
"Interrupt @ CPU{}: {:?} ",
|
||||
@ -59,27 +60,7 @@ fn external() {
|
||||
super::board::handle_external_interrupt();
|
||||
}
|
||||
|
||||
// true means handled, false otherwise
|
||||
let handlers = [try_process_serial, try_process_drivers];
|
||||
for handler in handlers.iter() {
|
||||
if handler() == true {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn try_process_serial() -> bool {
|
||||
match super::io::getchar_option() {
|
||||
Some(ch) => {
|
||||
crate::trap::serial(ch);
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn try_process_drivers() -> bool {
|
||||
IRQ_MANAGER.read().try_handle_interrupt(None)
|
||||
IRQ_MANAGER.read().try_handle_interrupt(None);
|
||||
}
|
||||
|
||||
fn ipi() {
|
||||
|
@ -5,7 +5,9 @@ use device_tree::{DeviceTree, Node};
|
||||
|
||||
use super::bus::virtio_mmio::virtio_probe;
|
||||
use super::net::router::router_init;
|
||||
use super::serial::uart16550;
|
||||
use super::CMDLINE;
|
||||
use crate::memory::phys_to_virt;
|
||||
|
||||
const DEVICE_TREE_MAGIC: u32 = 0xd00dfeed;
|
||||
|
||||
@ -18,7 +20,11 @@ fn walk_dt_node(dt: &Node) {
|
||||
if compatible == "rcore,router" {
|
||||
router_init();
|
||||
}
|
||||
// TODO: initial other devices (16650, etc.)
|
||||
if compatible == "ns16550a" {
|
||||
let addr = dt.prop_u64("reg").unwrap() as usize;
|
||||
uart16550::init(None, phys_to_virt(addr));
|
||||
}
|
||||
// TODO: init other devices
|
||||
}
|
||||
if let Ok(bootargs) = dt.prop_str("bootargs") {
|
||||
if bootargs.len() > 0 {
|
||||
|
@ -38,7 +38,7 @@ impl Driver for COM {
|
||||
}
|
||||
|
||||
fn get_id(&self) -> String {
|
||||
format!("com_{}", self.base)
|
||||
format!("uart16550_{}", self.base)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ use core::fmt::{Result, Write};
|
||||
pub mod com;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub mod keyboard;
|
||||
pub mod uart16550;
|
||||
|
||||
pub trait SerialDriver: Driver {
|
||||
// read one byte from tty
|
||||
|
@ -1,18 +1,42 @@
|
||||
//! 16550 serial adapter driver for malta board
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use super::SerialDriver;
|
||||
use crate::drivers::IRQ_MANAGER;
|
||||
use crate::drivers::SERIAL_DRIVERS;
|
||||
use crate::drivers::{DeviceType, Driver, DRIVERS};
|
||||
use crate::sync::SpinLock as Mutex;
|
||||
use crate::util::{read, write};
|
||||
use alloc::{string::String, sync::Arc};
|
||||
use core::fmt::{Arguments, Result, Write};
|
||||
|
||||
pub struct SerialPort {
|
||||
base: usize,
|
||||
}
|
||||
|
||||
impl Driver for SerialPort {
|
||||
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool {
|
||||
if let Some(c) = self.getchar_option() {
|
||||
crate::trap::serial(c);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn device_type(&self) -> DeviceType {
|
||||
DeviceType::Serial
|
||||
}
|
||||
|
||||
fn get_id(&self) -> String {
|
||||
format!("com_{}", self.base)
|
||||
}
|
||||
}
|
||||
|
||||
impl SerialPort {
|
||||
fn new() -> SerialPort {
|
||||
SerialPort { base: 0 }
|
||||
fn new(base: usize) -> SerialPort {
|
||||
let mut res = SerialPort { base: 0 };
|
||||
res.init(base);
|
||||
res
|
||||
}
|
||||
|
||||
pub fn init(&mut self, base: usize) {
|
||||
@ -34,12 +58,12 @@ impl SerialPort {
|
||||
}
|
||||
|
||||
/// non-blocking version of putchar()
|
||||
pub fn putchar(&mut self, c: u8) {
|
||||
pub fn putchar(&self, c: u8) {
|
||||
write(self.base + COM_TX, c);
|
||||
}
|
||||
|
||||
/// blocking version of getchar()
|
||||
pub fn getchar(&mut self) -> char {
|
||||
pub fn getchar(&mut self) -> u8 {
|
||||
loop {
|
||||
if (read::<u8>(self.base + COM_LSR) & COM_LSR_DATA) == 0 {
|
||||
break;
|
||||
@ -47,43 +71,29 @@ impl SerialPort {
|
||||
}
|
||||
let c = read::<u8>(self.base + COM_RX);
|
||||
match c {
|
||||
255 => '\0', // null
|
||||
c => c as char,
|
||||
255 => b'\0', // null
|
||||
c => c,
|
||||
}
|
||||
}
|
||||
|
||||
/// non-blocking version of getchar()
|
||||
pub fn getchar_option(&mut self) -> Option<char> {
|
||||
pub fn getchar_option(&self) -> Option<u8> {
|
||||
match read::<u8>(self.base + COM_LSR) & COM_LSR_DATA {
|
||||
0 => None,
|
||||
_ => Some(read::<u8>(self.base + COM_RX) as u8 as char),
|
||||
_ => Some(read::<u8>(self.base + COM_RX) as u8),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn putfmt(&mut self, fmt: Arguments) {
|
||||
self.write_fmt(fmt).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for SerialPort {
|
||||
fn write_str(&mut self, s: &str) -> Result {
|
||||
for c in s.bytes() {
|
||||
match c {
|
||||
127 => {
|
||||
self.putchar(8);
|
||||
self.putchar(b' ');
|
||||
self.putchar(8);
|
||||
}
|
||||
b'\n' => {
|
||||
self.putchar(b'\r');
|
||||
self.putchar(b'\n');
|
||||
}
|
||||
c => {
|
||||
self.putchar(c);
|
||||
}
|
||||
}
|
||||
impl SerialDriver for SerialPort {
|
||||
fn read(&self) -> u8 {
|
||||
self.getchar_option().unwrap_or(0)
|
||||
}
|
||||
|
||||
fn write(&self, data: &[u8]) {
|
||||
for byte in data {
|
||||
self.putchar(*byte);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,10 +117,10 @@ const COM_LSR_DATA: u8 = 0x01; // Data available
|
||||
const COM_LSR_TXRDY: u8 = 0x20; // Transmit buffer avail
|
||||
const COM_LSR_TSRE: u8 = 0x40; // Transmitter off
|
||||
|
||||
lazy_static! {
|
||||
pub static ref SERIAL_PORT: Mutex<SerialPort> = Mutex::new(SerialPort::new());
|
||||
}
|
||||
|
||||
pub fn init(base: usize) {
|
||||
SERIAL_PORT.lock().init(base);
|
||||
pub fn init(irq: Option<usize>, base: usize) {
|
||||
info!("Init uart16550 at {:#x}", base);
|
||||
let com = Arc::new(SerialPort::new(base));
|
||||
DRIVERS.write().push(com.clone());
|
||||
SERIAL_DRIVERS.write().push(com.clone());
|
||||
IRQ_MANAGER.write().register_opt(irq, com);
|
||||
}
|
@ -9,6 +9,7 @@ use crate::arch::{
|
||||
memory::{get_page_fault_addr, set_page_table},
|
||||
paging::*,
|
||||
};
|
||||
use crate::drivers::IRQ_MANAGER;
|
||||
use crate::fs::{FileHandle, FileLike, OpenOptions, FOLLOW_MAX_DEPTH};
|
||||
use crate::ipc::SemProc;
|
||||
use crate::memory::{
|
||||
@ -443,9 +444,12 @@ pub fn spawn(thread: Arc<Thread>) {
|
||||
Syscall => exit = handle_syscall(&thread, &mut cx).await,
|
||||
IrqMin..=IrqMax => {
|
||||
crate::arch::interrupt::ack(trap_num);
|
||||
trace!("handle irq {}", trap_num);
|
||||
info!("handle irq {:#x}", trap_num);
|
||||
if trap_num == Timer {
|
||||
crate::arch::interrupt::timer();
|
||||
} else {
|
||||
// we don't know the actual irq
|
||||
IRQ_MANAGER.read().try_handle_interrupt(None);
|
||||
}
|
||||
}
|
||||
_ if is_page_fault(trap_num) => {
|
||||
|
Loading…
Reference in New Issue
Block a user