Merge pull request #170 from torfmaster/feature/libcore-futures

bors is causing trouble. Merging manually...
diff --git a/.gitignore b/.gitignore
index da66475..ae858ab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
-Cargo.lock
-layout.ld
-platform
-target
+/Cargo.lock
+/layout.ld
+/platform
+/target
diff --git a/.travis.yml b/.travis.yml
index 8efe4b7..94ba1ed 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,7 +6,7 @@
 
 language: rust
 rust:
-  - nightly-2020-01-16
+  - nightly-2020-04-06
 
 os:
   - linux
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7af6694..c036926 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,9 +9,10 @@
   - To retrieve the value of an asynchronous `value`, use `value.await`
   - This is only possible within an `async fn`, so either
     - Make the caller `fn` of `.await` an `async fn`
-    - Not recommended: Use `core::executor::block_on(value)` to retrieve the `value`
+    - Not recommended: Use `libtock::executor::block_on(value)` to retrieve the `value`
 - Most API functions, including `main()`, return a `Result<T, TockError>`
 - All drivers can exclusively be retrieved by `retrieve_drivers` which returns a `Drivers` singleton. Drivers can be shared between different tasks only if it is safe to do so.
+- The low-level functions have been moved to a new crate called `libtock-core`. This crate is intended to be less experimental and more stable.
 
 ### Changed APIs
 
@@ -42,6 +43,8 @@
 - Targets without support for atomics can be built
 - The `TockAllocator` is no longer included by default and needs to to be opted-in via `--features=alloc`
 - `hardware_test.rs` is now called `libtock_test.rs` to make clear that the intent is to test the correctness of `libtock-rs`, not the hardware or the kernel
+- The panic handler can now be customized using the `custom_panic_handler` feature
+- The error alloc handler can now be customized using the `custom_alloc_error_handler` feature
 
 ## a8bb4fa9be504517d5533511fd8e607ea61f1750 (0.1.0)
 
diff --git a/Cargo.toml b/Cargo.toml
index eb56daa..0f3a704 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,7 +12,6 @@
 __internal_disable_gpio_in_integration_test = []
 
 [dependencies]
-core = { package = "async-support", path = "async-support" }
 libtock-core = { path = "core" }
 libtock_codegen = { path = "codegen" }
 futures = { version = "0.3.1", default-features = false, features = ["unstable", "cfg-target-has-atomic"] }
