feat?: it boots on orange pi 3
This commit is contained in:
parent
683861b401
commit
e21d7fdd59
11
Makefile
11
Makefile
@ -6,6 +6,7 @@ GDB?=gdb-multiarch
|
||||
|
||||
LLVM_BASE=$(shell llvm-config --bindir)
|
||||
OBJCOPY=$(LLVM_BASE)/llvm-objcopy
|
||||
MKIMAGE?=mkimage
|
||||
|
||||
PROFILE?=debug
|
||||
O=target/$(ARCH)-$(MACH)/$(PROFILE)
|
||||
@ -30,6 +31,12 @@ QEMU_OPTS+=-kernel $(O)/kernel.bin \
|
||||
-m 512 \
|
||||
-serial chardev:serial0
|
||||
endif
|
||||
ifeq ($(MACH),rpi3b)
|
||||
QEMU_OPTS+=-kernel $(O)/kernel.bin \
|
||||
-M raspi3b \
|
||||
-serial null \
|
||||
-serial chardev:serial0
|
||||
endif
|
||||
endif
|
||||
|
||||
.PHONY: address error etc kernel src
|
||||
@ -41,6 +48,10 @@ kernel:
|
||||
ifeq ($(ARCH),aarch64)
|
||||
$(OBJCOPY) -O binary $(O)/kernel $(O)/kernel.bin
|
||||
endif
|
||||
ifeq ($(MACH),orangepi3)
|
||||
$(LLVM_BASE)/llvm-strip $(O)/kernel
|
||||
$(LLVM_BASE)/llvm-size $(O)/kernel
|
||||
endif
|
||||
|
||||
clean:
|
||||
cargo clean
|
||||
|
17
etc/aarch64-orangepi3.json
Normal file
17
etc/aarch64-orangepi3.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"arch": "aarch64",
|
||||
"data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
|
||||
"disable-redzone": true,
|
||||
"executables": true,
|
||||
"features": "+strict-align,+neon,+fp-armv8",
|
||||
"linker": "rust-lld",
|
||||
"linker-flavor": "ld.lld",
|
||||
"llvm-target": "aarch64-unknown-none",
|
||||
"max-atomic-width": 128,
|
||||
"panic-strategy": "abort",
|
||||
"relocation-model": "static",
|
||||
"target-pointer-width": "64",
|
||||
"pre-link-args": {
|
||||
"ld.lld": [ "-Tetc/aarch64-orangepi3.ld" ]
|
||||
}
|
||||
}
|
35
etc/aarch64-orangepi3.ld
Normal file
35
etc/aarch64-orangepi3.ld
Normal file
@ -0,0 +1,35 @@
|
||||
ENTRY(_entry);
|
||||
|
||||
MEMORY {
|
||||
ram : ORIGIN = 0x48000000, LENGTH = 992M
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
PROVIDE(__kernel_start = .);
|
||||
|
||||
.text : {
|
||||
*(.text._entry)
|
||||
*(.text*)
|
||||
} >ram
|
||||
|
||||
. = ALIGN(4K);
|
||||
.rodata : {
|
||||
*(.rodata*)
|
||||
} >ram
|
||||
|
||||
. = ALIGN(4K);
|
||||
.data : {
|
||||
*(.data*)
|
||||
} >ram
|
||||
|
||||
. = ALIGN(4K);
|
||||
.bss : {
|
||||
PROVIDE(__bss_start = .);
|
||||
*(COMMON)
|
||||
*(.bss*)
|
||||
. = ALIGN(4K);
|
||||
PROVIDE(__bss_end = .);
|
||||
} >ram
|
||||
|
||||
PROVIDE(__kernel_end = .);
|
||||
}
|
@ -20,4 +20,4 @@ cortex-a = { version = "6.x.x" }
|
||||
|
||||
[features]
|
||||
mach_qemu = []
|
||||
default = ["mach_qemu"]
|
||||
mach_orangepi3 = []
|
||||
|
@ -1,3 +1,5 @@
|
||||
// vi:ft=a64asm.asm:
|
||||
|
||||
.macro ADR_REL reg, sym
|
||||
adrp \reg, \sym
|
||||
add \reg, \reg, #:lo12:\sym
|
||||
|
@ -1,37 +1,71 @@
|
||||
//! aarch64 common boot logic
|
||||
use crate::arch::aarch64::asm::CPACR_EL1;
|
||||
use cortex_a::registers::VBAR_EL1;
|
||||
use tock_registers::interfaces::Writeable;
|
||||
|
||||
use crate::arch::aarch64::asm::{CPACR_EL1};
|
||||
use cortex_a::registers::{VBAR_EL1, SCTLR_EL1};
|
||||
use tock_registers::interfaces::{Writeable, ReadWriteable};
|
||||
|
||||
use cortex_a::asm::barrier::{self, dsb, isb};
|
||||
|
||||
#[no_mangle]
|
||||
fn __aa64_bsp_main() {
|
||||
// Disable FP instruction trapping
|
||||
CPACR_EL1.write(CPACR_EL1::FPEN::TrapNone);
|
||||
CPACR_EL1.modify(CPACR_EL1::FPEN::TrapNone);
|
||||
|
||||
extern "C" {
|
||||
static aa64_el1_vectors: u8;
|
||||
}
|
||||
unsafe {
|
||||
VBAR_EL1.set(&aa64_el1_vectors as *const _ as u64);
|
||||
|
||||
// Setup caching in SCTLR_EL1
|
||||
dsb(barrier::SY);
|
||||
isb(barrier::SY);
|
||||
|
||||
SCTLR_EL1.modify(SCTLR_EL1::I::SET +
|
||||
SCTLR_EL1::SA::SET +
|
||||
SCTLR_EL1::C::SET +
|
||||
SCTLR_EL1::A::SET);
|
||||
|
||||
dsb(barrier::SY);
|
||||
isb(barrier::SY);
|
||||
}
|
||||
|
||||
debugln!("Test");
|
||||
|
||||
use crate::arch::machine;
|
||||
use crate::dev::{serial::SerialDevice, timer::TimestampSource, Device};
|
||||
|
||||
let mut el: u64;
|
||||
let mut sctlr_el1: u64;
|
||||
unsafe {
|
||||
machine::console().lock().enable().unwrap();
|
||||
machine::local_timer().lock().enable().unwrap();
|
||||
asm!("mrs {}, currentel", out(reg) el);
|
||||
asm!("mrs {}, sctlr_el1", out(reg) sctlr_el1);
|
||||
}
|
||||
el >>= 2;
|
||||
el &= 0x3;
|
||||
|
||||
let base = machine::local_timer().lock().timestamp().unwrap();
|
||||
debugln!("Current EL = {}", el);
|
||||
debugln!("SCTLR_EL1 = {:#x}", sctlr_el1);
|
||||
|
||||
//use crate::arch::machine;
|
||||
//use crate::dev::{serial::SerialDevice, timer::TimestampSource, Device};
|
||||
|
||||
//unsafe {
|
||||
//machine::console().lock().enable().unwrap();
|
||||
//machine::local_timer().lock().enable().unwrap();
|
||||
//}
|
||||
|
||||
//let base = machine::local_timer().lock().timestamp().unwrap();
|
||||
|
||||
loop {
|
||||
let count = machine::local_timer().lock().timestamp().unwrap();
|
||||
let ch = machine::console().lock().recv(true).unwrap();
|
||||
debugln!("[{:?}] {:#04x} = '{}'!", count - base, ch, ch as char);
|
||||
cortex_a::asm::wfe();
|
||||
//let count = machine::local_timer().lock().timestamp().unwrap();
|
||||
//let ch = machine::console().lock().recv(true).unwrap();
|
||||
//debugln!("[{:?}] {:#04x} = '{}'!", count - base, ch, ch as char);
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "mach_orangepi3")] {
|
||||
global_asm!(include_str!("uboot.S"));
|
||||
} else {
|
||||
global_asm!(include_str!("entry.S"));
|
||||
}
|
||||
}
|
||||
|
46
kernel/src/arch/aarch64/boot/uboot.S
Normal file
46
kernel/src/arch/aarch64/boot/uboot.S
Normal file
@ -0,0 +1,46 @@
|
||||
// vi:ft=a64asm.asm:
|
||||
|
||||
.set UART0_BASE, 0x05000000
|
||||
|
||||
.set SPSR_EL2_EL1h, 0x5
|
||||
.set HCR_EL2_RW, 1 << 31
|
||||
.set HCR_EL2_HCD, 1 << 29
|
||||
|
||||
.macro ADR_REL reg, sym
|
||||
adrp \reg, \sym
|
||||
add \reg, \reg, #:lo12:\sym
|
||||
.endm
|
||||
|
||||
.section .text._entry
|
||||
.global _entry
|
||||
_entry:
|
||||
// Test for EL2
|
||||
mrs x0, CurrentEL
|
||||
lsr x0, x0, #2
|
||||
cmp x0, #2
|
||||
bne 1f
|
||||
// Exit EL2
|
||||
// TODO cnthtctl_el2 setup
|
||||
|
||||
ADR_REL x0, 1f
|
||||
msr elr_el2, x0
|
||||
mov x0, #SPSR_EL2_EL1h
|
||||
msr spsr_el2, x0
|
||||
mov x0, #(HCR_EL2_RW | HCR_EL2_HCD)
|
||||
msr hcr_el2, x0
|
||||
|
||||
eret
|
||||
1:
|
||||
dsb sy
|
||||
isb
|
||||
|
||||
ADR_REL x0, bsp_stack_top
|
||||
mov sp, x0
|
||||
|
||||
b __aa64_bsp_main
|
||||
|
||||
.section .bss
|
||||
.p2align 12
|
||||
bsp_stack_bottom:
|
||||
.skip 32768
|
||||
bsp_stack_top:
|
62
kernel/src/arch/aarch64/mach_orangepi3/mod.rs
Normal file
62
kernel/src/arch/aarch64/mach_orangepi3/mod.rs
Normal file
@ -0,0 +1,62 @@
|
||||
//! QEMU virt machine
|
||||
|
||||
use crate::arch::aarch64::timer::GenericTimer;
|
||||
use crate::dev::{Device, serial::SerialDevice};
|
||||
use crate::dev::timer::TimestampSource;
|
||||
use crate::sync::Spin;
|
||||
use error::Errno;
|
||||
|
||||
fn delay(mut p: usize) {
|
||||
while p != 0 {
|
||||
cortex_a::asm::nop();
|
||||
p -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct Uart {
|
||||
base: usize
|
||||
}
|
||||
|
||||
impl Device for Uart {
|
||||
fn name() -> &'static str {
|
||||
"Allwinner H6 UART"
|
||||
}
|
||||
|
||||
unsafe fn enable(&mut self) -> Result<(), Errno> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl SerialDevice for Uart {
|
||||
fn send(&mut self, byte: u8) -> Result<(), Errno> {
|
||||
unsafe {
|
||||
if byte == b'\n' {
|
||||
core::ptr::write_volatile(self.base as *mut u32, 13u32);
|
||||
delay(10000);
|
||||
}
|
||||
core::ptr::write_volatile(self.base as *mut u32, byte as u32);
|
||||
delay(10000);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn recv(&mut self, blocking: bool) -> Result<u8, Errno> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
const UART0_BASE: usize = 0x05000000;
|
||||
|
||||
/// Returns primary console for this machine
|
||||
#[inline]
|
||||
pub fn console() -> &'static Spin<impl SerialDevice> {
|
||||
&UART0
|
||||
}
|
||||
|
||||
///// Returns the timer used as CPU-local periodic IRQ source
|
||||
//#[inline]
|
||||
//pub fn local_timer() -> &'static Spin<impl TimestampSource> {
|
||||
// &LOCAL_TIMER
|
||||
//}
|
||||
|
||||
static UART0: Spin<Uart> = Spin::new(Uart { base: UART0_BASE });
|
@ -10,5 +10,9 @@ cfg_if! {
|
||||
pub mod mach_qemu;
|
||||
|
||||
pub use mach_qemu as machine;
|
||||
} else if #[cfg(feature = "mach_orangepi3")] {
|
||||
pub mod mach_orangepi3;
|
||||
|
||||
pub use mach_orangepi3 as machine;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user