kernel/hil/flash.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.
//! Interface for reading, writing, and erasing flash storage pages.
//!
//! Operates on single pages. The page size is set by the associated type
//! `page`. Here is an example of a page type and implementation of this trait:
//!
//! ```rust
//! use core::ops::{Index, IndexMut};
//!
//! use kernel::hil;
//! use kernel::ErrorCode;
//!
//! // Size in bytes
//! const PAGE_SIZE: u32 = 1024;
//!
//! struct NewChipPage(pub [u8; PAGE_SIZE as usize]);
//!
//! impl Default for NewChipPage {
//! fn default() -> Self {
//! Self {
//! 0: [0; PAGE_SIZE as usize],
//! }
//! }
//! }
//!
//! impl NewChipPage {
//! fn len(&self) -> usize {
//! self.0.len()
//! }
//! }
//!
//! impl Index<usize> for NewChipPage {
//! type Output = u8;
//!
//! fn index(&self, idx: usize) -> &u8 {
//! &self.0[idx]
//! }
//! }
//!
//! impl IndexMut<usize> for NewChipPage {
//! fn index_mut(&mut self, idx: usize) -> &mut u8 {
//! &mut self.0[idx]
//! }
//! }
//!
//! impl AsMut<[u8]> for NewChipPage {
//! fn as_mut(&mut self) -> &mut [u8] {
//! &mut self.0
//! }
//! }
//!
//! struct NewChipStruct {};
//!
//! impl<'a, C> hil::flash::HasClient<'a, C> for NewChipStruct {
//! fn set_client(&'a self, client: &'a C) { }
//! }
//!
//! impl hil::flash::Flash for NewChipStruct {
//! type Page = NewChipPage;
//!
//! fn read_page(&self, page_number: usize, buf: &'static mut Self::Page) -> Result<(), (ErrorCode, &'static mut Self::Page)> { Err((ErrorCode::FAIL, buf)) }
//! fn write_page(&self, page_number: usize, buf: &'static mut Self::Page) -> Result<(), (ErrorCode, &'static mut Self::Page)> { Err((ErrorCode::FAIL, buf)) }
//! fn erase_page(&self, page_number: usize) -> Result<(), ErrorCode> { Err(ErrorCode::FAIL) }
//! }
//! ```
//!
//! A user of this flash interface might look like:
//!
//! ```rust
//! use kernel::utilities::cells::TakeCell;
//! use kernel::hil;
//!
//! pub struct FlashUser<'a, F: hil::flash::Flash + 'static> {
//! driver: &'a F,
//! buffer: TakeCell<'static, F::Page>,
//! }
//!
//! impl<'a, F: hil::flash::Flash> FlashUser<'a, F> {
//! pub fn new(driver: &'a F, buffer: &'static mut F::Page) -> FlashUser<'a, F> {
//! FlashUser {
//! driver: driver,
//! buffer: TakeCell::new(buffer),
//! }
//! }
//! }
//!
//! impl<'a, F: hil::flash::Flash> hil::flash::Client<F> for FlashUser<'a, F> {
//! fn read_complete(&self, buffer: &'static mut F::Page, result: Result<(), hil::flash::Error>) {}
//! fn write_complete(&self, buffer: &'static mut F::Page, result: Result<(), hil::flash::Error>) { }
//! fn erase_complete(&self, result: Result<(), hil::flash::Error>) {}
//! }
//! ```
use crate::ErrorCode;
/// Flash errors returned in the callbacks.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Error {
/// An error occurred during the flash operation.
FlashError,
/// A flash memory protection violation was detected.
FlashMemoryProtectionError,
}
pub trait HasClient<'a, C> {
/// Set the client for this flash peripheral. The client will be called
/// when operations complete.
fn set_client(&'a self, client: &'a C);
}
/// A page of writable persistent flash memory.
pub trait Flash {
/// Type of a single flash page for the given implementation.
type Page: AsMut<[u8]> + Default;
/// Read a page of flash into the buffer.
fn read_page(
&self,
page_number: usize,
buf: &'static mut Self::Page,
) -> Result<(), (ErrorCode, &'static mut Self::Page)>;
/// Write a page of flash from the buffer.
fn write_page(
&self,
page_number: usize,
buf: &'static mut Self::Page,
) -> Result<(), (ErrorCode, &'static mut Self::Page)>;
/// Erase a page of flash by setting every byte to 0xFF.
fn erase_page(&self, page_number: usize) -> Result<(), ErrorCode>;
}
/// Implement `Client` to receive callbacks from `Flash`.
pub trait Client<F: Flash> {
/// Flash read complete.
fn read_complete(&self, read_buffer: &'static mut F::Page, result: Result<(), Error>);
/// Flash write complete.
fn write_complete(&self, write_buffer: &'static mut F::Page, result: Result<(), Error>);
/// Flash erase complete.
fn erase_complete(&self, result: Result<(), Error>);
}