inav icon indicating copy to clipboard operation
inav copied to clipboard

Add custom targets for BOTWINGF405 and BOTWINGF722 flight controllers

Open PrateekShanker99 opened this issue 7 months ago • 5 comments

This pull request adds support for two custom flight controller targets:

  1. BOTWINGF405 – based on STM32F405 MCU
  2. BOTWINGF722 – based on STM32F722 MCU

Key Features:

  • IMU: ICM42688P over SPI
  • Barometer: DPS310 via I2C
  • Verified compatibility with INAV Configurator(8.0.0)

Validation:

  • All sensors and outputs tested and verified using INAV(version 8.0.0) build system
  • Board boots correctly with full initialization.

PrateekShanker99 avatar May 28 '25 17:05 PrateekShanker99

F405

  • [x] Samples received
  • [x] Flash firmware
  • [x] Calibrate
  • [x] Orientation matches
  • [x] Gyro working
  • [x] Accel working
  • [x] Baro working
  • [x] Voltage correct
  • [x] Current correct
  • [ ] Analog RSSI - This is the correct pin. I may have an error in my testing
  • [x] Mag I2C Bus
  • [x] UART1
  • [x] UART2
  • [x] UART3
  • [x] UART4
  • [x] UART5
  • [x] UART6
  • [x] LEDs working
  • [x] Buzzer working
  • [x] Motor outputs
  • [x] DShot support on m1-4
  • [x] Blackbox
  • [x] Analog Camera working
  • [x] Video Out working
  • [x] OSD working
  • [x] PINIO1
  • [x] PINIO2

sensei-hacker avatar Jun 08 '25 23:06 sensei-hacker

F722

  • [x] Samples received
  • [x] Flash firmware
  • [x] Calibrate
  • [x] Orientation matches
  • [x] Gyro working
  • [x] Accel working
  • [x] Baro working
  • [x] Voltage correct
  • [ ] Current correct
  • [x] Analog RSSI
  • [x] Mag I2C Bus
  • [x] UART1
  • [x] UART2
  • [x] UART3
  • [x] UART4
  • [x] UART6
  • [x] LEDs working
  • [x] Buzzer working
  • [x] Motor outputs
  • [x] DShot support on m1-4
  • [x] Servo outputs (if MAX_PWM_OUTPUT_PORTS is increased)
  • [x] Blackbox
  • [x] Analog Camera working
  • [x] Video Out working
  • [x] OSD working
  • [ ] PINIO1
  • [ ] PINIO2

sensei-hacker avatar Jun 08 '25 23:06 sensei-hacker

Thanks for the PR!

On the F405, the ADC defintions at the moment are: #define ADC_CHANNEL_1_PIN PC1 #define ADC_CHANNEL_2_PIN PC2

#define VBAT_ADC_CHANNEL ADC_CHN_1 #define CURRENT_METER_ADC_CHANNEL ADC_CHN_2

