Add rx ability to uart
This commit is contained in:
parent
5490a2ffd6
commit
41a450393e
34
Cargo.lock
generated
34
Cargo.lock
generated
|
@ -2,6 +2,40 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "riscv-uefi"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"spinning_top",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "spinning_top"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
|
|
@ -4,3 +4,4 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
spinning_top = "0.3.0"
|
||||
|
|
28
src/main.rs
28
src/main.rs
|
@ -22,6 +22,19 @@ unsafe extern "C" fn _start() -> ! {
|
|||
// set the stack pointer
|
||||
"la sp, _init_stack_top",
|
||||
|
||||
"la sp, _init_stack_top",
|
||||
|
||||
// clear the BSS
|
||||
"la t0, _bss_start",
|
||||
"la t1, _bss_end",
|
||||
"bgeu t0, t1, 2f",
|
||||
"1:",
|
||||
"sb zero, 0(t0)",
|
||||
"addi t0, t0, 1",
|
||||
"bne t0, t1, 1b",
|
||||
"2:",
|
||||
// BSS is clear!
|
||||
|
||||
// "tail-call" to {entry} (call without saving a return address)
|
||||
"tail {entry}",
|
||||
entry = sym entry, // {entry} refers to the function [entry] below
|
||||
|
@ -30,13 +43,16 @@ unsafe extern "C" fn _start() -> ! {
|
|||
}
|
||||
|
||||
extern "C" fn entry() -> ! {
|
||||
// UNSAFE: correct address for QEMU virt device
|
||||
let mut console = unsafe { uart::Device::new(0x1000_0000) };
|
||||
for byte in "Hello, world!".bytes() {
|
||||
console.put(byte);
|
||||
}
|
||||
println!("This should not print because the console is not initialised.");
|
||||
unsafe { uart::init_console(0x1000_0000) };
|
||||
println!("Hello, world!");
|
||||
|
||||
loop {}
|
||||
loop {
|
||||
let c = uart::CONSOLE.lock().as_mut().and_then(uart::Device::get);
|
||||
if let Some(c) = c {
|
||||
print!("{}", c as char);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
|
|
55
src/uart.rs
55
src/uart.rs
|
@ -1,5 +1,9 @@
|
|||
//! This module provides access to the UART console.
|
||||
|
||||
use spinning_top::Spinlock;
|
||||
|
||||
pub static CONSOLE: Spinlock<Option<Device>> = Spinlock::new(None);
|
||||
|
||||
/// Represents an initialised UART device.
|
||||
pub struct Device {
|
||||
base: usize,
|
||||
|
@ -29,4 +33,55 @@ impl Device {
|
|||
core::ptr::write_volatile(ptr, character);
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a character from the UART input.
|
||||
pub fn get(&mut self) -> Option<u8> {
|
||||
const READY: u8 = 0b1;
|
||||
|
||||
let ptr = self.base as *mut u8;
|
||||
// SAFETY: Fine as long as base is correct.
|
||||
let lsr = unsafe { ptr.offset(5) };
|
||||
unsafe {
|
||||
if core::ptr::read_volatile(lsr) & READY == READY {
|
||||
Some(core::ptr::read_volatile(ptr))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Write for Device {
|
||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||
for c in s.bytes() {
|
||||
self.put(c);
|
||||
}
|
||||
Ok(()) // there are never errors writing to UART :)
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialise the UART debugging console.
|
||||
/// # Safety
|
||||
/// `base` must point to the base address of a UART device.
|
||||
pub unsafe fn init_console(base: usize) {
|
||||
let mut console = CONSOLE.lock();
|
||||
*console = Some(unsafe { Device::new(base) });
|
||||
}
|
||||
|
||||
/// Prints a formatted string to the [CONSOLE].
|
||||
#[macro_export]
|
||||
macro_rules! print {
|
||||
($($arg:tt)*) => ({
|
||||
use core::fmt::Write;
|
||||
$crate::uart::CONSOLE.lock().as_mut().map(|writer| {
|
||||
writer.write_fmt(format_args!($($arg)*)).unwrap()
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// println prints a formatted string to the [CONSOLE] with a trailing newline character.
|
||||
#[macro_export]
|
||||
macro_rules! println {
|
||||
($fmt:expr) => ($crate::print!(concat!($fmt, "\n")));
|
||||
($fmt:expr, $($arg:tt)*) => ($crate::print!(concat!($fmt, "\n"), $($arg)*));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue