From 24dcf5d5bd0beac3d4785a618c8f9c86840031d1 Mon Sep 17 00:00:00 2001 From: taitep Date: Sun, 21 Dec 2025 21:25:29 +0100 Subject: [PATCH] Improve UART by using nonblocking stdin --- Cargo.lock | 31 ++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/basic_uart.rs | 48 ++++++++++++++++++++++------------------------- 3 files changed, 54 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a77c839..8ff751b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,24 @@ version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "libc" version = "0.2.176" @@ -23,10 +41,23 @@ dependencies = [ "libc", ] +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "trve" version = "0.0.0" dependencies = [ "anyhow", "memmap2", + "nix", ] diff --git a/Cargo.toml b/Cargo.toml index 003b0b5..c4c3ece 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,3 +6,4 @@ edition = "2024" [dependencies] anyhow = "1.0.100" memmap2 = "0.9.8" +nix = { version = "0.30.1", features = ["fs"] } diff --git a/src/basic_uart.rs b/src/basic_uart.rs index 3c9e064..f178574 100644 --- a/src/basic_uart.rs +++ b/src/basic_uart.rs @@ -1,30 +1,35 @@ use std::collections::VecDeque; -use std::io::{Read, stdin}; +use std::io; +use std::os::fd::AsFd; use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; +use nix::fcntl::fcntl; +use nix::fcntl::{FcntlArg, OFlag}; use trve::consts::{Byte, DWord, HWord, Word}; use trve::mem::{MemAccessFault, MemDeviceInterface, PageNum}; /// byte 0: rx/tx /// byte 1: status (------rt, r=rxready, t=txready)/none pub struct BasicUart { - buffers: Mutex, -} - -struct UartBuffers { - rx: VecDeque, - tx: VecDeque, + rx_buf: Mutex>, } impl BasicUart { pub fn new() -> Self { + // Make sure stdin is nonblocking + let stdin = io::stdin(); + let fd = stdin.as_fd(); + let flags = fcntl(fd, FcntlArg::F_GETFL).unwrap(); + fcntl( + fd, + FcntlArg::F_SETFL(OFlag::from_bits_truncate(flags) | OFlag::O_NONBLOCK), + ) + .unwrap(); + BasicUart { - buffers: Mutex::new(UartBuffers { - rx: VecDeque::new(), - tx: VecDeque::new(), - }), + rx_buf: Mutex::new(VecDeque::new()), } } @@ -44,32 +49,23 @@ impl BasicUart { } fn write(&self, byte: u8) { - let mut bufs = self.buffers.lock().unwrap(); - bufs.tx.push_back(byte); + print!("{}", byte as char); } fn read(&self) -> u8 { - let mut bufs = self.buffers.lock().unwrap(); - bufs.rx.pop_front().unwrap_or(0) + self.rx_buf.lock().unwrap().pop_front().unwrap_or(0) } fn can_read(&self) -> bool { - let bufs = self.buffers.lock().unwrap(); - !bufs.rx.is_empty() + !self.rx_buf.lock().unwrap().is_empty() } pub fn poll(&self) { - let mut bufs = self.buffers.lock().unwrap(); - - while let Some(byte) = bufs.tx.pop_front() { - print!("{}", byte as char); - } + let mut rx_buf = self.rx_buf.lock().unwrap(); let mut buffer = [0u8; 1]; - if let Ok(n) = stdin().read(&mut buffer) { - if n > 0 { - bufs.rx.push_back(buffer[0]); - } + while let Ok(1) = nix::unistd::read(io::stdin().as_fd(), &mut buffer) { + rx_buf.push_back(buffer[0]); } } }