Skip to content

Add NEXUS target for RadioMaster Nexus (Original) flight controller#11324

Open
joshperry wants to merge 1 commit intoiNavFlight:maintenance-9.xfrom
joshperry:master
Open

Add NEXUS target for RadioMaster Nexus (Original) flight controller#11324
joshperry wants to merge 1 commit intoiNavFlight:maintenance-9.xfrom
joshperry:master

Conversation

@joshperry
Copy link

@joshperry joshperry commented Feb 11, 2026

STM32F722-based target for the original (discontinued) Nexus, distinct from the Nexus-X/XR (NEXUSX target). Pin mapping derived from Rotorflight NEXUS_F7 dump and verified on hardware.

Key hardware support:

  • ICM-42688-P IMU on SPI1 (CW90 alignment, EXTI PA15)
  • SPL06 barometer on I2C1 (PB8/PB9, separate from external I2C2)
  • W25N01G 128MB blackbox flash on SPI2
  • 5 servo/motor outputs (S1-S4 + M1), expandable to 7
  • UART4 with TX/RX swap for CRSF receiver on Port A
  • UART1 on PA9/PA10 (not PB6/PB7 as on Nexus-X/XR)

Also includes:

  • USE_UART4_SWAP support in serial_uart_hal.c

@github-actions
Copy link

Branch Targeting Suggestion

You've targeted the master branch with this PR. Please consider if a version branch might be more appropriate:

  • maintenance-9.x - If your change is backward-compatible and won't create compatibility issues between INAV firmware and Configurator 9.x versions. This will allow your PR to be included in the next 9.x release.

  • maintenance-10.x - If your change introduces compatibility requirements between firmware and configurator that would break 9.x compatibility. This is for PRs which will be included in INAV 10.x

If master is the correct target for this change, no action is needed.


This is an automated suggestion to help route contributions to the appropriate branch.

@qodo-code-review
Copy link
Contributor

Review Summary by Qodo

Add NEXUS target for RadioMaster Nexus flight controller

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Add NEXUS target for RadioMaster Nexus (Original) flight controller
  - STM32F722-based target with ICM-42688-P IMU on SPI1
  - SPL06 barometer on I2C1, W25N01G 128MB blackbox flash on SPI2
  - 5 servo/motor outputs (S1-S4 + M1) with expandable configuration
  - UART4 with TX/RX swap for CRSF receiver on Port A
• Add USE_UART4_SWAP support in serial_uart_hal.c for UART4 pin swapping
• Add Nix flake development environment for cross-compilation
• Disable cmake auto-download of ARM toolchain on version mismatch
Diagram
flowchart LR
  A["NEXUS Target<br/>STM32F722"] --> B["Hardware Config<br/>target.h"]
  A --> C["Timer/PWM<br/>target.c"]
  A --> D["Config Defaults<br/>config.c"]
  B --> E["ICM-42688-P IMU<br/>SPI1 CW90"]
  B --> F["SPL06 Baro<br/>I2C1"]
  B --> G["W25N01G Flash<br/>SPI2"]
  B --> H["UART4 Swap<br/>CRSF RX"]
  C --> I["5 PWM Outputs<br/>TIM2/3/4/5/9"]
  D --> J["Motor Mode<br/>Override TIM4"]
  K["serial_uart_hal.c"] --> H
  L["cmake checks"] --> M["Skip Toolchain<br/>Auto-download"]
  N["flake.nix"] --> O["Dev Environment<br/>ARM Toolchain"]
Loading

Grey Divider

File Changes

1. src/main/target/NEXUS/target.h New target +171/-0

Complete hardware pin mapping and configuration

• Complete target hardware definition for RadioMaster Nexus (Original) flight controller
• Defines ICM-42688-P IMU on SPI1 with CW90 alignment and PA15 EXTI
• Configures SPL06 barometer on I2C1 (PB8/PB9) and W25N01G flash on SPI2
• Sets up 6 UART ports with UART4 swap enabled for CRSF receiver on Port A
• Defines ADC channels for battery voltage monitoring (PC2) and BEC rail (PC1)
• Specifies 7 PWM output pins across TIM2/3/4/5/9 for servo and motor control

src/main/target/NEXUS/target.h


2. src/main/target/NEXUS/target.c New target +29/-0

Timer and PWM hardware configuration

