mirror of
https://github.com/iceHtwoO/novaOS.git
synced 2026-04-16 20:22:26 +00:00
151 lines
3.1 KiB
Rust
151 lines
3.1 KiB
Rust
use core::arch::asm;
|
|
|
|
use crate::{mmio_read, mmio_write};
|
|
|
|
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;
|
|
|
|
/// Print `s` over UART
|
|
pub fn print(s: &str) {
|
|
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 {}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
pub fn print_u32_hex(mut val: u32) {
|
|
let mut last_valid = 0;
|
|
let mut values = [0u32; 8];
|
|
for (i, c) in (&mut values).iter_mut().enumerate() {
|
|
if val == 0 {
|
|
break;
|
|
}
|
|
|
|
*c = val % 16;
|
|
val /= 16;
|
|
if *c != 0 {
|
|
last_valid = i;
|
|
}
|
|
}
|
|
|
|
for (i, c) in values.iter().enumerate().rev() {
|
|
if i > last_valid {
|
|
continue;
|
|
}
|
|
|
|
let ascii_byte = if *c < 10 {
|
|
b'0' + *c as u8
|
|
} else {
|
|
b'A' - 10 + *c as u8
|
|
};
|
|
|
|
let data = [ascii_byte];
|
|
|
|
let s = str::from_utf8(&data).unwrap();
|
|
print(s);
|
|
}
|
|
}
|
|
|
|
/// Initialize UART peripheral
|
|
pub fn uart_init() {
|
|
let baud_div_times_64 = (UART_CLK * 4) / BAUD;
|
|
|
|
let ibrd = baud_div_times_64 / 64;
|
|
let fbrd = baud_div_times_64 % 64;
|
|
|
|
uart_enable(false);
|
|
uart_fifo_enable(false);
|
|
|
|
mmio_write(UART0_IBRD, ibrd);
|
|
mmio_write(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;
|
|
|
|
mmio_write(UART0_CR, cr);
|
|
}
|
|
|
|
/// Enable UARTEN
|
|
fn uart_enable(enable: bool) {
|
|
let mut cr = mmio_read(UART0_CR);
|
|
|
|
if enable {
|
|
cr |= UART0_CR_UARTEN;
|
|
} else {
|
|
cr &= !UART0_CR_UARTEN;
|
|
}
|
|
|
|
mmio_write(UART0_CR, cr);
|
|
}
|
|
|
|
/// Enable UART FIFO
|
|
fn uart_fifo_enable(enable: bool) {
|
|
let mut lcrh = mmio_read(UART0_LCRH);
|
|
|
|
if enable {
|
|
lcrh |= UART0_LCRH_FEN;
|
|
} else {
|
|
lcrh &= !UART0_LCRH_FEN;
|
|
}
|
|
|
|
mmio_write(UART0_LCRH, lcrh);
|
|
}
|
|
|
|
/// Set UART word length and set FIFO status
|
|
fn uart_set_lcrh(wlen: u32, enable_fifo: bool) {
|
|
let mut value = (wlen & 0b11) << 5;
|
|
if enable_fifo {
|
|
value |= UART0_LCRH_FEN;
|
|
}
|
|
mmio_write(UART0_LCRH, value);
|
|
}
|