Merge #165

165: Makefile: Fix the OpenTitan target r=torfmaster a=alistair23

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>

Co-authored-by: Alistair Francis <alistair.francis@wdc.com>
diff --git a/.gitignore b/.gitignore
index e8cecc0..da66475 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
 Cargo.lock
 layout.ld
+platform
 target
diff --git a/Cargo.toml b/Cargo.toml
index 2fcb4bf..5641d3c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,12 +6,14 @@
 edition = "2018"
 
 [features]
-alloc = [ "linked_list_allocator" ]
+alloc = ["libtock-core/alloc"]
+custom_panic_handler = ["libtock-core/custom_panic_handler"]
+custom_alloc_error_handler = ["libtock-core/custom_alloc_error_handler"]
 
 [dependencies]
 core = { package = "async-support", path = "async-support" }
+libtock-core = { path = "core" }
 libtock_codegen = { path = "codegen" }
-linked_list_allocator = { optional = true, version = "=0.6.5", default-features = false }
 futures = { version = "0.3.1", default-features = false, features = ["unstable", "cfg-target-has-atomic"] }
 
 [dev-dependencies]
@@ -22,22 +24,27 @@
 
 [[example]]
 name = "alloc_error"
-path = "examples-alloc/alloc_error.rs"
-required-features = ["alloc"]
+path = "examples-features/alloc_error.rs"
+required-features = ["alloc", "custom_alloc_error_handler"]
 
 [[example]]
 name = "ble_scanning"
-path = "examples-alloc/ble_scanning.rs"
+path = "examples-features/ble_scanning.rs"
 required-features = ["alloc"]
 
 [[example]]
 name = "libtock_test"
-path = "examples-alloc/libtock_test.rs"
+path = "examples-features/libtock_test.rs"
 required-features = ["alloc"]
 
 [[example]]
+name = "panic"
+path = "examples-features/panic.rs"
+required-features = ["custom_panic_handler"]
+
+[[example]]
 name = "simple_ble"
-path = "examples-alloc/simple_ble.rs"
+path = "examples-features/simple_ble.rs"
 required-features = ["alloc"]
 
 [profile.dev]
@@ -52,4 +59,5 @@
 members = [
     "async-support",
     "codegen",
+    "core"
 ]
diff --git a/Makefile b/Makefile
index 27157a9..ef2ef29 100644
--- a/Makefile
+++ b/Makefile
@@ -42,7 +42,9 @@
 examples:
 	PLATFORM=nrf52 cargo build --release --target=thumbv7em-none-eabi --examples
 	PLATFORM=nrf52 cargo build --release --target=thumbv7em-none-eabi --examples --features=alloc
-	PLATFORM=opentitan cargo build --release --target=riscv32imc-unknown-none-elf --examples
+	PLATFORM=nrf52 cargo build --release --target=thumbv7em-none-eabi --example panic --features=custom_panic_handler,custom_alloc_error_handler
+	PLATFORM=nrf52 cargo build --release --target=thumbv7em-none-eabi --example alloc_error --features=alloc,custom_alloc_error_handler
+	PLATFORM=opentitan cargo build --release --target=riscv32imc-unknown-none-elf --examples # Important: This is testing a platform without atomics support
 
 .PHONY: test
 test:
