use core::{ cell::RefCell, fmt::{write, Arguments}, }; use cortex_m::interrupt::{self, Mutex}; #[macro_export] macro_rules! log { ($($args:tt)+) => { $crate::log::log_args(core::format_args!($($args)+)) } } #[macro_export] macro_rules! logln { () => ({ kprint!("\r\n") }); ($fmt: literal $(, $($arg: tt)+)?) => { log!(concat!($fmt, "\n") $(, $($arg)+)?) } } static TX: Mutex>> = Mutex::new(RefCell::new(None)); pub fn init(tx: arch::Writer) { interrupt::free(|cs| { TX.borrow(cs).replace(Some(tx)); }); } pub fn log_args(args: Arguments) { interrupt::free(|cs| { TX.borrow(cs) .borrow_mut() .as_mut() .map(|tx| write(tx, args)); }); } /* * Because the logger needs to have a size in order to be allocated * statically, we need to pull in architecture-specific details about * the implementation. * * By putting everything in an `arch` module, we can more easily swap * things out at compile time with feature flags, or a similar * mechanism. */ mod arch { use stm32f1xx_hal::{pac::USART1, serial::Tx}; pub type Writer = Tx; }