Files
trve/src/basic_uart.rs

98 lines
2.4 KiB
Rust

// Copyright (c) 2025 taitep
// SPDX-License-Identifier: MIT
//
// This file is part of TRVE (https://gitea.taitep.se/taitep/trve)
// See LICENSE file in the project root for full license text.
use std::collections::VecDeque;
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::{Addr, Byte};
use trve::exceptions::MemoryExceptionType;
use trve::mem::MemDeviceInterface;
/// byte 0: rx/tx
/// byte 1: status (------rt, r=rxready, t=txready)/none
pub struct BasicUart {
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 {
rx_buf: Mutex::new(VecDeque::new()),
}
}
pub fn spawn_poller(self, poll_interval: Duration) -> Arc<Self> {
let shared = Arc::new(self);
let uart_clone = shared.clone();
thread::spawn(move || {
loop {
uart_clone.poll();
thread::sleep(poll_interval);
}
});
shared
}
fn write(&self, byte: u8) {
print!("{}", byte as char);
}
fn read(&self) -> u8 {
self.rx_buf.lock().unwrap().pop_front().unwrap_or(0)
}
fn can_read(&self) -> bool {
!self.rx_buf.lock().unwrap().is_empty()
}
pub fn poll(&self) {
let mut rx_buf = self.rx_buf.lock().unwrap();
let mut buffer = [0u8; 1];
while let Ok(1) = nix::unistd::read(io::stdin().as_fd(), &mut buffer) {
rx_buf.push_back(buffer[0]);
}
}
}
impl MemDeviceInterface for BasicUart {
fn write_byte(&self, addr: Addr, value: Byte) -> Result<(), MemoryExceptionType> {
match addr {
0 => {
self.write(value);
Ok(())
}
_ => Err(MemoryExceptionType::AccessFault),
}
}
fn read_byte(&self, addr: Addr) -> Result<Byte, MemoryExceptionType> {
match addr {
0 => Ok(self.read()),
1 => Ok(1 | (self.can_read() as u8) << 1),
_ => Err(MemoryExceptionType::AccessFault),
}
}
}