#15700·betaflight

[low priority] flash_w25m.c: w25m_readBytes only chunks reads at die boundaries, not NAND page boundaries

Author: nerdCopterCreated Sep 15, 2026Updated Sep 15, 2026

AI Generated issue-ticket

Location

src/main/drivers/flash/flash_w25m.cw25m_readBytes.

Bug

The function splits a multi-die read only at die boundaries (dieSize), never at the underlying NAND page boundary:

c
for (rlen = length; rlen; rlen -= tlen) {
    int dieNumber = address / dieSize;
    uint32_t dieAddress = address % dieSize;
    tlen = MIN(dieAddress + rlen, dieSize) - dieAddress;

    w25m_dieSelect(fdevice->io.handle.dev, dieNumber);

    rbytes = dieDevice[dieNumber].vTable->readBytes(&dieDevice[dieNumber], dieAddress, buffer, tlen);

    if (!rbytes) {
        return 0;
    }

    address += tlen;
    buffer += tlen;
}

dieDevice[dieNumber].vTable->readBytes resolves to w25n_readBytes, which always clamps its own transfer to the current page and returns that clamped count, not the requested tlen. This wrapper checks only that rbytes is nonzero, then advances buffer/address by the full tlen regardless of how many bytes w25n_readBytes actually wrote. Any read that spans more than one NAND page silently leaves the buffer beyond the first page unfilled while reporting success.

Impact

Any caller requesting more than one NAND page (2048 bytes for W25N01G) in a single flashReadBytes call on a W25M02G-based target gets a buffer only partially filled, with no error indication — the function still returns the full requested length.

Fix

Split the read in w25m_readBytes at NAND page boundaries (not just die boundaries), and validate the returned byte count from each readBytes call before advancing the buffer, address, and remaining count — treat a short read as an error, not completion.

Low priority — flagging for tracking, not requesting immediate action.