Add gpio to drivers singleton
diff --git a/src/electronics/shift_register.rs b/src/electronics/shift_register.rs
index f170225..10eac0d 100644
--- a/src/electronics/shift_register.rs
+++ b/src/electronics/shift_register.rs
@@ -1,18 +1,18 @@
 use crate::gpio::GpioPinWrite;
 use crate::result::TockResult;
 
-pub struct ShiftRegister {
-    data_pin: GpioPinWrite,
-    clock_pin: GpioPinWrite,
-    latch_pin: GpioPinWrite,
+pub struct ShiftRegister<'a> {
+    data_pin: GpioPinWrite<'a>,
+    clock_pin: GpioPinWrite<'a>,
+    latch_pin: GpioPinWrite<'a>,
 }
 
-impl ShiftRegister {
+impl<'a> ShiftRegister<'a> {
     pub fn new(
-        data_pin: GpioPinWrite,
-        clock_pin: GpioPinWrite,
-        latch_pin: GpioPinWrite,
-    ) -> ShiftRegister {
+        data_pin: GpioPinWrite<'a>,
+        clock_pin: GpioPinWrite<'a>,
+        latch_pin: GpioPinWrite<'a>,
+    ) -> ShiftRegister<'a> {
         ShiftRegister {
             data_pin,
             clock_pin,
@@ -20,14 +20,14 @@
         }
     }
 
-    pub fn write_bits(&self, values: &[bool]) -> TockResult<()> {
+    pub fn write_bits(&mut self, values: &[bool]) -> TockResult<()> {
         for i in values {
             self.push_bit(*i)?;
         }
         self.display()
     }
 
-    fn push_bit(&self, value: bool) -> TockResult<()> {
+    fn push_bit(&mut self, value: bool) -> TockResult<()> {
         if value {
             self.data_pin.set_high()
         } else {
@@ -37,7 +37,7 @@
         self.clock_pin.set_low()
     }
 
-    fn display(&self) -> TockResult<()> {
+    fn display(&mut self) -> TockResult<()> {
         self.latch_pin.set_high()?;
         self.latch_pin.set_low()
     }
diff --git a/src/gpio.rs b/src/gpio.rs
index d416632..e8e0373 100644
--- a/src/gpio.rs
+++ b/src/gpio.rs
@@ -1,9 +1,12 @@
+use crate::result::OtherError;
+use crate::result::TockError;
 use crate::result::TockResult;
 use crate::syscalls;
+use core::marker::PhantomData;
 
 const DRIVER_NUMBER: usize = 0x00004;
-mod gpio_commands {
-    pub const SUBSCRIBE_CALLBACK: usize = 0;
+mod command_nr {
+    pub const NUMBER_PINS: usize = 0;
     pub const ENABLE_OUTPUT: usize = 1;
     pub const SET_HIGH: usize = 2;
     pub const SET_LOW: usize = 3;
@@ -15,6 +18,65 @@
     pub const DISABLE: usize = 9;
 }
 
+mod subscribe_nr {
+    pub const SUBSCRIBE_CALLBACK: usize = 0;
+}
+
+pub struct GpioDriver {
+    pub(crate) _unconstructible: (),
+}
+
+impl GpioDriver {
+    pub fn all_pins<'a>(&'a mut self) -> TockResult<GpioIter<'a>> {
+        let number = self.number_of_pins()?;
+        Ok(GpioIter {
+            curr_gpio: 0,
+            gpio_count: number,
+            phantom: PhantomData,
+        })
+    }
+
+    pub fn pin<'a>(&'a mut self, pin: usize) -> TockResult<GpioPinUnitialized<'a>> {
+        let number = self.number_of_pins()?;
+        if pin < number {
+            Ok(GpioPinUnitialized {
+                number: pin,
+                phantom: PhantomData,
+            })
+        } else {
+            Err(TockError::Other(OtherError::NotEnoughGpioPins))
+        }
+    }
+
+    fn number_of_pins(&self) -> TockResult<usize> {
+        syscalls::command(DRIVER_NUMBER, command_nr::NUMBER_PINS, 0, 0).map_err(Into::into)
+    }
+}
+
+#[derive(Copy, Clone)]
+pub struct GpioIter<'a> {
+    curr_gpio: usize,
+    gpio_count: usize,
+    phantom: PhantomData<&'a mut ()>,
+}
+
+impl<'a> Iterator for GpioIter<'a> {
+    type Item = GpioPinUnitialized<'a>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.curr_gpio < self.gpio_count {
+            let item = GpioPinUnitialized {
+                number: self.curr_gpio,
+                phantom: PhantomData,
+            };
+            self.curr_gpio += 1;
+            Some(item)
+        } else {
+            None
+        }
+    }
+}
+
 pub enum InputMode {
     PullUp,
     PullDown,
@@ -47,27 +109,34 @@
     }
 }
 
