services: kernel-test: add loopback test

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2021-03-25 16:01:57 +08:00
parent a5993f0445
commit 6efc6bdfd5
3 changed files with 49 additions and 190 deletions

View file

@ -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(())
}
}

View file

@ -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(())
}
}

View file

@ -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");
}
}