Skip to content

Commit 363bce3

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

File tree

1 file changed

+91
-65
lines changed

1 file changed

+91
-65
lines changed

src/nor_flash.rs

Lines changed: 91 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -77,117 +77,143 @@ impl Page {
7777
}
7878

7979
impl Region for Page {
80+
/// Checks if an address offset is contained within the page
8081
fn contains(&self, address: u32) -> bool {
8182
(self.start <= address) && (self.end() > address)
8283
}
8384
}
8485

8586
///
86-
pub struct RmwNorFlashStorage<S>(S);
87+
pub struct RmwNorFlashStorage<'a, S> {
88+
storage: S,
89+
merge_buffer: &'a mut [u8],
90+
}
8791

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

95-
impl<S> ReadStorage for RmwNorFlashStorage<S>
112+
impl<'a, S> ReadStorage for RmwNorFlashStorage<'a, S>
96113
where
97114
S: ReadNorFlash,
98115
{
99116
type Error = S::Error;
100117

101118
fn try_read(&mut self, address: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
102119
// Nothing special to be done for reads
103-
self.0.try_read(address, bytes)
120+
self.storage.try_read(address, bytes)
104121
}
105122

106123
fn capacity(&self) -> usize {
107-
self.0.capacity()
124+
self.storage.capacity()
108125
}
109126
}
110127

111-
impl<S> Storage for RmwNorFlashStorage<S>
128+
impl<'a, S> Storage for RmwNorFlashStorage<'a, S>
112129
where
113130
S: NorFlash,
114-
// [u8; S::ERASE_SIZE]: Sized,
115131
{
116132
fn try_write(&mut self, address: u32, bytes: &[u8]) -> Result<(), Self::Error> {
117133
// Perform read/modify/write operations on the byte slice.
118-
let last_page = (self.0.capacity() / S::ERASE_SIZE) - 1;
134+
let last_page = (self.storage.capacity() / S::ERASE_SIZE) - 1;
119135

120136
// `data` is the part of `bytes` contained within `page`,
121137
// and `addr` in the address offset of `page` + any offset into the page as requested by `address`
122138
for (data, page, addr) in (0..last_page as u32)
123139
.map(move |i| Page::new(i, S::ERASE_SIZE))
124140
.overlaps(bytes, address)
125141
{
126-
let merge_buffer = &mut [0u8; 2048];
127142
let offset_into_page = addr.saturating_sub(page.start) as usize;
128143

129-
self.try_read(page.start, merge_buffer)?;
144+
self.storage.try_read(page.start, self.merge_buffer)?;
130145

131146
// 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
147+
self.storage.try_erase(page.start, page.end())?;
148+
self.merge_buffer
134149
.iter_mut()
135150
.skip(offset_into_page)
136151
.zip(data)
137152
.for_each(|(byte, input)| *byte = *input);
138-
self.0.try_write(page.start, merge_buffer)?;
153+
self.storage.try_write(page.start, self.merge_buffer)?;
139154
}
140155
Ok(())
141156
}
142157
}
143158

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

0 commit comments

Comments
 (0)