mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-15 08:30:02 +00:00
kernel-test: add test for ticktimer-server
This test is an attempt to fix `sleep_ms()`. Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
27c35223cd
commit
751dc8ee3a
3 changed files with 57 additions and 323 deletions
|
|
@ -7,10 +7,12 @@ description = "Program to test various aspects of the kernel"
|
|||
|
||||
[dependencies]
|
||||
xous = { path = "../../xous-rs" }
|
||||
log-server = { path = "../log-server" }
|
||||
ticktimer-server = { path = "../ticktimer-server" }
|
||||
log = "0.4"
|
||||
|
||||
[target.'cfg(not(any(windows,unix)))'.dependencies]
|
||||
utralib = { path = "../../utralib"}
|
||||
|
||||
[features]
|
||||
logging = [] # adding this allocates the UART for logging of Xous
|
||||
default = ["logging"]
|
||||
default = []
|
||||
|
|
|
|||
|
|
@ -1,336 +1,68 @@
|
|||
#![cfg_attr(target_os = "none", no_std)]
|
||||
#![cfg_attr(target_os = "none", no_main)]
|
||||
|
||||
#[cfg(baremetal)]
|
||||
#[macro_use]
|
||||
mod debug;
|
||||
|
||||
use core::fmt::Write;
|
||||
use xous::String;
|
||||
|
||||
#[cfg(not(target_os = "none"))]
|
||||
mod implementation {
|
||||
use core::fmt::{Error, Write};
|
||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||
|
||||
enum ControlMessage {
|
||||
Text(String),
|
||||
Byte(u8),
|
||||
Exit,
|
||||
}
|
||||
|
||||
pub struct Output {
|
||||
tx: Sender<ControlMessage>,
|
||||
rx: Receiver<ControlMessage>,
|
||||
stdout: std::io::Stdout,
|
||||
}
|
||||
|
||||
pub fn init() -> Output {
|
||||
let (tx, rx) = channel();
|
||||
|
||||
Output {
|
||||
tx,
|
||||
rx,
|
||||
stdout: std::io::stdout(),
|
||||
}
|
||||
}
|
||||
|
||||
impl Output {
|
||||
pub fn run(&mut self) {
|
||||
use std::io::Write;
|
||||
loop {
|
||||
match self.rx.recv_timeout(std::time::Duration::from_millis(50)) {
|
||||
Ok(msg) => match msg {
|
||||
ControlMessage::Exit => break,
|
||||
ControlMessage::Text(s) => print!("{}", s),
|
||||
ControlMessage::Byte(s) => {
|
||||
let mut handle = self.stdout.lock();
|
||||
handle.write_all(&[s]).unwrap();
|
||||
}
|
||||
},
|
||||
Err(std::sync::mpsc::RecvTimeoutError::Timeout) => {}
|
||||
Err(e) => panic!("Error: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_writer(&self) -> OutputWriter {
|
||||
OutputWriter {
|
||||
tx: self.tx.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Output {
|
||||
fn drop(&mut self) {
|
||||
self.tx.send(ControlMessage::Exit).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for Output {
|
||||
fn write_str(&mut self, s: &str) -> Result<(), Error> {
|
||||
// It would be nice if this worked with &str
|
||||
self.tx.send(ControlMessage::Text(s.to_owned())).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OutputWriter {
|
||||
tx: Sender<ControlMessage>,
|
||||
}
|
||||
|
||||
impl OutputWriter {
|
||||
pub fn putc(&self, c: u8) {
|
||||
self.tx.send(ControlMessage::Byte(c)).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for OutputWriter {
|
||||
fn write_str(&mut self, s: &str) -> Result<(), Error> {
|
||||
// It would be nice if this worked with &str
|
||||
self.tx.send(ControlMessage::Text(s.to_owned())).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
struct LoopArg {
|
||||
msec: usize,
|
||||
}
|
||||
// fn sleep_10_loop(_ign: usize) {
|
||||
// let ticktimer_server_id = xous::SID::from_bytes(b"ticktimer-server").unwrap();
|
||||
// let ticktimer_conn = xous::connect(ticktimer_server_id).unwrap();
|
||||
|
||||
#[cfg(target_os = "none")]
|
||||
mod implementation {
|
||||
use core::fmt::{Error, Write};
|
||||
use utralib::generated::*;
|
||||
// let mut ms_count = 1;
|
||||
// loop {
|
||||
// log::info!("10ms Loop count {}", ms_count);
|
||||
// sleep_ms(ticktimer_conn, 10).unwrap();
|
||||
// ms_count += 1;
|
||||
// }
|
||||
// }
|
||||
|
||||
pub struct Output {}
|
||||
// fn sleep_5_loop(_ign: usize) {
|
||||
// let ticktimer_server_id = xous::SID::from_bytes(b"ticktimer-server").unwrap();
|
||||
// let ticktimer_conn = xous::connect(ticktimer_server_id).unwrap();
|
||||
|
||||
pub fn init() -> Output {
|
||||
if cfg!(feature = "logging") {
|
||||
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 serial port");
|
||||
unsafe { crate::debug::DEFAULT_UART_ADDR = uart.as_mut_ptr() as _ };
|
||||
println!("Mapped UART @ {:08x}", uart.addr.get());
|
||||
// let mut ms_count = 1;
|
||||
// loop {
|
||||
// log::info!("5ms Loop count {}", ms_count);
|
||||
// sleep_ms(ticktimer_conn, 5).unwrap();
|
||||
// ms_count += 1;
|
||||
// }
|
||||
// }
|
||||
|
||||
println!("Process: map success!");
|
||||
crate::debug::DEFAULT.enable_rx();
|
||||
fn sleep_loop(_arg: usize) {
|
||||
let ticktimer_server_id = xous::SID::from_bytes(b"ticktimer-server").unwrap();
|
||||
let ticktimer_conn = xous::connect(ticktimer_server_id).unwrap();
|
||||
let tid = xous::current_tid().unwrap();
|
||||
let sleep_ms = match tid {
|
||||
2 => 2,
|
||||
3 => 5,
|
||||
4 => 10,
|
||||
_ => panic!("Unknown TID"),
|
||||
};
|
||||
log::info!("My thread number is {}, sleeping {} ms", tid, sleep_ms);
|
||||
|
||||
println!("Allocating IRQ...");
|
||||
xous::syscall::claim_interrupt(
|
||||
utra::console::CONSOLE_IRQ,
|
||||
handle_irq,
|
||||
core::ptr::null_mut::<usize>(),
|
||||
)
|
||||
.expect("couldn't claim interrupt");
|
||||
println!("Claimed IRQ {}", utra::console::CONSOLE_IRQ);
|
||||
}
|
||||
Output {}
|
||||
}
|
||||
|
||||
impl Output {
|
||||
pub fn get_writer(&self) -> OutputWriter {
|
||||
OutputWriter {}
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
loop {
|
||||
xous::wait_event();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_irq(irq_no: usize, arg: *mut usize) {
|
||||
if cfg!(feature = "logging") {
|
||||
print!("Handling IRQ {} (arg: {:08x}): ", irq_no, arg as usize);
|
||||
|
||||
while let Some(c) = crate::debug::DEFAULT.getc() {
|
||||
print!("0x{:02x}", c);
|
||||
}
|
||||
println!();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OutputWriter {}
|
||||
|
||||
impl OutputWriter {
|
||||
pub fn putc(&self, c: u8) {
|
||||
if cfg!(feature = "logging") {
|
||||
let mut uart_csr = CSR::new(unsafe { crate::debug::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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for OutputWriter {
|
||||
fn write_str(&mut self, s: &str) -> Result<(), Error> {
|
||||
for c in s.bytes() {
|
||||
self.putc(c);
|
||||
if c == '\n' as u8 {
|
||||
self.putc('\r' as u8);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_scalar(
|
||||
output: &mut implementation::OutputWriter,
|
||||
sender: xous::MessageSender,
|
||||
msg: &xous::ScalarMessage,
|
||||
sender_pid: xous::PID,
|
||||
) {
|
||||
match msg.id {
|
||||
1000 => writeln!(output, "PANIC from PID {} | {}", sender_pid, sender).unwrap(),
|
||||
1100 => (),
|
||||
1101..=1132 => {
|
||||
let mut output_bfr = [0u8; core::mem::size_of::<usize>() * 4];
|
||||
let output_iter = output_bfr.iter_mut();
|
||||
|
||||
// Combine the four arguments to form a single
|
||||
// contiguous buffer. Note: The buffer size will change
|
||||
// depending on the platfor's `usize` length.
|
||||
let arg1_bytes = msg.arg1.to_le_bytes();
|
||||
let arg2_bytes = msg.arg2.to_le_bytes();
|
||||
let arg3_bytes = msg.arg3.to_le_bytes();
|
||||
let arg4_bytes = msg.arg4.to_le_bytes();
|
||||
let input_iter = arg1_bytes
|
||||
.iter()
|
||||
.chain(arg2_bytes.iter())
|
||||
.chain(arg3_bytes.iter())
|
||||
.chain(arg4_bytes.iter());
|
||||
for (dest, src) in output_iter.zip(input_iter) {
|
||||
*dest = *src;
|
||||
}
|
||||
let total_chars = msg.id - 1100;
|
||||
for (idx, c) in output_bfr.iter().enumerate() {
|
||||
if idx >= total_chars {
|
||||
break;
|
||||
}
|
||||
output.putc(*c);
|
||||
}
|
||||
}
|
||||
1200 => writeln!(output, "Terminating process").unwrap(),
|
||||
_ => writeln!(
|
||||
output,
|
||||
"Unrecognized scalar message from {}: {:#?}",
|
||||
sender, msg
|
||||
)
|
||||
.unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
fn reader_thread(mut output: implementation::OutputWriter) {
|
||||
writeln!(output, "LOG: Xous Logging Server starting up...").unwrap();
|
||||
|
||||
writeln!(output, "LOG: ****************************************************************").unwrap();
|
||||
// time stamp isn't actually the time stamp of the build, unfortunately. It's the time stamp of the
|
||||
// last time you managed to force a rebuild that also causes log-server to be rebuilt, not necessarily
|
||||
// capturing the build time of the very most recent change!
|
||||
// writeln!(output, "LOG: *** Built: {:49} ***", env!("VERGEN_BUILD_TIMESTAMP")).unwrap();
|
||||
writeln!(output, "LOG: ****************************************************************").unwrap();
|
||||
let server_addr = xous::create_server_with_address(b"xous-log-server ").unwrap();
|
||||
writeln!(output, "LOG: Server listening on address {:?}", server_addr).unwrap();
|
||||
|
||||
let mut counter: usize = 0;
|
||||
let mut ms_count = 1;
|
||||
loop {
|
||||
if counter.trailing_zeros() >= 12 {
|
||||
writeln!(output, "LOG: Counter tick: {}", counter).unwrap();
|
||||
}
|
||||
counter += 1;
|
||||
// writeln!(output, "LOG: Waiting for an event...").unwrap();
|
||||
let mut envelope =
|
||||
xous::syscall::receive_message(server_addr).expect("couldn't get address");
|
||||
let sender = envelope.sender;
|
||||
// writeln!(output, "LOG: Got message envelope: {:?}", envelope).unwrap();
|
||||
match &mut envelope.body {
|
||||
xous::Message::Scalar(msg) => handle_scalar(&mut output, sender, msg, envelope.sender.pid().unwrap()),
|
||||
xous::Message::BlockingScalar(msg) => {
|
||||
writeln!(
|
||||
output,
|
||||
"LOG: BlockingScalar message from {}: {:?}",
|
||||
envelope.sender, msg
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
xous::Message::Move(msg) => {
|
||||
String::<4000>::from_message(msg)
|
||||
.map(|log_entry: String<4000>| {
|
||||
writeln!(
|
||||
output,
|
||||
"LOG: Moved log message from {}: {}",
|
||||
sender, log_entry
|
||||
)
|
||||
.unwrap()
|
||||
})
|
||||
.or_else(|e| {
|
||||
writeln!(output, "LOG: unable to convert Move message to str: {}", e)
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
xous::Message::Borrow(msg) => {
|
||||
String::<4000>::from_message(msg)
|
||||
.map(|log_entry: String<4000>| writeln!(output, "{}", log_entry).unwrap())
|
||||
.or_else(|e| {
|
||||
writeln!(
|
||||
output,
|
||||
"LOG: unable to convert Borrow message to str: {}",
|
||||
e
|
||||
)
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
xous::Message::MutableBorrow(msg) => {
|
||||
String::<4000>::from_message(msg)
|
||||
.map(|mut log_entry: String<4000>| {
|
||||
writeln!(
|
||||
output,
|
||||
"LOG: Mutable borrowed log message from {} len {}:\n\r {}\n\r",
|
||||
sender,
|
||||
log_entry.len(),
|
||||
log_entry,
|
||||
)
|
||||
.unwrap();
|
||||
writeln!(log_entry, " << HELLO FROM THE SERVER").unwrap();
|
||||
})
|
||||
.or_else(|e| {
|
||||
writeln!(
|
||||
output,
|
||||
"LOG: unable to convert MutableBorrow message to str: {}",
|
||||
e
|
||||
)
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn writer_thread(_ignored: usize) {
|
||||
let mut counter = 0;
|
||||
loop {
|
||||
let conn = xous::connect(xous::SID::from_bytes(b"xous-log-server ").unwrap()).unwrap();
|
||||
let mut buffer = xous::String::<4000>::new();
|
||||
write!(buffer, "Hello, myself! Loop: {}", counter).unwrap();
|
||||
buffer.lend(conn).unwrap();
|
||||
|
||||
counter += 1;
|
||||
log::info!("{}ms Loop count {}", sleep_ms, ms_count);
|
||||
ticktimer_server::sleep_ms(ticktimer_conn, sleep_ms).unwrap();
|
||||
ms_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#[xous::xous_main]
|
||||
fn test_main() -> ! {
|
||||
let mut output = implementation::init();
|
||||
let writer = output.get_writer();
|
||||
println!("LOG: my PID is {}", xous::process::id());
|
||||
println!("LOG: Creating the reader thread");
|
||||
xous::create_thread_simple(reader_thread, writer).unwrap();
|
||||
xous::create_thread_simple(writer_thread, 0usize).unwrap();
|
||||
println!("LOG: Running the output");
|
||||
output.run();
|
||||
loop {}
|
||||
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();
|
||||
|
||||
xous::create_thread_simple(sleep_loop, 10).unwrap();
|
||||
xous::create_thread_simple(sleep_loop, 5).unwrap();
|
||||
xous::create_thread_simple(sleep_loop, 2).unwrap();
|
||||
|
||||
// let mut ms_count = 1;
|
||||
loop {
|
||||
xous::wait_event();
|
||||
// log::info!("Loop {}", ms_count);
|
||||
// sleep_ms(ticktimer_conn, 1).unwrap();
|
||||
// ms_count += 1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ fn try_main() -> Result<(), DynError> {
|
|||
let task = env::args().nth(1);
|
||||
match task.as_deref() {
|
||||
Some("renode-image") => renode_image(false, &hw_pkgs)?,
|
||||
Some("renode-test") => renode_image(false, &["kernel-test"])?,
|
||||
Some("renode-test") => renode_image(false, &["ticktimer-server", "log-server", "xous-names", "kernel-test"])?,
|
||||
Some("renode-image-debug") => renode_image(true, &hw_pkgs)?,
|
||||
Some("run") => run(false)?,
|
||||
Some("hw-image") => build_hw_image(false, env::args().nth(2), &hw_pkgs)?,
|
||||
|
|
|
|||
Loading…
Reference in a new issue