aboutsummaryrefslogtreecommitdiff
path: root/src/uart.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/uart.rs')
-rw-r--r--src/uart.rs108
1 files changed, 91 insertions, 17 deletions
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<UartInner>,
+}
+
+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();