diff --git a/src/framebuffer.rs b/src/framebuffer.rs index 544231d..b906047 100644 --- a/src/framebuffer.rs +++ b/src/framebuffer.rs @@ -4,7 +4,10 @@ mod bitmaps; use bitmaps::BASIC_LEGACY; -use crate::mailbox::{read_mailbox, write_mailbox}; +use crate::{ + mailbox::{read_mailbox, write_mailbox}, + println, +}; #[repr(align(16))] struct Mailbox([u32; 36]); diff --git a/src/interrupt_handlers.rs b/src/interrupt_handlers.rs new file mode 100644 index 0000000..a48b468 --- /dev/null +++ b/src/interrupt_handlers.rs @@ -0,0 +1,240 @@ +use core::arch::asm; + +use crate::{ + get_current_el, + interrupt_handlers::daif::unmask_irq, + peripherals::gpio::{read_gpio_event_detect_status, reset_gpio_event_detect_status}, + println, read_address, write_address, +}; + +const INTERRUPT_BASE: u32 = 0x3F00_B000; +const IRQ_PENDING_BASE: u32 = INTERRUPT_BASE + 0x204; +const ENABLE_IRQ_BASE: u32 = INTERRUPT_BASE + 0x210; +const DISABLE_IRQ_BASE: u32 = INTERRUPT_BASE + 0x21C; + +const GPIO_PENDING_BIT_OFFSET: u64 = 0b1111 << 49; + +#[repr(u32)] +pub enum IRQSource { + AuxInt = 29, + I2cSpiSlvInt = 44, + Pwa0 = 45, + Pwa1 = 46, + Smi = 48, + GpioInt0 = 49, + GpioInt1 = 50, + GpioInt2 = 51, + GpioInt3 = 52, + I2cInt = 53, + SpiInt = 54, + PcmInt = 55, + UartInt = 57, +} + +/// Representation of the ESR_ELx registers +/// +/// Reference: D1.10.4 +#[derive(Debug, Clone, Copy)] +#[allow(dead_code)] +struct EsrElX { + ec: u32, + il: u32, + iss: u32, +} + +impl From for EsrElX { + fn from(value: u32) -> Self { + Self { + ec: value >> 26, + il: (value >> 25) & 0b1, + iss: value & 0x1FFFFFF, + } + } +} + +#[no_mangle] +unsafe extern "C" fn rust_irq_handler() { + daif::mask_all(); + let pending_irqs = get_irq_pending_sources(); + + if pending_irqs & GPIO_PENDING_BIT_OFFSET != 0 { + handle_gpio_interrupt(); + } + let source_el = get_exception_return_exception_level() >> 2; + println!("Source EL: {}", source_el); + println!("Current EL: {}", get_current_el()); + println!("Return register address: {:#x}", get_elr_el1()); +} + +#[no_mangle] +unsafe extern "C" fn rust_synchronous_interrupt_no_el_change() { + daif::mask_all(); + + let source_el = get_exception_return_exception_level() >> 2; + println!("--------Sync Exception in EL{}--------", source_el); + println!("No EL change"); + println!("Current EL: {}", get_current_el()); + println!("{:?}", EsrElX::from(get_esr_el1())); + println!("Return register address: {:#x}", get_elr_el1()); + println!("-------------------------------------"); +} + +/// Synchronous Exception Handler +/// +/// Lower Exception level, where the implemented level +/// immediately lower than the target level is using +/// AArch64. +#[no_mangle] +unsafe extern "C" fn rust_synchronous_interrupt_imm_lower_aarch64() { + daif::mask_all(); + + let source_el = get_exception_return_exception_level() >> 2; + println!("--------Sync Exception in EL{}--------", source_el); + println!("Exception escalated to EL {}", get_current_el()); + println!("Current EL: {}", get_current_el()); + let esr = EsrElX::from(get_esr_el1()); + println!("{:?}", EsrElX::from(esr)); + println!("Return register address: {:#x}", get_elr_el1()); + + match esr.ec { + 0b100100 => { + println!("Cause: Data Abort from a lower Exception level"); + } + _ => {} + } + println!("-------------------------------------"); + + set_return_to_kernel_main(); +} + +fn set_return_to_kernel_main() { + unsafe { + asm!("ldr x0, =kernel_main", "msr ELR_EL1, x0"); + asm!("mov x0, #(0b0101)", "msr SPSR_EL1, x0"); + } +} + +fn get_exception_return_exception_level() -> u32 { + let spsr: u32; + unsafe { + asm!("mrs {0:x}, SPSR_EL1", out(reg) spsr); + } + spsr & 0b1111 +} + +/// Read the syndrome information that caused an exception +/// +/// ESR = Exception Syndrome Register +fn get_esr_el1() -> u32 { + let esr: u32; + unsafe { + asm!( + "mrs {esr:x}, ESR_EL1", + esr = out(reg) esr + ); + } + esr +} + +/// Read the return address +/// +/// ELR = Exception Link Registers +fn get_elr_el1() -> u32 { + let elr: u32; + unsafe { + asm!( + "mrs {esr:x}, ELR_EL1", + esr = out(reg) elr + ); + } + elr +} + +fn handle_gpio_interrupt() { + println!("Interrupt"); + for i in 0..=53u32 { + let val = read_gpio_event_detect_status(i); + + if val { + #[allow(clippy::single_match)] + match i { + 26 => { + println!("Button Pressed"); + } + _ => {} + } + // Reset GPIO Interrupt handler by writing a 1 + reset_gpio_event_detect_status(i); + } + } + unmask_irq(); +} + +/// Enables IRQ Source +pub fn enable_irq_source(state: IRQSource) { + let nr = state as u32; + let register = ENABLE_IRQ_BASE + 4 * (nr / 32); + let register_offset = nr % 32; + let current = unsafe { read_address(register) }; + let mask = 0b1 << register_offset; + let new_val = current | mask; + unsafe { write_address(register, new_val) }; +} + +/// Disable IRQ Source +pub fn disable_irq_source(state: IRQSource) { + let nr = state as u32; + let register = DISABLE_IRQ_BASE + 4 * (nr / 32); + let register_offset = nr % 32; + let current = unsafe { read_address(register) }; + let mask = 0b1 << register_offset; + let new_val = current | mask; + unsafe { write_address(register, new_val) }; +} + +/// Read current IRQ Source status +pub fn read_irq_source_status(state: IRQSource) -> u32 { + let nr = state as u32; + let register = ENABLE_IRQ_BASE + 4 * (nr / 32); + let register_offset = nr % 32; + (unsafe { read_address(register) } >> register_offset) & 0b1 +} + +/// Status if a IRQ Source is pending +pub fn is_irq_source_pending(state: IRQSource) -> bool { + let nr = state as u32; + let register = IRQ_PENDING_BASE + 4 * (nr / 32); + let register_offset = nr % 32; + ((unsafe { read_address(register) } >> register_offset) & 0b1) != 0 +} + +/// Status if a IRQ Source is pending +pub fn get_irq_pending_sources() -> u64 { + let mut pending = unsafe { read_address(IRQ_PENDING_BASE + 4) as u64 } << 32; + pending |= unsafe { read_address(IRQ_PENDING_BASE) as u64 }; + pending +} + +pub mod daif { + use core::arch::asm; + + #[inline(always)] + pub fn mask_all() { + unsafe { asm!("msr DAIFSet, #0xf", options(nomem, nostack)) } + } + + #[inline(always)] + pub fn unmask_all() { + unsafe { asm!("msr DAIFClr, #0xf", options(nomem, nostack)) } + } + + #[inline(always)] + pub fn mask_irq() { + unsafe { asm!("msr DAIFSet, #0x2", options(nomem, nostack)) } + } + + #[inline(always)] + pub fn unmask_irq() { + unsafe { asm!("msr DAIFClr, #0x2", options(nomem, nostack)) } + } +} diff --git a/src/lib.rs b/src/lib.rs index 7a0b173..ad704cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,14 +1,21 @@ #![no_std] #![allow(clippy::missing_safety_doc)] + +extern crate alloc; + +use alloc::boxed::Box; use core::{ arch::asm, + fmt, panic::PanicInfo, ptr::{read_volatile, write_volatile}, }; use heap::Heap; -pub static PERIPHERAL_BASE: u32 = 0x3F00_0000; +use crate::logger::{DefaultLogger, Logger}; + +static PERIPHERAL_BASE: u32 = 0x3F00_0000; unsafe extern "C" { unsafe static mut __heap_start: u8; @@ -33,37 +40,23 @@ fn panic(_panic: &PanicInfo) -> ! { } } -#[macro_export] -macro_rules! print { - () => {}; - ($($arg:tt)*) => { - $crate::peripherals::uart::_print(format_args!($($arg)*)) - }; -} - -#[macro_export] -macro_rules! println { - () => {}; - ($($arg:tt)*) => { - print!($($arg)*); - print!("\r\n"); - }; -} - pub mod peripherals; pub mod configuration; pub mod framebuffer; -pub mod irq_interrupt; +pub mod interrupt_handlers; +pub mod logger; pub mod mailbox; pub mod power_management; pub mod timer; -pub fn mmio_read(address: u32) -> u32 { +#[inline(always)] +pub unsafe fn read_address(address: u32) -> u32 { unsafe { read_volatile(address as *const u32) } } -pub fn mmio_write(address: u32, data: u32) { +#[inline(always)] +pub unsafe fn write_address(address: u32, data: u32) { unsafe { write_volatile(address as *mut u32, data) } } @@ -78,3 +71,7 @@ pub fn get_current_el() -> u64 { } el >> 2 } + +pub fn initialize_kernel() { + logger::set_logger(Box::new(DefaultLogger)); +} diff --git a/src/logger.rs b/src/logger.rs new file mode 100644 index 0000000..22beeae --- /dev/null +++ b/src/logger.rs @@ -0,0 +1,50 @@ +use core::fmt::Write; + +use alloc::{boxed::Box, fmt}; + +use crate::peripherals::uart; + +static mut LOGGER: Option> = None; + +pub trait Logger: Write + Sync {} + +pub struct DefaultLogger; + +impl Logger for DefaultLogger {} + +impl Write for DefaultLogger { + fn write_str(&mut self, s: &str) -> core::fmt::Result { + uart::write_str(s) + } +} + +#[macro_export] +macro_rules! print { + () => {}; + ($($arg:tt)*) => { + $crate::logger::_print(format_args!($($arg)*)) + }; +} + +pub fn _print(args: fmt::Arguments) { + unsafe { + if let Some(logger) = LOGGER.as_mut() { + logger.write_fmt(args); + } + } +} + +#[macro_export] +macro_rules! println { + () => {}; + ($($arg:tt)*) => { + $crate::print!($($arg)*); + $crate::print!("\r\n"); + }; +} + +pub fn set_logger(logger: Box) { + unsafe { + LOGGER = Some(logger); + } +} diff --git a/src/mailbox.rs b/src/mailbox.rs index cdbdf7c..c586684 100644 --- a/src/mailbox.rs +++ b/src/mailbox.rs @@ -1,4 +1,4 @@ -use crate::{mmio_read, mmio_write}; +use crate::{read_address, write_address}; use nova_error::NovaError; const MBOX_BASE: u32 = 0x3F00_0000 + 0xB880; @@ -67,8 +67,8 @@ mailbox_command!(get_display_resolution, 0x0004_0003, 0, 8); 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); + while unsafe { read_address(MBOX_STATUS) } & MAIL_EMPTY != 0 {} + let mut data = unsafe { read_address(MBOX_READ) }; let read_channel = data & 0xF; data >>= 4; @@ -80,6 +80,6 @@ pub fn read_mailbox(channel: u32) -> u32 { } pub fn write_mailbox(channel: u32, data: u32) { - while mmio_read(MBOX_STATUS) & MAIL_FULL != 0 {} - mmio_write(MBOX_WRITE, (data & !0xF) | (channel & 0xF)); + while unsafe { read_address(MBOX_STATUS) } & MAIL_FULL != 0 {} + unsafe { write_address(MBOX_WRITE, (data & !0xF) | (channel & 0xF)) }; } diff --git a/src/main.rs b/src/main.rs index 99e12e4..9076bce 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,18 +14,22 @@ use alloc::boxed::Box; use nova::{ framebuffer::{FrameBuffer, BLUE, GREEN, RED}, get_current_el, init_heap, - irq_interrupt::{daif, enable_irq_source}, + interrupt_handlers::{daif, enable_irq_source, IRQSource}, mailbox, peripherals::{ gpio::{ blink_gpio, gpio_pull_up, set_falling_edge_detect, set_gpio_function, GPIOFunction, SpecificGpio, }, - uart::uart_init, + uart::{read_uart_data, uart_init}, }, print, println, }; +use crate::uart_term::Terminal; + +mod uart_term; + global_asm!(include_str!("vector.S")); extern "C" { @@ -79,6 +83,7 @@ unsafe fn zero_bss() { #[no_mangle] pub extern "C" fn kernel_main() -> ! { + nova::initialize_kernel(); println!("Kernel Main"); println!("Exception Level: {}", get_current_el()); daif::unmask_all(); @@ -97,11 +102,13 @@ pub extern "C" fn el0() -> ! { println!("Jumped into EL0"); // Set GPIO 26 to Input - enable_irq_source(nova::irq_interrupt::IRQState::GpioInt0); //26 is on the first GPIO bank + enable_irq_source(IRQSource::GpioInt0); //26 is on the first GPIO bank let _ = set_gpio_function(26, GPIOFunction::Input); gpio_pull_up(26); set_falling_edge_detect(26, true); + enable_irq_source(IRQSource::UartInt); + let fb = FrameBuffer::default(); fb.draw_square(500, 500, 600, 700, RED); @@ -113,6 +120,7 @@ pub extern "C" fn el0() -> ! { fb.draw_function(cos, 100, 101, RED); loop { + read_uart_data(); let temp = mailbox::read_soc_temp([0]).unwrap(); println!("{} °C", temp[1] / 1000); @@ -128,8 +136,8 @@ fn cos(x: u32) -> f64 { } fn enable_uart() { - uart_init(); // Set GPIO Pins to UART let _ = set_gpio_function(14, GPIOFunction::Alternative0); let _ = set_gpio_function(15, GPIOFunction::Alternative0); + uart_init(); } diff --git a/src/peripherals/gpio.rs b/src/peripherals/gpio.rs index 3f4de8a..f9f5303 100644 --- a/src/peripherals/gpio.rs +++ b/src/peripherals/gpio.rs @@ -3,7 +3,7 @@ use core::result::Result::Ok; use core::sync::atomic::{compiler_fence, Ordering}; use crate::timer::{delay_nops, sleep_ms}; -use crate::{mmio_read, mmio_write}; +use crate::{read_address, write_address}; const GPFSEL_BASE: u32 = 0x3F20_0000; const GPSET_BASE: u32 = 0x3F20_001C; @@ -37,14 +37,14 @@ pub fn set_gpio_function(gpio: u8, state: GPIOFunction) -> Result<(), &'static s let register_index = gpio / 10; let register_offset = (gpio % 10) * 3; let register_addr = GPFSEL_BASE + (register_index as u32 * 4); - let current = mmio_read(register_addr); + let current = unsafe { read_address(register_addr) }; let mask = !(0b111 << register_offset); let cleared = current & mask; let new_val = cleared | ((state as u32) << register_offset); - mmio_write(register_addr, new_val); + unsafe { write_address(register_addr, new_val) }; Ok(()) } @@ -57,7 +57,7 @@ pub fn gpio_high(gpio: u8) -> Result<(), &'static str> { let register_offset = gpio % 32; let register_addr = GPSET_BASE + (register_index as u32 * 4); - mmio_write(register_addr, 1 << register_offset); + unsafe { write_address(register_addr, 1 << register_offset) }; Ok(()) } @@ -69,7 +69,7 @@ pub fn gpio_low(gpio: u8) -> Result<(), &'static str> { let register_offset = gpio % 32; let register_addr = GPCLR_BASE + (register_index as u32 * 4); - mmio_write(register_addr, 1 << register_offset); + unsafe { write_address(register_addr, 1 << register_offset) }; Ok(()) } @@ -79,7 +79,7 @@ pub fn gpio_get_state(gpio: u8) -> u8 { let register_offset = gpio % 32; let register_addr = GPLEV_BASE + (register_index as u32 * 4); - let state = mmio_read(register_addr); + let state = unsafe { read_address(register_addr) }; ((state >> register_offset) & 0b1) as u8 } @@ -103,23 +103,23 @@ fn gpio_pull_up_down(gpio: u8, val: u32) { let register_offset = gpio % 32; // 1. Write Pull up - mmio_write(GPPUD, val); + unsafe { write_address(GPPUD, val) }; // 2. Delay 150 cycles delay_nops(150); // 3. Write to clock let new_val = 0b1 << register_offset; - mmio_write(register_addr, new_val); + unsafe { write_address(register_addr, new_val) }; // 4. Delay 150 cycles delay_nops(150); // 5. reset GPPUD - mmio_write(GPPUD, 0); + unsafe { write_address(GPPUD, 0) }; // 6. reset clock - mmio_write(register_addr, 0); + unsafe { write_address(register_addr, 0) }; } /// Get the current status of the falling edge detection @@ -127,7 +127,7 @@ pub fn read_falling_edge_detect(gpio: u8) -> bool { let register_addr = GPFEN_BASE + 4 * (gpio as u32 / 32); let register_offset = gpio % 32; - let current = mmio_read(register_addr); + let current = unsafe { read_address(register_addr) }; ((current >> register_offset) & 0b1) != 0 } @@ -136,7 +136,7 @@ pub fn read_rising_edge_detect(gpio: u8) -> bool { let register_addr = GPREN_BASE + 4 * (gpio as u32 / 32); let register_offset = gpio % 32; - let current = mmio_read(register_addr); + let current = unsafe { read_address(register_addr) }; ((current >> register_offset) & 0b1) != 0 } @@ -145,7 +145,7 @@ pub fn set_falling_edge_detect(gpio: u8, enable: bool) { let register_addr = GPFEN_BASE + 4 * (gpio as u32 / 32); let register_offset = gpio % 32; - let current = mmio_read(register_addr); + let current = unsafe { read_address(register_addr) }; let mask = 0b1 << register_offset; let new_val = if enable { current | mask @@ -153,7 +153,7 @@ pub fn set_falling_edge_detect(gpio: u8, enable: bool) { current & !mask }; - mmio_write(register_addr, new_val); + unsafe { write_address(register_addr, new_val) }; } /// Enables rising edge detection @@ -161,7 +161,7 @@ pub fn set_rising_edge_detect(gpio: u8, enable: bool) { let register_addr = GPREN_BASE + 4 * (gpio as u32 / 32); let register_offset = gpio % 32; - let current = mmio_read(register_addr); + let current = unsafe { read_address(register_addr) }; let mask = 0b1 << register_offset; let new_val = if enable { @@ -170,7 +170,7 @@ pub fn set_rising_edge_detect(gpio: u8, enable: bool) { current & !mask }; - mmio_write(register_addr, new_val); + unsafe { write_address(register_addr, new_val) }; } /// Returns with the interrupt status of an GPIO. @@ -181,7 +181,7 @@ pub fn read_gpio_event_detect_status(id: u32) -> bool { let register = GPEDS_BASE + (id / 32) * 4; let register_offset = id % 32; - let val = mmio_read(register) >> register_offset; + let val = unsafe { read_address(register) } >> register_offset; (val & 0b1) != 0 } @@ -190,7 +190,7 @@ pub fn reset_gpio_event_detect_status(id: u32) { let register = GPEDS_BASE + (id / 32) * 4; let register_offset = id % 32; - mmio_write(register, 0b1 << register_offset); + unsafe { write_address(register, 0b1 << register_offset) }; compiler_fence(Ordering::SeqCst); } diff --git a/src/peripherals/uart.rs b/src/peripherals/uart.rs index 93eec3a..51aa82c 100644 --- a/src/peripherals/uart.rs +++ b/src/peripherals/uart.rs @@ -3,7 +3,7 @@ use core::{ fmt::{self, Write}, }; -use crate::{mmio_read, mmio_write}; +use crate::{println, read_address, write_address}; const BAUD: u32 = 115200; const UART_CLK: u32 = 48_000_000; @@ -18,35 +18,14 @@ const UART0_FBRD: u32 = 0x3F20_1028; const UART0_CR: u32 = 0x3F20_1030; const UART0_CR_UARTEN: u32 = 1 << 0; + +const UART0_CR_LBE: u32 = 1 << 7; const UART0_CR_TXE: u32 = 1 << 8; +const UART0_CR_RXE: u32 = 1 << 9; const UART0_LCRH: u32 = 0x3F20_102C; const UART0_LCRH_FEN: u32 = 1 << 4; -pub struct Uart; - -impl Write for Uart { - fn write_str(&mut self, s: &str) -> core::fmt::Result { - for byte in s.bytes() { - 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 {} - Ok(()) - } -} - -pub fn _print(args: fmt::Arguments) { - let _ = Uart.write_fmt(args); -} - -pub fn _print_str(st: &str) { - let _ = Uart.write_str(st); -} - /// Initialize UART peripheral pub fn uart_init() { let baud_div_times_64 = (UART_CLK * 4) / BAUD; @@ -55,23 +34,25 @@ pub fn uart_init() { let fbrd = baud_div_times_64 % 64; uart_enable(false); - uart_fifo_enable(false); + uart_fifo_enable(true); - mmio_write(UART0_IBRD, ibrd); - mmio_write(UART0_FBRD, fbrd); + unsafe { + write_address(UART0_IBRD, ibrd); + write_address(UART0_FBRD, fbrd); + } uart_set_lcrh(0b11, true); - // Enable transmit and uart - let mut cr = mmio_read(UART0_CR); - cr |= UART0_CR_UARTEN | UART0_CR_TXE; + // Enable transmit, receive and uart + let mut cr = unsafe { read_address(UART0_CR) }; + cr |= UART0_CR_UARTEN | UART0_CR_TXE | UART0_CR_RXE; - mmio_write(UART0_CR, cr); + unsafe { write_address(UART0_CR, cr) }; } /// Enable UARTEN fn uart_enable(enable: bool) { - let mut cr = mmio_read(UART0_CR); + let mut cr = unsafe { read_address(UART0_CR) }; if enable { cr |= UART0_CR_UARTEN; @@ -79,12 +60,12 @@ fn uart_enable(enable: bool) { cr &= !UART0_CR_UARTEN; } - mmio_write(UART0_CR, cr); + unsafe { write_address(UART0_CR, cr) }; } /// Enable UART FIFO fn uart_fifo_enable(enable: bool) { - let mut lcrh = mmio_read(UART0_LCRH); + let mut lcrh = unsafe { read_address(UART0_LCRH) }; if enable { lcrh |= UART0_LCRH_FEN; @@ -92,7 +73,7 @@ fn uart_fifo_enable(enable: bool) { lcrh &= !UART0_LCRH_FEN; } - mmio_write(UART0_LCRH, lcrh); + unsafe { write_address(UART0_LCRH, lcrh) }; } /// Set UART word length and set FIFO status @@ -101,5 +82,24 @@ fn uart_set_lcrh(wlen: u32, enable_fifo: bool) { if enable_fifo { value |= UART0_LCRH_FEN; } - mmio_write(UART0_LCRH, value); + unsafe { write_address(UART0_LCRH, value) }; +} + +pub fn read_uart_data() { + println!( + "{:?}", + (unsafe { read_address(UART0_DR) } & 0xFF) as u8 as char + ); +} + +pub fn write_str(s: &str) -> core::fmt::Result { + for byte in s.bytes() { + while (unsafe { read_address(UART0_FR) } & UART0_FR_TXFF) != 0 { + unsafe { asm!("nop") } + } + unsafe { write_address(UART0_DR, byte as u32) }; + } + // wait till uart is not busy anymore + while ((unsafe { read_address(UART0_FR) } >> 3) & 0b1) != 0 {} + Ok(()) } diff --git a/src/uart_term.rs b/src/uart_term.rs new file mode 100644 index 0000000..39a3ac8 --- /dev/null +++ b/src/uart_term.rs @@ -0,0 +1,17 @@ +use core::fmt::Write; + +use nova::logger::Logger; + +/// Goals: +/// - I want to have a functional terminal over uart +/// - It shall continue to log + +pub struct Terminal {} + +impl Write for Terminal { + fn write_str(&mut self, s: &str) -> core::fmt::Result { + Ok(()) + } +} + +impl Logger for Terminal {} diff --git a/tools/start_simulator.sh b/tools/start_simulator.sh index 0955560..b0942b2 100755 --- a/tools/start_simulator.sh +++ b/tools/start_simulator.sh @@ -6,6 +6,6 @@ llvm-objcopy -O binary ../target/aarch64-unknown-none/release/nova ../target/aar qemu-system-aarch64 \ -M raspi3b \ -cpu cortex-a53 \ - -serial stdio \ + -serial pty \ -sd ../sd.img \ -kernel ../target/aarch64-unknown-none/release/kernel8.img