• Defines timer hardware configuration with 7 PWM outputs
• Maps S1-S4 servo outputs to TIM3 and TIM2 channels on port B
• Configures M1/ESC motor output on TIM4 CH1 (PB6)
• Includes shared PA2/PA3 pins for UART2 and optional servo outputs

src/main/target/NEXUS/target.c


3. src/main/target/NEXUS/config.c New target +19/-0

Target configuration defaults

• Sets default target configuration for RadioMaster Nexus
• Forces TIM4 (M1/ESC) to motor mode to ensure proper PWM auto-allocator behavior
• Prevents timer table walk from converting TIM3 to motors and leaving no timers for servos

src/main/target/NEXUS/config.c


View more (5)
4. src/main/target/NEXUS/CMakeLists.txt New target +1/-0

CMake build configuration

• Minimal CMake configuration file for NEXUS target
• Specifies STM32F722XE MCU variant for build system

src/main/target/NEXUS/CMakeLists.txt


5. src/main/target/NEXUS/README.md 📝 Documentation +144/-0

Target documentation and setup guide

• Comprehensive documentation for RadioMaster Nexus (Original) flight controller
• Hardware specifications, pin functions, and connector pinouts
• Comparison table with Nexus-X/XR differences
• Typical glider setup instructions and verification checklist
• Build and flashing instructions via DFU

src/main/target/NEXUS/README.md


6. src/main/drivers/serial_uart_hal.c ✨ Enhancement +7/-0

Add UART4 TX/RX swap support

• Add conditional UART4 pin swap support via USE_UART4_SWAP macro
• Enables TX/RX pin swapping on UART4 for RadioMaster Nexus CRSF receiver configuration
• Uses STM32 AdvancedInit features to configure UART_ADVFEATURE_SWAP

src/main/drivers/serial_uart_hal.c


7. cmake/arm-none-eabi-checks.cmake ⚙️ Configuration changes +0/-8

Disable cmake toolchain auto-download

• Remove automatic ARM toolchain download when version mismatch is detected
• Simplifies build process by disabling auto-installation fallback behavior
• Allows build to proceed with version mismatch instead of attempting re-download

cmake/arm-none-eabi-checks.cmake


8. flake.nix ⚙️ Configuration changes +92/-0

Nix flake development environment

• Add Nix flake development environment for iNAV firmware development
• Provides default shell with ARM cross-compiler, build tools, and debugging utilities
• Includes minimal shell variant without optional packages
• Supports x86_64-linux and aarch64-linux systems
• Includes quick start and flashing instructions in shell hook

flake.nix


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Contributor

Code Review by Qodo

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

Grey Divider


Action required

1. Toolchain mismatch not handled 📘 Rule violation ⛯ Reliability
Description
When COMPILER_VERSION_CHECK is enabled and the detected arm-none-eabi-gcc version differs from
arm_none_eabi_gcc_version, the code only prints a message and continues. This leaves the build in
a potentially invalid state instead of failing deterministically or performing a defined fallback.
Code

cmake/arm-none-eabi-checks.cmake[R136-138]

    if(COMPILER_VERSION_CHECK AND NOT arm_none_eabi_gcc_version STREQUAL version)
        message("-- expecting ${prog} version ${arm_none_eabi_gcc_version}, but got version ${version} instead")
-	arm_none_eabi_gcc_install()
-        unset(gcc CACHE)
-        gcc_get_version(version
-            TRIPLET ${arm_none_eabi_triplet}
-            PROGRAM_NAME prog
-            PROGRAM_PATH prog_path
-        )
-        return()
    endif()
Evidence
PR Compliance ID 3 requires handling potential failure points with actionable context and
graceful/deterministic behavior. The added/modified logic for the version-mismatch case provides
only a log message and no deterministic error or fallback (e.g., install correct toolchain, abort
configuration).

Rule 3: Generic: Robust Error Handling and Edge Case Management
cmake/arm-none-eabi-checks.cmake[135-139]

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

## Issue description
When `COMPILER_VERSION_CHECK` is enabled and the detected `arm-none-eabi-gcc` version does not match `arm_none_eabi_gcc_version`, the current logic only prints a warning and continues. This can result in non-deterministic build failures later.

## Issue Context
This is a build-time dependency check; mismatch should be handled deterministically (fail early with actionable guidance) or with a clearly-defined fallback behavior.

