Skip to content

Optimize PG struct field ordering to eliminate alignment padding#11401

Draft
sensei-hacker wants to merge 16 commits intoiNavFlight:maintenance-10.xfrom
sensei-hacker:optimize/pg-struct-alignment
Draft

Optimize PG struct field ordering to eliminate alignment padding#11401
sensei-hacker wants to merge 16 commits intoiNavFlight:maintenance-10.xfrom
sensei-hacker:optimize/pg-struct-alignment

Conversation

@sensei-hacker
Copy link
Member

Summary

Reorder fields in four PG structs from largest-to-smallest type to eliminate internal alignment padding holes. No logic changes — field access by name is unaffected throughout the codebase (verified: MSP, settings, CMS all use named field access).

Changes

  • pidProfile_s: 292 → 272 bytes, 10 holes / 21 bytes eliminated, PG version 11→12
  • blackboxConfig_s: 16 → 12 bytes, 1 hole / 2 bytes eliminated, PG version 4→5
  • statsConfig_s: 20 → 16 bytes, 1 hole / 2 bytes eliminated, PG version 2→3
  • geozone_config_s: 20 → 16 bytes, 1 hole / 2 bytes eliminated, PG version 0→1

Result on MATEKF722: .pg_resetdata 1303→1275 bytes, text 470511→470491 bytes (-20 bytes flash).

Note: statsConfig version bump applies universally including targets without USE_ADC where the layout is unchanged. Those targets will lose saved stats on upgrade.

Testing

  • Builds successfully on MATEKF722
  • pahole confirms zero internal holes in all modified structs after change
  • No SITL/hardware runtime test performed; this is a mechanical struct reorder with no logic changes

mmosca and others added 16 commits December 16, 2024 00:21
Updated contact method for hardware feature requests.
SDMODEL SDH7 V2 flight controller with MPU6000 on SPI4 (CW270),
MAX7456 OSD on SPI2, SD card blackbox on SPI1, BMP280/MS5611 baro
and IST8310 mag on I2C1, 8 motor outputs across TIM2/3/5/8,
VCP + 6 UARTs (UART7 RX-only for ESC sensor).
…RT2 for onboard Bluetooth MSP

Remove the camera control timer output on PE9. Add config.c to wire
PINIO1/PINIO2 to USER1/USER2 mode boxes and preset UART2 for MSP at
115200 baud since it is connected to an onboard Bluetooth module.
…h7v2

New target: SDMODELH7V2 (STM32H743)
…ch-6

NEW_HARDWARE_POLICY.md: Use Discord rather than email
Removed HD_3016 resolution type from the enum.
…ero-special-case

Remove legacy hdzero special case
Add a workflow_run-triggered job that uploads each PR's firmware as
individually named release assets on iNavFlight/pr-test-builds, then
posts (or updates) a PR comment with a direct download link.

This avoids two limitations of GitHub Actions artifacts: the opaque
single-zip bundle, and the requirement for a GitHub login to download.

Requires a PR_BUILDS_TOKEN secret with Contents:write access to
iNavFlight/pr-test-builds.
- Add issues: write permission (required for github.rest.issues.* endpoints)
- Include fork repo name in concurrency key to prevent cross-fork cancellation
- Pin release tag to head_sha via --target flag
- Add parseInt radix and NaN validation for PR number
…t-builds

CI: publish PR test builds to iNavFlight/pr-test-builds
Multi-line shell string in the NOTES variable had unindented continuation
lines (**..., >...) that were less indented than the YAML block scalar
body, causing a parse error on every run.

Replace with printf + --notes-file to avoid multi-line strings in the
YAML block scalar entirely. Also moves ${{ }} expressions into env vars
rather than inline in the shell script.
Reorder fields in four PG structs from largest-to-smallest type to
eliminate internal padding holes created by misaligned fields.
Each modified PG version is incremented to force EEPROM reset on
firmware upgrade (required when struct layout changes).

Results on MATEKF722 (F722, flash-constrained target):
  .pg_resetdata: 1303 → 1275 bytes (-28 bytes)
  text total:  470511 → 470491 bytes (-20 bytes)

