diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/_arch/arm/asm.rs | 16 | ||||
| -rw-r--r-- | src/_arch/arm/cpu.rs | 12 | ||||
| -rw-r--r-- | src/_arch/arm/cpu/boot.rs | 16 | ||||
| -rw-r--r-- | src/alloc.rs | 12 | ||||
| -rw-r--r-- | src/console.rs | 37 | ||||
| -rw-r--r-- | src/cpu.rs | 9 | ||||
| -rw-r--r-- | src/cpu/boot.rs | 7 | ||||
| -rw-r--r-- | src/panic_wait.rs | 4 | ||||
| -rw-r--r-- | src/print.rs | 13 | ||||
| -rw-r--r-- | src/sync.rs | 33 | ||||
| -rw-r--r-- | src/uart.rs | 47 | 
11 files changed, 173 insertions, 33 deletions
| diff --git a/src/_arch/arm/asm.rs b/src/_arch/arm/asm.rs index c1af5b4..5d53aa0 100644 --- a/src/_arch/arm/asm.rs +++ b/src/_arch/arm/asm.rs @@ -1,6 +1,10 @@ -//! Wrapping ARMv7-A Instructions +//! # Wrapping ARMv7-A Instructions +//! +//! This provides bindings for assembly instructions +//! to be used in other rust functions without `unsafe` +//! markers everywhere. -/// WFE +/// # Wait for event  #[inline(always)]  pub fn wfe() {      unsafe { @@ -8,7 +12,7 @@ pub fn wfe() {      }  } -/// NOP +/// # No Operation  #[inline(always)]  pub fn nop() {      unsafe { @@ -16,7 +20,7 @@ pub fn nop() {      }  } -/// Store u32 to address +/// # Store u32 to memory address  #[inline]  pub fn store32(addr: u32, value: u32) {  	unsafe { @@ -24,7 +28,7 @@ pub fn store32(addr: u32, value: u32) {  	}  } -/// Read u32 value from address +/// # Read u32 from memory address  #[inline]  pub fn load32(addr: u32) -> u32 {  	unsafe { @@ -32,7 +36,7 @@ pub fn load32(addr: u32) -> u32 {  	}  } -/// Wait for n cycles +/// # Spin CPU for `n` cycles  #[inline]  pub fn spin_for_n_cycles(n: u32) {  	unsafe { diff --git a/src/_arch/arm/cpu.rs b/src/_arch/arm/cpu.rs index 1ca6fab..cd80151 100644 --- a/src/_arch/arm/cpu.rs +++ b/src/_arch/arm/cpu.rs @@ -1,8 +1,16 @@ -//! Architectural processor code. +//! # Architectural processor code. +//! +//! This module provides the assembly instructions and higher level constructions +//! for the rest of the kernel. +  mod asm; + +/// # Bare Assembly Instructions +/// +/// Re-export bare ASM bindings.  pub use asm::*; -/// Pause execution +/// # Halt until event  pub fn wait_forever() -> ! {      loop {          asm::wfe() diff --git a/src/_arch/arm/cpu/boot.rs b/src/_arch/arm/cpu/boot.rs index 9ea2330..b81a16a 100644 --- a/src/_arch/arm/cpu/boot.rs +++ b/src/_arch/arm/cpu/boot.rs @@ -1,11 +1,19 @@ -//! Architectural boot code -//!  # Boot code for ARM -//!  crate::cpu::boot::arch_boot +//! # Architectural boot code +//! +//! crate::cpu::boot::arch_boot +//! +//! ## Boot code for ARM +//! +//! Provides the initial handoff +//! function from Assembly to Rust.  use core::arch::global_asm;  global_asm!(include_str!("boot.s")); -/// The Rust entry of the `kernel` binary. +/// # Rust entry of the `kernel` binary. +/// +/// This function is unmangled so that the +/// ASM boot code can switch to Rust safely.  #[no_mangle]  pub unsafe fn _start_rust() -> ! {      crate::kernel_init() diff --git a/src/alloc.rs b/src/alloc.rs index 9b77f13..0c0df56 100644 --- a/src/alloc.rs +++ b/src/alloc.rs @@ -6,10 +6,14 @@  /// - Default: Default value  /// - Type: Data Type  macro_rules! init_queue { -    ($name:tt,$size:tt,$default:tt,$type:ty) => { -	#[link_section = ".data.alloc"] -        pub static $name: QueueAllocator<'static, $type, {$size+2}> = QueueAllocator::<$type, {$size+2}>{inner: NullLock::new([QueueItem{data: $default, next: None}; {$size+2}])}; -    } +	($name:tt,$size:tt,$default:tt,$type:ty) => { +		init_queue!{@gen [$name,$size,$default,$type,concat!("# ", stringify!($type), " Queue Allocator")]} +	}; +	(@gen [$name:tt,$size:tt,$default:tt,$type:ty,$doc:expr]) => { +		#[doc = $doc] +		#[link_section = ".data.alloc"] +		pub static $name: QueueAllocator<'static, $type, {$size+2}> = QueueAllocator::<$type, {$size+2}>{inner: NullLock::new([QueueItem{data: $default, next: None}; {$size+2}])}; +	};  }  use crate::sync::NullLock; diff --git a/src/console.rs b/src/console.rs index bcde05a..1a732a7 100644 --- a/src/console.rs +++ b/src/console.rs @@ -1,18 +1,55 @@ +//! # UART Console module +//!  +//! ## Encapsulates base trait for any console. +//! ## Wraps the UART console. + +/// # Interface module +/// +/// ## Provides trait for consoles.  pub mod interface {  	use core::fmt; +	/// # Write Trait +	/// +	/// Structure must provide ways to: +	///  - Write individual characters +	///  - Write formatted strings +	///  - Flush write queue  	pub trait Write { +		/// # Write Character +		/// +		/// Writes an individual character to a console  		fn write_char(&self, c: char); +		/// # Write Format +		/// +		/// Writes a formatted string to a console  		fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result; +		/// # Flush +		/// +		/// Flush console write queue  		fn flush(&self);  	} +	/// # Statistics Trait +	/// +	/// Structure must provide a way to: +	///  - Get how many characters have been written  	pub trait Statistics { +		/// # Get Written Chars +		/// +		/// Gets the statistic associated with how many +		/// characters have been written to a console.  		fn chars_written(&self) -> usize { 0 }  	} +	/// # All Trait +	/// +	/// Structure must provide both Write + Statistics  	pub trait All: Write + Statistics {}  } +/// # UART console +/// +/// Returns a borrow for the UART writer  pub fn console() -> &'static crate::uart::Uart {  	&crate::uart::UART_WRITER  } @@ -1,7 +1,10 @@ -//! Processor code. +//! # Processor code.  #[cfg(target_arch = "arm")]  #[path = "_arch/arm/cpu.rs"]  mod arch_cpu; -pub use arch_cpu::{nop,wait_forever,spin_for_n_cycles,load32,store32}; -  mod boot; + +/// # Low-level bindings +/// +/// Re-export low-level bindings +pub use arch_cpu::{nop,wait_forever,spin_for_n_cycles,load32,store32}; diff --git a/src/cpu/boot.rs b/src/cpu/boot.rs index 9ef25bd..43d8934 100644 --- a/src/cpu/boot.rs +++ b/src/cpu/boot.rs @@ -1,3 +1,8 @@ -//! Boot code +//! # Boot code +//! +//! ## Architectural Boot code. +//! +//! Provides the initial handoff function from Assembly to Rust. +  #[path = "../_arch/arm/cpu/boot.rs"]  mod arch_boot; diff --git a/src/panic_wait.rs b/src/panic_wait.rs index 33097d8..1136e54 100644 --- a/src/panic_wait.rs +++ b/src/panic_wait.rs @@ -1,8 +1,10 @@ +//! # Panic module +//!  //! A panic handler that infinitely waits  use core::panic::PanicInfo; -/// Panic handler +/// # Panic handler  #[panic_handler]  fn panic(_info: &PanicInfo) -> ! {      unimplemented!() diff --git a/src/print.rs b/src/print.rs index 932c655..88f39da 100644 --- a/src/print.rs +++ b/src/print.rs @@ -1,6 +1,7 @@ -//! Printing +//! # Printing to UART +//! +//! This module contains the macros to print formatted strings to UART.  use core::fmt; -  use crate::uart::UART_WRITER;  use crate::console::interface::Write; @@ -9,13 +10,17 @@ pub fn _print(args: fmt::Arguments) {  	UART_WRITER.write_fmt(args).unwrap();  } -/// Print without newline +/// # Print without newline +/// +/// Print formatted arguments without a newline  #[macro_export]  macro_rules! print {  	($($arg:tt)*) => ($crate::print::_print(format_args!($($arg)*)));  } -/// Print with newline +/// # Print with newline +/// +/// Print formatted arguments with a newline  #[macro_export]  macro_rules! println {  	() => ($crate::print!("\n")); diff --git a/src/sync.rs b/src/sync.rs index 2b7e1ff..cd626fa 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -1,20 +1,44 @@ +//! # Synchronization module +//! +//! Provides synchronization objects for thread-safe memory sharing. +use core::cell::UnsafeCell; + +/// # Synchronization interfaces +/// +/// Provides Synchronization traits.  pub mod interface { +	/// # Mutex Trait +	/// +	/// Basic Locking primitive to allow single-process access to data  	pub trait Mutex { +		/// # The data +		/// +		/// Each mutex protects some internal data from modification across +		/// processes when it is in use. This is important if the process +		/// is preempted while the function is using it.  		type Data; +		/// # Locking mechanism +		/// +		/// Locks the mutex to access the data in a closure. +		/// The data can be read and modified in this closure without worry +		/// of poisoning the data across processes.  		fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R;  	}  } -use core::cell::UnsafeCell; - +/// # Basic Lock Structure  pub struct NullLock<T> where T: ?Sized { +	/// The internal data to safely share  	data: UnsafeCell<T>,  } +/// # Allow thread sharing  unsafe impl<T> Send for NullLock<T> where T: ?Sized + Send {} +/// # Allow thread sharing  unsafe impl<T> Sync for NullLock<T> where T: ?Sized + Send {}  impl<T> NullLock<T> { +	/// # Create a new instance of the lock  	pub const fn new(data: T) -> Self {  		Self {  			data: UnsafeCell::new(data), @@ -23,8 +47,13 @@ impl<T> NullLock<T> {  }  impl<T> interface::Mutex for NullLock<T> { +	/// # Underlying data of the lock  	type Data = T; +	/// # Locking mechanism +	/// +	/// Locks the Mutex, and passes a mutable reference +	/// to the encapsulated data to a closure.  	fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut T) -> R) -> R {  		let data = unsafe { &mut *self.data.get() }; diff --git a/src/uart.rs b/src/uart.rs index ffd9204..0f66116 100644 --- a/src/uart.rs +++ b/src/uart.rs @@ -1,32 +1,58 @@ +//! # UART Console Definition  use crate::cpu::*; +use crate::sync::NullLock; +use core::fmt; +use crate::sync::interface::Mutex; +/// # Data Register  const UART0_DR: u32    = 0x3F201000; +/// # Flag Register  const UART0_FR: u32    = 0x3F201018; -const UART0_CR: u32    = 0x3F201030; -const UART0_ICR: u32   = 0x3F201044; -const UART0_IBRD: u32  = 0x3F201024; +/// # Fractional Baud Rate Register  const UART0_FBRD: u32  = 0x3F201028; +/// # Line Control Register  const UART0_LCRH: u32  = 0x3F20102C; +/// # Control Register +const UART0_CR: u32    = 0x3F201030; +/// # Interrupt Mask Set/ Clear Register  const UART0_IMSC: u32  = 0x3F201038; +/// # Interrupt Control Register +const UART0_ICR: u32   = 0x3F201044; +/// # Integer Baud Rate Register +const UART0_IBRD: u32  = 0x3F201024; + +/// GPIO Register  const GPPUD: u32       = 0x3F200094; +/// GPIO Clock 0 Register  const GPPUDCLK0: u32   = 0x3F200098; +/// # UART Inner Structure +/// +/// Keeps record of the console statistics.  struct UartInner {  	chars_written: usize,  } -use crate::sync::NullLock; +/// # UART Structure +/// +/// Wraps the UART writer in a sharable lock.  pub struct Uart {  	inner: NullLock<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) {  		store32(UART0_CR, 0);  		store32(GPPUD, 0); @@ -42,6 +68,7 @@ impl UartInner {  		store32(UART0_CR, (1<<0) | (1<<8) | (1<<9));  	} +	/// # Write `char` to UART  	fn write_char(&mut self, ch: char) {  		while load32(UART0_FR) & 0x20 != 0 {  			nop(); @@ -50,6 +77,7 @@ impl UartInner {  		self.chars_written += 1;  	} +	/// # Flush UART  	fn flush(&self) {  		while load32(UART0_FR) & 0x08 != 0 {  			nop(); @@ -57,8 +85,8 @@ impl UartInner {  	}  } -use core::fmt;  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); @@ -67,15 +95,16 @@ impl fmt::Write for UartInner {  	}  } -use crate::sync::interface::Mutex;  impl Uart { +	/// # Create sharable UART wrapper  	pub const fn new() -> Self {  		Self {  			inner: NullLock::new(UartInner::new()),  		}  	} +	/// # Call UART initialization  	pub fn init(&self) -> Result<(), &'static str> {  		self.inner.lock(|inner| inner.init());  		Ok(()) @@ -83,25 +112,31 @@ impl Uart {  }  impl super::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 super::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 super::console::interface::All for Uart {} +/// # Public reference to console.  pub static UART_WRITER: Uart = Uart::new(); | 
