Make led driver a singleton
diff --git a/examples/adc.rs b/examples/adc.rs
index 83b5919..afc110e 100644
--- a/examples/adc.rs
+++ b/examples/adc.rs
@@ -13,7 +13,7 @@
     let mut driver = context.create_timer_driver()?;
     let timer_driver = driver.activate()?;
 
-    let Hardware { console_driver } = libtock::retrieve_hardware()?;
+    let Hardware { console_driver, .. } = libtock::retrieve_hardware()?;
     let mut console = console_driver.create_console();
     let mut with_callback = adc::with_callback(|channel: usize, value: usize| {
         writeln!(console, "channel: {}, value: {}", channel, value).unwrap();
diff --git a/examples/adc_buffer.rs b/examples/adc_buffer.rs
index 067c67d..2559376 100644
--- a/examples/adc_buffer.rs
+++ b/examples/adc_buffer.rs
@@ -10,7 +10,7 @@
 #[libtock::main]
 /// Reads a 128 byte sample into a buffer and prints the first value to the console.
 async fn main() -> TockResult<()> {
-    let Hardware { console_driver } = libtock::retrieve_hardware()?;
+    let Hardware { console_driver, .. } = libtock::retrieve_hardware()?;
     let mut console = console_driver.create_console();
     let mut adc_buffer = AdcBuffer::default();
     let mut temp_buffer = [0; libtock::adc::BUFFER_SIZE];
diff --git a/examples/ble_scanning.rs b/examples/ble_scanning.rs
index 78de325..8846ed7 100644
--- a/examples/ble_scanning.rs
+++ b/examples/ble_scanning.rs
@@ -2,11 +2,11 @@
 
 use futures::future;
 use libtock::ble_parser;
-use libtock::led;
 use libtock::result::TockResult;
 use libtock::simple_ble;
 use libtock::simple_ble::BleCallback;
 use libtock::simple_ble::BleDriver;
+use libtock::Hardware;
 use serde::Deserialize;
 
 #[derive(Deserialize)]
@@ -20,13 +20,18 @@
     let mut shared_buffer = BleDriver::create_scan_buffer();
     let mut my_buffer = BleDriver::create_scan_buffer();
     let shared_memory = BleDriver::share_memory(&mut shared_buffer)?;
+    let Hardware { mut led_driver, .. } = libtock::retrieve_hardware()?;
 
     let mut callback = BleCallback::new(|_: usize, _: usize| {
         shared_memory.read_bytes(&mut my_buffer[..]);
         ble_parser::find(&my_buffer, simple_ble::gap_data::SERVICE_DATA as u8)
             .and_then(|service_data| ble_parser::extract_for_service([91, 79], service_data))
             .and_then(|payload| corepack::from_bytes::<LedCommand>(&payload).ok())
-            .and_then(|msg| led::get(msg.nr as usize).map(|led| led.set_state(msg.st)));
+            .and_then(|msg| {
+                led_driver
+                    .get(msg.nr as usize)
+                    .map(|mut led| led.set_state(msg.st))
+            });
     });
 
     let _subscription = BleDriver::start(&mut callback)?;
diff --git a/examples/blink.rs b/examples/blink.rs
index f37fd12..88857c2 100644
--- a/examples/blink.rs
+++ b/examples/blink.rs
@@ -1,13 +1,14 @@
 #![no_std]
 
-use libtock::led;
 use libtock::result::TockResult;
 use libtock::timer;
 use libtock::timer::Duration;
+use libtock::Hardware;
 
 #[libtock::main]
 async fn main() -> TockResult<()> {
-    let num_leds = led::count()?;
+    let Hardware { mut led_driver, .. } = libtock::retrieve_hardware()?;
+
     let context = timer::DriverContext::create()?;
     let mut driver = context.create_timer_driver()?;
     let timer_driver = driver.activate()?;
@@ -16,11 +17,12 @@
     // to the number of LEDs on the board.
     let mut count: usize = 0;
     loop {
-        for i in 0..num_leds {
+        for mut led in led_driver.all() {
+            let i = led.number();
             if count & (1 << i) == (1 << i) {
-                led::get(i).unwrap().on()?;
+                led.on()?;
             } else {
-                led::get(i).unwrap().off()?;
+                led.off()?;
             }
         }
         count = count.wrapping_add(1);
diff --git a/examples/blink_random.rs b/examples/blink_random.rs
index 6b964a2..a857181 100644
--- a/examples/blink_random.rs
+++ b/examples/blink_random.rs
@@ -1,18 +1,20 @@
 #![no_std]
 
-use libtock::led;
+use libtock::led::LedDriver;
 use libtock::result::TockResult;
 use libtock::rng;
 use libtock::timer;
 use libtock::timer::Duration;
+use libtock::Hardware;
 
 #[libtock::main]
 async fn main() -> TockResult<()> {
     let context = timer::DriverContext::create()?;
     let mut driver = context.create_timer_driver()?;
     let timer_driver = driver.activate()?;
+    let Hardware { mut led_driver, .. } = libtock::retrieve_hardware()?;
 
-    let num_leds = led::count()?;
+    let num_leds = led_driver.count()?;
     // blink_nibble assumes 4 leds.
     assert_eq!(num_leds, 4);
 
@@ -21,18 +23,18 @@
         rng::fill_buffer(&mut buf).await?;
 
         for &x in buf.iter() {
-            blink_nibble(x)?;
+            blink_nibble(x, &mut led_driver)?;
             timer_driver.sleep(Duration::from_ms(100)).await?;
-            blink_nibble(x >> 4)?;
+            blink_nibble(x >> 4, &mut led_driver)?;
             timer_driver.sleep(Duration::from_ms(100)).await?;
         }
     }
 }
 
 // Takes the 4 least-significant bits of x, and turn the 4 leds on/off accordingly.
-fn blink_nibble(x: u8) -> TockResult<()> {
+fn blink_nibble(x: u8, led_driver: &mut LedDriver) -> TockResult<()> {
     for i in 0..4 {
-        let led = led::get(i).unwrap();
+        let mut led = led_driver.get(i).unwrap();
         if (x >> i) & 1 != 0 {
             led.on()?;
         } else {
diff --git a/examples/button_leds.rs b/examples/button_leds.rs
index 294d45a..789cb9b 100644
--- a/examples/button_leds.rs
+++ b/examples/button_leds.rs
@@ -3,14 +3,16 @@
 use futures::future;
 use libtock::buttons;
 use libtock::buttons::ButtonState;
-use libtock::led;
 use libtock::result::TockResult;
+use libtock::Hardware;
 
 #[libtock::main]
 async fn main() -> TockResult<()> {
+    let Hardware { mut led_driver, .. } = libtock::retrieve_hardware()?;
+
     let mut with_callback = buttons::with_callback(|button_num: usize, state| {
         match state {
-            ButtonState::Pressed => led::get(button_num).unwrap().toggle().ok().unwrap(),
+            ButtonState::Pressed => led_driver.get(button_num).unwrap().toggle().ok().unwrap(),
             ButtonState::Released => (),
         };
     });
diff --git a/examples/button_read.rs b/examples/button_read.rs
index 32714de..ddd98e8 100644
--- a/examples/button_read.rs
+++ b/examples/button_read.rs
@@ -10,7 +10,7 @@
 
 #[libtock::main]
 async fn main() -> TockResult<()> {
-    let Hardware { console_driver } = libtock::retrieve_hardware()?;
+    let Hardware { console_driver, .. } = libtock::retrieve_hardware()?;
     let mut console = console_driver.create_console();
     let mut with_callback = buttons::with_callback(|_, _| {});
     let mut buttons = with_callback.init()?;
diff --git a/examples/button_subscribe.rs b/examples/button_subscribe.rs
index 05a0cfe..afc8079 100644
--- a/examples/button_subscribe.rs
+++ b/examples/button_subscribe.rs
@@ -10,7 +10,7 @@
 // FIXME: Hangs up when buttons are pressed rapidly. Yielding in callback leads to stack overflow.
 #[libtock::main]
 async fn main() -> TockResult<()> {
-    let Hardware { console_driver } = libtock::retrieve_hardware()?;
+    let Hardware { console_driver, .. } = libtock::retrieve_hardware()?;
     let mut console = console_driver.create_console();
     let mut with_callback = buttons::with_callback(|button_num: usize, state| {
         writeln!(
diff --git a/examples/gpio_read.rs b/examples/gpio_read.rs
index 7c7493d..9a69b8e 100644
--- a/examples/gpio_read.rs
+++ b/examples/gpio_read.rs
@@ -11,7 +11,7 @@
 // example works on p0.03
 #[libtock::main]
 async fn main() -> TockResult<()> {
-    let Hardware { console_driver } = libtock::retrieve_hardware()?;
+    let Hardware { console_driver, .. } = libtock::retrieve_hardware()?;
     let mut console = console_driver.create_console();
     let pin = GpioPinUnitialized::new(0);
     let pin = pin.open_for_read(None, InputMode::PullDown)?;
diff --git a/examples/hardware_test.rs b/examples/hardware_test.rs
index a98f378..8dd6da6 100644
--- a/examples/hardware_test.rs
+++ b/examples/hardware_test.rs
@@ -34,7 +34,7 @@
 
 #[libtock::main]
 async fn main() -> TockResult<()> {
-    let Hardware { console_driver } = libtock::retrieve_hardware()?;
+    let Hardware { console_driver, .. } = libtock::retrieve_hardware()?;
     let mut console = console_driver.create_console();
     writeln!(console, "[test-results]")?;
 
diff --git a/examples/hello.rs b/examples/hello.rs
index 81a629b..9bc98a8 100644
--- a/examples/hello.rs
+++ b/examples/hello.rs
@@ -8,7 +8,7 @@
 
 #[libtock::main]
 async fn main() -> TockResult<()> {
-    let Hardware { console_driver } = libtock::retrieve_hardware()?;
+    let Hardware { console_driver, .. } = libtock::retrieve_hardware()?;
     let mut console = console_driver.create_console();
     let context = timer::DriverContext::create()?;
     let mut driver = context.create_timer_driver()?;
diff --git a/examples/sensors.rs b/examples/sensors.rs
index 20e1f29..e24c95b 100644
--- a/examples/sensors.rs
+++ b/examples/sensors.rs
@@ -10,7 +10,7 @@
 
 #[libtock::main]
 async fn main() -> TockResult<()> {
-    let Hardware { console_driver } = libtock::retrieve_hardware()?;
+    let Hardware { console_driver, .. } = libtock::retrieve_hardware()?;
     let mut console = console_driver.create_console();
     let mut humidity = HumiditySensor;
     let mut temperature = TemperatureSensor;
diff --git a/examples/simple_ble.rs b/examples/simple_ble.rs
index 97511a0..7988c9e 100644
--- a/examples/simple_ble.rs
+++ b/examples/simple_ble.rs
@@ -2,11 +2,11 @@
 
 use libtock::ble_composer;
 use libtock::ble_composer::BlePayload;
-use libtock::led;
 use libtock::result::TockResult;
 use libtock::simple_ble::BleAdvertisingDriver;
 use libtock::timer;
 use libtock::timer::Duration;
+use libtock::Hardware;
 use serde::Serialize;
 
 #[derive(Serialize)]
@@ -17,7 +17,9 @@
 
 #[libtock::main]
 async fn main() -> TockResult<()> {
-    let led = led::get(0).unwrap();
+    let Hardware { mut led_driver, .. } = libtock::retrieve_hardware()?;
+
+    let mut led = led_driver.get(0).unwrap();
 
     let uuid: [u8; 2] = [0x00, 0x18];
 
diff --git a/examples/temperature.rs b/examples/temperature.rs
index 8143944..81245eb 100644
--- a/examples/temperature.rs
+++ b/examples/temperature.rs
@@ -7,7 +7,7 @@
 
 #[libtock::main]
 async fn main() -> TockResult<()> {
-    let Hardware { console_driver } = libtock::retrieve_hardware()?;
+    let Hardware { console_driver, .. } = libtock::retrieve_hardware()?;
     let mut console = console_driver.create_console();
     let temperature = temperature::measure_temperature().await?;
     writeln!(console, "Temperature: {}", temperature).map_err(Into::into)
diff --git a/examples/timer_parallel.rs b/examples/timer_parallel.rs
index c19e583..d640ebd 100644
--- a/examples/timer_parallel.rs
+++ b/examples/timer_parallel.rs
@@ -1,19 +1,20 @@
 #![no_std]
 
 use futures::future;
-use libtock::led;
+use libtock::led::Led;
 use libtock::result::TockResult;
 use libtock::timer;
 use libtock::timer::Duration;
 use libtock::timer::ParallelSleepDriver;
+use libtock::Hardware;
 
 async fn blink<'a>(
     timer_driver: &'a ParallelSleepDriver<'a>,
     duration: Duration<usize>,
-    led_number: usize,
+    led: &'a mut Led<'a>,
 ) -> TockResult<()> {
     loop {
-        led::get(led_number).unwrap().toggle()?;
+        led.toggle()?;
 
         timer_driver.sleep(duration).await?;
     }
@@ -21,13 +22,19 @@
 
 #[libtock::main]
 async fn main() -> TockResult<()> {
+    let Hardware { mut led_driver, .. } = libtock::retrieve_hardware()?;
+    let mut led_iter = led_driver.all();
+    let mut led_1 = led_iter.next().unwrap();
+    let mut led_2 = led_iter.next().unwrap();
+    let mut led_3 = led_iter.next().unwrap();
+
     let context = timer::DriverContext::create()?;
     let mut driver = context.create_timer_driver()?;
     let timer_driver = driver.activate()?;
 
-    let fut_1 = blink(&timer_driver, Duration::from_ms(500), 0);
-    let fut_2 = blink(&timer_driver, Duration::from_ms(333), 1);
-    let fut_3 = blink(&timer_driver, Duration::from_ms(250), 2);
+    let fut_1 = blink(&timer_driver, Duration::from_ms(500), &mut led_1);
+    let fut_2 = blink(&timer_driver, Duration::from_ms(333), &mut led_2);
+    let fut_3 = blink(&timer_driver, Duration::from_ms(250), &mut led_3);
 
     future::try_join3(fut_1, fut_2, fut_3).await?;
     Ok(())
diff --git a/examples/timer_subscribe.rs b/examples/timer_subscribe.rs
index 471e924..d1f0123 100644
--- a/examples/timer_subscribe.rs
+++ b/examples/timer_subscribe.rs
@@ -9,7 +9,7 @@
 
 #[libtock::main]
 async fn main() -> TockResult<()> {
-    let Hardware { console_driver } = libtock::retrieve_hardware()?;
+    let Hardware { console_driver, .. } = libtock::retrieve_hardware()?;
     let mut console = console_driver.create_console();
     let mut with_callback = timer::with_callback(|_, _| {
         writeln!(
diff --git a/src/hardware.rs b/src/hardware.rs
new file mode 100644
index 0000000..9cf8e98
--- /dev/null
+++ b/src/hardware.rs
@@ -0,0 +1,58 @@
+use crate::console::ConsoleDriver;
+use crate::led::LedDriver;
+use crate::result::OtherError;
+use crate::result::TockError;
+use crate::result::TockResult;
+
+/// Struct containing all drivers constructible through retrieve_hardware()
+pub struct Hardware {
+    pub console_driver: ConsoleDriver,
+    pub led_driver: LedDriver,
+}
+
+/// Retrieve Hardware struct. Returns Hardware only once.
+pub fn retrieve_hardware() -> TockResult<Hardware> {
+    match unsafe { HARDWARE_SINGLETON.take() } {
+        Some(hardware) => Ok(hardware),
+        None => Err(TockError::Other(OtherError::DriverAlreadyTaken)),
+    }
+}
+
+/// Retrieve [Hardware] struct without check whether it has already been taken
+/// at a different point.
+/// # Safety
+/// This shall only used in special situations where drivers cannot be passed as arguments
+/// as in the panic handler. Otherwise global mutable state (as shared buffers) may be exposed
+/// in an unsafe manner.
+pub unsafe fn retrieve_hardware_unsafe() -> Hardware {
+    HARDWARE
+}
+
+const HARDWARE: Hardware = Hardware {
+    console_driver: ConsoleDriver {
+        _unconstructible: (),
+    },
+    led_driver: LedDriver {
+        _unconstructible: (),
+    },
+};
+
+static mut HARDWARE_SINGLETON: Option<Hardware> = Some(HARDWARE);
+
+#[cfg(test)]
+mod test {
+    use crate::retrieve_hardware;
+    #[test]
+    pub fn can_be_retrieved_once() {
+        reset_hardware_singleton();
+
+        assert!(retrieve_hardware().is_ok());
+        assert!(retrieve_hardware().is_err());
+    }
+
+    fn reset_hardware_singleton() {
+        unsafe {
+            super::HARDWARE_SINGLETON = Some(super::HARDWARE);
+        };
+    }
+}
diff --git a/src/lang_items.rs b/src/lang_items.rs
index 197de47..0b3186e 100644
--- a/src/lang_items.rs
+++ b/src/lang_items.rs
@@ -18,9 +18,9 @@
 //! `rustc_main`. That's covered by the `_start` function in the root of this
 //! crate.
 
-use crate::led;
 use crate::timer;
 use crate::timer::Duration;
+use crate::Hardware;
 use core::alloc::Layout;
 use core::executor;
 use core::panic::PanicInfo;
@@ -50,14 +50,16 @@
         let context = timer::DriverContext::create().ok();
         let mut driver = context.as_ref().map(|c| c.create_timer_driver_unsafe());
         let timer_driver = driver.as_mut().and_then(|d| d.activate().ok());
+        let Hardware { mut led_driver, .. } = crate::retrieve_hardware_unsafe();
+
         loop {
-            for led in led::all() {
+            for mut led in led_driver.all() {
                 let _ = led.on();
             }
             if let Some(ref timer_driver) = timer_driver {
                 let _ = timer_driver.sleep(Duration::from_ms(100)).await;
             }
-            for led in led::all() {
+            for mut led in led_driver.all() {
                 let _ = led.off();
             }
             if let Some(ref timer_driver) = timer_driver {
@@ -75,14 +77,16 @@
         let context = timer::DriverContext::create().ok();
         let mut driver = context.as_ref().map(|c| c.create_timer_driver_unsafe());
         let timer_driver = driver.as_mut().and_then(|d| d.activate().ok());
+        let Hardware { mut led_driver, .. } = crate::retrieve_hardware_unsafe();
+
         loop {
-            for led in led::all() {
+            for mut led in led_driver.all() {
                 let _ = led.on();
             }
             if let Some(ref timer_driver) = timer_driver {
                 let _ = timer_driver.sleep(Duration::from_ms(100)).await;
             }
-            for led in led::all() {
+            for mut led in led_driver.all() {
                 let _ = led.off();
             }
             if let Some(ref timer_driver) = timer_driver {
diff --git a/src/led.rs b/src/led.rs
index d7aac8f..ded7d01 100644
--- a/src/led.rs
+++ b/src/led.rs
@@ -1,5 +1,6 @@
 use crate::result::TockResult;
 use crate::syscalls::command;
+use core::marker::PhantomData;
 
 const DRIVER_NUMBER: usize = 0x00002;
 
@@ -10,33 +11,45 @@
     pub const TOGGLE: usize = 3;
 }
 
-pub struct Led {
+pub struct LedDriver {
+    pub(crate) _unconstructible: (),
+}
+
+pub struct Led<'a> {
     led_num: usize,
+    phantom: PhantomData<&'a mut ()>,
 }
 
-pub fn count() -> TockResult<usize> {
-    command(DRIVER_NUMBER, command_nr::COUNT, 0, 0).map_err(Into::into)
-}
+impl LedDriver {
+    pub fn get(&mut self, led_num: usize) -> Option<Led> {
+        if led_num < self.count().ok().unwrap() {
+            Some(Led {
+                led_num,
+                phantom: PhantomData,
+            })
+        } else {
+            None
+        }
+    }
 
-pub fn get(led_num: usize) -> Option<Led> {
-    if led_num < count().ok().unwrap() {
-        Some(Led { led_num })
-    } else {
-        None
+    pub fn count(&self) -> TockResult<usize> {
+        command(DRIVER_NUMBER, command_nr::COUNT, 0, 0).map_err(Into::into)
+    }
+
+    pub fn all(&mut self) -> LedIter {
+        LedIter {
+            curr_led: 0,
+            led_count: self.count().unwrap_or(0),
+            phantom: PhantomData,
+        }
     }
 }
 
 /// Returns an iterator over all available LEDs. If the LED driver is not
 /// present, the iterator will be empty.
-pub fn all() -> LedIter {
-    LedIter {
-        curr_led: 0,
-        led_count: count().unwrap_or(0),
-    }
-}
 
-impl Led {
-    pub fn set_state(&self, state: bool) -> TockResult<()> {
+impl<'a> Led<'a> {
+    pub fn set_state(&mut self, state: bool) -> TockResult<()> {
         if state {
             self.on()
         } else {
@@ -44,35 +57,41 @@
         }
     }
 
-    pub fn on(&self) -> TockResult<()> {
+    pub fn on(&mut self) -> TockResult<()> {
         command(DRIVER_NUMBER, command_nr::ON, self.led_num, 0)?;
         Ok(())
     }
 
-    pub fn off(&self) -> TockResult<()> {
+    pub fn off(&mut self) -> TockResult<()> {
         command(DRIVER_NUMBER, command_nr::OFF, self.led_num, 0)?;
         Ok(())
     }
 
-    pub fn toggle(&self) -> TockResult<()> {
+    pub fn toggle(&mut self) -> TockResult<()> {
         command(DRIVER_NUMBER, command_nr::TOGGLE, self.led_num, 0)?;
         Ok(())
     }
+
+    pub fn number(&self) -> usize {
+        self.led_num
+    }
 }
 
 #[derive(Copy, Clone)]
-pub struct LedIter {
+pub struct LedIter<'a> {
     curr_led: usize,
     led_count: usize,
+    phantom: PhantomData<&'a ()>,
 }
 
-impl Iterator for LedIter {
-    type Item = Led;
+impl<'a> Iterator for LedIter<'a> {
+    type Item = Led<'a>;
 
     fn next(&mut self) -> Option<Self::Item> {
         if self.curr_led < self.led_count {
             let item = Led {
                 led_num: self.curr_led,
+                phantom: PhantomData,
             };
             self.curr_led += 1;
             Some(item)
diff --git a/src/lib.rs b/src/lib.rs
index 9d5ba70..2019925 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -31,56 +31,11 @@
 
 pub mod syscalls;
 
-use crate::console::ConsoleDriver;
 pub use libtock_codegen::main;
 
+mod hardware;
+pub use hardware::*;
+
 /// Dummy structure to force importing the panic_handler and other no_std elements when nothing else
 /// is imported.
 pub struct LibTock;
-
-/// Struct containing all drivers constructible through retrieve_hardware()
-pub struct Hardware {
-    pub console_driver: ConsoleDriver,
-}
-
-use result::OtherError;
-use result::TockError;
-use result::TockResult;
-
-/// Retrieve Hardware struct. Returns Hardware only once.
-pub fn retrieve_hardware() -> TockResult<Hardware> {
-    match unsafe { HARDWARE.take() } {
-        Some(hardware) => Ok(hardware),
-        None => Err(TockError::Other(OtherError::DriverAlreadyTaken)),
-    }
-}
-
-static mut HARDWARE: Option<Hardware> = Some(Hardware {
-    console_driver: ConsoleDriver {
-        _unconstructible: (),
-    },
-});
-
-#[cfg(test)]
-mod test {
-    use crate::console::ConsoleDriver;
-    use crate::retrieve_hardware;
-    use crate::Hardware;
-    #[test]
-    pub fn can_be_retrieved_once() {
-        reset_hardware_singleton();
-
-        assert!(retrieve_hardware().is_ok());
-        assert!(retrieve_hardware().is_err());
-    }
-
-    fn reset_hardware_singleton() {
-        unsafe {
-            super::HARDWARE = Some(Hardware {
-                console_driver: ConsoleDriver {
-                    _unconstructible: (),
-                },
-            })
-        };
-    }
-}