Skip to content

feat: Add complete SITL (Software-In-The-Loop) build support, repo hygiene, and debug-only filter checks#1100

Open
nerdCopter wants to merge 13 commits intomasterfrom
sitl-fix
Open

feat: Add complete SITL (Software-In-The-Loop) build support, repo hygiene, and debug-only filter checks#1100
nerdCopter wants to merge 13 commits intomasterfrom
sitl-fix

Conversation

@nerdCopter
Copy link
Member

@nerdCopter nerdCopter commented Mar 24, 2026

SITL Build Fix, Repo Hygiene, and Debug-Only Filter Checks

Summary:
This PR enables full SITL (Software-In-The-Loop) build support for EmuFlight, eliminates all actionable compiler warnings, and improves repo hygiene by removing the SITL runtime artifact (eeprom.bin). It also adds a debug-only assertion to catch rare Kalman filter instability during development/testing, with no impact on production or hardware firmware.


Key Changes

1. SITL Compilation and Warning Fixes

  • Adds all necessary guards, stubs, and conditional compilation for SITL to build and run cleanly.
  • All EmuFlight source warnings are eliminated with targeted pragmas and code hygiene.
  • No impact on hardware builds; all changes are opt-in for SITL or test builds only.

2. Kalman Covariance Robustness (Debug-Only)

  • Adds a debug-only assertion (guarded by UNIT_TEST/SIMULATOR_BUILD) to catch negative variance in the Kalman filter during SITL or unit tests.
  • Clamp-to-zero for variance is always active (production-safe, prevents NaN propagation).
  • Assert is never compiled into production/flight firmware.

3. Repo Hygiene: eeprom.bin

  • Removes the SITL runtime config file eeprom.bin from the repository.
  • Adds eeprom.bin to .gitignore to prevent future accidental commits.
  • No effect on firmware or SITL operation; file is created at runtime as intended.

Validation

  • ✅ Unit tests pass (including Kalman filter tests with new assert).
  • ✅ SITL builds and runs (assert active in debug/SITL, never in production).
  • ✅ Hardware targets (e.g., STRIXF10) build and run with no changes to firmware logic.
  • ✅ eeprom.bin is no longer tracked in the repo.

Safety and Impact

  • All changes are production-safe and hardware-safe.
  • No flight logic is changed for hardware builds; only SITL/test builds gain extra debug checks.
  • Repo is now clean of SITL runtime artifacts.

For Reviewers

  • All changes are minimal, targeted, and traceable to specific SITL or warning fixes.
  • The debug assert for Kalman variance is a development aid only.
  • No risk to hardware or production firmware.

This PR is now up to date with all recent changes and hygiene improvements. See ./tmp/sitl-fix_deep_investigation.md for a full technical breakdown.

Summary by CodeRabbit

  • Bug Fixes

    • Improved compiler diagnostic handling and prevented NaNs in covariance/sqrt calculations.
    • Narrowed when GPS-rescue failsafe conversion applies; fixed out-of-range checks and volatile data visibility.
  • Improvements

    • Better OSD handling: no-op stubs when OSD is disabled to improve build/link robustness.
    • Ensured motor/sensor initialization uses consistent floating-point behavior and refined SITL system clock setup.
  • Chores

    • Ignore root-level eeprom.bin in repository.

@coderabbitai
Copy link

coderabbitai bot commented Mar 24, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adjusts conditional compilation for simulator/test builds, adds GCC diagnostic pragmas, fixes numeric/type consistency, provides non-OSD stubs, and changes several global linkage/externs across multiple source files; includes small math and safety tweaks in Kalman and SITL SystemCoreClock initialization.

Changes

Cohort / File(s) Summary
Atomic / Build
src/main/build/atomic.h, src/main/build/atomic.c
BASEPRI helper gating changed to exclude both UNIT_TEST and SIMULATOR_BUILD for register helpers and atomic_BASEPRI is now declared for `UNIT_TEST
Kalman / Math Fallbacks
src/main/common/kalman.c
Added <math.h> and non-ARM fallback arm_sqrt_f32; update_kalman_covariance() now clamps variance with fmaxf before sqrt and adds `UNIT_TEST
GCC Diagnostic Pragmas
src/main/drivers/io.c, src/main/sensors/acceleration.c, src/main/sensors/barometer.c, src/main/sensors/gyro.c
Scoped suppression/restore of -Wlogical-op and -Wpedantic warnings via #pragma GCC diagnostic push/ignored/.../pop; minor scoping added in gyro's case body.
OSD Stubs & API Guards
src/main/io/displayport_hdzero_osd.h, src/main/io/osd.c, src/main/io/osd.h
OSD APIs and djiWarningBuffer wrapped by USE_OSD; non-OSD builds get static inline no-op implementations and a stub djiWarningBuffer to preserve linkage.
Global Linkage / Externs
src/main/fc/fc_core.c, src/main/target/SITL/target.c, src/main/target/SITL/target.h
isRXDataNew changed to extern volatile (storage elsewhere); SystemCoreClock moved to a translation-unit definition (init to 500000000u) and header changed to extern.
Flight Math / Type Consistency
src/main/flight/mixer.c, src/main/flight/pid.c
Replaced double literals with float literals (1.0f, 0.003f) and ensured motorPwmProtocol is explicitly set in non-brushed branch.
Unused Attributes / Minor Annotations
src/main/flight/imu.c, src/main/sensors/voltage.c
Marked small static functions and voltageMeterAdcChannelMap with __attribute__((unused)).
Failsafe Compile Guard Narrowing
src/main/fc/config.c
Changed #if defined(USE_GPS) to #if defined(USE_GPS_RESCUE) for the failsafe procedure conversion block.
Other small changes
.gitignore
Added /eeprom.bin to ignore rules.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.70% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main changes: SITL build support, repo hygiene, and debug-only filter checks, which directly align with the pull request's core objectives and modifications.
Description check ✅ Passed The PR description provides comprehensive information covering summary, key changes, validation, safety considerations, and impact assessment, though it references an external file and does not strictly follow the template structure.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sitl-fix

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (2)
src/main/flight/imu.c (1)

200-208: Apply __attribute__((unused)) conditionally to avoid misleading compiler diagnostics.

Both applyAccError and applySensorCorrection are actively called on lines 346 and 348 when the code at line 331 (#if defined(SIMULATOR_BUILD) && defined(SKIP_IMU_CALC)) evaluates to false—which is the case in most build configurations. They only become unused in the specific scenario where both SIMULATOR_BUILD and SKIP_IMU_CALC are defined. Applying the attribute unconditionally suppresses legitimate compiler warnings in typical builds.

Consider either:

  1. Conditionally defining the attribute: #if defined(SIMULATOR_BUILD) && defined(SKIP_IMU_CALC) #defineMAYBE_UNUSED __attribute__((unused))#endif``
  2. Wrapping the function definitions in conditional compilation: #if !defined(SIMULATOR_BUILD) || !defined(SKIP_IMU_CALC)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/flight/imu.c` around lines 200 - 208, The functions applyAccError
and applySensorCorrection are annotated unconditionally with
__attribute__((unused)) which hides real-use diagnostics in normal builds;
change this so the attribute is only present when both SIMULATOR_BUILD and
SKIP_IMU_CALC are defined (or omit the attribute in builds where the functions
are used). Implement either a conditional macro (e.g., define MAYBE_UNUSED as
__attribute__((unused)) only when SIMULATOR_BUILD && SKIP_IMU_CALC) and apply
MAYBE_UNUSED to applyAccError/applySensorCorrection, or wrap the function
definitions themselves in `#if` !defined(SIMULATOR_BUILD) ||
!defined(SKIP_IMU_CALC) ... `#endif` so the functions are compiled normally when
they are actually referenced.
src/main/target/SITL/target.c (1)

58-60: Prefer integer literals over floating-point for integer constants.

Using 1e6 (a double literal) for an integer constant is non-idiomatic and may trigger -Wfloat-conversion warnings with stricter compiler settings. The static initialization also makes the redundant assignment at line 192 unnecessary.

♻️ Suggested improvement
 // System clock for SITL (fake 500MHz)
-uint32_t SystemCoreClock = 500 * 1e6;
+uint32_t SystemCoreClock = 500000000U;

And optionally remove the redundant assignment at line 192:

     clock_gettime(CLOCK_MONOTONIC, &start_time);
     printf("[system]Init...\n");
-    SystemCoreClock = 500 * 1e6; // fake 500MHz
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/target/SITL/target.c` around lines 58 - 60, Replace the
floating-point literal used to initialize SystemCoreClock with an integer
literal (e.g., use 500000000u or 500U * 1000000U) to avoid double-to-int
conversion and -Wfloat-conversion warnings; also remove the redundant later
assignment to SystemCoreClock (the duplicate initialization in the same
translation unit) so the static initialization is the single source of truth.
Ensure you update the symbol SystemCoreClock and eliminate the redundant
assignment that resets it elsewhere in this file.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/build/atomic.h`:
- Around line 42-45: The header declares extern uint8_t atomic_BASEPRI when
either UNIT_TEST or SIMULATOR_BUILD is defined, but atomic.c only defines
atomic_BASEPRI under UNIT_TEST; update atomic.c to also define (and initialize)
uint8_t atomic_BASEPRI when SIMULATOR_BUILD is defined so the declaration in
atomic.h matches the definition, i.e., add the same definition/initialization
guarded by defined(SIMULATOR_BUILD) (or combine the guards to defined(UNIT_TEST)
|| defined(SIMULATOR_BUILD)) around the atomic_BASEPRI definition in atomic.c to
prevent the linker error.

In `@src/main/fc/fc_core.c`:
- Line 137: The extern declaration for the shared flag isRXDataNew in fc_core.c
lacks the volatile qualifier present on its definition, which can allow the
compiler to optimize away real-time reads; update the declaration from "extern
bool isRXDataNew;" to "extern volatile bool isRXDataNew;" so both declaration
and the definition in fc_rc.c match and volatile semantics are preserved for all
reads/writes of isRXDataNew.

In `@src/main/flight/mixer.c`:
- Around line 103-107: The change forces dev.motorPwmProtocol to
PWM_TYPE_ONESHOT42 when USE_DSHOT is not defined, which alters the legacy
default (previously zero-init → PWM_TYPE_STANDARD); update the non-DSHOT branch
to explicitly set motorConfig->dev.motorPwmProtocol = PWM_TYPE_STANDARD instead
of PWM_TYPE_ONESHOT42 so the hardware-facing default behavior is preserved
(refer to motorConfig, dev.motorPwmProtocol, PWM_TYPE_ONESHOT42,
PWM_TYPE_STANDARD and the `#ifdef` USE_DSHOT block).

In `@src/main/io/displayport_hdzero_osd.h`:
- Around line 33-38: When USE_HDZERO_OSD may be defined without USE_OSD, add a
stub declaration/definition for hdzeroOsdDisplayPortInit so callers guarded only
by USE_HDZERO_OSD link correctly: declare the function under `#if`
defined(USE_HDZERO_OSD) and provide a static inline stub that returns NULL (or
equivalent empty displayPort_t*) when USE_OSD is not set, while keeping the
existing no-op static inline hdzeroOsdSerialProcess; update the header around
the hdzeroOsdDisplayPortInit and hdzeroOsdSerialProcess symbols to ensure both
have safe stubs when USE_OSD is absent.

In `@src/main/sensors/acceleration.c`:
- Line 25: The file acceleration.c currently uses '#pragma GCC diagnostic
ignored "-Wpedantic"' without a matching push, causing an unmatched pop later;
add a matching '#pragma GCC diagnostic push' immediately before the existing
'#pragma GCC diagnostic ignored "-Wpedantic"' near the top of acceleration.c and
restrict the push/ignore/pop block to only surround the specific header includes
that require the pedantic suppression (so the later '#pragma GCC diagnostic pop'
at the end of the file matches this push).

In `@src/main/sensors/barometer.c`:
- Line 24: Add a matching diagnostic push before the existing suppression:
insert a `#pragma` GCC diagnostic push immediately before the existing `#pragma` GCC
diagnostic ignored "-Wpedantic" (the current suppression near the top of
barometer.c) so the later `#pragma` GCC diagnostic pop has a matching push;
additionally, restrict the push/ignored region to the minimal block that needs
-Wpedantic (wrap only the specific includes or declarations that trigger the
warning between push/ignored and pop) rather than spanning the entire file.

In `@src/main/sensors/gyro.c`:
- Line 26: Add a matching `#pragma` GCC diagnostic push immediately before the
existing `#pragma` GCC diagnostic ignored "-Wpedantic" and move the corresponding
`#pragma` GCC diagnostic pop so it only surrounds the minimal region that requires
suppression (instead of spanning the whole file); locate the suppression near
the top of gyro.c (the line with `#pragma` GCC diagnostic ignored "-Wpedantic")
and ensure the push/pop pair brackets only the specific functions or blocks
(e.g., the gyro initialization/ISR or any functions that triggered -Wpedantic)
so the pop directly follows the end of that small region.

---

Nitpick comments:
In `@src/main/flight/imu.c`:
- Around line 200-208: The functions applyAccError and applySensorCorrection are
annotated unconditionally with __attribute__((unused)) which hides real-use
diagnostics in normal builds; change this so the attribute is only present when
both SIMULATOR_BUILD and SKIP_IMU_CALC are defined (or omit the attribute in
builds where the functions are used). Implement either a conditional macro
(e.g., define MAYBE_UNUSED as __attribute__((unused)) only when SIMULATOR_BUILD
&& SKIP_IMU_CALC) and apply MAYBE_UNUSED to applyAccError/applySensorCorrection,
or wrap the function definitions themselves in `#if` !defined(SIMULATOR_BUILD) ||
!defined(SKIP_IMU_CALC) ... `#endif` so the functions are compiled normally when
they are actually referenced.

In `@src/main/target/SITL/target.c`:
- Around line 58-60: Replace the floating-point literal used to initialize
SystemCoreClock with an integer literal (e.g., use 500000000u or 500U *
1000000U) to avoid double-to-int conversion and -Wfloat-conversion warnings;
also remove the redundant later assignment to SystemCoreClock (the duplicate
initialization in the same translation unit) so the static initialization is the
single source of truth. Ensure you update the symbol SystemCoreClock and
eliminate the redundant assignment that resets it elsewhere in this file.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 03107b9a-1fed-4e12-819f-e041295625d5

📥 Commits

Reviewing files that changed from the base of the PR and between f09313e and bff892a.

⛔ Files ignored due to path filters (1)
  • eeprom.bin is excluded by !**/*.bin
📒 Files selected for processing (19)
  • src/main/build/atomic.h
  • src/main/common/kalman.c
  • src/main/drivers/io.c
  • src/main/fc/config.c
  • src/main/fc/fc_core.c
  • src/main/flight/imu.c
  • src/main/flight/mixer.c
  • src/main/flight/pid.c
  • src/main/flight/servos.h
  • src/main/io/displayport_hdzero_osd.h
  • src/main/io/osd.c
  • src/main/io/osd.h
  • src/main/io/rcdevice_cam.h
  • src/main/sensors/acceleration.c
  • src/main/sensors/barometer.c
  • src/main/sensors/gyro.c
  • src/main/sensors/voltage.c
  • src/main/target/SITL/target.c
  • src/main/target/SITL/target.h

Comment on lines +33 to +38
#if defined(USE_OSD) && defined(USE_HDZERO_OSD)
displayPort_t *hdzeroOsdDisplayPortInit(void);
void hdzeroOsdSerialProcess(mspProcessCommandFnPtr mspProcessCommandFn);
#else
static inline void hdzeroOsdSerialProcess(mspProcessCommandFnPtr mspProcessCommandFn) { (void)mspProcessCommandFn; }
#endif
Copy link

@coderabbitai coderabbitai bot Mar 24, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if USE_HDZERO_OSD can be enabled independently of USE_OSD in any target

# Find target.h files that define USE_HDZERO_OSD
echo "=== Targets with USE_HDZERO_OSD ==="
rg -l 'USE_HDZERO_OSD' --glob '**/target.h'

# Check if those same files also define USE_OSD
echo -e "\n=== Checking if USE_OSD is also defined in those targets ==="
for f in $(rg -l 'define\s+USE_HDZERO_OSD' --glob '**/target.h'); do
    echo "File: $f"
    echo "  USE_HDZERO_OSD: $(rg -c 'define\s+USE_HDZERO_OSD' "$f" || echo 'not found')"
    echo "  USE_OSD: $(rg -c 'define\s+USE_OSD' "$f" || echo 'not found')"
done

# Check SITL target specifically
echo -e "\n=== SITL target configuration ==="
fd -t f 'target.h' --exec grep -l -i 'sitl' {} \; 2>/dev/null | head -5 | xargs -I {} sh -c 'echo "=== {} ===" && cat {}'

Repository: emuflight/EmuFlight

Length of output: 6458


🏁 Script executed:

# Verify the exact state of the header file
echo "=== Header file: src/main/io/displayport_hdzero_osd.h ==="
cat -n src/main/io/displayport_hdzero_osd.h | sed -n '30,40p'

# Check for the call sites mentioned
echo -e "\n=== fc_init.c around line 516 ==="
if [ -f src/main/fc/fc_init.c ]; then
  cat -n src/main/fc/fc_init.c | sed -n '510,525p'
else
  echo "File not found"
fi

echo -e "\n=== fc_tasks.c around line 164 ==="
if [ -f src/main/fc/fc_tasks.c ]; then
  cat -n src/main/fc/fc_tasks.c | sed -n '158,175p'
else
  echo "File not found"
fi

# Search for any definitions of USE_HDZERO_OSD in the entire codebase
echo -e "\n=== All occurrences of USE_HDZERO_OSD ==="
rg 'USE_HDZERO_OSD' --type c --type h -n | head -30

Repository: emuflight/EmuFlight

Length of output: 2704


🏁 Script executed:

# Check where USE_HDZERO_OSD is defined and its context
echo "=== common_fc_pre.h around USE_HDZERO_OSD definition ==="
rg -B 3 -A 3 'define USE_HDZERO_OSD' src/main/target/common_fc_pre.h

# Check where USE_OSD is defined
echo -e "\n=== Checking if USE_OSD is also defined in common_fc_pre.h ==="
rg 'define USE_OSD' src/main/target/common_fc_pre.h

# Check the context of USE_HDZERO_OSD in osd.c and cms.c
echo -e "\n=== USE_HDZERO_OSD in osd.c ==="
rg -B 2 -A 2 'USE_HDZERO_OSD' src/main/io/osd.c

echo -e "\n=== USE_HDZERO_OSD in cms.c ==="
rg -B 2 -A 2 'USE_HDZERO_OSD' src/main/cms/cms.c

Repository: emuflight/EmuFlight

Length of output: 1275


Missing stub for hdzeroOsdDisplayPortInit causes linker error when USE_HDZERO_OSD is defined without USE_OSD.

The call sites in fc_init.c (line 516) and fc_tasks.c (line 164) guard their calls with only #if defined(USE_HDZERO_OSD), but this header requires both USE_OSD && USE_HDZERO_OSD for the real declarations.

If USE_HDZERO_OSD is enabled without USE_OSD:

  • hdzeroOsdDisplayPortInit() has no declaration → linker error
  • hdzeroOsdSerialProcess() silently uses the no-op stub → VTX heartbeat detection is lost

Either add a stub for hdzeroOsdDisplayPortInit or update the call sites to require both macros.

Option 1: Add stub returning NULL
 `#if` defined(USE_OSD) && defined(USE_HDZERO_OSD)
 displayPort_t *hdzeroOsdDisplayPortInit(void);
 void hdzeroOsdSerialProcess(mspProcessCommandFnPtr mspProcessCommandFn);
 `#else`
+static inline displayPort_t *hdzeroOsdDisplayPortInit(void) { return NULL; }
 static inline void hdzeroOsdSerialProcess(mspProcessCommandFnPtr mspProcessCommandFn) { (void)mspProcessCommandFn; }
 `#endif`
Option 2: Update call sites to require both macros

In src/main/fc/fc_init.c (line 516):

-#if defined(USE_HDZERO_OSD)
+#if defined(USE_OSD) && defined(USE_HDZERO_OSD)
     if (!osdDisplayPort) {
         osdDisplayPort = hdzeroOsdDisplayPortInit();
     }

In src/main/fc/fc_tasks.c (line 164):

-#ifdef USE_HDZERO_OSD
+#if defined(USE_OSD) && defined(USE_HDZERO_OSD)
     // Capture HDZero messages to determine if VTX is connected
     hdzeroOsdSerialProcess(mspFcProcessCommand);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#if defined(USE_OSD) && defined(USE_HDZERO_OSD)
displayPort_t *hdzeroOsdDisplayPortInit(void);
void hdzeroOsdSerialProcess(mspProcessCommandFnPtr mspProcessCommandFn);
#else
static inline void hdzeroOsdSerialProcess(mspProcessCommandFnPtr mspProcessCommandFn) { (void)mspProcessCommandFn; }
#endif
`#if` defined(USE_OSD) && defined(USE_HDZERO_OSD)
displayPort_t *hdzeroOsdDisplayPortInit(void);
void hdzeroOsdSerialProcess(mspProcessCommandFnPtr mspProcessCommandFn);
`#else`
static inline displayPort_t *hdzeroOsdDisplayPortInit(void) { return NULL; }
static inline void hdzeroOsdSerialProcess(mspProcessCommandFnPtr mspProcessCommandFn) { (void)mspProcessCommandFn; }
`#endif`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/io/displayport_hdzero_osd.h` around lines 33 - 38, When
USE_HDZERO_OSD may be defined without USE_OSD, add a stub declaration/definition
for hdzeroOsdDisplayPortInit so callers guarded only by USE_HDZERO_OSD link
correctly: declare the function under `#if` defined(USE_HDZERO_OSD) and provide a
static inline stub that returns NULL (or equivalent empty displayPort_t*) when
USE_OSD is not set, while keeping the existing no-op static inline
hdzeroOsdSerialProcess; update the header around the hdzeroOsdDisplayPortInit
and hdzeroOsdSerialProcess symbols to ensure both have safe stubs when USE_OSD
is absent.

Copy link
Member Author

Choose a reason for hiding this comment

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

@coderabbitai, resolved?

Copy link

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the current state of the header file
echo "=== displayport_hdzero_osd.h ==="
cat src/main/io/displayport_hdzero_osd.h

# Check the call sites in fc_init.c
echo -e "\n=== fc_init.c around hdzeroOsdDisplayPortInit ==="
rg -n -B 3 -A 3 'hdzeroOsdDisplayPortInit\|USE_HDZERO_OSD' src/main/fc/fc_init.c | head -40

# Check the call sites in fc_tasks.c
echo -e "\n=== fc_tasks.c around USE_HDZERO_OSD ==="
rg -n -B 3 -A 3 'hdzeroOsdSerialProcess\|USE_HDZERO_OSD' src/main/fc/fc_tasks.c | head -30

Length of output: 1565


@nerdCopter — not quite, but it's effectively a non-issue in this PR's codebase.

The stub for hdzeroOsdDisplayPortInit is still missing from the #else branch of the header. However, after checking the call sites I originally cited:

  • src/main/fc/fc_init.c has no references to hdzeroOsdDisplayPortInit or USE_HDZERO_OSD
  • src/main/fc/fc_tasks.c has no references to hdzeroOsdSerialProcess or USE_HDZERO_OSD

Since there are no call sites in this branch that use #if defined(USE_HDZERO_OSD) (without USE_OSD) to invoke hdzeroOsdDisplayPortInit, the linker risk I flagged is currently zero. The missing stub is a latent issue for defensive completeness, but does not cause any build failure in this PR.

If you'd like to close this out cleanly and guard against future regressions, you can add the one-liner stub (Option 1 from my original suggestion):

`#else`
static inline displayPort_t *hdzeroOsdDisplayPortInit(void) { return NULL; }
static inline void hdzeroOsdSerialProcess(mspProcessCommandFnPtr mspProcessCommandFn) { (void)mspProcessCommandFn; }
`#endif`

Otherwise, I'm happy to mark this as resolved given there are no active call sites affected.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/main/common/kalman.c (1)

22-31: Remove the unused SITL sqrt fallback or use it consistently.

The helper added at Line 28 is never called because the non-ARM path uses sqrtf directly at Line 79. Keeping both paths adds dead code and drift risk.

♻️ Proposed cleanup
 `#ifdef` USE_ARM_MATH
 `#include` "arm_math.h"
-#else
-// Fallback for SITL and non-ARM targets
-static inline void arm_sqrt_f32(float x, float *out) {
-    *out = sqrtf(x);
-}
 `#endif`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/common/kalman.c` around lines 22 - 31, The fallback helper
arm_sqrt_f32 is unused while code directly calls sqrtf; either remove the unused
arm_sqrt_f32 function or replace all direct sqrtf usages with the wrapper
(arm_sqrt_f32) so both ARM and non-ARM paths use the same API. Locate the
fallback definition arm_sqrt_f32 and the direct sqrtf call(s) (e.g., the sqrtf
at the Kalman computation site) and either delete the fallback block and keep
sqrtf everywhere, or change the sqrtf calls to call arm_sqrt_f32(out) and ensure
the wrapper signature matches existing usage.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/common/kalman.c`:
- Around line 76-80: Clamp the variance before taking the sqrt on the non-ARM
path to avoid NaN propagation: when computing squirt for
kalmanFilterStateRate[axis].axisVar (used to compute r), replace direct
sqrtf(...) with sqrtf(fmaxf(kalmanFilterStateRate[axis].axisVar, 0.0f)) so
negative axisVar values become 0 (matching arm_sqrt_f32 behavior); ensure squirt
is computed this way wherever sqrtf is used for
kalmanFilterStateRate[axis].axisVar so r and the filter state are not corrupted.

---

Nitpick comments:
In `@src/main/common/kalman.c`:
- Around line 22-31: The fallback helper arm_sqrt_f32 is unused while code
directly calls sqrtf; either remove the unused arm_sqrt_f32 function or replace
all direct sqrtf usages with the wrapper (arm_sqrt_f32) so both ARM and non-ARM
paths use the same API. Locate the fallback definition arm_sqrt_f32 and the
direct sqrtf call(s) (e.g., the sqrtf at the Kalman computation site) and either
delete the fallback block and keep sqrtf everywhere, or change the sqrtf calls
to call arm_sqrt_f32(out) and ensure the wrapper signature matches existing
usage.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6a129ba1-3c9c-4d4b-a92e-2891ba6fdb1b

📥 Commits

Reviewing files that changed from the base of the PR and between bff892a and aa0d17a.

📒 Files selected for processing (1)
  • src/main/common/kalman.c

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/main/common/kalman.c (1)

24-31: Add negative-input handling to fallback arm_sqrt_f32 for semantic consistency with CMSIS.

The fallback at lines 28–30 returns void whereas CMSIS arm_sqrt_f32 returns arm_status and handles negative inputs. More importantly, in the same file, the #ifdef USE_ARM_MATH branch (line 77) calls the fallback directly without pre-validation, while the #else branch (line 79) explicitly guards against negative values with fmaxf(value, 0.0f). This inconsistency should be reconciled.

Proposed refactor
 `#ifdef` USE_ARM_MATH
 `#include` "arm_math.h"
 `#else`
 // Fallback for SITL and non-ARM targets
-static inline void arm_sqrt_f32(float x, float *out) {
-    *out = sqrtf(x);
+typedef enum {
+    ARM_MATH_SUCCESS = 0,
+    ARM_MATH_ARGUMENT_ERROR = -1
+} arm_status;
+
+static inline arm_status arm_sqrt_f32(float x, float *out) {
+    if (x < 0.0f) {
+        *out = 0.0f;
+        return ARM_MATH_ARGUMENT_ERROR;
+    }
+    *out = sqrtf(x);
+    return ARM_MATH_SUCCESS;
 }
 `#endif`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/common/kalman.c` around lines 24 - 31, The fallback arm_sqrt_f32
currently has a void signature and doesn't mirror CMSIS behavior; change it to
static inline arm_status arm_sqrt_f32(float x, float *out) and implement
CMSIS-like negative input handling: if x < 0 set *out = 0.0f and return
ARM_MATH_ARGUMENT_ERROR, otherwise set *out = sqrtf(x) and return
ARM_MATH_SUCCESS; update callers in this file that call arm_sqrt_f32 (the branch
that invokes it without pre-validation) to handle the returned arm_status if
needed, ensuring behavior is now consistent with the USE_ARM_MATH branch which
guards with fmaxf(value, 0.0f).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/sensors/barometer.c`:
- Line 23: Line 23 currently concatenates three preprocessor directives on one
physical line; split them so each directive is on its own line. Specifically,
put `#include` <math.h> on its own line, then `#pragma` GCC diagnostic push on the
next line, and then `#pragma` GCC diagnostic ignored "-Wpedantic" on the following
line (ensure proper newline/line endings so the preprocessor can parse them).

---

Nitpick comments:
In `@src/main/common/kalman.c`:
- Around line 24-31: The fallback arm_sqrt_f32 currently has a void signature
and doesn't mirror CMSIS behavior; change it to static inline arm_status
arm_sqrt_f32(float x, float *out) and implement CMSIS-like negative input
handling: if x < 0 set *out = 0.0f and return ARM_MATH_ARGUMENT_ERROR, otherwise
set *out = sqrtf(x) and return ARM_MATH_SUCCESS; update callers in this file
that call arm_sqrt_f32 (the branch that invokes it without pre-validation) to
handle the returned arm_status if needed, ensuring behavior is now consistent
with the USE_ARM_MATH branch which guards with fmaxf(value, 0.0f).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 033b9800-3608-4ce3-a045-76ea70415f7d

📥 Commits

Reviewing files that changed from the base of the PR and between aa0d17a and 303911f.

📒 Files selected for processing (7)
  • src/main/build/atomic.c
  • src/main/common/kalman.c
  • src/main/fc/fc_core.c
  • src/main/flight/mixer.c
  • src/main/sensors/acceleration.c
  • src/main/sensors/barometer.c
  • src/main/sensors/gyro.c
✅ Files skipped from review due to trivial changes (2)
  • src/main/flight/mixer.c
  • src/main/sensors/acceleration.c
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/sensors/gyro.c
  • src/main/fc/fc_core.c

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/main/common/kalman.c (1)

24-31: Align non-ARM arm_sqrt_f32 fallback with CMSIS-DSP API contract for future compatibility.

The fallback implementation returns void, while the actual CMSIS-DSP arm_sqrt_f32 returns arm_status. Although current callsites at src/main/common/maths.c:107 and src/main/common/kalman.c:78 ignore the return value, matching the signature prevents potential portability issues if future code checks the status.

Proposed compatibility refactor
 `#ifdef` USE_ARM_MATH
 `#include` "arm_math.h"
 `#else`
 // Fallback for SITL and non-ARM targets
-static inline void arm_sqrt_f32(float x, float *out) {
-    *out = sqrtf(x);
+typedef enum {
+    ARM_MATH_SUCCESS = 0,
+    ARM_MATH_ARGUMENT_ERROR = -1
+} arm_status;
+
+static inline arm_status arm_sqrt_f32(float x, float *out) {
+    if (!out) {
+        return ARM_MATH_ARGUMENT_ERROR;
+    }
+    if (x < 0.0f) {
+        *out = 0.0f;
+        return ARM_MATH_ARGUMENT_ERROR;
+    }
+    *out = sqrtf(x);
+    return ARM_MATH_SUCCESS;
 }
 `#endif`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/common/kalman.c` around lines 24 - 31, The fallback arm_sqrt_f32
currently returns void; change it to match the CMSIS-DSP API by returning
arm_status (use the same arm_status type or typedef it if missing) and return
ARM_MATH_SUCCESS after computing *out = sqrtf(x); update the fallback definition
(symbol: arm_sqrt_f32) so its signature and return value match CMSIS-DSP and
avoid future portability issues with callsites that may check the status.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/main/common/kalman.c`:
- Around line 24-31: The fallback arm_sqrt_f32 currently returns void; change it
to match the CMSIS-DSP API by returning arm_status (use the same arm_status type
or typedef it if missing) and return ARM_MATH_SUCCESS after computing *out =
sqrtf(x); update the fallback definition (symbol: arm_sqrt_f32) so its signature
and return value match CMSIS-DSP and avoid future portability issues with
callsites that may check the status.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5912d929-1885-420c-8876-200109997737

📥 Commits

Reviewing files that changed from the base of the PR and between 303911f and 8d5102b.

📒 Files selected for processing (1)
  • src/main/common/kalman.c

@nerdCopter
Copy link
Member Author

@coderabbitai, review

@coderabbitai
Copy link

coderabbitai bot commented Mar 24, 2026

@nerdCopter Sure, I'll review the changes in this PR!

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/main/target/SITL/target.c (1)

192-192: Comment wording is inaccurate about linkage.

Line 192 says “initialized as static,” but SystemCoreClock is not static (it has external linkage). Please reword to avoid confusion.

✏️ Suggested wording update
-    // SystemCoreClock initialized as static at declaration
+    // SystemCoreClock is initialized at declaration in this translation unit
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/target/SITL/target.c` at line 192, The comment "SystemCoreClock
initialized as static at declaration" is incorrect about linkage; update the
comment near the SystemCoreClock declaration in target.c to state that
SystemCoreClock is initialized at declaration and has external linkage (not
declared static), e.g., rephrase to "SystemCoreClock initialized at declaration
(external linkage)" or similar to avoid implying it is a static symbol.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/main/target/SITL/target.c`:
- Line 192: The comment "SystemCoreClock initialized as static at declaration"
is incorrect about linkage; update the comment near the SystemCoreClock
declaration in target.c to state that SystemCoreClock is initialized at
declaration and has external linkage (not declared static), e.g., rephrase to
"SystemCoreClock initialized at declaration (external linkage)" or similar to
avoid implying it is a static symbol.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e83b7ffd-9fe5-41a6-b331-59100a3141d4

📥 Commits

Reviewing files that changed from the base of the PR and between 8d5102b and 2aa1c24.

📒 Files selected for processing (3)
  • src/main/common/kalman.c
  • src/main/sensors/barometer.c
  • src/main/target/SITL/target.c
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/sensors/barometer.c

@nerdCopter
Copy link
Member Author

@coderabbitai, review . all prior AI feedback implemented when valid. including local AI feedback.

@coderabbitai
Copy link

coderabbitai bot commented Mar 25, 2026

@nerdCopter Sure! I'll kick off a full review of all the changes in this PR, taking into account that prior AI feedback has already been addressed.

✅ Actions performed

Full review triggered.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/fc/config.c (1)

255-259: ⚠️ Potential issue | 🟠 Major

Risk: Invalid failsafe config persists when migrating between GPS_RESCUE and non-GPS_RESCUE targets.

The new guard fixes a compilation issue but introduces a configuration-portability gap:

  • On targets with USE_GPS_RESCUE: FAILSAFE_PROCEDURE_GPS_RESCUE has enum value 2
  • On targets without USE_GPS_RESCUE: enum value 2 equals FAILSAFE_PROCEDURE_COUNT (the sentinel/invalid marker)

When a config saved on a GPS_RESCUE-enabled target is loaded on a target with USE_GPS but not USE_GPS_RESCUE, the stored numeric value 2 becomes invalid, but this block won't compile to correct it. Downstream code (switch statements, bounds checks) may not handle FAILSAFE_PROCEDURE_COUNT as a valid procedure, risking undefined failsafe behavior.

A numeric bounds check would handle all invalid values regardless of which features are compiled:

🛡️ Proposed fix using numeric bounds check
 `#if` defined(USE_GPS_RESCUE)
-        if (failsafeConfig()->failsafe_procedure == FAILSAFE_PROCEDURE_GPS_RESCUE) {
+        if (failsafeConfig()->failsafe_procedure >= FAILSAFE_PROCEDURE_COUNT) {
             failsafeConfigMutable()->failsafe_procedure = FAILSAFE_PROCEDURE_DROP_IT;
         }
 `#endif`

This approach catches any out-of-bounds value (including GPS_RESCUE on non-GPS_RESCUE targets) and is safe across all feature combinations.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/fc/config.c` around lines 255 - 259, The guarded fix using `#if`
defined(USE_GPS_RESCUE) leaves an out-of-range numeric enum value intact when
migrating configs between builds; replace the compile-time guard with a runtime
numeric bounds check on failsafeConfig()->failsafe_procedure (compare against
FAILSAFE_PROCEDURE_COUNT) and, if the value is >= FAILSAFE_PROCEDURE_COUNT, set
failsafeConfigMutable()->failsafe_procedure = FAILSAFE_PROCEDURE_DROP_IT so any
invalid/stale numeric value (including the GPS_RESCUE value when that enum is
absent) is normalized regardless of build flags.
🧹 Nitpick comments (1)
src/main/flight/mixer.c (1)

1062-1064: LGTM! Float literals correctly eliminate implicit conversion warnings.

The change to use 1.0f and 0.0f instead of double literals aligns with the PR objective of eliminating compiler warnings.

For complete consistency, consider also updating the initializations at lines 1037-1038 which still use double literals:

Optional consistency improvement
-    float maxMotor = -1000.0;
-    float minMotor = 1000.0;
+    float maxMotor = -1000.0f;
+    float minMotor = 1000.0f;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/flight/mixer.c` around lines 1062 - 1064, The float-literal change
around maxMotor, motorCorrection, and minMotor is correct; make the remaining
initializations in the same scope consistent by replacing any double literals
(e.g., 1.0, 0.0) used when initializing related variables (such as maxMotor,
minMotor, motorCorrection or nearby variables declared just above this logic)
with float literals (1.0f, 0.0f) so all floating-point constants in that
function use the 'f' suffix.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/sensors/gyro.c`:
- Line 653: Wrap the entire case YAW_SPIN_RECOVERY_AUTO block in braces so any
local declarations after the case label are scoped within the diagnostic
push/pop, and remove the second unmatched "#pragma GCC diagnostic pop" (the
trailing pop) so the single "#pragma GCC diagnostic push" is balanced; ensure
the diagnostic pop remains inside the newly braced case block and that this
change is applied for builds with USE_YAW_SPIN_RECOVERY enabled.

---

Outside diff comments:
In `@src/main/fc/config.c`:
- Around line 255-259: The guarded fix using `#if` defined(USE_GPS_RESCUE) leaves
an out-of-range numeric enum value intact when migrating configs between builds;
replace the compile-time guard with a runtime numeric bounds check on
failsafeConfig()->failsafe_procedure (compare against FAILSAFE_PROCEDURE_COUNT)
and, if the value is >= FAILSAFE_PROCEDURE_COUNT, set
failsafeConfigMutable()->failsafe_procedure = FAILSAFE_PROCEDURE_DROP_IT so any
invalid/stale numeric value (including the GPS_RESCUE value when that enum is
absent) is normalized regardless of build flags.

---

Nitpick comments:
In `@src/main/flight/mixer.c`:
- Around line 1062-1064: The float-literal change around maxMotor,
motorCorrection, and minMotor is correct; make the remaining initializations in
the same scope consistent by replacing any double literals (e.g., 1.0, 0.0) used
when initializing related variables (such as maxMotor, minMotor, motorCorrection
or nearby variables declared just above this logic) with float literals (1.0f,
0.0f) so all floating-point constants in that function use the 'f' suffix.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 825c81fd-fb06-40ee-9db1-4eafa36f14ac

📥 Commits

Reviewing files that changed from the base of the PR and between f09313e and 0ecbd11.

⛔ Files ignored due to path filters (1)
  • eeprom.bin is excluded by !**/*.bin
📒 Files selected for processing (20)
  • src/main/build/atomic.c
  • src/main/build/atomic.h
  • src/main/common/kalman.c
  • src/main/drivers/io.c
  • src/main/fc/config.c
  • src/main/fc/fc_core.c
  • src/main/flight/imu.c
  • src/main/flight/mixer.c
  • src/main/flight/pid.c
  • src/main/flight/servos.h
  • src/main/io/displayport_hdzero_osd.h
  • src/main/io/osd.c
  • src/main/io/osd.h
  • src/main/io/rcdevice_cam.h
  • src/main/sensors/acceleration.c
  • src/main/sensors/barometer.c
  • src/main/sensors/gyro.c
  • src/main/sensors/voltage.c
  • src/main/target/SITL/target.c
  • src/main/target/SITL/target.h

Resolve SITL compilation and linking failures:

- kalman.c: guard arm_math.h include for SIMULATOR_BUILD
- config.c: use USE_GPS_RESCUE guard instead of USE_GPS for failsafe enum
- mixer.c: guard PWM_TYPE_DSHOT600 with USE_DSHOT for simulator fallback
- atomic.h: provide C fallback for SIMULATOR_BUILD (no __ASM)
- osd.h/osd.c: conditional guards and stubs for disabled USE_OSD
- displayport_hdzero_osd.h: conditional stub for HDZERO when disabled
- servos.h: fix enum typedef syntax (missing typedef keyword)
- rcdevice_cam.h: extern declaration for switchStates
- fc_core.c: extern declaration for isRXDataNew
- SITL/target.h: extern SystemCoreClock (defined in target.c)
- SITL/target.c: add SystemCoreClock global definition

All changes preserve existing functionality on hardware targets and
support simulator compilation without modification to non-SITL code paths.
- Add GCC diagnostic pragmas to ignore -Wpedantic in acceleration.c, gyro.c, barometer.c
- Warnings stem from FALLTHROUGH macro + conditional blocks in switch statements
- Pragmas localized to affected files only; no code logic altered
- SITL now builds warning-free for flight code
- Hardware firmware unmodified
- io.c:373: suppress -Wlogical-op for intentional bounds check
- atomic.h:130: suppress -Wcpp warning about #warning extension
- Scoped pragmas preserve all other warnings

Skipped (non-viable):
- dyad.c warnings: external library (lib/main/), not modifying third-party
- lto-wrapper notes: linker informational, not real issues
- RWX segment warning: SITL-specific, harmless for simulator
Previous guard used undefined USE_SIMULATOR_BUILD, breaking hardware builds.
Changed to SIMULATOR_BUILD (the actual flag set by make system).

- Hardware builds: arm_math.h IS included (needed for arm_sqrt_f32)
- SITL builds: arm_math.h NOT included (not available in simulator)
- Kalman filter needs sqrt function: arm_sqrt_f32 (ARM NEON) or sqrtf (C fallback)
- Previous guard (#ifndef SIMULATOR_BUILD) broke hardware builds when USE_ARM_MATH not defined
- New guard (#ifdef USE_ARM_MATH) properly selects between optimized and fallback implementations
- Provides inline C wrapper for SITL: arm_sqrt_f32(x, &out) -> out = sqrtf(x)

Fixes undefined reference to 'arm_sqrt_f32' in hardware builds
Both SITL and hardware (FF_RACEPIT) now build successfully
Valid findings implemented:
1. atomic.c: Guard atomic_BASEPRI definition with SIMULATOR_BUILD to match declaration
   - Changed: #if defined(UNIT_TEST) → #if defined(UNIT_TEST) || defined(SIMULATOR_BUILD)

2. fc_core.c: Add volatile qualifier to isRXDataNew extern declaration
   - Matches definition in fc_rc.c; prevents unwanted compiler optimizations
   - Changed: extern bool → extern volatile bool

3. mixer.c: Preserve legacy PWM default (PWM_TYPE_STANDARD) for hardware
   - Use STANDARD when USE_DSHOT not defined (not ONESHOT42)
   - Maintains backward compatibility

4. acceleration.c, barometer.c, gyro.c: Add pragma diagnostic push/pop matching
   - Unmatched #pragma GCC diagnostic pop at end of files without corresponding push
   - Added: #pragma GCC diagnostic push before #pragma GCC diagnostic ignored

5. kalman.c: Clamp variance to avoid NaN in sqrtf on fallback path
   - Added fmaxf(value, 0.0f) clamping in non-ARM branch
   - Keeps r and filter state from being corrupted by negative sqrt

Skipped findings:
- displayport_hdzero_osd.h stub: declaration already exists; uses inline null stubs
- kalman.c arm_sqrt_f32: function IS used in ARM branch; direct sqrtf in fallback is OK after clamping

All tests pass: SITL and hardware (FF_RACEPIT) builds successful
- Remove redundant #ifdef USE_ARM_MATH branching in update_kalman_covariance
- Always call arm_sqrt_f32() wrapper instead of conditional sqrtf calls
  - ARM path: arm_sqrt_f32 uses optimized NEON arm_math.h implementation
  - SITL/fallback: arm_sqrt_f32 wrapper calls standard sqrtf(x)
- Single code path improves maintainability and ensures consistent behavior
- Preserves variance clamping (fmaxf(..., 0.0f)) to prevent NaN propagation

Both ARM and non-ARM targets use same API; no functional change
- Change fallback return type from void to arm_status
- Return ARM_MATH_SUCCESS to match CMSIS-DSP API contract
- Define arm_status enum in fallback block (ARM_MATH_SUCCESS, ARM_MATH_ARGUMENT_ERROR)
- Improves compatibility and allows future callers to check return status
- No functional change: existing callers ignore return value
- Both ARM (via arm_math.h) and fallback now have compatible signatures
Valid fixes applied:
1. sensors/barometer.c: Split concatenated preprocessor directives onto separate lines
   - Fixed: #include <math.h>#pragma → separate lines for clarity/parsing

2. target/SITL/target.c: Use integer literal for SystemCoreClock initialization
   - Changed: 500 * 1e6 (double conversion) → 500000000u (integer literal)
   - Removed: Redundant SystemCoreClock assignment in function (line 192)
   - Preserves: Initialization at declaration as single source of truth

3. common/kalman.c: Enhance fallback arm_sqrt_f32 with CMSIS error handling
   - Added: Negative input check returns ARM_MATH_ARGUMENT_ERROR (out = 0.0f)
   - Returns: ARM_MATH_SUCCESS for valid inputs
   - Matches: CMSIS-DSP API contract for portability

Skipped findings (non-viable):
- displayport_hdzero_osd.h stub: Adding stub caused LTO linker conflicts in SITL
  (Inline stubs with LTO + guarded calls create undefined reference errors)

All tests pass: SITL and hardware (FF_RACEPIT) compile successfully
No hardware firmware broken
- Changed: 'initialized as static at declaration' (misleading)
- To: 'initialized at declaration (external linkage)' (accurate)
- SystemCoreClock is extern (external linkage), not static
- Clarifies that symbol is accessible from other translation units
- Remove unmatched #pragma GCC diagnostic pop at line 653
- Wrap YAW_SPIN_RECOVERY_AUTO case block in braces
- Move const int declaration inside braced case scope
- Single diagnostic pop at end of function properly scopes -Wpedantic suppression
- Const declarations after case labels now properly scoped

Fixes compiler warning scoping for SITL builds with USE_YAW_SPIN_RECOVERY
Adds assert(variance > -1e-6f) in Kalman covariance update, guarded by UNIT_TEST/SIMULATOR_BUILD flags. Provides development-time visibility into rare filter instability while keeping production/flight firmware safe (clamp-to-zero always active). Tolerance of -1e-6f allows floating-point rounding.

Validated: unit tests pass, SITL builds, hardware (STRIXF10) builds successfully.
Removes eeprom.bin (SITL config file) from repo and adds it to .gitignore for proper repo hygiene. No effect on firmware or SITL operation.
@nerdCopter nerdCopter changed the title feat: Add complete SITL (Software-In-The-Loop) build support with compiler warning fixes feat: Add complete SITL (Software-In-The-Loop) build support, repo hygiene, and debug-only filter checks Mar 26, 2026
@nerdCopter
Copy link
Member Author

@coderabbitai, all resolved including nitpicks? review or full review as needed.
mark approved if valid.

@coderabbitai
Copy link

coderabbitai bot commented Mar 26, 2026

@nerdCopter Sure! I'll kick off a fresh full review across all changes to verify everything — including nitpicks — has been addressed. I'll follow up with approval if the review comes back clean.


🧠 Learnings used
Learnt from: nerdCopter
Repo: emuflight/EmuFlight PR: 0
File: :0-0
Timestamp: 2026-03-26T16:06:21.354Z
Learning: In the EmuFlight repository (emuflight/EmuFlight), the maintainer (nerdCopter) does not want follow-up GitHub issues created for GitHub Actions SHA pinning or cache key hardening suggestions. The preference is mutable version tags (e.g., v4, v5) and no issue tracking for this topic.
✅ Actions performed

Full review triggered.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/fc/config.c (1)

255-259: ⚠️ Potential issue | 🔴 Critical

Failsafe procedure sanitization is now skipped in non-USE_GPS_RESCUE builds.

At Line 255, the new guard prevents cleanup of stale EEPROM values when GPS rescue is not compiled. That can leave failsafeConfig()->failsafe_procedure out of range, and the failsafe switch (in src/main/flight/failsafe.c) has no default case for recovery. Please keep sanitization active via a range check that compiles in all targets.

🔧 Suggested fix
-#if defined(USE_GPS_RESCUE)
-        if (failsafeConfig()->failsafe_procedure == FAILSAFE_PROCEDURE_GPS_RESCUE) {
-            failsafeConfigMutable()->failsafe_procedure = FAILSAFE_PROCEDURE_DROP_IT;
-        }
-#endif
+        if (failsafeConfig()->failsafe_procedure >= FAILSAFE_PROCEDURE_COUNT
+#ifdef USE_GPS_RESCUE
+            || failsafeConfig()->failsafe_procedure == FAILSAFE_PROCEDURE_GPS_RESCUE
+#endif
+        ) {
+            failsafeConfigMutable()->failsafe_procedure = FAILSAFE_PROCEDURE_DROP_IT;
+        }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/fc/config.c` around lines 255 - 259, The current `#if` guard removes
failsafe procedure sanitization unless USE_GPS_RESCUE is defined, leaving
failsafeConfig()->failsafe_procedure potentially out of range; restore a
compile-time-independent range check: always validate
failsafeConfig()->failsafe_procedure and if it's not a known/valid enum value
(i.e., not in the defined FAILSAFE_PROCEDURE_* range), set it via
failsafeConfigMutable()->failsafe_procedure to a safe default such as
FAILSAFE_PROCEDURE_DROP_IT (or the existing GPS rescue fallback) while retaining
any GPS-specific override guarded by USE_GPS_RESCUE; update the code around
failsafeConfig()/failsafeConfigMutable() to perform this unconditional
validation so all targets compile with sanitization.
🧹 Nitpick comments (4)
src/main/flight/mixer.c (1)

1062-1064: Good fix for float literal consistency.

The 1.0f and 0.0f suffixes correctly avoid implicit double-to-float conversions. However, the initializations at lines 1037-1038 still use double literals:

float maxMotor = -1000.0;
float minMotor = 1000.0;

Consider updating these for full consistency.

♻️ Proposed fix for consistency
-    float maxMotor = -1000.0;
-    float minMotor = 1000.0;
+    float maxMotor = -1000.0f;
+    float minMotor = 1000.0f;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/flight/mixer.c` around lines 1062 - 1064, The float initializations
for maxMotor and minMotor use double literals; change their initializers to
float literals (e.g., use -1000.0f and 1000.0f) so the declarations float
maxMotor and float minMotor avoid implicit double-to-float conversions and match
the existing 1.0f/0.0f usage in the same function in mixer.c.
src/main/flight/pid.c (1)

753-753: Good fix for type consistency, but line 404 has the same pattern unfixed.

The 0.003f suffix correctly ensures float-precision arithmetic. However, the identical calculation at line 404 for dtermBoostMultiplier still uses 0.003 (double literal):

dtermBoostMultiplier = (pidProfile->dtermBoost * pidProfile->dtermBoost / 1000000) * 0.003;

Consider applying the same fix there for consistency.

♻️ Proposed fix for consistency
-    dtermBoostMultiplier = (pidProfile->dtermBoost * pidProfile->dtermBoost / 1000000) * 0.003;
+    dtermBoostMultiplier = (pidProfile->dtermBoost * pidProfile->dtermBoost / 1000000) * 0.003f;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/flight/pid.c` at line 753, The multiplication for
dtermBoostMultiplier uses a double literal (0.003) causing mixed-precision;
update the expression setting dtermBoostMultiplier that uses
pidProfile->dtermBoost to use a float literal (0.003f) to match the float
arithmetic used for errorMultiplier, ensuring consistent float-precision
calculations for dtermBoostMultiplier.
src/main/sensors/voltage.c (1)

132-143: Consider conditional compilation instead of __attribute__((unused)).

While the attribute suppresses the warning effectively, wrapping the array definition in #ifdef USE_ADC would be architecturally cleaner since the array is only referenced within that guard (line 157).

♻️ Alternative approach using conditional compilation
+#ifdef USE_ADC
 static const uint8_t voltageMeterAdcChannelMap[] __attribute__((unused)) = {
     ADC_BATTERY,
 `#ifdef` ADC_POWER_12V
     ADC_POWER_12V,
 `#endif`
 `#ifdef` ADC_POWER_9V
     ADC_POWER_9V,
 `#endif`
 `#ifdef` ADC_POWER_5V
     ADC_POWER_5V,
 `#endif`
 };
+#endif

Then remove the __attribute__((unused)) since the array would only be compiled when actually used.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/sensors/voltage.c` around lines 132 - 143, The array
voltageMeterAdcChannelMap is marked with __attribute__((unused)) to silence
warnings but is only needed when the USE_ADC conditional is active; remove the
__attribute__((unused)) and instead wrap the entire voltageMeterAdcChannelMap
definition in the same `#ifdef` USE_ADC / `#endif` conditional used where the array
is referenced so it is compiled only when used (keep the ADC_* entries
unchanged), ensuring no unused-warning and cleaner architecture.
src/main/common/kalman.c (1)

86-93: Consider moving the #include <assert.h> to the top of the file.

The variance clamping and debug assertion correctly address the prior review feedback about NaN prevention. However, placing #include <assert.h> inside a function body (line 89) is unconventional and may confuse readers or cause issues with some static analyzers.

Suggested refactor
 `#include` <string.h>
 `#include` <math.h>
+#if defined(UNIT_TEST) || defined(SIMULATOR_BUILD)
+#include <assert.h>
+#endif

 `#ifdef` USE_ARM_MATH

Then at line 88-92:

 `#if` defined(UNIT_TEST) || defined(SIMULATOR_BUILD)
-#include <assert.h>
     // Debug: catch unexpectedly large negative variance (suggests calculation bug)
     assert(kalmanFilterStateRate[axis].axisVar > -1e-6f);
 `#endif`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/common/kalman.c` around lines 86 - 93, Move the conditional include
for assert.h out of the function body and place it with the other includes at
the top of the file, keeping the same conditional guards (i.e., `#if`
defined(UNIT_TEST) || defined(SIMULATOR_BUILD) / `#include` <assert.h> / `#endif`)
so the debug assertion in the kalman variance block (where clampedVar is
computed from kalmanFilterStateRate[axis].axisVar and arm_sqrt_f32 is called to
set squirt) still compiles and runs unchanged; this keeps the assert available
for the runtime check without nesting an include inside the code block.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/main/fc/config.c`:
- Around line 255-259: The current `#if` guard removes failsafe procedure
sanitization unless USE_GPS_RESCUE is defined, leaving
failsafeConfig()->failsafe_procedure potentially out of range; restore a
compile-time-independent range check: always validate
failsafeConfig()->failsafe_procedure and if it's not a known/valid enum value
(i.e., not in the defined FAILSAFE_PROCEDURE_* range), set it via
failsafeConfigMutable()->failsafe_procedure to a safe default such as
FAILSAFE_PROCEDURE_DROP_IT (or the existing GPS rescue fallback) while retaining
any GPS-specific override guarded by USE_GPS_RESCUE; update the code around
failsafeConfig()/failsafeConfigMutable() to perform this unconditional
validation so all targets compile with sanitization.

---

Nitpick comments:
In `@src/main/common/kalman.c`:
- Around line 86-93: Move the conditional include for assert.h out of the
function body and place it with the other includes at the top of the file,
keeping the same conditional guards (i.e., `#if` defined(UNIT_TEST) ||
defined(SIMULATOR_BUILD) / `#include` <assert.h> / `#endif`) so the debug assertion
in the kalman variance block (where clampedVar is computed from
kalmanFilterStateRate[axis].axisVar and arm_sqrt_f32 is called to set squirt)
still compiles and runs unchanged; this keeps the assert available for the
runtime check without nesting an include inside the code block.

In `@src/main/flight/mixer.c`:
- Around line 1062-1064: The float initializations for maxMotor and minMotor use
double literals; change their initializers to float literals (e.g., use -1000.0f
and 1000.0f) so the declarations float maxMotor and float minMotor avoid
implicit double-to-float conversions and match the existing 1.0f/0.0f usage in
the same function in mixer.c.

In `@src/main/flight/pid.c`:
- Line 753: The multiplication for dtermBoostMultiplier uses a double literal
(0.003) causing mixed-precision; update the expression setting
dtermBoostMultiplier that uses pidProfile->dtermBoost to use a float literal
(0.003f) to match the float arithmetic used for errorMultiplier, ensuring
consistent float-precision calculations for dtermBoostMultiplier.

In `@src/main/sensors/voltage.c`:
- Around line 132-143: The array voltageMeterAdcChannelMap is marked with
__attribute__((unused)) to silence warnings but is only needed when the USE_ADC
conditional is active; remove the __attribute__((unused)) and instead wrap the
entire voltageMeterAdcChannelMap definition in the same `#ifdef` USE_ADC / `#endif`
conditional used where the array is referenced so it is compiled only when used
(keep the ADC_* entries unchanged), ensuring no unused-warning and cleaner
architecture.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 92f2dccb-746f-40df-bc04-740c385f0d24

📥 Commits

Reviewing files that changed from the base of the PR and between 07624e2 and 022bd41.

📒 Files selected for processing (19)
  • .gitignore
  • src/main/build/atomic.c
  • src/main/build/atomic.h
  • src/main/common/kalman.c
  • src/main/drivers/io.c
  • src/main/fc/config.c
  • src/main/fc/fc_core.c
  • src/main/flight/imu.c
  • src/main/flight/mixer.c
  • src/main/flight/pid.c
  • src/main/io/displayport_hdzero_osd.h
  • src/main/io/osd.c
  • src/main/io/osd.h
  • src/main/sensors/acceleration.c
  • src/main/sensors/barometer.c
  • src/main/sensors/gyro.c
  • src/main/sensors/voltage.c
  • src/main/target/SITL/target.c
  • src/main/target/SITL/target.h

@nerdCopter
Copy link
Member Author

@coderabbitai, nitpicks and outside diff resolved?

@coderabbitai
Copy link

coderabbitai bot commented Mar 26, 2026

@nerdCopter I'll kick off a fresh full review right now to verify that all nitpicks and any outside-diff concerns have been addressed. I'll follow up with approval if everything checks out clean.


🧠 Learnings used
Learnt from: nerdCopter
Repo: emuflight/EmuFlight PR: 0
File: :0-0
Timestamp: 2026-03-26T16:06:21.354Z
Learning: In the EmuFlight repository (emuflight/EmuFlight), the maintainer (nerdCopter) does not want follow-up GitHub issues created for GitHub Actions SHA pinning or cache key hardening suggestions. The preference is mutable version tags (e.g., v4, v5) and no issue tracking for this topic.

Learnt from: nerdCopter
Repo: emuflight/EmuFlight PR: 1099
File: .github/workflows/test.yml:21-38
Timestamp: 2026-03-26T14:11:50.623Z
Learning: In the EmuFlight repository (emuflight/EmuFlight), the maintainer prefers using mutable version tags (e.g., v4, v5) for GitHub Actions rather than pinning to full 40-character commit SHAs. Do not flag unpinned action versions as issues in this repository.
✅ Actions performed

Full review triggered.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/fc/config.c (1)

255-259: ⚠️ Potential issue | 🟠 Major

Keep sanitizing stale GPS-rescue failsafe values on non-rescue targets.

Line 255 compiles this rewrite out whenever USE_GPS_RESCUE is absent. On targets that still define USE_GPS but not rescue support, this block now removes BOXGPSRESCUE yet leaves a persisted numeric GPS-rescue failsafe_procedure untouched. That preserves an unsupported enum value in EEPROM. Sanitize by range/raw value here instead of only behind the rescue enum guard.

💡 Proposed fix
-#if defined(USE_GPS_RESCUE)
-        if (failsafeConfig()->failsafe_procedure == FAILSAFE_PROCEDURE_GPS_RESCUE) {
+        if (failsafeConfig()->failsafe_procedure >= FAILSAFE_PROCEDURE_COUNT
+#if defined(USE_GPS_RESCUE)
+            || failsafeConfig()->failsafe_procedure == FAILSAFE_PROCEDURE_GPS_RESCUE
+#endif
+        ) {
             failsafeConfigMutable()->failsafe_procedure = FAILSAFE_PROCEDURE_DROP_IT;
         }
-#endif
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/fc/config.c` around lines 255 - 259, The current conditional gated
by USE_GPS_RESCUE leaves a stale numeric FAILSAFE_PROCEDURE_GPS_RESCUE value in
EEPROM on targets that lack rescue support; update the sanitation in the block
that calls failsafeConfig() / failsafeConfigMutable() so it checks the raw
failsafe_procedure value against valid enum range or specific invalid value(s)
(including the GPS_RESCUE numeric value) and coerces it to
FAILSAFE_PROCEDURE_DROP_IT when out-of-range or set to the unsupported
GPS_RESCUE value, rather than only compiling this logic under the USE_GPS_RESCUE
guard.
🧹 Nitpick comments (1)
src/main/flight/imu.c (1)

200-200: Add explanatory comments for the __attribute__((unused)) annotations.

Both applyAccError (line 200) and applySensorCorrection (line 208) are actively called in normal builds (lines 346, 348), but these call sites are compiled out when SIMULATOR_BUILD && SKIP_IMU_CALC are both defined. The attributes correctly suppress warnings in that configuration, but marking actively-used functions as "unused" without explanation could confuse future maintainers.

Suggested clarifying comments
+// Note: marked unused to suppress warnings in SIMULATOR_BUILD+SKIP_IMU_CALC configs where call sites are compiled out
 static void __attribute__((unused)) applyAccError(quaternion *vAcc, quaternion *vError) {
+// Note: marked unused to suppress warnings in SIMULATOR_BUILD+SKIP_IMU_CALC configs where call sites are compiled out
 static void __attribute__((unused)) applySensorCorrection(quaternion *vError) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/flight/imu.c` at line 200, Add a short explanatory comment
immediately above the function declarations for applyAccError and
applySensorCorrection that explains why the __attribute__((unused)) is present:
note that these functions are invoked in normal builds but their call sites are
conditionally compiled out when SIMULATOR_BUILD && SKIP_IMU_CALC are defined, so
the attribute suppresses unused-function warnings in that configuration; include
the conditional macro names and mention the normal call sites (the runtime IMU
flow) so future maintainers understand the attribute’s purpose and can safely
remove or change it if the build logic changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/sensors/gyro.c`:
- Around line 1452-1458: The switch handling yaw_spin_recovery in
validateAndFixGyroConfig() can leave enabledFlag and threshold uninitialized for
unknown/stale EEPROM values; ensure a safe default by either initializing
enabledFlag=false and threshold=YAW_SPIN_RECOVERY_THRESHOLD_MIN before the
switch or adding a switch default that sets enabledFlag=false and threshold to a
safe clamped value (e.g., YAW_SPIN_RECOVERY_THRESHOLD_MIN or constrained between
YAW_SPIN_RECOVERY_THRESHOLD_MIN and YAW_SPIN_RECOVERY_THRESHOLD_MAX) so that
yawSpinRecoveryEnabled and yawSpinRecoveryThreshold always receive defined
values.

---

Outside diff comments:
In `@src/main/fc/config.c`:
- Around line 255-259: The current conditional gated by USE_GPS_RESCUE leaves a
stale numeric FAILSAFE_PROCEDURE_GPS_RESCUE value in EEPROM on targets that lack
rescue support; update the sanitation in the block that calls failsafeConfig() /
failsafeConfigMutable() so it checks the raw failsafe_procedure value against
valid enum range or specific invalid value(s) (including the GPS_RESCUE numeric
value) and coerces it to FAILSAFE_PROCEDURE_DROP_IT when out-of-range or set to
the unsupported GPS_RESCUE value, rather than only compiling this logic under
the USE_GPS_RESCUE guard.

---

Nitpick comments:
In `@src/main/flight/imu.c`:
- Line 200: Add a short explanatory comment immediately above the function
declarations for applyAccError and applySensorCorrection that explains why the
__attribute__((unused)) is present: note that these functions are invoked in
normal builds but their call sites are conditionally compiled out when
SIMULATOR_BUILD && SKIP_IMU_CALC are defined, so the attribute suppresses
unused-function warnings in that configuration; include the conditional macro
names and mention the normal call sites (the runtime IMU flow) so future
maintainers understand the attribute’s purpose and can safely remove or change
it if the build logic changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6af26e5c-2ddf-4a71-9254-4f45d3c39d2e

📥 Commits

Reviewing files that changed from the base of the PR and between 07624e2 and 022bd41.

📒 Files selected for processing (19)
  • .gitignore
  • src/main/build/atomic.c
  • src/main/build/atomic.h
  • src/main/common/kalman.c
  • src/main/drivers/io.c
  • src/main/fc/config.c
  • src/main/fc/fc_core.c
  • src/main/flight/imu.c
  • src/main/flight/mixer.c
  • src/main/flight/pid.c
  • src/main/io/displayport_hdzero_osd.h
  • src/main/io/osd.c
  • src/main/io/osd.h
  • src/main/sensors/acceleration.c
  • src/main/sensors/barometer.c
  • src/main/sensors/gyro.c
  • src/main/sensors/voltage.c
  • src/main/target/SITL/target.c
  • src/main/target/SITL/target.h

Comment on lines +1452 to +1458
case YAW_SPIN_RECOVERY_AUTO: {
enabledFlag = true;
const int overshootAllowance = MAX(maxYawRate / 4, 200); // Allow a 25% or minimum 200dps overshoot tolerance
threshold = constrain(maxYawRate + overshootAllowance, YAW_SPIN_RECOVERY_THRESHOLD_MIN, YAW_SPIN_RECOVERY_THRESHOLD_MAX);
break;
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add a safe default for unknown yaw_spin_recovery values.

validateAndFixGyroConfig() does not clamp this field, so a stale EEPROM value can miss every case here. In that path enabledFlag and threshold stay uninitialized, then Lines 1460-1461 copy undefined data into yawSpinRecoveryEnabled and yawSpinRecoveryThreshold.

💡 Proposed fix
     switch (gyroConfig()->yaw_spin_recovery) {
     case YAW_SPIN_RECOVERY_OFF:
         enabledFlag = false;
         threshold = YAW_SPIN_RECOVERY_THRESHOLD_MAX;
         break;
     case YAW_SPIN_RECOVERY_ON:
         enabledFlag = true;
         threshold = gyroConfig()->yaw_spin_threshold;
         break;
     case YAW_SPIN_RECOVERY_AUTO: {
         enabledFlag = true;
         const int overshootAllowance = MAX(maxYawRate / 4, 200); // Allow a 25% or minimum 200dps overshoot tolerance
         threshold = constrain(maxYawRate + overshootAllowance, YAW_SPIN_RECOVERY_THRESHOLD_MIN, YAW_SPIN_RECOVERY_THRESHOLD_MAX);
         break;
     }
+    default:
+        enabledFlag = false;
+        threshold = YAW_SPIN_RECOVERY_THRESHOLD_MAX;
+        break;
     }

Also applies to: 1460-1463

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/sensors/gyro.c` around lines 1452 - 1458, The switch handling
yaw_spin_recovery in validateAndFixGyroConfig() can leave enabledFlag and
threshold uninitialized for unknown/stale EEPROM values; ensure a safe default
by either initializing enabledFlag=false and
threshold=YAW_SPIN_RECOVERY_THRESHOLD_MIN before the switch or adding a switch
default that sets enabledFlag=false and threshold to a safe clamped value (e.g.,
YAW_SPIN_RECOVERY_THRESHOLD_MIN or constrained between
YAW_SPIN_RECOVERY_THRESHOLD_MIN and YAW_SPIN_RECOVERY_THRESHOLD_MAX) so that
yawSpinRecoveryEnabled and yawSpinRecoveryThreshold always receive defined
values.

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.

1 participant