components/
nonvolatile_storage.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Component for non-volatile storage Drivers.
6//!
7//! This provides one component, NonvolatileStorageComponent, which provides
8//! a system call interface to non-volatile storage.
9//!
10//! Usage
11//! -----
12//! ```rust
13//! let nonvolatile_storage = components::nonvolatile_storage::NonvolatileStorageComponent::new(
14//!     board_kernel,
15//!     &sam4l::flashcalw::FLASH_CONTROLLER,
16//!     0x60000,
17//!     0x20000,
18//!     core::ptr::addr_of!(_sstorage) as usize,
19//!     core::ptr::addr_of!(_estorage) as usize,
20//! )
21//! .finalize(components::nonvolatile_storage_component_static!(
22//!     sam4l::flashcalw::FLASHCALW
23//! ));
24//! ```
25
26use capsules_extra::nonvolatile_storage_driver::NonvolatileStorage;
27use capsules_extra::nonvolatile_to_pages::NonvolatileToPages;
28use core::mem::MaybeUninit;
29use kernel::capabilities;
30use kernel::component::Component;
31use kernel::create_capability;
32use kernel::hil;
33
34// Setup static space for the objects.
35#[macro_export]
36macro_rules! nonvolatile_storage_component_static {
37    ($F:ty $(,)?) => {{
38        let page = kernel::static_buf!(<$F as kernel::hil::flash::Flash>::Page);
39        let ntp = kernel::static_buf!(
40            capsules_extra::nonvolatile_to_pages::NonvolatileToPages<'static, $F>
41        );
42        let ns = kernel::static_buf!(
43            capsules_extra::nonvolatile_storage_driver::NonvolatileStorage<'static>
44        );
45        let buffer = kernel::static_buf!([u8; capsules_extra::nonvolatile_storage_driver::BUF_LEN]);
46
47        (page, ntp, ns, buffer)
48    };};
49}
50
51pub type NonvolatileStorageComponentType = NonvolatileStorage<'static>;
52
53pub struct NonvolatileStorageComponent<
54    F: 'static + hil::flash::Flash + hil::flash::HasClient<'static, NonvolatileToPages<'static, F>>,
55> {
56    board_kernel: &'static kernel::Kernel,
57    driver_num: usize,
58    flash: &'static F,
59    userspace_start: usize,
60    userspace_length: usize,
61    kernel_start: usize,
62    kernel_length: usize,
63}
64
65impl<
66        F: 'static
67            + hil::flash::Flash
68            + hil::flash::HasClient<'static, NonvolatileToPages<'static, F>>,
69    > NonvolatileStorageComponent<F>
70{
71    pub fn new(
72        board_kernel: &'static kernel::Kernel,
73        driver_num: usize,
74        flash: &'static F,
75        userspace_start: usize,
76        userspace_length: usize,
77        kernel_start: usize,
78        kernel_length: usize,
79    ) -> Self {
80        Self {
81            board_kernel,
82            driver_num,
83            flash,
84            userspace_start,
85            userspace_length,
86            kernel_start,
87            kernel_length,
88        }
89    }
90}
91
92impl<
93        F: 'static
94            + hil::flash::Flash
95            + hil::flash::HasClient<'static, NonvolatileToPages<'static, F>>,
96    > Component for NonvolatileStorageComponent<F>
97{
98    type StaticInput = (
99        &'static mut MaybeUninit<<F as hil::flash::Flash>::Page>,
100        &'static mut MaybeUninit<NonvolatileToPages<'static, F>>,
101        &'static mut MaybeUninit<NonvolatileStorage<'static>>,
102        &'static mut MaybeUninit<[u8; capsules_extra::nonvolatile_storage_driver::BUF_LEN]>,
103    );
104    type Output = &'static NonvolatileStorage<'static>;
105
106    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
107        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
108
109        let buffer = static_buffer
110            .3
111            .write([0; capsules_extra::nonvolatile_storage_driver::BUF_LEN]);
112
113        let flash_pagebuffer = static_buffer
114            .0
115            .write(<F as hil::flash::Flash>::Page::default());
116
117        let nv_to_page = static_buffer
118            .1
119            .write(NonvolatileToPages::new(self.flash, flash_pagebuffer));
120        hil::flash::HasClient::set_client(self.flash, nv_to_page);
121
122        let nonvolatile_storage = static_buffer.2.write(NonvolatileStorage::new(
123            nv_to_page,
124            self.board_kernel.create_grant(self.driver_num, &grant_cap),
125            self.userspace_start, // Start address for userspace accessible region
126            self.userspace_length, // Length of userspace accessible region
127            self.kernel_start,    // Start address of kernel region
128            self.kernel_length,   // Length of kernel region
129            buffer,
130        ));
131        hil::nonvolatile_storage::NonvolatileStorage::set_client(nv_to_page, nonvolatile_storage);
132        nonvolatile_storage
133    }
134}