In my testing, it appears PC2 is the one labled for RSSI. So RSSI_ADC_CHANNEL should be defined as ADC_CHN_2 (PC2(

#define VBAT_ADC_CHANNEL should then be defined as whichever pin goes to the pad labeled for current?

The voltage scale looks a little off in my testing. We might want soemthing like: #define VBAT_SCALE_DEFAULT 1420

sensei-hacker avatar Jun 08 '25 23:06 sensei-hacker

On the F405, target.c contains:

#ifdef SPEEDYBEEF405MINI_6OUTPUTS

#define MAX_PWM_OUTPUT_PORTS        6

#else

#define MAX_PWM_OUTPUT_PORTS        4

#endif

Can we please remove the reference to SPEEDYBEEF405MINI_6OUTPUTS. Also the commented line in target.c

Also, we see UART1 defined to use:

#define UART1_TX_PIN               PB6
#define UART1_RX_PIN               PB7

But that same pin is defined as S5: DEF_TIM(TIM4, CH2, PB7, TIM_USE_OUTPUT_AUTO, 0, 0), // S5

It looks like the pin as actually connected to the UART1_RX pad, so the define for S5 should be removed?

sensei-hacker avatar Jun 09 '25 00:06 sensei-hacker

On the F405, I see there is a PIO available for the user -- that's great!

That probably needs to be added in config.c, where you already have the other PINIO:

pinioBoxConfigMutable()->permanentId[1] = BOX_PERMANENT_ID_USER2;

PS - thanks for using a more robust switch / button for DFU boot. That's much nicer than some of the other boards. :)

sensei-hacker avatar Jun 09 '25 00:06 sensei-hacker

on the F722:

- #define USE_FLASH_W25Q128FV
- #define W25Q128FV_CS_PIN                SPI1_NSS_PINAdd commentMore actions
- #define W25Q128FV_SPI_BUS               BUS_SPI1
- 
+ #define USE_FLASH_M25P16
+ #define M25P16_CS_PIN                SPI1_NSS_PIN
+ #define M25P16_SPI_BUS               BUS_SPI1

By the way, I could have handed you most of the changes as a pull request, if your new target was in a branch, rather than in master.

sensei-hacker avatar Jun 23 '25 23:06 sensei-hacker

On the F722:

#define MAX_PWM_OUTPUT_PORTS 4 Shouldn't this be 6?

TIM_USE_MOTOR and TIM_USE_SERVO should probably be TIM_USE_AUTO

DSHOT_BITBANG_AUTO can be removed. INAV doesn't bit-bang Dshot because the MCU is busy doing navigation, ADSB, radar, etc.

Thanks!

sensei-hacker avatar Jun 28 '25 04:06 sensei-hacker

It seems there was some communication difficulty, so I just sent over the updates as a pull request into your branch: https://github.com/PrateekShanker99/inav_custon_target/pull/1

I see on the F722 you have PINIO1_PIN and PINIO2_PIN defined. What do those do, please?

sensei-hacker avatar Jul 30 '25 03:07 sensei-hacker

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Unsafe array indexing

Description: Direct indexing into serial port array using findSerialPortIndexByIdentifier without
checking for invalid (-1) return may lead to out-of-bounds write if a port is absent on
the target.
config.c [15-18]

Referred Code
serialConfigMutable()->portConfigs[findSerialPortIndexByIdentifier(SERIAL_PORT_USART1)].functionMask = FUNCTION_RX_SERIAL;
serialConfigMutable()->portConfigs[findSerialPortIndexByIdentifier(SERIAL_PORT_USART4)].functionMask = FUNCTION_MSP;
serialConfigMutable()->portConfigs[findSerialPortIndexByIdentifier(SERIAL_PORT_USART4)].msp_baudrateIndex = BAUD_115200;
serialConfigMutable()->portConfigs[findSerialPortIndexByIdentifier(SERIAL_PORT_USART2)].functionMask = FUNCTION_ESCSERIAL;
Unsafe array indexing

Description: Direct indexing into serial port array using findSerialPortIndexByIdentifier without
validating the index can cause out-of-bounds access if the port is not configured.
config.c [26-29]

Referred Code
serialConfigMutable()->portConfigs[findSerialPortIndexByIdentifier(SERIAL_PORT_USART2)].functionMask = FUNCTION_RX_SERIAL;
serialConfigMutable()->portConfigs[findSerialPortIndexByIdentifier(SERIAL_PORT_USART3)].functionMask = FUNCTION_MSP;
serialConfigMutable()->portConfigs[findSerialPortIndexByIdentifier(SERIAL_PORT_USART3)].msp_baudrateIndex = BAUD_115200;
serialConfigMutable()->portConfigs[findSerialPortIndexByIdentifier(SERIAL_PORT_USART4)].functionMask = FUNCTION_ESCSERIAL;
Ticket Compliance
🎫 No ticket provided
  • [ ] Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
No custom compliance provided

Follow the guide to enable custom compliance check.

  • [ ] Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

qodo-code-review[bot] avatar Oct 14 '25 11:10 qodo-code-review[bot]

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Assign unique board identifiers

The suggestion points out that both new targets, BOTWINGF405 and BOTWINGF722,
use the same TARGET_BOARD_IDENTIFIER. It recommends assigning a unique
identifier to each target to prevent conflicts in configurator software.

Examples:

src/main/target/BOTWINGF405/target.h [4]
#define TARGET_BOARD_IDENTIFIER "BLDY"
src/main/target/BOTWINGF722/target.h [2]
#define TARGET_BOARD_IDENTIFIER                         "BLDY"

Solution Walkthrough:

Before:

// src/main/target/BOTWINGF405/target.h
#define TARGET_BOARD_IDENTIFIER "BLDY"
#define USBD_PRODUCT_STRING     "BOTWINGF405"

// src/main/target/BOTWINGF722/target.h
#define TARGET_BOARD_IDENTIFIER                         "BLDY"
#define USBD_PRODUCT_STRING                             "BOTWINGF722"

After:

// src/main/target/BOTWINGF405/target.h
#define TARGET_BOARD_IDENTIFIER "BWF4" // Example unique ID
#define USBD_PRODUCT_STRING     "BOTWINGF405"

// src/main/target/BOTWINGF722/target.h
#define TARGET_BOARD_IDENTIFIER                         "BWF7" // Example unique ID
#define USBD_PRODUCT_STRING                             "BOTWINGF722"

Suggestion importance[1-10]: 10

__

Why: This suggestion correctly identifies a critical issue where both new targets share the same TARGET_BOARD_IDENTIFIER, which would cause configuration conflicts and incorrect behavior in the configurator software.

High
Possible issue
Use correct timer auto-detection macro
Suggestion Impact:The commit changed all relevant DEF_TIM entries from TIM_USE_ANY to TIM_USE_OUTPUT_AUTO for motors and servos, matching the suggestion.

code diff:

+    DEF_TIM(TIM3, CH1, PB4,  TIM_USE_OUTPUT_AUTO, 0, 0), // S1
+    DEF_TIM(TIM3, CH2, PB5,  TIM_USE_OUTPUT_AUTO, 0, 0), // S2
+    DEF_TIM(TIM3, CH3, PB0,  TIM_USE_OUTPUT_AUTO, 0, 0), // S3
+    DEF_TIM(TIM3, CH4, PB1,  TIM_USE_OUTPUT_AUTO, 0, 0), // S4
+    DEF_TIM(TIM2, CH1, PA15, TIM_USE_OUTPUT_AUTO, 0, 0),// Servo 1
+    DEF_TIM(TIM2, CH2, PB3,  TIM_USE_OUTPUT_AUTO, 0, 0),// Servo 2

In src/main/target/BOTWINGF722/target.c, replace TIM_USE_ANY with the correct
TIM_USE_OUTPUT_AUTO macro for all motor and servo timer definitions to ensure
proper timer allocation.

src/main/target/BOTWINGF722/target.c [19-25]

-// not able to fins any "TIM_USE_AUTO" DEFINED INSIDE THE typedef enum in timer.h file so used "   TIM_USE_ANY" INSTEAD .
-DEF_TIM(TIM3, CH1, PB4,  TIM_USE_ANY, 0, 0), // S1
-DEF_TIM(TIM3, CH2, PB5,  TIM_USE_ANY, 0, 0), // S2
-DEF_TIM(TIM3, CH3, PB0,  TIM_USE_ANY, 0, 0), // S3
-DEF_TIM(TIM3, CH4, PB1,  TIM_USE_ANY, 0, 0), // S4
-DEF_TIM(TIM2, CH1, PA15, TIM_USE_ANY, 0, 0),// Servo 1
-DEF_TIM(TIM2, CH2, PB3,  TIM_USE_ANY, 0, 0),// Servo 2
+DEF_TIM(TIM3, CH1, PB4,  TIM_USE_OUTPUT_AUTO, 0, 0), // S1
+DEF_TIM(TIM3, CH2, PB5,  TIM_USE_OUTPUT_AUTO, 0, 0), // S2
+DEF_TIM(TIM3, CH3, PB0,  TIM_USE_OUTPUT_AUTO, 0, 0), // S3
+DEF_TIM(TIM3, CH4, PB1,  TIM_USE_OUTPUT_AUTO, 0, 0), // S4
+DEF_TIM(TIM2, CH1, PA15, TIM_USE_OUTPUT_AUTO, 0, 0),// Servo 1
+DEF_TIM(TIM2, CH2, PB3,  TIM_USE_OUTPUT_AUTO, 0, 0),// Servo 2

[Suggestion processed]

Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that TIM_USE_OUTPUT_AUTO should be used instead of TIM_USE_ANY, fixing a mistake the developer explicitly noted in a comment, which improves correctness.

Medium
Prevent potential out-of-bounds array access

Add checks for the return value of findSerialPortIndexByIdentifier before
accessing the portConfigs array to prevent potential out-of-bounds access and
system crashes.

src/main/target/BOTWINGF405/config.c [15-18]

-serialConfigMutable()->portConfigs[findSerialPortIndexByIdentifier(SERIAL_PORT_USART1)].functionMask = FUNCTION_RX_SERIAL;
-serialConfigMutable()->portConfigs[findSerialPortIndexByIdentifier(SERIAL_PORT_USART4)].functionMask = FUNCTION_MSP;
-serialConfigMutable()->portConfigs[findSerialPortIndexByIdentifier(SERIAL_PORT_USART4)].msp_baudrateIndex = BAUD_115200;
-serialConfigMutable()->portConfigs[findSerialPortIndexByIdentifier(SERIAL_PORT_USART2)].functionMask = FUNCTION_ESCSERIAL;
+int8_t portIndex;
 
+portIndex = findSerialPortIndexByIdentifier(SERIAL_PORT_USART1);
+if (portIndex != -1) {
+    serialConfigMutable()->portConfigs[portIndex].functionMask = FUNCTION_RX_SERIAL;
+}
+
+portIndex = findSerialPortIndexByIdentifier(SERIAL_PORT_USART4);
+if (portIndex != -1) {
+    serialConfigMutable()->portConfigs[portIndex].functionMask = FUNCTION_MSP;
+    serialConfigMutable()->portConfigs[portIndex].msp_baudrateIndex = BAUD_115200;
+}
+
+portIndex = findSerialPortIndexByIdentifier(SERIAL_PORT_USART2);
+if (portIndex != -1) {
+    serialConfigMutable()->portConfigs[portIndex].functionMask = FUNCTION_ESCSERIAL;
+}
+
  • [ ] Apply / Chat
Suggestion importance[1-10]: 5

__

Why: The suggestion correctly identifies a potential out-of-bounds access, which is a valid defensive programming practice, but the risk is low in this target-specific configuration file where the ports are guaranteed to exist.

Low
General
Configure second PINIO box as defined
Suggestion Impact:The commit added the exact line to configure the second PINIO box (USER2) as suggested.

code diff:

     pinioBoxConfigMutable()->permanentId[0] = BOX_PERMANENT_ID_USER1;
+	pinioBoxConfigMutable()->permanentId[1] = BOX_PERMANENT_ID_USER2;

Configure the second PINIO box (USER2) in src/main/target/BOTWINGF722/config.c
to match the two PINIO pins defined in the corresponding target.h file.

src/main/target/BOTWINGF722/config.c [25]

 pinioBoxConfigMutable()->permanentId[0] = BOX_PERMANENT_ID_USER1;
+pinioBoxConfigMutable()->permanentId[1] = BOX_PERMANENT_ID_USER2;

[Suggestion processed]

Suggestion importance[1-10]: 6

__

Why: The suggestion correctly identifies that the configuration for the second PINIO pin, defined in the header, is missing, likely an oversight. Applying this change would enable the intended hardware feature.

Low
  • [ ] Update

qodo-code-review[bot] avatar Oct 14 '25 11:10 qodo-code-review[bot]

I can merge this and it will be done as soon as someone clicks the merge here to accept my changes it:

https://github.com/PrateekShanker99/inav_custon_target/pull/1

sensei-hacker avatar Oct 14 '25 13:10 sensei-hacker