Merge #149

149: Update Rust toolchain r=Woyten a=Woyten

Fixes #138 and updates the Rust toolchain s.t. it is in line with Tock OS.

Co-authored-by: Woyten <woyten.tielesch@online.de>
diff --git a/.travis.yml b/.travis.yml
index 651ad97..dae25d0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,7 +7,7 @@
 
 language: rust
 rust:
-  - nightly-2019-11-06
+  - nightly-2020-01-16
 
 os:
   - linux
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 68c463d..1caeca5 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -45,6 +45,7 @@
 [      OK ] Dynamic dispatch
 [      OK ] Formatting
 [      OK ] Heap
+[      OK ] Drivers only instantiable once
 [      OK ] Callbacks
 [      OK ] GPIO initialization
 [      OK ] GPIO activation
diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs
index 6f51b9f..9804e29 100644
--- a/codegen/src/lib.rs
+++ b/codegen/src/lib.rs
@@ -5,7 +5,6 @@
 use proc_macro::TokenStream;
 
 use quote::quote;
-use syn;
 use syn::Error;
 use syn::ItemFn;
 
diff --git a/examples-alloc/libtock_test.rs b/examples-alloc/libtock_test.rs
index d764af3..26cccb4 100644
--- a/examples-alloc/libtock_test.rs
+++ b/examples-alloc/libtock_test.rs
@@ -46,6 +46,7 @@
     test.dynamic_dispatch()?;
     test.formatting()?;
     test.heap()?;
+    test.drivers_only_instantiable_once()?;
     test.callbacks(timer).await?;
     test.gpio(gpio)?;
     Ok(())
@@ -100,6 +101,13 @@
         self.check_if_true(string == "foobar", "Heap")
     }
 
+    fn drivers_only_instantiable_once(&mut self) -> TockResult<()> {
+        self.check_if_true(
+            libtock::retrieve_drivers().is_err(),
+            "Drivers only instantiable once",
+        )
+    }
+
     async fn callbacks(&mut self, timer_context: &mut DriverContext) -> TockResult<()> {
         let mut callback_hit = false;
         let mut with_callback = timer_context.with_callback(|_, _| callback_hit = true);
diff --git a/run_all_checks.sh b/run_all_checks.sh
index c445608..3dde5ff 100755
--- a/run_all_checks.sh
+++ b/run_all_checks.sh
@@ -5,6 +5,6 @@
 export PLATFORM=nrf52 # The specific platform doesn't matter for tests
 
 cargo fmt --all -- --check
-cargo test --workspace
 cargo clippy --workspace --all-targets
+cargo test --workspace
 ./build_examples.sh
diff --git a/rust-toolchain b/rust-toolchain
index 22e9048..20d9cda 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1 +1 @@
-nightly-2019-11-06
+nightly-2020-01-16
diff --git a/src/drivers.rs b/src/drivers.rs
index a8e1e98..4e7eff8 100644
--- a/src/drivers.rs
+++ b/src/drivers.rs
@@ -38,9 +38,15 @@
 
 /// Retrieve [Drivers] struct. Returns struct only once.
 pub fn retrieve_drivers() -> TockResult<Drivers> {
-    match unsafe { DRIVERS_SINGLETON.take() } {
-        Some(drivers) => Ok(drivers),
-        None => Err(TockError::Other(OtherError::DriverAlreadyTaken)),
+    static mut DRIVER_TAKEN: bool = false;
+
+    unsafe {
+        if DRIVER_TAKEN {
+            Err(TockError::Other(OtherError::DriverAlreadyTaken))
+        } else {
+            DRIVER_TAKEN = true;
+            Ok(retrieve_drivers_unsafe())
+        }
     }
 }
 
@@ -73,24 +79,3 @@
     humidity_sensor: HumiditySensor,
     ninedof: NinedofDriver,
 };
-
-static mut DRIVERS_SINGLETON: Option<Drivers> = Some(DRIVERS);
-
-#[cfg(test)]
-mod test {
-    use super::*;
-
-    #[test]
-    pub fn can_be_retrieved_once() {
-        reset_drivers_singleton();
-
-        assert!(retrieve_drivers().is_ok());
-        assert!(retrieve_drivers().is_err());
-    }
-
-    fn reset_drivers_singleton() {
-        unsafe {
-            DRIVERS_SINGLETON = Some(DRIVERS);
-        };
-    }
-}
diff --git a/src/lang_items.rs b/src/lang_items.rs
index b8731a2..9c301eb 100644
--- a/src/lang_items.rs
+++ b/src/lang_items.rs
@@ -27,11 +27,12 @@
 use core::panic::PanicInfo;
 
 #[lang = "start"]
-extern "C" fn start<T>(main: fn() -> T, _argc: isize, _argv: *const *const u8)
+extern "C" fn start<T>(main: fn() -> T, _argc: isize, _argv: *const *const u8) -> bool
 where
     T: Termination,
 {
     main().check_result();
+    true // Need to return anything sized. Otherwise, a linker error pops up. (See https://github.com/tock/libtock-rs/issues/138)
 }
 
 #[lang = "termination"]