diff --git a/core/Cargo.toml b/core/Cargo.toml
new file mode 100644
index 0000000..64fa96e
--- /dev/null
+++ b/core/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "libtock-core"
+version = "0.1.0"
+authors = ["Tock Project Developers <tock-dev@googlegroups.com>"]
+edition = "2018"
+
+[features]
+alloc = [ "linked_list_allocator" ]
+custom_panic_handler = []
+custom_alloc_error_handler = []
+
+[dependencies]
+linked_list_allocator = { optional = true, version = "=0.6.5", default-features = false }
diff --git a/core/README.md b/core/README.md
new file mode 100644
index 0000000..ba9602a
--- /dev/null
+++ b/core/README.md
@@ -0,0 +1,33 @@
+# libtock-core
+
+Core crate of `libtock-rs`. It contains the architecture specific code of `libtock-rs`. In particular:
+
+ * the entry point
+ * `panic` and `alloc_error` handlers
+ * the syscalls
+ * the allocator (optional)
+
+It has three important feature flags
+
+ * `alloc` - allow for heap. Enables a linked list allocator.
+ * `custom_panic_handler` - disable the default panic  handler and allow definition of a custom one using `#[panic_handler]`
+ * `custom_alloc_error_handler` - disable the default alloc error handler and allow definition of a custom one using `#[alloc_error_handler]`
+
+## License
+
+Licensed under either of
+
+- Apache License, Version 2.0
+  ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
+- MIT license
+  ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
+
+at your option.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
+dual licensed as above, without any additional terms or conditions.
+
+The contribution guidelines are identical to those of `libtock-rs` and can be found here: [contribution guidelines](../CONTRIBUTING.md)
diff --git a/core/src/alloc.rs b/core/src/alloc.rs
new file mode 100644
index 0000000..05e9669
--- /dev/null
+++ b/core/src/alloc.rs
@@ -0,0 +1,40 @@
+use core::alloc::GlobalAlloc;
+use core::alloc::Layout;
+use core::ptr;
+use core::ptr::NonNull;
+use linked_list_allocator::Heap;
+
+pub static mut HEAP: Heap = Heap::empty();
+
+struct TockAllocator;
+
+unsafe impl GlobalAlloc for TockAllocator {
+    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+        HEAP.allocate_first_fit(layout)
+            .ok()
+            .map_or(ptr::null_mut(), NonNull::as_ptr)
+    }
+
+    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
+        HEAP.deallocate(NonNull::new_unchecked(ptr), layout)
+    }
+}
+
+#[global_allocator]
+static ALLOCATOR: TockAllocator = TockAllocator;
+
+#[cfg(not(feature = "custom_alloc_error_handler"))]
+#[alloc_error_handler]
+unsafe fn alloc_error_handler(_: Layout) -> ! {
+    use crate::syscalls;
+
+    // Print 0x01 using the LowLevelDebug capsule (if available).
+    let _ = syscalls::command1_insecure(8, 2, 0x01);
+
+    // Signal a panic using the LowLevelDebug capsule (if available).
+    let _ = syscalls::command1_insecure(8, 1, 0x01);
+
+    loop {
+        syscalls::raw::yieldk();
+    }
+}
diff --git a/src/callback.rs b/core/src/callback.rs
similarity index 100%
rename from src/callback.rs
rename to core/src/callback.rs
diff --git a/core/src/debug/mod.rs b/core/src/debug/mod.rs
new file mode 100644
index 0000000..1f30644
--- /dev/null
+++ b/core/src/debug/mod.rs
@@ -0,0 +1,5 @@
+#[cfg_attr(target_arch = "arm", path = "platform_arm.rs")]
+#[cfg_attr(target_arch = "riscv32", path = "platform_riscv32.rs")]
+mod platform;
+
+pub use platform::*;
diff --git a/core/src/debug/platform.rs b/core/src/debug/platform.rs
new file mode 100644
index 0000000..5f1f9f4
--- /dev/null
+++ b/core/src/debug/platform.rs
@@ -0,0 +1,3 @@
+pub fn get_stack_pointer() -> usize {
+    panic!("No generic implementation.")
+}
diff --git a/core/src/debug/platform_arm.rs b/core/src/debug/platform_arm.rs
new file mode 100644
index 0000000..46211b3
--- /dev/null
+++ b/core/src/debug/platform_arm.rs
@@ -0,0 +1,5 @@
+pub fn get_stack_pointer() -> usize {
+    let stack_pointer;
+    unsafe { asm!("mov $0, sp" : "=r"(stack_pointer) : : : "volatile") };
+    stack_pointer
+}
diff --git a/core/src/debug/platform_riscv32.rs b/core/src/debug/platform_riscv32.rs
new file mode 100644
index 0000000..7f4a4e0
--- /dev/null
+++ b/core/src/debug/platform_riscv32.rs
@@ -0,0 +1,5 @@
+pub fn get_stack_pointer() -> usize {
+    let stack_pointer;
+    unsafe { asm!("mv $0, sp" : "=r"(stack_pointer) : : : "volatile") };
+    stack_pointer
+}
diff --git a/src/entry_point/mod.rs b/core/src/entry_point/mod.rs
similarity index 97%
rename from src/entry_point/mod.rs
rename to core/src/entry_point/mod.rs
index 09044bd..d63b174 100644
--- a/src/entry_point/mod.rs
+++ b/core/src/entry_point/mod.rs
@@ -57,10 +57,6 @@
 
 #[cfg_attr(target_arch = "riscv32", path = "start_item_riscv32.rs")]
 #[cfg_attr(target_arch = "arm", path = "start_item_arm.rs")]
