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:
parent
517a78d114
commit
abf3418d24
@ -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!");
|
||||||
}
|
}
|
||||||
|
73
kernel/src/arch/aarch64/board/raspi3/serial.rs
Normal file
73
kernel/src/arch/aarch64/board/raspi3/serial.rs
Normal 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());
|
@ -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
|
||||||
|
@ -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!()
|
|
||||||
}
|
}
|
||||||
|
@ -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"));
|
||||||
|
Loading…
Reference in New Issue
Block a user