From 66ee8a34f3bcde31f9d5919f2e0e363ac11f4aca Mon Sep 17 00:00:00 2001 From: Christian Cunningham Date: Thu, 18 Aug 2022 20:37:09 -0700 Subject: Formatted printing to UART --- src/uart.rs | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 91 insertions(+), 17 deletions(-) (limited to 'src/uart.rs') diff --git a/src/uart.rs b/src/uart.rs index a26bb2f..ffd9204 100644 --- a/src/uart.rs +++ b/src/uart.rs @@ -1,4 +1,5 @@ use crate::cpu::*; + const UART0_DR: u32 = 0x3F201000; const UART0_FR: u32 = 0x3F201018; const UART0_CR: u32 = 0x3F201030; @@ -10,24 +11,97 @@ const UART0_IMSC: u32 = 0x3F201038; const GPPUD: u32 = 0x3F200094; const GPPUDCLK0: u32 = 0x3F200098; -pub fn uart_init() { - 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)); +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(()) + } } -pub fn write_char(ch: u8) { - while load32(UART0_FR) & 0x20 != 0 { - nop(); +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()); } - store32(UART0_DR, ch as u32); } + +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(); -- cgit v1.2.1