Conversation
flashPartitionErase() calls flashWaitForReady(0) after every block erase to wait for the erase to complete. The W25N driver took that as "time out after zero milliseconds": w25n_setTimeout(0) overwrote the 15 ms deadline that w25n_eraseSector() had just armed with a deadline that has already expired, so w25n_waitForReadyInternal() returned false on the first poll that saw the device busy. The following loop iteration then issued write enable and block erase into a device that was still erasing the previous block, where the NAND ignores both instructions, so most blocks of the partition were never erased. Only targets that erase the whole chip through flashEraseCompletely() were unaffected, because that path waits through w25n_waitForReadyInternal(). Interpret a zero timeout as "use the deadline the pending operation armed", which is what the NOR driver m25p16_waitForReady() already does. Fixes iNavFlight#11376
flashfsEraseCompletely() reset the write offset to zero in RAM, so the used size read as zero no matter what the chip had actually done. The offset is measured on the flash itself at boot, which is why a failed erase only became visible after a power cycle, with the supposedly deleted log back in place. Look for the start of the free space right after the erase, the same way flashfsInit() does, so that the reported used size is the one the next boot will find. A chip that is still erasing cannot be examined, because its reads time out and the device would be taken for full; that applies to a NOR chip erasing in the background through a single bulk erase instruction, which keeps the previous behaviour there. On the W25N side, w25n_eraseSector() threw away the result of its wait and issued write enable and block erase into a device that was still busy, which ignores both. Skip the block instead, drop the cached page number because the device data buffer may hold a page of the erased block, and let w25n_eraseCompletely() wait for the last block so the flash can be read back as soon as the erase returns. Fixes iNavFlight#11376
|
ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing |
PR Summary by QodoMake W25N erases blocking and report verified flash usage
AI Description
Diagram
High-Level Assessment
Files changed (2)
|
Code Review by Qodo
1.
|
Problem
On a RADIOLINKF405 with a W25N01GV,
flash_eraseprintsErasing... Done.andflash_infothen reportsusedSize=0, but after a power cycleflash_infoshows the previoususedSizeagain and the old log is still on the chip. The Configurator "Erase Flash" button behaves the same. Seen on INAV 9.0.1 and confirmed by a second user with the same board on 9.1.0-RC1. Reported in #11376.Cause
src/main/io/flashfs.c:72-77onmaintenance-10.x:flashfsEraseCompletely()sets the tail address to 0 in RAM without looking at the chip. The value the next boot shows comes fromflashfsIdentifyStartOfFreeSpace()(flashfs.c:500, called fromflashfsInit()at:583), so a failed erase reads asusedSize=0until reboot.src/main/drivers/flash_w25n.c:219-223:w25n_waitForReady()callsw25n_setTimeout()unconditionally.flashPartitionErase()(src/main/drivers/flash.c:313-317) callsflashWaitForReady(0)after every block erase, which replaces the 15 ms deadline armed atflash_w25n.c:306with one that has already expired, so the wait returns at once. The nextw25n_eraseSector()(flash_w25n.c:301-307) discards the result of its own ready-wait and sends write-enable and block-erase into a chip that is still busy. The NOR driver treats 0 as "use the armed deadline" (flash_m25p16.c:216).That loop only runs when the flash has more than one partition; a single FLASHFS partition takes the full-chip path (
flash.c:307-310,w25n_eraseCompletely()atflash_w25n.c:311-316), which already waits per block. The reporter'sflash_infolists a single partition, so the timeout defect alone does not account for that report; on that build this change alters whatflash_inforeports after the erase.Change
w25n_waitForReady()arms a new deadline only for a non-zero timeout and otherwise waits for the deadline the pending operation armed.w25n_eraseSector()returns without sending commands when the ready-wait fails and invalidates the cachedcurrentPageafter issuing the erase;w25n_eraseCompletely()waits for the last block.flashfsEraseCompletely()callsflashFlush()before the erase and afterwards, whenflashIsReady(), sets the tail address fromflashfsIdentifyStartOfFreeSpace(); a chip still erasing (NOR bulk erase) keeps the previous 0.Test
Not run on hardware or SITL. Cause verified by reading
flash_w25n.c:219-223andflash.c:313-317onmaintenance-10.x. Not built: the upstream "Build firmware" run for 9d112b9 is waiting for approval (https://github.com/iNavFlight/inav/actions/runs/34619673614) and the fork branch has no workflow runs. Qodo flagged the post-erase scan reading into a dirty W25N program buffer; commit 9d112b9 adds theflashFlush()before the erase for that. Compiled for all targets and the four SITL builds on the fork, green: https://github.com/Raffi1202/inav/actions/runs/34770680514Flash / RAM
Builds clean on all targets. No size comparison yet: the fork build has no baseline for this branch, and the upstream size report runs once CI is released for this PR.
Docs
No documentation change needed:
docs/Cli.mdanddocs/Blackbox.mddescribeflash_eraseand "erase flash" as erasing the chip; this change adds no setting and no new command.