From 4f8a76e29bac163c94fbef75a65c4e500bb01d87 Mon Sep 17 00:00:00 2001 From: Astro Date: Wed, 20 Nov 2019 17:00:57 +0100 Subject: [PATCH] stdio: lock for use by core1 --- src/main.rs | 1 + src/stdio.rs | 47 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/main.rs b/src/main.rs index b99fa78..9f0af11 100644 --- a/src/main.rs +++ b/src/main.rs @@ -122,5 +122,6 @@ pub fn main() { } pub fn main_core1() { + println!("Hello from core1!"); loop {} } diff --git a/src/stdio.rs b/src/stdio.rs index ca0900a..1b77175 100644 --- a/src/stdio.rs +++ b/src/stdio.rs @@ -1,19 +1,44 @@ +use core::ops::{Deref, DerefMut}; +use crate::cortex_a9::mutex::{Mutex, MutexGuard}; use crate::zynq::uart::Uart; const UART_RATE: u32 = 115_200; -static mut UART: Option = None; +static mut UART: Mutex = Mutex::new(LazyUart::Uninitialized); -// TODO: locking for SMP #[doc(hidden)] -pub fn get_uart() -> &'static mut Uart { - unsafe { - match &mut UART { - None => { +pub fn get_uart<'a>() -> MutexGuard<'a, LazyUart> { + unsafe { UART.lock() } +} + +/// 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); - UART = Some(uart); - UART.as_mut().unwrap() + *self = LazyUart::Initialized(uart); + self } - Some(uart) => uart, + LazyUart::Initialized(uart) => + uart, } } } @@ -22,7 +47,7 @@ pub fn get_uart() -> &'static mut Uart { macro_rules! print { ($($arg:tt)*) => ({ use core::fmt::Write; - let uart = crate::stdio::get_uart(); + let mut uart = crate::stdio::get_uart(); let _ = write!(uart, $($arg)*); }) } @@ -31,7 +56,7 @@ macro_rules! print { macro_rules! println { ($($arg:tt)*) => ({ use core::fmt::Write; - let uart = crate::stdio::get_uart(); + let mut uart = crate::stdio::get_uart(); let _ = write!(uart, $($arg)*); let _ = write!(uart, "\r\n"); while !uart.tx_fifo_empty() {}