console: Add support for println! and print!

Currently we have a cluncky way of printing by calling the following:

    writeln!(console, "My message")?;

Although this works, it means we need to keep track of the console
struct. This makes it difficult to support printing in third party
libraries. This also means that we don't follow the Rust convention of
supporting print! and println! macros.

This patch makes the console object a global static so that we can
support the print! and println! macros. All current users are converted
to use this new method.

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
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 97184f7..548511b 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.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..c13fb26 100644
--- a/src/console.rs
+++ b/src/console.rs
@@ -7,6 +7,9 @@
 use core::fmt;
 use core::mem;
 
+// Global console
+static mut CONSOLE: Option<Console> = None;
+
 const DRIVER_NUMBER: usize = 1;
 
 mod command_nr {
@@ -25,10 +28,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 +41,10 @@
     allow_buffer: [u8; 64],
 }
 
+pub fn get_global_console() -> Option<&'static mut Console> {
+    unsafe { CONSOLE.as_mut() }
+}
+
 impl Console {
     pub fn write<S: AsRef<[u8]>>(&mut self, text: S) -> TockResult<()> {
         let mut not_written_yet = text.as_ref();
@@ -73,6 +82,12 @@
 
         Ok(())
     }
+
+    fn set_global_console(self) {
+        unsafe {
+            CONSOLE = Some(self);
+        }
+    }
 }
 
 impl fmt::Write for Console {
@@ -80,3 +95,43 @@
         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(console) = $crate::console::get_global_console() {
+            use core::fmt::Write;
+            let _ = writeln!(console, $msg);
+        }
+    });
+    ($fmt:expr, $($arg:tt)+) => ({
+        if let Some(console) = $crate::console::get_global_console() {
+            use core::fmt::Write;
+            let _ = writeln!(console, "{}", format_args!($fmt, $($arg)+));
+        }
+    });
+}
+
+#[macro_export]
+macro_rules! print {
+    () => ({
+        // Allow an empty print!() to print the location when hit
+        print!("")
+    });
+    ($msg:expr) => ({
+        if let Some(console) = $crate::console::get_global_console() {
+            use core::fmt::Write;
+            let _ =  write!(console, $msg);
+        }
+    });
+    ($fmt:expr, $($arg:tt)+) => ({
+        if let Some(console) = $crate::console::get_global_console() {
+            use core::fmt::Write;
+            let _ = write!(console, "{}", format_args!($fmt, $($arg)+));
+        }
+    });
+}
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.