Skip to content

Commit a025330

Browse files
committed
Check if a cosmo flash sector is erased before erasing
The Winbond flash chip on Cosmo has a unique flash erase algorithm that significantly penalizes erasing already erased sectors. Check for this case before running a sector erase command. Before real 3m31.962s user 0m4.325s sys 0m3.188s After real 2m0.817s user 0m4.380s sys 0m3.305s
1 parent 5d3ee17 commit a025330

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

drv/cosmo-hf/src/main.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,9 @@ impl FlashDriver {
270270

271271
/// Erases the 64KiB flash sector containing the given address
272272
fn flash_sector_erase(&mut self, addr: FlashAddr) {
273+
if self.flash_is_sector_erased(addr) {
274+
return;
275+
}
273276
self.flash_write_enable();
274277
self.drv.data_bytes.set_count(0);
275278
self.drv.addr.set_addr(addr.0);
@@ -281,6 +284,37 @@ impl FlashDriver {
281284
self.wait_flash_busy(Trace::SectorEraseBusy);
282285
}
283286

287+
/// Returns true if the full 64KB sector is erased
288+
/// (all bits are set to `1`)
289+
fn flash_is_sector_erased(&mut self, addr: FlashAddr) -> bool {
290+
let cnt = SECTOR_SIZE_BYTES / (PAGE_SIZE_BYTES as u32);
291+
for i in 0..cnt {
292+
let addr = addr.0 + i * (PAGE_SIZE_BYTES as u32);
293+
self.clear_fifos();
294+
self.drv.data_bytes.set_count(PAGE_SIZE_BYTES as u16);
295+
self.drv.addr.set_addr(addr);
296+
self.drv.dummy_cycles.set_count(8);
297+
self.drv.instr.set_opcode(instr::FAST_READ_QUAD_OUTPUT_4B);
298+
let mut erased = true;
299+
// Technicaly we could terminiate this loop early when
300+
// we find the first non-erased byte but we still have
301+
// to drain the FIFOs and wait for the FPGA which means
302+
// there's no performance gain vs just reading everything
303+
// in a loop here.
304+
for _ in 0..PAGE_SIZE_BYTES.div_ceil(4) {
305+
self.wait_fpga_rx();
306+
let v = self.drv.rx_fifo_rdata.fifo_data();
307+
if v != u32::MAX {
308+
erased = false;
309+
}
310+
}
311+
if !erased {
312+
return false;
313+
}
314+
}
315+
true
316+
}
317+
284318
/// Reads data from the given address into a `BufWriter`
285319
///
286320
/// This function will only return an error if it fails to read from a

0 commit comments

Comments
 (0)