From bbfa20befe163c04d0a99278107f2608639318d3 Mon Sep 17 00:00:00 2001 From: taitep Date: Thu, 29 Jan 2026 19:07:43 +0100 Subject: Replace custom UART with a sifive uart subset --- src/devices/serial/fifo.rs | 113 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 src/devices/serial/fifo.rs (limited to 'src/devices/serial/fifo.rs') diff --git a/src/devices/serial/fifo.rs b/src/devices/serial/fifo.rs new file mode 100644 index 0000000..dbf4659 --- /dev/null +++ b/src/devices/serial/fifo.rs @@ -0,0 +1,113 @@ +// Copyright (c) 2026 taitep +// SPDX-License-Identifier: BSD-2-Clause +// +// 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::io::{self, Read, Write}; + +pub struct UartFifo { + buf: [u8; CAP], + head: usize, + tail: usize, + len: usize, +} + +impl UartFifo { + pub fn pop_single_byte(&mut self) -> Option { + if self.is_empty() { + return None; + } + + let value = self.buf[self.tail]; + self.advance_read(1); + Some(value) + } + + pub fn push_single_byte(&mut self, value: u8) -> bool { + if self.is_full() { + return false; + } + + self.buf[self.head] = value; + self.advance_write(1); + true + } + + pub fn is_empty(&self) -> bool { + self.len == 0 + } + + pub fn is_full(&self) -> bool { + self.len == CAP + } + + fn write_slice(&mut self) -> &mut [u8] { + if self.is_full() { + return &mut []; + } + + if self.head >= self.tail { + &mut self.buf[self.head..] + } else { + &mut self.buf[self.head..self.tail] + } + } + + fn advance_write(&mut self, n: usize) { + debug_assert!(n <= CAP - self.len); + self.head = (self.head + n) % CAP; + self.len += n; + } + + fn read_slice(&self) -> &[u8] { + if self.is_empty() { + return &[]; + } + + if self.tail < self.head { + &self.buf[self.tail..self.head] + } else { + &self.buf[self.tail..] + } + } + + fn advance_read(&mut self, n: usize) { + debug_assert!(n <= self.len); + self.tail = (self.tail + n) % CAP; + self.len -= n; + } + + pub fn read_from(&mut self, reader: &mut R) -> io::Result { + let slice = self.write_slice(); + if slice.is_empty() { + return Ok(0); + } + + let n = reader.read(slice)?; + self.advance_write(n); + Ok(n) + } + + pub fn write_to(&mut self, writer: &mut W) -> io::Result { + let slice = self.read_slice(); + if slice.is_empty() { + return Ok(0); + } + + let n = writer.write(slice)?; + self.advance_read(n); + Ok(n) + } +} + +impl Default for UartFifo { + fn default() -> Self { + UartFifo { + buf: [0; SIZE], + head: 0, + tail: 0, + len: 0, + } + } +} -- cgit v1.2.3