Skip to content

[BACKPORT] arch/arm/stm32h7: invalidate dcache after aligned SDMMC RX DMA#389

Merged
dakejahl merged 1 commit into
PX4:px4_firmware_nuttx-10.3.0+from
yangrui9501:backport/sdmmc-dcache
Jul 24, 2026
Merged

[BACKPORT] arch/arm/stm32h7: invalidate dcache after aligned SDMMC RX DMA#389
dakejahl merged 1 commit into
PX4:px4_firmware_nuttx-10.3.0+from
yangrui9501:backport/sdmmc-dcache

Conversation

@yangrui9501

Copy link
Copy Markdown
Contributor

Backport of apache/nuttx#19506 (open, not yet merged upstream at the
time of this backport).

Fixes a D-cache coherency bug in the STM32H7 SDMMC aligned RX DMA
path: the aligned completion branch in stm32_recvdma() never
invalidated the destination buffer after DMA completion, only
before it started in stm32_dmarecvsetup(). On the Cortex-M7 the
cache can speculatively prefetch into that buffer between the
pre-DMA invalidate and DMA completion, leaving stale lines that
shadow the freshly-written data.

Reproduced and hardware-verified on a PX4 FMUv6C board: MAVLink
ULog downloads were corrupted in 32-byte, cache-line-aligned
windows that were byte-for-byte identical to the previous 512-byte
SD sector — the exact signature of a stale cache line. See the
upstream PR for full forensic detail and verification (including a
byte-for-byte identical 5.8 MB download after the fix).

… DMA

The aligned direct-DMA receive path only invalidated the destination
buffer before the transfer in stm32_dmarecvsetup(). On the Cortex-M7
the cache can speculatively prefetch into that cacheable buffer
between the pre-DMA invalidate and DMA completion, leaving stale
lines that shadow the data just written by the IDMA, so the CPU
reads a previously cached sector instead of the freshly received
data.

Invalidate again in stm32_recvdma() once the aligned transfer
completes, before the buffer is consumed. The buffer and length are
cache-line aligned on this path, so no adjacent memory is affected.

This matches the STM32 AN4839 guidance that a cache invalidate is
required after DMA completion and before the CPU reads the updated
region, not only before the transfer starts. A related instance of
the same "invalidate too early" defect on STM32H7 SPI DMA is tracked
in apache/nuttx#11594.

Root-caused on a PX4 FMUv6C (STM32H743) board where MAVLink ULog
downloads were intermittently corrupted: forensic diffing showed
corrupted windows were exactly 32 bytes (the D-cache line size),
cache-line aligned, and byte-for-byte equal to the previous 512-byte
SD sector cached in the FAT single-sector buffer. Disabling the
D-cache made the corruption disappear, isolating the defect to cache
coherency. After this fix, downloaded files matched the source file
byte-for-byte (sha256 identical) across a 5.8 MB log spanning
thousands of sectors.

Backport of apache/nuttx#19506 (upstream fix, not yet merged at the
time of this backport).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Yang-Rui Li <yang77567789@gmail.com>
@yangrui9501

Copy link
Copy Markdown
Contributor Author

For reviewers who'd like to independently verify the corruption pattern described above, I've attached ulog_evidence.zip containing two files from the same download session (renamed for clarity; both are otherwise unmodified):

File Source sha256 (prefix) Result
reference_clean.ulg Copied directly off the SD card (also byte-identical to what an unaffected/fixed firmware downloads over MAVLink) 6da25f82… Correct
corrupted_download.ulg Downloaded over MAVLink through the buggy firmware (pre-fix) ec8a03f1… Corrupted

Running:

cmp reference_clean.ulg corrupted_download.ulg

reproduces the diffs referenced in the hex dump above — every difference falls in a 32-byte, cache-line-aligned window whose content matches reference_clean.ulg at offset - 512 (the previous SD sector), which is the signature this patch fixes.

ulog_evidence.zip

@dakejahl dakejahl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the fix!

@dakejahl
dakejahl merged commit 60da95f into PX4:px4_firmware_nuttx-10.3.0+ Jul 24, 2026
dakejahl pushed a commit to PX4/PX4-Autopilot that referenced this pull request Jul 24, 2026
See PX4/NuttX#389


Assisted-by: Claude:claude-sonnet-5

Signed-off-by: Yang-Rui Li <yang77567789@gmail.com>
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