-pub struct GpioPinUnitialized {
+pub struct GpioPinUnitialized<'a> {
     number: usize,
+    phantom: PhantomData<&'a mut ()>,
 }
 
-pub struct GpioPinWrite {
+pub struct GpioPinWrite<'a> {
     number: usize,
+    phantom: PhantomData<&'a mut ()>,
 }
 
-pub struct GpioPinRead {
+pub struct GpioPinRead<'a> {
     number: usize,
+    phantom: PhantomData<&'a mut ()>,
 }
 
-impl GpioPinUnitialized {
-    pub fn new(number: usize) -> GpioPinUnitialized {
-        GpioPinUnitialized { number }
+impl<'a> GpioPinUnitialized<'a> {
+    pub fn new(number: usize) -> GpioPinUnitialized<'a> {
+        GpioPinUnitialized {
+            number,
+            phantom: PhantomData,
+        }
     }
 
-    pub fn open_for_write(self) -> TockResult<GpioPinWrite> {
-        syscalls::command(DRIVER_NUMBER, gpio_commands::ENABLE_OUTPUT, self.number, 0)?;
+    pub fn open_for_write(self) -> TockResult<GpioPinWrite<'a>> {
+        syscalls::command(DRIVER_NUMBER, command_nr::ENABLE_OUTPUT, self.number, 0)?;
         Ok(GpioPinWrite {
             number: self.number,
+            phantom: PhantomData,
         })
     }
 
@@ -75,85 +144,81 @@
         self,
         callback: Option<(extern "C" fn(usize, usize, usize, usize), IrqMode)>,
         input_mode: InputMode,
-    ) -> TockResult<GpioPinRead> {
+    ) -> TockResult<GpioPinRead<'a>> {
         let (callback, irq_mode) = callback.unwrap_or((noop_callback, IrqMode::EitherEdge));
         self.enable_input(input_mode)
             .and_then(|pin| pin.subscribe_callback(callback))
-            .and_then(|pin| pin.enable_callback(irq_mode))
+            .and_then(move |pin| pin.enable_callback(irq_mode))
     }
 
     fn subscribe_callback(
         self,
         callback: extern "C" fn(usize, usize, usize, usize),
-    ) -> TockResult<GpioPinUnitialized> {
+    ) -> TockResult<GpioPinUnitialized<'a>> {
         syscalls::subscribe_fn(
             DRIVER_NUMBER,
-            gpio_commands::SUBSCRIBE_CALLBACK,
+            subscribe_nr::SUBSCRIBE_CALLBACK,
             callback,
             self.number,
         )?;
         Ok(self)
     }
 
-    fn enable_input(self, mode: InputMode) -> TockResult<GpioPinUnitialized> {
+    fn enable_input(self, mode: InputMode) -> TockResult<GpioPinUnitialized<'a>> {
         syscalls::command(
             DRIVER_NUMBER,
-            gpio_commands::ENABLE_INPUT,
+            command_nr::ENABLE_INPUT,
             self.number,
             mode.to_num(),
         )?;
         Ok(self)
     }
 
-    fn enable_callback(self, irq_mode: IrqMode) -> TockResult<GpioPinRead> {
+    fn enable_callback(self, irq_mode: IrqMode) -> TockResult<GpioPinRead<'a>> {
         syscalls::command(
             DRIVER_NUMBER,
-            gpio_commands::ENABLE_INTERRUPT,
+            command_nr::ENABLE_INTERRUPT,
             self.number,
             irq_mode.to_num(),
         )?;
         Ok(GpioPinRead {
             number: self.number,
+            phantom: PhantomData,
         })
     }
 }
 
