From b6ac53e5a20dc6088b18d6ff7b2a580cc123e4d3 Mon Sep 17 00:00:00 2001 From: tfx2001 Date: Thu, 25 Jul 2024 02:25:08 +0800 Subject: [PATCH] feat(board): support SBI call #02 getchar Support SBI call #0 Console Getchar from UART0. Signed-off-by: tfx2001 --- src/board/mod.rs | 22 ++++++++++++++++++---- src/board/uart.rs | 15 +++++++++++++++ src/trap.rs | 6 +++++- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/board/mod.rs b/src/board/mod.rs index b245b69..ccc5f90 100644 --- a/src/board/mod.rs +++ b/src/board/mod.rs @@ -24,7 +24,7 @@ static UART: Mutex> = Mutex::new(MaybeUninit::uninit()); #[macro_export] macro_rules! print { ($fmt: literal $(, $($args: tt)+)?) => { - $crate::board::_print(format_args!($fmt $(, $($args)+)?)); + $crate::board::putchar(format_args!($fmt $(, $($args)+)?)); }; } @@ -32,7 +32,7 @@ macro_rules! print { macro_rules! println { () => ($crate::print!("\n")); ($($arg:tt)*) => {{ - $crate::board::_print(core::format_args!($($arg)*)); + $crate::board::putchar(core::format_args!($($arg)*)); $crate::println!(); }} } @@ -47,7 +47,7 @@ pub fn board_init() { pins.setup(); let uart = Uart::new(pac::UART0); - uart.setup(250_000, clock.get_clk_freq(clocks::URT0)); + uart.setup(115_200, clock.get_clk_freq(clocks::URT0)); *UART.lock() = MaybeUninit::new(uart); let cpu0_clock_freq = clock.get_cpu0_clk_freq(); @@ -68,12 +68,26 @@ pub fn board_init() { } #[inline] -pub fn _print(args: fmt::Arguments) { +pub fn putchar(args: fmt::Arguments) { let mut guard = UART.lock(); unsafe { guard.assume_init_mut().write_fmt(args).unwrap() } } +#[inline] +pub fn getchar() -> usize { + let mut guard = UART.lock(); + let mut c: u8 = 0; + + unsafe { + if guard.assume_init_mut().receive_byte(&mut c) { + c as _ + } else { + usize::MAX + } + } +} + pub fn board_init_timer() -> MachineTimer { MachineTimer::new(pac::MCHTMR) } diff --git a/src/board/uart.rs b/src/board/uart.rs index 1d6e580..8685172 100644 --- a/src/board/uart.rs +++ b/src/board/uart.rs @@ -39,11 +39,26 @@ impl Uart { self.inner.lsr().read().thre() } + #[inline] + fn is_data_ready(&self) -> bool { + self.inner.lsr().read().dr() + } + #[inline] pub fn send_byte(&self, byte: u8) { while !self.is_tx_fifo_empty() {} self.inner.dll().write(|w| w.set_dll(byte)); } + + #[inline] + pub fn receive_byte(&self, byte: &mut u8) -> bool { + if self.is_data_ready() { + *byte = self.inner.rbr().read().rbr(); + true + } else { + false + } + } } impl Write for Uart { diff --git a/src/trap.rs b/src/trap.rs index 637380c..68db243 100644 --- a/src/trap.rs +++ b/src/trap.rs @@ -5,6 +5,7 @@ use riscv::register::{ }; use rustsbi::RustSBI; +use crate::board; use crate::extension::SBI; use crate::local_hsm; use crate::print; @@ -128,7 +129,10 @@ pub extern "C" fn fast_handler( ret.error = 0; ret.value = a1; } - legacy::LEGACY_CONSOLE_GETCHAR => unimplemented!(), + legacy::LEGACY_CONSOLE_GETCHAR => { + ret.error = board::getchar(); + ret.value = a1; + } _ => unimplemented!( "EID: {:#010x} FID: {:#010x} is not implemented!", a7,