From cf86641937d5351d13bdea7af0866b70ddb48e8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Neuh=C3=A4user?= Date: Sun, 18 May 2025 20:04:58 +0200 Subject: [PATCH] Fix UART output --- .vscode/tasks.json | 2 +- kernel.img | Bin 0 -> 66600 bytes src/main.rs | 94 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 92 insertions(+), 4 deletions(-) create mode 100755 kernel.img diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 0cbd7f7..5428958 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-a72 -display none -kernel ${workspaceFolder}/target/aarch64-unknown-none/debug/nova -s -S", + "command": "qemu-system-aarch64 -M raspi3b -cpu cortex-a53 -display none -kernel ${workspaceFolder}/target/aarch64-unknown-none/debug/nova -s -S -serial stdio", "isBackground": true } ] diff --git a/kernel.img b/kernel.img new file mode 100755 index 0000000000000000000000000000000000000000..eecf22d2cea2a574b1a8376f5940b55b7ed5a3a2 GIT binary patch literal 66600 zcmeIwPj4GV6aetIb`rc%Kq%^g3IUb)BN7p}QC&4T;Y*QHAtWp~M+vo{hXge?sO3V` zTkm`a;K~L0h{RXm%mog)!6z`Y-dUP#X*t00xAN|rdGp@P`e%QA>;3mSMG?)_i65h$ z^%kjNUihx_xMmnT(T!oO#L}X6c~R4>*L@Ln9OQHpBkx|NSJFMmXAg>|zUi+IUaLcT z)*F5J`}9uL=ORFW009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7csf&W)v-aY!Ei1?-#4@bAVr=#9) z-=37)!`a4z*VfDJn3Y@A_~rF-D`tCfI$C`*W~(opj>?S`Q*QH08dvqj>gJ;U=SQPo z-|hagu^jh)n$JHfFAryD^Q$+@GSwAnzdZkb?c)5=^Ut22wbsj}i}h!#t$C|{uX^Wm z=Ra{?>wPv_`|lNXf6~A7tY08m#!~z_Z`ZuCNK~u63rkmWzSqjXp7QJQxW4Jy%=xDN zovI{VSJVAsbYfUEm5X%jJ|%zaDf!!r{FCn={ptArH2Q~=N%SWVj;05PDSkGYp46i{ z#_{K09`p}yZ0{b9cduW&adT&UeP?&;lTW|sUyC>HSD*dK^x$L~M+bM0V}Czww?96< zlSlQ^`NZ9?#`X93ug{99x>x?*sBx+R2idV%UTOw8K9^$E(arNgb{-UU<66!)p|xF9 z>z!utT-?e1f8^Y9iq+Z8+r54Xt4|4y<|I+^# DGVh&P literal 0 HcmV?d00001 diff --git a/src/main.rs b/src/main.rs index d1a7d4e..6aee0e2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,15 +13,33 @@ fn panic(_panic: &PanicInfo) -> ! { loop {} } +const BAUD: u32 = 115200; +const UART_CLK: u32 = 48_000_000; + const UART0_DR: u32 = 0x3F20_1000; +const UART0_FR: u32 = 0x3F20_1018; +const UART0_FR_TXFF: u32 = 1 << 5; + +const UART0_IBRD: u32 = 0x3F20_1024; +const UART0_FBRD: u32 = 0x3F20_1028; + +const UART0_CR: u32 = 0x3F20_1030; +const UART0_CR_UARTEN: u32 = 1 << 0; +const UART0_CR_TXE: u32 = 1 << 8; + +const UART0_LCRH: u32 = 0x3F20_102c; +const UART0_LCRH_FEN: u32 = 1 << 4; +const UART0_LCRH_WLEN: u32 = 11 << 5; + struct Uart; impl Write for Uart { fn write_str(&mut self, s: &str) -> fmt::Result { for byte in s.bytes() { unsafe { - core::ptr::write_volatile(UART0_DR as *mut u8, byte); + while core::ptr::read_volatile(UART0_FR as *const u32) & UART0_FR_TXFF != 0 {} + core::ptr::write_volatile(UART0_DR as *mut u32, byte as u32); } } Ok(()) @@ -36,7 +54,77 @@ pub extern "C" fn _start() -> ! { #[no_mangle] fn main() { + configure_uart(); + delay(50000); let mut uart = Uart {}; - writeln!(uart, "Hello World!\n"); - loop {} + loop { + writeln!(uart, "Hello World!"); + } +} + +pub fn configure_uart() { + let baud_div_times_64 = (UART_CLK * 4) / BAUD; + + let ibrd = baud_div_times_64 / 64; + let fbrd = baud_div_times_64 % 64; + + unsafe { + uart_enable(false); + uart_fifo_enable(false); + + core::ptr::write_volatile(UART0_IBRD as *mut u32, ibrd); + core::ptr::write_volatile(UART0_FBRD as *mut u32, fbrd); + + uart_set_lcrh(0b11, true); + + // Enable transmit and uart + let mut cr = core::ptr::read_volatile(UART0_CR as *mut u32); + cr |= UART0_CR_UARTEN | UART0_CR_TXE; + core::ptr::write_volatile(UART0_CR as *mut u32, cr); + } +} + +fn uart_enable(enable: bool) { + unsafe { + let mut cr = core::ptr::read_volatile(UART0_CR as *mut u32); + + if enable { + cr |= UART0_CR_UARTEN; + } else { + cr &= !UART0_CR_UARTEN; + } + + core::ptr::write_volatile(UART0_CR as *mut u32, cr); + } +} + +fn uart_fifo_enable(enable: bool) { + unsafe { + let mut lcrh = core::ptr::read_volatile(UART0_LCRH as *mut u32); + + if enable { + lcrh |= UART0_LCRH_FEN; + } else { + lcrh &= !UART0_LCRH_FEN; + } + + core::ptr::write_volatile(UART0_LCRH as *mut u32, lcrh); + } +} + +fn uart_set_lcrh(wlen: u32, enable_fifo: bool) { + unsafe { + let mut value = (wlen & 0b11) << 5; + if enable_fifo { + value |= UART0_LCRH_FEN; + } + core::ptr::write_volatile(UART0_LCRH as *mut u32, value); + } +} + +fn delay(count: u32) { + for _ in 0..count { + // Prevent compiler optimizing away the loop + core::sync::atomic::spin_loop_hint(); + } }