Skip to content

Commit 41d168f

Browse files
Merge pull request #11324 from joshperry/master
Add NEXUS target for RadioMaster Nexus (Original) flight controller
2 parents 16d2b10 + 38da5a7 commit 41d168f

6 files changed

Lines changed: 378 additions & 0 deletions

File tree

src/main/drivers/serial_uart_hal.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ static void usartConfigurePinInversion(uartPort_t *uartPort) {
5252
uartPort->Handle.AdvancedInit.TxPinLevelInvert = UART_ADVFEATURE_TXINV_ENABLE;
5353
}
5454
}
55+
56+
#ifdef USE_UART4_SWAP
57+
if (uartPort->Handle.Instance == UART4) {
58+
uartPort->Handle.AdvancedInit.AdvFeatureInit |= UART_ADVFEATURE_SWAP_INIT;
59+
uartPort->Handle.AdvancedInit.Swap = UART_ADVFEATURE_SWAP_ENABLE;
60+
}
61+
#endif
5562
}
5663

5764
static void uartReconfigure(uartPort_t *uartPort)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
target_stm32f722xe(NEXUS)

src/main/target/NEXUS/README.md

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# RadioMaster Nexus (Original)
2+
3+
Flight controller originally designed for helicopters using Rotorflight.
4+
Based on STM32F722RET6. This is the **original** (discontinued) Nexus,
5+
not the Nexus-X or Nexus-XR.
6+
7+
For the Nexus-X and Nexus-XR, use the `NEXUSX` target instead.
8+
9+
## Hardware
10+
11+
| Component | Spec |
12+
|-----------|------|
13+
| MCU | STM32F722RET6 (216MHz, 256KB RAM, 512KB flash) |
14+
| IMU | ICM-42688-P (SPI1), CW90 alignment |
15+
| Barometer | SPL06-001 (I2C1, internal) |
16+
| Blackbox | W25N01G 128MB (SPI2) |
17+
| Input voltage | 5 - 12.6V |
18+
| BEC output | 5V / 2A on Port A, B, C |
19+
| DSM power | 3.3V / 0.5A |
20+
| Dimensions | 41.3 x 25.4 x 13.1mm |
21+
| Weight | 16.8g |
22+
23+
## Differences from Nexus-X/XR
24+
25+
| | OG Nexus | Nexus-X/XR |
26+
|---|----------|------------|
27+
| IMU EXTI | PA15 | PB8 |
28+
| IMU alignment | CW90 | CW180 |
29+
| Baro I2C | I2C1 (PB8/PB9) | I2C2 (PB10/PB11) |
30+
| Flash | W25N01G (128MB) | W25N02K (256MB) |
31+
| Internal ELRS RX | None | RP4TD-M on UART5 |
32+
| PINIO1 (RX power) | None | PC8 |
33+
| UART1 pins | PA9/PA10 | PB6/PB7 |
34+
| Voltage sense | Vin ADC only (5-12.6V) | EXT-V input (3.6-70V) |
35+
| Servo outputs | 5 | 7 default (9 max) |
36+
| Rotorflight target | NEXUS_F7 | NEXUSX |
37+
38+
## Pin Functions
39+
40+
### Default Output Assignment
41+
42+
| Output | Pin | Timer | Connector |
43+
|--------|-----|-------|-----------|
44+
| S1 | PB4 | TIM3_CH1 | Servo header |
45+
| S2 | PB5 | TIM3_CH2 | Servo header |
46+
| S3 | PB0 | TIM3_CH3 | Servo header |
47+
| S4 | PB3 | TIM2_CH2 | Servo header (Tail) |
48+
| M1 | PB6 | TIM4_CH1 | ESC header |
49+
50+
### UART Ports
51+
52+
| UART | Label | TX | RX | Notes |
53+
|------|-------|----|----|-------|
54+
| UART1 | DSM | PA9 | PA10 | |
55+
| UART2 | SBUS | PA2 | PA3 | Shared with FREQ/PPM |
56+
| UART3 | Port C | PB11 | PB10 | Shared with I2C2 |
57+
| UART4 | Port A | PA1 | PA0 | Primary receiver (CRSF) |
58+
| UART6 | Port B | PC7 | PC6 | |
59+
60+
### I2C Buses
61+
62+
| Bus | SCL | SDA | Usage |
63+
|-----|-----|-----|-------|
64+
| I2C1 | PB8 | PB9 | Internal barometer (SPL06) |
65+
| I2C2 | PB10 | PB11 | External sensors via Port C |
66+
67+
### ADC Channels
68+
69+
| Channel | Pin | Divider | Usage |
70+
|---------|-----|---------|-------|
71+
| BUS | PC2 | 320 | Vin rail, 5-12.6V (mapped as VBAT) |
72+
| BEC | PC1 | 160 | 5V BEC rail monitoring |
73+
74+
Note: Unlike the Nexus-X/XR, the OG Nexus has no dedicated EXT-V
75+
high-voltage battery sense input. VBAT monitors the board input power.
76+
77+
### Connector Pinouts
78+
79+
**Port A (UART4 - CRSF receiver):**
80+
1. GND
81+
2. 5V
82+
3. RX (PA0, connect to receiver TX)
83+
4. TX (PA1, connect to receiver RX / telemetry)
84+
85+
**Port B (UART6):**
86+
1. GND
87+
2. 5V
88+
3. TX (PC7)
89+
4. RX (PC6)
90+
91+
**Port C (UART3 / I2C2):**
92+
1. GND
93+
2. 5V
94+
3. SDA/TX (PB11)
95+
4. SCL/RX (PB10)
96+
97+
**ESC Header:**
98+
- Signal: PB6 (TIM4_CH1 PWM)
99+
100+
## Typical Glider Setup (Elevon / Flying Wing)
101+
102+
For a 5-channel elevon glider like the Kunai:
103+
104+
1. Flash NEXUS target via DFU
105+
2. Set aircraft type: **Flying Wing**
106+
3. Connect RP3-H receiver to **Port A** (CRSF on UART4)
107+
4. Connect ESC to **ESC header** (M1)
108+
5. Connect left elevon servo to **S1**
109+
6. Connect right elevon servo to **S2**
110+
7. Configure elevon mixing in the Mixer tab
111+
8. Vario: SPL06 baro provides altitude-based vario out of the box
112+
9. GPS (Phase 2): Connect to **Port B** (UART6)
113+
114+
## Verified on Hardware
115+
116+
- [x] MCU boots, LEDs active (PC14, PC15)
117+
- [x] USB CDC enumeration and iNAV CLI
118+
- [x] IMU (gyro + accel) detected and responding
119+
- [x] Gyro alignment (CW90) confirmed
120+
- [x] Accelerometer working
121+
- [x] Barometer (SPL06 on I2C1) working
122+
- [x] VBAT ADC (PC2) working (scale 320)
123+
- [x] All UART ports (1-4, 6) verified
124+
- [x] UART4 CRSF receiver working (TX/RX swap confirmed)
125+
- [x] DShot on all motor outputs
126+
- [x] Servo outputs working
127+
- [x] Blackbox logging working
128+
- [x] LEDs working
129+
- [x] I2C2 bus working
130+
131+
## Building
132+
133+
Requires NixOS flake (included in repo root) or standard iNAV build deps.
134+
135+
```sh
136+
nix develop --impure # or set up arm-none-eabi-gcc manually
137+
mkdir -p build && cd build
138+
cmake -GNinja -DCOMPILER_VERSION_CHECK=OFF ..
139+
ninja NEXUS
140+
```
141+
142+
## Flashing via DFU
143+
144+
Hold button while connecting USB, then:
145+
146+
```sh
147+
arm-none-eabi-objcopy -O binary build/bin/NEXUS.elf build/NEXUS.bin
148+
dfu-util -a 0 -s 0x08000000:leave -D build/NEXUS.bin
149+
```