## Fix Focus Areas
- cmake/arm-none-eabi-checks.cmake[135-139]

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


2. I2C2/UART3 share guard missing 🐞 Bug ✓ Correctness
Description
NEXUS enables I2C2 on PB10/PB11 and also enables UART3 on the same pins but does not define
I2C_DEVICE_2_SHARES_UART3, so i2cInit(I2CDEV_2) is not conditionally skipped when UART3 is
configured. This can cause pin contention and break either UART3 or I2C2 depending on init
order/runtime configuration.
Code

src/main/target/NEXUS/target.h[R63-110]

+// I2C2: PB10/PB11 - external via Port C connector (shared with UART3)
+// Available for external sensors (magnetometer, rangefinder, etc.)
+#define USE_I2C_DEVICE_2
+#define I2C2_SCL                PB10
+#define I2C2_SDA                PB11
+
+/* ---- Barometer: SPL06-001 ---- */
+// Confirmed on I2C1 per Rotorflight NEXUS_F7 dump
+#define USE_BARO
+#define USE_BARO_SPL06
+#define BARO_I2C_BUS            BUS_I2C1
+
+/* ---- Magnetometer (external, optional via Port C / I2C2) ---- */
+#define USE_MAG
+#define MAG_I2C_BUS             BUS_I2C2
+
+/* ---- Flash: W25N01G (128MB) ---- */
+#define USE_FLASHFS
+#define USE_FLASH_W25N01G
+#define W25N01G_SPI_BUS         BUS_SPI2
+#define W25N01G_CS_PIN          PB12
+#define ENABLE_BLACKBOX_LOGGING_ON_SPIFLASH_BY_DEFAULT
+
+/* ---- UARTs ---- */
+// OG Nexus UART layout (confirmed from Rotorflight NEXUS_F7 dump):
+//   UART1 [DSM port]  : PA9 (TX) / PA10 (RX)
+//   UART2 [SBUS/FREQ] : PA2 (TX) / PA3 (RX) - shared with RPM/TLM pins
+//   UART3 [Port C]    : PB11 (TX) / PB10 (RX) - shared with I2C2
+//   UART4 [Port A]    : PA1 (TX) / PA0 (RX) - primary CRSF receiver
+//   UART6 [Port B]    : PC7 (TX) / PC6 (RX)
+//
+// NOTE: No UART5 on OG Nexus (X/XR uses UART5 for internal ELRS)
+
+#define USE_VCP
+#define USE_USB_DETECT
+#define USB_DETECT_PIN          NONE
+
+#define USE_UART1
+#define UART1_TX_PIN            PA9
+#define UART1_RX_PIN            PA10
+
+#define USE_UART2
+#define UART2_TX_PIN            PA2
+#define UART2_RX_PIN            PA3
+
+#define USE_UART3
+#define UART3_TX_PIN            PB11
+#define UART3_RX_PIN            PB10
Evidence
fc_init only avoids initializing a shared I2C bus when the corresponding SHARES_UART3 macro is
defined; NEXUS does not define it despite declaring I2C2 and UART3 on the same pins. NEXUSX sets the
macro for the same sharing scenario.

src/main/target/NEXUS/target.h[63-68]
src/main/target/NEXUS/target.h[108-110]
src/main/fc/fc_init.c[418-425]
src/main/target/NEXUSX/target.h[50-54]

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

### Issue description
NEXUS defines both I2C2 and UART3 on PB10/PB11 but does not define `I2C_DEVICE_2_SHARES_UART3`. As a result, firmware init will not guard I2C2 initialization when UART3 is configured, creating a pin/resource conflict.

### Issue Context
`fc_init.c` has explicit conditional logic to skip `i2cInit(I2CDEV_2)` when `doesConfigurationUsePort(SERIAL_PORT_USART3)` is true, but only when the `I2C_DEVICE_2_SHARES_UART3` macro is defined.

### Fix Focus Areas
- src/main/target/NEXUS/target.h[63-68]
- src/main/fc/fc_init.c[418-425]

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



Remediation recommended

