1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-23 00:16:17 +04:00

aarch64: add crate bcm2837, implement GPIO

This commit is contained in:
equation314 2018-10-27 02:45:47 +08:00
parent cc936ded35
commit addf49ffdb
9 changed files with 212 additions and 8 deletions

7
crate/bcm2837/Cargo.toml Normal file
View File

@ -0,0 +1,7 @@
[package]
name = "bcm2837"
version = "0.1.0"
authors = ["equation314 <equation618@gmail.com>"]
[dependencies]
volatile = "0.2.4"

10
crate/bcm2837/src/asm.rs Normal file
View File

@ -0,0 +1,10 @@
//! utility assembly instructions
/// delay for some clocks
#[inline]
pub unsafe fn delay(clock: u32) {
#[cfg(target_arch = "aarch64")]
asm!("1: subs x0, x0, #1; bne 1b;"
:: "{x0}"(clock)
:: "volatile");
}

159
crate/bcm2837/src/gpio.rs Normal file
View File

@ -0,0 +1,159 @@
use super::IO_BASE;
use super::asm::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.
#[repr(u8)]
pub enum Function {
Input = 0b000,
Output = 0b001,
Alt0 = 0b100,
Alt1 = 0b101,
Alt2 = 0b110,
Alt3 = 0b111,
Alt4 = 0b011,
Alt5 = 0b010,
}
#[repr(C)]
#[allow(non_snake_case)]
struct Registers {
FSEL: [Volatile<u32>; 6],
__reserved0: u32,
SET: [WriteOnly<u32>; 2],
__reserved1: u32,
CLR: [WriteOnly<u32>; 2],
__reserved2: u32,
LEV: [ReadOnly<u32>; 2],
__reserved3: u32,
EDS: [Volatile<u32>; 2],
__reserved4: u32,
REN: [Volatile<u32>; 2],
__reserved5: u32,
FEN: [Volatile<u32>; 2],
__reserved6: u32,
HEN: [Volatile<u32>; 2],
__reserved7: u32,
LEN: [Volatile<u32>; 2],
__reserved8: u32,
AREN: [Volatile<u32>; 2],
__reserved9: u32,
AFEN: [Volatile<u32>; 2],
__reserved10: u32,
PUD: Volatile<u32>,
PUDCLK: [Volatile<u32>; 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<State> {
pin: u8,
registers: &'static mut Registers,
_state: PhantomData<State>,
}
impl<T> Gpio<T> {
/// 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<S>(self) -> Gpio<S> {
Gpio {
pin: self.pin,
registers: self.registers,
_state: PhantomData,
}
}
/// Set the Gpio pull-up/pull-down state for values in `pin_value`
pub fn set_gpio_pd(&mut self, pud_value: u8) {
unsafe {
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<Uninitialized> {
/// Returns a new `GPIO` structure for pin number `pin`.
///
/// # Panics
///
/// Panics if `pin` > `53`.
pub fn new(pin: u8) -> Gpio<Uninitialized> {
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<Alt> {
self.registers.FSEL[(self.pin / 10) as usize]
.write((function as u32) << (3 * (self.pin % 10)));
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<Output> {
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<Input> {
self.into_alt(Function::Input).transition()
}
}
impl Gpio<Output> {
/// 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<Input> {
/// 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
}
}

11
crate/bcm2837/src/lib.rs Normal file
View File

@ -0,0 +1,11 @@
#![no_std]
#![feature(asm)]
extern crate volatile;
mod asm;
pub mod gpio;
pub mod mini_uart;
pub const IO_BASE: usize = 0x3F000000;

View File

@ -0,0 +1 @@
use super::IO_BASE;

14
kernel/Cargo.lock generated
View File

@ -7,6 +7,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "bbl"
version = "0.1.0"
[[package]]
name = "bcm2837"
version = "0.1.0"
dependencies = [
"volatile 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bit-allocator"
version = "0.1.0"
@ -211,6 +218,7 @@ name = "ucore"
version = "0.1.0"
dependencies = [
"bbl 0.1.0",
"bcm2837 0.1.0",
"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)",
@ -227,7 +235,7 @@ dependencies = [
"uart_16550 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ucore-memory 0.1.0",
"ucore-process 0.1.0",
"volatile 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"volatile 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"x86_64 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -265,7 +273,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "volatile"
version = "0.1.0"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -344,7 +352,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f70329e2cbe45d6c97a5112daad40c34cd9a4e18edb5a2a18fefeb584d8d25e5"
"checksum ux 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53d8df5dd8d07fedccd202de1887d94481fadaea3db70479f459e8163a1fab41"
"checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051"
"checksum volatile 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37c5d76c0f40ba4f8ac10ec4717d4e98ce3e58c5607eea36e9464226fc5e0a95"
"checksum volatile 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "54d4343a2df2d65144a874f95950754ee7b7e8594f6027aae8c7d0f4858a3fe8"
"checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@ -25,7 +25,7 @@ once = "0.3.3"
xmas-elf = "0.6"
bitflags = "1.0"
bit_field = "0.9.0"
volatile = "0.1.0"
volatile = "0.2.4"
linked_list_allocator = "0.6"
lazy_static = { version = "1.0.0", features = ["spin_no_std"] }
bit-allocator = { path = "../crate/bit-allocator" }
@ -43,6 +43,9 @@ uart_16550 = "0.1"
riscv = { path = "../crate/riscv" }
bbl = { path = "../crate/bbl" }
[target.'cfg(target_arch = "aarch64")'.dependencies]
bcm2837 = { path = "../crate/bcm2837" }
[package.metadata.bootimage]
default-target = "x86_64-blog_os.json"
output = "target/x86_64-blog_os/bootimage.bin"

View File

@ -1,5 +1,9 @@
//! Raspberry PI 3 Model B/B+
extern crate bcm2837;
pub fn init() {
// TODO
bcm2837::gpio::Gpio::new(14).set_gpio_pd(0);
bcm2837::gpio::Gpio::new(15).set_gpio_pd(0);
}

View File

@ -11,8 +11,11 @@ pub mod board;
/// TODO
/// The entry point of kernel
#[no_mangle] // don't mangle the name of this function
pub extern fn rust_main() -> ! {
#[no_mangle] // don't mangle the name of this function
pub extern "C" fn rust_main() -> ! {
// Init board.
board::init();
println!("Hello ARM64!");
// First init log mod, so that we can print log info.
@ -24,8 +27,6 @@ pub extern fn rust_main() -> ! {
// Now heap is available
// timer::init();
// Init board.
board::init();
::kmain();
}