osal-rs 0.4.7

Operating System Abstraction Layer for Rust with support for FreeRTOS and POSIX
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
/***************************************************************************
 *
 * osal-rs
 * Copyright (C) 2026 Antonio Salsi <passy.linux@zresa.it>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <https://www.gnu.org/licenses/>.
 *
 ***************************************************************************/

//! Logging system for embedded environments.
//!
//! Provides a flexible logging system with multiple severity levels and color support.
//! Designed for no-std environments with UART output support.
//!
//! # Features
//!
//! - Multiple log levels (DEBUG, INFO, WARNING, ERROR, FATAL)
//! - Color-coded output support (ANSI colors)
//! - Timestamp logging with millisecond precision
//! - Thread-safe logging with busy-wait synchronization
//! - Configurable log level masking
//! - Zero-cost when logs are disabled
//!
//! # Examples
//!
//! ## Basic logging
//!
//! ```ignore
//! use osal_rs::{log_info, log_error, log_debug};
//! 
//! log_info!("APP", "Application started");
//! log_debug!("APP", "Counter value: {}", 42);
//! log_error!("APP", "Failed to initialize: {}", error_msg);
//! ```
//!
//! ## Configuring log levels
//!
//! ```ignore
//! use osal_rs::log::*;
//! 
//! // Set log level to WARNING and above
//! set_level_log(log_levels::LEVEL_WARNING);
//! 
//! // Enable/disable logging
//! set_enable_log(true);
//! 
//! // Enable/disable color output
//! set_enable_color(true);
//! ```
//!
//! ## Using print macros
//!
//! ```ignore
//! use osal_rs::{print, println};
//! 
//! print!("Hello");
//! println!(" World!");
//! println!("Value: {}", 123);
//! ```
//!
//! # Thread Safety
//!
//! The logging system uses a simple busy-wait lock to ensure thread-safe output:
//! - Only one thread can log at a time
//! - Other threads spin-wait until the log is complete
//! - No heap allocation during the lock
//! - Suitable for task context only (see ISR Context below)
//!
//! # ISR Context
//!
//! **WARNING**: Do not use logging macros from interrupt service routines (ISRs).
//! 
//! Reasons:
//! - Busy-wait lock can cause priority inversion
//! - String formatting allocates memory
//! - UART operations may block
//! - Can significantly delay interrupt response
//!
//! If you need logging from ISR context, use a queue to defer the log to a task.
//!
//! # Performance Considerations
//!
//! - Each log call allocates a string (uses RTOS heap)
//! - UART transmission is synchronous and relatively slow
//! - Verbose logging (DEBUG level) can impact real-time performance
//! - Consider using WARNING or ERROR level in production
//! - Logs are compiled out when the level is disabled (zero cost)
//!
//! # Color Output
//!
//! When colors are enabled, log levels are color-coded:
//! - **DEBUG**: Cyan - Detailed debugging information
//! - **INFO**: Green - Normal operational messages
//! - **WARNING**: Yellow - Potential issues, non-critical
//! - **ERROR**: Red - Errors affecting functionality
//! - **FATAL**: Magenta - Critical errors, system failure
//!
//! Disable colors if your terminal doesn't support ANSI escape codes.
//!
//! # Best Practices
//!
//! 1. **Use appropriate tags**: Use meaningful tags like "NET", "FS", "APP" to identify sources
//! 2. **Choose correct levels**: DEBUG for development, INFO for milestones, ERROR for failures
//! 3. **Avoid logging in hot paths**: Logging can significantly slow down tight loops
//! 4. **Set production levels**: Use WARNING or ERROR level in production builds
//! 5. **Never log from ISRs**: Defer to task context using queues or notifications

#[cfg(not(feature = "std"))]
pub mod ffi {
    //! Foreign Function Interface (FFI) to C UART functions.
    //!
    //! This module provides low-level bindings to C functions for UART communication.
    //! These functions are only available in `no_std` mode.
    //!
    //! # Safety
    //!
    //! All functions in this module are `unsafe` because they:
    //! - Call external C code that cannot be verified by Rust
    //! - Require valid C string pointers (null-terminated)
    //! - May access hardware registers directly
    //! - Do not perform bounds checking
    //!
    //! # Platform Requirements
    //!
    //! The C implementation must provide `printf_on_uart` that:
    //! - Accepts printf-style format strings
    //! - Outputs to UART hardware
    //! - Is thread-safe (or only called from synchronized contexts)
    //! - Returns number of characters written, or negative on error
    