-impl GpioPinWrite {
-    pub fn set_low(&self) -> TockResult<()> {
-        syscalls::command(DRIVER_NUMBER, gpio_commands::SET_LOW, self.number, 0)?;
+impl<'a> GpioPinWrite<'a> {
+    pub fn set_low(&mut self) -> TockResult<()> {
+        syscalls::command(DRIVER_NUMBER, command_nr::SET_LOW, self.number, 0)?;
         Ok(())
     }
-    pub fn set_high(&self) -> TockResult<()> {
-        syscalls::command(DRIVER_NUMBER, gpio_commands::SET_HIGH, self.number, 0)?;
+    pub fn set_high(&mut self) -> TockResult<()> {
+        syscalls::command(DRIVER_NUMBER, command_nr::SET_HIGH, self.number, 0)?;
         Ok(())
     }
-    pub fn toggle(&self) -> TockResult<()> {
-        syscalls::command(DRIVER_NUMBER, gpio_commands::TOGGLE, self.number, 0)?;
+    pub fn toggle(&mut self) -> TockResult<()> {
+        syscalls::command(DRIVER_NUMBER, command_nr::TOGGLE, self.number, 0)?;
         Ok(())
     }
 }
 
-impl GpioPinRead {
-    pub fn read(&self) -> bool {
-        syscalls::command(DRIVER_NUMBER, gpio_commands::READ, self.number, 0).ok() == Some(1)
+impl<'a> GpioPinRead<'a> {
+    pub fn read(&'a self) -> bool {
+        syscalls::command(DRIVER_NUMBER, command_nr::READ, self.number, 0).ok() == Some(1)
     }
 }
 
-impl Drop for GpioPinWrite {
+impl<'a> Drop for GpioPinWrite<'a> {
     fn drop(&mut self) {
-        let _ = syscalls::command(DRIVER_NUMBER, gpio_commands::DISABLE, self.number, 0);
+        let _ = syscalls::command(DRIVER_NUMBER, command_nr::DISABLE, self.number, 0);
     }
 }
 
-impl Drop for GpioPinRead {
+impl<'a> Drop for GpioPinRead<'a> {
     fn drop(&mut self) {
-        let _ = syscalls::command(
-            DRIVER_NUMBER,
-            gpio_commands::DISABLE_INTERRUPT,
-            self.number,
-            0,
-        );
-        let _ = syscalls::command(DRIVER_NUMBER, gpio_commands::DISABLE, self.number, 0);
+        let _ = syscalls::command(DRIVER_NUMBER, command_nr::DISABLE_INTERRUPT, self.number, 0);
+        let _ = syscalls::command(DRIVER_NUMBER, command_nr::DISABLE, self.number, 0);
     }
 }
 
diff --git a/src/hardware.rs b/src/hardware.rs
index 6e8b84d..bd9a87d 100644
--- a/src/hardware.rs
+++ b/src/hardware.rs
@@ -1,4 +1,5 @@
 use crate::console::ConsoleDriver;
+use crate::gpio::GpioDriver;
 use crate::led::LedDriver;
 use crate::result::OtherError;
 use crate::result::TockError;
@@ -11,6 +12,7 @@
     pub console_driver: ConsoleDriver,
     pub led_driver: LedDriver,
     pub timer_context: DriverContext,
+    pub gpio_driver: GpioDriver,
 }
 
 /// Retrieve Hardware struct. Returns Hardware only once.
@@ -42,6 +44,9 @@
     timer_context: DriverContext {
         active_timer: Cell::new(None),
     },
+    gpio_driver: GpioDriver {
+        _unconstructible: (),
+    },
 };
 
 static mut HARDWARE_SINGLETON: Option<Hardware> = Some(HARDWARE);
diff --git a/src/led.rs b/src/led.rs
index ded7d01..ae2a2d4 100644
--- a/src/led.rs
+++ b/src/led.rs
@@ -81,7 +81,7 @@
 pub struct LedIter<'a> {
     curr_led: usize,
     led_count: usize,
-    phantom: PhantomData<&'a ()>,
+    phantom: PhantomData<&'a mut ()>,
 }
 
 impl<'a> Iterator for LedIter<'a> {
diff --git a/src/result.rs b/src/result.rs
index 4eaec21..f3929ca 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -70,6 +70,7 @@
     TimerDriverDurationOutOfRange,
     TimerDriverErroneousClockFrequency,
     DriverAlreadyTaken,
+    NotEnoughGpioPins,
 }
 
 impl From<OtherError> for TockError {