From 855b26aa1993f942886cc9b06ad0d77879cb5fd3 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Mon, 13 Jul 2020 14:59:56 +0800 Subject: [PATCH] Logger: ported log_buffer. --- src/runtime/src/logger.rs | 111 ++++++++++++++++++++++++++++++++++++++ src/runtime/src/main.rs | 13 ++++- 2 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 src/runtime/src/logger.rs diff --git a/src/runtime/src/logger.rs b/src/runtime/src/logger.rs new file mode 100644 index 00000000..2e3caca4 --- /dev/null +++ b/src/runtime/src/logger.rs @@ -0,0 +1,111 @@ +use core::cell::{Cell, RefCell, RefMut}; +use core::fmt::Write; +use log::{Log, LevelFilter}; +use log_buffer::LogBuffer; +use libboard_zynq::{println, timer::GlobalTimer}; + +pub struct LogBufferRef<'a> { + buffer: RefMut<'a, LogBuffer<&'static mut [u8]>>, + old_log_level: LevelFilter +} + +impl<'a> LogBufferRef<'a> { + fn new(buffer: RefMut<'a, LogBuffer<&'static mut [u8]>>) -> LogBufferRef<'a> { + let old_log_level = log::max_level(); + log::set_max_level(LevelFilter::Off); + LogBufferRef { buffer, old_log_level } + } + + pub fn is_empty(&self) -> bool { + self.buffer.is_empty() + } + + pub fn clear(&mut self) { + self.buffer.clear() + } + + pub fn extract(&mut self) -> &str { + self.buffer.extract() + } +} + +impl<'a> Drop for LogBufferRef<'a> { + fn drop(&mut self) { + log::set_max_level(self.old_log_level) + } +} + +pub struct BufferLogger { + buffer: RefCell>, + uart_filter: Cell +} + +static mut LOGGER: Option = None; + +impl BufferLogger { + pub fn new(buffer: &'static mut [u8]) -> BufferLogger { + BufferLogger { + buffer: RefCell::new(LogBuffer::new(buffer)), + uart_filter: Cell::new(LevelFilter::Info), + } + } + + pub fn register(self) { + unsafe { + LOGGER = Some(self); + log::set_logger(LOGGER.as_ref().unwrap()) + .expect("global logger can only be initialized once"); + } + } + + pub unsafe fn get_logger() -> &'static mut Option { + &mut LOGGER + } + + pub fn buffer<'a>(&'a self) -> Result, ()> { + self.buffer + .try_borrow_mut() + .map(LogBufferRef::new) + .map_err(|_| ()) + } + + pub fn uart_log_level(&self) -> LevelFilter { + self.uart_filter.get() + } + + pub fn set_uart_log_level(&self, max_level: LevelFilter) { + self.uart_filter.set(max_level) + } +} + +// required for impl Log +unsafe impl Sync for BufferLogger {} + +impl Log for BufferLogger { + fn enabled(&self, _metadata: &log::Metadata) -> bool { + true + } + + fn log(&self, record: &log::Record) { + if self.enabled(record.metadata()) { + let timestamp = unsafe { + GlobalTimer::get() + }.get_us(); + let seconds = timestamp / 1_000_000; + let micros = timestamp % 1_000_000; + + if let Ok(mut buffer) = self.buffer.try_borrow_mut() { + writeln!(buffer, "[{:6}.{:06}s] {:>5}({}): {}", seconds, micros, + record.level(), record.target(), record.args()).unwrap(); + } + + if record.level() <= self.uart_log_level() { + println!("[{:6}.{:06}s] {:>5}({}): {}", seconds, micros, + record.level(), record.target(), record.args()); + } + } + } + + fn flush(&self) { + } +} diff --git a/src/runtime/src/main.rs b/src/runtime/src/main.rs index 4c0c4189..1bef8b79 100644 --- a/src/runtime/src/main.rs +++ b/src/runtime/src/main.rs @@ -9,7 +9,7 @@ extern crate alloc; use core::{cmp, str}; use log::{info, warn}; -use libboard_zynq::{timer::GlobalTimer, time::Milliseconds, logger, devc, slcr}; +use libboard_zynq::{timer::GlobalTimer, time::Milliseconds, devc, slcr}; use libsupport_zynq::ram; use libregister::RegisterW; use nb::block; @@ -30,6 +30,7 @@ mod moninj; mod load_pl; mod eh_artiq; mod panic; +mod logger; fn init_gateware() { // Set up PS->PL clocks @@ -124,11 +125,19 @@ fn init_rtio(timer: GlobalTimer, cfg: &config::Config) { } } +static mut LOG_BUFFER: [u8; 1<<17] = [0; 1<<17]; + #[no_mangle] pub fn main_core0() { let timer = GlobalTimer::start(); - let _ = logger::init(); + + let buffer_logger = unsafe { + logger::BufferLogger::new(&mut LOG_BUFFER[..]) + }; + buffer_logger.set_uart_log_level(log::LevelFilter::Debug); + buffer_logger.register(); log::set_max_level(log::LevelFilter::Debug); + info!("NAR3/Zynq7000 starting..."); ram::init_alloc_linker();