    use core::ffi::{c_char, c_int};

    unsafe extern "C" {
        /// FFI function to print formatted strings to UART.
        ///
        /// This is the low-level C function that interfaces with the hardware UART.
        /// Typically implemented in the platform-specific porting layer.
        ///
        /// # Safety
        ///
        /// - `format` must be a valid null-terminated C string
        /// - Variable arguments must match the format specifiers
        /// - Must not be called from multiple threads simultaneously (unless C implementation is thread-safe)
        ///
        /// # Parameters
        ///
        /// * `format` - Printf-style format string (null-terminated)
        /// * `...` - Variable arguments matching format specifiers
        ///
        /// # Returns
        ///
        /// Number of characters written, or negative value on error
        pub fn printf_on_uart(format: *const c_char, ...) -> c_int;

    }
}

use core::ffi::c_char;

use crate::log::ffi::printf_on_uart;
use crate::os::{System, SystemFn};
use crate::utils::Bytes;

pub const LOG_BUFFER_SIZE: usize = 256;

/// ANSI escape code for red text color
const COLOR_RED: &str = "\x1b[31m";
/// ANSI escape code for green text color
const COLOR_GREEN: &str = "\x1b[32m";
/// ANSI escape code for yellow text color
const COLOR_YELLOW: &str = "\x1b[33m";
/// ANSI escape code for blue text color
const COLOR_BLUE: &str = "\x1b[34m";
/// ANSI escape code for magenta text color
const COLOR_MAGENTA: &str = "\x1b[35m";
/// ANSI escape code for cyan text color
const COLOR_CYAN: &str = "\x1b[36m";
/// ANSI escape code to reset all text attributes
const COLOR_RESET: &str = "\x1b[0m";
/// Carriage return + line feed for proper terminal output
pub const RETURN: &str = "\r\n";

/// Log level flags and level configurations.
///
/// This module defines bit flags for different log levels and combined
/// level masks for filtering log messages.
///
/// # Flag vs Level
///
/// - **FLAGS** (`FLAG_*`): Individual bits for each log level, used internally
/// - **LEVELS** (`LEVEL_*`): Combined masks that include all levels at or above the specified severity
///
/// For example, `LEVEL_WARNING` includes WARNING, ERROR, and FATAL flags.
///
/// # Usage
///
/// ```ignore
/// use osal_rs::log::log_levels::*;
/// use osal_rs::log::set_level_log;
///
/// // Set minimum level to WARNING (shows WARNING, ERROR, FATAL)
/// set_level_log(LEVEL_WARNING);
///
/// // Check if specific level is enabled
/// if is_enabled_log(FLAG_DEBUG) {
///     // Debug is enabled
/// }
/// ```
pub mod log_levels {
    /// Flag for DEBUG level messages (bit 0, most verbose).
    ///
    /// Use for detailed debugging information during development.
    pub const FLAG_DEBUG: u8 = 1 << 0;
    
    /// Flag for INFO level messages (bit 1).
    ///
    /// Use for informational messages about normal operation.
    pub const FLAG_INFO: u8 = 1 << 1;
    
    /// Flag for WARNING level messages (bit 2).
    ///
    /// Use for potentially problematic situations that don't prevent operation.
    pub const FLAG_WARNING: u8 = 1 << 2;
    
    /// Flag for ERROR level messages (bit 3).
    ///
    /// Use for errors that affect functionality but allow continued operation.
    pub const FLAG_ERROR: u8 = 1 << 3;
    
    /// Flag for FATAL level messages (bit 4, most severe).
    ///
    /// Use for critical errors that prevent continued operation.
    pub const FLAG_FATAL: u8 = 1 << 4;
    
    /// Flag to enable color output (bit 6).
    ///
    /// When set, log messages are color-coded by severity level.
    pub const FLAG_COLOR_ON: u8 = 1 << 6;
    
    /// Flag to enable/disable logging entirely (bit 7).
    ///
    /// When clear, all logging is disabled for zero runtime cost.
    pub const FLAG_STATE_ON: u8 = 1 << 7;

    /// DEBUG level: Shows all messages (DEBUG, INFO, WARNING, ERROR, FATAL).
    ///
    /// Most verbose setting, suitable for development and troubleshooting.
    pub const LEVEL_DEBUG: u8 = FLAG_DEBUG | FLAG_INFO | FLAG_WARNING | FLAG_ERROR | FLAG_FATAL;
    