src/main/target/NEXUS/config.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* RadioMaster Nexus (Original) - Target configuration defaults
3+
*
4+
* Unlike the Nexus-X/XR, the OG Nexus has no internal ELRS receiver,
5+
* so there is no PINIO / USER1 box configuration needed here.
6+
*/
7+
8+
#include <stdint.h>
9+
#include "platform.h"
10+
#include "drivers/pwm_mapping.h"
11+
12+
void targetConfiguration(void)
13+
{
14+
// Force M1/ESC (PB6/TIM4) to motor mode so the PWM auto-allocator
15+
// picks it as the motor output first. Without this, it walks the
16+
// timer table in order, converts TIM3 (S1/S2/S3) to motors via
17+
// pwmClaimTimer(), and leaves no timers available for servos.
18+
timerOverridesMutable(timer2id(TIM4))->outputMode = OUTPUT_MODE_MOTORS;
19+
}

src/main/target/NEXUS/target.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* RadioMaster Nexus (Original) - Timer/PWM hardware configuration
3+
*
4+
* Timer allocation (from Rotorflight NEXUS_F7 dump):
5+
* TIM3: S1 (PB4/CH1), S2 (PB5/CH2), S3 (PB0/CH3)
6+
* TIM2: S4 (PB3/CH2)
7+
* TIM4: M1 (PB6/CH1) - ESC output
8+
*
9+
* Note: PA2/PA3 are FREQ/PPM inputs in Rotorflight. In iNAV they
10+
* can be repurposed as servo outputs when UART2 is not assigned.
11+
*/
12+
13+
#include <stdint.h>
14+
#include "platform.h"
15+
#include "drivers/io.h"
16+
#include "drivers/timer.h"
17+
#include "drivers/pwm_mapping.h"
18+
19+
timerHardware_t timerHardware[] = {
20+
DEF_TIM(TIM3, CH1, PB4, TIM_USE_OUTPUT_AUTO, 0, 0), // S1
21+
DEF_TIM(TIM3, CH2, PB5, TIM_USE_OUTPUT_AUTO, 0, 0), // S2
22+
DEF_TIM(TIM3, CH3, PB0, TIM_USE_OUTPUT_AUTO, 0, 0), // S3
23+
DEF_TIM(TIM2, CH2, PB3, TIM_USE_OUTPUT_AUTO, 0, 0), // S4
24+
DEF_TIM(TIM4, CH1, PB6, TIM_USE_OUTPUT_AUTO, 0, 0), // M1/ESC
25+
DEF_TIM(TIM5, CH3, PA2, TIM_USE_OUTPUT_AUTO, 0, 0), // shared w/ UART2 TX
26+
DEF_TIM(TIM9, CH2, PA3, TIM_USE_OUTPUT_AUTO, 0, 0), // shared w/ UART2 RX
27+
};
28+
29+
const int timerHardwareCount = sizeof(timerHardware) / sizeof(timerHardware[0]);

