diff --git a/.vscode/launch.json b/.vscode/launch.json index 941b38e..bffd237 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,5 +1,12 @@ { "version": "0.2.0", + "compounds": [ + { + "name": "Run QEMU + Attach LLDB", + "configurations": ["Attach LLDB"], + "preLaunchTask": "Run QEMU" + } + ], "configurations": [ { "name": "Attach to QEMU (AArch64)", @@ -12,19 +19,29 @@ "stopAtEntry": true, "externalConsole": false, "MIMode": "gdb", -"setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - }, - { - "description": "Show assembly on stop", - "text": "layout asm", - "ignoreFailures": true - } -], + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "Show assembly on stop", + "text": "set disassemble-next-line on", + "ignoreFailures": true + } + ], "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"] } ] } diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..7a1c1a5 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "lldb.displayFormat": "auto", + "lldb.showDisassembly": "always", + "lldb.dereferencePointers": true, + "lldb.consoleMode": "commands" +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 9445da3..18998f4 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -14,7 +14,7 @@ { "label": "Run QEMU", "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, "dependsOn": ["Build"] } diff --git a/Cargo.toml b/Cargo.toml index 45aea39..c8de713 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,8 @@ edition = "2021" [profile.dev] panic = "abort" +debug = true +opt-level = 0 [profile.release] panic = "abort" diff --git a/firmware_files/fixup.dat b/firmware_files/fixup.dat new file mode 100755 index 0000000..f830300 Binary files /dev/null and b/firmware_files/fixup.dat differ diff --git a/src/irq_interrupt.rs b/src/irq_interrupt.rs index 27b2af8..6d1277f 100644 --- a/src/irq_interrupt.rs +++ b/src/irq_interrupt.rs @@ -3,7 +3,10 @@ use core::{ sync::atomic::{compiler_fence, Ordering}, }; -use crate::{mmio_read, mmio_write, peripherals::uart::print}; +use crate::{ + mmio_read, mmio_write, + peripherals::{gpio::blink_gpio, uart::print}, +}; const INTERRUPT_BASE: u32 = 0x3F00_B000; const IRQ_PENDING_BASE: u32 = INTERRUPT_BASE + 0x204; @@ -35,7 +38,18 @@ unsafe extern "C" fn irq_handler() { handle_gpio_interrupt(); } +#[no_mangle] +unsafe extern "C" fn synchronous_interrupt() { + loop { + let el: u64; + asm!("mrs x5, FAR_EL1"); + blink_gpio(29, 100); + print("Sync Exception \r\n"); + } +} + fn handle_gpio_interrupt() { + print("Interrupt\r\n"); for i in 0..=53u32 { let val = read_gpio_event_detect_status(i); diff --git a/src/mailbox.rs b/src/mailbox.rs index cac50fa..5df8a89 100644 --- a/src/mailbox.rs +++ b/src/mailbox.rs @@ -1,26 +1,33 @@ -use crate::{mmio_read, mmio_write}; +use core::ptr::read_volatile; -const MBOX_BASE: u32 = 0x3F00_B880; +use crate::{ + mmio_read, mmio_write, + peripherals::uart::{print, print_u32}, +}; + +const MBOX_BASE: u32 = 0x3F00_0000 + 0xB880; // MB0 const MBOX_READ: u32 = MBOX_BASE + 0x00; -const MBOX_READ_STATUS: u32 = MBOX_BASE + 0x18; +const MBOX_STATUS: u32 = MBOX_BASE + 0x18; // MB1 const MBOX_WRITE: u32 = MBOX_BASE + 0x20; -const MBOX_WRITE_STATUS: u32 = MBOX_BASE + 0x38; // Status const MAIL_FULL: u32 = 0x80000000; const MAIL_EMPTY: u32 = 0x40000000; -#[repr(align(16))] +#[repr(C, align(16))] struct MailboxBuffer([u32; 36]); +#[no_mangle] +static mut MBOX: MailboxBuffer = MailboxBuffer([0; 36]); + pub fn read_mailbox(channel: u32) -> u32 { // Wait until mailbox is not empty loop { - while (mmio_read(MBOX_READ_STATUS) & MAIL_EMPTY != 0) {} + while mmio_read(MBOX_STATUS) & MAIL_EMPTY != 0 {} let mut data = mmio_read(MBOX_READ); let read_channel = data & 0xF; @@ -33,25 +40,35 @@ pub fn read_mailbox(channel: u32) -> u32 { } pub fn write_mailbox(channel: u32, data: u32) { - while (mmio_read(MBOX_WRITE_STATUS) & MAIL_FULL != 0) {} - mmio_write(MBOX_WRITE, data << 4 | (channel & 0xF)); + while mmio_read(MBOX_STATUS) & MAIL_FULL != 0 {} + mmio_write(MBOX_WRITE, (data & !0xF) | (channel & 0xF)); } pub fn read_soc_temp() -> u32 { - let mut mbox = MailboxBuffer([0; 36]); + unsafe { + // MBOX.0[0] = 7 * 4; // Total size in bytes + // MBOX.0[1] = 0; // Request + // MBOX.0[2] = 0x00010002; // Tag + // MBOX.0[3] = 4; // Maximum buffer lenb + // MBOX.0[4] = 0; // Request length + // MBOX.0[5] = 0; // Value Buffer + // MBOX.0[6] = 0; // End + // core::arch::asm!("dsb sy"); // Ensure write reaches RAM + // core::arch::asm!("dmb sy"); // Memory barrier - mbox.0[0] = 8 * 4; // Total size in bytes - mbox.0[1] = 0; // Request - mbox.0[2] = 0x00030006; // Tag: Get temperature - mbox.0[3] = 8; // Value buffer size (bytes) - mbox.0[4] = 4; // Request size (bytes) - mbox.0[5] = 0; // Temp ID: 0 = SoC - mbox.0[6] = 0; // Response will be written here - mbox.0[7] = 0; // End tag + print("Reading address\r\n"); + //let addr = core::ptr::addr_of!(MBOX.0[0]); - let addr = &mbox.0 as *const u32 as u32; - write_mailbox(8, addr); - let _ = read_mailbox(8); - let raw_temp = mbox.0[6]; - raw_temp / 1000 + print("Write address\r\n"); + + // write_mailbox(8, addr); + + let _ = read_mailbox(8); + + if MBOX.0[1] == 0 { + print("Failed\r\n"); + } + let raw_temp = MBOX.0[5]; + raw_temp + } } diff --git a/src/main.rs b/src/main.rs index a5d19ad..69d9316 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ use core::{ arch::{asm, global_asm}, panic::PanicInfo, + ptr::write_volatile, }; use nova::{ @@ -12,18 +13,19 @@ use nova::{ mailbox::read_soc_temp, peripherals::{ gpio::{ - gpio_get_state, gpio_high, gpio_low, gpio_pull_up, set_falling_edge_detect, - set_gpio_function, GPIOFunction, + blink_gpio, gpio_pull_up, set_falling_edge_detect, set_gpio_function, GPIOFunction, }, - 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")); extern "C" { fn el2_to_el1(); + static mut __bss_start: u32; + static mut __bss_end: u32; } #[panic_handler] @@ -47,6 +49,9 @@ pub unsafe extern "C" fn _start() { #[no_mangle] pub extern "C" fn main() -> ! { + unsafe { + zero_bss(); + } enable_uart(); // Set ACT Led to Outout @@ -59,14 +64,24 @@ pub extern "C" fn main() -> ! { print("Hello World!\r\n"); unsafe { + asm!("mrs x0, SCTLR_EL1"); el2_to_el1(); } 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] pub extern "C" fn kernel_main() -> ! { + print("AAA\r\n"); print_current_el_str(); sleep_us(500_000); @@ -78,38 +93,13 @@ pub extern "C" fn kernel_main() -> ! { set_falling_edge_detect(26, true); loop { - //let temp = read_soc_temp(); - //u32_to_ascii(temp as u8); + let temp = read_soc_temp(); + print_u32(temp); - let _ = gpio_high(29); - - sleep_ms(500); // 0.5s - let _ = gpio_low(29); - sleep_ms(500); // 0.5s - print_gpio_state(); + blink_gpio(29, 500); } } -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"); -} - -fn u32_to_ascii(val: u8) { - let ascii_byte = b'0' + val; - let data = [ascii_byte]; - - let s = str::from_utf8(&data).unwrap(); - print(s); - print("C\r\n"); -} - pub fn get_current_el() -> u64 { let el: u64; unsafe { diff --git a/src/peripherals/gpio.rs b/src/peripherals/gpio.rs index c283148..5e39716 100644 --- a/src/peripherals/gpio.rs +++ b/src/peripherals/gpio.rs @@ -1,7 +1,7 @@ use core::result::Result; use core::result::Result::Ok; -use crate::timer::delay_nops; +use crate::timer::{delay_nops, sleep_ms}; use crate::{mmio_read, mmio_write}; const GPFSEL_BASE: u32 = 0x3F20_0000; @@ -164,3 +164,11 @@ pub fn set_rising_edge_detect(gpio: u8, enable: bool) { 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); +} diff --git a/src/peripherals/uart.rs b/src/peripherals/uart.rs index 1ad0fd2..3fda269 100644 --- a/src/peripherals/uart.rs +++ b/src/peripherals/uart.rs @@ -1,3 +1,5 @@ +use core::{arch::asm, fmt}; + use crate::{mmio_read, mmio_write}; const BAUD: u32 = 115200; @@ -21,11 +23,34 @@ const UART0_LCRH_FEN: u32 = 1 << 4; /// Print `s` over UART pub fn print(s: &str) { 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); } // 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 values = [0u32; 10]; + for c in &mut values { + if val == 0 { + break; + } + + *c = val % 10; + val /= 10; + } + + for c in values.iter().rev() { + 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 diff --git a/src/vector.S b/src/vector.S index 1e125a6..d8562db 100644 --- a/src/vector.S +++ b/src/vector.S @@ -14,8 +14,8 @@ vector_table: ventry . ventry . - ventry . - ventry irq_handler // IRQ(Interrupt Request) 0x280 + ventry synchronous_interrupt // Synchronous Exception 0x200 + ventry irq_handler // IRQ(Interrupt Request) 0x280 ventry . ventry . @@ -44,6 +44,11 @@ el2_to_el1: adr x0, vector_table msr VBAR_EL1, x0 + // Disable MMU + mrs x0, sctlr_el1 + bic x0, x0, #1 + msr sctlr_el1, x0 + isb // Return to EL1 diff --git a/tools/start_simulator_debug.sh b/tools/start_simulator_debug.sh index 5c75ea3..17e9660 100755 --- a/tools/start_simulator_debug.sh +++ b/tools/start_simulator_debug.sh @@ -10,4 +10,5 @@ qemu-system-aarch64 \ -serial stdio \ -sd ../sd.img \ -display none \ - -kernel ../target/aarch64-unknown-none/debug/kernel8.img + -kernel ../target/aarch64-unknown-none/debug/kernel8.img \ + -s -S