Skip to content

Commit 736273e

Browse files
committed
feat: 支持 DBCN
- 一个简单的支持非阻塞读写的 16550 驱动 Signed-off-by: YdrMaster <[email protected]>
1 parent 7b3e0cb commit 736273e

File tree

6 files changed

+141
-70
lines changed

6 files changed

+141
-70
lines changed

Cargo.lock

Lines changed: 46 additions & 40 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rustsbi-qemu/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ rustsbi = { git = "https://github.com/rustsbi/rustsbi", rev = "91cfa36", feature
2323
sbi-spec = { version = "0.0.5", features = ["legacy"] }
2424
riscv = "0.10.1"
2525
spin = "0.9"
26-
uart_16550 = "0.2"
2726
rcore-console = "0.0.0"
2827
aclint = "0.0.0"
2928
sifive-test-device = "0.0.0"

rustsbi-qemu/src/dbcn.rs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![allow(unused)]
22

3-
use crate::UART;
3+
use crate::uart16550;
44
use core::ops::Range;
55
use rustsbi::{spec::binary::SbiRet, Console, Physical};
66
use spin::Once;
@@ -22,11 +22,12 @@ impl Console for DBCN {
2222
let start = bytes.phys_addr_lo();
2323
let end = start + bytes.num_bytes();
2424
if self.0.contains(&start) && self.0.contains(&(end - 1)) {
25-
let mut uart = UART.lock();
26-
let uart = unsafe { uart.assume_init_mut() };
25+
let uart = uart16550::UART.lock();
2726
for ptr in start..end {
28-
let c = ptr as *const u8;
29-
unsafe { uart.send(c.read_volatile()) };
27+
let c = unsafe { (ptr as *const u8).read_volatile() };
28+
if !uart.get().write(c) {
29+
return SbiRet::success(ptr - start);
30+
}
3031
}
3132
SbiRet::success(bytes.num_bytes())
3233
} else {
@@ -38,11 +39,13 @@ impl Console for DBCN {
3839
let start = bytes.phys_addr_lo();
3940
let end = start + bytes.num_bytes();
4041
if self.0.contains(&start) && self.0.contains(&(end - 1)) {
41-
let mut uart = UART.lock();
42-
let uart = unsafe { uart.assume_init_mut() };
42+
let uart = uart16550::UART.lock();
4343
for ptr in start..end {
44-
let c = ptr as *mut u8;
45-
unsafe { c.write_volatile(uart.receive()) };
44+
if let Some(c) = uart.get().read() {
45+
unsafe { (ptr as *mut u8).write_volatile(c) };
46+
} else {
47+
return SbiRet::success(ptr - start);
48+
}
4649
}
4750
SbiRet::success(bytes.num_bytes())
4851
} else {
@@ -52,9 +55,11 @@ impl Console for DBCN {
5255

5356
#[inline]
5457
fn write_byte(&self, byte: u8) -> SbiRet {
55-
let mut uart = UART.lock();
56-
let uart = unsafe { uart.assume_init_mut() };
57-
uart.send(byte);
58-
SbiRet::success(0)
58+
let uart = uart16550::UART.lock();
59+
loop {
60+
if uart.get().write(byte) {
61+
return SbiRet::success(0);
62+
}
63+
}
5964
}
6065
}

rustsbi-qemu/src/main.rs

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ mod qemu_test;
1111
mod riscv_spec;
1212
mod trap_stack;
1313
mod trap_vec;
14+
mod uart16550;
1415

1516
mod constants {
1617
/// 特权软件入口。
@@ -35,10 +36,9 @@ use device_tree::BoardInfo;
3536
use fast_trap::{FastContext, FastResult};
3637
use riscv_spec::*;
3738
use rustsbi::{spec::binary::SbiRet, RustSBI};
38-
use spin::{Mutex, Once};
39+
use spin::Once;
3940
use trap_stack::{local_hsm, local_remote_hsm, remote_hsm};
4041
use trap_vec::trap_vec;
41-
use uart_16550::MmioSerialPort;
4242

4343
/// 入口。
4444
///
@@ -83,7 +83,7 @@ extern "C" fn rust_main(hartid: usize, opaque: usize) {
8383
// 解析设备树
8484
let board_info = BOARD_INFO.call_once(|| device_tree::parse(opaque));
8585
// 初始化外设
86-
*UART.lock() = MaybeUninit::new(unsafe { MmioSerialPort::new(board_info.uart.start) });
86+
uart16550::init(board_info.uart.start);
8787
rcore_console::init_console(&Console);
8888
rcore_console::set_log_level(option_env!("LOG"));
8989
clint::init(board_info.clint.start);
@@ -120,7 +120,7 @@ extern "C" fn rust_main(hartid: usize, opaque: usize) {
120120
.with_timer(&clint::Clint)
121121
.with_hsm(Hsm)
122122
.with_reset(qemu_test::get())
123-
// .with_console(dbcn::get())
123+
.with_console(dbcn::get())
124124
.build(),
125125
);
126126
}
@@ -262,10 +262,14 @@ extern "C" fn fast_handler(
262262
ret.error = 0;
263263
ret.value = a1;
264264
}
265-
legacy::LEGACY_CONSOLE_GETCHAR => {
266-
ret.error = unsafe { UART.lock().assume_init_mut() }.receive() as _;
267-
ret.value = a1;
268-
}
265+
legacy::LEGACY_CONSOLE_GETCHAR => loop {
266+
let uart = uart16550::UART.lock();
267+
if let Some(c) = uart.get().read() {
268+
ret.error = c as _;
269+
ret.value = a1;
270+
break;
271+
}
272+
},
269273
_ => {}
270274
}
271275
}
@@ -316,20 +320,23 @@ struct Supervisor {
316320
}
317321

318322
struct Console;
319-
static UART: Mutex<MaybeUninit<MmioSerialPort>> = Mutex::new(MaybeUninit::uninit());
320323

321324
impl rcore_console::Console for Console {
322325
#[inline]
323326
fn put_char(&self, c: u8) {
324-
unsafe { UART.lock().assume_init_mut() }.send(c);
327+
let uart = uart16550::UART.lock();
328+
while !uart.get().write(c) {
329+
core::hint::spin_loop();
330+
}
325331
}
326332

327333
#[inline]
328334
fn put_str(&self, s: &str) {
329-
let mut uart = UART.lock();
330-
let uart = unsafe { uart.assume_init_mut() };
335+
let uart = uart16550::UART.lock();
331336
for c in s.bytes() {
332-
uart.send(c);
337+
while !uart.get().write(c) {
338+
core::hint::spin_loop();
339+
}
333340
}
334341
}
335342
}
@@ -343,8 +350,7 @@ type FixedRustSBI<'a> = RustSBI<
343350
Hsm,
344351
&'a qemu_test::QemuTest,
345352
Infallible,
346-
Infallible,
347-
// &'a dbcn::DBCN,
353+
&'a dbcn::DBCN,
348354
>;
349355

350356
struct Hsm;

0 commit comments

Comments
 (0)