use crate::os::xous::ffi::Connection; use core::sync::atomic::{AtomicU32, Ordering}; /// Group `usize` bytes into a `usize` and return it, beginning /// from `offset` * sizeof(usize) bytes from the start. For example, /// `group_or_null([1,2,3,4,5,6,7,8], 1)` on a 32-bit system will /// return a usize with 5678 packed into it. fn group_or_null(data: &[u8], offset: usize) -> usize { let start = offset * core::mem::size_of::(); let mut out_array = [0u8; core::mem::size_of::()]; if start < data.len() { for (dest, src) in out_array.iter_mut().zip(&data[start..]) { *dest = *src; } } usize::from_le_bytes(out_array) } pub(crate) enum LogScalar<'a> { /// A panic occurred, and a panic log is forthcoming BeginPanic, /// Some number of bytes will be appended to the log message AppendPanicMessage(&'a [u8]), } impl<'a> Into<[usize; 5]> for LogScalar<'a> { fn into(self) -> [usize; 5] { match self { LogScalar::BeginPanic => [1000, 0, 0, 0, 0], LogScalar::AppendPanicMessage(c) => // Text is grouped into 4x `usize` words. The id is 1100 plus // the number of characters in this message. // Ignore errors since we're already panicking. { [ 1100 + c.len(), group_or_null(&c, 0), group_or_null(&c, 1), group_or_null(&c, 2), group_or_null(&c, 3), ] } } } } /// Return a `Connection` to the log server, which is used for printing messages to /// the console and reporting panics. If the log server has not yet started, this /// will block until the server is running. It is safe to call this multiple times, /// because the address is shared among all threads in a process. pub(crate) fn log_server() -> Connection { static LOG_SERVER_CONNECTION: AtomicU32 = AtomicU32::new(0); let cid = LOG_SERVER_CONNECTION.load(Ordering::Relaxed); if cid != 0 { return cid.into(); } let cid = crate::os::xous::ffi::connect("xous-log-server ".try_into().unwrap()).unwrap(); LOG_SERVER_CONNECTION.store(cid.into(), Ordering::Relaxed); cid }