From a04cf2dbb8d2e890405fbf0a1022aaad3015b1e8 Mon Sep 17 00:00:00 2001 From: Christian Cunningham Date: Fri, 26 Aug 2022 17:25:34 -0700 Subject: Modularize --- src/bsp/drivers/uart/console.rs | 112 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 src/bsp/drivers/uart/console.rs (limited to 'src/bsp/drivers/uart/console.rs') diff --git a/src/bsp/drivers/uart/console.rs b/src/bsp/drivers/uart/console.rs new file mode 100644 index 0000000..e3ee2f2 --- /dev/null +++ b/src/bsp/drivers/uart/console.rs @@ -0,0 +1,112 @@ +//! # UART Console Definition +use super::*; +use crate::bsp::drivers::gpio::*; +use crate::cpu::*; +use crate::lib::sync::interface::Mutex; +use crate::lib::sync::SpinLock; +use core::fmt; + +/// # UART Inner Structure +/// +/// Keeps record of the console statistics. +struct UartInner { + chars_written: usize, +} + +/// # UART Structure +/// +/// Wraps the UART writer in a sharable lock. +pub struct Uart { + inner: SpinLock, +} + +impl UartInner { + /// # Clear statistics + /// + /// Create the writer with cleared statistics + pub const fn new() -> Self { + Self { chars_written: 0 } + } + + /// # Initialize the UART setup + /// + /// Set baud rate and timings + pub fn init(&mut self) { + UART::CR::off(); + GPPUDCLK0::init(); + UART::ICR::clear(); + UART::IBRD::set(9); + UART::FBRD::set(49); + UART::LCRH::enable8(); + UART::IMSC::mask(); + UART::CR::all_on(); + } + + /// # Write `char` to UART + fn write_char(&mut self, ch: char) { + while UART::FR::TXFF::is_set() { + nop(); + } + UART::DR::set(ch); + self.chars_written += 1; + } + + /// # Flush UART + fn flush(&self) { + while UART::FR::BUSY::is_set() { + nop(); + } + } +} + +impl fmt::Write for UartInner { + /// # Write string to UART console + fn write_str(&mut self, s: &str) -> fmt::Result { + for c in s.chars() { + self.write_char(c); + } + Ok(()) + } +} + +impl Uart { + /// # Create sharable UART wrapper + pub const fn new() -> Self { + Self { + inner: SpinLock::new(UartInner::new()), + } + } + + /// # Call UART initialization + pub fn init(&self) -> Result<(), &'static str> { + self.inner.lock(|inner| inner.init()); + Ok(()) + } +} + +impl crate::lib::console::interface::Write for Uart { + /// # Write `char` to UART + fn write_char(&self, c: char) { + self.inner.lock(|inner| inner.write_char(c)); + } + + /// # Write formatted string to UART + fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result { + self.inner.lock(|inner| fmt::Write::write_fmt(inner, args)) + } + + /// # Flush UART + fn flush(&self) { + self.inner.lock(|inner| inner.flush()); + } +} + +impl crate::lib::console::interface::Statistics for Uart { + /// # Get `char` written stats + fn chars_written(&self) -> usize { + self.inner.lock(|inner| inner.chars_written) + } +} + +/// # UART Writer + Stats +impl crate::lib::console::interface::All for Uart {} -- cgit v1.2.1