osal_rs/
log.rs

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}