diff --git a/bootloader/Cargo.lock b/bootloader/Cargo.lock index e2fe90a..3e48379 100644 --- a/bootloader/Cargo.lock +++ b/bootloader/Cargo.lock @@ -15,6 +15,7 @@ dependencies = [ [[package]] name = "bcm2837" version = "0.1.0" +source = "git+https://github.com/equation314/bcm2837#446f0ea04deb5216ba5e08f10af36e5c1729e6fd" dependencies = [ "volatile 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -98,7 +99,7 @@ name = "rcore-bootloader" version = "0.1.0" dependencies = [ "aarch64 2.2.2 (git+https://github.com/equation314/aarch64)", - "bcm2837 0.1.0", + "bcm2837 0.1.0 (git+https://github.com/equation314/bcm2837)", "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", "fixedvec 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -205,6 +206,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum aarch64 2.2.2 (git+https://github.com/equation314/aarch64)" = "" +"checksum bcm2837 0.1.0 (git+https://github.com/equation314/bcm2837)" = "" "checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92" diff --git a/bootloader/Cargo.toml b/bootloader/Cargo.toml index 70f7550..09c8b6d 100644 --- a/bootloader/Cargo.toml +++ b/bootloader/Cargo.toml @@ -10,7 +10,7 @@ fixedvec = "0.2.3" [target.'cfg(target_arch = "aarch64")'.dependencies] aarch64 = { git = "https://github.com/equation314/aarch64" } -bcm2837 = { path = "../crate/bcm2837" } +bcm2837 = { git = "https://github.com/equation314/bcm2837" } [build-dependencies] cc = "1.0" diff --git a/crate/bcm2837/Cargo.toml b/crate/bcm2837/Cargo.toml deleted file mode 100644 index 18cb598..0000000 --- a/crate/bcm2837/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "bcm2837" -version = "0.1.0" -authors = ["equation314 "] -edition = "2018" - -[features] -zero_kernel_offset = [] -use_generic_timer = ["aarch64"] - -[dependencies] -volatile = "0.2.4" -aarch64= { git = "https://github.com/equation314/aarch64", optional = true } diff --git a/crate/bcm2837/src/atags/atag.rs b/crate/bcm2837/src/atags/atag.rs deleted file mode 100644 index 30315ea..0000000 --- a/crate/bcm2837/src/atags/atag.rs +++ /dev/null @@ -1,65 +0,0 @@ -use super::raw; -use core::slice; -use core::str; - -/// An ATAG. -#[derive(Debug, Copy, Clone)] -pub enum Atag { - Core(raw::Core), - Mem(raw::Mem), - Cmd(&'static str), - Unknown(u32), - None, -} - -impl Atag { - /// Returns `Some` if this is a `Core` ATAG. Otherwise returns `None`. - pub fn core(self) -> Option { - match self { - Atag::Core(x) => Some(x), - _ => None, - } - } - - /// Returns `Some` if this is a `Mem` ATAG. Otherwise returns `None`. - pub fn mem(self) -> Option { - match self { - Atag::Mem(x) => Some(x), - _ => None, - } - } - - /// Returns `Some` with the command line string if this is a `Cmd` ATAG. - /// Otherwise returns `None`. - pub fn cmd(self) -> Option<&'static str> { - match self { - Atag::Cmd(x) => Some(x), - _ => None, - } - } -} - -// Convert between raw::* types and Atag wrapper. -impl<'a> From<&'a raw::Atag> for Atag { - fn from(atag: &raw::Atag) -> Atag { - unsafe { - match (atag.tag, &atag.kind) { - (raw::Atag::CORE, &raw::Kind { core }) => Atag::Core(core), - (raw::Atag::MEM, &raw::Kind { mem }) => Atag::Mem(mem), - (raw::Atag::CMDLINE, &raw::Kind { ref cmd }) => { - let cmd_ptr: *const u8 = &cmd.cmd as *const u8; - let mut len: usize = 0; - - while *cmd_ptr.add(len) != 0 { - len += 1; - } - - let cmd_slice = slice::from_raw_parts(cmd_ptr, len); - Atag::Cmd(str::from_utf8_unchecked(cmd_slice)) - } - (raw::Atag::NONE, _) => Atag::None, - (id, _) => Atag::Unknown(id), - } - } - } -} diff --git a/crate/bcm2837/src/atags/mod.rs b/crate/bcm2837/src/atags/mod.rs deleted file mode 100644 index 8787fcc..0000000 --- a/crate/bcm2837/src/atags/mod.rs +++ /dev/null @@ -1,41 +0,0 @@ -mod atag; -mod raw; - -use super::consts::KERNEL_OFFSET; -pub use self::atag::*; -pub use self::raw::{Cmd, Core, Mem}; - -/// The address at which the firmware loads the ATAGS. -const ATAG_BASE: usize = KERNEL_OFFSET + 0x100; - -/// An iterator over the ATAGS on this system. -pub struct Atags { - ptr: &'static raw::Atag, -} - -impl Atags { - /// Returns an instance of `Atags`, an iterator over ATAGS on this system. - pub fn get() -> Atags { - Atags { - ptr: unsafe { &*(ATAG_BASE as *const raw::Atag) }, - } - } -} - -impl Iterator for Atags { - type Item = Atag; - - /// Iterate over Atags. Returns a valid Atag until the iterator hits the - /// Atag::None. - fn next(&mut self) -> Option { - let cur = self.ptr; - match cur.next() { - Some(next) => { - let result = Some(Atag::from(cur)); - self.ptr = next; - result - } - None => None, - } - } -} diff --git a/crate/bcm2837/src/atags/raw.rs b/crate/bcm2837/src/atags/raw.rs deleted file mode 100644 index 22bed83..0000000 --- a/crate/bcm2837/src/atags/raw.rs +++ /dev/null @@ -1,65 +0,0 @@ -/// A raw `ATAG` as laid out in memory. -#[repr(C)] -pub struct Atag { - pub dwords: u32, - pub tag: u32, - pub kind: Kind, -} - -impl Atag { - pub const NONE: u32 = 0x00000000; - pub const CORE: u32 = 0x54410001; - pub const MEM: u32 = 0x54410002; - pub const VIDEOTEXT: u32 = 0x54410003; - pub const RAMDISK: u32 = 0x54410004; - pub const INITRD2: u32 = 0x54420005; - pub const SERIAL: u32 = 0x54410006; - pub const REVISION: u32 = 0x54410007; - pub const VIDEOLFB: u32 = 0x54410008; - pub const CMDLINE: u32 = 0x54410009; - - /// Returns the ATAG following `self`, if there is one. - pub fn next(&self) -> Option<&Atag> { - if self.tag == Atag::NONE { - None - } else { - let current = self as *const Atag as *const u32; - let next: &Atag = unsafe { &*(current.add(self.dwords as usize) as *const Atag) }; - - Some(next) - } - } -} - -/// The possible variant of an ATAG. -#[repr(C)] -pub union Kind { - pub core: Core, - pub mem: Mem, - pub cmd: Cmd, -} - -/// A `CORE` ATAG. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Core { - pub flags: u32, - pub page_size: u32, - pub root_dev: u32, -} - -/// A `MEM` ATAG. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Mem { - pub size: u32, - pub start: u32, -} - -/// A `CMDLINE` ATAG. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Cmd { - /// The first byte of the command line string. - pub cmd: u8, -} diff --git a/crate/bcm2837/src/consts.rs b/crate/bcm2837/src/consts.rs deleted file mode 100644 index 92ec433..0000000 --- a/crate/bcm2837/src/consts.rs +++ /dev/null @@ -1,7 +0,0 @@ -#[cfg(feature = "zero_kernel_offset")] -pub const KERNEL_OFFSET: usize = 0; -#[cfg(not(feature = "zero_kernel_offset"))] -pub const KERNEL_OFFSET: usize = 0xFFFF_0000_0000_0000; - -pub const RAW_IO_BASE: usize = 0x3F00_0000; -pub const IO_BASE: usize = KERNEL_OFFSET + RAW_IO_BASE; diff --git a/crate/bcm2837/src/gpio.rs b/crate/bcm2837/src/gpio.rs deleted file mode 100644 index 2bcf901..0000000 --- a/crate/bcm2837/src/gpio.rs +++ /dev/null @@ -1,163 +0,0 @@ -use crate::consts::IO_BASE; -use crate::timer::delay; -use core::marker::PhantomData; -use volatile::{ReadOnly, Volatile, WriteOnly}; - -/// The base address of the `GPIO` registers. -const GPIO_BASE: usize = IO_BASE + 0x200000; - -/// An alternative GPIO function. (ref: peripherals 6.1, page 92) -#[repr(u8)] -pub enum Function { - Input = 0b000, - Output = 0b001, - Alt0 = 0b100, - Alt1 = 0b101, - Alt2 = 0b110, - Alt3 = 0b111, - Alt4 = 0b011, - Alt5 = 0b010, -} - -/// GPIO registers starting from `GPIO_BASE` (ref: peripherals 6.1, page 90) -#[repr(C)] -#[allow(non_snake_case)] -struct Registers { - FSEL: [Volatile; 6], - __reserved0: u32, - SET: [WriteOnly; 2], - __reserved1: u32, - CLR: [WriteOnly; 2], - __reserved2: u32, - LEV: [ReadOnly; 2], - __reserved3: u32, - EDS: [Volatile; 2], - __reserved4: u32, - REN: [Volatile; 2], - __reserved5: u32, - FEN: [Volatile; 2], - __reserved6: u32, - HEN: [Volatile; 2], - __reserved7: u32, - LEN: [Volatile; 2], - __reserved8: u32, - AREN: [Volatile; 2], - __reserved9: u32, - AFEN: [Volatile; 2], - __reserved10: u32, - PUD: Volatile, - PUDCLK: [Volatile; 2], -} - -/// Possible states for a GPIO pin. -pub enum Uninitialized {} -pub enum Input {} -pub enum Output {} -pub enum Alt {} - -/// A GPIO pin in state `State`. -/// -/// The `State` generic always corresponds to an uninstantiatable type that is -/// use solely to mark and track the state of a given GPIO pin. A `Gpio` -/// structure starts in the `Uninitialized` state and must be transitions into -/// one of `Input`, `Output`, or `Alt` via the `into_input`, `into_output`, and -/// `into_alt` methods before it can be used. -pub struct Gpio { - pin: u8, - registers: &'static mut Registers, - _state: PhantomData, -} - -impl Gpio { - /// Transitions `self` to state `S`, consuming `self` and returning a new - /// `Gpio` instance in state `S`. This method should _never_ be exposed to - /// the public! - #[inline(always)] - fn transition(self) -> Gpio { - Gpio { - pin: self.pin, - registers: self.registers, - _state: PhantomData, - } - } - - /// Set the Gpio pull-up/pull-down state for values in `pin_value` - /// (ref: peripherals 6.1, page 101) - pub fn set_gpio_pd(&mut self, pud_value: u8) { - let index = if self.pin >= 32 { 1 } else { 0 }; - - self.registers.PUD.write(pud_value as u32); - delay(150); - self.registers.PUDCLK[index as usize].write((1 << self.pin) as u32); - delay(150); - self.registers.PUD.write(0); - self.registers.PUDCLK[index as usize].write(0); - } -} - -impl Gpio { - /// Returns a new `GPIO` structure for pin number `pin`. - /// - /// # Panics - /// - /// Panics if `pin` > `53`. - pub fn new(pin: u8) -> Gpio { - if pin > 53 { - panic!("Gpio::new(): pin {} exceeds maximum of 53", pin); - } - - Gpio { - registers: unsafe { &mut *(GPIO_BASE as *mut Registers) }, - pin: pin, - _state: PhantomData, - } - } - - /// Enables the alternative function `function` for `self`. Consumes self - /// and returns a `Gpio` structure in the `Alt` state. - pub fn into_alt(self, function: Function) -> Gpio { - let select = (self.pin / 10) as usize; - let offset = 3 * (self.pin % 10) as usize; - self.registers.FSEL[select].update(|value| { - *value &= !(0b111 << offset); - *value |= (function as u32) << offset; - }); - self.transition() - } - - /// Sets this pin to be an _output_ pin. Consumes self and returns a `Gpio` - /// structure in the `Output` state. - pub fn into_output(self) -> Gpio { - self.into_alt(Function::Output).transition() - } - - /// Sets this pin to be an _input_ pin. Consumes self and returns a `Gpio` - /// structure in the `Input` state. - pub fn into_input(self) -> Gpio { - self.into_alt(Function::Input).transition() - } -} - -impl Gpio { - /// Sets (turns on) the pin. - pub fn set(&mut self) { - let index = if self.pin >= 32 { 1 } else { 0 }; - self.registers.SET[index as usize].write(1 << (self.pin - index * 32)); - } - - /// Clears (turns off) the pin. - pub fn clear(&mut self) { - let index = if self.pin >= 32 { 1 } else { 0 }; - self.registers.CLR[index as usize].write(1 << (self.pin - index * 32)); - } -} - -impl Gpio { - /// Reads the pin's value. Returns `true` if the level is high and `false` - /// if the level is low. - pub fn level(&mut self) -> bool { - let index = if self.pin >= 32 { 1 } else { 0 }; - let high = 1 << (self.pin - index * 32); - (self.registers.LEV[index as usize].read() & high) == high - } -} diff --git a/crate/bcm2837/src/interrupt.rs b/crate/bcm2837/src/interrupt.rs deleted file mode 100644 index d3caba6..0000000 --- a/crate/bcm2837/src/interrupt.rs +++ /dev/null @@ -1,88 +0,0 @@ -use crate::consts::IO_BASE; -use volatile::{ReadOnly, Volatile}; - -const INT_BASE: usize = IO_BASE + 0xB000 + 0x200; - -/// Allowed interrupts (ref: peripherals 7.5, page 113) -#[repr(u8)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum Interrupt { - Timer1 = 1, - Timer3 = 3, - Usb = 9, - Aux = 29, - Gpio0 = 49, - Gpio1 = 50, - Gpio2 = 51, - Gpio3 = 52, - Uart = 57, -} - -/// Interrupts registers starting from `INT_BASE` (ref: peripherals 7.5, page 112) -#[repr(C)] -#[allow(non_snake_case)] -struct Registers { - IRQBasicPending: ReadOnly, - IRQPending: [ReadOnly; 2], - FIQControl: Volatile, - EnableIRQ: [Volatile; 2], - EnableBasicIRQ: Volatile, - DisableIRQ: [Volatile; 2], - DisableBasicIRQ: Volatile, -} - -/// Pending interrupts -pub struct PendingInterrupts(u64); - -impl Iterator for PendingInterrupts { - type Item = usize; - - #[inline] - fn next(&mut self) -> Option { - let int = self.0.trailing_zeros(); - if int < 64 { - self.0 &= !(1 << int); - Some(int as usize) - } else { - None - } - } -} - -/// An interrupt controller. Used to enable and disable interrupts as well as to -/// check if an interrupt is pending. -pub struct Controller { - registers: &'static mut Registers, -} - -impl Controller { - /// Returns a new handle to the interrupt controller. - #[inline] - pub fn new() -> Controller { - Controller { - registers: unsafe { &mut *(INT_BASE as *mut Registers) }, - } - } - - /// Enables the interrupt `int`. - pub fn enable(&mut self, int: Interrupt) { - self.registers.EnableIRQ[int as usize / 32].write(1 << (int as usize) % 32); - } - - /// Disables the interrupt `int`. - pub fn disable(&mut self, int: Interrupt) { - self.registers.DisableIRQ[int as usize / 32].write(1 << (int as usize) % 32); - } - - /// Returns `true` if `int` is pending. Otherwise, returns `false`. - pub fn is_pending(&self, int: Interrupt) -> bool { - self.registers.IRQPending[int as usize / 32].read() & (1 << (int as usize) % 32) != 0 - } - - /// Return all pending interrupts. - pub fn pending_interrupts(&self) -> PendingInterrupts { - let irq1 = self.registers.IRQPending[0].read() as u64; - let irq2 = self.registers.IRQPending[1].read() as u64; - PendingInterrupts((irq2 << 32) | irq1) - } -} diff --git a/crate/bcm2837/src/lib.rs b/crate/bcm2837/src/lib.rs deleted file mode 100644 index ba9cc2a..0000000 --- a/crate/bcm2837/src/lib.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![no_std] -#![feature(asm)] - -extern crate volatile; - -pub mod atags; -pub mod consts; -pub mod gpio; -pub mod interrupt; -pub mod mailbox; -pub mod mini_uart; -pub mod timer; diff --git a/crate/bcm2837/src/mailbox.rs b/crate/bcm2837/src/mailbox.rs deleted file mode 100644 index e20c0ff..0000000 --- a/crate/bcm2837/src/mailbox.rs +++ /dev/null @@ -1,80 +0,0 @@ -use crate::consts::IO_BASE; -use volatile::{ReadOnly, Volatile, WriteOnly}; - -/// The base address for the `MU` registers. -const MAILBOX_BASE: usize = IO_BASE + 0xB000 + 0x880; - -/// Available mailbox channels -/// -/// (ref: https://github.com/raspberrypi/firmware/wiki/Mailboxes) -#[repr(u8)] -#[derive(Copy, Clone, Debug)] -pub enum MailboxChannel { - Framebuffer = 1, - Property = 8, -} - -/// Read from mailbox status register (MAILx_STA). -#[repr(u32)] -enum MailboxStatus { - MailboxEmpty = 1 << 30, - MailboxFull = 1 << 31, -} - -/// Mailbox registers. We basically only support mailbox 0 & 1. We -/// deliver to the VC in mailbox 1, it delivers to us in mailbox 0. See -/// BCM2835-ARM-Peripherals.pdf section 1.3 for an explanation about -/// the placement of memory barriers. -/// -/// (ref: https://github.com/raspberrypi/firmware/wiki/Mailboxes) -#[repr(C)] -#[allow(non_snake_case)] -struct Registers { - MAIL0_RD: ReadOnly, // 0x00 - __reserved0: [u32; 3], - MAIL0_POL: ReadOnly, // 0x10 - MAIL0_SND: ReadOnly, // 0x14 - MAIL0_STA: ReadOnly, // 0x18 - MAIL0_CNF: Volatile, // 0x1c - - MAIL1_WRT: WriteOnly, // 0x20 - __reserved1: [u32; 3], - _MAIL1_POL: ReadOnly, // 0x30 - _MAIL1_SND: ReadOnly, // 0x34 - MAIL1_STA: ReadOnly, // 0x38 - _MAIL1_CNF: Volatile, // 0x3c -} - -/// The Raspberry Pi's mailbox. -/// -/// (ref: https://github.com/raspberrypi/firmware/wiki/Accessing-mailboxes) -pub struct Mailbox { - registers: &'static mut Registers, -} - -impl Mailbox { - /// Returns a new instance of `Mailbox`. - #[inline] - pub fn new() -> Mailbox { - Mailbox { - registers: unsafe { &mut *(MAILBOX_BASE as *mut Registers) }, - } - } - - /// Read from the requested channel of mailbox 0. - pub fn read(&self, channel: MailboxChannel) -> u32 { - loop { - while self.registers.MAIL0_STA.read() & (MailboxStatus::MailboxEmpty as u32) != 0 {} - let data = self.registers.MAIL0_RD.read(); - if data & 0xF == channel as u32 { - return data & !0xF; - } - } - } - - /// Write to the requested channel of mailbox 1. - pub fn write(&mut self, channel: MailboxChannel, data: u32) { - while self.registers.MAIL1_STA.read() & (MailboxStatus::MailboxFull as u32) != 0 {} - self.registers.MAIL1_WRT.write((data & !0xF) | (channel as u32)); - } -} diff --git a/crate/bcm2837/src/mini_uart.rs b/crate/bcm2837/src/mini_uart.rs deleted file mode 100644 index 9606cf8..0000000 --- a/crate/bcm2837/src/mini_uart.rs +++ /dev/null @@ -1,133 +0,0 @@ -use crate::consts::IO_BASE; -use crate::gpio::{Function, Gpio}; -use volatile::{ReadOnly, Volatile}; - -/// The `AUXENB` register from page 9 of the BCM2837 documentation. -const AUX_ENABLES: *mut Volatile = (IO_BASE + 0x215004) as *mut Volatile; - -/// The base address for the `MU` registers. -const MU_REG_BASE: usize = IO_BASE + 0x215040; - -/// Enum representing bit fields of the `AUX_MU_IIR_REG` register. -#[repr(u8)] -pub enum MiniUartInterruptId { - Transmit = 0b010, - Recive = 0b100, -} - -/// Enum representing bit fields of the `AUX_MU_LSR_REG` register. -#[repr(u8)] -enum LsrStatus { - DataReady = 1, - TxAvailable = 1 << 5, -} - -/// MU registers starting from `MU_REG_BASE` (ref: peripherals 2.1, page 8) -#[repr(C)] -#[allow(non_snake_case)] -struct Registers { - AUX_MU_IO_REG: Volatile, - __r0: [u8; 3], - AUX_MU_IER_REG: Volatile, - __r1: [u8; 3], - AUX_MU_IIR_REG: Volatile, - __r2: [u8; 3], - AUX_MU_LCR_REG: Volatile, - __r3: [u8; 3], - AUX_MU_MCR_REG: Volatile, - __r4: [u8; 3], - AUX_MU_LSR_REG: ReadOnly, - __r5: [u8; 3], - AUX_MU_MSR_REG: ReadOnly, - __r6: [u8; 3], - AUX_MU_SCRATCH: Volatile, - __r7: [u8; 3], - AUX_MU_CNTL_REG: Volatile, - __r8: [u8; 3], - AUX_MU_STAT_REG: ReadOnly, - AUX_MU_BAUD_REG: Volatile, -} - -/// The Raspberry Pi's "mini UART". -pub struct MiniUart { - registers: &'static mut Registers, - timeout: Option, -} - -impl MiniUart { - /// Returns a new instance of `MiniUart`. - #[inline] - pub fn new() -> MiniUart { - let registers = unsafe { &mut *(MU_REG_BASE as *mut Registers) }; - - MiniUart { - registers: registers, - timeout: None, - } - } - - /// Initializes the mini UART by enabling it as an auxiliary peripheral, - /// setting the data size to 8 bits, setting the BAUD rate to ~115200 (baud - /// divider of 270), setting GPIO pins 14 and 15 to alternative function 5 - /// (TXD1/RDXD1), and finally enabling the UART transmitter and receiver. - /// - /// By default, reads will never time out. To set a read timeout, use - /// `set_read_timeout()`. - pub fn init(&mut self) { - // Enable the mini UART as an auxiliary device. - unsafe { (*AUX_ENABLES).write(1) } - - Gpio::new(14).into_alt(Function::Alt5).set_gpio_pd(0); - Gpio::new(15).into_alt(Function::Alt5).set_gpio_pd(0); - - self.registers.AUX_MU_CNTL_REG.write(0); // Disable auto flow control and disable receiver and transmitter (for now) - self.registers.AUX_MU_IER_REG.write(1); // Enable receive interrupts and disable transmit interrupts - self.registers.AUX_MU_LCR_REG.write(3); // Enable 8 bit mode - self.registers.AUX_MU_MCR_REG.write(0); // Set RTS line to be always high - self.registers.AUX_MU_BAUD_REG.write(270); // Set baud rate to 115200 - - self.registers.AUX_MU_CNTL_REG.write(3); // Finally, enable transmitter and receiver - } - - /// Set the read timeout to `milliseconds` milliseconds. - pub fn set_read_timeout(&mut self, milliseconds: u32) { - self.timeout = Some(milliseconds) - } - - /// Write the byte `byte`. This method blocks until there is space available - /// in the output FIFO. - pub fn write_byte(&mut self, byte: u8) { - while self.registers.AUX_MU_LSR_REG.read() & (LsrStatus::TxAvailable as u8) == 0 {} - self.registers.AUX_MU_IO_REG.write(byte); - } - - /// Returns `true` if there is at least one byte ready to be read. If this - /// method returns `true`, a subsequent call to `read_byte` is guaranteed to - /// return immediately. This method does not block. - pub fn has_byte(&self) -> bool { - self.registers.AUX_MU_LSR_REG.read() & (LsrStatus::DataReady as u8) != 0 - } - - /// Blocks until there is a byte ready to read. If a read timeout is set, - /// this method blocks for at most that amount of time. Otherwise, this - /// method blocks indefinitely until there is a byte to read. - /// - /// Returns `Ok(())` if a byte is ready to read. Returns `Err(())` if the - /// timeout expired while waiting for a byte to be ready. If this method - /// returns `Ok(())`, a subsequent call to `read_byte` is guaranteed to - /// return immediately. - pub fn wait_for_byte(&self) -> Result<(), ()> { - unimplemented!() - } - - /// Reads a byte. Blocks indefinitely until a byte is ready to be read. - pub fn read_byte(&self) -> u8 { - while !self.has_byte() {} - self.registers.AUX_MU_IO_REG.read() - } - - // Read `AUX_MU_IIR_REG` and determine if the interrupt `id` is pending. - pub fn interrupt_is_pending(&self, id: MiniUartInterruptId) -> bool { - self.registers.AUX_MU_IIR_REG.read() & 0b110 == id as u8 - } -} diff --git a/crate/bcm2837/src/timer/generic_timer.rs b/crate/bcm2837/src/timer/generic_timer.rs deleted file mode 100644 index 9128dce..0000000 --- a/crate/bcm2837/src/timer/generic_timer.rs +++ /dev/null @@ -1,77 +0,0 @@ -extern crate aarch64; - -use super::BasicTimer; -use crate::consts::KERNEL_OFFSET; -use aarch64::regs::*; -use volatile::*; - -/// The base address for the ARM generic timer, IRQs, mailboxes -const GEN_TIMER_REG_BASE: usize = KERNEL_OFFSET + 0x4000_0000; - -/// Core interrupt sources (ref: QA7 4.10, page 16) -#[repr(u8)] -#[allow(dead_code)] -#[allow(non_snake_case)] -#[derive(Copy, Clone, PartialEq, Debug)] -enum CoreInterrupt { - CNTPSIRQ = 0, - CNTPNSIRQ = 1, - CNTHPIRQ = 2, - CNTVIRQ = 3, - Mailbox0 = 4, - Mailbox1 = 5, - Mailbox2 = 6, - Mailbox3 = 7, - Gpu = 8, - Pmu = 9, - AxiOutstanding = 10, - LocalTimer = 11, -} - -/// Timer, IRQs, mailboxes registers (ref: QA7 chapter 4, page 7) -#[allow(non_snake_case)] -#[repr(C)] -struct Registers { - CONTROL: Volatile, - _unused1: [Volatile; 8], - LOCAL_IRQ: Volatile, - _unused2: [Volatile; 3], - LOCAL_TIMER_CTL: Volatile, - LOCAL_TIMER_FLAGS: Volatile, - _unused3: Volatile, - CORE_TIMER_IRQCNTL: [Volatile; 4], - CORE_MAILBOX_IRQCNTL: [Volatile; 4], - CORE_IRQ_SRC: [Volatile; 4], -} - -/// The ARM generic timer. -pub struct GenericTimer { - registers: &'static mut Registers, -} - -impl BasicTimer for GenericTimer { - fn new() -> Self { - GenericTimer { - registers: unsafe { &mut *(GEN_TIMER_REG_BASE as *mut Registers) }, - } - } - - fn init(&mut self) { - self.registers.CORE_TIMER_IRQCNTL[0].write(1 << (CoreInterrupt::CNTPNSIRQ as u8)); - CNTP_CTL_EL0.write(CNTP_CTL_EL0::ENABLE::SET); - } - - fn read(&self) -> u64 { - let cntfrq = CNTFRQ_EL0.get(); // 62500000 - (CNTPCT_EL0.get() * 1000000 / (cntfrq as u64)) as u64 - } - - fn tick_in(&mut self, us: u32) { - let cntfrq = CNTFRQ_EL0.get(); // 62500000 - CNTP_TVAL_EL0.set(((cntfrq as f64) * (us as f64) / 1000000.0) as u32); - } - - fn is_pending(&self) -> bool { - self.registers.CORE_IRQ_SRC[0].read() & (1 << (CoreInterrupt::CNTPNSIRQ as u8)) != 0 - } -} diff --git a/crate/bcm2837/src/timer/mod.rs b/crate/bcm2837/src/timer/mod.rs deleted file mode 100644 index e628a99..0000000 --- a/crate/bcm2837/src/timer/mod.rs +++ /dev/null @@ -1,38 +0,0 @@ -#[cfg(feature = "use_generic_timer")] -mod generic_timer; -#[cfg(feature = "use_generic_timer")] -pub use self::generic_timer::GenericTimer as Timer; - -#[cfg(not(feature = "use_generic_timer"))] -mod system_timer; -#[cfg(not(feature = "use_generic_timer"))] -pub use self::system_timer::SystemTimer as Timer; - -/// The Raspberry Pi timer. -pub trait BasicTimer { - /// Returns a new instance. - fn new() -> Self; - - /// Initialization timer. - fn init(&mut self); - - /// Reads the timer's counter and returns the 64-bit counter value. - /// The returned value is the number of elapsed microseconds. - fn read(&self) -> u64; - - /// Sets up a match in timer 1 to occur `us` microseconds from now. If - /// interrupts for timer 1 are enabled and IRQs are unmasked, then a timer - /// interrupt will be issued in `us` microseconds. - fn tick_in(&mut self, us: u32); - - /// Returns `true` if timer interruption is pending. Otherwise, returns `false`. - fn is_pending(&self) -> bool; -} - -/// wait for `cycle` CPU cycles -#[inline(always)] -pub fn delay(cycle: u32) { - for _ in 0..cycle { - unsafe { asm!("nop") } - } -} diff --git a/crate/bcm2837/src/timer/system_timer.rs b/crate/bcm2837/src/timer/system_timer.rs deleted file mode 100644 index 6ad1d85..0000000 --- a/crate/bcm2837/src/timer/system_timer.rs +++ /dev/null @@ -1,62 +0,0 @@ -use super::BasicTimer; -use crate::consts::IO_BASE; -use crate::interrupt::{Controller, Interrupt}; -use volatile::{ReadOnly, Volatile}; - -/// The base address for the ARM system timer registers. -const TIMER_REG_BASE: usize = IO_BASE + 0x3000; - -/// System timer registers (ref: peripherals 12.1, page 172) -#[repr(C)] -#[allow(non_snake_case)] -struct Registers { - CS: Volatile, - CLO: ReadOnly, - CHI: ReadOnly, - COMPARE: [Volatile; 4], -} - -#[repr(u8)] -#[allow(dead_code)] -#[derive(Copy, Clone, PartialEq, Debug)] -enum SystemTimerId { - Timer0 = 0, - Timer1 = 1, - Timer2 = 2, - Timer3 = 3, -} - -/// The Raspberry Pi ARM system timer. -pub struct SystemTimer { - registers: &'static mut Registers, -} - -impl BasicTimer for SystemTimer { - fn new() -> Self { - SystemTimer { - registers: unsafe { &mut *(TIMER_REG_BASE as *mut Registers) }, - } - } - - fn init(&mut self) { - Controller::new().enable(Interrupt::Timer1); - } - - fn read(&self) -> u64 { - let low = self.registers.CLO.read(); - let high = self.registers.CHI.read(); - ((high as u64) << 32) | (low as u64) - } - - fn tick_in(&mut self, us: u32) { - let current_low = self.registers.CLO.read(); - let compare = current_low.wrapping_add(us); - self.registers.COMPARE[SystemTimerId::Timer1 as usize].write(compare); - self.registers.CS.write(1 << (SystemTimerId::Timer1 as usize)); // unmask - } - - fn is_pending(&self) -> bool { - let controller = Controller::new(); - controller.is_pending(Interrupt::Timer1) - } -} diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index fe415ce..2468c5d 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -45,6 +45,7 @@ version = "0.1.0" [[package]] name = "bcm2837" version = "0.1.0" +source = "git+https://github.com/equation314/bcm2837#446f0ea04deb5216ba5e08f10af36e5c1729e6fd" dependencies = [ "aarch64 2.2.2 (git+https://github.com/equation314/aarch64)", "volatile 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -248,7 +249,7 @@ dependencies = [ "aarch64 2.2.2 (git+https://github.com/equation314/aarch64)", "apic 0.1.0 (git+https://github.com/wangrunji0408/APIC-Rust)", "bbl 0.1.0", - "bcm2837 0.1.0", + "bcm2837 0.1.0 (git+https://github.com/equation314/bcm2837)", "bit-allocator 0.1.0", "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -525,6 +526,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum apic 0.1.0 (git+https://github.com/wangrunji0408/APIC-Rust)" = "" "checksum array-init 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "23589ecb866b460d3a0f1278834750268c607e8e28a1b982c907219f3178cd72" "checksum bare-metal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a3caf393d93b2d453e80638d0674597020cef3382ada454faacd43d1a55a735a" +"checksum bcm2837 0.1.0 (git+https://github.com/equation314/bcm2837)" = "" "checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum bitvec 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cfadef5c4e2c2e64067b9ecc061179f12ac7ec65ba613b1f60f3972bbada1f5b" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 6b26913..159e350 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -72,7 +72,7 @@ bbl = { path = "../crate/bbl" } [target.'cfg(target_arch = "aarch64")'.dependencies] aarch64 = { git = "https://github.com/equation314/aarch64" } -bcm2837 = { path = "../crate/bcm2837", optional = true } +bcm2837 = { git = "https://github.com/equation314/bcm2837", optional = true } [package.metadata.bootimage] default-target = "targets/x86_64.json"