|
1 | | -use crate::{iter::IterableByOverlaps, ReadStorage, Region, Storage}; |
2 | | - |
3 | 1 | /// Read only NOR flash trait. |
4 | 2 | pub trait ReadNorFlash { |
5 | 3 | /// An enumeration of storage errors |
@@ -54,193 +52,3 @@ pub trait NorFlash: ReadNorFlash { |
54 | 52 | /// - Bits that were 0 on flash are guaranteed to stay as 0 |
55 | 53 | /// - Rest of the bits in the page are guaranteed to be unchanged |
56 | 54 | pub trait MultiwriteNorFlash: NorFlash {} |
57 | | - |
58 | | -struct Page { |
59 | | - pub start: u32, |
60 | | - pub size: usize, |
61 | | -} |
62 | | - |
63 | | -impl Page { |
64 | | - fn new(index: u32, size: usize) -> Self { |
65 | | - Self { |
66 | | - start: index * size as u32, |
67 | | - size, |
68 | | - } |
69 | | - } |
70 | | - |
71 | | - /// The end address of the page |
72 | | - const fn end(&self) -> u32 { |
73 | | - self.start + self.size as u32 |
74 | | - } |
75 | | -} |
76 | | - |
77 | | -impl Region for Page { |
78 | | - /// Checks if an address offset is contained within the page |
79 | | - fn contains(&self, address: u32) -> bool { |
80 | | - (self.start <= address) && (self.end() > address) |
81 | | - } |
82 | | -} |
83 | | - |
84 | | -/// |
85 | | -pub struct RmwNorFlashStorage<'a, S> { |
86 | | - storage: S, |
87 | | - merge_buffer: &'a mut [u8], |
88 | | -} |
89 | | - |
90 | | -impl<'a, S> RmwNorFlashStorage<'a, S> |
91 | | -where |
92 | | - S: NorFlash, |
93 | | -{ |
94 | | - /// Instantiate a new generic `Storage` from a `NorFlash` peripheral |
95 | | - /// |
96 | | - /// **NOTE** This will panic if the provided merge buffer, |
97 | | - /// is smaller than the erase size of the flash peripheral |
98 | | - 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 | | - |
110 | | -impl<'a, S> ReadStorage for RmwNorFlashStorage<'a, S> |
111 | | -where |
112 | | - S: ReadNorFlash, |
113 | | -{ |
114 | | - type Error = S::Error; |
115 | | - |
116 | | - fn try_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { |
117 | | - // Nothing special to be done for reads |
118 | | - self.storage.try_read(offset, bytes) |
119 | | - } |
120 | | - |
121 | | - fn capacity(&self) -> usize { |
122 | | - self.storage.capacity() |
123 | | - } |
124 | | -} |
125 | | - |
126 | | -impl<'a, S> Storage for RmwNorFlashStorage<'a, S> |
127 | | -where |
128 | | - S: NorFlash, |
129 | | -{ |
130 | | - fn try_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { |
131 | | - // Perform read/modify/write operations on the byte slice. |
132 | | - let last_page = self.storage.capacity() / S::ERASE_SIZE; |
133 | | - |
134 | | - // `data` is the part of `bytes` contained within `page`, |
135 | | - // and `addr` in the address offset of `page` + any offset into the page as requested by `address` |
136 | | - 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 | | - .try_read(page.start, &mut self.merge_buffer[..S::ERASE_SIZE])?; |
144 | | - |
145 | | - // If we cannot write multiple times to the same page, we will have to erase it |
146 | | - self.storage.try_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 | | - .try_write(page.start, &self.merge_buffer[..S::ERASE_SIZE])?; |
154 | | - } |
155 | | - Ok(()) |
156 | | - } |
157 | | -} |
158 | | - |
159 | | -/// |
160 | | -pub struct RmwMultiwriteNorFlashStorage<'a, S> { |
161 | | - storage: S, |
162 | | - merge_buffer: &'a mut [u8], |
163 | | -} |
164 | | - |
165 | | -impl<'a, S> RmwMultiwriteNorFlashStorage<'a, S> |
166 | | -where |
167 | | - S: MultiwriteNorFlash, |
168 | | -{ |
169 | | - /// Instantiate a new generic `Storage` from a `NorFlash` peripheral |
170 | | - /// |
171 | | - /// **NOTE** This will panic if the provided merge buffer, |
172 | | - /// is smaller than the erase size of the flash peripheral |
173 | | - 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 | | - |
185 | | -impl<'a, S> ReadStorage for RmwMultiwriteNorFlashStorage<'a, S> |
186 | | -where |
187 | | - S: ReadNorFlash, |
188 | | -{ |
189 | | - type Error = S::Error; |
190 | | - |
191 | | - fn try_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { |
192 | | - // Nothing special to be done for reads |
193 | | - self.storage.try_read(offset, bytes) |
194 | | - } |
195 | | - |
196 | | - fn capacity(&self) -> usize { |
197 | | - self.storage.capacity() |
198 | | - } |
199 | | -} |
200 | | - |
201 | | -impl<'a, S> Storage for RmwMultiwriteNorFlashStorage<'a, S> |
202 | | -where |
203 | | - S: MultiwriteNorFlash, |
204 | | -{ |
205 | | - fn try_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { |
206 | | - // Perform read/modify/write operations on the byte slice. |
207 | | - let last_page = self.storage.capacity() / S::ERASE_SIZE; |
208 | | - |
209 | | - // `data` is the part of `bytes` contained within `page`, |
210 | | - // and `addr` in the address offset of `page` + any offset into the page as requested by `address` |
211 | | - 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 | | - .try_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 | | - // Check if we can write the data block directly, under the limitations imposed by NorFlash: |
224 | | - // - We can only change 1's to 0's |
225 | | - if is_subset { |
226 | | - // Use `merge_buffer` as allocation for padding `data` to `WRITE_SIZE` |
227 | | - let offset = addr as usize % S::WRITE_SIZE; |
228 | | - let alligned_end = data.len() % S::WRITE_SIZE; |
229 | | - self.merge_buffer[..S::WRITE_SIZE].fill(0xff); |
230 | | - self.merge_buffer[offset..data.len()].copy_from_slice(data); |
231 | | - self.storage |
232 | | - .try_write(addr - offset as u32, &self.merge_buffer[..S::WRITE_SIZE])?; |
233 | | - } else { |
234 | | - self.storage.try_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 | | - .try_write(page.start, &self.merge_buffer[..S::ERASE_SIZE])?; |
242 | | - } |
243 | | - } |
244 | | - Ok(()) |
245 | | - } |
246 | | -} |
0 commit comments