1use super::println;
2use alloc::string::String;
3use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
4use embassy_sync::channel::Channel;
5
6extern crate alloc;
7
8struct LogMessage {
10 level: log::Level,
11 args: String,
12 timestamp: u64,
13}
14
15static LOG_CHANNEL: Channel<CriticalSectionRawMutex, LogMessage, 1024> = Channel::new();
17static mut LOGGER: MpfsLogger = MpfsLogger {
18 level: log::LevelFilter::Error,
19};
20
21pub fn init_logger(level: log::LevelFilter) {
23 unsafe {
24 LOGGER.level = level;
25 #[allow(static_mut_refs)]
26 log::set_logger_racy(&LOGGER).unwrap();
27 log::set_max_level_racy(level);
28 }
29}
30
31pub async fn log_task() -> ! {
32 let receiver = LOG_CHANNEL.receiver();
33 loop {
34 if let Ok(message) = receiver.try_receive() {
36 const RESET: &str = "\u{001B}[0m";
37 const RED: &str = "\u{001B}[31m";
38 const GREEN: &str = "\u{001B}[32m";
39 const YELLOW: &str = "\u{001B}[33m";
40 const BLUE: &str = "\u{001B}[34m";
41 const CYAN: &str = "\u{001B}[35m";
42
43 #[cfg(feature = "log-colors")]
44 let color = match message.level {
45 log::Level::Error => RED,
46 log::Level::Warn => YELLOW,
47 log::Level::Info => GREEN,
48 log::Level::Debug => BLUE,
49 log::Level::Trace => CYAN,
50 };
51 #[cfg(feature = "log-colors")]
52 let reset = RESET;
53
54 #[cfg(not(feature = "log-colors"))]
55 let color = "";
56 #[cfg(not(feature = "log-colors"))]
57 let reset = "";
58
59 println!(
60 "{}{} [{:?}] - {}{}",
61 color, message.level, message.timestamp, message.args, reset
62 );
63 }
64 yield_now().await;
65 }
66}
67
68struct MpfsLogger {
69 level: log::LevelFilter,
70}
71
72impl log::Log for MpfsLogger {
73 fn enabled(&self, metadata: &log::Metadata) -> bool {
74 metadata.level() <= self.level
75 }
76
77 #[allow(unused)]
78 fn log(&self, record: &log::Record) {
79 if !self.enabled(&record.metadata()) {
80 return;
81 }
82
83 let mut args = String::new();
84 let _ = core::fmt::write(&mut args, *record.args());
85
86 let message = LogMessage {
88 level: record.level(),
89 args,
90 timestamp: unsafe { crate::pac::readmcycle() / 600 }, };
92
93 let _ = LOG_CHANNEL.try_send(message);
94 }
95
96 fn flush(&self) {}
97}
98
99use core::future::Future;
102use core::pin::Pin;
103use core::task::{Context, Poll};
104
105fn yield_now() -> impl Future<Output = ()> {
106 YieldNowFuture { yielded: false }
107}
108
109#[must_use = "futures do nothing unless you `.await` or poll them"]
110struct YieldNowFuture {
111 yielded: bool,
112}
113
114impl Future for YieldNowFuture {
115 type Output = ();
116 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
117 if self.yielded {
118 Poll::Ready(())
119 } else {
120 self.yielded = true;
121 cx.waker().wake_by_ref();
122 Poll::Pending
123 }
124 }
125}