src/main/target/NEXUS/target.h

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/*
2+
* RadioMaster Nexus (Original) - iNAV target
3+
*
4+
* Based on the NEXUSX target by functionpointer, adapted for the
5+
* original (discontinued) Nexus hardware.
6+
*
7+
* Key differences from Nexus-X/XR:
8+
* - IMU EXTI on PA15 (X/XR uses PB8)
9+
* - IMU alignment CW180 (Rotorflight uses CW90 with a different
10+
* board orientation reference; iNAV uses the arrow on the case)
11+
* - Flash is W25N01G 128MB (X/XR uses W25N02K 256MB)
12+
* - No internal ELRS receiver (X/XR has RP4TD-M on UART5)
13+
* - No PINIO1 receiver power gate
14+
* - Voltage input 5-12.6V (X/XR supports 3.6-70V)
15+
* - 5 servo/motor outputs vs 7-9 on X/XR
16+
* - Baro on I2C1 (PB8/PB9), not I2C2
17+
* - UART1 on PA9/PA10, not PB6/PB7
18+
*
19+
* Pin mapping derived from:
20+
* - Rotorflight NEXUS_F7 target (authoritative)
21+
* - groundflight project (joshperry/groundflight)
22+
* - RadioMaster documentation
23+
*/
24+
25+
#pragma once
26+
27+
#define TARGET_BOARD_IDENTIFIER "NEXS"
28+
#define USBD_PRODUCT_STRING "RadioMaster Nexus"
29+
30+
/* ---- LEDs ---- */
31+
#define LED0 PC14 // active low
32+
#define LED1 PC15 // active low
33+
34+
/* ---- Beeper ---- */
35+
// No dedicated beeper pin on Nexus hardware
36+
37+
/* ---- SPI ---- */
38+
#define USE_SPI
39+
#define USE_SPI_DEVICE_1
40+
#define SPI1_SCK_PIN PA5
41+
#define SPI1_MISO_PIN PA6
42+
#define SPI1_MOSI_PIN PA7
43+
44+
#define USE_SPI_DEVICE_2
45+
#define SPI2_SCK_PIN PB13
46+
#define SPI2_MISO_PIN PB14
47+
#define SPI2_MOSI_PIN PB15
48+
49+
/* ---- IMU: ICM-42688-P ---- */
50+
// iNAV uses ICM42605 driver which is register-compatible with ICM42688P
51+
#define USE_IMU_ICM42605
52+
#define IMU_ICM42605_ALIGN CW180_DEG
53+
#define ICM42605_CS_PIN PA4
54+
#define ICM42605_SPI_BUS BUS_SPI1
55+
#define ICM42605_EXTI_PIN PA15
56+
57+
/* ---- I2C ---- */
58+
// I2C1: PB8/PB9 - internal, used for barometer
59+
#define USE_I2C
60+
#define USE_I2C_DEVICE_1
61+
#define I2C1_SCL PB8
62+
#define I2C1_SDA PB9
63+
64+
// I2C2: PB10/PB11 - external via Port C connector (shared with UART3)
65+
// Available for external sensors (magnetometer, rangefinder, etc.)
66+
#define USE_I2C_DEVICE_2
67+
#define I2C2_SCL PB10
68+
#define I2C2_SDA PB11
69+
#define I2C_DEVICE_2_SHARES_UART3
70+
71+
/* ---- Barometer: SPL06-001 ---- */
72+
// Confirmed on I2C1 per Rotorflight NEXUS_F7 dump
73+
#define USE_BARO
74+
#define USE_BARO_SPL06
75+
#define BARO_I2C_BUS BUS_I2C1
76+
77+
/* ---- Magnetometer (external, optional via Port C / I2C2) ---- */
78+
#define USE_MAG
79+
#define USE_MAG_ALL
80+
#define MAG_I2C_BUS BUS_I2C2
81+
82+
/* ---- Flash: W25N01G (128MB) ---- */
83+
#define USE_FLASHFS
84+
#define USE_FLASH_W25N01G
85+
#define W25N01G_SPI_BUS BUS_SPI2
86+
#define W25N01G_CS_PIN PB12
87+
#define ENABLE_BLACKBOX_LOGGING_ON_SPIFLASH_BY_DEFAULT
88+
89+
/* ---- UARTs ---- */
90+
// OG Nexus UART layout (confirmed from Rotorflight NEXUS_F7 dump):
91+
// UART1 [DSM port] : PA9 (TX) / PA10 (RX)
92+
// UART2 [SBUS/FREQ] : PA2 (TX) / PA3 (RX) - shared with RPM/TLM pins
93+
// UART3 [Port C] : PB11 (TX) / PB10 (RX) - shared with I2C2
94+
// UART4 [Port A] : PA1 (TX) / PA0 (RX) - primary CRSF receiver
95+
// UART6 [Port B] : PC7 (TX) / PC6 (RX)
96+
//
97+
// NOTE: No UART5 on OG Nexus (X/XR uses UART5 for internal ELRS)
98+
99+
#define USE_VCP
100+
#define USE_USB_DETECT
101+
#define USB_DETECT_PIN NONE
102+
103+
#define USE_UART1
104+
#define UART1_TX_PIN PA9
105+
#define UART1_RX_PIN PA10
106+
107+
#define USE_UART2
108+
#define UART2_TX_PIN PA2
109+
#define UART2_RX_PIN PA3
110+
111+
#define USE_UART3
112+
#define UART3_TX_PIN PB11
113+
#define UART3_RX_PIN PB10
114+
115+
#define USE_UART4
116+
#define USE_UART4_SWAP
117+
#define UART4_TX_PIN PA1
118+
#define UART4_RX_PIN PA0
119+
120+
#define USE_UART6
121+
#define UART6_TX_PIN PC7
122+
#define UART6_RX_PIN PC6
123+
124+
#define SERIAL_PORT_COUNT 6 // VCP + UART1-4 + UART6
125+
126+
/* ---- Default serial receiver ---- */
127+
#define DEFAULT_RX_TYPE RX_TYPE_SERIAL
128+
#define SERIALRX_PROVIDER SERIALRX_CRSF
129+
#define SERIALRX_UART SERIAL_PORT_USART4
130+
131+
132+
/* ---- ADC ---- */
133+
// OG Nexus has no EXT-V input (unlike X/XR which has a dedicated
134+
// high-voltage sense on PC0). Only two ADC channels:
135+
// ADC_BUS = PC2, divider 320 (Vin rail, 5-12.6V)
136+
// ADC_BEC = PC1, divider 160 (BEC 5V rail)
137+
// Map Vin as VBAT since it's the primary power input
138+
#define USE_ADC
139+
#define ADC_INSTANCE ADC1
140+
#define ADC_CHANNEL_1_PIN PC2 // Vin (input power rail)
141+
#define VBAT_ADC_CHANNEL ADC_CHN_1
142+
#define ADC_CHANNEL_2_PIN PC1 // BEC 5V rail
143+
// VBAT scale: hardware-verified value (divider ratio ~320)
144+
#define VBAT_SCALE_DEFAULT 320
145+
146+
/* ---- Sensors ---- */
147+
#define SENSORS_SET (SENSOR_ACC | SENSOR_BARO)
148+
149+
/* ---- PWM / Servo / Motor outputs ---- */
150+
// OG Nexus outputs (from Rotorflight dump):
151+
// S1: PB4 (TIM3_CH1) - Servo header
152+
// S2: PB5 (TIM3_CH2) - Servo header
153+
// S3: PB0 (TIM3_CH3) - Servo header
154+
// S4: PB3 (TIM2_CH2) - Servo header (Tail)
155+
// M1: PB6 (TIM4_CH1) - ESC header (motor only, NOT UART1)
156+
//
157+
// Pin multiplexing when UARTs freed:
158+
// PA2 (TIM5_CH3) - shared with UART2 TX / FREQ input
159+
// PA3 (TIM9_CH2) - shared with UART2 RX / PPM input
160+
161+
#define MAX_PWM_OUTPUT_PORTS 7
162+
163+
/* ---- No internal receiver ---- */
164+
// OG Nexus has no internal ELRS receiver.
165+
// No UART5, no PINIO1 power gate.
166+
167+
/* ---- Platform ---- */
168+
#define USE_SERIAL_4WAY_BLHELI_INTERFACE
169+
#define TARGET_IO_PORTA 0xffff
170+
#define TARGET_IO_PORTB 0xffff
171+
#define TARGET_IO_PORTC 0xffff
172+
173+
#define DEFAULT_FEATURES (FEATURE_TX_PROF_SEL | FEATURE_BLACKBOX)

0 commit comments

Comments
 (0)