2019-11-21 00:00:57 +08:00
|
|
|
use core::ops::{Deref, DerefMut};
|
2020-08-18 01:38:41 +08:00
|
|
|
use libcortex_a9::{asm, mutex::{Mutex, MutexGuard}};
|
2019-12-18 06:35:58 +08:00
|
|
|
use crate::uart::Uart;
|
2019-06-20 06:30:18 +08:00
|
|
|
|
|
|
|
const UART_RATE: u32 = 115_200;
|
2019-11-21 00:00:57 +08:00
|
|
|
static mut UART: Mutex<LazyUart> = Mutex::new(LazyUart::Uninitialized);
|
2019-06-20 06:30:18 +08:00
|
|
|
|
|
|
|
#[doc(hidden)]
|
2019-11-21 00:00:57 +08:00
|
|
|
pub fn get_uart<'a>() -> MutexGuard<'a, LazyUart> {
|
|
|
|
unsafe { UART.lock() }
|
|
|
|
}
|
|
|
|
|
2020-08-18 01:38:41 +08:00
|
|
|
/// Deinitialize so that the Uart will be reinitialized on next
|
|
|
|
/// output.
|
|
|
|
///
|
|
|
|
/// Delays so that an outstanding transmission can finish.
|
2020-01-24 05:34:37 +08:00
|
|
|
pub fn drop_uart() {
|
2020-08-18 01:38:41 +08:00
|
|
|
for _ in 0..1_000_000 {
|
|
|
|
asm::nop();
|
|
|
|
}
|
|
|
|
|
2020-01-24 05:34:37 +08:00
|
|
|
unsafe { UART = Mutex::new(LazyUart::Uninitialized); }
|
|
|
|
}
|
|
|
|
|
2019-11-21 00:00:57 +08:00
|
|
|
/// Initializes the UART on first use through `.deref_mut()` for debug
|
|
|
|
/// output through the `print!` and `println!` macros.
|
|
|
|
pub enum LazyUart {
|
|
|
|
Uninitialized,
|
|
|
|
Initialized(Uart),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Deref for LazyUart {
|
|
|
|
type Target = Uart;
|
|
|
|
fn deref(&self) -> &Uart {
|
|
|
|
match self {
|
|
|
|
LazyUart::Uninitialized =>
|
|
|
|
panic!("stdio not initialized!"),
|
|
|
|
LazyUart::Initialized(uart) =>
|
|
|
|
uart,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DerefMut for LazyUart {
|
|
|
|
fn deref_mut(&mut self) -> &mut Uart {
|
|
|
|
match self {
|
|
|
|
LazyUart::Uninitialized => {
|
2020-09-09 20:10:05 +08:00
|
|
|
#[cfg(any(feature = "target_cora_z7_10", feature = "target_redpitaya"))]
|
2020-08-12 16:27:17 +08:00
|
|
|
let uart = Uart::uart0(UART_RATE);
|
|
|
|
#[cfg(feature = "target_zc706")]
|
|
|
|
let uart = Uart::uart1(UART_RATE);
|
2019-11-21 00:00:57 +08:00
|
|
|
*self = LazyUart::Initialized(uart);
|
|
|
|
self
|
2019-06-20 06:30:18 +08:00
|
|
|
}
|
2019-11-21 00:00:57 +08:00
|
|
|
LazyUart::Initialized(uart) =>
|
|
|
|
uart,
|
2019-06-20 06:30:18 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-21 07:18:24 +08:00
|
|
|
#[macro_export]
|
|
|
|
macro_rules! print {
|
|
|
|
($($arg:tt)*) => ({
|
|
|
|
use core::fmt::Write;
|
2019-12-18 06:35:58 +08:00
|
|
|
let mut uart = $crate::stdio::get_uart();
|
2019-08-11 06:55:27 +08:00
|
|
|
let _ = write!(uart, $($arg)*);
|
2019-06-21 07:18:24 +08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-06-20 06:30:18 +08:00
|
|
|
#[macro_export]
|
|
|
|
macro_rules! println {
|
|
|
|
($($arg:tt)*) => ({
|
|
|
|
use core::fmt::Write;
|
2019-12-18 06:35:58 +08:00
|
|
|
let mut uart = $crate::stdio::get_uart();
|
2019-08-11 06:55:27 +08:00
|
|
|
let _ = write!(uart, $($arg)*);
|
2020-04-21 05:43:50 +08:00
|
|
|
let _ = write!(uart, "\n");
|
2020-05-03 05:32:01 +08:00
|
|
|
// flush after the newline
|
|
|
|
while !uart.tx_idle() {}
|
2019-06-20 06:30:18 +08:00
|
|
|
})
|
|
|
|
}
|