aboutsummaryrefslogtreecommitdiff
path: root/src/bsp/drivers/uart/console.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bsp/drivers/uart/console.rs')
-rw-r--r--src/bsp/drivers/uart/console.rs112
1 files changed, 112 insertions, 0 deletions
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<UartInner>,
+}
+
+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 {}