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
//! # Semihosting or ITM logger for cortex-m applications

#![no_std]

#[cfg(feature = "semihosting")]
mod semihosting {
    use log::{Log, Metadata, Record};

    /// A logger with a semihosting backend
    ///
    /// Does no filtering
    #[derive(Default, Clone, Copy)]
    pub struct SemihostingLogger;

    impl Log for SemihostingLogger {
        fn log(&self, record: &Record) {
            let _ = cortex_m_semihosting::hprintln!(
                "[{} {}] {}",
                record.level(),
                record.target(),
                record.args()
            );
        }

        fn enabled(&self, _: &Metadata) -> bool {
            true
        }

        fn flush(&self) {}
    }

    impl SemihostingLogger {
        pub fn init() {
            log::set_logger(&SemihostingLogger).unwrap()
        }
    }
}
#[cfg(feature = "semihosting")]
pub use self::semihosting::*;

mod itm {
    use cortex_m::peripheral::ITM;
    use log::{Log, Metadata, Record};

    /// A logger with an ITM backend
    ///
    /// Does no filtering, uses a different stimulus port for each logging level,
    /// starting at 1.
    #[derive(Default, Clone, Copy)]
    pub struct ITMLogger;

    impl Log for ITMLogger {
        fn log(&self, record: &Record) {
            cortex_m::iprintln!(
                unsafe { &mut (&mut *ITM::ptr()).stim[record.level() as usize] },
                "[{}] {}",
                record.target(),
                record.args()
            );
        }

        fn enabled(&self, _: &Metadata) -> bool {
            true
        }

        fn flush(&self) {}
    }

    impl ITMLogger {
        pub fn init() {
            log::set_logger(&ITMLogger).unwrap()
        }
    }
}
pub use self::itm::*;