Fix erasing across banks

This commit is contained in:
chemicstry 2022-07-14 20:58:01 +03:00
parent 039acda3a8
commit 5a265661bb
2 changed files with 38 additions and 34 deletions

View File

@ -7,8 +7,6 @@ use super::{ERASE_SIZE, FLASH_BASE, FLASH_SIZE};
use crate::flash::Error; use crate::flash::Error;
use crate::pac; use crate::pac;
// Only available on some devices
const SECOND_BANK_OFFSET: usize = FLASH_SIZE / 2;
const SECOND_BANK_SECTOR_START: u32 = 12; const SECOND_BANK_SECTOR_START: u32 = 12;
unsafe fn is_dual_bank() -> bool { unsafe fn is_dual_bank() -> bool {
@ -68,44 +66,52 @@ pub(crate) unsafe fn blocking_write(offset: u32, buf: &[u8]) -> Result<(), Error
ret ret
} }
unsafe fn get_sector(addr: u32) -> u8 { struct FlashSector {
index: u8,
size: u32,
}
fn get_sector(addr: u32, dual_bank: bool) -> FlashSector {
let offset = addr - FLASH_BASE as u32; let offset = addr - FLASH_BASE as u32;
let sector = if is_dual_bank() { let bank_size = match dual_bank {
let bank = offset / SECOND_BANK_OFFSET as u32; true => FLASH_SIZE / 2,
let offset_in_bank = offset % SECOND_BANK_OFFSET as u32; false => FLASH_SIZE,
} as u32;
let sector_in_bank = if offset_in_bank >= ERASE_SIZE as u32 / 2 { let bank = offset / bank_size;
let offset_in_bank = offset % bank_size;
let index_in_bank = if offset_in_bank >= ERASE_SIZE as u32 / 2 {
4 + offset_in_bank / ERASE_SIZE as u32 4 + offset_in_bank / ERASE_SIZE as u32
} else { } else {
offset_in_bank / (ERASE_SIZE as u32 / 8) offset_in_bank / (ERASE_SIZE as u32 / 8)
}; };
if bank == 1 { // First 4 sectors are 16KB, then one 64KB, and rest are 128KB
SECOND_BANK_SECTOR_START + sector_in_bank let size = match index_in_bank {
} else { 0..=3 => 16 * 1024,
sector_in_bank 4 => 64 * 1024,
} _ => 128 * 1024,
} else {
if offset >= ERASE_SIZE as u32 / 2 {
4 + offset / ERASE_SIZE as u32
} else {
offset / (ERASE_SIZE as u32 / 8)
}
}; };
sector as u8 let index = if bank == 1 {
SECOND_BANK_SECTOR_START + index_in_bank
} else {
index_in_bank
} as u8;
FlashSector { index, size }
} }
pub(crate) unsafe fn blocking_erase(from: u32, to: u32) -> Result<(), Error> { pub(crate) unsafe fn blocking_erase(from: u32, to: u32) -> Result<(), Error> {
let start_sector = get_sector(from); let mut addr = from;
let end_sector = get_sector(to - 1); // end range is exclusive let dual_bank = is_dual_bank();
for sector in start_sector..=end_sector { while addr < to {
let ret = erase_sector(sector as u8); let sector = get_sector(addr, dual_bank);
if ret.is_err() { erase_sector(sector.index)?;
return ret; addr += sector.size;
}
} }
Ok(()) Ok(())

View File

@ -7,6 +7,7 @@ use embassy::executor::Spawner;
use embassy::time::{Duration, Timer}; use embassy::time::{Duration, Timer};
use embassy_stm32::flash::Flash; use embassy_stm32::flash::Flash;
use embassy_stm32::Peripherals; use embassy_stm32::Peripherals;
use embedded_storage::nor_flash::{NorFlash, ReadNorFlash};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
#[embassy::main] #[embassy::main]
@ -18,11 +19,8 @@ async fn main(_spawner: Spawner, p: Peripherals) {
// Sector 5 // Sector 5
test_flash(&mut f, 128 * 1024, 128 * 1024); test_flash(&mut f, 128 * 1024, 128 * 1024);
// Sector 11, last in bank 1 // Sectors 11..=16, across banks (128K, 16K, 16K, 16K, 16K, 64K)
test_flash(&mut f, (1024 - 128) * 1024, 128 * 1024); test_flash(&mut f, (1024 - 128) * 1024, 256 * 1024);
// Sectors 12..=16, start of bank 2 (16K, 16K, 16K, 16K, 64K)
test_flash(&mut f, 1024 * 1024, 128 * 1024);
// Sectors 23, last in bank 2 // Sectors 23, last in bank 2
test_flash(&mut f, (2048 - 128) * 1024, 128 * 1024); test_flash(&mut f, (2048 - 128) * 1024, 128 * 1024);