mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-04 04:27:34 +00:00
services: kernel-test: add loopback test
Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
a5993f0445
commit
6efc6bdfd5
3 changed files with 49 additions and 190 deletions
|
|
@ -1,111 +0,0 @@
|
|||
use core::fmt::{Error, Write};
|
||||
|
||||
use utralib::generated::*;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! print
|
||||
{
|
||||
($($args:tt)+) => ({
|
||||
use core::fmt::Write;
|
||||
let _ = write!(crate::debug::Uart {}, $($args)+);
|
||||
});
|
||||
}
|
||||
#[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)+)
|
||||
});
|
||||
}
|
||||
|
||||
fn handle_irq(irq_no: usize, arg: *mut usize) {
|
||||
print!("Handling IRQ {} (arg: {:08x}): ", irq_no, arg as usize);
|
||||
|
||||
while let Some(c) = { crate::debug::Uart {} }.getc() {
|
||||
print!("{}", c as char);
|
||||
}
|
||||
println!();
|
||||
}
|
||||
|
||||
pub struct Uart {}
|
||||
|
||||
// this is a hack to bypass an explicit initialization/allocation step for the debug structure
|
||||
pub static mut DEFAULT_UART_ADDR: *mut usize = 0x0000_0000 as *mut usize;
|
||||
|
||||
pub const DEFAULT: Uart = Uart {};
|
||||
|
||||
impl Uart {
|
||||
fn map_uart(&self) {
|
||||
/*
|
||||
Note: the memory address and interrupt specified here needs to map to a unique hardware
|
||||
UART resource. Modify in this function as necessary.
|
||||
*/
|
||||
let uart = xous::syscall::map_memory(
|
||||
xous::MemoryAddress::new(utra::console::HW_CONSOLE_BASE),
|
||||
None,
|
||||
4096,
|
||||
xous::MemoryFlags::R | xous::MemoryFlags::W,
|
||||
)
|
||||
.expect("couldn't map debug uart");
|
||||
unsafe {
|
||||
DEFAULT_UART_ADDR = uart.as_mut_ptr() as _;
|
||||
}
|
||||
println!("Mapped UART @ {:08x}", uart.addr.get());
|
||||
// core::mem::forget(uart);
|
||||
|
||||
println!("Allocating IRQ...");
|
||||
xous::claim_interrupt(
|
||||
utra::console::CONSOLE_IRQ,
|
||||
handle_irq,
|
||||
core::ptr::null_mut::<usize>(),
|
||||
)
|
||||
.expect("unable to allocate IRQ");
|
||||
self.enable_rx();
|
||||
}
|
||||
|
||||
pub fn putc(&self, c: u8) {
|
||||
if unsafe { DEFAULT_UART_ADDR } as usize == 0 {
|
||||
self.map_uart();
|
||||
}
|
||||
let mut uart_csr = CSR::new(unsafe { DEFAULT_UART_ADDR as *mut u32 });
|
||||
|
||||
// Wait until TXFULL is `0`
|
||||
while uart_csr.r(utra::uart::TXFULL) != 0 {}
|
||||
uart_csr.wo(utra::uart::RXTX, c as u32);
|
||||
}
|
||||
|
||||
pub fn enable_rx(&self) {
|
||||
let mut uart_csr = CSR::new(unsafe { DEFAULT_UART_ADDR as *mut u32 });
|
||||
uart_csr.rmwf(utra::uart::EV_ENABLE_RX, 1);
|
||||
}
|
||||
|
||||
pub fn getc(&self) -> Option<u8> {
|
||||
if unsafe { DEFAULT_UART_ADDR } as usize == 0 {
|
||||
self.map_uart();
|
||||
}
|
||||
let mut uart_csr = CSR::new(unsafe { DEFAULT_UART_ADDR as *mut u32 });
|
||||
match uart_csr.rf(utra::uart::EV_PENDING_RX) {
|
||||
0 => None,
|
||||
ack => {
|
||||
let c = Some(uart_csr.rf(utra::uart::RXTX_RXTX) as u8);
|
||||
uart_csr.wfo(utra::uart::EV_PENDING_RX, ack);
|
||||
c
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for Uart {
|
||||
fn write_str(&mut self, s: &str) -> Result<(), Error> {
|
||||
for c in s.bytes() {
|
||||
self.putc(c);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
use core::fmt;
|
||||
use core::slice;
|
||||
|
||||
pub struct LogString<'a> {
|
||||
raw_slice: &'a mut [u8],
|
||||
pub s: &'a str,
|
||||
pub len: u32,
|
||||
msg_len: &'a mut Option<xous::MemorySize>,
|
||||
}
|
||||
|
||||
impl<'a> LogString<'a> {
|
||||
pub fn from_message(message: &'a mut xous::MemoryMessage) -> LogString<'a> {
|
||||
// println!("LOG: Message address is at {:08x} (whole message: {:?})", message.buf.addr.get(), message);
|
||||
let raw_slice = unsafe { slice::from_raw_parts_mut(message.buf.as_ptr() as *mut u8, message.buf.len() as usize) };
|
||||
let starting_length = message.valid.map(|x| x.get()).unwrap_or(0);
|
||||
|
||||
// print!("LOG: String @ {:08x}:", message.buf.as_ptr() as usize);
|
||||
// for offset in 0..starting_length {
|
||||
// print!(" {:02x}", raw_slice[offset]);
|
||||
// }
|
||||
// println!(" (length: {})", starting_length);
|
||||
|
||||
LogString {
|
||||
s: unsafe {
|
||||
core::str::from_utf8_unchecked(slice::from_raw_parts(
|
||||
message.buf.as_ptr() as *mut u8,
|
||||
starting_length,
|
||||
))
|
||||
},
|
||||
len: starting_length as u32,
|
||||
raw_slice,
|
||||
msg_len: &mut message.valid,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for LogString<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Write for LogString<'a> {
|
||||
fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
|
||||
for c in s.bytes() {
|
||||
if self.len as usize < self.raw_slice.len() {
|
||||
self.raw_slice[self.len as usize] = c;
|
||||
self.len += 1;
|
||||
}
|
||||
}
|
||||
self.s = unsafe {
|
||||
core::str::from_utf8_unchecked(slice::from_raw_parts(self.raw_slice.as_ptr(), self.len as usize))
|
||||
};
|
||||
*self.msg_len = Some(xous::MemorySize::new(self.len as usize).unwrap());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
@ -3,12 +3,18 @@
|
|||
|
||||
const EXTRA_KEY: usize = 42;
|
||||
|
||||
fn sleep_loop_4(sleep_ms: usize, conn: usize, pid: usize, extra: usize) {
|
||||
fn sleep_loop_4(main_conn: usize, sleep_ms: usize, ticktimer_conn: usize, pid: usize) {
|
||||
let tid = xous::current_tid().unwrap();
|
||||
let conn = conn as _;
|
||||
let ticktimer_conn = ticktimer_conn as _;
|
||||
// let pid = xous::current_pid().unwrap().get();
|
||||
log::info!("My thread number is {}, sleeping 0x{:08x} ({}) ms and EXTRA: {}", tid, sleep_ms, sleep_ms, extra);
|
||||
assert_eq!(extra, EXTRA_KEY, "extra key in arg 4 didn't match -- was {}, not {}", extra, EXTRA_KEY);
|
||||
log::info!(
|
||||
"My thread number is {}, sleeping 0x{:08x} ({}) ms and main_conn: {}",
|
||||
tid,
|
||||
sleep_ms,
|
||||
sleep_ms,
|
||||
main_conn
|
||||
);
|
||||
let main_conn = main_conn as xous::CID;
|
||||
|
||||
let mut loop_count = 0;
|
||||
loop {
|
||||
|
|
@ -18,9 +24,9 @@ fn sleep_loop_4(sleep_ms: usize, conn: usize, pid: usize, extra: usize) {
|
|||
// sleep_ms,
|
||||
// loop_count
|
||||
// );
|
||||
let start_time = ticktimer_server::elapsed_ms(conn).unwrap();
|
||||
ticktimer_server::sleep_ms(conn, sleep_ms).unwrap();
|
||||
let end_time = ticktimer_server::elapsed_ms(conn).unwrap();
|
||||
let start_time = ticktimer_server::elapsed_ms(ticktimer_conn).unwrap();
|
||||
ticktimer_server::sleep_ms(ticktimer_conn, sleep_ms).unwrap();
|
||||
let end_time = ticktimer_server::elapsed_ms(ticktimer_conn).unwrap();
|
||||
log::info!(
|
||||
"TEST THREAD {}:{}: target {}ms, {} loops: Sleep finished (uptime: {}, took {} ms)",
|
||||
pid,
|
||||
|
|
@ -31,36 +37,56 @@ fn sleep_loop_4(sleep_ms: usize, conn: usize, pid: usize, extra: usize) {
|
|||
end_time - start_time,
|
||||
);
|
||||
loop_count += 1;
|
||||
xous::send_message(
|
||||
main_conn,
|
||||
xous::Message::Scalar(xous::ScalarMessage::from_usize(
|
||||
pid as _,
|
||||
tid as _,
|
||||
sleep_ms as _,
|
||||
loop_count as _,
|
||||
end_time as _,
|
||||
)),
|
||||
).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn sleep_loop_3(sleep_ms: usize, conn: usize, pid: usize) {
|
||||
sleep_loop_4(sleep_ms, conn, pid, EXTRA_KEY);
|
||||
fn sleep_loop_3(main_conn: usize, sleep_ms: usize, ticktimer_conn: usize) {
|
||||
sleep_loop_4(
|
||||
main_conn,
|
||||
sleep_ms,
|
||||
ticktimer_conn,
|
||||
xous::current_pid().unwrap().get() as _,
|
||||
);
|
||||
}
|
||||
|
||||
fn sleep_loop_2(sleep_ms: usize, conn: usize) {
|
||||
sleep_loop_3(sleep_ms, conn, xous::current_pid().unwrap().get() as _);
|
||||
}
|
||||
|
||||
fn sleep_loop_1(sleep_ms: usize) {
|
||||
fn sleep_loop_2(main_conn: usize, sleep_ms: usize) {
|
||||
let ticktimer_server_id = xous::SID::from_bytes(b"ticktimer-server").unwrap();
|
||||
let ticktimer_conn = xous::connect(ticktimer_server_id).unwrap();
|
||||
sleep_loop_2(sleep_ms, ticktimer_conn as _);
|
||||
let ticktimer_conn = xous::connect(ticktimer_server_id).unwrap() as usize;
|
||||
sleep_loop_3(main_conn, sleep_ms, ticktimer_conn);
|
||||
}
|
||||
|
||||
fn sleep_loop_1(main_conn: usize) {
|
||||
let sleep_ms =
|
||||
(xous::current_pid().unwrap().get() as usize) * (xous::current_tid().unwrap() as usize);
|
||||
sleep_loop_2(main_conn, sleep_ms);
|
||||
}
|
||||
|
||||
static mut MAIN_CONN: xous::CID = 0;
|
||||
fn sleep_loop_0() {
|
||||
let sleep_ms = (xous::current_pid().unwrap().get() as usize) * (xous::current_tid().unwrap() as usize);
|
||||
let ticktimer_server_id = xous::SID::from_bytes(b"ticktimer-server").unwrap();
|
||||
let ticktimer_conn = xous::connect(ticktimer_server_id).unwrap();
|
||||
sleep_loop_2(sleep_ms, ticktimer_conn as _);
|
||||
sleep_loop_1(unsafe { MAIN_CONN } as _);
|
||||
}
|
||||
|
||||
#[xous::xous_main]
|
||||
fn test_main() -> ! {
|
||||
log_server::init_wait().unwrap();
|
||||
|
||||
let ticktimer_server_id = xous::SID::from_bytes(b"ticktimer-server").unwrap();
|
||||
let ticktimer_conn = xous::connect(ticktimer_server_id).unwrap();
|
||||
|
||||
log_server::init_wait().unwrap();
|
||||
let main_server = xous::create_server().unwrap();
|
||||
let server_conn = xous::connect(main_server).unwrap();
|
||||
unsafe { MAIN_CONN = server_conn };
|
||||
|
||||
let pid = xous::current_pid().unwrap().get() as usize;
|
||||
|
||||
xous::create_thread_0(sleep_loop_0).unwrap();
|
||||
|
|
@ -70,6 +96,7 @@ fn test_main() -> ! {
|
|||
xous::create_thread_4(sleep_loop_4, 180 * pid, ticktimer_conn as _, pid, EXTRA_KEY).unwrap();
|
||||
|
||||
loop {
|
||||
xous::wait_event();
|
||||
xous::receive_message(main_server).unwrap();
|
||||
log::info!("Received message from remote");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue