Enable clippy and fix lints
diff --git a/.travis.yml b/.travis.yml
index 69d3a37..0bcbb0c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -19,8 +19,10 @@
   - rustup target add thumbv7em-none-eabi
   - rustup target add riscv32imc-unknown-none-elf
   - rustup component add rustfmt-preview
+  - rustup component add clippy
 
 script:
   - cargo fmt --all -- --check
   - cargo test --workspace
+  - cargo clippy --workspace --all-targets
   - ./build_examples.sh
diff --git a/.vscode/settings.json b/.vscode/settings.json
index d14867b..8bbc33e 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,4 +1,5 @@
 {
-    "editor.formatOnSave": true,
-    "rust.all_targets": true,
-}
\ No newline at end of file
+  "editor.formatOnSave": true,
+  "rust.all_targets": true,
+  "rust.clippy_preference": "on"
+}
diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs
index c97ae32..6f51b9f 100644
--- a/codegen/src/lib.rs
+++ b/codegen/src/lib.rs
@@ -9,6 +9,7 @@
 use syn::Error;
 use syn::ItemFn;
 
+#[allow(clippy::needless_doctest_main)]
 /// Procedural attribute macro. This is meant to be applied to a binary's async
 /// `main()`, transforming into a function that returns a type acceptable for
 /// `main()`. In other words, this will not compile with libtock-rs:
@@ -30,7 +31,7 @@
 }
 
 fn generate_main_wrapped(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
-    try_generate_main_wrapped(input).unwrap_or_else(|err| err.to_compile_error().into())
+    try_generate_main_wrapped(input).unwrap_or_else(|err| err.to_compile_error())
 }
 
 fn try_generate_main_wrapped(
@@ -63,11 +64,8 @@
             async fn main() -> ::libtock::result::TockResult<()>{
                 method_call().await;
             }
-        }
-        .into();
-        let actual: ItemFn = syn::parse2::<ItemFn>(generate_main_wrapped(method_def.into()))
-            .unwrap()
-            .into();
+        };
+        let actual: ItemFn = syn::parse2::<ItemFn>(generate_main_wrapped(method_def)).unwrap();
         let expected: ItemFn = syn::parse2::<ItemFn>(quote!(
             fn main() -> ::libtock::result::TockResult<()> {
                 static mut MAIN_INVOKED: bool = false;
@@ -83,8 +81,7 @@
                 unsafe { ::core::executor::block_on(_block) }
             }
         ))
-        .unwrap()
-        .into();
+        .unwrap();
         assert_eq!(actual, expected);
     }
 }
diff --git a/examples/adc.rs b/examples/adc.rs
index 2ed3b88..61894ad 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 mut console = Console::new();
+    let mut console = Console::default();
     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 b1d8fe0..406bf57 100644
--- a/examples/adc_buffer.rs
+++ b/examples/adc_buffer.rs
@@ -10,8 +10,8 @@
 #[libtock::main]
 /// Reads a 128 byte sample into a buffer and prints the first value to the console.
 async fn main() -> TockResult<()> {
-    let mut console = Console::new();
-    let mut adc_buffer = AdcBuffer::new();
+    let mut console = Console::default();
+    let mut adc_buffer = AdcBuffer::default();
     let mut temp_buffer = [0; libtock::adc::BUFFER_SIZE];
 
     let adc_buffer = libtock::adc::Adc::init_buffer(&mut adc_buffer)?;
diff --git a/examples/button_read.rs b/examples/button_read.rs
index 74d1479..d86e70d 100644
--- a/examples/button_read.rs
+++ b/examples/button_read.rs
@@ -10,7 +10,7 @@
 
 #[libtock::main]
 async fn main() -> TockResult<()> {
-    let mut console = Console::new();
+    let mut console = Console::default();
     let mut with_callback = buttons::with_callback(|_, _| {});
     let mut buttons = with_callback.init()?;
     let mut button = buttons.iter_mut().next().unwrap();
diff --git a/examples/button_subscribe.rs b/examples/button_subscribe.rs
index 8ea4fac..3453c9b 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 mut console = Console::new();
+    let mut console = Console::default();
 
     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 cb3dc22..ad871ac 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 mut console = Console::new();
+    let mut console = Console::default();
     let pin = GpioPinUnitialized::new(0);
     let pin = pin.open_for_read(None, InputMode::PullDown)?;
     let context = timer::DriverContext::create()?;
diff --git a/examples/hardware_test.rs b/examples/hardware_test.rs
index 8a4689b..4f8ad5f 100644
--- a/examples/hardware_test.rs
+++ b/examples/hardware_test.rs
@@ -21,20 +21,20 @@
 
 impl MyTrait for usize {
     fn do_something_with_a_console(&self, console: &mut Console) {
-        write!(console, "trait_obj_value_usize = {}\n", &self).unwrap();
+        writeln!(console, "trait_obj_value_usize = {}", &self).unwrap();
     }
 }
 
 impl MyTrait for String {
     fn do_something_with_a_console(&self, console: &mut Console) {
-        write!(console, "trait_obj_value_string = {}\n", &self).unwrap();
+        writeln!(console, "trait_obj_value_string = {}", &self).unwrap();
     }
 }
 
 #[libtock::main]
 async fn main() -> TockResult<()> {
-    let mut console = Console::new();
-    write!(console, "[test-results]\n")?;
+    let mut console = Console::default();
+    writeln!(console, "[test-results]")?;
 
     test_heap(&mut console);
     test_formatting(&mut console);
@@ -49,12 +49,12 @@
 
 fn test_heap(console: &mut Console) {
     let mut string = String::from("heap_test = \"Heap ");
-    string.push_str("works.\"\n");
-    write!(console, "{}", string).unwrap();
+    string.push_str("works.\"");
+    writeln!(console, "{}", string).unwrap();
 }
 
 fn test_formatting(console: &mut Console) {
-    write!(console, "formatting =  {}\n", String::from("works")).unwrap();
+    writeln!(console, "formatting =  {}", String::from("works")).unwrap();
 }
 
 /// needs P0.03 and P0.04 to be connected
@@ -91,7 +91,7 @@
 fn test_static_mut(console: &mut Console) {
     increment_static_mut();
 
-    write!(console, "should_be_one = {}\n", unsafe { STATIC }).unwrap();
+    writeln!(console, "should_be_one = {}", unsafe { STATIC }).unwrap();
 }
 
 /// needs P0.03 and P0.04 to be connected
@@ -106,13 +106,13 @@
     let pin_out = pin_out.open_for_write().ok().unwrap();
     pin_out.set_high().ok().unwrap();
 
-    write!(console, "gpio_works = {}\n", pin_in.read()).unwrap();
+    writeln!(console, "gpio_works = {}", pin_in.read()).unwrap();
 }
 
 async fn test_callbacks_and_wait_forever(console: &mut Console) -> TockResult<()> {
     let mut with_callback = timer::with_callback(|_, _| {
-        write!(console, "callbacks_work = true\n").unwrap();
-        write!(console, "all_tests_run = true").unwrap();
+        writeln!(console, "callbacks_work = true").unwrap();
+        writeln!(console, "all_tests_run = true").unwrap();
     });
 
     let mut timer = with_callback.init()?;
diff --git a/examples/hello.rs b/examples/hello.rs
index 989a572..5e4f987 100644
--- a/examples/hello.rs
+++ b/examples/hello.rs
@@ -8,7 +8,7 @@
 
 #[libtock::main]
 async fn main() -> TockResult<()> {
-    let mut console = Console::new();
+    let mut console = Console::default();
     let context = timer::DriverContext::create()?;
     let mut driver = context.create_timer_driver()?;
     let timer_driver = driver.activate()?;
diff --git a/examples/sensors.rs b/examples/sensors.rs
index 1dd373b..9936d31 100644
--- a/examples/sensors.rs
+++ b/examples/sensors.rs
@@ -3,17 +3,18 @@
 use core::fmt::Write;
 use libtock::console::Console;
 use libtock::result::TockResult;
+use libtock::sensors::Ninedof;
 use libtock::sensors::*;
 use libtock::timer;
 use libtock::timer::Duration;
 
 #[libtock::main]
 async fn main() -> TockResult<()> {
-    let mut console = Console::new();
+    let mut console = Console::default();
     let mut humidity = HumiditySensor;
     let mut temperature = TemperatureSensor;
     let mut light = AmbientLightSensor;
-    let mut ninedof = unsafe { Ninedof::new() };
+    let mut ninedof = Ninedof::default();
     let context = timer::DriverContext::create()?;
     let mut driver = context.create_timer_driver()?;
     let timer_driver = driver.activate()?;
diff --git a/examples/simple_ble.rs b/examples/simple_ble.rs
index a4bee5a..97511a0 100644
--- a/examples/simple_ble.rs
+++ b/examples/simple_ble.rs
@@ -24,7 +24,7 @@
     let payload = corepack::to_bytes(LedCommand { nr: 2, st: true }).unwrap();
 
     let mut buffer = BleAdvertisingDriver::create_advertising_buffer();
-    let mut gap_payload = BlePayload::new();
+    let mut gap_payload = BlePayload::default();
     gap_payload
         .add_flag(ble_composer::flags::LE_GENERAL_DISCOVERABLE)
         .unwrap();
@@ -34,10 +34,7 @@
         .unwrap();
 
     gap_payload
-        .add(
-            ble_composer::gap_types::COMPLETE_LOCAL_NAME,
-            "Tock!".as_bytes(),
-        )
+        .add(ble_composer::gap_types::COMPLETE_LOCAL_NAME, b"Tock!")
         .unwrap();
     gap_payload.add_service_payload([91, 79], &payload).unwrap();
 
diff --git a/examples/temperature.rs b/examples/temperature.rs
index 8bce671..8a3eef0 100644
--- a/examples/temperature.rs
+++ b/examples/temperature.rs
@@ -7,7 +7,7 @@
 
 #[libtock::main]
 async fn main() -> TockResult<()> {
-    let mut console = Console::new();
+    let mut console = Console::default();
     let temperature = temperature::measure_temperature().await?;
     writeln!(console, "Temperature: {}", temperature).map_err(Into::into)
 }
diff --git a/examples/timer_subscribe.rs b/examples/timer_subscribe.rs
index c61c759..11afdfd 100644
--- a/examples/timer_subscribe.rs
+++ b/examples/timer_subscribe.rs
@@ -9,7 +9,7 @@
 
 #[libtock::main]
 async fn main() -> TockResult<()> {
-    let mut console = Console::new();
+    let mut console = Console::default();
 
     let mut with_callback = timer::with_callback(|_, _| {
         writeln!(
diff --git a/src/adc.rs b/src/adc.rs
index e01b6ca..ecb18df 100644
--- a/src/adc.rs
+++ b/src/adc.rs
@@ -29,8 +29,8 @@
     buffer: [u8; BUFFER_SIZE],
 }
 
-impl AdcBuffer {
-    pub fn new() -> AdcBuffer {
+impl Default for AdcBuffer {
+    fn default() -> Self {
         AdcBuffer {
             buffer: [0; BUFFER_SIZE],
         }
diff --git a/src/ble_composer.rs b/src/ble_composer.rs
index 1701ec5..0bb96d8 100644
--- a/src/ble_composer.rs
+++ b/src/ble_composer.rs
@@ -36,13 +36,6 @@
         Ok(())
     }
 
-    pub fn new() -> Self {
-        BlePayload {
-            bytes: [0; 39],
-            occupied: 0,
-        }
-    }
-
     pub fn add_service_payload(&mut self, uuid: [u8; 2], content: &[u8]) -> Result<(), ()> {
         self.check_can_write_num_bytes(4 + content.len())?;
         self.bytes[self.occupied] = (content.len() + 3) as u8;
@@ -65,6 +58,14 @@
     }
 }
 
+impl Default for BlePayload {
+    fn default() -> Self {
+        BlePayload {
+            bytes: [0; 39],
+            occupied: 0,
+        }
+    }
+}
 impl AsRef<[u8]> for BlePayload {
     fn as_ref(&self) -> &[u8] {
         &self.bytes[0..self.occupied]
@@ -77,7 +78,7 @@
 
     #[test]
     fn test_add() {
-        let mut pld = BlePayload::new();
+        let mut pld = BlePayload::default();
         pld.add(1, &[2]).unwrap();
         assert_eq!(pld.as_ref().len(), 3);
         assert_eq!(pld.as_ref(), &mut [2, 1, 2])
@@ -85,14 +86,14 @@
 
     #[test]
     fn test_add_service_payload() {
-        let mut pld = BlePayload::new();
+        let mut pld = BlePayload::default();
         pld.add_service_payload([1, 2], &[2]).unwrap();
         assert_eq!(pld.as_ref(), &[4, 0x16, 1, 2, 2])
     }
 
     #[test]
     fn test_add_service_payload_two_times() {
-        let mut pld = BlePayload::new();
+        let mut pld = BlePayload::default();
         pld.add_service_payload([1, 2], &[2]).unwrap();
         pld.add_service_payload([1, 2], &[2, 3]).unwrap();
 
@@ -101,13 +102,13 @@
 
     #[test]
     fn big_data_causes_error() {
-        let mut pld = BlePayload::new();
+        let mut pld = BlePayload::default();
         assert!(pld.add_service_payload([1, 2], &[0; 36]).is_err());
     }
 
     #[test]
     fn initial_size_is_zero() {
-        let pld = BlePayload::new();
+        let pld = BlePayload::default();
         assert_eq!(pld.as_ref().len(), 0);
     }
 }
diff --git a/src/console.rs b/src/console.rs
index 3fd0361..bfcd6d7 100644
--- a/src/console.rs
+++ b/src/console.rs
@@ -25,12 +25,6 @@
 }
 
 impl Console {
-    pub fn new() -> Console {
-        Console {
-            allow_buffer: [0; 64],
-        }
-    }
-
     pub fn write<S: AsRef<[u8]>>(&mut self, text: S) -> TockResult<()> {
         let mut not_written_yet = text.as_ref();
         while !not_written_yet.is_empty() {
@@ -69,6 +63,14 @@
     }
 }
 
+impl Default for Console {
+    fn default() -> Self {
+        Console {
+            allow_buffer: [0; 64],
+        }
+    }
+}
+
 impl fmt::Write for Console {
     fn write_str(&mut self, string: &str) -> Result<(), fmt::Error> {
         self.write(string).map_err(|_| fmt::Error)
diff --git a/src/debug/mod.rs b/src/debug/mod.rs
index a64b664..f67ae9b 100644
--- a/src/debug/mod.rs
+++ b/src/debug/mod.rs
@@ -7,13 +7,15 @@
 
 pub fn println() {
     let buffer = [b'\n'];
-    let _ = Console::new().write(&buffer);
+    let mut console = Console::default();
+    let _ = console.write(&buffer);
 }
 
 pub fn print_as_hex(value: usize) {
     let mut buffer = [b'\n'; 11];
     write_as_hex(&mut buffer, value);
-    let _ = Console::new().write(buffer);
+    let mut console = Console::default();
+    let _ = console.write(buffer);
 }
 
 #[cfg(target_arch = "arm")]
@@ -24,34 +26,42 @@
     let mut buffer = [b'\n'; 15];
     buffer[0..4].clone_from_slice(b"SP: ");
     write_as_hex(&mut buffer[4..15], stack_pointer);
-    let _ = Console::new().write(buffer);
+    let mut console = Console::default();
+    let _ = console.write(buffer);
 }
 
 #[cfg(target_arch = "riscv32")]
 pub fn print_stack_pointer() {}
 
-#[inline(always)] // Initial stack size is too small (128 bytes currently)
-pub fn dump_address(address: *const usize) {
+#[inline(always)]
+/// Dumps address
+/// # Safety
+/// dereferences pointer without check - may lead to access violation.
+pub unsafe fn dump_address(address: *const usize) {
     let mut buffer = [b' '; 28];
     write_as_hex(&mut buffer[0..10], address as usize);
     buffer[10] = b':';
-    write_as_hex(&mut buffer[12..22], unsafe { *address });
+    write_as_hex(&mut buffer[12..22], *address);
     for index in 0..4 {
-        let byte = unsafe { *(address as *const u8).offset(index) };
+        let byte = *(address as *const u8).offset(index);
         let byte_is_printable_char = byte >= 0x20 && byte < 0x80;
         if byte_is_printable_char {
             buffer[23 + index as usize] = byte;
         }
     }
     buffer[27] = b'\n';
-    let _ = Console::new().write(&buffer);
+    let mut console = Console::default();
+    let _ = console.write(&buffer);
 }
 
-pub fn dump_memory(start_address: *const usize, count: isize) {
+/// Dumps arbitrary memory regions.
+/// # Safety
+/// dereferences pointer without check - may lead to access violation.
+pub unsafe fn dump_memory(start_address: *const usize, count: isize) {
     let range = if count < 0 { count..0 } else { 0..count };
 
     for offset in range {
-        dump_address(unsafe { start_address.offset(offset) });
+        dump_address(start_address.offset(offset));
     }
 }
 
diff --git a/src/memop.rs b/src/memop.rs
index eaccb18..064841c 100644
--- a/src/memop.rs
+++ b/src/memop.rs
@@ -3,16 +3,19 @@
 use crate::syscalls;
 use core::slice;
 
-// Setting the break is marked as unsafe as it should only be called by the entry point to setup
-// the allocator. Updating the break afterwards can lead to allocated memory becoming unaccessible.
-//
-// Alternate allocator implementations may still find this useful in the future.
+/// Set the memory break
+/// # Safety
+/// Setting the break is marked as unsafe as it should only be called by the entry point to setup
+/// the allocator. Updating the break afterwards can lead to allocated memory becoming unaccessible.
+///
+/// Alternate allocator implementations may still find this useful in the future.
 pub unsafe fn set_brk(ptr: *const u8) -> bool {
     syscalls::raw::memop(0, ptr as usize) == 0
 }
 
-pub unsafe fn increment_brk(increment: usize) -> Option<*const u8> {
-    let result = syscalls::raw::memop(1, increment);
+/// Increment the memory break
+pub fn increment_brk(increment: usize) -> Option<*const u8> {
+    let result = unsafe { syscalls::raw::memop(1, increment) };
     if result >= 0 {
         Some(result as *const u8)
     } else {
@@ -64,8 +67,8 @@
     }
 }
 
-// It is safe to return a 'static immutable slice, as the Tock kernel doesn't change the layout of
-// flash regions during the application's lifetime.
+/// It is safe to return a 'static immutable slice, as the Tock kernel doesn't change the layout of
+/// flash regions during the application's lifetime.
 pub fn get_flash_region(i: usize) -> Option<&'static [u8]> {
     if i < get_flash_regions_count() {
         let start = unsafe { syscalls::raw::memop(8, i) as *const u8 };
@@ -78,15 +81,22 @@
     }
 }
 
-// Setting the stack_top and heap_start addresses are marked as unsafe as they should only be called
-// by the entry point to setup the allocator. Updating these values afterwards can lead to incorrect
-// debug output from the kernel.
-//
-// Alternate allocator implementations may still find this useful in the future.
+/// Set the top of the stack
+/// # Safety
+/// Setting the stack_top and heap_start addresses are marked as unsafe as they should only be called
+/// by the entry point to setup the allocator. Updating these values afterwards can lead to incorrect
+/// debug output from the kernel.
+///
+/// Alternate allocator implementations may still find this useful in the future.
 pub unsafe fn set_stack_top(ptr: *const u8) {
     let _ = syscalls::raw::memop(10, ptr as usize);
 }
 
+/// Set the top of the heap
+/// # Safety
+/// Setting the stack_top and heap_start addresses are marked as unsafe as they should only be called
+/// by the entry point to setup the allocator. Updating these values afterwards can lead to incorrect
+/// debug output from the kernel.
 pub unsafe fn set_heap_start(ptr: *const u8) {
     let _ = syscalls::raw::memop(11, ptr as usize);
 }
diff --git a/src/sensors/ninedof.rs b/src/sensors/ninedof.rs
index 7da0dda..7986a40 100644
--- a/src/sensors/ninedof.rs
+++ b/src/sensors/ninedof.rs
@@ -30,10 +30,6 @@
 }
 
 impl Ninedof {
-    pub unsafe fn new() -> Ninedof {
-        Ninedof
-    }
-
     pub fn read_acceleration(&mut self) -> TockResult<NinedofReading> {
         let res: CbData = Default::default();
         subscribe(Self::cb, unsafe { mem::transmute(&res) })?;
@@ -61,6 +57,12 @@
     }
 }
 
+impl Default for Ninedof {
+    fn default() -> Self {
+        Ninedof
+    }
+}
+
 pub fn subscribe(cb: extern "C" fn(usize, usize, usize, usize), ud: usize) -> TockResult<()> {
     syscalls::subscribe_fn(DRIVER_NUM, 0, cb, ud)?;
     Ok(())
diff --git a/src/syscalls/mod.rs b/src/syscalls/mod.rs
index 4cbef0f..7c5377a 100644
--- a/src/syscalls/mod.rs
+++ b/src/syscalls/mod.rs
@@ -89,7 +89,7 @@
     arg1: usize,
     arg2: usize,
 ) -> Result<usize, CommandError> {
-    let return_code = unsafe { raw::command(driver_number, command_number, arg1, arg2) };
+    let return_code = raw::command(driver_number, command_number, arg1, arg2);
     if return_code >= 0 {
         Ok(return_code as usize)
     } else {
diff --git a/src/syscalls/platform_arm.rs b/src/syscalls/platform_arm.rs
index 98730d3..cf0048e 100644
--- a/src/syscalls/platform_arm.rs
+++ b/src/syscalls/platform_arm.rs
@@ -31,6 +31,8 @@
 }
 
 #[inline(always)]
+// Justification: documentation is generated from mocks
+#[allow(clippy::missing_safety_doc)]
 pub unsafe fn subscribe(
     major: usize,
     minor: usize,
@@ -46,16 +48,20 @@
 }
 
 #[inline(always)]
-pub unsafe fn command(major: usize, minor: usize, arg1: usize, arg2: usize) -> isize {
-    let res;
-    asm!("svc 2" : "={r0}"(res)
-                 : "{r0}"(major) "{r1}"(minor) "{r2}"(arg1) "{r3}"(arg2)
-                 : "memory"
-                 : "volatile");
-    res
+pub fn command(major: usize, minor: usize, arg1: usize, arg2: usize) -> isize {
+    unsafe {
+        let res;
+        asm!("svc 2" : "={r0}"(res)
+                     : "{r0}"(major) "{r1}"(minor) "{r2}"(arg1) "{r3}"(arg2)
+                     : "memory"
+                     : "volatile");
+        res
+    }
 }
 
 #[inline(always)]
+// Justification: documentation is generated from mocks
+#[allow(clippy::missing_safety_doc)]
 pub unsafe fn command1(major: usize, minor: usize, arg: usize) -> isize {
     let res;
     asm!("svc 2" : "={r0}"(res)
@@ -66,6 +72,8 @@
 }
 
 #[inline(always)]
+// Justification: documentation is generated from mocks
+#[allow(clippy::missing_safety_doc)]
 pub unsafe fn allow(major: usize, minor: usize, slice: *mut u8, len: usize) -> isize {
     let res;
     asm!("svc 3" : "={r0}"(res)
@@ -76,6 +84,8 @@
 }
 
 #[inline(always)]
+// Justification: documentation is generated from mocks
+#[allow(clippy::missing_safety_doc)]
 pub unsafe fn memop(major: u32, arg1: usize) -> isize {
     let res;
     asm!("svc 4" : "={r0}"(res)
diff --git a/src/syscalls/platform_mock.rs b/src/syscalls/platform_mock.rs
index e794c05..e8e026f 100644
--- a/src/syscalls/platform_mock.rs
+++ b/src/syscalls/platform_mock.rs
@@ -1,5 +1,12 @@
+/// 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.
 pub unsafe fn yieldk() {}
 
+/// Subscribe a callback to the kernel
+/// # Safety
+/// Unsafe as passed callback is dereferenced and called.
 pub unsafe fn subscribe(
     _: usize,
     _: usize,
@@ -9,18 +16,27 @@
     unimplemented()
 }
 
-pub unsafe fn command(_: usize, _: usize, _: usize, _: usize) -> isize {
+pub fn command(_: usize, _: usize, _: usize, _: usize) -> isize {
     unimplemented()
 }
 
+/// Call a command only taking into accoun the first argument
+/// # Safety
+/// Unsafe as ignored arguments cause leaking of registers to the kernel
 pub unsafe fn command1(_: usize, _: usize, _: usize) -> isize {
     unimplemented()
 }
 
+/// Share a memory region with the kernel
+/// # Safety
+/// Unsafe as the pointer to the shared buffer is potentially dereferenced by the kernel.
 pub unsafe fn allow(_: usize, _: usize, _: *mut u8, _: usize) -> isize {
     unimplemented()
 }
 
+/// Generic operations on the app's memory as requesting more memory
+/// # Safety
+/// Allows the kernel to do generic operations on the app's memory which can cause memory corruption.
 pub unsafe fn memop(_: u32, _: usize) -> isize {
     unimplemented()
 }
diff --git a/src/syscalls/platform_riscv32.rs b/src/syscalls/platform_riscv32.rs
index 943b72a..7985545 100644
--- a/src/syscalls/platform_riscv32.rs
+++ b/src/syscalls/platform_riscv32.rs
@@ -1,4 +1,6 @@
 #[inline(always)]
+// Justification: documentation is generated from mocks
+#[allow(clippy::missing_safety_doc)]
 pub unsafe fn yieldk() {
     /* TODO: Stop yielding */
     asm! (
@@ -12,6 +14,8 @@
 }
 
 #[inline(always)]
+// Justification: documentation is generated from mocks
+#[allow(clippy::missing_safety_doc)]
 pub unsafe fn subscribe(
     major: usize,
     minor: usize,
@@ -29,18 +33,22 @@
 }
 
 #[inline(always)]
-pub unsafe fn command(major: usize, minor: usize, arg1: usize, arg2: usize) -> isize {
-    let res;
-    asm!("li    a0, 2
+pub fn command(major: usize, minor: usize, arg1: usize, arg2: usize) -> isize {
+    unsafe {
+        let res;
+        asm!("li    a0, 2
           ecall"
          : "={x10}" (res)
          : "{x11}" (major), "{x12}" (minor), "{x13}" (arg1), "{x14}" (arg2)
          : "memory"
          : "volatile");
-    res
+        res
+    }
 }
 
 #[inline(always)]
+// Justification: documentation is generated from mocks
+#[allow(clippy::missing_safety_doc)]
 pub unsafe fn command1(major: usize, minor: usize, arg: usize) -> isize {
     let res;
     asm!("li    a0, 2
@@ -53,6 +61,8 @@
 }
 
 #[inline(always)]
+// Justification: documentation is generated from mocks
+#[allow(clippy::missing_safety_doc)]
 pub unsafe fn allow(major: usize, minor: usize, slice: *mut u8, len: usize) -> isize {
     let res;
     asm!("li    a0, 3
@@ -65,6 +75,8 @@
 }
 
 #[inline(always)]
+// Justification: documentation is generated from mocks
+#[allow(clippy::missing_safety_doc)]
 pub unsafe fn memop(major: u32, arg1: usize) -> isize {
     let res;
     asm!("li    a0, 4
diff --git a/src/timer.rs b/src/timer.rs
index 9a43027..a0172b0 100644
--- a/src/timer.rs
+++ b/src/timer.rs
@@ -334,7 +334,11 @@
         }
     }
 
-    pub unsafe fn create_timer_driver_unsafe<'a>(&'a self) -> TimerDriver<'a> {
+    /// Create a timer driver instance without checking for running instance
+    /// # Safety
+    /// May lead to undefined behavior at the previous consumer of the timer driver.
+    /// Only safe if no other consumer is still running (e.g. on unwind)
+    pub unsafe fn create_timer_driver_unsafe(&self) -> TimerDriver<'_> {
         TimerDriver {
             callback: Callback {
                 now: &self.current_time,
@@ -431,11 +435,11 @@
         Ok(())
     }
 
-    fn activate_timer(&self, timer: &ActiveTimer) -> TockResult<()> {
+    fn activate_timer(&self, timer: ActiveTimer) -> TockResult<()> {
         set_alarm_at(timer.instant as usize)?;
         let now = get_current_ticks()?;
-        if !is_over(*timer, now as u32) {
-            self.context.active_timer.set(Some(*timer));
+        if !is_over(timer, now as u32) {
+            self.context.active_timer.set(Some(timer));
         } else {
             self.wakeup_soon()?;
         }
@@ -457,10 +461,7 @@
             if !is_over(next_timer, now as u32) {
                 break;
             } else {
-                match stop_alarm_at(next_timer.instant as usize) {
-                    Ok(_) => (),
-                    Err(_) => (),
-                }
+                stop_alarm_at(next_timer.instant as usize)?;
             }
         }
         Ok(())
@@ -507,14 +508,14 @@
         if let Some(active) = self.context.active_timer.get() {
             if left_is_later(active, this_alarm) {
                 suspended_timer.set(Some(active));
-                self.activate_timer(&this_alarm)?;
+                self.activate_timer(this_alarm)?;
             }
         } else {
-            self.activate_timer(&this_alarm)?;
+            self.activate_timer(this_alarm)?;
         }
         if is_over(this_alarm, now as u32) {
             if let Some(paused) = suspended_timer.get() {
-                self.activate_timer(&paused)?;
+                self.activate_timer(paused)?;
             } else {
                 self.context.active_timer.set(None);
             }