aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/console.rs18
-rw-r--r--src/kernel.rs16
-rw-r--r--src/print.rs25
-rw-r--r--src/sync.rs33
-rw-r--r--src/uart.rs108
5 files changed, 176 insertions, 24 deletions
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<T> where T: ?Sized {
+ data: UnsafeCell<T>,
+}
+
+unsafe impl<T> Send for NullLock<T> where T: ?Sized + Send {}
+unsafe impl<T> Sync for NullLock<T> where T: ?Sized + Send {}
+
+impl<T> NullLock<T> {
+ pub const fn new(data: T) -> Self {
+ Self {
+ data: UnsafeCell::new(data),
+ }
+ }
+}
+
+impl<T> interface::Mutex for NullLock<T> {
+ 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<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();