cortex_m_logger/
lib.rs

1//! # Semihosting or ITM logger for cortex-m applications
2
3#![no_std]
4
5#[cfg(feature = "semihosting")]
6mod semihosting {
7    use log::{Log, Metadata, Record};
8
9    /// A logger with a semihosting backend
10    ///
11    /// Does no filtering
12    #[derive(Default, Clone, Copy)]
13    pub struct SemihostingLogger;
14
15    impl Log for SemihostingLogger {
16        fn log(&self, record: &Record) {
17            let _ = cortex_m_semihosting::hprintln!(
18                "[{} {}] {}",
19                record.level(),
20                record.target(),
21                record.args()
22            );
23        }
24
25        fn enabled(&self, _: &Metadata) -> bool {
26            true
27        }
28
29        fn flush(&self) {}
30    }
31
32    impl SemihostingLogger {
33        pub fn init() {
34            log::set_logger(&SemihostingLogger).unwrap()
35        }
36    }
37}
38#[cfg(feature = "semihosting")]
39pub use self::semihosting::*;
40
41mod itm {
42    use cortex_m::peripheral::ITM;
43    use log::{Log, Metadata, Record};
44
45    /// A logger with an ITM backend
46    ///
47    /// Does no filtering, uses a different stimulus port for each logging level,
48    /// starting at 1.
49    #[derive(Default, Clone, Copy)]
50    pub struct ITMLogger;
51
52    impl Log for ITMLogger {
53        fn log(&self, record: &Record) {
54            cortex_m::iprintln!(
55                unsafe { &mut (&mut *ITM::ptr()).stim[record.level() as usize] },
56                "[{}] {}",
57                record.target(),
58                record.args()
59            );
60        }
61
62        fn enabled(&self, _: &Metadata) -> bool {
63            true
64        }
65
66        fn flush(&self) {}
67    }
68
69    impl ITMLogger {
70        pub fn init() {
71            log::set_logger(&ITMLogger).unwrap()
72        }
73    }
74}
75pub use self::itm::*;