mirror of
https://github.com/iceHtwoO/novaOS.git
synced 2026-04-17 04:32:27 +00:00
Compare commits
8 Commits
8c193f5c15
...
d948ad81aa
| Author | SHA1 | Date | |
|---|---|---|---|
| d948ad81aa | |||
|
|
ebed65e0b2 | ||
| 863f6000b0 | |||
|
|
5a4a8e5aac | ||
|
|
a02c38a8e4 | ||
| fbc2fcff72 | |||
| fe8e5e000a | |||
| 1ff752e3dd |
36
.github/workflows/rust.yml
vendored
Normal file
36
.github/workflows/rust.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
name: Rust
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
branches: ["master"]
|
||||||
|
|
||||||
|
env:
|
||||||
|
CARGO_TERM_COLOR: always
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install rustfmt for nightly
|
||||||
|
run: rustup component add --toolchain nightly-x86_64-unknown-linux-gnu rustfmt clippy
|
||||||
|
- name: Add AArch64 Target
|
||||||
|
run: rustup target add aarch64-unknown-none
|
||||||
|
- name: Run format check
|
||||||
|
run: cargo fmt --check
|
||||||
|
- name: Run lint
|
||||||
|
run: cargo clippy
|
||||||
|
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install rustfmt for nightly
|
||||||
|
run: rustup component add --toolchain nightly-x86_64-unknown-linux-gnu rustfmt clippy
|
||||||
|
- name: Add AArch64 Target
|
||||||
|
run: rustup target add aarch64-unknown-none
|
||||||
|
- name: Build
|
||||||
|
run: cargo build --verbose
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@
|
|||||||
kernel8.img
|
kernel8.img
|
||||||
.env
|
.env
|
||||||
sd.img
|
sd.img
|
||||||
|
settings.json
|
||||||
|
|||||||
41
.vscode/launch.json
vendored
41
.vscode/launch.json
vendored
@@ -1,5 +1,12 @@
|
|||||||
{
|
{
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
|
"compounds": [
|
||||||
|
{
|
||||||
|
"name": "Run QEMU + Attach LLDB",
|
||||||
|
"configurations": ["Attach LLDB"],
|
||||||
|
"preLaunchTask": "Run QEMU"
|
||||||
|
}
|
||||||
|
],
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "Attach to QEMU (AArch64)",
|
"name": "Attach to QEMU (AArch64)",
|
||||||
@@ -12,19 +19,29 @@
|
|||||||
"stopAtEntry": true,
|
"stopAtEntry": true,
|
||||||
"externalConsole": false,
|
"externalConsole": false,
|
||||||
"MIMode": "gdb",
|
"MIMode": "gdb",
|
||||||
"setupCommands": [
|
"setupCommands": [
|
||||||
{
|
{
|
||||||
"description": "Enable pretty-printing for gdb",
|
"description": "Enable pretty-printing for gdb",
|
||||||
"text": "-enable-pretty-printing",
|
"text": "-enable-pretty-printing",
|
||||||
"ignoreFailures": true
|
"ignoreFailures": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Show assembly on stop",
|
"description": "Show assembly on stop",
|
||||||
"text": "layout asm",
|
"text": "set disassemble-next-line on",
|
||||||
"ignoreFailures": true
|
"ignoreFailures": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"preLaunchTask": "Run QEMU"
|
"preLaunchTask": "Run QEMU"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "Attach LLDB",
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "attach",
|
||||||
|
"debugServer": 1234,
|
||||||
|
"program": "${workspaceFolder}/target/aarch64-unknown-none/debug/nova",
|
||||||
|
"stopOnEntry": true,
|
||||||
|
"processCreateCommands": ["gdb-remote localhost:1234"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
2
.vscode/tasks.json
vendored
2
.vscode/tasks.json
vendored
@@ -14,7 +14,7 @@
|
|||||||
{
|
{
|
||||||
"label": "Run QEMU",
|
"label": "Run QEMU",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "qemu-system-aarch64 -M raspi3b -cpu cortex-a53 -serial stdio -sd sd.img -display none -kernel ${workspaceFolder}/target/aarch64-unknown-none/debug/kernel8.img -S -s",
|
"command": "qemu-system-aarch64 -M raspi3b -cpu cortex-a53 -serial stdio -sd sd.img -display none -kernel ${workspaceFolder}/target/aarch64-unknown-none/debug/kernel8.img -S -s -m 1024",
|
||||||
"isBackground": true,
|
"isBackground": true,
|
||||||
"dependsOn": ["Build"]
|
"dependsOn": ["Build"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ edition = "2021"
|
|||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
|
debug = true
|
||||||
|
opt-level = 0
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
|
|||||||
BIN
firmware_files/fixup.dat
Executable file
BIN
firmware_files/fixup.dat
Executable file
Binary file not shown.
3
link.ld
3
link.ld
@@ -27,10 +27,9 @@ SECTIONS {
|
|||||||
KEEP(*(.vector_table))
|
KEEP(*(.vector_table))
|
||||||
}
|
}
|
||||||
|
|
||||||
.stack 0x8008000 : ALIGN(16)
|
.stack 0x8018000 : ALIGN(16)
|
||||||
{
|
{
|
||||||
__stack_start = .;
|
__stack_start = .;
|
||||||
.+=0x10000;
|
|
||||||
__stack_end = .;
|
__stack_end = .;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
15
src/configuration.rs
Normal file
15
src/configuration.rs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
static SCTLR_EL1_MMU_DISABLED: u64 = 0 << 0; //M
|
||||||
|
static SCTLR_EL1_DATA_CACHE_DISABLED: u64 = 0 << 2; //C
|
||||||
|
static SCTLR_EL1_INSTRUCTION_CACHE_DISABLED: u64 = 0 << 12; //I
|
||||||
|
static SCTLR_EL1_LITTLE_ENDIAN_EL0: u64 = 0 << 24; //E0E
|
||||||
|
static SCTLR_EL1_LITTLE_ENDIAN_EL1: u64 = 0 << 25; //EE
|
||||||
|
|
||||||
|
static SCTLR_EL1_RES: u64 = (0 << 6) | (1 << 11) | (0 << 17) | (1 << 20) | (1 << 22); //Res0 & Res1
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub static SCTLR_EL1_CONF: u64 = SCTLR_EL1_MMU_DISABLED
|
||||||
|
| SCTLR_EL1_DATA_CACHE_DISABLED
|
||||||
|
| SCTLR_EL1_INSTRUCTION_CACHE_DISABLED
|
||||||
|
| SCTLR_EL1_LITTLE_ENDIAN_EL0
|
||||||
|
| SCTLR_EL1_LITTLE_ENDIAN_EL1
|
||||||
|
| SCTLR_EL1_RES;
|
||||||
@@ -3,7 +3,14 @@ use core::{
|
|||||||
sync::atomic::{compiler_fence, Ordering},
|
sync::atomic::{compiler_fence, Ordering},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{mmio_read, mmio_write, peripherals::uart::print};
|
use crate::{
|
||||||
|
mmio_read, mmio_write,
|
||||||
|
peripherals::{
|
||||||
|
gpio::{blink_gpio, SpecificGpio},
|
||||||
|
uart::print,
|
||||||
|
},
|
||||||
|
timer::{sleep_ms, sleep_s},
|
||||||
|
};
|
||||||
|
|
||||||
const INTERRUPT_BASE: u32 = 0x3F00_B000;
|
const INTERRUPT_BASE: u32 = 0x3F00_B000;
|
||||||
const IRQ_PENDING_BASE: u32 = INTERRUPT_BASE + 0x204;
|
const IRQ_PENDING_BASE: u32 = INTERRUPT_BASE + 0x204;
|
||||||
@@ -35,7 +42,42 @@ unsafe extern "C" fn irq_handler() {
|
|||||||
handle_gpio_interrupt();
|
handle_gpio_interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn synchronous_interrupt() {
|
||||||
|
loop {
|
||||||
|
print("Sync Exception \r\n");
|
||||||
|
blink_gpio(SpecificGpio::OnboardLed as u8, 100);
|
||||||
|
esr_uart_dump();
|
||||||
|
sleep_s(200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn esr_uart_dump() {
|
||||||
|
let esr: u32;
|
||||||
|
unsafe {
|
||||||
|
asm!(
|
||||||
|
"mrs {esr}, ESR_EL1",
|
||||||
|
esr = out(reg) esr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for i in (0..32).rev() {
|
||||||
|
if ((esr >> i) & 1) == 0 {
|
||||||
|
print("0");
|
||||||
|
} else {
|
||||||
|
print("1");
|
||||||
|
}
|
||||||
|
if i % 4 == 0 && i > 0 {
|
||||||
|
print("_");
|
||||||
|
}
|
||||||
|
|
||||||
|
if i == 26 || i == 25 || i == 0 {
|
||||||
|
print("\n\r");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_gpio_interrupt() {
|
fn handle_gpio_interrupt() {
|
||||||
|
print("Interrupt\r\n");
|
||||||
for i in 0..=53u32 {
|
for i in 0..=53u32 {
|
||||||
let val = read_gpio_event_detect_status(i);
|
let val = read_gpio_event_detect_status(i);
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use core::ptr::{read_volatile, write_volatile};
|
|||||||
|
|
||||||
pub mod peripherals;
|
pub mod peripherals;
|
||||||
|
|
||||||
|
pub mod configuration;
|
||||||
pub mod irq_interrupt;
|
pub mod irq_interrupt;
|
||||||
pub mod mailbox;
|
pub mod mailbox;
|
||||||
pub mod timer;
|
pub mod timer;
|
||||||
|
|||||||
58
src/mailbox.rs
Normal file
58
src/mailbox.rs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
use crate::{mmio_read, mmio_write, peripherals::uart::print};
|
||||||
|
|
||||||
|
const MBOX_BASE: u32 = 0x3F00_0000 + 0xB880;
|
||||||
|
|
||||||
|
// MB0
|
||||||
|
const MBOX_READ: u32 = MBOX_BASE + 0x00;
|
||||||
|
const MBOX_STATUS: u32 = MBOX_BASE + 0x18;
|
||||||
|
|
||||||
|
// MB1
|
||||||
|
const MBOX_WRITE: u32 = MBOX_BASE + 0x20;
|
||||||
|
|
||||||
|
// Status
|
||||||
|
const MAIL_FULL: u32 = 0x80000000;
|
||||||
|
const MAIL_EMPTY: u32 = 0x40000000;
|
||||||
|
|
||||||
|
pub fn read_mailbox(channel: u32) -> u32 {
|
||||||
|
// Wait until mailbox is not empty
|
||||||
|
loop {
|
||||||
|
while mmio_read(MBOX_STATUS) & MAIL_EMPTY != 0 {}
|
||||||
|
let mut data = mmio_read(MBOX_READ);
|
||||||
|
let read_channel = data & 0xF;
|
||||||
|
|
||||||
|
data >>= 4;
|
||||||
|
|
||||||
|
if channel == read_channel {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_mailbox(channel: u32, data: u32) {
|
||||||
|
while mmio_read(MBOX_STATUS) & MAIL_FULL != 0 {}
|
||||||
|
mmio_write(MBOX_WRITE, (data & !0xF) | (channel & 0xF));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_soc_temp() -> u32 {
|
||||||
|
let mut mailbox = [0; 36];
|
||||||
|
mailbox[0] = 8 * 4; // Total size in bytes
|
||||||
|
mailbox[1] = 0; // Request
|
||||||
|
mailbox[2] = 0x00030006; // Tag
|
||||||
|
mailbox[3] = 8; // Maximum buffer len
|
||||||
|
mailbox[4] = 4; // Request length
|
||||||
|
mailbox[5] = 0; // Value Buffer
|
||||||
|
mailbox[6] = 0; // Value Buffer
|
||||||
|
mailbox[7] = 0; // End
|
||||||
|
|
||||||
|
let addr = core::ptr::addr_of!(mailbox[0]) as u32;
|
||||||
|
|
||||||
|
write_mailbox(8, addr);
|
||||||
|
|
||||||
|
let _ = read_mailbox(8);
|
||||||
|
|
||||||
|
if mailbox[1] == 0 {
|
||||||
|
print("Failed\r\n");
|
||||||
|
}
|
||||||
|
let raw_temp = mailbox[6] / 1000;
|
||||||
|
raw_temp
|
||||||
|
}
|
||||||
43
src/main.rs
43
src/main.rs
@@ -5,24 +5,28 @@
|
|||||||
use core::{
|
use core::{
|
||||||
arch::{asm, global_asm},
|
arch::{asm, global_asm},
|
||||||
panic::PanicInfo,
|
panic::PanicInfo,
|
||||||
|
ptr::write_volatile,
|
||||||
};
|
};
|
||||||
|
|
||||||
use nova::{
|
use nova::{
|
||||||
irq_interrupt::enable_irq_source,
|
irq_interrupt::enable_irq_source,
|
||||||
|
mailbox::read_soc_temp,
|
||||||
peripherals::{
|
peripherals::{
|
||||||
gpio::{
|
gpio::{
|
||||||
gpio_get_state, gpio_high, gpio_low, gpio_pull_up, set_falling_edge_detect,
|
blink_gpio, gpio_pull_up, set_falling_edge_detect, set_gpio_function, GPIOFunction,
|
||||||
set_gpio_function, GPIOFunction,
|
SpecificGpio,
|
||||||
},
|
},
|
||||||
uart::{print, uart_init},
|
uart::{print, print_u32, uart_init},
|
||||||
},
|
},
|
||||||
timer::{delay_nops, sleep_ms, sleep_us},
|
timer::{delay_nops, sleep_us},
|
||||||
};
|
};
|
||||||
|
|
||||||
global_asm!(include_str!("vector.S"));
|
global_asm!(include_str!("vector.S"));
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn el2_to_el1();
|
fn el2_to_el1();
|
||||||
|
static mut __bss_start: u32;
|
||||||
|
static mut __bss_end: u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
@@ -46,6 +50,9 @@ pub unsafe extern "C" fn _start() {
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn main() -> ! {
|
pub extern "C" fn main() -> ! {
|
||||||
|
unsafe {
|
||||||
|
zero_bss();
|
||||||
|
}
|
||||||
enable_uart();
|
enable_uart();
|
||||||
|
|
||||||
// Set ACT Led to Outout
|
// Set ACT Led to Outout
|
||||||
@@ -58,12 +65,21 @@ pub extern "C" fn main() -> ! {
|
|||||||
print("Hello World!\r\n");
|
print("Hello World!\r\n");
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
asm!("mrs x0, SCTLR_EL1");
|
||||||
el2_to_el1();
|
el2_to_el1();
|
||||||
}
|
}
|
||||||
|
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn zero_bss() {
|
||||||
|
let mut bss: *mut u32 = &raw mut __bss_start as *mut u32;
|
||||||
|
while bss < &raw mut __bss_end as *mut u32 {
|
||||||
|
write_volatile(bss, 0);
|
||||||
|
bss = bss.add(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn kernel_main() -> ! {
|
pub extern "C" fn kernel_main() -> ! {
|
||||||
print_current_el_str();
|
print_current_el_str();
|
||||||
@@ -77,26 +93,13 @@ pub extern "C" fn kernel_main() -> ! {
|
|||||||
set_falling_edge_detect(26, true);
|
set_falling_edge_detect(26, true);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let _ = gpio_high(29);
|
let temp = read_soc_temp();
|
||||||
|
print_u32(temp);
|
||||||
|
|
||||||
sleep_ms(500); // 0.5s
|
blink_gpio(SpecificGpio::OnboardLed as u8, 500);
|
||||||
let _ = gpio_low(29);
|
|
||||||
sleep_ms(500); // 0.5s
|
|
||||||
print_gpio_state();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_gpio_state() {
|
|
||||||
let state = gpio_get_state(26);
|
|
||||||
|
|
||||||
let ascii_byte = b'0' + state;
|
|
||||||
let data = [ascii_byte];
|
|
||||||
|
|
||||||
let s = str::from_utf8(&data).unwrap();
|
|
||||||
print(s);
|
|
||||||
print("\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_current_el() -> u64 {
|
pub fn get_current_el() -> u64 {
|
||||||
let el: u64;
|
let el: u64;
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use core::result::Result;
|
use core::result::Result;
|
||||||
use core::result::Result::Ok;
|
use core::result::Result::Ok;
|
||||||
|
|
||||||
use crate::timer::delay_nops;
|
use crate::timer::{delay_nops, sleep_ms};
|
||||||
use crate::{mmio_read, mmio_write};
|
use crate::{mmio_read, mmio_write};
|
||||||
|
|
||||||
const GPFSEL_BASE: u32 = 0x3F20_0000;
|
const GPFSEL_BASE: u32 = 0x3F20_0000;
|
||||||
@@ -13,6 +13,11 @@ const GPPUDCLK_BASE: u32 = 0x3F20_0098;
|
|||||||
const GPREN_BASE: u32 = 0x3F20_004C;
|
const GPREN_BASE: u32 = 0x3F20_004C;
|
||||||
const GPFEN_BASE: u32 = 0x3F20_0058;
|
const GPFEN_BASE: u32 = 0x3F20_0058;
|
||||||
|
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum SpecificGpio {
|
||||||
|
OnboardLed = 29,
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
pub enum GPIOFunction {
|
pub enum GPIOFunction {
|
||||||
Input = 0b000,
|
Input = 0b000,
|
||||||
@@ -90,30 +95,28 @@ pub fn gpio_pull_down(gpio: u8) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn gpio_pull_up_down(gpio: u8, val: u32) {
|
fn gpio_pull_up_down(gpio: u8, val: u32) {
|
||||||
unsafe {
|
// Determine GPPUDCLK Register
|
||||||
// Determine GPPUDCLK Register
|
let register_addr = GPPUDCLK_BASE + 4 * (gpio as u32 / 32);
|
||||||
let register_addr = GPPUDCLK_BASE + 4 * (gpio as u32 / 32);
|
let register_offset = gpio % 32;
|
||||||
let register_offset = gpio % 32;
|
|
||||||
|
|
||||||
// 1. Write Pull up
|
// 1. Write Pull up
|
||||||
mmio_write(GPPUD, val);
|
mmio_write(GPPUD, val);
|
||||||
|
|
||||||
// 2. Delay 150 cycles
|
// 2. Delay 150 cycles
|
||||||
delay_nops(150);
|
delay_nops(150);
|
||||||
|
|
||||||
// 3. Write to clock
|
// 3. Write to clock
|
||||||
let new_val = 0b1 << register_offset;
|
let new_val = 0b1 << register_offset;
|
||||||
mmio_write(register_addr, new_val);
|
mmio_write(register_addr, new_val);
|
||||||
|
|
||||||
// 4. Delay 150 cycles
|
// 4. Delay 150 cycles
|
||||||
delay_nops(150);
|
delay_nops(150);
|
||||||
|
|
||||||
// 5. reset GPPUD
|
// 5. reset GPPUD
|
||||||
mmio_write(GPPUD, 0);
|
mmio_write(GPPUD, 0);
|
||||||
|
|
||||||
// 6. reset clock
|
// 6. reset clock
|
||||||
mmio_write(register_addr, 0);
|
mmio_write(register_addr, 0);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the current status if falling edge detection is set
|
/// Get the current status if falling edge detection is set
|
||||||
@@ -166,3 +169,11 @@ pub fn set_rising_edge_detect(gpio: u8, enable: bool) {
|
|||||||
|
|
||||||
mmio_write(register_addr, new_val);
|
mmio_write(register_addr, new_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn blink_gpio(gpio: u8, duration_ms: u32) {
|
||||||
|
let _ = gpio_high(gpio);
|
||||||
|
|
||||||
|
sleep_ms(duration_ms);
|
||||||
|
let _ = gpio_low(gpio);
|
||||||
|
sleep_ms(duration_ms);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use core::arch::asm;
|
||||||
|
|
||||||
use crate::{mmio_read, mmio_write};
|
use crate::{mmio_read, mmio_write};
|
||||||
|
|
||||||
const BAUD: u32 = 115200;
|
const BAUD: u32 = 115200;
|
||||||
@@ -21,11 +23,41 @@ const UART0_LCRH_FEN: u32 = 1 << 4;
|
|||||||
/// Print `s` over UART
|
/// Print `s` over UART
|
||||||
pub fn print(s: &str) {
|
pub fn print(s: &str) {
|
||||||
for byte in s.bytes() {
|
for byte in s.bytes() {
|
||||||
while mmio_read(UART0_FR) & UART0_FR_TXFF != 0 {}
|
while (mmio_read(UART0_FR) & UART0_FR_TXFF) != 0 {
|
||||||
|
unsafe { asm!("nop") }
|
||||||
|
}
|
||||||
mmio_write(UART0_DR, byte as u32);
|
mmio_write(UART0_DR, byte as u32);
|
||||||
}
|
}
|
||||||
// wait till uart is not busy anymore
|
// wait till uart is not busy anymore
|
||||||
while (mmio_read(UART0_FR) >> 3) & 0b1 != 0 {}
|
while ((mmio_read(UART0_FR) >> 3) & 0b1) != 0 {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_u32(mut val: u32) {
|
||||||
|
let mut last_valid = 0;
|
||||||
|
let mut values = [0u32; 10];
|
||||||
|
for (i, c) in (&mut values).iter_mut().enumerate() {
|
||||||
|
if val == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*c = val % 10;
|
||||||
|
val /= 10;
|
||||||
|
if *c != 0 {
|
||||||
|
last_valid = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i, c) in values.iter().enumerate().rev() {
|
||||||
|
if i > last_valid {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let ascii_byte = b'0' + *c as u8;
|
||||||
|
let data = [ascii_byte];
|
||||||
|
|
||||||
|
let s = str::from_utf8(&data).unwrap();
|
||||||
|
print(s);
|
||||||
|
}
|
||||||
|
print("\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize UART peripheral
|
/// Initialize UART peripheral
|
||||||
|
|||||||
15
src/vector.S
15
src/vector.S
@@ -14,14 +14,13 @@ vector_table:
|
|||||||
ventry .
|
ventry .
|
||||||
ventry .
|
ventry .
|
||||||
|
|
||||||
ventry .
|
ventry synchronous_interrupt // Synchronous Exception 0x200
|
||||||
ventry irq_handler // IRQ(Interrupt Request) 0x280
|
ventry irq_handler // IRQ(Interrupt Request) 0x280
|
||||||
ventry .
|
ventry .
|
||||||
ventry .
|
ventry .
|
||||||
|
|
||||||
|
|
||||||
.align 4
|
.align 4
|
||||||
.extern main
|
|
||||||
.global el2_to_el1
|
.global el2_to_el1
|
||||||
el2_to_el1:
|
el2_to_el1:
|
||||||
|
|
||||||
@@ -44,6 +43,16 @@ el2_to_el1:
|
|||||||
adr x0, vector_table
|
adr x0, vector_table
|
||||||
msr VBAR_EL1, x0
|
msr VBAR_EL1, x0
|
||||||
|
|
||||||
|
// Disable MMU
|
||||||
|
ldr x0, =SCTLR_EL1_CONF
|
||||||
|
msr sctlr_el1, x0
|
||||||
|
|
||||||
|
// SIMD should not be trapped
|
||||||
|
mrs x0, CPACR_EL1
|
||||||
|
mov x1, #(0b11<<20)
|
||||||
|
orr x0,x0, x1
|
||||||
|
msr CPACR_EL1,x0
|
||||||
|
|
||||||
isb
|
isb
|
||||||
|
|
||||||
// Return to EL1
|
// Return to EL1
|
||||||
|
|||||||
@@ -10,4 +10,5 @@ qemu-system-aarch64 \
|
|||||||
-serial stdio \
|
-serial stdio \
|
||||||
-sd ../sd.img \
|
-sd ../sd.img \
|
||||||
-display none \
|
-display none \
|
||||||
-kernel ../target/aarch64-unknown-none/debug/kernel8.img
|
-kernel ../target/aarch64-unknown-none/debug/kernel8.img \
|
||||||
|
-s -S
|
||||||
|
|||||||
Reference in New Issue
Block a user