esp_storage/
storage.rs

1use core::mem::MaybeUninit;
2
3use embedded_storage::{ReadStorage, Storage};
4
5use crate::{FlashSectorBuffer, FlashStorage, FlashStorageError};
6
7impl ReadStorage for FlashStorage {
8    type Error = FlashStorageError;
9
10    fn read(&mut self, offset: u32, mut bytes: &mut [u8]) -> Result<(), Self::Error> {
11        self.check_bounds(offset, bytes.len())?;
12
13        let mut data_offset = offset % Self::WORD_SIZE;
14        let mut aligned_offset = offset - data_offset;
15
16        // Bypass clearing sector buffer for performance reasons
17        let mut sector_data = MaybeUninit::<FlashSectorBuffer>::uninit();
18        let sector_data = unsafe { sector_data.assume_init_mut() };
19
20        while !bytes.is_empty() {
21            let len = bytes.len().min((Self::SECTOR_SIZE - data_offset) as _);
22
23            let aligned_end = (data_offset as usize + len + (Self::WORD_SIZE - 1) as usize)
24                & !(Self::WORD_SIZE - 1) as usize;
25
26            // Read only needed data words
27            self.internal_read(aligned_offset, &mut sector_data[..aligned_end])?;
28
29            bytes[..len].copy_from_slice(&sector_data[data_offset as usize..][..len]);
30
31            aligned_offset += Self::SECTOR_SIZE;
32            data_offset = 0;
33            bytes = &mut bytes[len..];
34        }
35
36        Ok(())
37    }
38
39    /// The SPI flash size is configured by writing a field in the software
40    /// bootloader image header. This is done during flashing in espflash /
41    /// esptool.
42    fn capacity(&self) -> usize {
43        self.capacity
44    }
45}
46
47impl Storage for FlashStorage {
48    fn write(&mut self, offset: u32, mut bytes: &[u8]) -> Result<(), Self::Error> {
49        self.check_bounds(offset, bytes.len())?;
50
51        let mut data_offset = offset % Self::SECTOR_SIZE;
52        let mut aligned_offset = offset - data_offset;
53
54        // Bypass clearing sector buffer for performance reasons
55        let mut sector_data = MaybeUninit::<FlashSectorBuffer>::uninit();
56        let sector_data = unsafe { sector_data.assume_init_mut() };
57
58        while !bytes.is_empty() {
59            self.internal_read(aligned_offset, &mut sector_data[..])?;
60
61            let len = bytes.len().min((Self::SECTOR_SIZE - data_offset) as _);
62
63            sector_data[data_offset as usize..][..len].copy_from_slice(&bytes[..len]);
64            self.internal_erase(aligned_offset / Self::SECTOR_SIZE)?;
65            self.internal_write(aligned_offset, &sector_data[..])?;
66
67            aligned_offset += Self::SECTOR_SIZE;
68            data_offset = 0;
69            bytes = &bytes[len..];
70        }
71
72        Ok(())
73    }
74}