1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-23 08:26:17 +04:00

aarch64: implement I/O by serial port

This commit is contained in:
equation314 2018-10-29 13:38:27 +08:00
parent 517a78d114
commit abf3418d24
5 changed files with 117 additions and 20 deletions

View File

@ -2,8 +2,12 @@
extern crate bcm2837; extern crate bcm2837;
pub mod serial;
pub fn init() { pub fn init() {
// TODO assert_has_not_been_called!("board::init must be called only once");
bcm2837::gpio::Gpio::new(14).set_gpio_pd(0);
bcm2837::gpio::Gpio::new(15).set_gpio_pd(0); serial::SERIAL_PORT.lock().init();
println!("Hello Raspberry Pi!");
} }

View File

@ -0,0 +1,73 @@
use super::bcm2837::mini_uart::MiniUart;
use core::fmt;
use spin::Mutex;
/// Struct to get a global SerialPort interface
pub struct SerialPort {
mu: Option<MiniUart>,
}
pub trait SerialRead {
fn receive(&mut self) -> u8;
}
impl SerialPort {
/// Creates a new instance of `SerialPort`.
const fn new() -> SerialPort {
SerialPort { mu: None }
}
/// Init a newly created SerialPort, can only be called once.
pub fn init(&mut self) {
assert_has_not_been_called!("SerialPort::init must be called only once");
self.mu = Some(MiniUart::new());
}
/// Writes the byte `byte` to the UART device.
pub fn write_byte(&mut self, byte: u8) {
match &mut self.mu {
Some(mu) => mu.write_byte(byte),
None => panic!("SerialPort is not initialized"),
}
}
/// Reads a byte from the UART device, blocking until a byte is available.
pub fn read_byte(&mut self) -> u8 {
match &mut self.mu {
Some(mu) => return mu.read_byte(),
None => panic!("SerialPort is not initialized"),
}
}
}
impl SerialRead for SerialPort {
fn receive(&mut self) -> u8 {
self.read_byte()
}
}
impl fmt::Write for SerialPort {
fn write_str(&mut self, s: &str) -> fmt::Result {
for byte in s.bytes() {
match byte {
// Backspace
b'\x7f' => {
self.write_byte(b'\x08');
self.write_byte(b' ');
self.write_byte(b'\x08');
}
// Return
b'\n' => {
self.write_byte(b'\r');
self.write_byte(b'\n');
}
// Others
_ => self.write_byte(byte),
}
}
Ok(())
}
}
pub static SERIAL_PORT: Mutex<SerialPort> = Mutex::new(SerialPort::new());

View File

@ -55,6 +55,15 @@ switch_to_el1:
movk x0, #0x8000, lsl #16 movk x0, #0x8000, lsl #16
msr hcr_el2, x0 msr hcr_el2, x0
# don't trap accessing SVE registers (ref: D10.2.30)
msr cptr_el2, xzr
# enable floating point and SVE (SIMD) (bits 20, 21) (ref: D10.2.29)
mrs x0, cpacr_el1
orr x0, x0, #(0x3 << 20)
msr cpacr_el1, x0
# Set SCTLR to known state (RES1: 11, 20, 22, 23, 28, 29) (ref: D10.2.100) # Set SCTLR to known state (RES1: 11, 20, 22, 23, 28, 29) (ref: D10.2.100)
mov x0, #0x0800 mov x0, #0x0800
movk x0, #0x30d0, lsl #16 movk x0, #0x30d0, lsl #16

View File

@ -1,13 +1,12 @@
//! Serial driver for aarch64. //! Serial driver for aarch64.
use core::fmt::{Arguments}; use core::fmt::{Arguments, Write};
use super::board::serial::{SerialRead, SERIAL_PORT};
/// TODO
pub fn getchar() -> char { pub fn getchar() -> char {
unimplemented!() SERIAL_PORT.lock().receive() as char
} }
/// TODO pub fn putfmt(fmt: Arguments) {
pub fn putfmt(fmt: Arguments<'_>) { SERIAL_PORT.lock().write_fmt(fmt).unwrap()
unimplemented!()
} }

View File

@ -13,21 +13,33 @@ pub mod board;
/// The entry point of kernel /// The entry point of kernel
#[no_mangle] // don't mangle the name of this function #[no_mangle] // don't mangle the name of this function
pub extern "C" fn rust_main() -> ! { pub extern "C" fn rust_main() -> ! {
// Init board. // Init board to enable serial port.
board::init(); board::init();
println!("Hello ARM64!");
// First init log mod, so that we can print log info. // First init log mod, so that we can print log info.
// ::logging::init(); ::logging::init();
// Init trap handling.
// interrupt::init();
// Init physical memory management and heap.
// memory::init();
// Now heap is available
// timer::init();
::kmain(); loop {
print!(">> ");
loop {
let c = io::getchar();
match c {
'\u{7f}' => {
print!("\u{7f}");
}
' '...'\u{7e}' => {
print!("{}", c);
}
'\n' | '\r' => {
print!("\n");
break;
}
_ => {}
}
}
}
// ::kmain();
} }
global_asm!(include_str!("boot/boot.S")); global_asm!(include_str!("boot/boot.S"));