Skip to main content

airbender_rt/
uart.rs

1//! UART writer compatible with the existing quasi-uart protocol.
2
3use crate::sys;
4use core::fmt;
5
6/// Minimal UART writer compatible with the existing quasi-uart protocol.
7#[derive(Default)]
8pub struct QuasiUart {
9    buffer: [u8; 4],
10    len: usize,
11}
12
13impl QuasiUart {
14    const HELLO_MARKER: u32 = u32::MAX;
15
16    #[inline(never)]
17    pub const fn new() -> Self {
18        Self {
19            buffer: [0u8; 4],
20            len: 0,
21        }
22    }
23
24    #[inline(never)]
25    pub fn write_entry_sequence(&mut self, message_len: usize) {
26        sys::write_word(Self::HELLO_MARKER);
27        sys::write_word(message_len.div_ceil(4) as u32 + 1);
28        sys::write_word(message_len as u32);
29    }
30
31    #[inline(never)]
32    pub fn write_byte(&mut self, byte: u8) {
33        self.buffer[self.len] = byte;
34        self.len += 1;
35        if self.len == 4 {
36            self.len = 0;
37            let word = u32::from_le_bytes(self.buffer);
38            sys::write_word(word);
39        }
40    }
41
42    pub fn flush(&mut self) {
43        if self.len == 0 {
44            self.buffer.fill(0);
45            return;
46        }
47        for i in self.len..4 {
48            self.buffer[i] = 0u8;
49        }
50        self.len = 0;
51        sys::write_word(u32::from_le_bytes(self.buffer));
52    }
53}
54
55impl fmt::Write for QuasiUart {
56    fn write_str(&mut self, s: &str) -> fmt::Result {
57        self.write_entry_sequence(s.len());
58        for c in s.bytes() {
59            self.write_byte(c);
60        }
61        self.flush();
62        Ok(())
63    }
64}