Structs optimized:
  pidProfile_s:     292 → 272 bytes (21 holes → 0), PG version 11→12
  blackboxConfig_s:  16 → 12 bytes  ( 2 holes → 0), PG version  4→5
  statsConfig_s:     20 → 16 bytes  ( 2 holes → 0), PG version  2→3
  geozone_config_s:  20 → 16 bytes  ( 2 holes → 0), PG version  0→1

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@qodo-code-review
Copy link
Contributor

ⓘ You are approaching your monthly quota for Qodo. Upgrade your plan

Review Summary by Qodo

Optimize struct alignment, add SDMODELH7V2 target, and improve CI/build distribution

✨ Enhancement 🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Reorder struct fields largest-to-smallest to eliminate alignment padding
  - pidProfile_s: 292→272 bytes (21 bytes saved)
  - blackboxConfig_s: 16→12 bytes (2 bytes saved)
  - statsConfig_s: 20→16 bytes (2 bytes saved)
  - geozone_config_s: 20→16 bytes (2 bytes saved)
• Add SDMODELH7V2 target (STM32H743 flight controller)
  - MPU6000 IMU on SPI4, MAX7456 OSD on SPI2, SD card on SPI1
  - BMP280/MS5611 baro and IST8310 mag on I2C1
  - 8 motor outputs, VCP + 6 UARTs with ESC sensor support
• Remove legacy HDZero special case and HD_3016 resolution mode
• Add CI workflow to publish PR test builds to external repository
Diagram
flowchart LR
  A["Struct Field Reordering"] -->|Eliminates padding| B["Flash savings: 20 bytes"]
  C["New SDMODELH7V2 Target"] -->|STM32H743| D["8 motors, 7 UARTs, OSD"]
  E["Remove HDZero Legacy Code"] -->|Simplification| F["Cleaner codebase"]
  G["PR Test Build Workflow"] -->|Automated distribution| H["iNavFlight/pr-test-builds"]
Loading

Grey Divider

File Changes

1. src/main/flight/pid.h ✨ Enhancement +37/-36

Reorder pidProfile_s fields by size

src/main/flight/pid.h


2. src/main/flight/pid.c ⚙️ Configuration changes +1/-1

Bump pidProfile PG version to 12

src/main/flight/pid.c


3. src/main/blackbox/blackbox.h ✨ Enhancement +1/-1

Reorder blackboxConfig_s fields by size

src/main/blackbox/blackbox.h


View more (13)
4. src/main/blackbox/blackbox.c ⚙️ Configuration changes +1/-1

Bump blackboxConfig PG version to 5

src/main/blackbox/blackbox.c


5. src/main/fc/stats.h ✨ Enhancement +1/-1

Reorder statsConfig_s fields by size

src/main/fc/stats.h


6. src/main/fc/stats.c ⚙️ Configuration changes +1/-1

Bump statsConfig PG version to 3

src/main/fc/stats.c


7. src/main/navigation/navigation.h ✨ Enhancement +1/-1

Reorder geozone_config_s fields by size

src/main/navigation/navigation.h


8. src/main/navigation/navigation_geozone.c ⚙️ Configuration changes +1/-1

Bump geozone_config PG version to 1

src/main/navigation/navigation_geozone.c


9. src/main/io/displayport_msp_osd.c 🐞 Bug fix +0/-30

Remove HDZero HD_3016 legacy mode function

src/main/io/displayport_msp_osd.c


10. src/main/target/SDMODELH7V2/target.h New target +183/-0

Define SDMODELH7V2 STM32H743 target configuration

src/main/target/SDMODELH7V2/target.h


11. src/main/target/SDMODELH7V2/target.c New target +45/-0

Configure timer hardware for 8 motor outputs

src/main/target/SDMODELH7V2/target.c


12. src/main/target/SDMODELH7V2/config.c New target +38/-0

Configure PINIO and Bluetooth MSP settings

src/main/target/SDMODELH7V2/config.c


13. src/main/target/SDMODELH7V2/CMakeLists.txt New target +1/-0

Add SDMODELH7V2 build configuration

