ross_logger/
lib.rs

1#![no_std]
2
3use cortex_m::iprint;
4use stm32f1xx_hal::pac::{ITM, DCB};
5
6#[macro_export]
7macro_rules! log_debug {
8    ($logger:expr, $fmt:expr) => {
9        unsafe {
10            $logger.borrow_mut().log_debug($fmt);
11        }
12    };
13    ($logger:expr, $fmt:expr, $($arg:tt)*) => {
14        unsafe {
15            extern crate alloc;
16            $logger.borrow_mut().log_debug(&alloc::format!($fmt, $($arg)*));
17        }
18    };
19}
20
21#[macro_export]
22macro_rules! log_info {
23    ($logger:expr, $fmt:expr) => {
24        unsafe {
25            $logger.borrow_mut().log_info($fmt);
26        }
27    };
28    ($logger:expr, $fmt:expr, $($arg:tt)*) => {
29        unsafe {
30            extern crate alloc;
31            $logger.borrow_mut().log_info(&alloc::format!($fmt, $($arg)*));
32        }
33    };
34}
35
36#[macro_export]
37macro_rules! log_warning {
38    ($logger:expr, $fmt:expr) => {
39        unsafe {
40            $logger.borrow_mut().log_warning($fmt);
41        }
42    };
43    ($logger:expr, $fmt:expr, $($arg:tt)*) => {
44        unsafe {
45            extern crate alloc;
46            $logger.borrow_mut().log_warning(&alloc::format!($fmt, $($arg)*));
47        }
48    };
49}
50
51#[macro_export]
52macro_rules! log_error {
53    ($logger:expr, $fmt:expr) => {
54        unsafe {
55            $logger.borrow_mut().log_error($fmt);
56        }
57    };
58    ($logger:expr, $fmt:expr, $($arg:tt)*) => {
59        unsafe {
60            extern crate alloc;
61            $logger.borrow_mut().log_error(&alloc::format!($fmt, $($arg)*));
62        }
63    };
64}
65
66pub enum LogLevel {
67    Debug,
68    Info,
69    Warning,
70    Error,
71}
72
73pub struct Logger {
74    log_level: LogLevel,
75    itm: ITM,
76}
77
78impl Logger {
79    pub fn new(log_level: LogLevel, itm: ITM) -> Self {
80        Logger { log_level, itm }
81    }
82
83    pub fn change_log_level(&mut self, log_level: LogLevel) {
84        self.log_level = log_level;
85    }
86
87    pub fn log_debug(&mut self, message: &str) {
88        if matches!(self.log_level, LogLevel::Debug) {
89            self.log("[DEBUG] ");
90            self.log(message);
91            self.log("\r\n");
92        }
93    }
94
95    pub fn log_info(&mut self, message: &str) {
96        if matches!(self.log_level, LogLevel::Debug) || matches!(self.log_level, LogLevel::Info) {
97            self.log("[INFO] ");
98            self.log(message);
99            self.log("\r\n");
100        }
101    }
102
103    pub fn log_warning(&mut self, message: &str) {
104        if matches!(self.log_level, LogLevel::Debug)
105            || matches!(self.log_level, LogLevel::Info)
106            || matches!(self.log_level, LogLevel::Warning)
107        {
108            self.log("[WARNING] ");
109            self.log(message);
110            self.log("\r\n");
111        }
112    }
113
114    pub fn log_error(&mut self, message: &str) {
115        self.log("[ERROR] ");
116        self.log(message);
117        self.log("\r\n");
118    }
119
120    fn log(&mut self, message: &str) {
121        // If no debugger is attached, ITM hangs when trying to print
122        if !DCB::is_debugger_attached() {
123            return;
124        }
125
126        iprint!(&mut self.itm.stim[0], message);
127    }
128}