embedded_storage/
nor_flash.rs1use crate::{iter::IterableByOverlaps, ReadStorage, Region, Storage};
2
3pub trait ReadNorFlash {
5 type Error;
7
8 const READ_SIZE: usize;
10
11 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error>;
17
18 fn capacity(&self) -> usize;
20}
21
22pub trait NorFlash: ReadNorFlash {
24 const WRITE_SIZE: usize;
26
27 const ERASE_SIZE: usize;
29
30 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error>;
38
39 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error>;
44}
45
46pub trait MultiwriteNorFlash: NorFlash {}
57
58struct Page {
59 pub start: u32,
60 pub size: usize,
61}
62
63impl Page {
64 fn new(index: u32, size: usize) -> Self {
65 Self {
66 start: index * size as u32,
67 size,
68 }
69 }
70
71 const fn end(&self) -> u32 {
73 self.start + self.size as u32
74 }
75}
76
77impl Region for Page {
78 fn contains(&self, address: u32) -> bool {
80 (self.start <= address) && (self.end() > address)
81 }
82}
83
84pub struct RmwNorFlashStorage<'a, S> {
86 storage: S,
87 merge_buffer: &'a mut [u8],
88}
89
90impl<'a, S> RmwNorFlashStorage<'a, S>
91where
92 S: NorFlash,
93{
94 pub fn new(nor_flash: S, merge_buffer: &'a mut [u8]) -> Self {
99 if merge_buffer.len() < S::ERASE_SIZE {
100 panic!("Merge buffer is too small");
101 }
102
103 Self {
104 storage: nor_flash,
105 merge_buffer,
106 }
107 }
108}
109
110impl<'a, S> ReadStorage for RmwNorFlashStorage<'a, S>
111where
112 S: ReadNorFlash,
113{
114 type Error = S::Error;
115
116 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
117 self.storage.read(offset, bytes)
119 }
120
121 fn capacity(&self) -> usize {
122 self.storage.capacity()
123 }
124}
125
126impl<'a, S> Storage for RmwNorFlashStorage<'a, S>
127where
128 S: NorFlash,
129{
130 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
131 let last_page = self.storage.capacity() / S::ERASE_SIZE;
133
134 for (data, page, addr) in (0..last_page as u32)
137 .map(move |i| Page::new(i, S::ERASE_SIZE))
138 .overlaps(bytes, offset)
139 {
140 let offset_into_page = addr.saturating_sub(page.start) as usize;
141
142 self.storage
143 .read(page.start, &mut self.merge_buffer[..S::ERASE_SIZE])?;
144
145 self.storage.erase(page.start, page.end())?;
147 self.merge_buffer[..S::ERASE_SIZE]
148 .iter_mut()
149 .skip(offset_into_page)
150 .zip(data)
151 .for_each(|(byte, input)| *byte = *input);
152 self.storage
153 .write(page.start, &self.merge_buffer[..S::ERASE_SIZE])?;
154 }
155 Ok(())
156 }
157}
158
159pub struct RmwMultiwriteNorFlashStorage<'a, S> {
161 storage: S,
162 merge_buffer: &'a mut [u8],
163}
164
165impl<'a, S> RmwMultiwriteNorFlashStorage<'a, S>
166where
167 S: MultiwriteNorFlash,
168{
169 pub fn new(nor_flash: S, merge_buffer: &'a mut [u8]) -> Self {
174 if merge_buffer.len() < S::ERASE_SIZE {
175 panic!("Merge buffer is too small");
176 }
177
178 Self {
179 storage: nor_flash,
180 merge_buffer,
181 }
182 }
183}
184
185impl<'a, S> ReadStorage for RmwMultiwriteNorFlashStorage<'a, S>
186where
187 S: ReadNorFlash,
188{
189 type Error = S::Error;
190
191 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
192 self.storage.read(offset, bytes)
194 }
195
196 fn capacity(&self) -> usize {
197 self.storage.capacity()
198 }
199}
200
201impl<'a, S> Storage for RmwMultiwriteNorFlashStorage<'a, S>
202where
203 S: MultiwriteNorFlash,
204{
205 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
206 let last_page = self.storage.capacity() / S::ERASE_SIZE;
208
209 for (data, page, addr) in (0..last_page as u32)
212 .map(move |i| Page::new(i, S::ERASE_SIZE))
213 .overlaps(bytes, offset)
214 {
215 let offset_into_page = addr.saturating_sub(page.start) as usize;
216
217 self.storage
218 .read(page.start, &mut self.merge_buffer[..S::ERASE_SIZE])?;
219
220 let rhs = &self.merge_buffer[offset_into_page..S::ERASE_SIZE];
221 let is_subset = data.iter().zip(rhs.iter()).all(|(a, b)| *a & *b == *a);
222
223 if is_subset {
226 let offset = addr as usize % S::WRITE_SIZE;
228 let aligned_end = data.len() % S::WRITE_SIZE + offset + data.len();
229 self.merge_buffer[..aligned_end].fill(0xff);
230 self.merge_buffer[offset..offset + data.len()].copy_from_slice(data);
231 self.storage
232 .write(addr - offset as u32, &self.merge_buffer[..aligned_end])?;
233 } else {
234 self.storage.erase(page.start, page.end())?;
235 self.merge_buffer[..S::ERASE_SIZE]
236 .iter_mut()
237 .skip(offset_into_page)
238 .zip(data)
239 .for_each(|(byte, input)| *byte = *input);
240 self.storage
241 .write(page.start, &self.merge_buffer[..S::ERASE_SIZE])?;
242 }
243 }
244 Ok(())
245 }
246}