    /// INFO level: Shows INFO and above (INFO, WARNING, ERROR, FATAL).
    ///
    /// Filters out DEBUG messages, suitable for normal operation.
    pub const LEVEL_INFO: u8 = FLAG_INFO | FLAG_WARNING | FLAG_ERROR | FLAG_FATAL;
    
    /// WARNING level: Shows WARNING and above (WARNING, ERROR, FATAL).
    ///
    /// Shows only warnings and errors, suitable for production.
    pub const LEVEL_WARNING: u8 = FLAG_WARNING | FLAG_ERROR | FLAG_FATAL;
    
    /// ERROR level: Shows ERROR and FATAL only.
    ///
    /// Shows only errors and critical failures.
    pub const LEVEL_ERROR: u8 = FLAG_ERROR | FLAG_FATAL;

    /// FATAL level: Shows only FATAL messages.
    ///
    /// Most restrictive setting, shows only critical failures.
    pub const LEVEL_FATAL: u8 = FLAG_FATAL;
}

/// Global log level mask with color and state flags enabled by default.
///
/// This mutable static holds the current logging configuration:
/// - Bits 0-4: Log level flags (DEBUG, INFO, WARNING, ERROR, FATAL)
/// - Bit 6: Color enable flag
/// - Bit 7: Logging enable/disable flag
///
/// # Default
///
/// Initialized to `LEVEL_DEBUG | FLAG_COLOR_ON | FLAG_STATE_ON`:
/// - All log levels enabled
/// - Color output enabled
/// - Logging enabled
///
/// # Thread Safety
///
/// Modifications are not atomic. Use the provided setter functions
/// (`set_level_log`, `set_enable_log`, `set_enable_color`) which perform
/// simple bit operations that are effectively atomic on most platforms.
/// Race conditions during initialization are unlikely to cause issues
/// beyond temporarily incorrect filter settings.
static mut MASK: u8 = log_levels::LEVEL_DEBUG | log_levels::FLAG_COLOR_ON | log_levels::FLAG_STATE_ON;

/// Simple busy flag for thread-safe logging (0 = free, non-zero = busy).
///
/// Used as a spinlock to ensure only one thread logs at a time:
/// - 0 = Lock is free, logging available
/// - Non-zero = Lock is held, other threads must wait
///
/// # Synchronization
///
/// Uses a basic busy-wait (spinlock) pattern:
/// 1. Wait until BUSY == 0
/// 2. Set BUSY = 1
/// 3. Perform logging
/// 4. Set BUSY = 0
///
/// # Limitations
///
/// - Not a true atomic operation (no memory barriers)
/// - Priority inversion possible (low-priority task holds lock)
/// - Wastes CPU cycles during contention
/// - **Never use from ISR context** - can deadlock
///
/// This simple approach is sufficient for most embedded use cases where
/// logging contention is infrequent.
static mut BUSY: u8 = 0;

/// Prints formatted text to UART without a newline.
///
/// This macro is only available in no-std mode. In std mode, use the standard `print!` macro.
///
/// # Examples
///
/// ```ignore
/// use osal_rs::print;
/// 
/// print!("Hello");
/// print!(" World: {}", 42);
/// ```
#[cfg(not(feature = "std"))]
#[macro_export]
macro_rules! print {
    ($($arg:tt)*) => {{
        unsafe {
            let mut buf = $crate::utils::Bytes::<{$crate::log::LOG_BUFFER_SIZE}>::new();
            buf.format(format_args!($($arg)*));
            $crate::log::ffi::printf_on_uart(b"%s\0".as_ptr() as *const core::ffi::c_char, buf.as_cstr().as_ptr());
        }
    }};
}

