Merge pull request #235 from alistair23/alistair/println

console: Add support for println! and print!
diff --git a/examples-features/alloc_error.rs b/examples-features/alloc_error.rs
index 40ae939..8b20f84 100644
--- a/examples-features/alloc_error.rs
+++ b/examples-features/alloc_error.rs
@@ -7,7 +7,7 @@
 
 use alloc::vec::Vec;
 use core::alloc::Layout;
-use core::fmt::Write;
+use libtock::println;
 use libtock::result::TockResult;
 use libtock::syscalls;
 
@@ -22,8 +22,8 @@
 #[alloc_error_handler]
 unsafe fn alloc_error_handler(_: Layout) -> ! {
     if let Ok(drivers) = libtock::retrieve_drivers() {
-        let mut console = drivers.console.create_console();
-        let _ = writeln!(console, "alloc_error_handler called");
+        drivers.console.create_console();
+        println!("alloc_error_handler called");
     }
     loop {
         syscalls::raw::yieldk();
diff --git a/examples-features/libtock_test.rs b/examples-features/libtock_test.rs
index ac1e541..ac2cb48 100644
--- a/examples-features/libtock_test.rs
+++ b/examples-features/libtock_test.rs
@@ -12,11 +12,11 @@
 use core::pin::Pin;
 use core::task::Context;
 use core::task::Poll;
-use libtock::console::Console;
 use libtock::console::ConsoleDriver;
 use libtock::gpio::GpioDriverFactory;
 use libtock::gpio::GpioState;
 use libtock::gpio::ResistorMode;
+use libtock::println;
 use libtock::result::TockResult;
 use libtock::timer::DriverContext;
 use libtock::timer::Duration;
@@ -59,16 +59,13 @@
 }
 
 struct LibtockTest {
-    console: Console,
     success: bool,
 }
 
 impl LibtockTest {
     fn initialize(console: ConsoleDriver) -> Self {
-        Self {
-            console: console.create_console(),
-            success: true,
-        }
+        console.create_console();
+        Self { success: true }
     }
 
     fn console(&mut self) -> TockResult<()> {
@@ -170,12 +167,12 @@
     }
 
     fn log_success(&mut self, message: &str) -> TockResult<()> {
-        writeln!(&mut self.console, "[      OK ] {}", message)?;
+        println!("[      OK ] {}", message);
         Ok(())
     }
 
     fn log_failure(&mut self, message: &str) -> TockResult<()> {
-        writeln!(&mut self.console, "[ FAILURE ] {}", message)?;
+        println!("[ FAILURE ] {}", message);
         self.success = false;
         Ok(())
     }
diff --git a/examples-features/panic.rs b/examples-features/panic.rs
index 5a9123a..8af98bf 100644
--- a/examples-features/panic.rs
+++ b/examples-features/panic.rs
@@ -2,8 +2,8 @@
 
 #![no_std]
 
-use core::fmt::Write;
 use core::panic::PanicInfo;
+use libtock::println;
 use libtock::result::TockResult;
 use libtock::syscalls;
 
@@ -15,8 +15,8 @@
 #[panic_handler]
 unsafe fn panic_handler(_info: &PanicInfo) -> ! {
     if let Ok(drivers) = libtock::retrieve_drivers() {
-        let mut console = drivers.console.create_console();
-        let _ = writeln!(console, "panic_handler called");
+        drivers.console.create_console();
+        println!("panic_handler called");
     }
     loop {
         syscalls::raw::yieldk();
diff --git a/examples/adc.rs b/examples/adc.rs
index 711176e..28b1534 100644
--- a/examples/adc.rs
+++ b/examples/adc.rs
@@ -1,6 +1,6 @@
 #![no_std]
 
-use core::fmt::Write;
+use libtock::println;
 use libtock::result::TockResult;
 use libtock::timer::Duration;
 
@@ -11,10 +11,10 @@
     let adc_driver = drivers.adc.init_driver()?;
     let mut timer_driver = drivers.timer.create_timer_driver();
     let timer_driver = timer_driver.activate()?;
-    let mut console = drivers.console.create_console();
+    drivers.console.create_console();
 
     let mut callback = |channel, value| {
-        writeln!(console, "channel: {}, value: {}", channel, value).unwrap();
+        println!("channel: {}, value: {}", channel, value);
     };
 
     let _subscription = adc_driver.subscribe(&mut callback)?;
diff --git a/examples/adc_buffer.rs b/examples/adc_buffer.rs
index 86f94b2..1337cf4 100644
--- a/examples/adc_buffer.rs
+++ b/examples/adc_buffer.rs
@@ -1,7 +1,7 @@
 #![no_std]
 
-use core::fmt::Write;
 use libtock::adc::AdcBuffer;
+use libtock::println;
 use libtock::result::TockResult;
 use libtock::syscalls;
 
@@ -11,7 +11,7 @@
     let mut drivers = libtock::retrieve_drivers()?;
 
     let adc_driver = drivers.adc.init_driver()?;
-    let mut console = drivers.console.create_console();
+    drivers.console.create_console();
 
     let mut adc_buffer = AdcBuffer::default();
     let mut temp_buffer = [0; libtock::adc::BUFFER_SIZE];
@@ -20,7 +20,7 @@
 
     let mut callback = |_, _| {
         adc_buffer.read_bytes(&mut temp_buffer[..]);
-        writeln!(console, "First sample in buffer: {}", temp_buffer[0]).unwrap();
+        println!("First sample in buffer: {}", temp_buffer[0]);
     };
 
     let _subscription = adc_driver.subscribe(&mut callback)?;
diff --git a/examples/button_read.rs b/examples/button_read.rs
index c3f9aa6..e888185 100644
--- a/examples/button_read.rs
+++ b/examples/button_read.rs
@@ -1,6 +1,6 @@
 #![no_std]
 
-use core::fmt::Write;
+use libtock::println;
 use libtock::result::TockResult;
 use libtock::timer::Duration;
 
@@ -11,16 +11,11 @@
     let buttons_driver = drivers.buttons.init_driver()?;
     let mut timer_driver = drivers.timer.create_timer_driver();
     let timer_driver = timer_driver.activate()?;
-    let mut console = drivers.console.create_console();
+    drivers.console.create_console();
 
     loop {
         for button in buttons_driver.buttons() {
-            writeln!(
-                console,
-                "button {}: {:?}",
-                button.button_num(),
-                button.read()?
-            )?;
+            println!("button {}: {:?}", button.button_num(), button.read()?);
         }
         timer_driver.sleep(Duration::from_ms(500)).await?;
     }
diff --git a/examples/button_subscribe.rs b/examples/button_subscribe.rs
index d06a0e9..8b2f17e 100644
--- a/examples/button_subscribe.rs
+++ b/examples/button_subscribe.rs
@@ -1,8 +1,8 @@
 #![no_std]
 
 use core::cell::Cell;
-use core::fmt::Write;
 use libtock::buttons::ButtonState;
+use libtock::println;
 use libtock::result::TockResult;
 use libtock::timer::Duration;
 
@@ -13,7 +13,7 @@
     let buttons_driver = drivers.buttons.init_driver()?;
     let mut timer_driver = drivers.timer.create_timer_driver();
     let timer_driver = timer_driver.activate()?;
-    let mut console = drivers.console.create_console();
+    drivers.console.create_console();
 
     let pressed_count = Cell::new(0usize);
     let released_count = Cell::new(0usize);
@@ -30,12 +30,11 @@
     }
 
     loop {
-        writeln!(
-            console,
+        println!(
             "pressed: {}, released: {}",
             pressed_count.get(),
             released_count.get()
-        )?;
+        );
         timer_driver.sleep(Duration::from_ms(500)).await?;
     }
 }
diff --git a/examples/ctap.rs b/examples/ctap.rs
index 42917d1..d545d0c 100644
--- a/examples/ctap.rs
+++ b/examples/ctap.rs
@@ -1,38 +1,39 @@
 #![no_std]
 /// This is a very basic CTAP example
 /// This example only calls the CTAP driver calls, it does not implement CTAP
-use core::fmt::Write;
 use libtock::ctap::{CtapRecvBuffer, CtapSendBuffer};
 use libtock::result::TockResult;
 use libtock::syscalls;
+use libtock::{print, println};
 
 #[libtock::main]
 async fn main() -> TockResult<()> {
     let mut drivers = libtock::retrieve_drivers()?;
-    let mut console = drivers.console.create_console();
-    writeln!(console, "Starting CTAP example")?;
+    drivers.console.create_console();
+    println!("Starting CTAP example");
     let ctap_driver = drivers.ctap.init_driver()?;
 
-    writeln!(console, "Creating recv buffer")?;
+    println!("Creating recv buffer");
     let mut recv_buffer = CtapRecvBuffer::default();
     let recv_buffer = ctap_driver.init_recv_buffer(&mut recv_buffer)?;
-    writeln!(console, "  done")?;
+    println!("  done");
 
-    writeln!(console, "Creating send buffer")?;
+    println!("Creating send buffer");
     let mut send_buffer = CtapSendBuffer::default();
     let _send_buffer = ctap_driver.init_send_buffer(&mut send_buffer)?;
-    writeln!(console, "  done")?;
+    println!("  done");
 
     let mut temp_buffer = [0; libtock::ctap::RECV_BUFFER_SIZE];
 
-    writeln!(console, "Setting callback and running")?;
+    println!("Setting callback and running");
     let mut callback = |_, _| {
-        writeln!(console, "CTAP Complete, printing data").unwrap();
+        println!("CTAP Complete, printing data");
         recv_buffer.read_bytes(&mut temp_buffer[..]);
 
         for buf in temp_buffer.iter().take(libtock::ctap::RECV_BUFFER_SIZE) {
-            write!(console, "{:x}", *buf).unwrap();
+            print!("{:x}", *buf);
         }
+        println!();
 
         let _ret = ctap_driver.allow_receive();
     };
diff --git a/examples/gpio_read.rs b/examples/gpio_read.rs
index a29662e..8fc216b 100644
--- a/examples/gpio_read.rs
+++ b/examples/gpio_read.rs
@@ -1,7 +1,7 @@
 #![no_std]
 
-use core::fmt::Write;
 use libtock::gpio::ResistorMode;
+use libtock::println;
 use libtock::result::TockResult;
 use libtock::timer::Duration;
 
@@ -13,12 +13,12 @@
     let mut gpio_driver = drivers.gpio.init_driver()?;
     let mut timer_driver = drivers.timer.create_timer_driver();
     let timer_driver = timer_driver.activate()?;
-    let mut console = drivers.console.create_console();
+    drivers.console.create_console();
 
     let mut gpio = gpio_driver.gpios().next().unwrap();
     let gpio_in = gpio.enable_input(ResistorMode::PullDown)?;
     loop {
-        writeln!(console, "{:?}", gpio_in.read()?)?;
+        println!("{:?}", gpio_in.read()?);
         timer_driver.sleep(Duration::from_ms(500)).await?;
     }
 }
diff --git a/examples/hello_world.rs b/examples/hello_world.rs
index 052cf69..49ada78 100644
--- a/examples/hello_world.rs
+++ b/examples/hello_world.rs
@@ -4,16 +4,16 @@
 
 #![no_std]
 
-use core::fmt::Write;
+use libtock::println;
 use libtock::result::TockResult;
 
 #[libtock::main]
 async fn main() -> TockResult<()> {
     let drivers = libtock::retrieve_drivers()?;
 
-    let mut console = drivers.console.create_console();
+    drivers.console.create_console();
 
-    writeln!(console, "Hello Tock World")?;
+    println!("Hello Tock World");
 
     Ok(())
 }
diff --git a/examples/hmac.rs b/examples/hmac.rs
index b6f2881..fe956bb 100644
--- a/examples/hmac.rs
+++ b/examples/hmac.rs
@@ -1,23 +1,23 @@
 #![no_std]
 
-use core::fmt::Write;
 use libtock::hmac::{HmacDataBuffer, HmacDestBuffer, HmacKeyBuffer};
+use libtock::println;
 use libtock::result::TockResult;
 use libtock::syscalls;
 
 #[libtock::main]
 async fn main() -> TockResult<()> {
     let mut drivers = libtock::retrieve_drivers()?;
-    let mut console = drivers.console.create_console();
-    writeln!(console, "Starting HMAC example")?;
+    drivers.console.create_console();
+    println!("Starting HMAC example");
     let hmac_driver = drivers.hmac.init_driver()?;
 
-    writeln!(console, "Loading in 0 key")?;
+    println!("Loading in 0 key");
     let mut key_buffer = HmacKeyBuffer::default();
     let _key_buffer = hmac_driver.init_key_buffer(&mut key_buffer)?;
-    writeln!(console, "  done")?;
+    println!("  done");
 
-    writeln!(console, "Creating data buffer")?;
+    println!("Creating data buffer");
     let mut data_buffer = HmacDataBuffer::default();
     let data: &[u8; 72] =
         b"A language empowering everyone to build reliable and efficient software.";
@@ -26,22 +26,22 @@
         data_buffer[i] = *d;
     }
     let _data_buffer = hmac_driver.init_data_buffer(&mut data_buffer)?;
-    writeln!(console, "  done")?;
+    println!("  done");
 
-    writeln!(console, "Creating dest buffer")?;
+    println!("Creating dest buffer");
     let mut dest_buffer = HmacDestBuffer::default();
     let dest_buffer = hmac_driver.init_dest_buffer(&mut dest_buffer)?;
-    writeln!(console, "  done")?;
+    println!("  done");
 
     let mut temp_buffer = [0; libtock::hmac::DEST_BUFFER_SIZE];
 
-    writeln!(console, "Setting callback and running")?;
+    println!("Setting callback and running");
     let mut callback = |_result, _digest| {
-        writeln!(console, "HMAC Complete, printing digest").unwrap();
+        println!("HMAC Complete, printing digest");
         dest_buffer.read_bytes(&mut temp_buffer[..]);
 
         for buf in temp_buffer.iter().take(libtock::hmac::DEST_BUFFER_SIZE) {
-            write!(console, "{:x}", *buf).unwrap();
+            println!("{:x}", *buf);
         }
     };
 
diff --git a/examples/sensors.rs b/examples/sensors.rs
index 7ea87c7..5196cd1 100644
--- a/examples/sensors.rs
+++ b/examples/sensors.rs
@@ -1,6 +1,6 @@
 #![no_std]
 
-use core::fmt::Write;
+use libtock::println;
 use libtock::result::TockResult;
 use libtock::sensors::Sensor;
 use libtock::timer::Duration;
@@ -11,29 +11,13 @@
 
     let mut timer_driver = drivers.timer.create_timer_driver();
     let timer_driver = timer_driver.activate()?;
-    let mut console = drivers.console.create_console();
+    drivers.console.create_console();
 
     loop {
-        writeln!(
-            console,
-            "Humidity:    {}\n",
-            drivers.humidity_sensor.read()?
-        )?;
-        writeln!(
-            console,
-            "Temperature: {}\n",
-            drivers.temperature_sensor.read()?
-        )?;
-        writeln!(
-            console,
-            "Light:       {}\n",
-            drivers.ambient_light_sensor.read()?
-        )?;
-        writeln!(
-            console,
-            "Accel:       {}\n",
-            drivers.ninedof.read_acceleration()?
-        )?;
+        println!("Humidity:    {}\n", drivers.humidity_sensor.read()?);
+        println!("Temperature: {}\n", drivers.temperature_sensor.read()?);
+        println!("Light:       {}\n", drivers.ambient_light_sensor.read()?);
+        println!("Accel:       {}\n", drivers.ninedof.read_acceleration()?);
         timer_driver.sleep(Duration::from_ms(500)).await?;
     }
 }
diff --git a/examples/temperature.rs b/examples/temperature.rs
index 7428187..6298cb4 100644
--- a/examples/temperature.rs
+++ b/examples/temperature.rs
@@ -1,6 +1,6 @@
 #![no_std]
 
-use core::fmt::Write;
+use libtock::println;
 use libtock::result::TockResult;
 use libtock::timer::Duration;
 
@@ -11,11 +11,11 @@
     let mut temperature_driver = drivers.temperature.init_driver()?;
     let mut timer_driver = drivers.timer.create_timer_driver();
     let timer_driver = timer_driver.activate()?;
-    let mut console = drivers.console.create_console();
+    drivers.console.create_console();
 
     loop {
         let temperature = temperature_driver.measure_temperature().await?;
-        writeln!(console, "Temperature: {}", temperature)?;
+        println!("Temperature: {}", temperature);
         timer_driver.sleep(Duration::from_ms(1000)).await?;
     }
 }
