Repository navigation
Conversation
The D-cache has been off on F7 since 2017 ("Disable F7 I/D-caches for
now"), so every constant and table read from flash pays the AXIM wait
states. On a MAMBAF722 2022B the PID task drops from 104 to 84 us on
average with it on.
DMA_RAM becomes a real section on F7, as on H7 and AT32: SRAM2 (16 KB) is
carved out of RAM in each chip linker script and the MPU makes the whole
bank shareable, which the Cortex-M7 does not cache. The DShot burst buffer
and the ADC buffer join the buffers already tagged DMA_RAM; the ADC buffer
is cleared at init, since the section is not zeroed at startup.
SD over SDIO (MATEKF765, MATEKF765SE) gets what H7 already has: the afatfs
cache and the MSC bounce buffer 32-byte aligned, the alignment check no
longer skipped on F7, and the buffer invalidated before a read as well as
after it. The cache maintenance by address works on whole lines.
After a config write the config area is invalidated in the D-cache, so
the reload reads flash: the erase leaves the old lines cached, and
Cortex-M7 erratum 1259864 (ES0334 2.1.1) can return stale data after
write-through stores, which is what flash programming does.
|
ⓘ 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 QodoEnable F7 D-cache with DMA buffers in non-cacheable SRAM2
AI Description
Diagram
High-Level Assessment
Files changed (21)
|
Code Review by Qodo
1.
|
A write refused before the transfer (block size, or the alignment check that F7 now runs too) left TXCplt set, so the card read as busy for good. Set it only right before the DMA starts, and clear it if the start fails. The optional multi-block write cache is now 32-byte aligned as well, so it passes that check if someone enables it.
|
RAM / Flash usage vs. base commit
See RAM/flash optimization guide for techniques to reduce usage. |
|
Test firmware build ready — commit Download firmware for PR #12119 251 targets built. Find your board's
|
iNavFlight#12119 turns the F7 D-cache on and makes DMA_RAM an uncached SRAM2 region. A ring left in cached RAM could then hand the CPU a line it cached before the stream filled it. The rings go in DMA_RAM, as on H7; on F7 that is plain RAM until iNavFlight#12119, so on its own this changes nothing. Not seen to fail at 115200: FLYWOOF722PRO with iNavFlight#12119 and the GPS sending on the interrupt had 0-1 errors per boot with the rings in cached RAM and in DMA_RAM alike.
MSP DisplayPort and the serial gimbal swap their own TX buffer into the port after opening it. On H7 that buffer is in AXI SRAM, which the CPU caches, so the stream sends what is in RAM rather than what was just written. Kakute H7 Mini with the GPS port given such a buffer (a test patch): the u-blox never got its configuration (3 timeouts, no navigation messages); with this, a navigation message every 120 ms and 0 errors over 3 reboots. On F7 every ring is cached once iNavFlight#12119 turns its D-cache on: FLYWOOF722PRO with iNavFlight#12119 had 11-14 GPS errors and no fix on every boot, and 0 with this. The lines the transfer covers are written back first. Without a D-cache, or on the uncached D2 rings, that does nothing.
The F7 UART receive rings of iNavFlight#12033 are compiled only then; without the D-cache the port's own ring does.
On F7 DMA_RAM is plain RAM until iNavFlight#12119 turns the D-cache on and makes it an uncached SRAM2 section, so until then each ring only duplicated the port's own, 256 B per UART with a receive stream. They are compiled only where build_config.h says DMA_RAM is uncached (DMA_RAM_UNCACHED, set together with the D-cache), so either PR can go in first.
The F7 D-cache has been off since 2017 (39997f0, "Disable F7 I/D-caches for now"). F7 runs its code from flash
over AXIM: instructions go through the I-cache, but every constant and table the code reads as data pays the flash
wait states again (7 at 216 MHz). H7 already runs with the D-cache on, because its DMA buffers sit in
DMA_RAM, aregion the MPU makes shareable, which the Cortex-M7 does not cache. This PR does the same on F7.
DMA_RAMbecomes a real section on F7, as on H7 and AT32:.DMA_RAM (NOLOAD)instm32_flash_f7_split.ld,placed in SRAM2 (16 KB). F722 and F745 carve SRAM2 out of their RAM region; F765 already had it.
memprot_stm32f7xx.c: one MPU region over the whole SRAM2 bank, shareable, set up before the caches are enabled.It uses H7's
memprot_hal.c, now built for F7 too.USE_DSHOT_DMAR) and the ADC buffer move intoDMA_RAM. They join the per-port DShotbuffers, the keep-alive buffer and the LED strip buffer, which were already tagged. A NOLOAD section is not zeroed
at startup, so the ADC buffer is cleared at init, and a burst buffer is cleared when its timer gets its first
motor (a channel that drives no motor has to read zero).
The cache maintenance by address works on whole lines, so an unaligned sector would lose its last bytes on a
write. On the current image the afatfs cache happened to be aligned; on the base it was not.
the old lines in the cache. Cortex-M7 erratum 1259864 (ES0334 2.1.1, "data corruption when using data cache
configured in write-through") can also return stale data after a sequence of write-through stores, and flash
programming is exactly that: flash is the only write-through memory in the default map.
Measured
Three boots per image,
tasks40 s after boot, same config on both images.Size,
maintenance-10.x3f9fde4 -> this branchAll 107 F7 targets build. Across them, the fullest SRAM2 is at 34 % and the fullest RAM at 52 %.
The cost is RAM: SRAM2 now holds only DMA buffers. The RAM left for everything else shrinks by 16 KB minus what
moved (MAMBAF722_2022B: 101 104 -> 90 120 B free).
Testing
On a MAMBAF722_2022B and a Flywoo F722 Pro V2 (FLYWOOF722PRO image):
Every value read back right, and the last one survived a reboot;
steps while disarmed and read MSP_ANALOG on each step. Both boards read the same with and without this PR:
Not tested yet, and testers are welcome:
Open PRs that touch the same thing
array on every MCU. That covers what this PR does for F7 in
asyncfatfs.c, so whichever lands second keepsafatfs: count only the cache sectors that can take data, and size the cache per MCU family #12057's version of those three spots.
rings go in
DMA_RAM, built only where it is uncached: this PR setsDMA_RAM_UNCACHEDtogether with theD-cache (4d2c700), so the two can go in either order. Both came after trying them together with this PR: before, the GPS on a FLYWOOF722PRO
had 11-14 errors and no fix on every boot, from the transmit side. With every UART on DMA (serial: DMA on every UART, the stream picked at runtime where the target names none #12129) merged too:
FLYWOOF722PRO SRAM2 4672 B of 16 KB, MAMBAF722_2022B 7488 B.
DMA_RAM. Merged with this PR, ITCM overflows by24 bytes on KAKUTEF7 and KAKUTEF7HDV, although each one alone fits. With asyncfatfs: keep afatfs_poll out of the ITCM scheduler #12118 (afatfs_poll out of ITCM) on top,
the three together use 15 328 / 15 456 B.