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
//! Provides debug output based on semihosting //! //! If you're running your program attached to a debugger, you might want to use //! this module to enable debug output based on semihosting. This requires the //! `semihosting` feature to be enabled. //! //! Without the `semihosting` feature, semihosting will not be initialized and //! the macros in this module will not print anything. This makes it possible to //! run your program without a debugger attached. //! //! ATTENTION: If you intend your program to run without a debugger attached, //! always compile it without the `semihosting` feature. Programs that enable //! semihosting cannot run without a debugger attached. use core::cell::RefCell; use cortex_m::interrupt::Mutex; use cortex_m_semihosting::hio::HStdout; /// Connects to the host's stdout /// /// Users can typically ignore this static, and use [`init`], [`print!`], and /// [`println!`] instead. pub static STDOUT: Mutex<RefCell<Option<HStdout>>> = Mutex::new(RefCell::new(None)); /// Initializes the debug output, if semihosting is enabled /// /// You should add a call to this function to the start any program that uses /// [`print!`] or [`println!`]. If semihosting is enabled via the `semihosting` /// feature, this function will initialize it. If the `semihosting` feature is /// not enabled, this function does nothing. pub fn init() { // Enable debug output only if the semihosting feature is enabled. We need // the option to disable semihosting, otherwise programs won't run without a // debugger attached. #[cfg(feature = "semihosting")] { use cortex_m::interrupt; use cortex_m_semihosting::hio; interrupt::free(|cs| { *STDOUT.borrow(cs).borrow_mut() = Some( hio::hstdout() .expect("Failed to initialize semihosting") ); }); } } /// Sends a debug message to the host, if semihosting is enabled #[macro_export] macro_rules! print { ($($arg:tt)*) => { $crate::cortex_m::interrupt::free(|cs| { if let Some(ref mut stdout) = *$crate::debug::STDOUT.borrow(cs).borrow_mut() { use core::fmt::Write; write!(stdout, $($arg)*) .expect("Failed to write to stdout") } }) } } /// Sends a debug message to the host, if semihosting is enabled #[macro_export] macro_rules! println { ($fmt:expr, $($arg:tt)*) => { print!(concat!($fmt, "\n"), $($arg)*); } }