components/
app_flash_driver.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 any App Flash Driver.
6//!
7//! Usage
8//! -----
9//! ```rust
10//! let app_flash =
11//!     components::app_flash_driver::AppFlashComponent::new(board_kernel, &base_peripherals.nvmc)
12//!         .finalize(components::app_flash_component_static!(
13//!             nrf52833::nvmc::Nvmc,
14//!             512
15//!     ));
16//! ```
17
18use capsules_extra::app_flash_driver::AppFlash;
19use capsules_extra::nonvolatile_to_pages::NonvolatileToPages;
20use core::mem::MaybeUninit;
21use kernel::capabilities;
22use kernel::component::Component;
23use kernel::create_capability;
24use kernel::hil;
25use kernel::hil::nonvolatile_storage::NonvolatileStorage;
26
27#[macro_export]
28macro_rules! app_flash_component_static {
29    ($F:ty, $buffer_size: literal) => {{
30        let buffer = kernel::static_buf!([u8; $buffer_size]);
31        let page_buffer = kernel::static_buf!(<$F as kernel::hil::flash::Flash>::Page);
32        let nv_to_page = kernel::static_buf!(
33            capsules_extra::nonvolatile_to_pages::NonvolatileToPages<'static, $F>
34        );
35        let app_flash = kernel::static_buf!(capsules_extra::app_flash_driver::AppFlash<'static>);
36        (buffer, page_buffer, nv_to_page, app_flash)
37    };};
38}
39
40pub struct AppFlashComponent<
41    F: 'static + hil::flash::Flash + hil::flash::HasClient<'static, NonvolatileToPages<'static, F>>,
42    const BUF_LEN: usize,
43> {
44    board_kernel: &'static kernel::Kernel,
45    driver_num: usize,
46    storage: &'static F,
47}
48
49impl<
50        F: 'static
51            + hil::flash::Flash
52            + hil::flash::HasClient<'static, NonvolatileToPages<'static, F>>,
53        const BUF_LEN: usize,
54    > AppFlashComponent<F, BUF_LEN>
55{
56    pub fn new(
57        board_kernel: &'static kernel::Kernel,
58        driver_num: usize,
59        storage: &'static F,
60    ) -> AppFlashComponent<F, BUF_LEN> {
61        AppFlashComponent {
62            board_kernel,
63            driver_num,
64            storage,
65        }
66    }
67}
68
69impl<
70        F: 'static
71            + hil::flash::Flash
72            + hil::flash::HasClient<'static, NonvolatileToPages<'static, F>>,
73        const BUF_LEN: usize,
74    > Component for AppFlashComponent<F, BUF_LEN>
75{
76    type StaticInput = (
77        &'static mut MaybeUninit<[u8; BUF_LEN]>,
78        &'static mut MaybeUninit<<F as hil::flash::Flash>::Page>,
79        &'static mut MaybeUninit<NonvolatileToPages<'static, F>>,
80        &'static mut MaybeUninit<AppFlash<'static>>,
81    );
82    type Output = &'static AppFlash<'static>;
83
84    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
85        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
86
87        let buffer = static_buffer.0.write([0; BUF_LEN]);
88
89        let flash_pagebuffer = static_buffer
90            .1
91            .write(<F as hil::flash::Flash>::Page::default());
92
93        let nv_to_page = static_buffer
94            .2
95            .write(NonvolatileToPages::new(self.storage, flash_pagebuffer));
96        self.storage.set_client(nv_to_page);
97
98        let app_flash = static_buffer
99            .3
100            .write(capsules_extra::app_flash_driver::AppFlash::new(
101                nv_to_page,
102                self.board_kernel.create_grant(self.driver_num, &grant_cap),
103                buffer,
104            ));
105
106        nv_to_page.set_client(app_flash);
107
108        app_flash
109    }
110}