Skip to main content

embedded_c_sdk_bind_hal/
flash.rs

1use crate::ll_api::{FlashOperate, ll_cmd::*};
2use core::marker::PhantomData;
3use embedded_storage::{
4    self,
5    nor_flash::{NorFlashError, NorFlashErrorKind},
6};
7
8pub const READ_SIZE: usize = 1;
9
10/// Blocking flash mode typestate.
11pub enum Blocking {}
12
13/// Async flash mode typestate.
14// pub enum Async {}
15
16/// Flash error
17///
18#[allow(missing_docs)]
19#[derive(Debug, Copy, Clone, PartialEq, Eq)]
20#[cfg_attr(feature = "defmt", derive(defmt::Format))]
21pub enum Error {
22    Prog,
23    Size,
24    Miss,
25    Seq,
26    Protected,
27    Unaligned,
28    Parallelism,
29    Other,
30}
31
32impl From<i32> for Error {
33    fn from(value: i32) -> Self {
34        match value {
35            -1 => Self::Prog,
36            -2 => Self::Size,
37            -3 => Self::Miss,
38            -4 => Self::Seq,
39            -5 => Self::Protected,
40            -6 => Self::Unaligned,
41            -7 => Self::Parallelism,
42            _ => Self::Other,
43        }
44    }
45}
46
47impl NorFlashError for Error {
48    fn kind(&self) -> NorFlashErrorKind {
49        match self {
50            Self::Size => NorFlashErrorKind::OutOfBounds,
51            Self::Unaligned => NorFlashErrorKind::NotAligned,
52            _ => NorFlashErrorKind::Other,
53        }
54    }
55}
56
57/// Internal flash memory driver.
58pub struct Flash<
59    const PAGE_SIZE: usize,
60    const PAGE_NUM: usize,
61    const MINI_WRITE_SIZE: usize = 4,
62    const MINI_READ_SIZE: usize = 1,
63    MODE = Blocking,
64> {
65    pub(crate) _mode: PhantomData<MODE>,
66}
67
68impl<
69    const PAGE_SIZE: usize,
70    const PAGE_NUM: usize,
71    const MINI_WRITE_SIZE: usize,
72    const MINI_READ_SIZE: usize,
73> Flash<PAGE_SIZE, PAGE_NUM, MINI_WRITE_SIZE, MINI_READ_SIZE, Blocking>
74{
75    /// Create a new flash driver, usable in blocking mode.
76    pub fn new_blocking() -> Self {
77        Self { _mode: PhantomData }
78    }
79}
80
81impl<
82    const PAGE_SIZE: usize,
83    const PAGE_NUM: usize,
84    const MINI_WRITE_SIZE: usize,
85    const MINI_READ_SIZE: usize,
86    MODE,
87> Flash<PAGE_SIZE, PAGE_NUM, MINI_WRITE_SIZE, MINI_READ_SIZE, MODE>
88{
89    /// Blocking read.
90    ///
91    /// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
92    /// For example, to read address `0x0800_1234` you have to use offset `0x1234`.
93    pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
94        let result = ll_invoke_inner!(
95            INVOKE_ID_FLASH_OPERATE,
96            FlashOperate::Read,
97            offset,
98            bytes.as_mut_ptr(),
99            bytes.len()
100        );
101        if result < 0 {
102            return Err(result.into());
103        }
104
105        Ok(())
106    }
107
108    /// Blocking write.
109    ///
110    /// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
111    /// For example, to write address `0x0800_1234` you have to use offset `0x1234`.
112    pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
113        let result = ll_invoke_inner!(
114            INVOKE_ID_FLASH_OPERATE,
115            FlashOperate::Write,
116            offset,
117            bytes.as_ptr(),
118            bytes.len()
119        );
120        if result < 0 {
121            return Err(result.into());
122        }
123
124        Ok(())
125    }
126
127    /// Blocking erase.
128    ///
129    /// NOTE: `from` and `to` are offsets from the flash start, NOT an absolute address.
130    /// For example, to erase address `0x0801_0000` you have to use offset `0x1_0000`.
131    pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
132        let result = ll_invoke_inner!(INVOKE_ID_FLASH_OPERATE, FlashOperate::Erase, from, to);
133        if result < 0 {
134            return Err(result.into());
135        }
136        Ok(())
137    }
138}
139
140impl<
141    const PAGE_SIZE: usize,
142    const PAGE_NUM: usize,
143    const MINI_WRITE_SIZE: usize,
144    const MINI_READ_SIZE: usize,
145    MODE,
146> embedded_storage::nor_flash::ErrorType
147    for Flash<PAGE_SIZE, PAGE_NUM, MINI_WRITE_SIZE, MINI_READ_SIZE, MODE>
148{
149    type Error = Error;
150}
151
152impl<
153    const PAGE_SIZE: usize,
154    const PAGE_NUM: usize,
155    const MINI_WRITE_SIZE: usize,
156    const MINI_READ_SIZE: usize,
157    MODE,
158> embedded_storage::nor_flash::ReadNorFlash
159    for Flash<PAGE_SIZE, PAGE_NUM, MINI_WRITE_SIZE, MINI_READ_SIZE, MODE>
160{
161    const READ_SIZE: usize = MINI_READ_SIZE;
162
163    fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
164        self.blocking_read(offset, bytes)
165    }
166
167    fn capacity(&self) -> usize {
168        PAGE_SIZE * PAGE_NUM
169    }
170}
171
172impl<
173    const PAGE_SIZE: usize,
174    const PAGE_NUM: usize,
175    const MINI_WRITE_SIZE: usize,
176    const MINI_READ_SIZE: usize,
177    MODE,
178> embedded_storage::nor_flash::NorFlash
179    for Flash<PAGE_SIZE, PAGE_NUM, MINI_WRITE_SIZE, MINI_READ_SIZE, MODE>
180{
181    const WRITE_SIZE: usize = MINI_WRITE_SIZE;
182    const ERASE_SIZE: usize = PAGE_SIZE;
183
184    fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
185        self.blocking_write(offset, bytes)
186    }
187
188    fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
189        self.blocking_erase(from, to)
190    }
191}