 +        }
 +    }
  }
-
+ 
  /// Entry point in the vector table called on hard reset.
 @@ -204,7 +230,10 @@ pub unsafe fn reset_handler() {
          UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD))
      };
-
+ 
 -    let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&PROCESSES));
 +    let board_kernel = static_init!(
 +        kernel::Kernel,
 +        kernel::Kernel::new_with_storage(&PROCESSES, &STORAGE_LOCATIONS)
 +    );
-
+ 
      let gpio = components::gpio::GpioComponent::new(
          board_kernel,
 @@ -411,6 +440,14 @@ pub unsafe fn reset_handler() {
          nrf52840::acomp::Comparator
      ));
-
+ 
 +    let nvmc = static_init!(
 +        nrf52840::nvmc::SyscallDriver,
 +        nrf52840::nvmc::SyscallDriver::new(

+    }
+
+    fn fits_in_storage_location(&self, ptr: usize, len: usize) -> bool {
+        self.kernel.storage_locations().iter().any(|storage_location| {
+            let storage_ptr = storage_location.address;
+            let storage_len = storage_location.size;
+            // We want to check the 2 following inequalities:
+            // (1) `storage_ptr <= ptr`
+            // (2) `ptr + len <= storage_ptr + storage_len`
+            // However, the second one may overflow written as is. We introduce a third
+            // inequality to solve this issue:
+            // (3) `len <= storage_len`
+            // Using this third inequality, we can rewrite the second one as:
+            // (4) `ptr - storage_ptr <= storage_len - len`
+            // This fourth inequality is equivalent to the second one but doesn't overflow when
+            // the first and third inequalities hold.
+            storage_ptr <= ptr && len <= storage_len && ptr - storage_ptr <= storage_len - len
+        })
+    }
+
     fn update_stack_start_pointer(&self, stack_pointer: *const u8) {
         if stack_pointer >= self.mem_start() && stack_pointer < self.mem_end() {
             self.debug.map(|debug| {
@@ -1664,6 +1699,33 @@ impl<C: 'static + Chip> Process<'_, C> {
             return Err(ProcessLoadError::MpuInvalidFlashLength);
         }

+        // Allocate MPU region for the storage locations. The storage locations are currently
+        // readable by all processes due to lack of stable app id.
+        for storage_location in kernel.storage_locations() {

+        nvmc,
         ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability),
     };
 
diff --git a/chips/nrf52/src/nvmc.rs b/chips/nrf52/src/nvmc.rs
index b70162cae..9dcb82b07 100644
--- a/chips/nrf52/src/nvmc.rs
+++ b/chips/nrf52/src/nvmc.rs
@@ -3,6 +3,7 @@
 //! Used in order read and write to internal flash.
 
 use core::cell::Cell;
+use core::convert::TryFrom;
 use core::ops::{Index, IndexMut};
 use kernel::common::cells::OptionalCell;
 use kernel::common::cells::TakeCell;
@@ -11,7 +12,7 @@ use kernel::common::deferred_call::DeferredCall;
 use kernel::common::registers::{register_bitfields, ReadOnly, ReadWrite};
 use kernel::common::StaticRef;
 use kernel::hil;
-use kernel::ReturnCode;
+use kernel::{AppId, AppSlice, Callback, Driver, Grant, ReturnCode, Shared};
 
 use crate::deferred_call_tasks::DeferredCallTask;
 
@@ -141,7 +142,13 @@ register_bitfields! [u32,
 static DEFERRED_CALL: DeferredCall<DeferredCallTask> =
     unsafe { DeferredCall::new(DeferredCallTask::Nvmc) };
 
+type WORD = u32;
+const WORD_SIZE: usize = core::mem::size_of::<WORD>();
 const PAGE_SIZE: usize = 4096;
