Skip to main content

embedded_storage_file/
synhronous.rs

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