@@ -58,7 +57,6 @@
 
 [workspace]
 members = [
-    "async-support",
     "codegen",
     "core",
     "test-runner"
diff --git a/async-support/Cargo.toml b/async-support/Cargo.toml
deleted file mode 100644
index 9287c6b..0000000
--- a/async-support/Cargo.toml
+++ /dev/null
@@ -1,8 +0,0 @@
-[package]
-name = "async-support"
-version = "0.1.0"
-authors = ["Woyten <woyten.tielesch@online.de>"]
-edition = "2018"
-description = "`libtock` specific patch of `core` for `async`-`await` syntax in a `#![no_std]` environment. It implements the methods `core::future::poll_with_tls_context` and `core::future::from_generator` which are currently missing in `core`."
-
-[dependencies]
diff --git a/async-support/src/lib.rs b/async-support/src/lib.rs
deleted file mode 100644
index 05946b4..0000000
--- a/async-support/src/lib.rs
+++ /dev/null
@@ -1,109 +0,0 @@
-#![feature(generator_trait)]
-#![no_std]
-
-pub use core::*;
-
-pub mod future {
-    pub use core::future::Future;
-    use core::ops::Generator;
-    use core::pin::Pin;
-    use core::task::Poll;
-
-    pub fn poll_with_tls_context<F>(f: Pin<&mut F>) -> Poll<F::Output>
-    where
-        F: Future,
-    {
-        crate::executor::poll(f)
-    }
-
-    pub fn from_generator<G: Generator<Yield = ()>>(
-        generator: G,
-    ) -> impl Future<Output = G::Return> {
-        crate::executor::from_generator(generator)
-    }
-}
-
-pub mod executor {
-    use core::future::Future;
-    use core::ops::Generator;
-    use core::ops::GeneratorState;
-    use core::pin::Pin;
-    use core::ptr;
-    use core::task::Context;
-    use core::task::Poll;
-    use core::task::RawWaker;
-    use core::task::RawWakerVTable;
-    use core::task::Waker;
-
-    extern "Rust" {
-        #[link_name = "libtock::syscalls::raw::yieldk"]
-        fn yieldk();
-    }
-
-    /// # Safety
-    ///
-    /// [[block_on]] yields whenever a future cannot make any progress at present. Yielding is considered unsafe.
-    pub unsafe fn block_on<T>(mut future: impl Future<Output = T>) -> T {
-        // Contract described in the Rustdoc: "A value, once pinned, must remain pinned forever (...).".
-        // IOW calling Pin::new_unchecked is safe as long as no &mut future is leaked after pinning.
-        let mut pinned_future = Pin::new_unchecked(&mut future);
-
-        loop {
-            match poll(pinned_future.as_mut()) {
-                Poll::Pending => yieldk(),
-                Poll::Ready(value) => {
-                    return value;
-                }
-            }
-        }
-    }
-
-    pub(crate) fn poll<F: Future>(pinned_future: Pin<&mut F>) -> Poll<F::Output> {
-        let waker = unsafe { Waker::from_raw(get_dummy_waker()) };
-        let mut context = Context::from_waker(&waker);
-        pinned_future.poll(&mut context)
-    }
-
-    // Since Tock OS comes with waking-up functionality built-in, we use dummy wakers that do nothing at all.
-    fn get_dummy_waker() -> RawWaker {
-        fn clone(_x: *const ()) -> RawWaker {
-            get_dummy_waker()
-        }
-
-        fn do_nothing(_x: *const ()) {}
-
-        // This vtable implements the methods required for managing the lifecycle of the wakers.
-        // Our wakers are dummies, so those functions don't do anything.
-        static DUMMY_WAKER_VTABLE: RawWakerVTable =
-            RawWakerVTable::new(clone, do_nothing, do_nothing, do_nothing);
-
-        // The wakers don't have any implementation, so the instance can simply be null.
-        RawWaker::new(ptr::null(), &DUMMY_WAKER_VTABLE)
-    }
-
-    pub(crate) fn from_generator<G: Generator<Yield = ()>>(
-        generator: G,
-    ) -> impl Future<Output = G::Return> {
-        GeneratorFuture { generator }
-    }
-
-    struct GeneratorFuture<G> {
-        generator: G,
-    }
-
-    impl<G: Generator<Yield = ()>> Future for GeneratorFuture<G> {
-        type Output = G::Return;
-
-        fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
-            // Pin::map_unchecked_mut is safe as long as the move and drop guarantees are propagated through the mapping.
-            // This is trivially satisfied since our future is only a newtype decorator of the generator.
-            let pinned_generator =
-                unsafe { self.map_unchecked_mut(|future| &mut future.generator) };
-
-            match pinned_generator.resume() {
-                GeneratorState::Yielded(()) => Poll::Pending,
-                GeneratorState::Complete(out) => Poll::Ready(out),
-            }
-        }
-    }
-}
diff --git a/build.rs b/build.rs
index 6d7920e..b24d3d2 100644
--- a/build.rs
+++ b/build.rs
@@ -6,21 +6,25 @@
 use std::path::Path;
 use std::process;
 
+static LAYOUT_FILE_NAME: &str = "layout.ld";
+
 fn main() {
-    static ENV_VAR: &str = "PLATFORM";
-    static FILE_NAME: &str = "platform";
+    static PLATFORM_ENV_VAR: &str = "PLATFORM";
+    static PLATFORM_FILE_NAME: &str = "platform";
     static APP_HEAP_SIZE: &str = "APP_HEAP_SIZE";
     static KERNEL_HEAP_SIZE: &str = "KERNEL_HEAP_SIZE";
 
-    println!("cargo:rerun-if-env-changed={}", ENV_VAR);
+    println!("cargo:rerun-if-env-changed={}", PLATFORM_ENV_VAR);
     println!("cargo:rerun-if-env-changed={}", APP_HEAP_SIZE);
     println!("cargo:rerun-if-env-changed={}", KERNEL_HEAP_SIZE);
-    println!("cargo:rerun-if-changed={}", FILE_NAME);
+    println!("cargo:rerun-if-changed={}", PLATFORM_FILE_NAME);
+    println!("cargo:rerun-if-changed={}", LAYOUT_FILE_NAME);
 
-    let platform_name = read_env_var(ENV_VAR).or_else(|| read_board_name_from_file(FILE_NAME));
+    let platform_name =
+        read_env_var(PLATFORM_ENV_VAR).or_else(|| read_board_name_from_file(PLATFORM_FILE_NAME));
     if let Some(platform_name) = platform_name {
-        println!("cargo:rustc-env={}={}", ENV_VAR, platform_name);
-        copy_linker_file(&platform_name.trim());
+        println!("cargo:rustc-env={}={}", PLATFORM_ENV_VAR, platform_name);
+        copy_linker_file(platform_name.trim());
     } else {
         println!(
             "cargo:warning=No platform specified. \
@@ -66,5 +70,5 @@
         println!("Cannot find layout file {:?}", path);
         process::exit(1);
     }
-    fs::copy(linker_file_name, "layout.ld").unwrap();
+    fs::copy(linker_file_name, LAYOUT_FILE_NAME).unwrap();
 }
diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs
index ccb0bfb..e13fc97 100644
--- a/codegen/src/lib.rs
+++ b/codegen/src/lib.rs
@@ -98,7 +98,7 @@
                 MAIN_INVOKED = true;
             }
             let _block = async #block;
-            unsafe {::core::executor::block_on(_block) }
+            unsafe { ::libtock::executor::block_on(_block) }
         }
     ))
 }
@@ -126,7 +126,7 @@
                 let _block = async {
                     method_call().await;
                 };
-                unsafe { ::core::executor::block_on(_block) }
+                unsafe { ::libtock::executor::block_on(_block) }
             }
         ))
         .unwrap();
diff --git a/core/Cargo.toml b/core/Cargo.toml
index 3110346..94f3c8f 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -10,5 +10,5 @@
 custom_alloc_error_handler = []
 
 [dependencies]
-linked_list_allocator = { optional = true, version = "=0.6.5", default-features = false }
+linked_list_allocator = { optional = true, version = "=0.8.1", default-features = false }
 libtock_codegen = { path = "../codegen" }
diff --git a/core/src/entry_point/start_item_arm.rs b/core/src/entry_point/start_item_arm.rs
index c3bfab7..c9390f6 100644
--- a/core/src/entry_point/start_item_arm.rs
+++ b/core/src/entry_point/start_item_arm.rs
@@ -105,7 +105,7 @@
         bl rust_start"
         :                                                              // No output operands
         : "{r0}"(app_start), "{r1}"(mem_start), "{r3}"(app_heap_break) // Input operands
-        : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r12",
+        : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r12",
           "cc", "memory"                                               // Clobbers
         : "volatile"                                                   // Options
     );
