feat: Add complete SITL (Software-In-The-Loop) build support, repo hygiene, and debug-only filter checks#1100
feat: Add complete SITL (Software-In-The-Loop) build support, repo hygiene, and debug-only filter checks#1100nerdCopter wants to merge 13 commits intomasterfrom
Conversation
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdjusts 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
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related issues
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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
applyAccErrorandapplySensorCorrectionare 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 bothSIMULATOR_BUILDandSKIP_IMU_CALCare defined. Applying the attribute unconditionally suppresses legitimate compiler warnings in typical builds.Consider either:
- Conditionally defining the attribute:
#if defined(SIMULATOR_BUILD) && defined(SKIP_IMU_CALC)#defineMAYBE_UNUSED __attribute__((unused))#endif``- 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(adoubleliteral) for an integer constant is non-idiomatic and may trigger-Wfloat-conversionwarnings 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
⛔ Files ignored due to path filters (1)
eeprom.binis excluded by!**/*.bin
📒 Files selected for processing (19)
src/main/build/atomic.hsrc/main/common/kalman.csrc/main/drivers/io.csrc/main/fc/config.csrc/main/fc/fc_core.csrc/main/flight/imu.csrc/main/flight/mixer.csrc/main/flight/pid.csrc/main/flight/servos.hsrc/main/io/displayport_hdzero_osd.hsrc/main/io/osd.csrc/main/io/osd.hsrc/main/io/rcdevice_cam.hsrc/main/sensors/acceleration.csrc/main/sensors/barometer.csrc/main/sensors/gyro.csrc/main/sensors/voltage.csrc/main/target/SITL/target.csrc/main/target/SITL/target.h
| #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 |
There was a problem hiding this comment.
🧩 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 -30Repository: 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.cRepository: 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 errorhdzeroOsdSerialProcess()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.
| #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.
There was a problem hiding this comment.
🧩 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.chas no references tohdzeroOsdDisplayPortInitorUSE_HDZERO_OSDsrc/main/fc/fc_tasks.chas no references tohdzeroOsdSerialProcessorUSE_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.
There was a problem hiding this comment.
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
sqrtfdirectly 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
📒 Files selected for processing (1)
src/main/common/kalman.c
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/main/common/kalman.c (1)
24-31: Add negative-input handling to fallbackarm_sqrt_f32for semantic consistency with CMSIS.The fallback at lines 28–30 returns
voidwhereas CMSISarm_sqrt_f32returnsarm_statusand handles negative inputs. More importantly, in the same file, the#ifdef USE_ARM_MATHbranch (line 77) calls the fallback directly without pre-validation, while the#elsebranch (line 79) explicitly guards against negative values withfmaxf(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
📒 Files selected for processing (7)
src/main/build/atomic.csrc/main/common/kalman.csrc/main/fc/fc_core.csrc/main/flight/mixer.csrc/main/sensors/acceleration.csrc/main/sensors/barometer.csrc/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
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/main/common/kalman.c (1)
24-31: Align non-ARMarm_sqrt_f32fallback with CMSIS-DSP API contract for future compatibility.The fallback implementation returns
void, while the actual CMSIS-DSParm_sqrt_f32returnsarm_status. Although current callsites atsrc/main/common/maths.c:107andsrc/main/common/kalman.c:78ignore 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
📒 Files selected for processing (1)
src/main/common/kalman.c
|
@coderabbitai, review |
|
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
🧹 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
SystemCoreClockis notstatic(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
📒 Files selected for processing (3)
src/main/common/kalman.csrc/main/sensors/barometer.csrc/main/target/SITL/target.c
🚧 Files skipped from review as they are similar to previous changes (1)
- src/main/sensors/barometer.c
|
@coderabbitai, review . all prior AI feedback implemented when valid. including local AI feedback. |
|
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
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 | 🟠 MajorRisk: 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_RESCUEhas enum value2- On targets without
USE_GPS_RESCUE: enum value2equalsFAILSAFE_PROCEDURE_COUNT(the sentinel/invalid marker)When a config saved on a GPS_RESCUE-enabled target is loaded on a target with
USE_GPSbut notUSE_GPS_RESCUE, the stored numeric value2becomes invalid, but this block won't compile to correct it. Downstream code (switch statements, bounds checks) may not handleFAILSAFE_PROCEDURE_COUNTas 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.0fand0.0finstead 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
⛔ Files ignored due to path filters (1)
eeprom.binis excluded by!**/*.bin
📒 Files selected for processing (20)
src/main/build/atomic.csrc/main/build/atomic.hsrc/main/common/kalman.csrc/main/drivers/io.csrc/main/fc/config.csrc/main/fc/fc_core.csrc/main/flight/imu.csrc/main/flight/mixer.csrc/main/flight/pid.csrc/main/flight/servos.hsrc/main/io/displayport_hdzero_osd.hsrc/main/io/osd.csrc/main/io/osd.hsrc/main/io/rcdevice_cam.hsrc/main/sensors/acceleration.csrc/main/sensors/barometer.csrc/main/sensors/gyro.csrc/main/sensors/voltage.csrc/main/target/SITL/target.csrc/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.
|
@coderabbitai, all resolved including nitpicks? review or full review as needed. |
|
🧠 Learnings used✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
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 | 🔴 CriticalFailsafe procedure sanitization is now skipped in non-
USE_GPS_RESCUEbuilds.At Line 255, the new guard prevents cleanup of stale EEPROM values when GPS rescue is not compiled. That can leave
failsafeConfig()->failsafe_procedureout of range, and the failsafe switch (insrc/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.0fand0.0fsuffixes 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.003fsuffix correctly ensures float-precision arithmetic. However, the identical calculation at line 404 fordtermBoostMultiplierstill uses0.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_ADCwould 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` }; +#endifThen 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_MATHThen 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
📒 Files selected for processing (19)
.gitignoresrc/main/build/atomic.csrc/main/build/atomic.hsrc/main/common/kalman.csrc/main/drivers/io.csrc/main/fc/config.csrc/main/fc/fc_core.csrc/main/flight/imu.csrc/main/flight/mixer.csrc/main/flight/pid.csrc/main/io/displayport_hdzero_osd.hsrc/main/io/osd.csrc/main/io/osd.hsrc/main/sensors/acceleration.csrc/main/sensors/barometer.csrc/main/sensors/gyro.csrc/main/sensors/voltage.csrc/main/target/SITL/target.csrc/main/target/SITL/target.h
|
@coderabbitai, nitpicks and outside diff resolved? |
|
🧠 Learnings used✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
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 | 🟠 MajorKeep sanitizing stale GPS-rescue failsafe values on non-rescue targets.
Line 255 compiles this rewrite out whenever
USE_GPS_RESCUEis absent. On targets that still defineUSE_GPSbut not rescue support, this block now removesBOXGPSRESCUEyet leaves a persisted numeric GPS-rescuefailsafe_procedureuntouched. 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) andapplySensorCorrection(line 208) are actively called in normal builds (lines 346, 348), but these call sites are compiled out whenSIMULATOR_BUILD && SKIP_IMU_CALCare 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
📒 Files selected for processing (19)
.gitignoresrc/main/build/atomic.csrc/main/build/atomic.hsrc/main/common/kalman.csrc/main/drivers/io.csrc/main/fc/config.csrc/main/fc/fc_core.csrc/main/flight/imu.csrc/main/flight/mixer.csrc/main/flight/pid.csrc/main/io/displayport_hdzero_osd.hsrc/main/io/osd.csrc/main/io/osd.hsrc/main/sensors/acceleration.csrc/main/sensors/barometer.csrc/main/sensors/gyro.csrc/main/sensors/voltage.csrc/main/target/SITL/target.csrc/main/target/SITL/target.h
| 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; | ||
| } | ||
| } |
There was a problem hiding this comment.
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.
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
2. Kalman Covariance Robustness (Debug-Only)
UNIT_TEST/SIMULATOR_BUILD) to catch negative variance in the Kalman filter during SITL or unit tests.3. Repo Hygiene: eeprom.bin
eeprom.binfrom the repository.eeprom.binto.gitignoreto prevent future accidental commits.Validation
Safety and Impact
For Reviewers
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
Improvements
Chores