src/main/target/SDMODELH7V2/CMakeLists.txt


14. .github/workflows/ci.yml ⚙️ Configuration changes +10/-0

Save and upload PR number artifact for CI

.github/workflows/ci.yml


15. .github/workflows/pr-test-builds.yml ✨ Enhancement +153/-0

New workflow to publish PR builds to external repository

.github/workflows/pr-test-builds.yml


16. docs/policies/NEW_HARDWARE_POLICY.md 📝 Documentation +1/-1

Update hardware request contact method to Discord

docs/policies/NEW_HARDWARE_POLICY.md


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Mar 6, 2026

Code Review by Qodo

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

Grey Divider


Action required

1. resolutionType_e values renumbered 📘 Rule violation ✓ Correctness
Description
Removing HD_3016 from resolutionType_e (without explicit numeric assignments) shifts the numeric
values sent in MSP_DP_OPTIONS, while the docs still publish the old mapping. This creates
divergent behavior/meaning between code and documentation and can break consumers that rely on the
documented values.
Code

src/main/io/displayport_msp_osd.c[R64-69]

typedef enum {          // defines are from hdzero code
    SD_3016,
    HD_5018,
-    HD_3016,           // Special HDZERO mode that just sends the centre 30x16 of the 50x18 canvas to the VRX
    HD_6022,           // added to support DJI wtfos 60x22 grid
    HD_5320            // added to support Avatar and BetaflightHD
} resolutionType_e;
Evidence
The compliance rule requires shared meaning/priority logic to remain consistent and documentation to
stay synchronized. The PR changes the resolutionType_e enum (removing HD_3016) which implicitly
renumbers subsequent values used in an MSP payload field, but the published enum documentation still
lists HD_3016 and the prior numeric mapping.

src/main/io/displayport_msp_osd.c[64-69]
src/main/io/displayport_msp_osd.c[156-160]
docs/development/msp/inav_enums_ref.md[4818-4824]
docs/development/msp/inav_enums.json[3290-3296]
Best Practice: Learned patterns

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

## Issue description
`resolutionType_e` had an enumerator removed (`HD_3016`) without explicit numeric assignments, which implicitly renumbers later values and can break the documented/on-wire MSP meaning. The docs under `docs/development/msp/` still publish the old mapping.

## Issue Context
`currentOsdMode` is sent in `MSP_DP_OPTIONS`, so the numeric value of `resolutionType_e` is part of an external interface. Documentation files currently still list `HD_3016` and the previous numeric IDs.

## Fix Focus Areas
- src/main/io/displayport_msp_osd.c[64-69]
- src/main/io/displayport_msp_osd.c[156-160]
- docs/development/msp/inav_enums_ref.md[4818-4824]
- docs/development/msp/inav_enums.json[3290-3296]

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



Remediation recommended

2. Unnecessary stats PG bump 🐞 Bug ⛯ Reliability
Description
PG_STATS_CONFIG is bumped to version 3 for all builds, but when USE_ADC is not defined the struct’s
conditional field is absent and the layout is likely unchanged. This forces stats resets on non-ADC
targets for little/no benefit.
Code

src/main/fc/stats.c[24]

+PG_REGISTER_WITH_RESET_TEMPLATE(statsConfig_t, statsConfig, PG_STATS_CONFIG, 3);
Evidence
The PG registration version is bumped unconditionally. The only conditional field in the struct is
gated by USE_ADC; therefore, on builds where USE_ADC is not set, the struct excludes
stats_total_energy and the remaining field set is the same independent of that conditional, making a
forced version bump potentially unnecessary (but still causes a reset).

src/main/fc/stats.c[20-34]
src/main/fc/stats.h[5-13]

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

### Issue description
`PG_STATS_CONFIG` version is bumped universally, which forces saved stats to reset even on builds where `USE_ADC` is disabled and the struct likely doesn’t change.

### Issue Context
The `stats_total_energy` field is the only `#ifdef USE_ADC` member in the struct; non-ADC builds exclude it.

### Fix Focus Areas
- src/main/fc/stats.c[20-34]
- src/main/fc/stats.h[5-13]

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


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

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