-#[cfg_attr(
-    not(any(target_arch = "arm", target_arch = "riscv32")),
-    path = "start_item_mock.rs"
-)]
 mod start_item;
 
 /// The header encoded at the beginning of .text by the linker script. It is
diff --git a/src/entry_point/start_item_mock.rs b/core/src/entry_point/start_item.rs
similarity index 100%
rename from src/entry_point/start_item_mock.rs
rename to core/src/entry_point/start_item.rs
diff --git a/src/entry_point/start_item_arm.rs b/core/src/entry_point/start_item_arm.rs
similarity index 100%
rename from src/entry_point/start_item_arm.rs
rename to core/src/entry_point/start_item_arm.rs
diff --git a/src/entry_point/start_item_riscv32.rs b/core/src/entry_point/start_item_riscv32.rs
similarity index 100%
rename from src/entry_point/start_item_riscv32.rs
rename to core/src/entry_point/start_item_riscv32.rs
diff --git a/core/src/lang_items.rs b/core/src/lang_items.rs
new file mode 100644
index 0000000..b5c2cd4
--- /dev/null
+++ b/core/src/lang_items.rs
@@ -0,0 +1,62 @@
+//! Lang item required to make the normal `main` work in applications
+//!
+//! This is how the `start` lang item works:
+//! When `rustc` compiles a binary crate, it creates a `main` function that looks
+//! like this:
+//!
+//! ```
+//! #[export_name = "main"]
+//! pub extern "C" fn rustc_main(argc: isize, argv: *const *const u8) -> isize {
+//!     start(main, argc, argv)
+//! }
+//! ```
+//!
+//! Where `start` is this function and `main` is the binary crate's `main`
+//! function.
+//!
+//! The final piece is that the entry point of our program, _start, has to call
+//! `rustc_main`. That's covered by the `_start` function in the root of this
+//! crate.
+
+use crate::syscalls;
+
+#[lang = "start"]
+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"]
+pub trait Termination {
+    fn check_result(self);
+}
+
+impl Termination for () {
+    fn check_result(self) {}
+}
+
+impl<S, T> Termination for Result<S, T> {
+    fn check_result(self) {
+        if self.is_err() {
+            unsafe { report_panic() };
+        }
+    }
+}
+
+#[cfg(not(feature = "custom_panic_handler"))]
+#[panic_handler]
+unsafe fn panic_handler(_info: &core::panic::PanicInfo) -> ! {
+    report_panic()
+}
+
+unsafe fn report_panic() -> ! {
+    // Signal a panic using the LowLevelDebug capsule (if available).
+    let _ = syscalls::command1_insecure(8, 1, 1);
+
+    loop {
+        syscalls::raw::yieldk();
+    }
+}
diff --git a/core/src/lib.rs b/core/src/lib.rs
new file mode 100644
index 0000000..e465f4d
--- /dev/null
+++ b/core/src/lib.rs
@@ -0,0 +1,17 @@
+#![feature(asm, lang_items, naked_functions)]
+#![cfg_attr(any(target_arch = "arm", target_arch = "riscv32"), no_std)]
+#![cfg_attr(feature = "alloc", feature(alloc_error_handler))]
+
+#[cfg(feature = "alloc")]
+mod alloc;
+mod entry_point;
+#[cfg(any(target_arch = "arm", target_arch = "riscv32"))]
+mod lang_items;
+
+pub mod callback;
+pub mod debug;
+pub mod memop;
+pub mod result;
+pub mod shared_memory;
+pub mod syscalls;
+pub mod unwind_symbols;
diff --git a/src/memop.rs b/core/src/memop.rs
similarity index 100%
rename from src/memop.rs
rename to core/src/memop.rs
diff --git a/core/src/result.rs b/core/src/result.rs
new file mode 100644
index 0000000..9508738
--- /dev/null
+++ b/core/src/result.rs
@@ -0,0 +1,30 @@
+#[derive(Copy, Clone)]
+pub struct SubscribeError {
+    pub driver_number: usize,
+    pub subscribe_number: usize,
+    pub return_code: isize,
+}
+
+#[derive(Copy, Clone)]
+pub struct CommandError {
+    pub driver_number: usize,
+    pub command_number: usize,
+    pub arg1: usize,
+    pub arg2: usize,
+    pub return_code: isize,
+}
+
+#[derive(Copy, Clone)]
+pub struct AllowError {
+    pub driver_number: usize,
+    pub allow_number: usize,
+    pub return_code: isize,
+}
+
+pub const SUCCESS: isize = 0;
+pub const FAIL: isize = -1;
+pub const EBUSY: isize = -2;
+pub const EALREADY: isize = -3;
+pub const EINVAL: isize = -6;
+pub const ESIZE: isize = -7;
+pub const ENOMEM: isize = -9;
diff --git a/src/shared_memory.rs b/core/src/shared_memory.rs
similarity index 100%
rename from src/shared_memory.rs
rename to core/src/shared_memory.rs
diff --git a/src/syscalls/mod.rs b/core/src/syscalls/mod.rs
similarity index 97%
rename from src/syscalls/mod.rs
rename to core/src/syscalls/mod.rs
index c0289e5..833c356 100644
--- a/src/syscalls/mod.rs
+++ b/core/src/syscalls/mod.rs
@@ -1,9 +1,5 @@
 #[cfg_attr(target_arch = "riscv32", path = "platform_riscv32.rs")]
 #[cfg_attr(target_arch = "arm", path = "platform_arm.rs")]
-#[cfg_attr(
-    not(any(target_arch = "arm", target_arch = "riscv32")),
-    path = "platform_mock.rs"
-)]
 mod platform;
 
 use crate::callback::CallbackSubscription;
diff --git a/src/syscalls/platform_mock.rs b/core/src/syscalls/platform.rs
similarity index 100%
rename from src/syscalls/platform_mock.rs
rename to core/src/syscalls/platform.rs
diff --git a/src/syscalls/platform_arm.rs b/core/src/syscalls/platform_arm.rs
similarity index 100%
rename from src/syscalls/platform_arm.rs
rename to core/src/syscalls/platform_arm.rs
diff --git a/src/syscalls/platform_riscv32.rs b/core/src/syscalls/platform_riscv32.rs
similarity index 100%
rename from src/syscalls/platform_riscv32.rs
rename to core/src/syscalls/platform_riscv32.rs
diff --git a/src/unwind_symbols.rs b/core/src/unwind_symbols.rs
similarity index 100%
rename from src/unwind_symbols.rs
rename to core/src/unwind_symbols.rs
diff --git a/examples-alloc/alloc_error.rs b/examples-alloc/alloc_error.rs
deleted file mode 100644
index ec42b5a..0000000
--- a/examples-alloc/alloc_error.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-// Triggers the out-of-memory handler. Should make all LEDs cycle.
-
-#![no_std]
-
-extern crate alloc;
-
-use alloc::vec::Vec;
-use libtock::result::TockResult;
-
-#[libtock::main]
-fn main() -> TockResult<()> {
-    let mut vec = Vec::new();
-    loop {
-        vec.push(0);
-    }
-}
diff --git a/examples-features/alloc_error.rs b/examples-features/alloc_error.rs
new file mode 100644
index 0000000..40ae939
--- /dev/null
+++ b/examples-features/alloc_error.rs
@@ -0,0 +1,31 @@
+// Triggers the out-of-memory handler. Should print an error message.
+
+#![no_std]
+#![feature(alloc_error_handler)]
+
+extern crate alloc;
+
+use alloc::vec::Vec;
+use core::alloc::Layout;
+use core::fmt::Write;
+use libtock::result::TockResult;
+use libtock::syscalls;
+
+#[libtock::main]
+fn main() -> TockResult<()> {
+    let mut vec = Vec::new();
+    loop {
+        vec.push(0);
+    }
+}
+
+#[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");
+    }
+    loop {
+        syscalls::raw::yieldk();
+    }
+}
diff --git a/examples-alloc/ble_scanning.rs b/examples-features/ble_scanning.rs
similarity index 100%
rename from examples-alloc/ble_scanning.rs
rename to examples-features/ble_scanning.rs
diff --git a/examples-alloc/libtock_test.rs b/examples-features/libtock_test.rs
similarity index 100%
rename from examples-alloc/libtock_test.rs
rename to examples-features/libtock_test.rs
diff --git a/examples-features/panic.rs b/examples-features/panic.rs
new file mode 100644
index 0000000..5a9123a
--- /dev/null
+++ b/examples-features/panic.rs
@@ -0,0 +1,24 @@
+// Triggers the panic handler. Should print an error message.
+
+#![no_std]
+
+use core::fmt::Write;
+use core::panic::PanicInfo;
+use libtock::result::TockResult;
+use libtock::syscalls;
+
+#[libtock::main]
+async fn main() -> TockResult<()> {
+    panic!("Bye world!");
+}
+
+#[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");
+    }
+    loop {
+        syscalls::raw::yieldk();
+    }
+}
diff --git a/examples-alloc/simple_ble.rs b/examples-features/simple_ble.rs
similarity index 100%
rename from examples-alloc/simple_ble.rs
rename to examples-features/simple_ble.rs
diff --git a/examples/panic.rs b/examples/panic.rs
deleted file mode 100644
index 5abc01a..0000000
--- a/examples/panic.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// Triggers the panic handler. Should make all LEDs flash.
-
-#![no_std]
-
-use libtock::result::TockResult;
-
-#[libtock::main]
-async fn main() -> TockResult<()> {
-    panic!("Bye world!");
-}
diff --git a/src/alloc.rs b/src/alloc.rs
deleted file mode 100644
index 523cb64..0000000
--- a/src/alloc.rs
+++ /dev/null
@@ -1,62 +0,0 @@
-use crate::drivers;
-use crate::leds::LedsDriver;
-use crate::result::TockResult;
-use crate::timer::Duration;
-use crate::timer::ParallelSleepDriver;
-use core::alloc::GlobalAlloc;
-use core::alloc::Layout;
-use core::executor;
-use core::ptr;
-use core::ptr::NonNull;
-use futures::future;
-use linked_list_allocator::Heap;
-
-pub static mut HEAP: Heap = Heap::empty();
-
-struct TockAllocator;
-
-unsafe impl GlobalAlloc for TockAllocator {
-    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
-        HEAP.allocate_first_fit(layout)
-            .ok()
-            .map_or(ptr::null_mut(), NonNull::as_ptr)
-    }
-
-    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
-        HEAP.deallocate(NonNull::new_unchecked(ptr), layout)
-    }
-}
-
-#[global_allocator]
-static ALLOCATOR: TockAllocator = TockAllocator;
-
-#[alloc_error_handler]
-unsafe fn alloc_error_handler(_: Layout) -> ! {
-    executor::block_on(async {
-        let mut drivers = drivers::retrieve_drivers_unsafe();
-
-        let leds_driver = drivers.leds.init_driver();
-        let mut timer_driver = drivers.timer.create_timer_driver();
-        let timer_driver = timer_driver.activate();
-
-        if let (Ok(leds_driver), Ok(timer_driver)) = (leds_driver, timer_driver) {
-            let _ = cycle_all_leds(&leds_driver, &timer_driver).await;
-        } else {
-            future::pending::<()>().await
-        }
-        loop {}
-    })
-}
-
-async fn cycle_all_leds(
-    leds_driver: &LedsDriver<'_>,
-    timer_driver: &ParallelSleepDriver<'_>,
-) -> TockResult<()> {
-    loop {
-        for led in leds_driver.leds() {
-            led.on()?;
-            timer_driver.sleep(Duration::from_ms(100)).await?;
-            led.off()?;
-        }
-    }
-}
diff --git a/src/debug/mod.rs b/src/debug/mod.rs
index 4596aaa..3bae683 100644
--- a/src/debug/mod.rs
+++ b/src/debug/mod.rs
@@ -3,6 +3,7 @@
 mod low_level_debug;
 
 use crate::drivers;
