From 26ab71043d97c1b06bdd252378b64171cb95b1a9 Mon Sep 17 00:00:00 2001 From: Christian Cunningham Date: Fri, 19 Aug 2022 21:22:18 -0700 Subject: Updated docs --- src/_arch/arm/asm.rs | 16 ++++++++++------ src/_arch/arm/cpu.rs | 12 ++++++++++-- src/_arch/arm/cpu/boot.rs | 16 ++++++++++++---- src/alloc.rs | 12 ++++++++---- src/console.rs | 37 +++++++++++++++++++++++++++++++++++++ src/cpu.rs | 9 ++++++--- src/cpu/boot.rs | 7 ++++++- src/panic_wait.rs | 4 +++- src/print.rs | 13 +++++++++---- src/sync.rs | 33 +++++++++++++++++++++++++++++++-- src/uart.rs | 47 +++++++++++++++++++++++++++++++++++++++++------ 11 files changed, 173 insertions(+), 33 deletions(-) (limited to 'src') 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 } diff --git a/src/cpu.rs b/src/cpu.rs index 9f003f8..26efd52 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -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 where T: ?Sized { + /// The internal data to safely share data: UnsafeCell, } +/// # Allow thread sharing unsafe impl Send for NullLock where T: ?Sized + Send {} +/// # Allow thread sharing unsafe impl Sync for NullLock where T: ?Sized + Send {} impl NullLock { + /// # Create a new instance of the lock pub const fn new(data: T) -> Self { Self { data: UnsafeCell::new(data), @@ -23,8 +47,13 @@ impl NullLock { } impl interface::Mutex for NullLock { + /// # 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, } 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(); -- cgit v1.2.1