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/console.rs | 18 ++++++++++ src/kernel.rs | 16 +++++---- src/print.rs | 25 +++++++++++++ src/sync.rs | 33 ++++++++++++++++++ src/uart.rs | 108 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 5 files changed, 176 insertions(+), 24 deletions(-) create mode 100644 src/console.rs create mode 100644 src/print.rs create mode 100644 src/sync.rs diff --git a/src/console.rs b/src/console.rs new file mode 100644 index 0000000..bcde05a --- /dev/null +++ b/src/console.rs @@ -0,0 +1,18 @@ +pub mod interface { + use core::fmt; + pub trait Write { + fn write_char(&self, c: char); + fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result; + fn flush(&self); + } + + pub trait Statistics { + fn chars_written(&self) -> usize { 0 } + } + + pub trait All: Write + Statistics {} +} + +pub fn console() -> &'static crate::uart::Uart { + &crate::uart::UART_WRITER +} diff --git a/src/kernel.rs b/src/kernel.rs index a194b14..56f53c1 100644 --- a/src/kernel.rs +++ b/src/kernel.rs @@ -9,20 +9,22 @@ #![no_main] #![no_std] +mod console; mod cpu; mod panic_wait; +mod print; +mod sync; mod uart; -use crate::uart::*; +use crate::console::console; /// Initialization Code unsafe fn kernel_init() -> ! { - uart_init(); - - kernel_main() + console().init().unwrap(); + kernel_main() } +/// Post init fn kernel_main() -> ! { - write_char(b'a'); - loop { - } + println!("I should be able to print {} here!", 5); + loop { } } diff --git a/src/print.rs b/src/print.rs new file mode 100644 index 0000000..932c655 --- /dev/null +++ b/src/print.rs @@ -0,0 +1,25 @@ +//! Printing +use core::fmt; + +use crate::uart::UART_WRITER; +use crate::console::interface::Write; + +#[doc(hidden)] +pub fn _print(args: fmt::Arguments) { + UART_WRITER.write_fmt(args).unwrap(); +} + +/// Print without newline +#[macro_export] +macro_rules! print { + ($($arg:tt)*) => ($crate::print::_print(format_args!($($arg)*))); +} + +/// Print with newline +#[macro_export] +macro_rules! println { + () => ($crate::print!("\n")); + ($($arg:tt)*) => ({ + $crate::print::_print(format_args_nl!($($arg)*)); + }) +} diff --git a/src/sync.rs b/src/sync.rs new file mode 100644 index 0000000..2b7e1ff --- /dev/null +++ b/src/sync.rs @@ -0,0 +1,33 @@ +pub mod interface { + pub trait Mutex { + type Data; + fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R; + } +} + +use core::cell::UnsafeCell; + +pub struct NullLock where T: ?Sized { + data: UnsafeCell, +} + +unsafe impl Send for NullLock where T: ?Sized + Send {} +unsafe impl Sync for NullLock where T: ?Sized + Send {} + +impl NullLock { + pub const fn new(data: T) -> Self { + Self { + data: UnsafeCell::new(data), + } + } +} + +impl interface::Mutex for NullLock { + type Data = T; + + fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut T) -> R) -> R { + let data = unsafe { &mut *self.data.get() }; + + f(data) + } +} 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