mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-04 04:27:34 +00:00
initial cut at splitting out the lib section of log-server
This commit is contained in:
parent
6811e23f20
commit
3b48ff8be7
4 changed files with 251 additions and 0 deletions
22
api/log-server/Cargo.toml
Normal file
22
api/log-server/Cargo.toml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
[package]
|
||||
authors = ["Sean Cross <sean@xobs.io>"]
|
||||
description = "Log server API"
|
||||
edition = "2018"
|
||||
name = "xousapi-log-server"
|
||||
version = "0.1.0"
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/betrusted-io/xous-core/"
|
||||
homepage = "https://betrusted.io/xous-book/"
|
||||
|
||||
# Dependency versions enforced by Cargo.lock.
|
||||
[dependencies]
|
||||
log = "0.4.14"
|
||||
num-derive = {version = "0.3.3", default-features = false}
|
||||
num-traits = {version = "0.2.14", default-features = false}
|
||||
xous = "0.9.8"
|
||||
xous-ipc = "0.9.7"
|
||||
|
||||
[features]
|
||||
debugprint = [] # adding this allocates the UART for debugging the logger
|
||||
logging = [] # adding this allocates the hardware UART for console interactions
|
||||
default = ["logging"]
|
||||
76
api/log-server/src/api.rs
Normal file
76
api/log-server/src/api.rs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
#[repr(C, align(4096))]
|
||||
pub struct LogRecord {
|
||||
pub file_length: u32,
|
||||
pub file: [u8; 128],
|
||||
pub line: Option<core::num::NonZeroU32>,
|
||||
pub module_length: u32,
|
||||
pub module: [u8; 128],
|
||||
pub level: u32,
|
||||
pub args_length: u32,
|
||||
pub args: [u8; 3820],
|
||||
}
|
||||
|
||||
impl Default for LogRecord {
|
||||
fn default() -> Self {
|
||||
LogRecord { file_length: 0, file: [0u8; 128], line: None, module_length: 0, module: [0u8; 128], level: 0, args_length: 0, args: [0u8; 3820] }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, num_derive::FromPrimitive, num_derive::ToPrimitive)]
|
||||
pub enum Opcode {
|
||||
/// A `LogRecord` message, delivering structured log output
|
||||
LogRecord = 0,
|
||||
|
||||
/// A `&[u8]` destined for stdout
|
||||
StandardOutput = 1,
|
||||
|
||||
/// A `&[u8]` destined for stderr
|
||||
StandardError = 2,
|
||||
|
||||
/// A `xous::StringBuffer` containing this program's name
|
||||
ProgramName = 3,
|
||||
|
||||
/// A panic occurred, and a panic log is forthcoming
|
||||
PanicStarted = 1000,
|
||||
|
||||
/// Log messages of varying size
|
||||
PanicMessage0 = 1100,
|
||||
PanicMessage1 = 1101,
|
||||
PanicMessage2 = 1102,
|
||||
PanicMessage3 = 1103,
|
||||
PanicMessage4 = 1104,
|
||||
PanicMessage5 = 1105,
|
||||
PanicMessage6 = 1106,
|
||||
PanicMessage7 = 1107,
|
||||
PanicMessage8 = 1108,
|
||||
PanicMessage9 = 1109,
|
||||
PanicMessage10 = 1110,
|
||||
PanicMessage11 = 1111,
|
||||
PanicMessage12 = 1112,
|
||||
PanicMessage13 = 1113,
|
||||
PanicMessage14 = 1114,
|
||||
PanicMessage15 = 1115,
|
||||
PanicMessage16 = 1116,
|
||||
PanicMessage17 = 1117,
|
||||
PanicMessage18 = 1118,
|
||||
PanicMessage19 = 1119,
|
||||
PanicMessage20 = 1120,
|
||||
PanicMessage21 = 1121,
|
||||
PanicMessage22 = 1122,
|
||||
PanicMessage23 = 1123,
|
||||
PanicMessage24 = 1124,
|
||||
PanicMessage25 = 1125,
|
||||
PanicMessage26 = 1126,
|
||||
PanicMessage27 = 1127,
|
||||
PanicMessage28 = 1128,
|
||||
PanicMessage29 = 1129,
|
||||
PanicMessage30 = 1130,
|
||||
PanicMessage31 = 1131,
|
||||
PanicMessage32 = 1132,
|
||||
|
||||
/// End of a panic
|
||||
PanicFinished = 1200,
|
||||
|
||||
/// Enable receiving messages when the system is resumed from sleep.
|
||||
EnableRx = 2000,
|
||||
}
|
||||
43
api/log-server/src/cursor.rs
Normal file
43
api/log-server/src/cursor.rs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/// no_std replacement for Cursor.
|
||||
|
||||
pub struct BufferWrapper<'a> {
|
||||
buf: &'a mut [u8],
|
||||
offset: usize,
|
||||
}
|
||||
|
||||
impl<'a> BufferWrapper<'a> {
|
||||
pub fn new(buf: &'a mut [u8]) -> Self {
|
||||
BufferWrapper {
|
||||
buf: buf,
|
||||
offset: 0,
|
||||
}
|
||||
}
|
||||
pub fn len(&self) -> usize {
|
||||
self.offset
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> core::fmt::Write for BufferWrapper<'a> {
|
||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||
let bytes = s.as_bytes();
|
||||
|
||||
// Skip over already-copied data
|
||||
let remainder = &mut self.buf[self.offset..];
|
||||
|
||||
// Check if there is space remaining (return error instead of panicking)
|
||||
if remainder.len() < bytes.len() {
|
||||
return Err(core::fmt::Error);
|
||||
}
|
||||
|
||||
// Make the two slices the same length
|
||||
let remainder = &mut remainder[..bytes.len()];
|
||||
|
||||
// Copy
|
||||
remainder.copy_from_slice(bytes);
|
||||
|
||||
// Update offset to avoid overwriting
|
||||
self.offset += bytes.len();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
110
api/log-server/src/lib.rs
Normal file
110
api/log-server/src/lib.rs
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
#![cfg_attr(target_os = "none", no_std)]
|
||||
use core::fmt::Write;
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
use num_traits::ToPrimitive;
|
||||
|
||||
pub mod api;
|
||||
mod cursor;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LogError {
|
||||
LoggerExists,
|
||||
NoConnection,
|
||||
}
|
||||
|
||||
struct XousLogger;
|
||||
static XOUS_LOGGER: XousLogger = XousLogger {};
|
||||
static XOUS_LOGGER_CONNECTION: AtomicU32 = AtomicU32::new(0);
|
||||
|
||||
impl XousLogger {
|
||||
fn log_impl(&self, record: &log::Record) {
|
||||
let mut log_record = api::LogRecord::default();
|
||||
assert_eq!(core::mem::size_of::<api::LogRecord>(), 4096);
|
||||
|
||||
// A "line" of 0 is the same as "None" for our purposes here.
|
||||
log_record.line = core::num::NonZeroU32::new(record.line().unwrap_or_default());
|
||||
|
||||
log_record.level = record.level() as u32;
|
||||
|
||||
let file = record.file().unwrap_or_default().as_bytes();
|
||||
log_record.file_length = file.len().min(file.len()) as u32;
|
||||
for (dest, src) in log_record.file.iter_mut().zip(file) {
|
||||
*dest = *src;
|
||||
}
|
||||
|
||||
let module = record.module_path().unwrap_or_default().as_bytes();
|
||||
log_record.module_length = module.len().min(module.len()) as u32;
|
||||
for (dest, src) in log_record.module.iter_mut().zip(module) {
|
||||
*dest = *src;
|
||||
}
|
||||
|
||||
// Serialize the text to our record buffer
|
||||
let mut wrapper = cursor::BufferWrapper::new(&mut log_record.args);
|
||||
write!(wrapper, "{}", record.args()).ok(); // truncate if error
|
||||
log_record.args_length = wrapper.len().min(log_record.args.len()) as u32;
|
||||
|
||||
let buf = unsafe {
|
||||
xous::MemoryRange::new(
|
||||
&log_record as *const api::LogRecord as usize,
|
||||
core::mem::size_of::<api::LogRecord>(),
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
xous::send_message(
|
||||
XOUS_LOGGER_CONNECTION.load(Ordering::Relaxed),
|
||||
xous::Message::new_lend(
|
||||
crate::api::Opcode::LogRecord.to_usize().unwrap(),
|
||||
buf,
|
||||
None,
|
||||
None,
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn resume(&self) {
|
||||
xous::send_message(
|
||||
XOUS_LOGGER_CONNECTION.load(Ordering::Relaxed),
|
||||
xous::Message::new_scalar(2000, 0, 0, 0, 0), // logger is one of the few servers that uses special, non-encoded message IDs.
|
||||
)
|
||||
.expect("couldn't send resume message to the logger implementation");
|
||||
}
|
||||
}
|
||||
|
||||
impl log::Log for XousLogger {
|
||||
fn enabled(&self, _metadata: &log::Metadata) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn log(&self, record: &log::Record) {
|
||||
XOUS_LOGGER.log_impl(record);
|
||||
}
|
||||
|
||||
fn flush(&self) {}
|
||||
}
|
||||
|
||||
pub fn init() -> Result<(), LogError> {
|
||||
XOUS_LOGGER_CONNECTION.store(
|
||||
xous::try_connect(xous::SID::from_bytes(b"xous-log-server ").unwrap())
|
||||
.or(Err(LogError::NoConnection))?,
|
||||
Ordering::Relaxed,
|
||||
);
|
||||
log::set_logger(&XOUS_LOGGER).map_err(|_| LogError::LoggerExists)?;
|
||||
log::set_max_level(log::LevelFilter::Info);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn init_wait() -> Result<(), ()> {
|
||||
XOUS_LOGGER_CONNECTION.store(
|
||||
xous::connect(xous::SID::from_bytes(b"xous-log-server ").unwrap()).or(Err(()))?,
|
||||
Ordering::Relaxed,
|
||||
);
|
||||
log::set_logger(&XOUS_LOGGER).or(Err(()))?;
|
||||
log::set_max_level(log::LevelFilter::Info);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn resume() {
|
||||
XOUS_LOGGER.resume();
|
||||
}
|
||||
Loading…
Reference in a new issue