From d667c955d769eccf47ef7b809bffdc9ab9e422cb Mon Sep 17 00:00:00 2001 From: Isabelle Lesko Date: Mon, 27 Jul 2020 13:59:01 -0500 Subject: [PATCH] mmio work (not working) --- Cargo.toml | 1 + asm/boot-1.s | 21 ----------- asm/{boot-2.s => boot.s} | 0 justfile | 17 ++++++--- src/lib.rs | 72 ++++++++++++++++++++---------------- src/mem.rs | 80 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 133 insertions(+), 58 deletions(-) delete mode 100644 asm/boot-1.s rename asm/{boot-2.s => boot.s} (100%) create mode 100644 src/mem.rs diff --git a/Cargo.toml b/Cargo.toml index 3aff455..dbcdfdf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,3 +11,4 @@ panic = "abort" panic = "abort" [dependencies] + diff --git a/asm/boot-1.s b/asm/boot-1.s deleted file mode 100644 index 22f5125..0000000 --- a/asm/boot-1.s +++ /dev/null @@ -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 - diff --git a/asm/boot-2.s b/asm/boot.s similarity index 100% rename from asm/boot-2.s rename to asm/boot.s diff --git a/justfile b/justfile index 155ae25..229ab7f 100644 --- a/justfile +++ b/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 \ No newline at end of file +# 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 \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 142dd56..7f3ad8e 100644 --- a/src/lib.rs +++ b/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() {} diff --git a/src/mem.rs b/src/mem.rs new file mode 100644 index 0000000..0d0e4f7 --- /dev/null +++ b/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, +}