You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
109 lines
3.3 KiB
Rust
109 lines
3.3 KiB
Rust
// SPDX-License-Identifier: MIT OR Apache-2.0
|
|
//
|
|
// Copyright (c) 2022 Andre Richter <andre.o.richter@gmail.com>
|
|
|
|
//! A console that buffers input during the init phase.
|
|
|
|
use super::interface;
|
|
use crate::{console, info, synchronization, synchronization::InitStateLock};
|
|
use core::fmt;
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Private Definitions
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
const BUF_SIZE: usize = 1024 * 64;
|
|
|
|
pub struct BufferConsoleInner {
|
|
buf: [char; BUF_SIZE],
|
|
write_ptr: usize,
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Public Definitions
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
pub struct BufferConsole {
|
|
inner: InitStateLock<BufferConsoleInner>,
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Global instances
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
pub static BUFFER_CONSOLE: BufferConsole = BufferConsole {
|
|
inner: InitStateLock::new(BufferConsoleInner {
|
|
// Use the null character, so this lands in .bss and does not waste space in the binary.
|
|
buf: ['\0'; BUF_SIZE],
|
|
write_ptr: 0,
|
|
}),
|
|
};
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Private Code
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
impl BufferConsoleInner {
|
|
fn write_char(&mut self, c: char) {
|
|
if self.write_ptr < (BUF_SIZE - 1) {
|
|
self.buf[self.write_ptr] = c;
|
|
self.write_ptr += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
impl fmt::Write for BufferConsoleInner {
|
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
|
for c in s.chars() {
|
|
self.write_char(c);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Public Code
|
|
//--------------------------------------------------------------------------------------------------
|
|
use synchronization::interface::ReadWriteEx;
|
|
|
|
impl BufferConsole {
|
|
/// Dump the buffer.
|
|
///
|
|
/// # Invariant
|
|
///
|
|
/// It is expected that this is only called when self != crate::console::console().
|
|
pub fn dump(&self) {
|
|
self.inner.read(|inner| {
|
|
console::console().write_array(&inner.buf[0..inner.write_ptr]);
|
|
|
|
if inner.write_ptr == (BUF_SIZE - 1) {
|
|
info!("Pre-UART buffer overflowed");
|
|
} else if inner.write_ptr > 0 {
|
|
info!("End of pre-UART buffer")
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
impl interface::Write for BufferConsole {
|
|
fn write_char(&self, c: char) {
|
|
self.inner.write(|inner| inner.write_char(c));
|
|
}
|
|
|
|
fn write_array(&self, _a: &[char]) {}
|
|
|
|
fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result {
|
|
self.inner.write(|inner| fmt::Write::write_fmt(inner, args))
|
|
}
|
|
|
|
fn flush(&self) {}
|
|
}
|
|
|
|
impl interface::Read for BufferConsole {
|
|
fn clear_rx(&self) {}
|
|
}
|
|
|
|
impl interface::Statistics for BufferConsole {}
|
|
impl interface::All for BufferConsole {}
|