Skip to content

Send the full page address on 2Gbit W25N devices - #11916

Open
Raffi1202 wants to merge 1 commit into
iNavFlight:maintenance-10.xfrom
Raffi1202:fix/w25n-page-address
Open

Raffi1202 wants to merge 1 commit into
iNavFlight:maintenance-10.xfrom
Raffi1202:fix/w25n-page-address

Conversation

@Raffi1202

@Raffi1202 Raffi1202 commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Problem

#11376 reports that on a RADIOLINKF405 flash_erase prints "Done" and flash_info shows usedSize=0, but after a power cycle the old usedSize is back. That board has a 1 Gbit W25N01GV. While reading the driver for that report, a second defect turned up that affects only the 2 Gbit parts served by the same driver (W25N02KV on NEXUSX and ORBITH743, MX35LF2G): bit 16 of the page address is never sent, so every read, program and erase aimed at the upper 128 MB lands in the lower half. This PR fixes that defect only; the bytes sent to a W25N01GV are unchanged, so it does not close #11376.

Cause

src/main/drivers/flash_w25n.c:163 on maintenance-10.x: w25n_performCommandWithPageAddress() sends { command, 0, pageAddress >> 8, pageAddress }, a fixed zero followed by 16 address bits. The W25N01GV has 1024 blocks x 64 pages = 65536 pages (:38), which fits; the W25N02KV and MX35LF2G have 2048 blocks (:39-40), so page addresses reach 131071 and bit 16 is lost. All three callers go through this helper: block erase (:305), program execute (:345), page data read (:494). FLASHFS spans every sector (src/main/drivers/flash.c:217), so addresses above 128 MB are reached in normal logging.

Change

The first address byte now carries bits 23..16 of the page address instead of a constant zero, with a comment explaining why. On the W25N01GV those bits are zero for every valid page, so its wire sequence is byte-for-byte unchanged. No die select is added: the driver's geometry gives 2048 blocks per die for both 2 Gbit parts.

Test

Not run on hardware, and no CI run exists for this branch yet. Cause verified by reading flash_w25n.c:163 and the geometry table at :237-274 on maintenance-10.x. The byte layout matches Betaflight's driver, which sends (pageAddress >> 16) & 0xff in the same position: https://github.com/betaflight/betaflight/blob/master/src/main/drivers/flash/flash_w25n.c. Qodo review on 31d637f: 0 bugs.

Flash / RAM

Not measured yet. The upstream firmware CI has not been released for this PR, so no size report exists.

Docs

No documentation change needed: docs/Blackbox.md:125 and docs/development/targets/common-issues.md:361 already list the W25N02 as a 2 Gbit / 256 MB chip; the driver now matches that.

w25n_performCommandWithPageAddress() sent a fixed zero byte followed by 16
bits of page address. That is correct for the 1Gbit W25N01GV, which has 1024
blocks of 64 pages and therefore 65536 pages, but not for the 2Gbit W25N02KV
and MX35LF2G. Both have 2048 blocks of 64 pages, so page addresses run up to
131071 and the first address byte carries bit 16.

With the upper bit dropped, page data read, program execute and block erase
all addressed the lower half of the chip, so the upper half mirrored onto the
lower half: erasing a block in the upper half erased the wrong block, and the
data of the upper half was never reachable.

Pass bits 23..16 of the page address in the first address byte. On the
W25N01GV those bits are zero for every valid page address, so the instruction
sequence for that device is unchanged.

Found while investigating iNavFlight#11376
@Raffi1202
Raffi1202 marked this pull request as ready for review September 11, 2026 15:42
@qodo-code-review

Copy link
Copy Markdown
Contributor

ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Send full page addresses to 2 Gbit W25N flash devices

🐞 Bug fix 🕐 10-20 Minutes

Grey Divider

AI Description

• Preserve page-address bit 16 when commanding 2 Gbit W25N-compatible NAND devices.
• Prevent upper-half reads, programs, and erases from targeting lower-half pages.
• Keep command bytes unchanged for valid 1 Gbit device addresses.
Diagram

sequenceDiagram
    participant Ops as Flash Operations
    participant Addr as Address Command
    participant Bus as SPI Bus
    participant NAND as W25N Device
    Ops->>Addr: Read program or erase page
    Addr->>Addr: Encode bits 23 through 0
    Addr->>Bus: Send command and address
    Bus->>NAND: Transfer full page address
    NAND-->>Ops: Access intended page
Loading
High-Level Assessment

Serializing bits 23 through 16 in the existing three-byte address field is the protocol-correct and simplest approach. Conditional encoding by device geometry was considered unnecessary because valid W25N01GV addresses naturally leave the added byte zero, preserving its existing wire sequence.

Files changed (1) +4 / -1

Bug fix (1) +4 / -1
flash_w25n.cSerialize the complete NAND page address +4/-1

Serialize the complete NAND page address

• The shared page-address command helper now places bits 23 through 16 into the first address byte instead of always sending zero. This fixes page reads, program execution, and block erasure in the upper half of supported 2 Gbit devices while leaving valid W25N01GV commands unchanged.

src/main/drivers/flash_w25n.c

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Tip of the day
💡 Did you know, you can switch off images and animations for a plain-text comment

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@sensei-hacker sensei-hacker added this to the 10.0 milestone Sep 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants