Skip to content

FW turn predictor: gate the arc turn coordinator off <=512KB flash targets - #11998

Closed
sensei-hacker wants to merge 4 commits into
iNavFlight:maintenance-10.xfrom
sensei-hacker:gate-fw-turn-arc-flash
Closed

sensei-hacker wants to merge 4 commits into
iNavFlight:maintenance-10.xfrom
sensei-hacker:gate-fw-turn-arc-flash

Conversation

@sensei-hacker

Copy link
Copy Markdown
Member

Summary

PR #11812 added a fixed-wing coordinated waypoint-turn system (the "arc turn coordinator"). Its geometry/state-machine code, concentrated almost entirely in one function (updateFwTurnArc(), ~440 lines), costs roughly 8KB of flash. On the STM32F722 target ZEEZF7V3 (512KB flash), that pushed FLASH1 over budget — CI on PR #11924 failed with region 'FLASH1' overflowed by 171 bytes on that target, unrelated to PR #11924's own change (which measured at 0 bytes delta on the same target).

This PR gates the arc coordinator behind a new USE_FW_TURN_PREDICTOR flag, added to the existing MCU_FLASH_SIZE > 512 feature-gate list in common.h (alongside USE_AUTO_TRANSITION etc.), so it's compiled out entirely on <=512KB flash targets.

Changes

  • src/main/target/common.h: add USE_FW_TURN_PREDICTOR to the MCU_FLASH_SIZE > 512 gate list.
  • src/main/navigation/navigation_fixedwing.c: wrap updateFwTurnArc(), getFwCoordinatedTurnRadius(), getFwTurnFeedForward(), their exclusive static state, and their call sites in #ifdef USE_FW_TURN_PREDICTOR. nav_fw_wp_turn_mode's DIRECT setting already has a no-op path through the arc coordinator, so gating it out and falling back to DIRECT behavior on affected targets revives nothing — it's the same code path DIRECT mode already took.
  • Deliberately not gated: updateFwEnergyBankGuard, updateFwLoiterArc/getFwStableLoiterRadius, applyFwRollInSmoothing. These are general fixed-wing improvements from the same PR, independent of wp_turn_mode, and stay compiled in on every flash size.
  • src/main/fc/settings.yaml: mark nav_fw_turn_ff_gain and nav_fw_wp_turn_max_lead_time condition: USE_FW_TURN_PREDICTOR (they're only read by the now-gated code, so they were previously settable-but-inert on affected targets — matches the existing USE_AUTO_TRANSITION convention in this file). Updated nav_fw_wp_turn_mode's description to note that its COORD_* values (the default is COORD_FLYBY) silently behave as DIRECT on <=512KB flash targets.
  • src/main/navigation/navigation.c: guard the two now-conditional settings' default-value initializers with the same flag.
  • docs/Settings.md regenerated via src/utils/update_cli_docs.py.

Testing

  • Builds: ZEEZF7V3 (512KB, gate off) links with FLASH1 485,667 B / 480 KB (98.81%, ~5.8KB of margin restored vs. the prior overflow). MATEKH743 (>512KB, gate on) links with FLASH1 797,267 B / 1792 KB (43.45%), confirming the feature stays fully compiled in on larger-flash targets. SITL also builds clean.
  • Code-level equivalence proof: confirmed via nm/objdump on the compiled navigation_fixedwing.c.o that when USE_FW_TURN_PREDICTOR is undefined, none of updateFwTurnArc, getFwTurnFeedForward, or their exclusive state symbols exist in the binary at all — so nav_fw_wp_turn_mode = DIRECT and = COORD_FLYBY are provably identical in control flow on gated builds, by construction, not just by runtime observation.
  • What I could not test: a live SITL flight of a fixed-wing waypoint mission with turns, to sanity-check the DIRECT-fallback flight behavior and loiter/RTH end-to-end. This was blocked by a SITL-HITL test harness issue (arming stays latched on ARMING_DISABLED_SENSORS_CALIBRATING | ARMING_DISABLED_NAVIGATION_UNSAFE / "WAITING FOR GPS FIX" once a nav-capable mode range is configured, despite feeding a valid GPS fix via MSP). I confirmed this reproduces identically on the unmodified base commit (before any change in this PR), so it's a pre-existing SITL test-infrastructure gap, not a regression from this change — but it means the actual in-flight turn behavior on a gated build hasn't been flight-tested by me, only proven equivalent at the code level. Requesting a maintainer or someone with working SITL/hardware HITL flight-test this before merge if that gap matters for confidence here.

Code Review

Reviewed with the inav-code-review agent. Findings addressed: added condition: to the two settings that become inert when gated (previously missing), and updated nav_fw_wp_turn_mode's description to surface the <=512KB fallback behavior rather than leaving it silent. No CRITICAL issues found; ifdef boundaries traced symbol-by-symbol and confirmed self-consistent (every gated symbol's only usages are themselves inside the same gate).

Related

Relates to #11812 (the feature this gates) and #11924 (where the ZEEZF7V3 overflow was first observed in CI, though unrelated to that PR's own change).

…2KB flash

PR iNavFlight#11812's coordinated-turn arc coordinator (updateFwTurnArc, ~440 lines)
and its direct helpers (getFwCoordinatedTurnRadius, getFwTurnFeedForward)
account for ~8KB of the feature's flash footprint, concentrated almost
entirely in one LTO-merged function. This alone is what pushed ZEEZF7V3
(STM32F722, 512KB flash) over its FLASH1 budget on later maintenance-10.x
commits (PR iNavFlight#11924's CI run reported a 171-byte overflow there).

wp_turn_mode's DIRECT setting (legacy heading-PID turn) already has a
no-op path through the arc coordinator, so gating this code out and
falling back to DIRECT behavior on <=512KB targets requires reviving
nothing. USE_FW_TURN_PREDICTOR is added to common.h's existing
"MCU_FLASH_SIZE > 512" gate list, alongside USE_AUTO_TRANSITION etc.

Deliberately NOT gated: updateFwEnergyBankGuard, updateFwLoiterArc/
getFwStableLoiterRadius, and applyFwRollInSmoothing. These are general
fixed-wing improvements independent of wp_turn_mode and apply to every
flash size.

Verified: ZEEZF7V3 FLASH1 490,743 B -> 484,703 B (-6,040 B). MATEKH743
(2048KB) keeps the feature compiled in (confirmed via preprocessor
replay, since LTO inlines the gated symbols away either way). No
conflict markers, no accidental deletions - a pure #ifdef wrap.
…DICTOR

nav_fw_turn_ff_gain and nav_fw_wp_turn_max_lead_time are only read by
code gated behind USE_FW_TURN_PREDICTOR (getFwTurnFeedForward and the
FLY_BY corner-cut block), so on <=512KB flash targets they were settable
but silently inert. condition: hides them there, matching the existing
USE_AUTO_TRANSITION-gated settings in this file.

Also updated nav_fw_wp_turn_mode's description to note that its COORD_*
values (COORD_FLYBY is the default) fall back to a plain DIRECT turn on
those same targets, since the setting itself stays selectable - flagged
by code review as worth surfacing since it affects the shipped default.

docs/Settings.md regenerated via src/utils/update_cli_docs.py.
…E_FW_TURN_PREDICTOR

The previous commit added condition: USE_FW_TURN_PREDICTOR to these two
settings.yaml entries, so their SETTING_*_DEFAULT macros are no longer
generated when the flag is undefined - breaking every <=512KB target
with "undeclared" errors in navConfig_t's PG_RESET_TEMPLATE. Neither
field is read anywhere outside the gated arc-coordinator code, so
leaving them zero-initialized when gated is a safe substitute.

Verified: ZEEZF7V3 links again (FLASH1 484,687 B, 98.61%), MATEKH743
unaffected (FLASH1 795,579 B, 43.36%, both settings still present).
@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

Disable fixed-wing arc turn prediction on ≤512 KB targets

🐞 Bug fix ⚙️ Configuration changes 📝 Documentation 🕐 20-40 Minutes

Grey Divider

AI Description

• Compile arc-turn prediction only on targets with more than 512 KB flash.
• Preserve DIRECT waypoint turns and independent fixed-wing improvements on constrained targets.
• Condition predictor-only settings and document coordinated-mode fallback behavior.
Diagram

graph TD
    A{"Flash > 512 KB?"} -->|Yes| B["Enable predictor"] --> C["Arc coordinator"]
    A -->|No| D["Omit predictor"] --> E["Direct turns"]
    B --> F["Expose settings"]
    D --> G["Hide settings"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Target-specific exclusion
  • ➕ Limits behavior changes to currently overflowing boards.
  • ➕ Avoids using flash capacity as a broad capability proxy.
  • ➖ Requires maintaining an expanding target blacklist.
  • ➖ Does not proactively protect other 512 KB targets from overflow.
2. Optimize the arc coordinator
  • ➕ Could retain coordinated turns across all supported targets.
  • ➕ Avoids feature differences based on flash capacity.
  • ➖ Requires substantial geometry and state-machine rework.
  • ➖ Carries greater regression risk and may not recover enough flash.

Recommendation: Use the centralized flash-capacity gate as the safest immediate fix. It follows existing optional-feature conventions, removes the complete predictor footprint, and preserves unrelated fixed-wing behavior; optimization can be pursued separately if coordinated turns become necessary on constrained targets.

Files changed (5) +38 / -11

Bug fix (2) +29 / -5
navigation.cGuard predictor setting defaults +2/-0

Guard predictor setting defaults

• Conditionally initializes predictor-only navigation fields so constrained builds do not reference settings omitted by generation.

src/main/navigation/navigation.c

navigation_fixedwing.cCompile out waypoint arc prediction on constrained targets +27/-5

Compile out waypoint arc prediction on constrained targets

• Wraps arc prediction, turn feed-forward, fly-by smoothing, exclusive state, resets, and call sites with USE_FW_TURN_PREDICTOR. Leaves loiter arcs, energy guarding, roll smoothing, and DIRECT waypoint behavior available on all targets.

src/main/navigation/navigation_fixedwing.c

Documentation (1) +3 / -3
Settings.mdDocument predictor availability and DIRECT fallback +3/-3

Document predictor availability and DIRECT fallback

• Documents that turn feed-forward and fly-by lead-time settings require more than 512 KB flash. Clarifies that coordinated turn modes behave as DIRECT on constrained targets.

docs/Settings.md

Other (2) +6 / -3
settings.yamlCondition predictor-only settings by flash capability +5/-3

Condition predictor-only settings by flash capability

• Adds USE_FW_TURN_PREDICTOR conditions to the feed-forward gain and maximum lead-time settings. Updates setting descriptions to explain target availability and coordinated-mode fallback behavior.

src/main/fc/settings.yaml

common.hEnable turn prediction only above 512 KB flash +1/-0

Enable turn prediction only above 512 KB flash

• Defines USE_FW_TURN_PREDICTOR inside the existing larger-flash optional-feature gate, excluding the feature from targets with 512 KB flash or less.

src/main/target/common.h

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

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Aircraft keep banking after loiter 🐞 Bug ≡ Correctness
Description
Gating updateFwTurnArc() also removes the only per-cycle assignment that clears fwArcActive,
while the ungated updateFwLoiterArc() can still set that flag. On targets with 512 KB flash or
less, leaving an established loiter or exceeding its release band makes the loiter function return
without clearing the flag, so cross-track correction remains suppressed and the stale arc-bank
command continues overriding the navigation controller.
Code

src/main/navigation/navigation_fixedwing.c[R1291-1293]

+#ifdef USE_FW_TURN_PREDICTOR
    updateFwTurnArc(deltaMicros);
+#endif
Evidence
The waypoint arc function clears fwArcActive at its start, but this PR conditionally removes its
call. The retained loiter controller sets the flag when established, yet its inactive and release
paths return without clearing it; downstream heading control then suppresses cross-track correction,
freezes the integrator, and replaces controller output with fwArcBankCmd whenever the stale flag
remains set.

src/main/navigation/navigation_fixedwing.c[715-744]
src/main/navigation/navigation_fixedwing.c[1163-1207]
src/main/navigation/navigation_fixedwing.c[1290-1294]
src/main/navigation/navigation_fixedwing.c[1381-1385]
src/main/navigation/navigation_fixedwing.c[1460-1479]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Compiling out `updateFwTurnArc()` removes the per-cycle reset of `fwArcActive`, although the retained loiter controller can set it. After an established loiter stops driving, stale arc state continues overriding normal fixed-wing navigation.

## Fix Focus Areas
- src/main/navigation/navigation_fixedwing.c[715-744]
- src/main/navigation/navigation_fixedwing.c[1163-1207]
- src/main/navigation/navigation_fixedwing.c[1290-1294]

## Recommended Fix
Move the per-cycle `fwArcActive = false` reset out of `updateFwTurnArc()` and place it immediately before the optional waypoint-arc update and unconditional loiter-arc update. This lets either controller assert activity during the current cycle while ensuring gated builds clear stale loiter activity when neither controller drives.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
Review mode: ⚖️ Balanced: This is a cross-file compile-time feature gate affecting fixed-wing navigation behavior, settings visibility/defaults, and multiple target configurations, so it warrants a complete careful review.

Grey Divider

Tip of the day
💡 Did you know, you can add REVIEW.md to your repo root and Qodo follows it on every PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment on lines +1291 to +1293
#ifdef USE_FW_TURN_PREDICTOR
updateFwTurnArc(deltaMicros);
#endif

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Aircraft keep banking after loiter 🐞 Bug ≡ Correctness

Gating updateFwTurnArc() also removes the only per-cycle assignment that clears fwArcActive,
while the ungated updateFwLoiterArc() can still set that flag. On targets with 512 KB flash or
less, leaving an established loiter or exceeding its release band makes the loiter function return
without clearing the flag, so cross-track correction remains suppressed and the stale arc-bank
command continues overriding the navigation controller.
Agent Prompt
## Issue description
Compiling out `updateFwTurnArc()` removes the per-cycle reset of `fwArcActive`, although the retained loiter controller can set it. After an established loiter stops driving, stale arc state continues overriding normal fixed-wing navigation.

## Fix Focus Areas
- src/main/navigation/navigation_fixedwing.c[715-744]
- src/main/navigation/navigation_fixedwing.c[1163-1207]
- src/main/navigation/navigation_fixedwing.c[1290-1294]

## Recommended Fix
Move the per-cycle `fwArcActive = false` reset out of `updateFwTurnArc()` and place it immediately before the optional waypoint-arc update and unconditional loiter-arc update. This lets either controller assert activity during the current cycle while ensuring gated builds clear stale loiter activity when neither controller drives.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@github-actions

Copy link
Copy Markdown

RAM / Flash usage vs. base commit cd0108b — commit b32ae7c

Using the nearest available size baseline — the PR's exact base commit has no stored baseline yet.

Target Flash Δ RAM Δ
MATEKF405 +32 B (+0.00%) CCM: ±0 B (±0.00%)
RAM: +32 B (+0.03%)
MATEKF722 ⚠️ -5648 B (-1.17%) ITCM_RAM: ±0 B (±0.00%)
RAM: -80 B (-0.09%)
TCM: ±0 B (±0.00%)
MATEKF765 +1152 B (+0.15%) DTCM_RAM: +136 B (+0.48%)
SRAM1: +88 B (+0.07%)
MATEKH743 +1416 B (+0.18%) D2_RAM: ±0 B (±0.00%)
DTCM_RAM: +116 B (+0.90%)
ITCM_RAM: -184 B (-1.12%)
RAM: +128 B (+0.09%)

See RAM/flash optimization guide for techniques to reduce usage.

@github-actions

Copy link
Copy Markdown

Test firmware build ready — commit b32ae7c

Download firmware for PR #11998

249 targets built. Find your board's .hex file by name on that page (e.g. MATEKF405SE.hex). Files are individually downloadable — no GitHub login required.

Development build for testing only. Use Full Chip Erase when flashing.

@sensei-hacker

Copy link
Copy Markdown
Member Author

Compare and contrast #11996

@b14ckyy

b14ckyy commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator

Flash comparison: this gating PR vs the behaviour-identical refactor (#11996)

Built all four states with the CI compiler (arm-none-eabi-gcc 13.2.1, RelWithDebInfo, LTO) on the fullest 512 KB targets from the #11924 CI ranking. B and C both sit directly on top of A, so the deltas are clean; D is 75 commits older and only serves as a "no feature at all" reference.

FLASH1, budget 491,520 B:

Target A B (#11996) C (#11998) D
ZEEZF7V3 497,539 overflow +6,019 496,823 overflow +5,303 491,507 (13 B free) 488,595
MATEKF722 485,979 485,199 479,947 477,287
MATEKF722SE 490,375 489,659 484,343
IFLIGHT_BLITZ_F722_X1_OSD 490,755 490,039 484,723
TMOTORF7V2 490,423 489,643 484,327
MAMBAF722_2022B 490,315 489,599 484,283

Per target: B−A = −716…−780 B, C−A = −6,032…−6,096 B (RAM −100 B), C−B = −5,252…−5,316 B. MATEKH743 is byte-identical under A and C, so the gate is off above 512 KB as intended. B+C combined was not built; arithmetically ZEEZF7V3 would land near 490.8 KB.

What the numbers say:

  1. maintenance-10.x does not link ZEEZF7V3 today (+6,019 B). The 171 B from the compass: add MAG debug mode for raw magnetometer logging #11924 CI run and the ~5.8 KB margin quoted in this PR's description both predate the blackbox: optionally log the second gyro on dual-IMU boards #11933 merge; on the current base this PR leaves 13 bytes on that board. The next merge of anything will overflow it again, with nothing left to gate.
  2. The refactor alone does not rescue ZEEZF7V3 and it never could: ~10 % of the feature's +8 KB is recoverable bit-exactly, the rest is the geometry itself. It does keep every other F722 target linking with 1.3–2.4 KB to spare, which matches the base.
  3. The gate removes the coordinated WP turn on every ≤512 KB board, not only on the one that overflows: COORD_* silently behaves as DIRECT on MATEKF722 & co., while guard, loiter arc and roll smoothing stay in. If the goal is only to unbreak ZEEZF7V3, #undef USE_FW_TURN_PREDICTOR in that board's target.h does the same with one line and keeps the feature on the boards that still fit. Either way the underlying problem is that the 512 KB class as a whole is at the wall on maintenance-10.x.

Refs and exact commands are recorded; happy to re-run on any target you want added.

@sensei-hacker

Copy link
Copy Markdown
Member Author

Follow-up: closed the testing gap noted above. A SITL WP-mission test (arm → fly DIRECT → fly COORD_FLYBY, comparing the FC's own desired_heading output) now runs to completion and confirms the two turn modes are behaviorally identical on this build (max diff 29/100 deg over 167 samples, within floating-point/timing noise), live-confirming the USE_FW_TURN_PREDICTOR gate's fallback is a true no-op — not just the static symbol-absence proof in the description.

DIRECT       PASS
COORD_FLYBY  PASS
desired_heading max diff: 29 centidegrees -> IDENTICAL (gate fallback confirmed)
POSHOLD: PASS   RTH: PASS
OVERALL: PASS

(The prior arming block was a SITL test-harness sequencing bug — HITL was enabled before gyro calibration finished — not a firmware issue; fixed in the test script only.)

@b14ckyy

b14ckyy commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator

I am running a 3 stage flash check as before on all F722 targets right now and report back.

removing the old code means removing the "Direct" option entirely? >That would mean no fallback and every turn will be an arc. Would need to force the FLYBY as fallback for the other two.

I am almost out of claude budget. Tomorrow when its reset, I will do a more intensive optimization check of INAV, starting with that Idea. Maybe We can find other so far undiscovered levers. I have the big 20x plan now and can let my worker agents run for hours to check possibilities.

@sensei-hacker

sensei-hacker commented Sep 21, 2026

Copy link
Copy Markdown
Member Author

removing the old code means removing the "Direct" option entirely? >That would mean no fallback and every turn will be an arc. Would need to force the FLYBY as fallback for the other two.

Yeah, that was my thought. Instead of having three algorithms, have two.
My gut feeling is that removing DIRECT wouldn't save much flash, but it might be worth 5-10 minutes to see if that's even worth exploring.

@b14ckyy

b14ckyy commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator

On it right now. Just a pure POC analysis.

Option 1: remove direct and remaining turn smoothing code and rely only on the 3 new methods (with 2 algorithms and one is just a reverse). and FlyOver would be the fallback as its closest to the "Direct" method.

Option 2: gate it for F722 only. so other boards keep the Direct option.

@sensei-hacker

sensei-hacker commented Sep 21, 2026

Copy link
Copy Markdown
Member Author

and rely only on the 3 new methods

I stand corrected -- we're looking at going from four algorithms to choose from, to three algorithms to choose from.

Just writing that sentence, gut feeling is is that four different choices on how to make a turn in a mission might be too many. :)

In a race, maybe you fly the turns for the gates a little differently in different courses. On a mission -- it kinda feels like three options might be enough? Without saying which three options there should be, but three choices seems like enough?

@b14ckyy

b14ckyy commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator

analysis just finished and there is no code that only DIRECT uses. its a simple PID carrot method that inav uses in general to hold course. So there is nothing to gain back.

But you are actually right. Even if it does not help anything. The Direct method as a selectable option doesn't do anything better except harder and more wind dependent turns. FLyOver is the smooth and controlled equivalent. Fallback will still be "DIRECT" if a prediction cannot get a reasonable turn path but having it selectable makes not much sense.

My suggestion:

  • we merge the refactor, there is no behavior change and its HITL validated
  • then based on that we do the gating but needs to be done on the refactored code
  • The gating should disable the coordinated turn methods and only show DIRECT on F722 for now. And for all other MCUs the DIRECT is hidden.
  • Then we have a ground to release RC1 on with a note for that limitation

I will look into flash optimization possibilities tomorrow. maybe we find old wasteful code somewhere. If we can find some flash somewhere, we can ungate F722 for RC2. If not we discuss what we can do or if we just exclude them entirely.

@b14ckyy

b14ckyy commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator

OK this is important: After the refactor I did there is literally just ONE FC in the F722 family that overflows. Every other FC still has room. Full report of the 86 Builds:

Flash report: all 86 STM32F722 (512 KB) targets, refactor #11996 vs gating #11998

Every target built from cmake/stm32f7.cmake's single 512 KB variant (target_stm32f722xe, 86 targets incl. variants), both states, same CI compiler (arm-none-eabi-gcc 13.2.1, RelWithDebInfo = -Os + LTO on this family). FLASH1 budget 491,520 B.

Both branch from the same maintenance-10.x head (d1a87ed6c); on that base, without either PR, the numbers are B + ~750 B (measured on six targets earlier: −716…−780 B for B).

The ten tightest targets

# Target B refactor (bytes / %) free B C gating (bytes / %) free C C−B
1 ZEEZF7V3 496,823 / 101.08 % overflow 5,303 491,507 / 100.00 % 13 −5,316
2 FLASHHOBBYF722 490,579 / 99.81 % 941 485,263 / 98.73 % 6,257 −5,316
3 IFLIGHT_BLITZ_F722_X1_OSD 490,039 / 99.70 % 1,481 484,723 / 98.62 % 6,797 −5,316
4 MATEKF722SE 489,659 / 99.62 % 1,861 484,343 / 98.54 % 7,177 −5,316
5 TMOTORF7V2 489,643 / 99.62 % 1,877 484,327 / 98.54 % 7,193 −5,316
6 MAMBAF722_2022B 489,599 / 99.61 % 1,921 484,283 / 98.53 % 7,237 −5,316
7 JHEMCUF722 488,875 / 99.46 % 2,645 483,559 / 98.38 % 7,961 −5,316
8 HAKRCKD722 488,267 / 99.34 % 3,253 482,951 / 98.26 % 8,569 −5,316
9 TMOTORF7 488,223 / 99.33 % 3,297 482,971 / 98.26 % 8,549 −5,252
10 AXISFLYINGF7PRO 488,207 / 99.33 % 3,313 482,891 / 98.24 % 8,629 −5,316

Whole family

  • Overflows with the refactor: 1 of 86 (ZEEZF7V3, +5,303 B). Overflows with the gating: 0, but ZEEZF7V3 keeps 13 bytes.
  • Six targets have less than 2 KB free with the refactor; the family median is 98.66 % full, the emptiest target (GEPRC_F722_AIO_UART3) 93.99 %.
  • Gating saves −5,252…−5,384 B flash and 80–96 B RAM on every target. On MATEKH743 it is byte-identical to the base (gate is off above 512 KB).
  • ZEEZF7V3 does not link on plain maintenance-10.x either (+6,019 B); before Fixed wing: predictive coordinated waypoint turns (Needs/Includes #11804)  #11812 merged it had 2.9 KB free, and blackbox: optionally log the second gyro on dual-IMU boards #11933 alone added ~3 KB since. The 171 B and the 5.8 KB margin quoted earlier both predate that merge.

"Remove DIRECT / the old turn smoothing" (measured, prototype only)

No 9.x turn-smoothing code survives; DIRECT is two OR-clauses that share the coordinator's "no tracking" early-return. Removing it entirely: MATEKF722 −16 B, MATEKH743 +240 B (-O2 inlining shift). Not a flash candidate; it would also renumber the stored wp_turn_mode enum (PG bump + migration change).

Reading

The refactor keeps the feature on 85 of 86 boards and unbreaks none; the gating unbreaks ZEEZF7V3 by 13 bytes and drops the coordinated WP turn on all 86. A ZEEZF7V3-only #undef USE_FW_TURN_PREDICTOR in its target.h would do the same for the one board that needs it. Either way the 512 KB class is at the wall on maintenance-10.x; the next feature merge re-overflows ZEEZF7V3 and puts FLASHHOBBYF722 next in line.

Full 86-row table (B/C bytes, %, RAM, deltas) available on request; raw build logs kept.

@b14ckyy

b14ckyy commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator

Why ZEEZF7V3 is 11.6 KB heavier than MATEKF722 and 12.8 KB heavier than its own sibling ZEEZF7V2

src/main/target/ZEEZF7/target.h builds the V3 variant for two board revisions at once and with both blackbox backends:

  • two IMU drivers for one IMU slot (ICM42688P and BMI270 on SPI3, autodetected per revision), ~2.2 KB versus the 0.5 KB MPU6000 of the V2;
  • SD card over SPI plus FlashFS with two flash-chip drivers (M25P16 NOR and W25N01G NAND). The SD/FAT stack alone is ~12.6 KB on F722; FlashFS with both chip drivers at least 3 KB visible in nm, realistically 4–6 KB after LTO folding. ZEEZF7V2 has only FlashFS, MATEKF722 only SD;
  • plus BMP388 as a third baro (~0.9 KB), MSP optical flow and rangefinder (~1.4 KB), PINIO/PINIOBOX, UART6, I2C3.

So the overflow is not the turn feature's doing and not fixable durably by gating it: it is one board carrying every driver either of its revisions or storage options could need.

Suggestion

Split ZEEZF7V3 into two target variants (by IMU revision, or by blackbox backend, whichever matches the actual hardware) instead of gating the coordinated turns for the whole 512 KB class. That gives the board 4–12 KB of headroom permanently and leaves the other 85 F722 targets with the feature they still fit. A per-board #undef USE_FW_TURN_PREDICTOR in ZEEZF7/target.h would be the fallback if the split is not wanted for 10.0. The 512 KB class as a whole is at the wall on maintenance-10.x regardless; we plan a broader pass on drivers compiled for unpopulated hardware next.

Full 86-row table and the per-driver nm sums are available on request.

@sensei-hacker

Copy link
Copy Markdown
Member Author

I see there is a ZEEZF7V3 20x20 and a ZEEZF7V3 30x30.
One has an SD card, the other has flash.

@b14ckyy

b14ckyy commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator

so lets split the target then? I can make a PR for that. ZEEZF7V3_20MM and ZEEZF7V3_30MM?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants