forked from betrusted-io/xous-core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
kernel: Split debug shell and uart driver.
I've added a `platform` module to store all platform specific code, (not architecture specific) as some platforms will require custom drivers, e.g. for debug output and for the random number generation code. The platform code is in charge of mapping any peripherals needed to work, also to initialize any other parts of the kernel that require drivers, for example the debug shell. Signed-off-by: Jean-Pierre De Jesus DIAZ <me@jeandudey.tech>
- Loading branch information
Showing
8 changed files
with
431 additions
and
350 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// SPDX-FileCopyrightText: 2020 Sean Cross <sean@xobs.io> | ||
// SPDX-FileCopyrightText: 2022 Foundation Devices, Inc. <hello@foundationdevices.com> | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
/// Prints to the debug output directly. | ||
#[cfg(baremetal)] | ||
#[macro_export] | ||
macro_rules! print { | ||
($($args:tt)+) => {{ | ||
#[allow(unused_unsafe)] | ||
unsafe { | ||
use core::fmt::Write; | ||
if let Some(stream) = crate::debug::shell::OUTPUT.as_mut() { | ||
write!(stream, $($args)+).unwrap(); | ||
} | ||
} | ||
}}; | ||
} | ||
|
||
/// Prints to the debug output directly, with a newline. | ||
#[cfg(baremetal)] | ||
#[macro_export] | ||
macro_rules! println { | ||
() => ({ | ||
print!("\r\n") | ||
}); | ||
($fmt:expr) => ({ | ||
print!(concat!($fmt, "\r\n")) | ||
}); | ||
($fmt:expr, $($args:tt)+) => ({ | ||
print!(concat!($fmt, "\r\n"), $($args)+) | ||
}); | ||
} | ||
|
||
#[cfg(feature = "debug-print")] | ||
#[macro_export] | ||
macro_rules! klog { | ||
() => ({ | ||
print!(" [{}:{}]", file!(), line!()) | ||
}); | ||
($fmt:expr) => ({ | ||
print!(concat!(" [{}:{} ", $fmt, "]"), file!(), line!()) | ||
}); | ||
($fmt:expr, $($args:tt)+) => ({ | ||
print!(concat!(" [{}:{} ", $fmt, "]"), file!(), line!(), $($args)+) | ||
}); | ||
} | ||
|
||
#[cfg(not(feature = "debug-print"))] | ||
#[macro_export] | ||
macro_rules! klog { | ||
($($args:tt)+) => {{}}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,318 +1,7 @@ | ||
// SPDX-FileCopyrightText: 2020 Sean Cross <sean@xobs.io> | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
#[cfg(baremetal)] | ||
use core::fmt::{Error, Write}; | ||
#[cfg(baremetal)] | ||
use utralib::generated::*; | ||
|
||
#[cfg(baremetal)] | ||
pub static mut DEBUG_OUTPUT: Option<&'static mut dyn Write> = None; | ||
|
||
pub use crate::arch::process::Process as ArchProcess; | ||
|
||
#[macro_use] | ||
#[cfg(all( | ||
not(test), | ||
baremetal, | ||
any(feature = "debug-print", feature = "print-panics") | ||
))] | ||
pub mod debug_print_hardware { | ||
// the HW device mapping is done in main.rs/init(); the virtual address has to be in the top 4MiB as it is the only page shared among all processes | ||
pub const SUPERVISOR_UART_ADDR: *mut usize = 0xffcf_0000 as *mut usize; // see https://github.com/betrusted-io/xous-core/blob/master/docs/memory.md | ||
} | ||
#[cfg(all( | ||
not(test), | ||
baremetal, | ||
any(feature = "debug-print", feature = "print-panics") | ||
))] | ||
pub use crate::debug::debug_print_hardware::SUPERVISOR_UART_ADDR; | ||
|
||
#[cfg(baremetal)] | ||
#[macro_export] | ||
macro_rules! print { | ||
($($args:tt)+) => {{ | ||
#[allow(unused_unsafe)] | ||
unsafe { | ||
if let Some(mut stream) = crate::debug::DEBUG_OUTPUT.as_mut() { | ||
write!(&mut stream, $($args)+).unwrap(); | ||
} | ||
} | ||
}}; | ||
} | ||
|
||
#[cfg(baremetal)] | ||
#[macro_export] | ||
macro_rules! println | ||
{ | ||
() => ({ | ||
print!("\r\n") | ||
}); | ||
($fmt:expr) => ({ | ||
print!(concat!($fmt, "\r\n")) | ||
}); | ||
($fmt:expr, $($args:tt)+) => ({ | ||
print!(concat!($fmt, "\r\n"), $($args)+) | ||
}); | ||
} | ||
|
||
#[cfg(baremetal)] | ||
pub struct Uart {} | ||
mod macros; | ||
#[cfg(baremetal)] | ||
pub static mut UART: Uart = Uart {}; | ||
|
||
#[cfg(all(baremetal, feature = "wrap-print"))] | ||
static mut CHAR_COUNT: usize = 0; | ||
|
||
#[cfg(baremetal)] | ||
impl Uart { | ||
#[allow(dead_code)] | ||
pub fn init(self) { | ||
unsafe { DEBUG_OUTPUT = Some(&mut UART) }; | ||
let mut uart_csr = CSR::new(crate::debug::SUPERVISOR_UART_ADDR as *mut u32); | ||
uart_csr.rmwf(utra::uart::EV_ENABLE_RX, 1); | ||
} | ||
|
||
pub fn putc(&self, c: u8) { | ||
if unsafe { DEBUG_OUTPUT.is_none() } { | ||
return; | ||
} | ||
|
||
let mut uart_csr = CSR::new(crate::debug::SUPERVISOR_UART_ADDR as *mut u32); | ||
// Wait until TXFULL is `0` | ||
while uart_csr.r(utra::uart::TXFULL) != 0 {} | ||
#[cfg(feature = "wrap-print")] | ||
unsafe { | ||
if c == b'\n' { | ||
CHAR_COUNT = 0; | ||
} else if CHAR_COUNT > 80 { | ||
CHAR_COUNT = 0; | ||
self.putc(b'\n'); | ||
self.putc(b'\r'); | ||
self.putc(b' '); | ||
self.putc(b' '); | ||
self.putc(b' '); | ||
self.putc(b' '); | ||
} else { | ||
CHAR_COUNT += 1; | ||
} | ||
} | ||
uart_csr.wfo(utra::uart::RXTX_RXTX, c as u32); | ||
} | ||
|
||
#[allow(dead_code)] | ||
pub fn getc(&self) -> Option<u8> { | ||
if unsafe { DEBUG_OUTPUT.is_none() } { | ||
return None; | ||
} | ||
let mut uart_csr = CSR::new(crate::debug::SUPERVISOR_UART_ADDR as *mut u32); | ||
// If EV_PENDING_RX is 1, return the pending character. | ||
// Otherwise, return None. | ||
match uart_csr.rf(utra::uart::EV_PENDING_RX) { | ||
0 => None, | ||
_ => { | ||
let ret = Some(uart_csr.r(utra::uart::RXTX) as u8); | ||
uart_csr.wfo(utra::uart::EV_PENDING_RX, 1); | ||
ret | ||
} | ||
} | ||
} | ||
} | ||
|
||
#[cfg(all( | ||
baremetal, | ||
not(test), | ||
any(feature = "debug-print", feature = "print-panics") | ||
))] | ||
pub fn irq(_irq_number: usize, _arg: *mut usize) { | ||
let uart = Uart {}; | ||
while let Some(b) = uart.getc() { | ||
process_irq_character(b); | ||
} | ||
// uart.acknowledge_irq(); | ||
} | ||
|
||
#[cfg(all( | ||
baremetal, | ||
not(test), | ||
any(feature = "debug-print", feature = "print-panics") | ||
))] | ||
fn process_irq_character(b: u8) { | ||
match b { | ||
b'i' => { | ||
println!("Interrupt handlers:"); | ||
println!(" IRQ | Process | Handler | Argument"); | ||
crate::services::SystemServices::with(|system_services| { | ||
crate::irq::for_each_irq(|irq, pid, address, arg| { | ||
println!( | ||
" {}: {} @ {:x?} {:x?}", | ||
irq, | ||
system_services.process_name(*pid).unwrap_or(""), | ||
address, | ||
arg | ||
); | ||
}); | ||
}); | ||
} | ||
b'm' => { | ||
println!("Printing memory page tables"); | ||
crate::services::SystemServices::with(|system_services| { | ||
let current_pid = system_services.current_pid(); | ||
for process in &system_services.processes { | ||
if !process.free() { | ||
println!( | ||
"PID {} {}:", | ||
process.pid, | ||
system_services.process_name(process.pid).unwrap_or("") | ||
); | ||
process.activate().unwrap(); | ||
crate::arch::mem::MemoryMapping::current().print_map(); | ||
println!(); | ||
} | ||
} | ||
system_services | ||
.get_process(current_pid) | ||
.unwrap() | ||
.activate() | ||
.unwrap(); | ||
}); | ||
} | ||
b'p' => { | ||
println!("Printing processes"); | ||
crate::services::SystemServices::with(|system_services| { | ||
let current_pid = system_services.current_pid(); | ||
for process in &system_services.processes { | ||
if !process.free() { | ||
process.activate().unwrap(); | ||
let mut connection_count = 0; | ||
ArchProcess::with_inner(|process_inner| { | ||
for conn in &process_inner.connection_map { | ||
if conn.is_some() { | ||
connection_count += 1; | ||
} | ||
} | ||
}); | ||
println!( | ||
"{:?} conns:{}/32 {}", | ||
process, | ||
connection_count, | ||
system_services.process_name(process.pid).unwrap_or("") | ||
); | ||
} | ||
} | ||
system_services | ||
.get_process(current_pid) | ||
.unwrap() | ||
.activate() | ||
.unwrap(); | ||
}); | ||
} | ||
b'P' => { | ||
println!("Printing processes and threads"); | ||
crate::services::SystemServices::with(|system_services| { | ||
let current_pid = system_services.current_pid(); | ||
for process in &system_services.processes { | ||
if !process.free() { | ||
println!( | ||
"{:?} {}:", | ||
process, | ||
system_services.process_name(process.pid).unwrap_or("") | ||
); | ||
process.activate().unwrap(); | ||
crate::arch::process::Process::with_current_mut(|arch_process| { | ||
arch_process.print_all_threads() | ||
}); | ||
println!(); | ||
} | ||
} | ||
system_services | ||
.get_process(current_pid) | ||
.unwrap() | ||
.activate() | ||
.unwrap(); | ||
}); | ||
} | ||
b'r' => { | ||
println!("RAM usage:"); | ||
let mut total_bytes = 0; | ||
crate::services::SystemServices::with(|system_services| { | ||
crate::mem::MemoryManager::with(|mm| { | ||
for process in &system_services.processes { | ||
if !process.free() { | ||
let bytes_used = mm.ram_used_by(process.pid); | ||
total_bytes += bytes_used; | ||
println!( | ||
" PID {:>3}: {:>4} k {}", | ||
process.pid, | ||
bytes_used / 1024, | ||
system_services.process_name(process.pid).unwrap_or("") | ||
); | ||
} | ||
} | ||
}); | ||
}); | ||
println!("{} k total", total_bytes / 1024); | ||
} | ||
b's' => { | ||
println!("Servers in use:"); | ||
crate::services::SystemServices::with(|system_services| { | ||
println!(" idx | pid | process | sid"); | ||
println!(" --- + --- + -------------------- | ------------------"); | ||
for (idx, server) in system_services.servers.iter().enumerate() { | ||
if let Some(s) = server { | ||
println!( | ||
" {:3} | {:3} | {:20} | {:x?}", | ||
idx, | ||
s.pid, | ||
system_services.process_name(s.pid).unwrap_or(""), | ||
s.sid | ||
); | ||
} | ||
} | ||
}); | ||
} | ||
b'h' => { | ||
println!("Xous Kernel Debug"); | ||
println!("key | command"); | ||
println!("--- + -----------------------"); | ||
println!(" i | print irq handlers"); | ||
println!(" m | print MMU page tables of all processes"); | ||
println!(" p | print all processes"); | ||
println!(" P | print all processes and threads"); | ||
println!(" r | report RAM usage of all processes"); | ||
println!(" s | print all allocated servers"); | ||
} | ||
_ => {} | ||
} | ||
} | ||
|
||
#[cfg(baremetal)] | ||
impl Write for Uart { | ||
fn write_str(&mut self, s: &str) -> Result<(), Error> { | ||
for c in s.bytes() { | ||
self.putc(c); | ||
} | ||
Ok(()) | ||
} | ||
} | ||
|
||
#[cfg(feature = "debug-print")] | ||
#[macro_export] | ||
macro_rules! klog | ||
{ | ||
() => ({ | ||
print!(" [{}:{}]", file!(), line!()) | ||
}); | ||
($fmt:expr) => ({ | ||
print!(concat!(" [{}:{} ", $fmt, "]"), file!(), line!()) | ||
}); | ||
($fmt:expr, $($args:tt)+) => ({ | ||
print!(concat!(" [{}:{} ", $fmt, "]"), file!(), line!(), $($args)+) | ||
}); | ||
} | ||
|
||
#[cfg(not(feature = "debug-print"))] | ||
#[macro_export] | ||
macro_rules! klog { | ||
($($args:tt)+) => {{}}; | ||
} | ||
pub mod shell; |
Oops, something went wrong.