Skip to content

Commit a3c2adb

Browse files
committed
Skip programming erased pages
Flash memory is set to all `1` when erased. We have to erase pages before writing so writing pages full of `1` is not a good use of CPU time. Before real 2m0.817s user 0m4.380s sys 0m3.305s After real 1m44.543s user 0m3.586s sys 0m2.710s
1 parent c00158c commit a3c2adb

File tree

3 files changed

+39
-43
lines changed

3 files changed

+39
-43
lines changed

drv/cosmo-hf/src/apob.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ impl ApobState {
647647
// If any byte is not a match, then we have to do a flash write
648648
// (otherwise, it's an idempotent write and we can skip it)
649649
if needs_write {
650-
drv.flash_write(addr, &mut &buf.page[..n])
650+
drv.flash_write(addr, &buf.page[..n])
651651
.map_err(|_| ApobWriteError::WriteFailed)?;
652652
}
653653
}
@@ -873,6 +873,6 @@ impl ApobState {
873873
addr
874874
});
875875
// Infallible when using a slice
876-
drv.flash_write(addr, &mut data.as_bytes()).unwrap_lite();
876+
drv.flash_write(addr, data.as_bytes()).unwrap_lite();
877877
}
878878
}

drv/cosmo-hf/src/hf.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use drv_hf_api::{
99
HF_PERSISTENT_DATA_STRIDE,
1010
};
1111
use idol_runtime::{
12-
LeaseBufReader, LeaseBufWriter, Leased, LenLimit, NotificationHandler,
12+
ClientError, LeaseBufWriter, Leased, LenLimit, NotificationHandler,
1313
RequestError, R, W,
1414
};
1515
use ringbuf::ringbuf_entry_root as ringbuf_entry;
@@ -205,7 +205,7 @@ impl ServerImpl {
205205
};
206206
// flash_write is infallible when given a slice
207207
self.drv
208-
.flash_write(addr, &mut raw_data.as_bytes())
208+
.flash_write(addr, raw_data.as_bytes())
209209
.unwrap_lite();
210210
}
211211

@@ -421,11 +421,13 @@ impl idl::InOrderHostFlashImpl for ServerImpl {
421421
self.drv.check_flash_mux_state()?;
422422
let addr = self.flash_addr(addr, data.len() as u32)?;
423423
self.invalidate_write();
424+
let mut block: [u8; PAGE_SIZE_BYTES] = [0; PAGE_SIZE_BYTES];
425+
// Read the entire data block into our address space.
426+
data.read_range(0..data.len(), &mut block[..data.len()])
427+
.map_err(|_| RequestError::Fail(ClientError::WentAway))?;
428+
424429
self.drv
425-
.flash_write(
426-
addr,
427-
&mut LeaseBufReader::<_, 32>::from(data.into_inner()),
428-
)
430+
.flash_write(addr, &block[..data.len()])
429431
.map_err(|()| RequestError::went_away())
430432
}
431433

drv/cosmo-hf/src/main.rs

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -345,44 +345,38 @@ impl FlashDriver {
345345
Ok(())
346346
}
347347

348-
/// Writes data from a `BufReader` into the flash
348+
/// Writes data from a slice into the flash
349349
///
350-
/// This function will only return an error if it fails to write to a
351-
/// provided lease; when given a slice, it is infallible.
352-
fn flash_write(
353-
&mut self,
354-
addr: FlashAddr,
355-
data: &mut dyn idol_runtime::BufReader<'_>,
356-
) -> Result<(), ()> {
357-
loop {
358-
let len = data.remaining_size().min(PAGE_SIZE_BYTES);
359-
if len == 0 {
360-
break;
361-
}
362-
self.flash_write_enable();
363-
self.drv.data_bytes.set_count(len as u16);
364-
self.drv.addr.set_addr(addr.0);
365-
self.drv.dummy_cycles.set_count(0);
366-
for i in 0..len.div_ceil(4) {
367-
let mut v = [0u8; 4];
368-
for (j, byte) in v.iter_mut().enumerate() {
369-
let k = i * 4 + j;
370-
if k < len {
371-
let Some(d) = data.read() else {
372-
return Err(());
373-
};
374-
*byte = d;
375-
}
376-
}
377-
let v = u32::from_le_bytes(v);
378-
self.drv.tx_fifo_wdata.set_fifo_data(v);
379-
}
380-
self.drv.instr.set_opcode(instr::QUAD_INPUT_PAGE_PROGRAM_4B);
381-
self.wait_fpga_busy();
350+
/// This function will only return an error if the slice len is not a full
351+
/// page size
352+
fn flash_write(&mut self, addr: FlashAddr, data: &[u8]) -> Result<(), ()> {
353+
// This function will not work if we try and write less than a full page
354+
if data.len() != PAGE_SIZE_BYTES {
355+
return Err(());
356+
}
382357

383-
// Wait for the busy flag to be unset
384-
self.wait_flash_busy(Trace::WriteBusy);
358+
let len = data.len();
359+
360+
// Don't bother writing erased pages
361+
if data.iter().all(|x| *x == 0xff) {
362+
return Ok(());
385363
}
364+
365+
self.flash_write_enable();
366+
self.drv.data_bytes.set_count(len as u16);
367+
self.drv.addr.set_addr(addr.0);
368+
self.drv.dummy_cycles.set_count(0);
369+
370+
for chunk in data.chunks(4) {
371+
let v = u32::from_le_bytes(chunk.try_into().unwrap());
372+
self.drv.tx_fifo_wdata.set_fifo_data(v);
373+
}
374+
375+
self.drv.instr.set_opcode(instr::QUAD_INPUT_PAGE_PROGRAM_4B);
376+
self.wait_fpga_busy();
377+
378+
// Wait for the busy flag to be unset
379+
self.wait_flash_busy(Trace::WriteBusy);
386380
Ok(())
387381
}
388382

0 commit comments

Comments
 (0)