+use libtock_core::debug as core_debug;
 
 pub use low_level_debug::*;
 
@@ -21,22 +22,15 @@
     let _ = console.write(buffer);
 }
 
-#[cfg(target_arch = "arm")]
 pub fn print_stack_pointer() {
-    let stack_pointer;
-    unsafe { asm!("mov $0, sp" : "=r"(stack_pointer) : : : "volatile") };
-
     let mut buffer = [b'\n'; 15];
     buffer[0..4].clone_from_slice(b"SP: ");
-    write_as_hex(&mut buffer[4..15], stack_pointer);
+    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);
 }
 
-#[cfg(target_arch = "riscv32")]
-pub fn print_stack_pointer() {}
-
 #[inline(always)]
 /// Dumps address
 /// # Safety
diff --git a/src/lang_items.rs b/src/lang_items.rs
deleted file mode 100644
index 91a20a1..0000000
--- a/src/lang_items.rs
+++ /dev/null
@@ -1,96 +0,0 @@
-//! Lang item required to make the normal `main` work in applications
-//!
-//! This is how the `start` lang item works:
-//! When `rustc` compiles a binary crate, it creates a `main` function that looks
-//! like this:
-//!
-//! ```
-//! #[export_name = "main"]
-//! pub extern "C" fn rustc_main(argc: isize, argv: *const *const u8) -> isize {
-//!     start(main, argc, argv)
-//! }
-//! ```
-//!
-//! Where `start` is this function and `main` is the binary crate's `main`
-//! function.
-//!
-//! The final piece is that the entry point of our program, _start, has to call
-//! `rustc_main`. That's covered by the `_start` function in the root of this
-//! crate.
-
-use crate::drivers;
-use crate::leds::LedsDriver;
-use crate::result::TockResult;
-use crate::timer::Duration;
-use crate::timer::ParallelSleepDriver;
-use core::executor;
-use core::panic::PanicInfo;
-use futures::future;
-
-#[lang = "start"]
-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"]
-pub trait Termination {
-    fn check_result(self);
-}
-
-impl Termination for () {
-    fn check_result(self) {}
-}
-
-impl Termination for TockResult<()> {
-    fn check_result(self) {
-        if self.is_err() {
-            unsafe { report_panic() };
-        }
-    }
-}
-
-#[panic_handler]
-unsafe fn panic_handler(_info: &PanicInfo) -> ! {
-    report_panic()
-}
-
-unsafe fn report_panic() -> ! {
-    // Signal a panic using the LowLevelDebug capsule (if available).
-    super::debug::low_level_status_code(1);
-
-    // Flash all LEDs (if available).
-    executor::block_on(async {
-        let mut drivers = drivers::retrieve_drivers_unsafe();
-
-        let leds_driver = drivers.leds.init_driver();
-        let mut timer_driver = drivers.timer.create_timer_driver();
-        let timer_driver = timer_driver.activate();
-
-        if let (Ok(leds_driver), Ok(timer_driver)) = (leds_driver, timer_driver) {
-            let _ = blink_all_leds(&leds_driver, &timer_driver).await;
-        } else {
-            future::pending::<()>().await
-        }
-        loop {}
-    })
-}
-
-async fn blink_all_leds(
-    leds_driver: &LedsDriver<'_>,
-    timer_driver: &ParallelSleepDriver<'_>,
-) -> TockResult<()> {
-    loop {
-        for led in leds_driver.leds() {
-            led.on()?;
-        }
-        timer_driver.sleep(Duration::from_ms(100)).await?;
-        for led in leds_driver.leds() {
-            led.off()?;
-        }
-        timer_driver.sleep(Duration::from_ms(100)).await?;
-    }
-}
diff --git a/src/lib.rs b/src/lib.rs
index 0744a53..0aabb1a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,18 +1,9 @@
-#![feature(asm, lang_items, naked_functions)]
-#![cfg_attr(feature = "alloc", feature(alloc_error_handler))]
 #![cfg_attr(any(target_arch = "arm", target_arch = "riscv32"), no_std)]
 
