Make flash syscall interface async
This commit is contained in:
committed by
Julien Cretin
parent
3d4b652e12
commit
ad0605c2fa
@@ -89,7 +89,7 @@ index e0e292a7e..b485a0997 100644
|
||||
};
|
||||
|
||||
diff --git a/boards/nordic/nrf52840dk_opensk/src/main.rs b/boards/nordic/nrf52840dk_opensk/src/main.rs
|
||||
index 8e4238018..ebee8704b 100644
|
||||
index 8e4238018..c80732f8d 100644
|
||||
--- a/boards/nordic/nrf52840dk_opensk/src/main.rs
|
||||
+++ b/boards/nordic/nrf52840dk_opensk/src/main.rs
|
||||
@@ -114,6 +114,11 @@ const NUM_PROCS: usize = 8;
|
||||
@@ -155,7 +155,7 @@ index 8e4238018..ebee8704b 100644
|
||||
|
||||
let gpio = components::gpio::GpioComponent::new(
|
||||
board_kernel,
|
||||
@@ -334,6 +363,14 @@ pub unsafe fn reset_handler() {
|
||||
@@ -334,6 +363,20 @@ pub unsafe fn reset_handler() {
|
||||
nrf52840::acomp::Comparator
|
||||
));
|
||||
|
||||
@@ -164,13 +164,19 @@ index 8e4238018..ebee8704b 100644
|
||||
+ nrf52840::nvmc::SyscallDriver::new(
|
||||
+ &nrf52840::nvmc::NVMC,
|
||||
+ board_kernel.create_grant(&memory_allocation_capability),
|
||||
+ dynamic_deferred_caller,
|
||||
+ )
|
||||
+ );
|
||||
+ nvmc.set_deferred_handle(
|
||||
+ dynamic_deferred_caller
|
||||
+ .register(nvmc)
|
||||
+ .expect("no deferred call slot available for nvmc"),
|
||||
+ );
|
||||
+
|
||||
nrf52_components::NrfClockComponent::new().finalize(());
|
||||
|
||||
let platform = Platform {
|
||||
@@ -345,6 +382,7 @@ pub unsafe fn reset_handler() {
|
||||
@@ -345,6 +388,7 @@ pub unsafe fn reset_handler() {
|
||||
rng,
|
||||
alarm,
|
||||
analog_comparator,
|
||||
@@ -179,10 +185,10 @@ index 8e4238018..ebee8704b 100644
|
||||
};
|
||||
|
||||
diff --git a/chips/nrf52/src/nvmc.rs b/chips/nrf52/src/nvmc.rs
|
||||
index b70162cae..9dcb82b07 100644
|
||||
index b70162cae..9934f3a31 100644
|
||||
--- a/chips/nrf52/src/nvmc.rs
|
||||
+++ b/chips/nrf52/src/nvmc.rs
|
||||
@@ -3,6 +3,7 @@
|
||||
@@ -3,15 +3,19 @@
|
||||
//! Used in order read and write to internal flash.
|
||||
|
||||
use core::cell::Cell;
|
||||
@@ -190,7 +196,11 @@ index b70162cae..9dcb82b07 100644
|
||||
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::cells::VolatileCell;
|
||||
use kernel::common::deferred_call::DeferredCall;
|
||||
+use kernel::common::dynamic_deferred_call::{
|
||||
+ DeferredCallHandle, DynamicDeferredCall, DynamicDeferredCallClient,
|
||||
+};
|
||||
use kernel::common::registers::{register_bitfields, ReadOnly, ReadWrite};
|
||||
use kernel::common::StaticRef;
|
||||
use kernel::hil;
|
||||
@@ -199,7 +209,7 @@ index b70162cae..9dcb82b07 100644
|
||||
|
||||
use crate::deferred_call_tasks::DeferredCallTask;
|
||||
|
||||
@@ -141,7 +142,13 @@ register_bitfields! [u32,
|
||||
@@ -141,7 +145,13 @@ register_bitfields! [u32,
|
||||
static DEFERRED_CALL: DeferredCall<DeferredCallTask> =
|
||||
unsafe { DeferredCall::new(DeferredCallTask::Nvmc) };
|
||||
|
||||
@@ -213,7 +223,7 @@ index b70162cae..9dcb82b07 100644
|
||||
|
||||
/// This is a wrapper around a u8 array that is sized to a single page for the
|
||||
/// nrf. Users of this module must pass an object of this type to use the
|
||||
@@ -219,6 +226,11 @@ impl Nvmc {
|
||||
@@ -219,6 +229,11 @@ impl Nvmc {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,7 +235,7 @@ index b70162cae..9dcb82b07 100644
|
||||
/// Configure the NVMC to allow writes to flash.
|
||||
pub fn configure_writeable(&self) {
|
||||
let regs = &*self.registers;
|
||||
@@ -234,7 +246,7 @@ impl Nvmc {
|
||||
@@ -234,7 +249,7 @@ impl Nvmc {
|
||||
let regs = &*self.registers;
|
||||
regs.config.write(Configuration::WEN::Een);
|
||||
while !self.is_ready() {}
|
||||
@@ -234,7 +244,7 @@ index b70162cae..9dcb82b07 100644
|
||||
while !self.is_ready() {}
|
||||
}
|
||||
|
||||
@@ -326,7 +338,7 @@ impl Nvmc {
|
||||
@@ -326,7 +341,7 @@ impl Nvmc {
|
||||
// Put the NVMC in write mode.
|
||||
regs.config.write(Configuration::WEN::Wen);
|
||||
|
||||
@@ -243,7 +253,7 @@ index b70162cae..9dcb82b07 100644
|
||||
let word: u32 = (data[i + 0] as u32) << 0
|
||||
| (data[i + 1] as u32) << 8
|
||||
| (data[i + 2] as u32) << 16
|
||||
@@ -394,3 +406,180 @@ impl hil::flash::Flash for Nvmc {
|
||||
@@ -394,3 +409,236 @@ impl hil::flash::Flash for Nvmc {
|
||||
self.erase_page(page_number)
|
||||
}
|
||||
}
|
||||
@@ -269,6 +279,7 @@ index b70162cae..9dcb82b07 100644
|
||||
+///
|
||||
+/// # Syscalls
|
||||
+///
|
||||
+/// - SUBSCRIBE(0, done): The callback for COMMAND(2) and COMMAND(3).
|
||||
+/// - COMMAND(0): Check the driver.
|
||||
+/// - COMMAND(1, 0): Get the word size (always 4).
|
||||
+/// - COMMAND(1, 1): Get the page size (always 4096).
|
||||
@@ -287,28 +298,45 @@ index b70162cae..9dcb82b07 100644
|
||||
+pub struct SyscallDriver {
|
||||
+ nvmc: &'static Nvmc,
|
||||
+ apps: Grant<App>,
|
||||
+ waiting: OptionalCell<AppId>,
|
||||
+ deferred_caller: &'static DynamicDeferredCall,
|
||||
+ deferred_handle: OptionalCell<DeferredCallHandle>,
|
||||
+}
|
||||
+
|
||||
+pub const DRIVER_NUM: usize = 0x50003;
|
||||
+
|
||||
+#[derive(Default)]
|
||||
+pub struct App {
|
||||
+ /// The callback for COMMAND(2) and COMMAND(3).
|
||||
+ callback: Option<Callback>,
|
||||
+ /// The allow slice for COMMAND(2).
|
||||
+ slice: Option<AppSlice<Shared, u8>>,
|
||||
+}
|
||||
+
|
||||
+impl SyscallDriver {
|
||||
+ pub fn new(nvmc: &'static Nvmc, apps: Grant<App>) -> SyscallDriver {
|
||||
+ SyscallDriver { nvmc, apps }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+fn is_write_needed(old: u32, new: u32) -> bool {
|
||||
+ // No need to write if it would not modify the current value.
|
||||
+ old & new != old
|
||||
+}
|
||||
+
|
||||
+impl SyscallDriver {
|
||||
+ pub fn new(
|
||||
+ nvmc: &'static Nvmc,
|
||||
+ apps: Grant<App>,
|
||||
+ deferred_caller: &'static DynamicDeferredCall,
|
||||
+ ) -> SyscallDriver {
|
||||
+ SyscallDriver {
|
||||
+ nvmc,
|
||||
+ apps,
|
||||
+ waiting: OptionalCell::empty(),
|
||||
+ deferred_caller,
|
||||
+ deferred_handle: OptionalCell::empty(),
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ pub fn set_deferred_handle(&self, handle: DeferredCallHandle) {
|
||||
+ self.deferred_handle.replace(handle);
|
||||
+ }
|
||||
+
|
||||
+ /// Writes a word-aligned slice at a word-aligned address.
|
||||
+ ///
|
||||
+ /// Words are written only if necessary, i.e. if writing the new value would change the current
|
||||
@@ -342,6 +370,8 @@ index b70162cae..9dcb82b07 100644
|
||||
+ }
|
||||
+ while !self.nvmc.is_ready() {}
|
||||
+ self.nvmc.configure_readonly();
|
||||
+ self.deferred_handle
|
||||
+ .map(|handle| self.deferred_caller.set(*handle));
|
||||
+ ReturnCode::SUCCESS
|
||||
+ }
|
||||
+
|
||||
@@ -358,13 +388,41 @@ index b70162cae..9dcb82b07 100644
|
||||
+ }
|
||||
+ self.nvmc.erase_page_helper(ptr / PAGE_SIZE);
|
||||
+ self.nvmc.configure_readonly();
|
||||
+ self.deferred_handle
|
||||
+ .map(|handle| self.deferred_caller.set(*handle));
|
||||
+ ReturnCode::SUCCESS
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+impl DynamicDeferredCallClient for SyscallDriver {
|
||||
+ fn call(&self, _handle: DeferredCallHandle) {
|
||||
+ self.waiting.take().map(|appid| {
|
||||
+ self.apps.enter(appid, |app, _| {
|
||||
+ app.callback.map(|mut cb| {
|
||||
+ cb.schedule(0, 0, 0);
|
||||
+ });
|
||||
+ })
|
||||
+ });
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+impl Driver for SyscallDriver {
|
||||
+ fn subscribe(&self, _: usize, _: Option<Callback>, _: AppId) -> ReturnCode {
|
||||
+ ReturnCode::ENOSUPPORT
|
||||
+ fn subscribe(
|
||||
+ &self,
|
||||
+ subscribe_num: usize,
|
||||
+ callback: Option<Callback>,
|
||||
+ appid: AppId,
|
||||
+ ) -> ReturnCode {
|
||||
+ match subscribe_num {
|
||||
+ 0 => self
|
||||
+ .apps
|
||||
+ .enter(appid, |app, _| {
|
||||
+ app.callback = callback;
|
||||
+ ReturnCode::SUCCESS
|
||||
+ })
|
||||
+ .unwrap_or_else(|err| err.into()),
|
||||
+ _ => ReturnCode::ENOSUPPORT,
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ fn command(&self, cmd: usize, arg0: usize, arg1: usize, appid: AppId) -> ReturnCode {
|
||||
@@ -391,6 +449,10 @@ index b70162cae..9dcb82b07 100644
|
||||
+ if len != slice.len() {
|
||||
+ return ReturnCode::EINVAL;
|
||||
+ }
|
||||
+ if self.waiting.is_some() {
|
||||
+ return ReturnCode::EBUSY;
|
||||
+ }
|
||||
+ self.waiting.set(appid);
|
||||
+ self.write_slice(ptr, slice.as_ref())
|
||||
+ })
|
||||
+ .unwrap_or_else(|err| err.into()),
|
||||
@@ -399,6 +461,10 @@ index b70162cae..9dcb82b07 100644
|
||||
+ if len != PAGE_SIZE {
|
||||
+ return ReturnCode::EINVAL;
|
||||
+ }
|
||||
+ if self.waiting.is_some() {
|
||||
+ return ReturnCode::EBUSY;
|
||||
+ }
|
||||
+ self.waiting.set(appid);
|
||||
+ self.erase_page(ptr)
|
||||
+ }
|
||||
+
|
||||
|
||||
Reference in New Issue
Block a user