add block erase routines

This commit is contained in:
bunnie 2025-05-04 03:32:52 +08:00
parent b2098916c7
commit d985491c7f

View file

@ -6,6 +6,7 @@ use crate::udma::*;
pub const FLASH_PAGE_LEN: usize = 256;
pub const FLASH_SECTOR_LEN: usize = 4096;
pub const BLOCK_ERASE_LEN: usize = 65536;
// ----------------------------------- SPIM ------------------------------------
@ -1225,6 +1226,70 @@ impl Spim {
result
}
fn flash_be(&mut self, block_address: u32) {
self.mem_cs(true);
self.mem_send_cmd(0xd8);
let cmd_list =
[SpimCmd::TxData(self.mode, SpimWordsPerXfer::Words1, 8 as u8, SpimEndian::MsbFirst, 3 as u32)];
self.tx_buf_mut()[..3].copy_from_slice(&block_address.to_be_bytes()[1..]);
// safety: this is safe because tx_buf_phys() slice is only used as a base/bounds reference
unsafe { self.udma_enqueue(Bank::Tx, &self.tx_buf_phys::<u8>()[..3], CFG_EN | CFG_SIZE_8) }
self.send_cmd_list(&cmd_list);
while self.udma_busy(Bank::Tx) {
#[cfg(feature = "std")]
xous::yield_slice();
}
self.mem_cs(false);
}
pub fn flash_erase_block(&mut self, start: usize, len: usize) -> bool {
if (start & (BLOCK_ERASE_LEN - 1)) != 0 {
// log::warn!("Bulk erase start address is not block-aligned. Aborting.");
return false;
}
if (len & (BLOCK_ERASE_LEN - 1)) != 0 {
// log::warn!("Bulk erase end address is not block-aligned. Aborting.");
return false;
}
for block_addr in (start..start + len).step_by(BLOCK_ERASE_LEN as usize) {
// enable writes: set wren mode
// crate::println!("flash_erase_sector: {:x}", sector_address);
loop {
self.flash_wren();
let status = self.flash_rdsr();
// crate::println!("wren status: {:x}", status);
if status & 0x02 != 0 {
break;
}
}
// issue erase command
self.flash_be(block_addr as u32);
// wait for WIP bit to drop
loop {
let status = self.flash_rdsr();
// crate::println!("WIP status: {:x}", status);
if status & 0x01 == 0 {
break;
}
}
// get the success code for return
// let result = self.flash_rdscur();
// disable writes: send wrdi
if self.flash_rdsr() & 0x02 != 0 {
loop {
self.flash_wrdi();
let status = self.flash_rdsr();
// crate::println!("WRDI status: {:x}", status);
if status & 0x02 == 0 {
break;
}
}
}
}
true
}
/// This routine can data that is strictly a multiple of a page length (256 bytes)
pub fn mem_flash_write_page(&mut self, addr: u32, buf: &[u8; FLASH_PAGE_LEN]) -> bool {
// crate::println!("write_page: {:x}, {:x?}", addr, &buf[..8]);