stdio: lock for use by core1

This commit is contained in:
Astro 2019-11-20 17:00:57 +01:00
parent ff41f4dd2d
commit 4f8a76e29b
2 changed files with 37 additions and 11 deletions

View File

@ -122,5 +122,6 @@ pub fn main() {
} }
pub fn main_core1() { pub fn main_core1() {
println!("Hello from core1!");
loop {} loop {}
} }

View File

@ -1,19 +1,44 @@
use core::ops::{Deref, DerefMut};
use crate::cortex_a9::mutex::{Mutex, MutexGuard};
use crate::zynq::uart::Uart; use crate::zynq::uart::Uart;
const UART_RATE: u32 = 115_200; const UART_RATE: u32 = 115_200;
static mut UART: Option<Uart> = None; static mut UART: Mutex<LazyUart> = Mutex::new(LazyUart::Uninitialized);
// TODO: locking for SMP
#[doc(hidden)] #[doc(hidden)]
pub fn get_uart() -> &'static mut Uart { pub fn get_uart<'a>() -> MutexGuard<'a, LazyUart> {
unsafe { unsafe { UART.lock() }
match &mut UART { }
None => {
/// 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 => {
let uart = Uart::serial(UART_RATE); let uart = Uart::serial(UART_RATE);
UART = Some(uart); *self = LazyUart::Initialized(uart);
UART.as_mut().unwrap() self
} }
Some(uart) => uart, LazyUart::Initialized(uart) =>
uart,
} }
} }
} }
@ -22,7 +47,7 @@ pub fn get_uart() -> &'static mut Uart {
macro_rules! print { macro_rules! print {
($($arg:tt)*) => ({ ($($arg:tt)*) => ({
use core::fmt::Write; use core::fmt::Write;
let uart = crate::stdio::get_uart(); let mut uart = crate::stdio::get_uart();
let _ = write!(uart, $($arg)*); let _ = write!(uart, $($arg)*);
}) })
} }
@ -31,7 +56,7 @@ macro_rules! print {
macro_rules! println { macro_rules! println {
($($arg:tt)*) => ({ ($($arg:tt)*) => ({
use core::fmt::Write; use core::fmt::Write;
let uart = crate::stdio::get_uart(); let mut uart = crate::stdio::get_uart();
let _ = write!(uart, $($arg)*); let _ = write!(uart, $($arg)*);
let _ = write!(uart, "\r\n"); let _ = write!(uart, "\r\n");
while !uart.tx_fifo_empty() {} while !uart.tx_fifo_empty() {}