-#[cfg(feature = "alloc")]
-mod alloc;
-mod entry_point;
-#[cfg(any(target_arch = "arm", target_arch = "riscv32"))]
-mod lang_items;
-
 pub mod adc;
 pub mod ble_composer;
 pub mod ble_parser;
 pub mod buttons;
-pub mod callback;
 pub mod console;
 pub mod debug;
 pub mod drivers;
@@ -20,16 +11,13 @@
 pub mod futures;
 pub mod gpio;
 pub mod leds;
-pub mod memop;
 pub mod result;
 pub mod rng;
 pub mod sensors;
-pub mod shared_memory;
 pub mod simple_ble;
-pub mod syscalls;
 pub mod temperature;
 pub mod timer;
-pub mod unwind_symbols;
 
 pub use drivers::retrieve_drivers;
 pub use libtock_codegen::main;
+pub use libtock_core::*;
diff --git a/src/result.rs b/src/result.rs
index 9dc4f16..74b4786 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -1,5 +1,7 @@
 use core::fmt;
 
+pub use libtock_core::result::*;
+
 pub type TockResult<T> = Result<T, TockError>;
 
 #[derive(Copy, Clone)]
@@ -18,41 +20,18 @@
     }
 }
 
-#[derive(Copy, Clone)]
-pub struct SubscribeError {
-    pub driver_number: usize,
-    pub subscribe_number: usize,
-    pub return_code: isize,
-}
-
 impl From<SubscribeError> for TockError {
     fn from(subscribe_error: SubscribeError) -> Self {
         TockError::Subscribe(subscribe_error)
     }
 }
 
-#[derive(Copy, Clone)]
-pub struct CommandError {
-    pub driver_number: usize,
-    pub command_number: usize,
-    pub arg1: usize,
-    pub arg2: usize,
-    pub return_code: isize,
-}
-
 impl From<CommandError> for TockError {
     fn from(command_error: CommandError) -> Self {
         TockError::Command(command_error)
     }
 }
 
-#[derive(Copy, Clone)]
-pub struct AllowError {
-    pub driver_number: usize,
-    pub allow_number: usize,
-    pub return_code: isize,
-}
-
 impl From<AllowError> for TockError {
     fn from(allow_error: AllowError) -> Self {
         TockError::Allow(allow_error)
@@ -88,11 +67,3 @@
         TockError::Other(OtherError::OutOfRangeError)
     }
 }
-
-pub const SUCCESS: isize = 0;
-pub const FAIL: isize = -1;
-pub const EBUSY: isize = -2;
-pub const EALREADY: isize = -3;
-pub const EINVAL: isize = -6;
-pub const ESIZE: isize = -7;
-pub const ENOMEM: isize = -9;