1use embedded_storage::nor_flash::{
2 ErrorType,
3 MultiwriteNorFlash,
4 NorFlash,
5 NorFlashError,
6 NorFlashErrorKind,
7 ReadNorFlash,
8};
9
10#[cfg(feature = "bytewise-read")]
11use crate::buffer::FlashWordBuffer;
12use crate::{
13 FlashStorage,
14 FlashStorageError,
15 buffer::{FlashSectorBuffer, uninit_slice, uninit_slice_mut},
16};
17
18impl FlashStorage {
19 #[inline(always)]
20 fn is_word_aligned(bytes: &[u8]) -> bool {
21 (bytes.as_ptr() as usize) % (Self::WORD_SIZE as usize) == 0
23 }
24}
25
26impl NorFlashError for FlashStorageError {
27 fn kind(&self) -> NorFlashErrorKind {
28 match self {
29 Self::NotAligned => NorFlashErrorKind::NotAligned,
30 Self::OutOfBounds => NorFlashErrorKind::OutOfBounds,
31 _ => NorFlashErrorKind::Other,
32 }
33 }
34}
35
36impl ErrorType for FlashStorage {
37 type Error = FlashStorageError;
38}
39
40impl ReadNorFlash for FlashStorage {
41 #[cfg(not(feature = "bytewise-read"))]
42 const READ_SIZE: usize = Self::WORD_SIZE as _;
43
44 #[cfg(feature = "bytewise-read")]
45 const READ_SIZE: usize = 1;
46
47 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
48 self.check_alignment::<{ Self::READ_SIZE as _ }>(offset, bytes.len())?;
49 self.check_bounds(offset, bytes.len())?;
50
51 #[cfg(feature = "bytewise-read")]
52 let (offset, bytes) = {
53 let byte_offset = (offset % Self::WORD_SIZE) as usize;
54 if byte_offset > 0 {
55 let mut word_buffer = FlashWordBuffer::uninit();
56
57 let offset = offset - byte_offset as u32;
58 let length = bytes.len().min(Self::WORD_SIZE as usize - byte_offset);
59
60 self.internal_read(offset, word_buffer.as_bytes_mut())?;
61 let word_buffer = unsafe { word_buffer.assume_init_bytes_mut() };
62 bytes[..length].copy_from_slice(&word_buffer[byte_offset..][..length]);
63
64 (offset + Self::WORD_SIZE, &mut bytes[length..])
65 } else {
66 (offset, bytes)
67 }
68 };
69
70 if Self::is_word_aligned(bytes) {
71 for (offset, chunk) in (offset..)
73 .step_by(Self::SECTOR_SIZE as _)
74 .zip(bytes.chunks_mut(Self::SECTOR_SIZE as _))
75 {
76 #[cfg(not(feature = "bytewise-read"))]
78 self.internal_read(offset, uninit_slice_mut(chunk))?;
79
80 #[cfg(feature = "bytewise-read")]
81 {
82 let length = chunk.len();
83 let byte_length = length % Self::WORD_SIZE as usize;
84 let length = length - byte_length;
85
86 self.internal_read(offset, &mut uninit_slice_mut(chunk)[..length])?;
87
88 if byte_length > 0 {
90 let mut word_buffer = FlashWordBuffer::uninit();
91
92 self.internal_read(offset + length as u32, word_buffer.as_bytes_mut())?;
93 let word_buffer = unsafe { word_buffer.assume_init_bytes_mut() };
94 chunk[length..].copy_from_slice(&word_buffer[..byte_length]);
95 }
96 }
97 }
98 } else {
99 let mut buffer = FlashSectorBuffer::uninit();
101
102 for (offset, chunk) in (offset..)
103 .step_by(Self::SECTOR_SIZE as _)
104 .zip(bytes.chunks_mut(Self::SECTOR_SIZE as _))
105 {
106 #[cfg(not(feature = "bytewise-read"))]
108 self.internal_read(offset, &mut buffer.as_bytes_mut()[..chunk.len()])?;
109
110 #[cfg(feature = "bytewise-read")]
112 {
113 let length = chunk.len();
114 let byte_length = length % Self::WORD_SIZE as usize;
115 let length = if byte_length > 0 {
116 length - byte_length + Self::WORD_SIZE as usize
117 } else {
118 length
119 };
120
121 self.internal_read(offset, &mut buffer.as_bytes_mut()[..length])?;
122 }
123 let buffer = unsafe { buffer.assume_init_bytes() };
124
125 chunk.copy_from_slice(&buffer[..chunk.len()]);
127 }
128 }
129
130 Ok(())
131 }
132
133 fn capacity(&self) -> usize {
134 self.capacity
135 }
136}
137
138impl NorFlash for FlashStorage {
139 const WRITE_SIZE: usize = Self::WORD_SIZE as _;
140 const ERASE_SIZE: usize = Self::SECTOR_SIZE as _;
141
142 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
143 self.check_alignment::<{ Self::WORD_SIZE }>(offset, bytes.len())?;
144 self.check_bounds(offset, bytes.len())?;
145
146 if Self::is_word_aligned(bytes) {
147 for (offset, chunk) in (offset..)
149 .step_by(Self::SECTOR_SIZE as _)
150 .zip(bytes.chunks(Self::SECTOR_SIZE as _))
151 {
152 self.internal_write(offset, chunk)?;
154 }
155 } else {
156 let mut buffer = FlashSectorBuffer::uninit();
158
159 for (offset, chunk) in (offset..)
160 .step_by(Self::SECTOR_SIZE as _)
161 .zip(bytes.chunks(Self::SECTOR_SIZE as _))
162 {
163 buffer.as_bytes_mut()[..chunk.len()].copy_from_slice(uninit_slice(chunk));
165 self.internal_write(offset, unsafe {
167 &buffer.assume_init_bytes()[..chunk.len()]
168 })?;
169 }
170 }
171
172 Ok(())
173 }
174
175 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
176 let len = (to - from) as _;
177 self.check_alignment::<{ Self::SECTOR_SIZE }>(from, len)?;
178 self.check_bounds(from, len)?;
179
180 for sector in from / Self::SECTOR_SIZE..to / Self::SECTOR_SIZE {
181 self.internal_erase(sector)?;
182 }
183
184 Ok(())
185 }
186}
187
188impl MultiwriteNorFlash for FlashStorage {}
189
190#[cfg(test)]
192mod test {
193 use super::*;
194
195 const WORD_SIZE: u32 = 4;
196 const SECTOR_SIZE: u32 = 4 << 10;
197 const NUM_SECTORS: u32 = 3;
198 const FLASH_SIZE: u32 = SECTOR_SIZE * NUM_SECTORS;
199 const MAX_OFFSET: u32 = SECTOR_SIZE * 1;
200 const MAX_LENGTH: u32 = SECTOR_SIZE * 2;
201
202 #[repr(C, align(4))]
203 struct TestBuffer {
204 data: [u8; FLASH_SIZE as _],
205 }
206
207 impl TestBuffer {
208 const fn seq() -> Self {
209 let mut data = [0u8; FLASH_SIZE as _];
210 let mut index = 0;
211 while index < FLASH_SIZE {
212 data[index as usize] = (index & 0xff) as u8;
213 index += 1;
214 }
215 Self { data }
216 }
217 }
218
219 impl Default for TestBuffer {
220 fn default() -> Self {
221 Self {
222 data: [0u8; FLASH_SIZE as usize],
223 }
224 }
225 }
226
227 #[cfg(not(miri))]
228 fn range_gen<const ALIGN: u32, const MAX_OFF: u32, const MAX_LEN: u32>(
229 aligned: Option<bool>,
230 ) -> impl Iterator<Item = (u32, u32)> {
231 (0..=MAX_OFF).flat_map(move |off| {
232 (0..=MAX_LEN - off)
233 .filter(move |len| {
234 aligned
235 .map(|aligned| aligned == (off % ALIGN == 0 && len % ALIGN == 0))
236 .unwrap_or(true)
237 })
238 .map(move |len| (off, len))
239 })
240 }
241
242 #[cfg(miri)]
243 fn range_gen<const ALIGN: u32, const MAX_OFF: u32, const MAX_LEN: u32>(
244 aligned: Option<bool>,
245 ) -> impl Iterator<Item = (u32, u32)> {
246 match aligned {
248 Some(true) => vec![(0, 4), (0, 8), (0, 16), (0, 32), (0, 1024)],
249 Some(false) => vec![(3, 7), (11, 11)],
250 None => vec![
251 (0, 4),
252 (0, 8),
253 (0, 16),
254 (0, 32),
255 (0, 1024),
256 (3, 7),
257 (11, 11),
258 (0, 4098),
259 ],
260 }
261 .into_iter()
262 }
263
264 #[test]
265 #[cfg(not(feature = "bytewise-read"))]
266 fn aligned_read() {
267 let mut flash = FlashStorage::new();
268 flash.capacity = 4 * 4096;
269 let src = TestBuffer::seq();
270 let mut data = TestBuffer::default();
271
272 flash.erase(0, FLASH_SIZE).unwrap();
273 flash.write(0, &src.data).unwrap();
274
275 for (off, len) in range_gen::<WORD_SIZE, MAX_OFFSET, MAX_LENGTH>(Some(true)) {
276 flash.read(off, &mut data.data[..len as usize]).unwrap();
277 assert_eq!(
278 data.data[..len as usize],
279 src.data[off as usize..][..len as usize]
280 );
281 }
282 }
283
284 #[test]
285 #[cfg(not(feature = "bytewise-read"))]
286 fn not_aligned_read_aligned_buffer() {
287 let mut flash = FlashStorage::new();
288 flash.capacity = 4 * 4096;
289 let mut data = TestBuffer::default();
290
291 for (off, len) in range_gen::<WORD_SIZE, MAX_OFFSET, MAX_LENGTH>(Some(false)) {
292 flash.read(off, &mut data.data[..len as usize]).unwrap_err();
293 }
294 }
295
296 #[test]
297 #[cfg(not(feature = "bytewise-read"))]
298 fn aligned_read_not_aligned_buffer() {
299 let mut flash = FlashStorage::new();
300 flash.capacity = 4 * 4096;
301 let src = TestBuffer::seq();
302 let mut data = TestBuffer::default();
303
304 flash.erase(0, FLASH_SIZE).unwrap();
305 flash.write(0, &src.data).unwrap();
306
307 for (off, len) in range_gen::<WORD_SIZE, MAX_OFFSET, MAX_LENGTH>(Some(true)) {
308 flash
309 .read(off, &mut data.data[1..][..len as usize])
310 .unwrap();
311 assert_eq!(
312 data.data[1..][..len as usize],
313 src.data[off as usize..][..len as usize]
314 );
315 }
316 }
317
318 #[test]
319 #[cfg(feature = "bytewise-read")]
320 fn bytewise_read_aligned_buffer() {
321 let mut flash = FlashStorage::new();
322 flash.capacity = 4 * 4096;
323 let src = TestBuffer::seq();
324 let mut data = TestBuffer::default();
325
326 flash.erase(0, FLASH_SIZE).unwrap();
327 flash.write(0, &src.data).unwrap();
328
329 for (off, len) in range_gen::<WORD_SIZE, MAX_OFFSET, MAX_LENGTH>(None) {
330 flash.read(off, &mut data.data[..len as usize]).unwrap();
331 assert_eq!(
332 data.data[..len as usize],
333 src.data[off as usize..][..len as usize]
334 );
335 }
336 }
337
338 #[test]
339 #[cfg(feature = "bytewise-read")]
340 fn bytewise_read_not_aligned_buffer() {
341 let mut flash = FlashStorage::new();
342 flash.capacity = 4 * 4096;
343 let src = TestBuffer::seq();
344 let mut data = TestBuffer::default();
345
346 flash.erase(0, FLASH_SIZE).unwrap();
347 flash.write(0, &src.data).unwrap();
348
349 for (off, len) in range_gen::<WORD_SIZE, MAX_OFFSET, MAX_LENGTH>(None) {
350 flash
351 .read(off, &mut data.data[1..][..len as usize])
352 .unwrap();
353 assert_eq!(
354 data.data[1..][..len as usize],
355 src.data[off as usize..][..len as usize]
356 );
357 }
358 }
359
360 #[test]
361 fn write_not_aligned_buffer() {
362 let mut flash = FlashStorage::new();
363 flash.capacity = 4 * 4096;
364 let mut read_data = TestBuffer::default();
365 let write_data = TestBuffer::seq();
366
367 flash.erase(0, FLASH_SIZE).unwrap();
368 flash.write(0, &write_data.data[1..129]).unwrap();
369
370 flash.read(0, &mut read_data.data[..128]).unwrap();
371
372 assert_eq!(&read_data.data[..128], &write_data.data[1..129]);
373 }
374}