Improve UART by using nonblocking stdin
This commit is contained in:
31
Cargo.lock
generated
31
Cargo.lock
generated
@@ -8,6 +8,24 @@ version = "1.0.100"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
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]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.176"
|
version = "0.2.176"
|
||||||
@@ -23,10 +41,23 @@ dependencies = [
|
|||||||
"libc",
|
"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]]
|
[[package]]
|
||||||
name = "trve"
|
name = "trve"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"memmap2",
|
"memmap2",
|
||||||
|
"nix",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -6,3 +6,4 @@ edition = "2024"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.100"
|
anyhow = "1.0.100"
|
||||||
memmap2 = "0.9.8"
|
memmap2 = "0.9.8"
|
||||||
|
nix = { version = "0.30.1", features = ["fs"] }
|
||||||
|
|||||||
@@ -1,30 +1,35 @@
|
|||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::io::{Read, stdin};
|
use std::io;
|
||||||
|
use std::os::fd::AsFd;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use nix::fcntl::fcntl;
|
||||||
|
use nix::fcntl::{FcntlArg, OFlag};
|
||||||
use trve::consts::{Byte, DWord, HWord, Word};
|
use trve::consts::{Byte, DWord, HWord, Word};
|
||||||
use trve::mem::{MemAccessFault, MemDeviceInterface, PageNum};
|
use trve::mem::{MemAccessFault, MemDeviceInterface, PageNum};
|
||||||
|
|
||||||
/// byte 0: rx/tx
|
/// byte 0: rx/tx
|
||||||
/// byte 1: status (------rt, r=rxready, t=txready)/none
|
/// byte 1: status (------rt, r=rxready, t=txready)/none
|
||||||
pub struct BasicUart {
|
pub struct BasicUart {
|
||||||
buffers: Mutex<UartBuffers>,
|
rx_buf: Mutex<VecDeque<u8>>,
|
||||||
}
|
|
||||||
|
|
||||||
struct UartBuffers {
|
|
||||||
rx: VecDeque<u8>,
|
|
||||||
tx: VecDeque<u8>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BasicUart {
|
impl BasicUart {
|
||||||
pub fn new() -> Self {
|
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 {
|
BasicUart {
|
||||||
buffers: Mutex::new(UartBuffers {
|
rx_buf: Mutex::new(VecDeque::new()),
|
||||||
rx: VecDeque::new(),
|
|
||||||
tx: VecDeque::new(),
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,32 +49,23 @@ impl BasicUart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn write(&self, byte: u8) {
|
fn write(&self, byte: u8) {
|
||||||
let mut bufs = self.buffers.lock().unwrap();
|
print!("{}", byte as char);
|
||||||
bufs.tx.push_back(byte);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read(&self) -> u8 {
|
fn read(&self) -> u8 {
|
||||||
let mut bufs = self.buffers.lock().unwrap();
|
self.rx_buf.lock().unwrap().pop_front().unwrap_or(0)
|
||||||
bufs.rx.pop_front().unwrap_or(0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn can_read(&self) -> bool {
|
fn can_read(&self) -> bool {
|
||||||
let bufs = self.buffers.lock().unwrap();
|
!self.rx_buf.lock().unwrap().is_empty()
|
||||||
!bufs.rx.is_empty()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll(&self) {
|
pub fn poll(&self) {
|
||||||
let mut bufs = self.buffers.lock().unwrap();
|
let mut rx_buf = self.rx_buf.lock().unwrap();
|
||||||
|
|
||||||
while let Some(byte) = bufs.tx.pop_front() {
|
|
||||||
print!("{}", byte as char);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut buffer = [0u8; 1];
|
let mut buffer = [0u8; 1];
|
||||||
if let Ok(n) = stdin().read(&mut buffer) {
|
while let Ok(1) = nix::unistd::read(io::stdin().as_fd(), &mut buffer) {
|
||||||
if n > 0 {
|
rx_buf.push_back(buffer[0]);
|
||||||
bufs.rx.push_back(buffer[0]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user