Commit cb9bbfa
fix(flash/nand): NAND flash fixes; re-enable W25M02G on STELLARH7DEV (#1231)
* fix(flash/nand): fix 5 NAND flash bugs; re-enable W25M02G on STELLARH7DEV
Fixes #1209 #1216 #1226 #1228
#1226 — flashPartitionSet off-by-one (flash.c)
`flashPartitions == FLASH_MAX_PARTITIONS - 1` silently blocked the last
valid slot; change to `>= FLASH_MAX_PARTITIONS`.
#1216 — flashfsEraseAsync not wired to scheduler (fc_tasks.c)
BF 4.5-m `taskMain` calls `flashfsEraseAsync()` under `#ifdef USE_FLASHFS`.
EF was missing this call entirely; the async erase state machine
(`FLASHFS_ERASING`) would never advance, stalling the erase dialog on all
flash targets.
#1209 — NAND erase blocks scheduler (flashfs.c)
`flashfsEraseCompletely()` called `flashEraseCompletely()` for single-
partition full-chip erases. On NAND (W25M02G: 2048 blocks × ~15ms each =
~30 s), this blocked the scheduler and disconnected USB. NOR flash has a
hardware bulk-erase command that completes near-instantly; NAND does not.
Fix: gate the synchronous NOR path on `flashType == FLASH_TYPE_NOR`. NAND
always takes the async `FLASHFS_ERASING` sector-by-sector path through
`flashfsEraseAsync()` now wired via #1216 fix.
#1228a — w25n_pageProgramContinue only used buffers[0] (flash_w25n.c)
Multi-buffer writes (bufferCount==2, used by flashfs for wrap-around across
the circular write buffer) silently dropped buffers[1]. Added a second
static segment (`segmentsBuffer2`) and link it when bufferCount>=2; total
`bytesWritten` accumulated and returned/reported to callback correctly.
#1228b — w25n_readBytes used `length` instead of `transferLength` (flash_w25n.c)
The SPI and QuadSPI segments in `w25n_readBytes` passed `length` (unclamped)
instead of `transferLength` (page-boundary-clamped). Reads past a page
boundary returned data from the wrong region.
#1228c — w25n_readBBLUT cmd[4] had 2 uninitialised bytes (flash_w25n.c)
Changed `uint8_t cmd[4]; cmd[0]=...; cmd[1]=0;` to
`uint8_t cmd[2] = { W25N_INSTRUCTION_READ_BBM_LUT, 0 };`.
The W25N BBLUT command only needs 2 bytes; the extra 2 garbage bytes were
transmitted to the device, shifting the 4-byte BBLUT record parsing.
Re-enable W25M02G flash on STELLARH7DEV: the boot-hang (flashfsIdentifyStart-
OfFreeSpace on bad-state chip) was misdiagnosed — real root cause was pinio_box
reset wiring USER1-always-active to VTX. Flash disabled as workaround; now
correct with async erase in place.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(flash_w25n): revert segmentsBuffer2 wrap-around — BF parity
#1228a added segmentsBuffer2 to handle flashfs ring-buffer wrap-around
(bufferCount=2) in a single DMA call. BF does not have this: it writes
only buffers[0] and lets the ring buffer tail advance, so the wrapped
portion becomes a normal bufferCount=1 write on the next scheduler tick.
The EF addition created a stale-link bug:
spiLinkSegments(dev, segmentsBuffer, segmentsBuffer2) sets
segmentsBuffer[1].u.link -> segmentsBuffer2 on every wrap-around call.
On the next call with bufferCount=1 and page NOT yet full (line 779
branch), segmentsBuffer[1] is never reset. The SPI DMA follows the
stale link, reasserts CS, and sends segmentsBuffer2[0]'s stale bytes
as an unintended SPI transaction. The W25N01G interprets byte 0 as an
opcode -> premature PROGRAM_EXECUTE / WRITE_DISABLE / random state
corruption -> corrupted BBL page -> Blackbox Explorer gap.
Observed: exactly 2 gaps in a ~6-second BBL log on STELLARH7DEV
(W25M02G, SPI4). BF has no gaps under identical conditions.
Fix: drop segmentsBuffer2 entirely; always use a single segmentsBuffer
and spiLinkSegments(dev, programSegment, segmentsBuffer). Wrap-around
writes are handled transparently across two scheduler ticks as BF does.
Also removes lastDataSegment indirection and the bufferCount>=2 branch;
callbackArg uses bufferSizes[0] directly, matching BF's bytesWritten.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>1 parent 6e50925 commit cb9bbfa
5 files changed
Lines changed: 19 additions & 16 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
429 | 429 | | |
430 | 430 | | |
431 | 431 | | |
432 | | - | |
| 432 | + | |
433 | 433 | | |
434 | 434 | | |
435 | 435 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
886 | 886 | | |
887 | 887 | | |
888 | 888 | | |
889 | | - | |
| 889 | + | |
890 | 890 | | |
891 | 891 | | |
892 | 892 | | |
| |||
1041 | 1041 | | |
1042 | 1042 | | |
1043 | 1043 | | |
1044 | | - | |
1045 | | - | |
1046 | | - | |
1047 | | - | |
| 1044 | + | |
1048 | 1045 | | |
1049 | 1046 | | |
1050 | 1047 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
131 | 131 | | |
132 | 132 | | |
133 | 133 | | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
134 | 137 | | |
135 | 138 | | |
136 | 139 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
126 | 126 | | |
127 | 127 | | |
128 | 128 | | |
129 | | - | |
130 | | - | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
131 | 135 | | |
132 | 136 | | |
133 | 137 | | |
134 | | - | |
| 138 | + | |
135 | 139 | | |
136 | 140 | | |
137 | 141 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
99 | 99 | | |
100 | 100 | | |
101 | 101 | | |
102 | | - | |
103 | | - | |
104 | | - | |
105 | | - | |
106 | | - | |
107 | | - | |
108 | | - | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
109 | 108 | | |
110 | 109 | | |
111 | 110 | | |
| |||
0 commit comments