/// Prints formatted text to UART with a newline (\r\n).
///
/// This macro is only available in no-std mode. In std mode, use the standard `println!` macro.
///
/// # Examples
///
/// ```ignore
/// use osal_rs::println;
/// 
/// println!("Hello World");
/// println!("Value: {}", 42);
/// println!();  // Just a newline
/// ```
#[cfg(not(feature = "std"))]
#[macro_export]
macro_rules! println {
    () => {
        $crate::print!("\r\n")
    };
    ($fmt:expr) => {{
        unsafe {
            let mut buf = $crate::utils::Bytes::<{$crate::log::LOG_BUFFER_SIZE}>::new();
            buf.format(format_args!(concat!($fmt, "\r\n")));
            $crate::log::ffi::printf_on_uart(b"%s\0".as_ptr() as *const core::ffi::c_char, buf.as_cstr().as_ptr());
        }
    }};
    ($fmt:expr, $($arg:tt)*) => {{
        unsafe {
            let mut buf = $crate::utils::Bytes::<{$crate::log::LOG_BUFFER_SIZE}>::new();
            buf.format(format_args!(concat!($fmt, "\r\n"), $($arg)*));
            $crate::log::ffi::printf_on_uart(b"%s\0".as_ptr() as *const core::ffi::c_char, buf.as_cstr().as_ptr());
        }
    }};
}

/// Sets the log level threshold.
///
/// Only log messages at or above this level will be displayed.
///
/// # Parameters
///
/// * `level` - Log level (use constants from `log_levels` module)
///
/// # Examples
///
/// ```ignore
/// use osal_rs::log::*;
/// 
/// // Show only warnings and errors
/// set_level_log(log_levels::LEVEL_WARNING);
/// 
/// // Show all messages
/// set_level_log(log_levels::LEVEL_DEBUG);
/// ```
pub fn set_level_log(level: u8) {
    unsafe {
        MASK =
            (MASK & log_levels::FLAG_STATE_ON) | (level & !log_levels::FLAG_STATE_ON);
    }
}

/// Enables or disables all logging.
///
/// When disabled, all log macros become no-ops for zero runtime cost.
///
/// # Parameters
///
/// * `enabled` - `true` to enable logging, `false` to disable
///
/// # Examples
///
/// ```ignore
/// use osal_rs::log::set_enable_log;
/// 
/// set_enable_log(false);  // Disable all logging
/// // ... logs will not be printed ...
/// set_enable_log(true);   // Re-enable logging
/// ```
pub fn set_enable_log(enabled: bool) {
    unsafe {
        if enabled {
            MASK |= log_levels::FLAG_STATE_ON;
        } else {
            MASK &= !log_levels::FLAG_STATE_ON;
        }
    }
}

/// Checks if logging is currently enabled.
///
/// # Returns
///
/// `true` if logging is enabled, `false` otherwise
///
/// # Examples
///
/// ```ignore
/// use osal_rs::log::get_enable_log;
/// 
/// if get_enable_log() {
///     println!("Logging is active");
/// }
/// ```
pub fn get_enable_log() -> bool {
    unsafe { (MASK & log_levels::FLAG_STATE_ON) != 0 }
}

/// Checks if a specific log level is enabled.
///
/// # Parameters
///
/// * `log_type` - Log level flag to check
///
/// # Returns
///
/// `true` if the log level is enabled, `false` otherwise
///
/// # Examples
///
/// ```ignore
/// use osal_rs::log::*;
/// 
/// if is_enabled_log(log_levels::FLAG_DEBUG) {
///     // Debug logging is active
/// }
/// ```
pub fn is_enabled_log(log_type: u8) -> bool {
    unsafe { (MASK & log_levels::FLAG_STATE_ON) != 0 && (MASK & log_type) != 0 }
}

/// Gets the current log level threshold.
///
/// # Returns
///
/// Current log level mask (without state and color flags)
///
/// # Examples
///
/// ```ignore
/// use osal_rs::log::*;
/// 
/// let level = get_level_log();
/// ```
pub fn get_level_log() -> u8 {
    unsafe { MASK & !log_levels::FLAG_STATE_ON & !log_levels::FLAG_COLOR_ON }
}

/// Enables or disables color output.
///
/// When enabled, log messages are color-coded by severity:
/// - DEBUG: Cyan
/// - INFO: Green  
/// - WARNING: Yellow
/// - ERROR: Red
/// - FATAL: Magenta
///
/// # Parameters
///
/// * `enabled` - `true` to enable colors, `false` for plain text
///
/// # Examples
///
/// ```ignore
/// use osal_rs::log::set_enable_color;
/// 
/// set_enable_color(true);   // Enable colored output
/// set_enable_color(false);  // Disable colors
/// ```
pub fn set_enable_color(enabled: bool) {
    unsafe {
        if enabled {
            MASK |= log_levels::FLAG_COLOR_ON;
        } else {
            MASK &= !log_levels::FLAG_COLOR_ON;
        }
    }
}



