Skip to content

Commit 95a1196

Browse files
committed
Make RmwNorFlashStorage::new take a mutable merge_buffer, that must be atleast EraseSize long. Introduce RmwMultiwriteNorFlashStorage
1 parent 5943283 commit 95a1196

File tree

1 file changed

+95
-66
lines changed

1 file changed

+95
-66
lines changed

src/nor_flash.rs

+95-66
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use crate::{iter::IterableByOverlaps, ReadStorage, Region, Storage};
1+
use crate::{
2+
iter::{IterableByOverlaps, OverlapIterator},
3+
ReadStorage, Region, Storage,
4+
};
25

36
/// Read only NOR flash trait.
47
pub trait ReadNorFlash {
@@ -77,117 +80,143 @@ impl Page {
7780
}
7881

7982
impl Region for Page {
83+
/// Checks if an address offset is contained within the page
8084
fn contains(&self, address: u32) -> bool {
8185
(self.start <= address) && (self.end() > address)
8286
}
8387
}
8488

8589
///
86-
pub struct RmwNorFlashStorage<S>(S);
90+
pub struct RmwNorFlashStorage<'a, S> {
91+
storage: S,
92+
merge_buffer: &'a mut [u8],
93+
}
8794

88-
impl<S> RmwNorFlashStorage<S> {
95+
impl<'a, S> RmwNorFlashStorage<'a, S>
96+
where
97+
S: NorFlash,
98+
{
8999
/// Instantiate a new generic `Storage` from a `NorFlash` peripheral
90-
pub fn new(nor_flash: S) -> Self {
91-
Self(nor_flash)
100+
///
101+
/// **NOTE** This will panic if the provided merge buffer,
102+
/// is smaller than the erase size of the flash peripheral
103+
pub fn new(nor_flash: S, merge_buffer: &'a mut [u8]) -> Self {
104+
if merge_buffer.len() < S::ERASE_SIZE {
105+
panic!("Merge buffer is too small");
106+
}
107+
108+
Self {
109+
storage: nor_flash,
110+
merge_buffer,
111+
}
92112
}
93113
}
94114

95-
impl<S> ReadStorage for RmwNorFlashStorage<S>
115+
impl<'a, S> ReadStorage for RmwNorFlashStorage<'a, S>
96116
where
97117
S: ReadNorFlash,
98118
{
99119
type Error = S::Error;
100120

101121
fn try_read(&mut self, address: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
102122
// Nothing special to be done for reads
103-
self.0.try_read(address, bytes)
123+
self.storage.try_read(address, bytes)
104124
}
105125

106126
fn capacity(&self) -> usize {
107-
self.0.capacity()
127+
self.storage.capacity()
108128
}
109129
}
110130

111-
impl<S> Storage for RmwNorFlashStorage<S>
131+
impl<'a, S> Storage for RmwNorFlashStorage<'a, S>
112132
where
113133
S: NorFlash,
114-
// [u8; S::ERASE_SIZE]: Sized,
115134
{
116135
fn try_write(&mut self, address: u32, bytes: &[u8]) -> Result<(), Self::Error> {
117136
// Perform read/modify/write operations on the byte slice.
118-
let last_page = (self.0.capacity() / S::ERASE_SIZE) - 1;
137+
let last_page = (self.storage.capacity() / S::ERASE_SIZE) - 1;
119138

120139
// `data` is the part of `bytes` contained within `page`,
121140
// and `addr` in the address offset of `page` + any offset into the page as requested by `address`
122141
for (data, page, addr) in (0..last_page as u32)
123142
.map(move |i| Page::new(i, S::ERASE_SIZE))
124143
.overlaps(bytes, address)
125144
{
126-
let merge_buffer = &mut [0u8; 2048];
127145
let offset_into_page = addr.saturating_sub(page.start) as usize;
128146

129-
self.try_read(page.start, merge_buffer)?;
147+
self.storage.try_read(page.start, self.merge_buffer)?;
130148

131149
// If we cannot write multiple times to the same page, we will have to erase it
132-
self.0.try_erase(page.start, page.end())?;
133-
merge_buffer
150+
self.storage.try_erase(page.start, page.end())?;
151+
self.merge_buffer
134152
.iter_mut()
135153
.skip(offset_into_page)
136154
.zip(data)
137155
.for_each(|(byte, input)| *byte = *input);
138-
self.0.try_write(page.start, merge_buffer)?;
156+
self.storage.try_write(page.start, self.merge_buffer)?;
139157
}
140158
Ok(())
141159
}
142160
}
143161

144-
// FIXME: Requires specialization to take advantage of MultiwriteNorFlash?
145-
// impl<S: MultiwriteNorFlash> Storage for RmwNorFlashStorage<S> {
146-
// type Error = S::Error;
147-
148-
// fn try_read(&mut self, address: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
149-
// // Nothing special to be done for reads
150-
// self.0.try_read(address, bytes)
151-
// }
152-
153-
// fn try_write(&mut self, address: u32, bytes: &[u8]) -> Result<(), Self::Error> {
154-
// // Perform read/modify/write operations on the byte slice.
155-
// let erase_size = self.0.erase_size();
156-
// let last_page = (self.0.capacity() / erase_size) - 1;
157-
158-
// // `data` is the part of `bytes` contained within `page`,
159-
// // and `addr` in the address offset of `page` + any offset into the page as requested by `address`
160-
// for (data, page, addr) in (0..last_page)
161-
// .map(move |i| Page::new(i, erase_size))
162-
// .overlaps(bytes, address)
163-
// {
164-
// let merge_buffer = &mut [0u8; MAX_PAGE_SIZE][0..erase_size as usize];
165-
// let offset_into_page = addr.saturating_sub(page.start) as usize;
166-
167-
// self.try_read(page.start, merge_buffer)?;
168-
169-
// let rhs = &merge_buffer[offset_into_page..];
170-
// let is_subset =
171-
// data.len() < rhs.len() && data.iter().zip(rhs.iter()).all(|(a, b)| (*a | *b) == *b);
172-
173-
// // Check if we can write the data block directly, under the limitations imposed by NorFlash:
174-
// // - We can only change 1's to 0's
175-
// if is_subset {
176-
// self.0.try_write(addr, data)?;
177-
// } else {
178-
// self.0.try_erase(page.start, page.end())?;
179-
// merge_buffer
180-
// .iter_mut()
181-
// .skip(offset_into_page)
182-
// .zip(data)
183-
// .for_each(|(byte, input)| *byte = *input);
184-
// self.0.try_write(page.start, merge_buffer)?;
185-
// }
186-
// }
187-
// Ok(())
188-
// }
189-
190-
// fn capacity(&self) -> u32 {
191-
// self.0.capacity()
192-
// }
193-
// }
162+
///
163+
pub struct RmwMultiwriteNorFlashStorage<'a, S> {
164+
storage: S,
165+
merge_buffer: &'a mut [u8],
166+
}
167+
168+
impl<'a, S> ReadStorage for RmwMultiwriteNorFlashStorage<'a, S>
169+
where
170+
S: ReadNorFlash,
171+
{
172+
type Error = S::Error;
173+
174+
fn try_read(&mut self, address: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
175+
// Nothing special to be done for reads
176+
self.storage.try_read(address, bytes)
177+
}
178+
179+
fn capacity(&self) -> usize {
180+
self.storage.capacity()
181+
}
182+
}
183+
184+
impl<'a, S> Storage for RmwMultiwriteNorFlashStorage<'a, S>
185+
where
186+
S: NorFlash,
187+
{
188+
fn try_write(&mut self, address: u32, bytes: &[u8]) -> Result<(), Self::Error> {
189+
// Perform read/modify/write operations on the byte slice.
190+
let last_page = (self.storage.capacity() / S::ERASE_SIZE) - 1;
191+
192+
// `data` is the part of `bytes` contained within `page`,
193+
// and `addr` in the address offset of `page` + any offset into the page as requested by `address`
194+
for (data, page, addr) in (0..last_page as u32)
195+
.map(move |i| Page::new(i, S::ERASE_SIZE))
196+
.overlaps(bytes, address)
197+
{
198+
let offset_into_page = addr.saturating_sub(page.start) as usize;
199+
200+
self.storage.try_read(page.start, self.merge_buffer)?;
201+
202+
let rhs = &self.merge_buffer[offset_into_page..];
203+
let is_subset =
204+
data.len() < rhs.len() && data.iter().zip(rhs.iter()).all(|(a, b)| (*a | *b) == *b);
205+
206+
// Check if we can write the data block directly, under the limitations imposed by NorFlash:
207+
// - We can only change 1's to 0's
208+
if is_subset {
209+
self.storage.try_write(addr, data)?;
210+
} else {
211+
self.storage.try_erase(page.start, page.end())?;
212+
self.merge_buffer
213+
.iter_mut()
214+
.skip(offset_into_page)
215+
.zip(data)
216+
.for_each(|(byte, input)| *byte = *input);
217+
self.storage.try_write(page.start, self.merge_buffer)?;
218+
}
219+
}
220+
Ok(())
221+
}
222+
}

0 commit comments

Comments
 (0)