diff --git a/core/src/syscalls/mod.rs b/core/src/syscalls/mod.rs
index 833c356..bae938b 100644
--- a/core/src/syscalls/mod.rs
+++ b/core/src/syscalls/mod.rs
@@ -10,23 +10,7 @@
 use crate::shared_memory::SharedMemory;
 
 pub mod raw {
-    use super::platform;
-
-    pub use platform::*;
-
-    /// # Safety
-    ///
-    /// Yielding in the main function should be safe. Nevertheless, yielding manually is not required as this is already achieved by the `async` runtime.
-    ///
-    /// When yielding in callbacks, two problems can arise:
-    /// - The guarantees of `FnMut` are violated. In this case, make sure your callback has `Fn` behavior.
-    /// - Callbacks can get executed in a nested manner and overflow the stack quickly.
-    ///
-    /// This function is exported as `libtock::syscalls::raw::yieldk`. Do not reference this name directly. Its only purpose is to establish a back-channel from `async-support`, a patched version of `core` to `libtock-rs` via linking. This workaround has been chosen to keep the `core` crate free of dependencies on platform-specific syscall implementations and is expected to get removed as soon as possible.
-    #[export_name = "libtock::syscalls::raw::yieldk"]
-    pub unsafe fn yieldk() {
-        platform::yieldk()
-    }
+    pub use super::platform::*;
 }
 
 pub fn subscribe<C: Consumer<T>, T>(
diff --git a/core/src/syscalls/platform.rs b/core/src/syscalls/platform.rs
index 66e79f0..3d039d5 100644
--- a/core/src/syscalls/platform.rs
+++ b/core/src/syscalls/platform.rs
@@ -3,9 +3,15 @@
 use std::vec::Vec;
 
 /// yield for a callback fired by the kernel
+///
 /// # Safety
-/// Yielding inside a callback conflicts with Rust's safety guarantees. For example,
-/// a FnMut closure could be triggered multiple times making a &mut a shared reference.
+///
+/// Yielding in the main function should be safe. Nevertheless, yielding manually
+/// is not required as this is already achieved by the `async` runtime.
+///
+/// When yielding in callbacks, two problems can arise:
+/// - The guarantees of `FnMut` are violated. In this case, make sure your callback has `Fn` behavior.
+/// - Callbacks can get executed in a nested manner and overflow the stack quickly.
 pub unsafe fn yieldk() {
     EVENTS.with(|e| e.borrow_mut().push(Event::YieldK));
 }
diff --git a/rust-toolchain b/rust-toolchain
index 20d9cda..8bd4ff0 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1 +1 @@
-nightly-2020-01-16
+nightly-2020-04-06
diff --git a/src/console.rs b/src/console.rs
index ee6f50a..a94fc13 100644
--- a/src/console.rs
+++ b/src/console.rs
@@ -1,9 +1,9 @@
 use crate::callback::Identity0Consumer;
+use crate::executor;
 use crate::futures;
 use crate::result::TockResult;
 use crate::syscalls;
 use core::cell::Cell;
-use core::executor;
 use core::fmt;
 use core::mem;
 
diff --git a/src/drivers.rs b/src/drivers.rs
index 8d8e8ab..185f6ea 100644
--- a/src/drivers.rs
+++ b/src/drivers.rs
@@ -5,7 +5,6 @@
 use crate::leds::LedsDriverFactory;
 use crate::result::OtherError;
 use crate::result::TockError;
-use crate::result::TockResult;
 use crate::rng::RngDriver;
 use crate::sensors::ninedof::NinedofDriver;
 use crate::sensors::AmbientLightSensor;
@@ -37,12 +36,12 @@
 }
 
 /// Retrieve [Drivers] struct. Returns struct only once.
-pub fn retrieve_drivers() -> TockResult<Drivers> {
+pub fn retrieve_drivers() -> Result<Drivers, DriversAlreadyTakenError> {
     static mut DRIVER_TAKEN: bool = false;
 
     unsafe {
         if DRIVER_TAKEN {
-            Err(TockError::Other(OtherError::DriverAlreadyTaken))
+            Err(DriversAlreadyTakenError)
         } else {
             DRIVER_TAKEN = true;
             Ok(retrieve_drivers_unsafe())
@@ -79,3 +78,11 @@
     humidity_sensor: HumiditySensor,
     ninedof: NinedofDriver,
 };
+
+pub struct DriversAlreadyTakenError;
+
+impl From<DriversAlreadyTakenError> for TockError {
+    fn from(_: DriversAlreadyTakenError) -> Self {
+        TockError::Other(OtherError::DriversAlreadyTaken)
+    }
+}
diff --git a/src/executor.rs b/src/executor.rs
new file mode 100644
index 0000000..9204616
--- /dev/null
+++ b/src/executor.rs
@@ -0,0 +1,50 @@
+use crate::syscalls;
+use core::pin::Pin;
+use core::ptr;
+use core::task::Context;
+use core::task::Poll;
+use core::task::RawWaker;
+use core::task::RawWakerVTable;
+use core::task::Waker;
+use futures::Future;
+
+/// # Safety
+///
+/// [[block_on]] yields whenever a future cannot make any progress at present. Yielding is considered unsafe.
+pub unsafe fn block_on<T>(mut future: impl Future<Output = T>) -> T {
+    // Contract described in the Rustdoc: "A value, once pinned, must remain pinned forever (...).".
+    // IOW calling Pin::new_unchecked is safe as long as no &mut future is leaked after pinning.
+    let mut pinned_future = Pin::new_unchecked(&mut future);
+
+    loop {
+        match poll(pinned_future.as_mut()) {
+            Poll::Pending => syscalls::raw::yieldk(),
+            Poll::Ready(value) => {
+                return value;
+            }
+        }
+    }
+}
+
+fn poll<F: Future>(pinned_future: Pin<&mut F>) -> Poll<F::Output> {
+    let waker = unsafe { Waker::from_raw(get_dummy_waker()) };
+    let mut context = Context::from_waker(&waker);
+    pinned_future.poll(&mut context)
+}
+
+// Since Tock OS comes with waking-up functionality built-in, we use dummy wakers that do nothing at all.
+fn get_dummy_waker() -> RawWaker {
+    fn clone(_x: *const ()) -> RawWaker {
+        get_dummy_waker()
+    }
+
+    fn do_nothing(_x: *const ()) {}
+
+    // This vtable implements the methods required for managing the lifecycle of the wakers.
+    // Our wakers are dummies, so those functions don't do anything.
+    static DUMMY_WAKER_VTABLE: RawWakerVTable =
+        RawWakerVTable::new(clone, do_nothing, do_nothing, do_nothing);
+
+    // The wakers don't have any implementation, so the instance can simply be null.
+    RawWaker::new(ptr::null(), &DUMMY_WAKER_VTABLE)
+}
diff --git a/src/lib.rs b/src/lib.rs
index 0aabb1a..152e223 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,4 +1,4 @@
-#![cfg_attr(any(target_arch = "arm", target_arch = "riscv32"), no_std)]
+#![cfg_attr(not(test), no_std)]
 
 pub mod adc;
 pub mod ble_composer;
@@ -8,6 +8,7 @@
 pub mod debug;
 pub mod drivers;
 pub mod electronics;
+pub mod executor;
 pub mod futures;
 pub mod gpio;
 pub mod leds;
diff --git a/src/result.rs b/src/result.rs
index 74b4786..84af6bf 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -50,8 +50,8 @@
     GpioDriverInvalidState,
     TimerDriverDurationOutOfRange,
     TimerDriverErroneousClockFrequency,
-    DriverAlreadyTaken,
-    OutOfRangeError,
+    DriversAlreadyTaken,
+    OutOfRange,
 }
 
 impl From<OtherError> for TockError {
@@ -63,7 +63,7 @@
 pub struct OutOfRangeError;
 
 impl From<OutOfRangeError> for TockError {
-    fn from(_other: OutOfRangeError) -> Self {
-        TockError::Other(OtherError::OutOfRangeError)
+    fn from(_: OutOfRangeError) -> Self {
+        TockError::Other(OtherError::OutOfRange)
     }
 }
diff --git a/src/sensors/mod.rs b/src/sensors/mod.rs
index c4b962f..f3a0e7a 100644
--- a/src/sensors/mod.rs
+++ b/src/sensors/mod.rs
@@ -1,9 +1,9 @@
+use crate::executor;
 use crate::futures;
 use crate::result::TockResult;
 use crate::syscalls;
 use core::cell::Cell;
 use core::convert::From;
-use core::executor;
 use core::fmt;
 use core::mem;
 
diff --git a/src/sensors/ninedof.rs b/src/sensors/ninedof.rs
index e468690..b5e7191 100644
--- a/src/sensors/ninedof.rs
+++ b/src/sensors/ninedof.rs
@@ -1,8 +1,8 @@
+use crate::executor;
 use crate::futures;
 use crate::result::TockResult;
 use crate::syscalls;
 use core::cell::Cell;
-use core::executor;
 use core::fmt;
 use core::mem;