use crate::cpu::*; const UART0_DR: u32 = 0x3F201000; const UART0_FR: u32 = 0x3F201018; const UART0_CR: u32 = 0x3F201030; const UART0_ICR: u32 = 0x3F201044; const UART0_IBRD: u32 = 0x3F201024; const UART0_FBRD: u32 = 0x3F201028; const UART0_LCRH: u32 = 0x3F20102C; const UART0_IMSC: u32 = 0x3F201038; const GPPUD: u32 = 0x3F200094; const GPPUDCLK0: u32 = 0x3F200098; struct UartInner { chars_written: usize, } use crate::sync::NullLock; pub struct Uart { inner: NullLock, } impl UartInner { pub const fn new() -> Self { Self { chars_written: 0, } } pub fn init(&mut self) { store32(UART0_CR, 0); store32(GPPUD, 0); spin_for_n_cycles(150); store32(GPPUDCLK0, (1 << 14) | (1 << 15)); spin_for_n_cycles(150); store32(GPPUDCLK0, 0); store32(UART0_ICR, 0x7FF); store32(UART0_IBRD, 9); store32(UART0_FBRD, 49); store32(UART0_LCRH, (1<<4) | (1<<5) | (1<<6)); store32(UART0_IMSC, (1<<1) | (1<<4) | (1<<5) | (1<<6) | (1<<7) | (1<<8) | (1<<9) | (1<<10)); store32(UART0_CR, (1<<0) | (1<<8) | (1<<9)); } fn write_char(&mut self, ch: char) { while load32(UART0_FR) & 0x20 != 0 { nop(); } store32(UART0_DR, ch as u32); self.chars_written += 1; } fn flush(&self) { while load32(UART0_FR) & 0x08 != 0 { nop(); } } } use core::fmt; impl fmt::Write for UartInner { fn write_str(&mut self, s: &str) -> fmt::Result { for c in s.chars() { self.write_char(c); } Ok(()) } } use crate::sync::interface::Mutex; impl Uart { pub const fn new() -> Self { Self { inner: NullLock::new(UartInner::new()), } } pub fn init(&self) -> Result<(), &'static str> { self.inner.lock(|inner| inner.init()); Ok(()) } } impl super::console::interface::Write for Uart { fn write_char(&self, c: char) { self.inner.lock(|inner| inner.write_char(c)); } fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result { self.inner.lock(|inner| fmt::Write::write_fmt(inner, args)) } fn flush(&self) { self.inner.lock(|inner| inner.flush()); } } impl super::console::interface::Statistics for Uart { fn chars_written(&self) -> usize { self.inner.lock(|inner| inner.chars_written) } } impl super::console::interface::All for Uart {} pub static UART_WRITER: Uart = Uart::new();