Improve UART by using nonblocking stdin

This commit is contained in:
2025-12-21 21:25:29 +01:00
parent 209e44ae64
commit 24dcf5d5bd
3 changed files with 54 additions and 26 deletions

View File

@@ -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<UartBuffers>,
}
struct UartBuffers {
rx: VecDeque<u8>,
tx: VecDeque<u8>,
rx_buf: Mutex<VecDeque<u8>>,
}
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]);
}
}
}