embedded_storage_file/
synhronous.rs

1use embedded_storage;
2use embedded_storage::nor_flash::NorFlash;
3use embedded_storage::nor_flash::ReadNorFlash;
4use embedded_storage::nor_flash::RmwNorFlashStorage;
5
6use std::usize;
7
8// This module provides an implementation of a NOR flash memory storage
9// using a buffer backend. It includes structures and traits to handle
10// reading, writing, and erasing operations on the NOR flash memory.
11
12/// Error type for NOR flash operations.
13pub type Error = embedded_storage::nor_flash::NorFlashErrorKind;
14
15/// Structure representing a NOR flash memory with a buffer backend.
16pub struct NorMemory<
17    B: BufferBackend,
18    const READ_SIZE: usize,
19    const WRITE_SIZE: usize,
20    const ERASE_SIZE: usize,
21> {
22    pub(crate) buffer: B,
23}
24
25impl<B: BufferBackend, const READ_SIZE: usize, const WRITE_SIZE: usize, const ERASE_SIZE: usize>
26    NorMemory<B, READ_SIZE, WRITE_SIZE, ERASE_SIZE>
27{
28    /// Converts the NOR memory into a NOR storage.
29    pub fn storage(self) -> NorStorage<B, READ_SIZE, WRITE_SIZE, ERASE_SIZE> {
30        NorStorage {
31            wrapper: self,
32            merge_buffer: vec![0u8; ERASE_SIZE],
33        }
34    }
35}
36
37/// Trait representing a buffer backend for the NOR flash memory.
38pub trait BufferBackend {
39    /// Executes a closure with a slice of data from the buffer.
40    fn with_data<F>(&self, from: usize, to: usize, f: F) -> Result<(), Error>
41    where
42        F: FnMut(&[u8]) -> Result<(), Error>;
43
44    /// Executes a closure with a mutable slice of data from the buffer.
45    fn with_data_mut<F>(&mut self, from: usize, to: usize, f: F) -> Result<(), Error>
46    where
47        F: FnMut(&mut [u8]) -> Result<(), Error>;
48
49    /// Returns the size of the buffer.
50    fn size(&self) -> usize;
51}
52
53/// Structure representing a NOR storage with a buffer backend.
54pub struct NorStorage<
55    B: BufferBackend,
56    const READ_SIZE: usize,
57    const WRITE_SIZE: usize,
58    const ERASE_SIZE: usize,
59> {
60    wrapper: NorMemory<B, READ_SIZE, WRITE_SIZE, ERASE_SIZE>,
61    merge_buffer: Vec<u8>,
62}
63
64impl<B: BufferBackend, const READ_SIZE: usize, const WRITE_SIZE: usize, const ERASE_SIZE: usize>
65    NorStorage<B, READ_SIZE, WRITE_SIZE, ERASE_SIZE>
66{
67    /// Converts the NOR storage back into a NOR memory.
68    pub fn nor_flash(self) -> NorMemory<B, READ_SIZE, WRITE_SIZE, ERASE_SIZE> {
69        self.wrapper
70    }
71}
72
73impl<B: BufferBackend, const READ_SIZE: usize, const WRITE_SIZE: usize, const ERASE_SIZE: usize>
74    embedded_storage::nor_flash::ErrorType for NorMemory<B, READ_SIZE, WRITE_SIZE, ERASE_SIZE>
75{
76    type Error = embedded_storage::nor_flash::NorFlashErrorKind;
77}
78
79impl<B: BufferBackend, const READ_SIZE: usize, const WRITE_SIZE: usize, const ERASE_SIZE: usize>
80    ReadNorFlash for NorMemory<B, READ_SIZE, WRITE_SIZE, ERASE_SIZE>
81{
82    const READ_SIZE: usize = READ_SIZE;
83
84    /// Reads data from the NOR flash memory into the provided buffer.
85    fn read(&mut self, address: u32, buf: &mut [u8]) -> Result<(), Error> {
86        if address as usize + buf.len() > self.capacity() {
87            return Err(embedded_storage::nor_flash::NorFlashErrorKind::OutOfBounds);
88        }
89        let start = address as usize;
90        let end = start + buf.len();
91        self.buffer.with_data(start, end, |data| {
92            buf.copy_from_slice(data);
93            Ok(())
94        })
95    }
96
97    /// Returns the capacity of the NOR flash memory.
98    fn capacity(&self) -> usize {
99        self.buffer.size()
100    }
101}
102
103impl<B: BufferBackend, const READ_SIZE: usize, const WRITE_SIZE: usize, const ERASE_SIZE: usize>
104    NorFlash for NorMemory<B, READ_SIZE, WRITE_SIZE, ERASE_SIZE>
105{
106    const WRITE_SIZE: usize = WRITE_SIZE;
107    const ERASE_SIZE: usize = ERASE_SIZE;
108
109    /// Erases data in the NOR flash memory from the specified range.
110    fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
111        if from as usize % ERASE_SIZE != 0 {
112            return Err(Error::NotAligned);
113        }
114        if to as usize % ERASE_SIZE != 0 {
115            return Err(Error::NotAligned);
116        }
117        if to < from {
118            return Err(Error::OutOfBounds);
119        }
120        if to as usize > NorMemory::capacity(self) {
121            return Err(Error::OutOfBounds);
122        }
123        if from == to {
124            // nothing to do
125            return Ok(());
126        }
127        self.buffer
128            .with_data_mut(from as usize, to as usize, |data| {
129                let len = data.len();
130                if from as usize + len != to as usize {
131                    // this is not expected
132                    return Err(Error::OutOfBounds);
133                }
134                for i in 0..len {
135                    data[i] = 0xFF;
136                }
137                Ok(())
138            })
139    }
140
141    /// Writes data to the NOR flash memory at the specified offset.
142    fn write(&mut self, offset: u32, data: &[u8]) -> Result<(), Error> {
143        let cap = self.capacity();
144        if offset as usize + data.len() > cap {
145            return Err(Error::OutOfBounds);
146        }
147        self.buffer
148            .with_data_mut(offset as usize, offset as usize + data.len(), |buf| {
149                buf.copy_from_slice(data);
150                Ok(())
151            })
152    }
153}
154
155impl<B: BufferBackend, const READ_SIZE: usize, const WRITE_SIZE: usize, const ERASE_SIZE: usize>
156    embedded_storage::ReadStorage for NorStorage<B, READ_SIZE, WRITE_SIZE, ERASE_SIZE>
157{
158    type Error = embedded_storage::nor_flash::NorFlashErrorKind;
159
160    /// Reads data from the NOR storage into the provided buffer.
161    fn read(&mut self, address: u32, buf: &mut [u8]) -> Result<(), Error> {
162        let mut storage = RmwNorFlashStorage::new(&mut self.wrapper, &mut self.merge_buffer[..]);
163        storage.read(address, buf)
164    }
165
166    /// Returns the capacity of the NOR storage.
167    fn capacity(&self) -> usize {
168        self.wrapper.capacity()
169    }
170}
171
172impl<B: BufferBackend, const READ_SIZE: usize, const WRITE_SIZE: usize, const ERASE_SIZE: usize>
173    embedded_storage::Storage for NorStorage<B, READ_SIZE, WRITE_SIZE, ERASE_SIZE>
174{
175    /// Writes data to the NOR storage at the specified address.
176    fn write(&mut self, address: u32, buf: &[u8]) -> Result<(), Error> {
177        let mut storage = RmwNorFlashStorage::new(&mut self.wrapper, &mut self.merge_buffer[..]);
178        storage.write(address, buf)
179    }
180}