3. UART3 pin mapping ambiguity 🐞 Bug ✓ Correctness
Description
NEXUS sets UART3 as TX=PB11/RX=PB10, but the same README’s Port C pinout labels PB10 as SCL/TX and
PB11 as SDA/RX; additionally, no STM32F7 UART3 swap mechanism is configured here (only UART4 swap
was added). This mismatch is likely to confuse users and may result in a non-working Port C UART if
the intended mapping is PB10=TX/PB11=RX.
Code

src/main/target/NEXUS/target.h[R108-110]

+#define USE_UART3
+#define UART3_TX_PIN            PB11
+#define UART3_RX_PIN            PB10
Evidence
Target config and documentation disagree about which Port C pin is TX vs RX, and the only swap
support added in this PR is hard-coded for UART4, not UART3. That leaves UART3 mapping correctness
unclear and risky.

src/main/target/NEXUS/target.h[108-110]
src/main/target/NEXUS/README.md[52-58]
src/main/target/NEXUS/README.md[88-92]
src/main/drivers/serial_uart_hal.c[56-60]

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

### Issue description
UART3 pin mapping for Port C is inconsistent across `target.h` and the README pinout, and the PR only adds swap support for UART4. This creates a high risk that Port C UART is wired/configured incorrectly.

### Issue Context
- `target.h` currently defines UART3 TX/RX as PB11/PB10.
- The README Port C pinout labels PB10 as SCL/TX and PB11 as SDA/RX.
- Swap support added in this PR is only for UART4.

### Fix Focus Areas
- src/main/target/NEXUS/target.h[108-110]
- src/main/target/NEXUS/README.md[52-58]
- src/main/target/NEXUS/README.md[88-92]
- src/main/drivers/serial_uart_hal.c[56-60]

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


4. Mag drivers not enabled 🐞 Bug ✓ Correctness
Description
NEXUS enables USE_MAG and sets MAG_I2C_BUS, but does not define USE_MAG_ALL or any specific
magnetometer driver, so only the MSP mag driver is enabled. External I2C magnetometers on Port C
likely won’t be detected/usable without additional compile-time driver enables.
Code

src/main/target/NEXUS/target.h[R75-78]

+/* ---- Magnetometer (external, optional via Port C / I2C2) ---- */
+#define USE_MAG
+#define MAG_I2C_BUS             BUS_I2C2
+
Evidence
common_post.h only enables actual hardware I2C magnetometer drivers when USE_MAG_ALL is defined;
otherwise it enables only USE_MAG_MSP. NEXUSX enables USE_MAG_ALL for external mag use, but NEXUS
does not.

src/main/target/NEXUS/target.h[75-78]
src/main/target/common_post.h[77-104]
src/main/target/NEXUSX/target.h[60-63]

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

### Issue description
The NEXUS target enables compass support (`USE_MAG`) but does not enable any hardware magnetometer drivers (`USE_MAG_ALL` or specific drivers). This likely prevents external I2C magnetometers from working.

### Issue Context
`common_post.h` enables only `USE_MAG_MSP` unless `USE_MAG_ALL` is defined.

### Fix Focus Areas
- src/main/target/NEXUS/target.h[75-78]
- src/main/target/common_post.h[77-104]

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


Grey Divider

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

Grey Divider

Qodo Logo

STM32F722-based target for the original (discontinued) Nexus,
distinct from the Nexus-X/XR (NEXUSX target). Pin mapping derived
from Rotorflight NEXUS_F7 dump and verified on hardware.

Key hardware support:
- ICM-42688-P IMU on SPI1 (CW90 alignment, EXTI PA15)
- SPL06 barometer on I2C1 (PB8/PB9, separate from external I2C2)
- W25N01G 128MB blackbox flash on SPI2
- 5 servo/motor outputs (S1-S4 + M1), expandable to 7
- UART4 with TX/RX swap for CRSF receiver on Port A
- UART1 on PA9/PA10 (not PB6/PB7 as on Nexus-X/XR)

Also adds USE_UART4_SWAP support in serial_uart_hal.c for the
STM32 HAL advanced UART pin swap feature.
@joshperry
Copy link
Author

Addressed the qodo issues except for 3 because UART3 TX=PB11/RX=PB10 is correct per the Rotorflight dump, the OG Nexus has these swapped vs the default STM32 pinout. The INAV HAL configures based on the UART3_TX_PIN/UART3_RX_PIN defines directly, so no swap macro is needed.

@joshperry joshperry changed the base branch from master to maintenance-9.x February 11, 2026 20:50
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