/// Core logging function that outputs formatted log messages.
///
/// This is the low-level function called by all log macros. It handles:
/// - Thread-safe output using a busy-wait lock
/// - Color formatting based on log level
/// - Timestamp prefixing with millisecond precision
/// - Tag prefixing for message categorization
///
/// # Parameters
///
/// * `tag` - Category or module name for the log message (e.g., "APP", "NET", "FS")
/// * `log_type` - Log level flag (DEBUG, INFO, WARNING, ERROR, FATAL)
/// * `to_print` - The formatted message string to log
///
/// # Thread Safety
///
/// Uses a busy-wait lock (BUSY flag) to ensure only one thread logs at a time:
/// 1. Spins until BUSY == 0
/// 2. Sets BUSY = 1
/// 3. Formats and outputs the message
/// 4. Sets BUSY = 0
///
/// Other threads will spin-wait during this time.
///
/// # Output Format
///
/// In `no_std` mode:
/// ```text
/// {color}({timestamp}ms)[{tag}] {message}{color_reset}\r\n
/// ```
///
/// Example:
/// ```text
/// \x1b[32m(1234ms)[APP] System initialized\x1b[0m\r\n
/// ```
///
/// # Examples
///
/// ```ignore
/// use osal_rs::log::*;
/// 
/// sys_log("APP", log_levels::FLAG_INFO, "Application started");
/// sys_log("NET", log_levels::FLAG_ERROR, "Connection failed");
/// ```
///
/// # Note
///
/// Prefer using the log macros (`log_info!`, `log_error!`, etc.) instead of
/// calling this function directly. The macros check if the log level is enabled
/// before formatting the message, avoiding allocation for disabled levels.
///
/// # Warning
///
/// **Never call from ISR context** - the busy-wait can cause deadlock if a
/// higher-priority ISR preempts a task that holds the lock.
pub fn sys_log(tag: &str, log_type: u8, to_print: &str) {
    unsafe {
        while BUSY != 0 {}
        BUSY = 1;

        let mut color_reset = COLOR_RESET;
        let color = if MASK & log_levels::FLAG_COLOR_ON == log_levels::FLAG_COLOR_ON {

            match log_type {
                log_levels::FLAG_DEBUG => COLOR_CYAN,
                log_levels::FLAG_INFO => COLOR_GREEN,
                log_levels::FLAG_WARNING => COLOR_YELLOW,
                log_levels::FLAG_ERROR => COLOR_RED,
                log_levels::FLAG_FATAL => COLOR_MAGENTA,
                _ => COLOR_RESET,
            }
        } else {
            color_reset = "";
            ""
        };


        let now = System::get_current_time_us();


        #[cfg(not(feature = "std"))]
        {
            let mut buf = Bytes::<512>::new();
            buf.format(format_args!("{color}({millis}ms)[{tag}] {to_print}{color_reset}{RETURN}", millis=now.as_millis()));
            printf_on_uart(b"%s\0".as_ptr() as *const c_char, buf.as_cstr().as_ptr());
        }

        #[cfg(feature = "std")]
        {
            print!("{}[{}] ", color, tag);
            core::fmt::write(&mut core::fmt::Formatter::new(), args).unwrap();
            print!("{}", COLOR_RESET);
            print!("\r\n");
        }

        BUSY = 0;
    }
}

/// Logs a DEBUG level message.
///
/// Debug messages are the most verbose and typically used during development.
/// Color: Cyan (if colors are enabled)
///
/// # Parameters
///
/// * `app_tag` - Category or module identifier
/// * `fmt` - Format string
/// * `arg` - Optional format arguments
///
/// # Examples
///
/// ```ignore
/// use osal_rs::log_debug;
/// 
/// log_debug!("APP", "Initializing subsystem");
/// log_debug!("APP", "Counter: {}, Status: {}", counter, status);
/// ```
#[macro_export]
macro_rules! log_debug {
    ($app_tag:expr, $fmt:expr $(, $($arg:tt)*)?) => {{
        if $crate::log::is_enabled_log($crate::log::log_levels::FLAG_DEBUG) {
            let mut msg = $crate::utils::Bytes::<{$crate::log::LOG_BUFFER_SIZE}>::new();
            msg.format(format_args!($fmt $(, $($arg)*)?));
            $crate::log::sys_log($app_tag, $crate::log::log_levels::FLAG_DEBUG, msg.as_str());
        }
    }};
}

