Dear friends,
We're plagued by an occasional issue with the flash API where, after attempting to erase a sector, the erase operation nominally succeeds but the sector is not in fact blank.
In particular, this happens when trying to erase sector 1 (0x8000-0xFFFF). (Erasing sector 0 seems to work.) Again, the actual call to erase the sector returns a success code. However, the Fapi_doBlankCheck() immediately after fails on the first word of the sector (0x8000); the reported value is 0xe59ff018 (instead of the expected 0xffffffff). If I simply skip the blank check, then the subsequent program call fails, with getFsmStatus() returning INVDAT (this makes sense if the sector wasn't actually erased).
This is what my code looks like. At the point of failure, sector_address is 0x8000, sector_size is 0x8000,
==========
// Try: Blank check, erase, blank check, give up.
for (int attempt = 0; attempt < 2; ++attempt) {
// Fapi_doBlankCheck() on a whole sector takes 12+ms; do it in chunks.
status->error_code = Fapi_Status_Success;
for (uint32_t chunk = sector_address;
chunk < sector_address + sector_size; ) {
int length = Min<int>(1024, sector_address + sector_size - chunk);
Fapi_FlashStatusWordType fsw;
status->error_code = Fapi_doBlankCheck(
reinterpret_cast<uint32 *>(chunk),
length / sizeof(uint32), &fsw);
if (Failed("Fapi_doBlankCheck failed", status)) {
status->error_code = fsw.au32StatusWord[0]; // Bad address.
if (attempt > 0) return; // Should have succeeded by now.
break; // Before erase; now try erasing the sector.
}
chunk += length;
WatchdogServiceExternal();
}
if (status->error_code == Fapi_Status_Success) break; // Blank!
// First attempt: Issue the command to erase the sector.
CPU_SR_ALLOC();
CPU_INT_DIS(); // No interrupts while flashing!
status->error_code = Fapi_issueAsyncCommandWithAddress(
Fapi_EraseSector, reinterpret_cast<uint32 *>(sector_address));
if (Failed("Fapi_EraseSector failed", status)) {
CPU_INT_EN();
return;
}
while (Fapi_checkFsmForReady() == Fapi_Status_FsmBusy)
WatchdogServiceExternal(); // Wait for completion.
status->error_code = Fapi_getFsmStatus();
CPU_INT_EN();
if (Failed("Erase operation failed", status)) return;
Fapi_flushPipeline(); // Defensively flush after every erase.
}
==========
Like I said, this doesn't always seem to happen -- it comes and goes with unrelated code changes -- we're trying to narrow down what triggers this (whether it's related to the data being flashed, or the code doing the flashing, or what). Meanwhile, is there anything that could cause this kind of behavior?