ソースを参照

mmio work (not working)

master
Isabelle L. 5年前
コミット
d667c955d7
6個のファイルの変更133行の追加58行の削除
  1. +1
    -0
      Cargo.toml
  2. +0
    -21
      asm/boot-1.s
  3. +0
    -0
      asm/boot.s
  4. +12
    -5
      justfile
  5. +40
    -32
      src/lib.rs
  6. +80
    -0
      src/mem.rs

+ 1
- 0
Cargo.toml ファイルの表示

@@ -11,3 +11,4 @@ panic = "abort"
panic = "abort"

[dependencies]


+ 0
- 21
asm/boot-1.s ファイルの表示

@@ -1,21 +0,0 @@
// AArch32 mode
.section ".text.boot"
.globl _start
.org 0x8000
_start:
mov sp, #0x8000
ldr r4, =__bss_start
ldr r9, =__bss_end
mov r5, #0
mov r6, #0
mov r7, #0
mov r8, #0
b 2f
1: stmia r4!, {r4-r8}
2: cmp r4, r9
blo 1b
ldr r4, =kernel_main
blx r3
halt: wfe
b halt


asm/boot-2.s → asm/boot.s ファイルの表示


+ 12
- 5
justfile ファイルの表示

@@ -1,7 +1,14 @@
# build the OS
build-os:
arm-none-eabi-gcc -mcpu=cortex-a7 -fpic -ffreestanding -c asm/boot-2.s -o build/boot.o
cargo xbuild --release --target armv7r-none-eabihf
arm-none-eabi-gcc -T linker.ld -o build/grove.img -ffreestanding -O2 -nostdlib build/boot.o target/target/release/libgrove.rlib
rm build/*
arm-none-eabi-gcc -mcpu=cortex-a7 -fpic -ffreestanding -c asm/boot.s -o build/boot.o
cargo xbuild --target armv7a-none-eabi
arm-none-eabi-gcc -T linker.ld -o build/grove.img -ffreestanding -O2 -nostdlib build/boot.o target/armv7a-none-eabi/debug/libgrove.rlib

run-os: build-os
qemu-system-arm -M raspi2 -kernel build/grove.img -serial stdio
# build the OS and run it on QEMU
run: build-os
qemu-system-arm -M raspi2 -kernel build/grove.img -serial stdio

# build just the rust binary
build:
cargo xbuild --target armv7a-none-eabi

+ 40
- 32
src/lib.rs ファイルの表示

@@ -1,51 +1,59 @@
#![no_std]
#![feature(asm)]

use core::panic::PanicInfo;
use core::ptr::{read_volatile, write_volatile};

const UART_DR: u32 = 0x3f20_1000;
const UART_FR: u32 = 0x3f20_1018;

fn mmio_write(reg: u32, val: u32) {
unsafe { write_volatile(reg as *mut u32, val) }
}
mod mem;

fn mmio_read(reg: u32) -> u32 {
unsafe { read_volatile(reg as *const u32) }
}
use core::panic::PanicInfo;

fn transmit_fifo_full() -> bool {
mmio_read(UART_FR) & (1 << 5) > 0
/// represents the board type
#[derive(PartialEq, Eq)]
pub enum BoardType {
PiZeroOne,
PiTwo,
PiThree,
PiFour,
Unknown,
}

fn receive_fifo_empty() -> bool {
mmio_read(UART_FR) & (1 << 4) > 0
}
impl BoardType {
/// detect the type of Raspberry Pi board
pub fn detect() -> Self {
let mut reg_data: u32;

fn writec(c: u8) {
while transmit_fifo_full() {}
mmio_write(UART_DR, c as u32);
}
unsafe {
asm!("mrc p15, 0, {}, c0, c0, 0", out(reg) reg_data);
}

fn getc() -> u8 {
while receive_fifo_empty() {}
mmio_read(UART_DR) as u8
}
match reg_data >> 4 & 0xFFF {
0xB76 => BoardType::PiZeroOne,
0xC07 => BoardType::PiTwo,
0xD03 => BoardType::PiThree,
0xD08 => BoardType::PiFour,
_ => BoardType::Unknown,
}
}

fn write(msg: &str) {
for c in msg.bytes() {
writec(c);
/// return the MMIO base address
pub fn mmio_base_addr(self) -> *const u32 {
match self {
BoardType::PiZeroOne | BoardType::Unknown => 0x2000_0000 as *const u32,
BoardType::PiTwo | BoardType::PiThree => 0x3F00_0000 as *const u32,
BoardType::PiFour => 0xFE00_0000 as *const u32,
}
}
}

#[no_mangle]
pub extern "C" fn kernel_main() {
write("hello rust raspberry pi kernel");
loop {
writec(getc())
}
let board_type = BoardType::detect();
let mem = mem::MemoryMappedIo::init(board_type);
mem.write_str("hello grove kernel <3");

loop {}
}

/// these functions are here to make the compiler/linker happy :)

#[no_mangle]
pub extern "C" fn __aeabi_unwind_cpp_pr0() {}



+ 80
- 0
src/mem.rs ファイルの表示

@@ -0,0 +1,80 @@
pub struct MemoryMappedIo {
base_addr: *const u32,
}

impl MemoryMappedIo {
pub fn init(board_type: crate::BoardType) -> Self {
let mem = MemoryMappedIo { base_addr: board_type.mmio_base_addr() };
mem.uart_init();
mem
}

fn uart_init(&self) {}

// receive fifo empty
fn recv_fifo_empty(&self) -> bool {
self.read_word(PeripheralAddress::UartFr) & (1 << 5) > 0
}

// transmit fifo full
fn tran_fifo_full(&self) -> bool {
self.read_word(PeripheralAddress::UartFr) & (1 << 4) > 0
}

pub fn write_str(&self, s: &str) {
s.bytes().for_each(|byte| self.write_byte(byte))
}

pub fn write_byte(&self, byte: u8) {
while self.tran_fifo_full() {}
self.write_word(PeripheralAddress::UartDr, byte as u32);
}

pub fn get_byte(&self) -> u8 {
while self.recv_fifo_empty() {}
self.read_word(PeripheralAddress::UartDr) as u8
}

// write a word to the memory mapped IO
pub fn write_word(&self, peripheral_addr: PeripheralAddress, data: u32) {
unsafe {
let addr = self.base_addr.offset(peripheral_addr as isize) as *mut u32;
addr.write_volatile(data);
}
}

// read a word from memory mapped IO
pub fn read_word(&self, peripheral_addr: PeripheralAddress) -> u32 {
unsafe {
let addr = self.base_addr.offset(peripheral_addr as isize) as *mut u32;
addr.read_volatile()
}
}
}

/// represents the offset from the base address
#[allow(dead_code)]
#[repr(isize)]
pub enum PeripheralAddress {
Gpiobase = 0x0020_0000,
Gppud = 0x0020_0094,
Gppudclk0 = 0x0020_0098,
UartDr = 0x0020_1000,
UartRsrecr = 0x0020_1004,
UartFr = 0x0020_1018,
UartIlpr = 0x0020_1020,
UartIbrd = 0x0020_1024,
UartFbrd = 0x0020_1028,
UartLcrh = 0x0020_102C,
UartCr = 0x0020_1030,
UartIfls = 0x0020_1034,
UartImsc = 0x0020_1038,
Uartris = 0x0020_103C,
UartMis = 0x0020_1040,
UartIcr = 0x0020_1044,
UartDmacr = 0x0020_1048,
UartItcr = 0x0020_1080,
UartItip = 0x0020_1084,
UartItop = 0x0020_1088,
UartTdr = 0x0020_108C,
}

読み込み中…
キャンセル
保存