/// Logs an INFO level message.
///
/// Informational messages about normal application operation.
/// Color: Green (if colors are enabled)
///
/// # Parameters
///
/// * `app_tag` - Category or module identifier
/// * `fmt` - Format string  
/// * `arg` - Optional format arguments
///
/// # Examples
///
/// ```ignore
/// use osal_rs::log_info;
/// 
/// log_info!("APP", "System initialized successfully");
/// log_info!("NET", "Connected to server at {}", ip_addr);
/// ```
#[macro_export]
macro_rules! log_info {
    ($app_tag:expr, $fmt:expr $(, $($arg:tt)*)?) => {{
        if $crate::log::is_enabled_log($crate::log::log_levels::FLAG_INFO) {
            let mut msg = $crate::utils::Bytes::<{$crate::log::LOG_BUFFER_SIZE}>::new();
            msg.format(format_args!($fmt $(, $($arg)*)?));
            $crate::log::sys_log($app_tag, $crate::log::log_levels::FLAG_INFO, msg.as_str());
        }
    }};
}

/// Logs a WARNING level message.
///
/// Warning messages indicate potential issues that don't prevent operation.
/// Color: Yellow (if colors are enabled)
///
/// # Parameters
///
/// * `app_tag` - Category or module identifier
/// * `fmt` - Format string
/// * `arg` - Optional format arguments
///
/// # Examples
///
/// ```ignore
/// use osal_rs::log_warning;
/// 
/// log_warning!("MEM", "Memory usage above 80%");
/// log_warning!("SENSOR", "Temperature high: {} C", temp);
/// ```
#[macro_export]
macro_rules! log_warning {
    ($app_tag:expr, $fmt:expr $(, $($arg:tt)*)?) => {{
        if $crate::log::is_enabled_log($crate::log::log_levels::FLAG_WARNING) {
            let mut msg = $crate::utils::Bytes::<{$crate::log::LOG_BUFFER_SIZE}>::new();
            msg.format(format_args!($fmt $(, $($arg)*)?));
            $crate::log::sys_log($app_tag, $crate::log::log_levels::FLAG_WARNING, msg.as_str());
        }
    }};
}

/// Logs an ERROR level message.
///
/// Error messages indicate failures that affect functionality.
/// Color: Red (if colors are enabled)
///
/// # Parameters
///
/// * `app_tag` - Category or module identifier
/// * `fmt` - Format string
/// * `arg` - Optional format arguments
///
/// # Examples
///
/// ```ignore
/// use osal_rs::log_error;
/// 
/// log_error!("FS", "Failed to open file");
/// log_error!("NET", "Connection timeout: {}", error);
/// ```
#[macro_export]
macro_rules! log_error {
    ($app_tag:expr, $fmt:expr $(, $($arg:tt)*)?) => {{
        if $crate::log::is_enabled_log($crate::log::log_levels::FLAG_ERROR) {
            let mut msg = $crate::utils::Bytes::<{$crate::log::LOG_BUFFER_SIZE}>::new();
            msg.format(format_args!($fmt $(, $($arg)*)?));
            $crate::log::sys_log($app_tag, $crate::log::log_levels::FLAG_ERROR, msg.as_str());
        }
    }};
}

/// Logs a FATAL level message.
///
/// Fatal messages indicate critical errors that prevent continued operation.
/// Color: Magenta (if colors are enabled)
///
/// # Parameters
///
/// * `app_tag` - Category or module identifier
/// * `fmt` - Format string
/// * `arg` - Optional format arguments
///
/// # Examples
///
/// ```ignore
/// use osal_rs::log_fatal;
/// 
/// log_fatal!("SYS", "Kernel panic!");
/// log_fatal!("HW", "Hardware fault detected: {}", fault_code);
/// ```
#[macro_export]
macro_rules! log_fatal {
    ($app_tag:expr, $fmt:expr $(, $($arg:tt)*)?) => {{
        if $crate::log::is_enabled_log($crate::log::log_levels::FLAG_FATAL) {
            let mut msg = $crate::utils::Bytes::<{$crate::log::LOG_BUFFER_SIZE}>::new();
            msg.format(format_args!($fmt $(, $($arg)*)?));
            $crate::log::sys_log($app_tag, $crate::log::log_levels::FLAG_FATAL, msg.as_str());
        }
    }};
}