1#[cfg(not(feature = "std"))]
2pub mod ffi {
3 use core::ffi::{c_char, c_int};
4
5 unsafe extern "C" {
6 pub fn printf_on_uart(format: *const c_char, ...) -> c_int;
7
8 }
9}
10
11use core::ffi::c_char;
12
13use alloc::{ffi::CString, format};
14
15use crate::log::ffi::printf_on_uart;
16use crate::os::{System, SystemFn};
17
18
19const COLOR_RED: &str = "\x1b[31m";
20const COLOR_GREEN: &str = "\x1b[32m";
21const COLOR_YELLOW: &str = "\x1b[33m";
22const COLOR_BLUE: &str = "\x1b[34m";
23const COLOR_MAGENTA: &str = "\x1b[35m";
24const COLOR_CYAN: &str = "\x1b[36m";
25const COLOR_RESET: &str = "\x1b[0m";
26pub const RETURN: &str = "\r\n";
27
28pub mod log_levels {
29 pub const FLAG_DEBUG: u8 = 1 << 0;
30 pub const FLAG_INFO: u8 = 1 << 1;
31 pub const FLAG_WARNING: u8 = 1 << 2;
32 pub const FLAG_ERROR: u8 = 1 << 3;
33 pub const FLAG_FATAL: u8 = 1 << 4;
34 pub const FLAG_COLOR_ON: u8 = 1 << 6;
35 pub const FLAG_STATE_ON: u8 = 1 << 7;
36
37 pub const LEVEL_DEBUG: u8 = FLAG_DEBUG | FLAG_INFO | FLAG_WARNING | FLAG_ERROR | FLAG_FATAL;
38 pub const LEVEL_INFO: u8 = FLAG_INFO | FLAG_WARNING | FLAG_ERROR | FLAG_FATAL;
39 pub const LEVEL_WARNING: u8 = FLAG_WARNING | FLAG_ERROR | FLAG_FATAL;
40 pub const LEVEL_ERROR: u8 = FLAG_ERROR | FLAG_FATAL;
41
42 pub const LEVEL_FATAL: u8 = FLAG_FATAL;
43}
44
45static mut MASK: u8 = log_levels::LEVEL_DEBUG | log_levels::FLAG_COLOR_ON | log_levels::FLAG_STATE_ON;
46static mut BUSY: u8 = 0;
47
48#[cfg(not(feature = "std"))]
49#[macro_export]
50macro_rules! print {
51 ($($arg:tt)*) => {{
52 unsafe {
53 use alloc::string::ToString;
54 let formatted = alloc::format!($($arg)*);
55 if let Ok(c_str) = alloc::ffi::CString::new(formatted) {
56 $crate::log::ffi::printf_on_uart(b"%s\0".as_ptr() as *const core::ffi::c_char, c_str.as_ptr());
57 }
58 }
59 }};
60}
61
62#[cfg(not(feature = "std"))]
63#[macro_export]
64macro_rules! println {
65 () => {
66 $crate::print!("\r\n")
67 };
68 ($fmt:expr) => {{
69 unsafe {
70 use alloc::string::ToString;
71 let formatted = alloc::format!(concat!($fmt, "\r\n"));
72 if let Ok(c_str) = alloc::ffi::CString::new(formatted) {
73 $crate::log::ffi::printf_on_uart(b"%s\0".as_ptr() as *const core::ffi::c_char, c_str.as_ptr());
74 }
75 }
76 }};
77 ($fmt:expr, $($arg:tt)*) => {{
78 unsafe {
79 use alloc::string::ToString;
80 let formatted = alloc::format!(concat!($fmt, "\r\n"), $($arg)*);
81 if let Ok(c_str) = alloc::ffi::CString::new(formatted) {
82 $crate::log::ffi::printf_on_uart(b"%s\0".as_ptr() as *const core::ffi::c_char, c_str.as_ptr());
83 }
84 }
85 }};
86}
87
88pub fn set_level_log(level: u8) {
89 unsafe {
90 MASK =
91 (MASK & log_levels::FLAG_STATE_ON) | (level & !log_levels::FLAG_STATE_ON);
92 }
93}
94
95pub fn set_enable_log(enabled: bool) {
96 unsafe {
97 if enabled {
98 MASK |= log_levels::FLAG_STATE_ON;
99 } else {
100 MASK &= !log_levels::FLAG_STATE_ON;
101 }
102 }
103}
104
105pub fn get_enable_log() -> bool {
106 unsafe { (MASK & log_levels::FLAG_STATE_ON) != 0 }
107}
108
109pub fn is_enabled_log(log_type: u8) -> bool {
110 unsafe { (MASK & log_levels::FLAG_STATE_ON) != 0 && (MASK & log_type) != 0 }
111}
112
113pub fn get_level_log() -> u8 {
114 unsafe { MASK & !log_levels::FLAG_STATE_ON & !log_levels::FLAG_COLOR_ON }
115}
116
117pub fn set_enable_color(enabled: bool) {
118 unsafe {
119 if enabled {
120 MASK |= log_levels::FLAG_COLOR_ON;
121 } else {
122 MASK &= !log_levels::FLAG_COLOR_ON;
123 }
124 }
125}
126
127
128
129pub fn sys_log(tag: &str, log_type: u8, to_print: &str) {
130 unsafe {
131 while BUSY != 0 {}
132 BUSY = 1;
133
134 let mut color_reset = COLOR_RESET;
135 let color = if MASK & log_levels::FLAG_COLOR_ON == log_levels::FLAG_COLOR_ON {
136
137 match log_type {
138 log_levels::FLAG_DEBUG => COLOR_CYAN,
139 log_levels::FLAG_INFO => COLOR_GREEN,
140 log_levels::FLAG_WARNING => COLOR_YELLOW,
141 log_levels::FLAG_ERROR => COLOR_RED,
142 log_levels::FLAG_FATAL => COLOR_MAGENTA,
143 _ => COLOR_RESET,
144 }
145 } else {
146 color_reset = "";
147 ""
148 };
149
150
151 let now = System::get_current_time_us();
152
153
154 #[cfg(not(feature = "std"))]
155 {
156 let formatted = format!("{color}({millis}ms)[{tag}] {to_print}{color_reset}{RETURN}", millis=now.as_millis());
157 if let Ok(c_str) = CString::new(formatted) {
158 printf_on_uart(b"%s\0".as_ptr() as *const c_char, c_str.as_ptr());
159 }
160 }
161
162 #[cfg(feature = "std")]
163 {
164 print!("{}[{}] ", color, tag);
165 core::fmt::write(&mut core::fmt::Formatter::new(), args).unwrap();
166 print!("{}", COLOR_RESET);
167 print!("\r\n");
168 }
169
170 BUSY = 0;
171 }
172}
173
174#[macro_export]
175macro_rules! log_debug {
176 ($app_tag:expr, $fmt:expr $(, $($arg:tt)*)?) => {{
177 if $crate::log::is_enabled_log($crate::log::log_levels::FLAG_DEBUG) {
178 let msg = alloc::format!($fmt $(, $($arg)*)?);
179 $crate::log::sys_log($app_tag, $crate::log::log_levels::FLAG_DEBUG, &msg);
180 }
181 }};
182}
183
184#[macro_export]
185macro_rules! log_info {
186 ($app_tag:expr, $fmt:expr $(, $($arg:tt)*)?) => {{
187 if $crate::log::is_enabled_log($crate::log::log_levels::FLAG_INFO) {
188 let msg = alloc::format!($fmt $(, $($arg)*)?);
189 $crate::log::sys_log($app_tag, $crate::log::log_levels::FLAG_INFO, &msg);
190 }
191 }};
192}
193
194#[macro_export]
195macro_rules! log_warning {
196 ($app_tag:expr, $fmt:expr $(, $($arg:tt)*)?) => {{
197 if $crate::log::is_enabled_log($crate::log::log_levels::FLAG_WARNING) {
198 let msg = alloc::format!($fmt $(, $($arg)*)?);
199 $crate::log::sys_log($app_tag, $crate::log::log_levels::FLAG_WARNING, &msg);
200 }
201 }};
202}
203
204#[macro_export]
205macro_rules! log_error {
206 ($app_tag:expr, $fmt:expr $(, $($arg:tt)*)?) => {{
207 if $crate::log::is_enabled_log($crate::log::log_levels::FLAG_ERROR) {
208 let msg = alloc::format!($fmt $(, $($arg)*)?);
209 $crate::log::sys_log($app_tag, $crate::log::log_levels::FLAG_ERROR, &msg);
210 }
211 }};
212}
213
214#[macro_export]
215macro_rules! log_fatal {
216 ($app_tag:expr, $fmt:expr $(, $($arg:tt)*)?) => {{
217 if $crate::log::is_enabled_log($crate::log::log_levels::FLAG_FATAL) {
218 let msg = alloc::format!($fmt $(, $($arg)*)?);
219 $crate::log::sys_log($app_tag, $crate::log::log_levels::FLAG_FATAL, &msg);
220 }
221 }};
222}