hermit/
console.rs
1use core::task::Waker;
2use core::{fmt, mem};
3
4use heapless::Vec;
5use hermit_sync::{InterruptTicketMutex, Lazy};
6
7use crate::arch;
8
9const SERIAL_BUFFER_SIZE: usize = 256;
10
11pub(crate) struct Console {
12 pub inner: arch::kernel::Console,
13 buffer: Vec<u8, SERIAL_BUFFER_SIZE>,
14}
15
16impl Console {
17 fn new() -> Self {
18 Self {
19 inner: arch::kernel::Console::new(),
20 buffer: Vec::new(),
21 }
22 }
23
24 pub fn write(&mut self, buf: &[u8]) {
25 if SERIAL_BUFFER_SIZE - self.buffer.len() >= buf.len() {
26 self.buffer.extend_from_slice(buf).unwrap();
28 if buf.contains(&b'\n') {
29 self.inner.write(&self.buffer);
30 self.buffer.clear();
31 }
32 } else {
33 self.inner.write(&self.buffer);
34 self.buffer.clear();
35 if buf.len() >= SERIAL_BUFFER_SIZE {
36 self.inner.write(buf);
37 } else {
38 self.buffer.extend_from_slice(buf).unwrap();
40 if buf.contains(&b'\n') {
41 self.inner.write(&self.buffer);
42 self.buffer.clear();
43 }
44 }
45 }
46 }
47
48 pub fn read(&mut self) -> Option<u8> {
49 self.inner.read()
50 }
51
52 pub fn is_empty(&self) -> bool {
53 self.inner.is_empty()
54 }
55
56 pub fn register_waker(&mut self, waker: &Waker) {
57 self.inner.register_waker(waker);
58 }
59}
60
61impl fmt::Write for Console {
64 #[inline]
66 fn write_str(&mut self, s: &str) -> fmt::Result {
67 if !s.is_empty() {
68 self.write(s.as_bytes());
69 }
70
71 Ok(())
72 }
73}
74
75pub(crate) static CONSOLE: Lazy<InterruptTicketMutex<Console>> =
76 Lazy::new(|| InterruptTicketMutex::new(Console::new()));
77
78#[doc(hidden)]
79pub fn _print(args: fmt::Arguments<'_>) {
80 use fmt::Write;
81 CONSOLE.lock().write_fmt(args).unwrap();
82}
83
84#[doc(hidden)]
85pub fn _panic_print(args: fmt::Arguments<'_>) {
86 use fmt::Write;
87 let mut console = unsafe { CONSOLE.make_guard_unchecked() };
88 console.write_fmt(args).ok();
89 mem::forget(console);
90}
91
92#[cfg(all(test, not(target_os = "none")))]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn test_console() {
98 println!("HelloWorld");
99 }
100}