Skip to main content

mpfs_hal/
print.rs

1use crate::{Mutex, Peripheral, uart::*};
2use core::panic::PanicInfo;
3
4use embedded_io::Write;
5
6static mut UART: Option<UartTx<UartTx0>> = None;
7static MUTEX: Mutex = Mutex::new();
8
9pub(crate) fn init_print() {
10    let baud_rate = match option_env!("DEBUG_UART_BAUD_RATE") {
11        Some(size) => u32::from_str_radix(size, 10)
12            .expect("DEBUG_UART_BAUD_RATE must be a valid decimal number"),
13        None => 115_200,
14    };
15    unsafe {
16        UART = Some(UartTx::new(
17            UartTx0::take().unwrap(),
18            UartConfig {
19                baud_rate: BaudRate::Custom(baud_rate),
20                ..Default::default()
21            },
22        ))
23    }
24}
25
26pub struct Printer;
27
28impl Printer {
29    // We need to hold onto a lock _longer_ than just what `write_str` needs
30    // because `writeln` will call `write_str` multiple times.
31    pub fn with_lock<F>(f: F)
32    where
33        F: FnOnce(),
34    {
35        let lock_token = MUTEX.lock();
36        f();
37        MUTEX.release(lock_token);
38    }
39}
40
41impl core::fmt::Write for Printer {
42    fn write_str(&mut self, s: &str) -> core::fmt::Result {
43        #[allow(static_mut_refs)]
44        let uart = unsafe { UART.as_mut().unwrap() };
45        uart.write(s.as_bytes()).unwrap();
46        Ok(())
47    }
48}
49
50#[macro_export]
51macro_rules! println {
52    ($($arg:tt)*) => {{
53        {
54            use core::fmt::Write;
55            $crate::Printer::with_lock(|| {
56                writeln!($crate::Printer, $($arg)*).ok();
57            });
58        }
59    }};
60}
61
62#[macro_export]
63macro_rules! print {
64    ($($arg:tt)*) => {{
65        {
66            use core::fmt::Write;
67            $crate::Printer::with_lock(|| {
68                write!($crate::Printer, $($arg)*).ok();
69            });
70        }
71    }};
72}
73
74pub fn print_panic(panic: &PanicInfo<'_>) {
75    if let Some(location) = panic.location() {
76        println!(
77            "PANIC at {}:{}: {}",
78            location.file(),
79            location.line(),
80            panic.message()
81        );
82    }
83}
84
85pub struct UnguardedPrinter;
86
87impl core::fmt::Write for UnguardedPrinter {
88    fn write_str(&mut self, s: &str) -> core::fmt::Result {
89        unsafe {
90            // If the UART is not initialized, do nothing
91            #[allow(static_mut_refs)]
92            if UART.is_none() {
93                return Ok(());
94            }
95            super::pac::MSS_UART_polled_tx(UartTx0::steal().address(), s.as_ptr(), s.len() as u32);
96        }
97        Ok(())
98    }
99}
100
101#[macro_export]
102macro_rules! println_unguarded {
103    ($($arg:tt)*) => {{
104        {
105            use core::fmt::Write;
106            writeln!($crate::UnguardedPrinter, $($arg)*).ok();
107        }
108    }};
109}
110
111#[macro_export]
112macro_rules! print_unguarded {
113    ($($arg:tt)*) => {{
114        {
115            use core::fmt::Write;
116            write!($crate::UnguardedPrinter, $($arg)*).ok();
117        }
118    }};
119}