diff --git a/examples/timer.rs b/examples/timer.rs
index 493f0b9..2277e6c 100644
--- a/examples/timer.rs
+++ b/examples/timer.rs
@@ -1,10 +1,9 @@
 #![no_std]
+use libtock::println;
 /**
  * This example shows a repeated timer combined with reading and displaying the current time in
  * clock ticks.
  **/
-use core::fmt::Write;
-use libtock::console::Console;
 use libtock::result::TockResult;
 use libtock::timer::DriverContext;
 use libtock::timer::Duration;
@@ -15,12 +14,12 @@
 async fn main() -> TockResult<()> {
     let mut drivers = libtock::retrieve_drivers()?;
 
-    let mut console = drivers.console.create_console();
+    drivers.console.create_console();
 
     let mut previous_ticks = None;
 
     for i in 0.. {
-        print_now(&mut console, &mut drivers.timer, &mut previous_ticks, i)?;
+        print_now(&mut drivers.timer, &mut previous_ticks, i)?;
         let mut timer_driver = drivers.timer.create_timer_driver();
         let timer_driver = timer_driver.activate()?;
 
@@ -31,7 +30,6 @@
 }
 
 fn print_now(
-    console: &mut Console,
     timer_context: &mut DriverContext,
     previous_ticks: &mut Option<isize>,
     i: usize,
@@ -41,8 +39,7 @@
     let current_clock = timer.get_current_clock()?;
     let ticks = current_clock.num_ticks();
     let frequency = timer.clock_frequency().hz();
-    writeln!(
-        console,
+    println!(
         "[{}] Waited roughly {}. Now is {} = {:#010x} ticks ({:?} ticks since last time at {} Hz)",
         i,
         PrettyTime::from_ms(i * DELAY_MS),
@@ -50,7 +47,7 @@
         ticks,
         previous_ticks.map(|previous| ticks - previous),
         frequency
-    )?;
+    );
     *previous_ticks = Some(ticks);
     Ok(())
 }
diff --git a/examples/timer_subscribe.rs b/examples/timer_subscribe.rs
index 5c69be1..5a7ad4b 100644
--- a/examples/timer_subscribe.rs
+++ b/examples/timer_subscribe.rs
@@ -1,7 +1,7 @@
 #![no_std]
 
-use core::fmt::Write;
 use futures::future;
+use libtock::println;
 use libtock::result::TockResult;
 use libtock::timer::Duration;
 
@@ -9,14 +9,10 @@
 async fn main() -> TockResult<()> {
     let mut drivers = libtock::retrieve_drivers()?;
 
-    let mut console = drivers.console.create_console();
+    drivers.console.create_console();
 
     let mut with_callback = drivers.timer.with_callback(|_, _| {
-        writeln!(
-            console,
-            "This line is printed 2 seconds after the start of the program.",
-        )
-        .unwrap();
+        println!("This line is printed 2 seconds after the start of the program.");
     });
 
     let mut timer = with_callback.init()?;
diff --git a/src/console.rs b/src/console.rs
index a94fc13..9bf2c24 100644
--- a/src/console.rs
+++ b/src/console.rs
@@ -5,8 +5,12 @@
 use crate::syscalls;
 use core::cell::Cell;
 use core::fmt;
+use core::fmt::Write;
 use core::mem;
 
+// Global console
+static mut CONSOLE: Option<Console> = None;
+
 const DRIVER_NUMBER: usize = 1;
 
 mod command_nr {
@@ -25,10 +29,12 @@
 pub struct ConsoleDriver;
 
 impl ConsoleDriver {
-    pub fn create_console(self) -> Console {
-        Console {
+    pub fn create_console(self) {
+        let console = Console {
             allow_buffer: [0; 64],
-        }
+        };
+
+        console.set_global_console();
     }
 }
 
@@ -36,6 +42,22 @@
     allow_buffer: [u8; 64],
 }
 
+pub static mut MISSED_PRINT: bool = false;
+
+pub fn get_global_console() -> Option<Console> {
+    unsafe {
+        if let Some(con) = CONSOLE.take() {
+            Some(con)
+        } else {
+            // If we get here then either the console was never initalised
+            // or someone else took it. Set MISSED_PRINT to true so that we
+            // can warn the user.
+            MISSED_PRINT = true;
+            None
+        }
+    }
+}
+
 impl Console {
     pub fn write<S: AsRef<[u8]>>(&mut self, text: S) -> TockResult<()> {
         let mut not_written_yet = text.as_ref();
@@ -73,6 +95,19 @@
 
         Ok(())
     }
+
+    pub fn set_global_console(mut self) {
+        unsafe {
+            if MISSED_PRINT {
+                // Someone tried to print while we were or someone tried
+                // to print before initalisation, print a warning here.
+                let _ = write!(self, "A print was dropped while the console was locked");
+                MISSED_PRINT = false;
+            }
+
+            CONSOLE = Some(self);
+        }
+    }
 }
 
 impl fmt::Write for Console {
@@ -80,3 +115,47 @@
         self.write(string).map_err(|_| fmt::Error)
     }
 }
+
+#[macro_export]
+macro_rules! println {
+    () => ({
+        // Allow an empty println!() to print the location when hit
+        println!("")
+    });
+    ($msg:expr) => ({
+        if let Some(mut console) = $crate::console::get_global_console() {
+            use core::fmt::Write;
+            let _ = writeln!(console, $msg);
+            console.set_global_console();
+        }
+    });
+    ($fmt:expr, $($arg:tt)+) => ({
+        if let Some(mut console) = $crate::console::get_global_console() {
+            use core::fmt::Write;
+            let _ = writeln!(console, "{}", format_args!($fmt, $($arg)+));
+            console.set_global_console();
+        }
+    });
+}
+
+#[macro_export]
+macro_rules! print {
+    () => ({
+        // Allow an empty print!() to print the location when hit
+        print!("")
+    });
+    ($msg:expr) => ({
+        if let Some(mut console) = $crate::console::get_global_console() {
+            use core::fmt::Write;
+            let _ =  write!(console, $msg);
+            console.set_global_console();
+        }
+    });
+    ($fmt:expr, $($arg:tt)+) => ({
+        if let Some(mut console) = $crate::console::get_global_console() {
+            use core::fmt::Write;
+            let _ = write!(console, "{}", format_args!($fmt, $($arg)+));
+            console.set_global_console();
+        }
+    });
+}
diff --git a/src/debug/mod.rs b/src/debug/mod.rs
index 3bae683..85b4337 100644
--- a/src/debug/mod.rs
+++ b/src/debug/mod.rs
@@ -3,32 +3,18 @@
 mod low_level_debug;
 
 use crate::drivers;
+use crate::println;
 use libtock_core::debug as core_debug;
 
 pub use low_level_debug::*;
 
-pub fn println() {
-    let buffer = [b'\n'];
-    let drivers = unsafe { drivers::retrieve_drivers_unsafe() };
-    let mut console = drivers.console.create_console();
-    let _ = console.write(&buffer);
-}
-
-pub fn print_as_hex(value: usize) {
-    let mut buffer = [b'\n'; 11];
-    write_as_hex(&mut buffer, value);
-    let drivers = unsafe { drivers::retrieve_drivers_unsafe() };
-    let mut console = drivers.console.create_console();
-    let _ = console.write(buffer);
-}
-
 pub fn print_stack_pointer() {
     let mut buffer = [b'\n'; 15];
     buffer[0..4].clone_from_slice(b"SP: ");
     write_as_hex(&mut buffer[4..15], core_debug::get_stack_pointer());
     let drivers = unsafe { drivers::retrieve_drivers_unsafe() };
-    let mut console = drivers.console.create_console();
-    let _ = console.write(buffer);
+    drivers.console.create_console();
+    println!("{:?}", buffer);
 }
 
 #[inline(always)]
@@ -49,8 +35,8 @@
     }
     buffer[27] = b'\n';
     let drivers = drivers::retrieve_drivers_unsafe();
-    let mut console = drivers.console.create_console();
-    let _ = console.write(&buffer);
+    drivers.console.create_console();
+    println!("{:?}", buffer);
 }
 
 /// Dumps arbitrary memory regions.