From ce87656949c51594f550462e8cb4bd021c719e7c Mon Sep 17 00:00:00 2001 From: dakefpv Date: Tue, 16 Dec 2025 17:30:38 +0800 Subject: [PATCH 01/42] Add new target DAKEFPVH743_SLIM --- .../target/DAKEFPVH743_SLIM/CMakeLists.txt | 1 + src/main/target/DAKEFPVH743_SLIM/config.c | 34 +++ src/main/target/DAKEFPVH743_SLIM/target.c | 61 ++++++ src/main/target/DAKEFPVH743_SLIM/target.h | 197 ++++++++++++++++++ 4 files changed, 293 insertions(+) create mode 100644 src/main/target/DAKEFPVH743_SLIM/CMakeLists.txt create mode 100644 src/main/target/DAKEFPVH743_SLIM/config.c create mode 100644 src/main/target/DAKEFPVH743_SLIM/target.c create mode 100644 src/main/target/DAKEFPVH743_SLIM/target.h diff --git a/src/main/target/DAKEFPVH743_SLIM/CMakeLists.txt b/src/main/target/DAKEFPVH743_SLIM/CMakeLists.txt new file mode 100644 index 00000000000..93c2d867499 --- /dev/null +++ b/src/main/target/DAKEFPVH743_SLIM/CMakeLists.txt @@ -0,0 +1 @@ +target_stm32h743xi(DAKEFPVH743_SLIM) diff --git a/src/main/target/DAKEFPVH743_SLIM/config.c b/src/main/target/DAKEFPVH743_SLIM/config.c new file mode 100644 index 00000000000..c8c3c081a95 --- /dev/null +++ b/src/main/target/DAKEFPVH743_SLIM/config.c @@ -0,0 +1,34 @@ +/* + * This file is part of INAV. + * + * INAV is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * INAV is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with INAV. If not, see . + */ + +#include +#include + +#include + +#include "io/serial.h" +#include "rx/rx.h" + +#include "io/piniobox.h" + +void targetConfiguration(void) +{ + pinioBoxConfigMutable()->permanentId[0] = BOX_PERMANENT_ID_USER1; + pinioBoxConfigMutable()->permanentId[1] = BOX_PERMANENT_ID_USER2; + pinioBoxConfigMutable()->permanentId[2] = BOX_PERMANENT_ID_USER3; + pinioBoxConfigMutable()->permanentId[3] = BOX_PERMANENT_ID_USER4; +} diff --git a/src/main/target/DAKEFPVH743_SLIM/target.c b/src/main/target/DAKEFPVH743_SLIM/target.c new file mode 100644 index 00000000000..af599ac23fd --- /dev/null +++ b/src/main/target/DAKEFPVH743_SLIM/target.c @@ -0,0 +1,61 @@ +/* + * This file is part of INAV. + * + * INAV is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * INAV is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with INAV. If not, see . + */ + + #include + + #include + #include "drivers/io.h" + #include "drivers/pwm_mapping.h" + #include "drivers/timer.h" + #include "drivers/bus.h" + #include "drivers/sensor.h" + + #include "drivers/pwm_output.h" + #include "common/maths.h" + #include "fc/config.h" + // Board hardware definitions - IMU1 slot + +BUSDEV_REGISTER_SPI_TAG(busdev_1_mpu6000, DEVHW_MPU6000, IMU_1_SPI_BUS, IMU_1_CS_PIN, IMU_1_IRQ_PIN, 0, DEVFLAGS_NONE, IMU_1_ALIGN); +BUSDEV_REGISTER_SPI_TAG(busdev_1_mpu6500, DEVHW_MPU6500, IMU_1_SPI_BUS, IMU_1_CS_PIN, IMU_1_IRQ_PIN, 0, DEVFLAGS_NONE, IMU_1_ALIGN); +BUSDEV_REGISTER_SPI_TAG(busdev_1_ICM42605, DEVHW_ICM42605, IMU_1_SPI_BUS, IMU_1_CS_PIN, IMU_1_IRQ_PIN, 0, DEVFLAGS_NONE, IMU_1_ALIGN); +BUSDEV_REGISTER_SPI_TAG(busdev_1_BMI270, DEVHW_BMI270, IMU_1_SPI_BUS, IMU_1_CS_PIN, IMU_1_IRQ_PIN, 0, DEVFLAGS_NONE, IMU_1_ALIGN); + +// // Board hardware definitions - IMU2 slot +BUSDEV_REGISTER_SPI_TAG(busdev_2_mpu6000, DEVHW_MPU6000, IMU_2_SPI_BUS, IMU_2_CS_PIN, IMU_2_IRQ_PIN, 1, DEVFLAGS_NONE, IMU_2_ALIGN); +BUSDEV_REGISTER_SPI_TAG(busdev_2_mpu6500, DEVHW_MPU6500, IMU_2_SPI_BUS, IMU_2_CS_PIN, IMU_2_IRQ_PIN, 1, DEVFLAGS_NONE, IMU_2_ALIGN); +BUSDEV_REGISTER_SPI_TAG(busdev_2_ICM42605, DEVHW_ICM42605, IMU_2_SPI_BUS, IMU_2_CS_PIN, IMU_2_IRQ_PIN, 1, DEVFLAGS_NONE, IMU_2_ALIGN); +BUSDEV_REGISTER_SPI_TAG(busdev_2_BMI270, DEVHW_BMI270, IMU_2_SPI_BUS, IMU_2_CS_PIN, IMU_2_IRQ_PIN, 1, DEVFLAGS_NONE, IMU_2_ALIGN); + +timerHardware_t timerHardware[] = { + DEF_TIM(TIM1, CH1, PE9, TIM_USE_OUTPUT_AUTO, 0, 0), // M1 + DEF_TIM(TIM1, CH2, PE11, TIM_USE_OUTPUT_AUTO, 0, 1), // M2 + DEF_TIM(TIM1, CH3, PE13, TIM_USE_OUTPUT_AUTO, 0, 2), // M3 + DEF_TIM(TIM1, CH4, PE14, TIM_USE_OUTPUT_AUTO, 0, 3), // M4 + DEF_TIM(TIM2, CH1, PA0, TIM_USE_OUTPUT_AUTO, 0, 4), // M5 + DEF_TIM(TIM2, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 5), // M6 + DEF_TIM(TIM2, CH3, PA2, TIM_USE_OUTPUT_AUTO, 0, 6), // M7 + DEF_TIM(TIM2, CH4, PA3, TIM_USE_OUTPUT_AUTO, 0, 7), // M8 DMA None + DEF_TIM(TIM4, CH1, PD12, TIM_USE_OUTPUT_AUTO, 0, 0), // S1 + DEF_TIM(TIM4, CH2, PD13, TIM_USE_OUTPUT_AUTO, 0, 0), // S2 DMA None + DEF_TIM(TIM4, CH3, PD14, TIM_USE_OUTPUT_AUTO, 0, 0), // S3 + DEF_TIM(TIM4, CH4, PD15, TIM_USE_OUTPUT_AUTO, 0, 0), // S4 + DEF_TIM(TIM15, CH1, PE5, TIM_USE_ANY, 0, 0), // CAMERA_CONTROL_PIN + DEF_TIM(TIM8, CH3, PC8, TIM_USE_ANY, 0, 0), // GYRO_1_CLKIN_PIN + DEF_TIM(TIM3, CH3, PB0, TIM_USE_LED, 0, 8), // LED_2812 +}; + +const int timerHardwareCount = sizeof(timerHardware) / sizeof(timerHardware[0]); diff --git a/src/main/target/DAKEFPVH743_SLIM/target.h b/src/main/target/DAKEFPVH743_SLIM/target.h new file mode 100644 index 00000000000..0d74f9ab9fd --- /dev/null +++ b/src/main/target/DAKEFPVH743_SLIM/target.h @@ -0,0 +1,197 @@ +/* + * This file is part of INAV. + * + * INAV is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * INAV is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with INAV. If not, see . + */ + +#pragma once + +#define TARGET_BOARD_IDENTIFIER "DAK7" +#define USBD_PRODUCT_STRING "DAKEFPV H743 SLIM" + +#define LED0 PD10 +#define LED1 PD11 +#define LED2 PA8 + +#define BEEPER_PIN PE10 +#define BEEPER_INVERTED +#define USE_DSHOT_DMAR +// Buses +#define USE_SPI +#define USE_SPI_DEVICE_1 + +#define SPI1_SCK_PIN PA5 +#define SPI1_MISO_PIN PA6 +#define SPI1_MOSI_PIN PA7 + +#define USE_SPI_DEVICE_2 +#define SPI2_SCK_PIN PB13 +#define SPI2_MISO_PIN PC2 +#define SPI2_MOSI_PIN PC3 + +#define USE_SPI_DEVICE_3 +#define SPI3_SCK_PIN PC10 +#define SPI3_MISO_PIN PC11 +#define SPI3_MOSI_PIN PC12 + +#define USE_SPI_DEVICE_4 +#define SPI4_SCK_PIN PE12 +#define SPI4_MISO_PIN PE5 +#define SPI4_MOSI_PIN PE6 + +#define USE_I2C +#define USE_I2C_DEVICE_2 +#define I2C2_SCL PB10 +#define I2C2_SDA PB11 + +#define DEFAULT_I2C_BUS BUS_I2C2 + +// GYRO +#define USE_DUAL_GYRO +#define USE_TARGET_IMU_HARDWARE_DESCRIPTORS // Don't use common busdev descriptors for IMU +#define USE_IMU_MPU6500 +#define USE_IMU_MPU6000 + +#define USE_IMU_ICM42605 +#define USE_IMU_BMI270 + +// IMU_1 is verified to work on OBF4V6 and Omnibus Fireworks board +# define IMU_1_CS_PIN PC9 +# define IMU_1_IRQ_PIN PD4 +# define IMU_1_SPI_BUS BUS_SPI1 +# define IMU_1_ALIGN CW0_DEG_FLIP +// IMU_2 is sketchy and was not verified on actual hardware +# define IMU_2_CS_PIN PB1 +# define IMU_2_IRQ_PIN PB2 +# define IMU_2_SPI_BUS BUS_SPI4 +# define IMU_2_ALIGN CW90_DEG_FLIP + +// M25P256 flash +#define USE_FLASHFS +#define USE_FLASH_M25P16 + +#define M25P16_SPI_BUS BUS_SPI3 +#define M25P16_CS_PIN PA15 + +// *************** SDIO SD BLACKBOX******************* +#define USE_SDCARD +#define USE_SDCARD_SDIO +#define SDCARD_SDIO_DEVICE SDIODEV_2 +#define SDCARD_SDIO_4BIT +#define SDCARD_SDIO2_CMD_ALT // spare pin + +#define ENABLE_BLACKBOX_LOGGING_ON_SDCARD_BY_DEFAULT + +// OSD +#define USE_MAX7456 +#define MAX7456_SPI_BUS BUS_SPI2 +#define MAX7456_CS_PIN PB12 + +// CAMERA_CONTROL +#define CAMERA_CONTROL_PIN PC8 // TIM8 CH3 + +// Serial ports +#define USE_VCP + +#define USE_UART1 +#define USE_UART2 +#define USE_UART3 +#define USE_UART4 +#define USE_UART5 +#define USE_UART6 +#define USE_UART7 +#define USE_UART8 +#define UART1_TX_PIN PA9 +#define UART1_RX_PIN PA10 +#define UART2_TX_PIN PD5 +#define UART2_RX_PIN PD6 +#define UART3_TX_PIN PD8 +#define UART3_RX_PIN PD9 +#define UART4_TX_PIN PB9 +#define UART4_RX_PIN PB8 +#define UART5_TX_PIN PB6 +#define UART5_RX_PIN PB5 +#define UART6_TX_PIN PC6 +#define UART6_RX_PIN PC7 +#define UART7_TX_PIN PE8 +#define UART7_RX_PIN PE7 +#define UART8_TX_PIN PE1 +#define UART8_RX_PIN PE0 + +#define SERIAL_PORT_COUNT 9 + +#define DEFAULT_RX_TYPE RX_TYPE_SERIAL +#define SERIALRX_PROVIDER SERIALRX_CRSF +#define SERIALRX_UART SERIAL_PORT_USART5 +#define GPS_UART SERIAL_PORT_USART1 + +//Baro +#define USE_BARO +#define USE_BARO_BMP280 +#define USE_BARO_DPS310 +#define BARO_I2C_BUS DEFAULT_I2C_BUS + +// Mag +#define USE_MAG +#define MAG_I2C_BUS DEFAULT_I2C_BUS +#define USE_MAG_ALL + +#define TEMPERATURE_I2C_BUS DEFAULT_I2C_BUS + +#define USE_RANGEFINDER +#define USE_RANGEFINDER_MSP +#define RANGEFINDER_I2C_BUS DEFAULT_I2C_BUS + +#define PITOT_I2C_BUS DEFAULT_I2C_BUS + +// ADC +#define USE_ADC +#define ADC_INSTANCE ADC1 +#define ADC_CHANNEL_1_PIN PA4 +#define ADC_CHANNEL_2_PIN PC5 +#define ADC_CHANNEL_3_PIN PC0 +#define ADC_CHANNEL_4_PIN PC4 +#define VBAT_ADC_CHANNEL ADC_CHN_1 +#define RSSI_ADC_CHANNEL ADC_CHN_2 +#define CURRENT_METER_ADC_CHANNEL ADC_CHN_3 +#define AIRSPEED_ADC_CHANNEL ADC_CHN_4 + +#define USE_LED_STRIP +#define WS2811_PIN PB0 // TIM3 CH3 + +#define DEFAULT_FEATURES (FEATURE_OSD | FEATURE_CURRENT_METER | FEATURE_VBAT | FEATURE_TELEMETRY | FEATURE_LED_STRIP | FEATURE_GPS | FEATURE_BLACKBOX) + +#define USE_SERIAL_4WAY_BLHELI_INTERFACE + +#define TARGET_IO_PORTA 0xffff +#define TARGET_IO_PORTB 0xffff +#define TARGET_IO_PORTC 0xffff +#define TARGET_IO_PORTD 0xffff +#define TARGET_IO_PORTE 0xffff + +#define USE_DSHOT +#define USE_ESC_SENSOR + +#define MAX_PWM_OUTPUT_PORTS 12 + +// PINIO +#define USE_PINIO +#define USE_PINIOBOX +#define PINIO1_PIN PE2 +#define PINIO2_PIN PE3 +#define PINIO3_PIN PE4 +#define PINIO4_PIN PD2 + +// VBAT 10K/160K +#define VBAT_SCALE_DEFAULT 1600 From 59532eac7cc86957337dccf6bce9411d597eb4eb Mon Sep 17 00:00:00 2001 From: dakefpv Date: Tue, 16 Dec 2025 17:30:38 +0800 Subject: [PATCH 02/42] Fix the incorrect pins PC8 and PB7 --- src/main/target/DAKEFPVH743_SLIM/target.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/target/DAKEFPVH743_SLIM/target.c b/src/main/target/DAKEFPVH743_SLIM/target.c index af599ac23fd..6bf84f5ee19 100644 --- a/src/main/target/DAKEFPVH743_SLIM/target.c +++ b/src/main/target/DAKEFPVH743_SLIM/target.c @@ -53,8 +53,8 @@ timerHardware_t timerHardware[] = { DEF_TIM(TIM4, CH2, PD13, TIM_USE_OUTPUT_AUTO, 0, 0), // S2 DMA None DEF_TIM(TIM4, CH3, PD14, TIM_USE_OUTPUT_AUTO, 0, 0), // S3 DEF_TIM(TIM4, CH4, PD15, TIM_USE_OUTPUT_AUTO, 0, 0), // S4 - DEF_TIM(TIM15, CH1, PE5, TIM_USE_ANY, 0, 0), // CAMERA_CONTROL_PIN - DEF_TIM(TIM8, CH3, PC8, TIM_USE_ANY, 0, 0), // GYRO_1_CLKIN_PIN + DEF_TIM(TIM8, CH3, PC8, TIM_USE_ANY, 0, 0), // CAMERA_CONTROL_PIN + DEF_TIM(TIM17, CH1N,PB7, TIM_USE_ANY, 0, 0), // GYRO_1_CLKIN_PIN DEF_TIM(TIM3, CH3, PB0, TIM_USE_LED, 0, 8), // LED_2812 }; From cebc906a0d7dd3d5c5826bfe2205bd4ff9c2d432 Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 22 Dec 2025 01:49:51 -0600 Subject: [PATCH 03/42] Refactor OMNIBUSF4 targets into separate directories Split OMNIBUSF4 mega-target into 4 directories to improve maintainability: - DYSF4: DYSF4PRO, DYSF4PROV2 - OMNIBUSF4: Base OMNIBUSF4 variant only - OMNIBUSF4PRO: OMNIBUSF4PRO, OMNIBUSF4V3, OMNIBUSF4V3_ICM - OMNIBUSF4V3_SS: Softserial variants (S6_SS, S5S6_SS, S5_S6_2SS) Each directory now contains only the code relevant to its variants, with irrelevant preprocessor conditionals removed. Changes: - Reduced DYSF4/target.h from 271 to 169 lines (37% reduction) - Reduced preprocessor conditionals from 18 to 4 in DYSF4 files - All 11 targets build successfully and produce identical binaries --- src/main/target/DYSF4/CMakeLists.txt | 2 + src/main/target/DYSF4/target.c | 47 ++++ src/main/target/DYSF4/target.h | 169 +++++++++++++ src/main/target/OMNIBUSF4/CMakeLists.txt | 10 - src/main/target/OMNIBUSF4PRO/CMakeLists.txt | 5 + src/main/target/OMNIBUSF4PRO/target.c | 61 +++++ src/main/target/OMNIBUSF4PRO/target.h | 232 ++++++++++++++++++ src/main/target/OMNIBUSF4V3_SS/CMakeLists.txt | 4 + src/main/target/OMNIBUSF4V3_SS/target.c | 60 +++++ src/main/target/OMNIBUSF4V3_SS/target.h | 209 ++++++++++++++++ 10 files changed, 789 insertions(+), 10 deletions(-) create mode 100644 src/main/target/DYSF4/CMakeLists.txt create mode 100644 src/main/target/DYSF4/target.c create mode 100644 src/main/target/DYSF4/target.h create mode 100644 src/main/target/OMNIBUSF4PRO/CMakeLists.txt create mode 100644 src/main/target/OMNIBUSF4PRO/target.c create mode 100644 src/main/target/OMNIBUSF4PRO/target.h create mode 100644 src/main/target/OMNIBUSF4V3_SS/CMakeLists.txt create mode 100644 src/main/target/OMNIBUSF4V3_SS/target.c create mode 100644 src/main/target/OMNIBUSF4V3_SS/target.h diff --git a/src/main/target/DYSF4/CMakeLists.txt b/src/main/target/DYSF4/CMakeLists.txt new file mode 100644 index 00000000000..ec00b5acc49 --- /dev/null +++ b/src/main/target/DYSF4/CMakeLists.txt @@ -0,0 +1,2 @@ +target_stm32f405xg(DYSF4PRO) +target_stm32f405xg(DYSF4PROV2) diff --git a/src/main/target/DYSF4/target.c b/src/main/target/DYSF4/target.c new file mode 100644 index 00000000000..2eed0188f97 --- /dev/null +++ b/src/main/target/DYSF4/target.c @@ -0,0 +1,47 @@ +/* + * This file is part of Cleanflight. + * + * Cleanflight is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Cleanflight is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Cleanflight. If not, see . + */ + +#include + +#include +#include "drivers/io.h" +#include "drivers/pwm_mapping.h" +#include "drivers/timer.h" +#include "drivers/bus.h" + +timerHardware_t timerHardware[] = { + + DEF_TIM(TIM3, CH3, PB0, TIM_USE_OUTPUT_AUTO, 0, 0), // S1_OUT D1_ST7 + DEF_TIM(TIM3, CH4, PB1, TIM_USE_OUTPUT_AUTO, 0, 0), // S2_OUT D1_ST2 + DEF_TIM(TIM2, CH4, PA3, TIM_USE_OUTPUT_AUTO, 0, 1), // S3_OUT D1_ST6 + DEF_TIM(TIM2, CH3, PA2, TIM_USE_OUTPUT_AUTO, 0, 0), // S4_OUT D1_ST1 + + // { TIM9, IO_TAG(PA3), TIM_Channel_2, 1, IOCFG_AF_PP_PD, GPIO_AF_TIM9, TIM_USE_OUTPUT_AUTO }, // MOTOR_3 + DEF_TIM(TIM5, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 0), // S5_OUT MOTOR, SERVO or LED + DEF_TIM(TIM1, CH1, PA8, TIM_USE_OUTPUT_AUTO, 0, 0), // S6_OUT + + + // DEF_TIM(TIM12, CH1, PB14, TIM_USE_PPM, 0, 0), // PPM + DEF_TIM(TIM12, CH2, PB15, TIM_USE_ANY, 0, 0), // S2_IN + DEF_TIM(TIM8, CH1, PC6, TIM_USE_ANY, 0, 0), // S3_IN, UART6_TX + DEF_TIM(TIM8, CH2, PC7, TIM_USE_ANY, 0, 0), // S4_IN, UART6_RX + DEF_TIM(TIM8, CH3, PC8, TIM_USE_ANY, 0, 0), // S5_IN // pad labelled CH5 on OMNIBUSF4PRO + DEF_TIM(TIM8, CH4, PC9, TIM_USE_ANY, 0, 0), // S6_IN // pad labelled CH6 on OMNIBUSF4PRO + +}; + +const int timerHardwareCount = sizeof(timerHardware) / sizeof(timerHardware[0]); diff --git a/src/main/target/DYSF4/target.h b/src/main/target/DYSF4/target.h new file mode 100644 index 00000000000..24d5aa0dac4 --- /dev/null +++ b/src/main/target/DYSF4/target.h @@ -0,0 +1,169 @@ +/* + * This file is part of Cleanflight. + * + * Cleanflight is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Cleanflight is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Cleanflight. If not, see . + */ + +#pragma once + +//Same target as OMNIBUSF4PRO with LED strip in M5 +//Same target as OMNIBUSF4V3 with softserial in M5 and M6 + +#if defined(DYSF4PRO) +#define TARGET_BOARD_IDENTIFIER "DYS4" +#elif defined(DYSF4PROV2) +#define TARGET_BOARD_IDENTIFIER "DY42" +#else +#define TARGET_BOARD_IDENTIFIER "OBF4" +#endif + +#if defined(DYSF4PRO) || defined(DYSF4PROV2) +#define USBD_PRODUCT_STRING "DysF4Pro" +#else +#define USBD_PRODUCT_STRING "Omnibus F4" +#endif + +#define LED0 PB5 + +#define BEEPER PB4 +#define BEEPER_INVERTED + +#if defined(DYSF4PROV2) +#define USE_I2C +#define USE_I2C_DEVICE_1 +#define I2C1_SCL PB8 +#define I2C1_SDA PB9 +#define I2C_EXT_BUS BUS_I2C1 +#else +#define USE_I2C +#define USE_I2C_DEVICE_2 +#define I2C_DEVICE_2_SHARES_UART3 +#define I2C_EXT_BUS BUS_I2C2 +#endif + +#define UG2864_I2C_BUS I2C_EXT_BUS + +#define MPU6000_CS_PIN PA4 +#define MPU6000_SPI_BUS BUS_SPI1 + + #define USE_IMU_MPU6000 + #define IMU_MPU6000_ALIGN CW180_DEG + +// Support for OMNIBUS F4 PRO CORNER - it has ICM20608 instead of MPU6000 + +#define USE_MAG +#define MAG_I2C_BUS I2C_EXT_BUS +#define USE_MAG_ALL + +#define TEMPERATURE_I2C_BUS I2C_EXT_BUS + +#define USE_BARO + + #define BARO_I2C_BUS I2C_EXT_BUS + #define USE_BARO_BMP085 + #define USE_BARO_BMP280 + #define USE_BARO_MS5611 + +#define PITOT_I2C_BUS I2C_EXT_BUS + +#define USE_RANGEFINDER +#define RANGEFINDER_I2C_BUS I2C_EXT_BUS + +#define USE_VCP +#define VBUS_SENSING_PIN PC5 +#define VBUS_SENSING_ENABLED + + +#define USE_UART1 +#define UART1_RX_PIN PA10 +#define UART1_TX_PIN PA9 +#define UART1_AHB1_PERIPHERALS RCC_AHB1Periph_DMA2 + +#define USE_UART3 +#define UART3_RX_PIN PB11 +#define UART3_TX_PIN PB10 + +#define USE_UART6 +#define UART6_RX_PIN PC7 +#define UART6_TX_PIN PC6 + +#define USE_SOFTSERIAL1 +#define SOFTSERIAL_1_RX_PIN PC8 // pad labelled CH5 on OMNIBUSF4PRO +#define SOFTSERIAL_1_TX_PIN PC9 // pad labelled CH6 on OMNIBUSF4PRO + +#define SERIAL_PORT_COUNT 5 // VCP, USART1, USART3, USART6, SOFTSERIAL1 + +#define DEFAULT_RX_TYPE RX_TYPE_SERIAL +#define SERIALRX_PROVIDER SERIALRX_SBUS +#define SERIALRX_UART SERIAL_PORT_USART1 + +#define USE_SPI + +#define USE_SPI_DEVICE_1 + + +#define USE_SPI_DEVICE_3 + #define SPI3_NSS_PIN PB3 +#define SPI3_SCK_PIN PC10 +#define SPI3_MISO_PIN PC11 +#define SPI3_MOSI_PIN PC12 + +#define USE_MAX7456 +#define MAX7456_SPI_BUS BUS_SPI3 +#define MAX7456_CS_PIN PA15 + + #define ENABLE_BLACKBOX_LOGGING_ON_SPIFLASH_BY_DEFAULT + #define M25P16_CS_PIN SPI3_NSS_PIN + #define M25P16_SPI_BUS BUS_SPI3 + #define USE_FLASHFS + #define USE_FLASH_M25P16 + +#define USE_ADC +#define ADC_CHANNEL_1_PIN PC1 +#define ADC_CHANNEL_2_PIN PC2 + +#ifdef DYSF4PRO + #define ADC_CHANNEL_3_PIN PC3 +#else + #define ADC_CHANNEL_3_PIN PA0 +#endif + +#define CURRENT_METER_ADC_CHANNEL ADC_CHN_1 +#define VBAT_ADC_CHANNEL ADC_CHN_2 +#define RSSI_ADC_CHANNEL ADC_CHN_3 + +#define SENSORS_SET (SENSOR_ACC|SENSOR_MAG|SENSOR_BARO) + +#define USE_LED_STRIP + #define WS2811_PIN PA1 + +#define DISABLE_RX_PWM_FEATURE +#define DEFAULT_FEATURES (FEATURE_TX_PROF_SEL | FEATURE_BLACKBOX | FEATURE_VBAT | FEATURE_OSD) + +#define USE_SPEKTRUM_BIND +#define BIND_PIN PB11 // USART3 RX + +#define USE_SERIAL_4WAY_BLHELI_INTERFACE + +// Number of available PWM outputs +#define MAX_PWM_OUTPUT_PORTS 6 +#define TARGET_MOTOR_COUNT 6 +#define USE_DSHOT +#define USE_ESC_SENSOR + +#define TARGET_IO_PORTA 0xffff +#define TARGET_IO_PORTB 0xffff +#define TARGET_IO_PORTC 0xffff +#define TARGET_IO_PORTD 0xffff + diff --git a/src/main/target/OMNIBUSF4/CMakeLists.txt b/src/main/target/OMNIBUSF4/CMakeLists.txt index a6ccb483bf5..28f13c7cd5b 100644 --- a/src/main/target/OMNIBUSF4/CMakeLists.txt +++ b/src/main/target/OMNIBUSF4/CMakeLists.txt @@ -1,11 +1 @@ -target_stm32f405xg(DYSF4PRO) -target_stm32f405xg(DYSF4PROV2) target_stm32f405xg(OMNIBUSF4) -# the OMNIBUSF4SD has an SDCARD instead of flash, a BMP280 baro and therefore a slightly different ppm/pwm and SPI mapping -target_stm32f405xg(OMNIBUSF4PRO) -target_stm32f405xg(OMNIBUSF4V3_S5_S6_2SS) -target_stm32f405xg(OMNIBUSF4V3_S5S6_SS) -target_stm32f405xg(OMNIBUSF4V3_S6_SS) -# OMNIBUSF4V3 is a (almost identical) variant of OMNIBUSF4PRO target, -# except for an inverter on UART6. -target_stm32f405xg(OMNIBUSF4V3) diff --git a/src/main/target/OMNIBUSF4PRO/CMakeLists.txt b/src/main/target/OMNIBUSF4PRO/CMakeLists.txt new file mode 100644 index 00000000000..e09984ac0a9 --- /dev/null +++ b/src/main/target/OMNIBUSF4PRO/CMakeLists.txt @@ -0,0 +1,5 @@ +# OMNIBUSF4PRO has SD card, BMP280 baro +target_stm32f405xg(OMNIBUSF4PRO) +# OMNIBUSF4V3 is similar to PRO but with UART6 inverter +target_stm32f405xg(OMNIBUSF4V3) +target_stm32f405xg(OMNIBUSF4V3_ICM SKIP_RELEASES) diff --git a/src/main/target/OMNIBUSF4PRO/target.c b/src/main/target/OMNIBUSF4PRO/target.c new file mode 100644 index 00000000000..9aad85a14af --- /dev/null +++ b/src/main/target/OMNIBUSF4PRO/target.c @@ -0,0 +1,61 @@ +/* + * This file is part of Cleanflight. + * + * Cleanflight is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Cleanflight is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Cleanflight. If not, see . + */ + +#include + +#include +#include "drivers/io.h" +#include "drivers/pwm_mapping.h" +#include "drivers/timer.h" +#include "drivers/bus.h" + +timerHardware_t timerHardware[] = { + + DEF_TIM(TIM3, CH3, PB0, TIM_USE_OUTPUT_AUTO, 0, 0), // S1_OUT D1_ST7 + DEF_TIM(TIM3, CH4, PB1, TIM_USE_OUTPUT_AUTO, 0, 0), // S2_OUT D1_ST2 + DEF_TIM(TIM2, CH4, PA3, TIM_USE_OUTPUT_AUTO, 0, 1), // S3_OUT D1_ST6 + DEF_TIM(TIM2, CH3, PA2, TIM_USE_OUTPUT_AUTO, 0, 0), // S4_OUT D1_ST1 + + // { TIM9, IO_TAG(PA3), TIM_Channel_2, 1, IOCFG_AF_PP_PD, GPIO_AF_TIM9, TIM_USE_OUTPUT_AUTO }, // MOTOR_3 +#if (defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3)) && !(defined(OMNIBUSF4PRO_LEDSTRIPM5) || defined(OMNIBUSF4V3_S6_SS) || defined(OMNIBUSF4V3_S5S6_SS) || defined(OMNIBUSF4V3_S5_S6_2SS)) + + DEF_TIM(TIM5, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 0), // S5_OUT + DEF_TIM(TIM1, CH1, PA8, TIM_USE_OUTPUT_AUTO, 0, 0), // S6_OUT +#else + DEF_TIM(TIM5, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 0), // S5_OUT MOTOR, SERVO or LED + DEF_TIM(TIM1, CH1, PA8, TIM_USE_OUTPUT_AUTO, 0, 0), // S6_OUT +#endif + +#if (defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3)) + DEF_TIM(TIM4, CH1, PB6, TIM_USE_LED, 0, 0), // LED strip for F4 V2 / F4-Pro-0X and later (RCD_CS for F4) +#endif + +#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) + // DEF_TIM(TIM10, CH1, PB8, TIM_USE_PPM, 0, 0), // PPM + DEF_TIM(TIM4, CH4, PB9, TIM_USE_ANY, 0, 0), // S2_IN +#else + // DEF_TIM(TIM12, CH1, PB14, TIM_USE_PPM, 0, 0), // PPM + DEF_TIM(TIM12, CH2, PB15, TIM_USE_ANY, 0, 0), // S2_IN +#endif + DEF_TIM(TIM8, CH1, PC6, TIM_USE_ANY, 0, 0), // S3_IN, UART6_TX + DEF_TIM(TIM8, CH2, PC7, TIM_USE_ANY, 0, 0), // S4_IN, UART6_RX + DEF_TIM(TIM8, CH3, PC8, TIM_USE_ANY, 0, 0), // S5_IN // pad labelled CH5 on OMNIBUSF4PRO + DEF_TIM(TIM8, CH4, PC9, TIM_USE_ANY, 0, 0), // S6_IN // pad labelled CH6 on OMNIBUSF4PRO + +}; + +const int timerHardwareCount = sizeof(timerHardware) / sizeof(timerHardware[0]); diff --git a/src/main/target/OMNIBUSF4PRO/target.h b/src/main/target/OMNIBUSF4PRO/target.h new file mode 100644 index 00000000000..74829342c2c --- /dev/null +++ b/src/main/target/OMNIBUSF4PRO/target.h @@ -0,0 +1,232 @@ +/* + * This file is part of Cleanflight. + * + * Cleanflight is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Cleanflight is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Cleanflight. If not, see . + */ + +#pragma once + +//Same target as OMNIBUSF4PRO with LED strip in M5 +#ifdef OMNIBUSF4PRO_LEDSTRIPM5 +#define OMNIBUSF4PRO +#endif +//Same target as OMNIBUSF4V3 with softserial in M5 and M6 + +#ifdef OMNIBUSF4PRO +#define TARGET_BOARD_IDENTIFIER "OBSD" +#elif defined(OMNIBUSF4V3) +#define TARGET_BOARD_IDENTIFIER "OB43" +#else +#define TARGET_BOARD_IDENTIFIER "OBF4" +#endif + +#define USBD_PRODUCT_STRING "Omnibus F4" + +#define LED0 PB5 + +#define BEEPER PB4 +#define BEEPER_INVERTED + +#define USE_I2C +#define USE_I2C_DEVICE_2 +#define I2C_DEVICE_2_SHARES_UART3 +#define I2C_EXT_BUS BUS_I2C2 + +#define UG2864_I2C_BUS I2C_EXT_BUS + +#define MPU6000_CS_PIN PA4 +#define MPU6000_SPI_BUS BUS_SPI1 + +#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) + #define USE_IMU_MPU6000 + #define IMU_MPU6000_ALIGN CW270_DEG +#else + #define USE_IMU_MPU6000 + #define IMU_MPU6000_ALIGN CW180_DEG +#endif + +// Support for OMNIBUS F4 PRO CORNER - it has ICM20608 instead of MPU6000 +#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) + #define MPU6500_CS_PIN MPU6000_CS_PIN + #define MPU6500_SPI_BUS MPU6000_SPI_BUS + #define USE_IMU_MPU6500 + #define IMU_MPU6500_ALIGN IMU_MPU6000_ALIGN + + //BMI270 + #define USE_IMU_BMI270 + #define IMU_BMI270_ALIGN IMU_MPU6000_ALIGN + #define BMI270_SPI_BUS MPU6000_SPI_BUS + #define BMI270_CS_PIN MPU6000_CS_PIN +#endif + +#define USE_MAG +#define MAG_I2C_BUS I2C_EXT_BUS +#define USE_MAG_ALL + +#define TEMPERATURE_I2C_BUS I2C_EXT_BUS + +#define USE_BARO + +#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) + #define USE_BARO_BMP280 + #define BMP280_SPI_BUS BUS_SPI3 + #define BMP280_CS_PIN PB3 // v1 + // Support external barometers + #define BARO_I2C_BUS I2C_EXT_BUS + #define USE_BARO_BMP085 + #define USE_BARO_MS5611 +#else + #define BARO_I2C_BUS I2C_EXT_BUS + #define USE_BARO_BMP085 + #define USE_BARO_BMP280 + #define USE_BARO_MS5611 +#endif + +#define PITOT_I2C_BUS I2C_EXT_BUS + +#define USE_RANGEFINDER +#define RANGEFINDER_I2C_BUS I2C_EXT_BUS + +#define USE_VCP +#define VBUS_SENSING_PIN PC5 +#define VBUS_SENSING_ENABLED + +#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) +#define USE_UART_INVERTER +#endif + +#define USE_UART1 +#define UART1_RX_PIN PA10 +#define UART1_TX_PIN PA9 +#define UART1_AHB1_PERIPHERALS RCC_AHB1Periph_DMA2 +#if defined(OMNIBUSF4PRO) +#define INVERTER_PIN_UART1_RX PC0 // PC0 has never been used as inverter control on genuine OMNIBUS F4 variants, but leave it as is since some clones actually implement it. +#endif + +#define USE_UART3 +#define UART3_RX_PIN PB11 +#define UART3_TX_PIN PB10 + +#define USE_UART6 +#define UART6_RX_PIN PC7 +#define UART6_TX_PIN PC6 +#if defined(OMNIBUSF4V3) + #define INVERTER_PIN_UART6_RX PC8 + #define INVERTER_PIN_UART6_TX PC9 +#endif + +#if defined(OMNIBUSF4V3) && !(defined(OMNIBUSF4V3_S6_SS) || defined(OMNIBUSF4V3_S5S6_SS) || defined(OMNIBUSF4V3_S5_S6_2SS)) +#define USE_SOFTSERIAL1 +#define SOFTSERIAL_1_RX_PIN PC6 // shared with UART6 TX +#define SOFTSERIAL_1_TX_PIN PC6 // shared with UART6 TX + +#define SERIAL_PORT_COUNT 5 // VCP, USART1, USART3, USART6, SOFTSERIAL1 + +#else // One softserial on versions other than OMNIBUSF4V3 +#define USE_SOFTSERIAL1 +#define SOFTSERIAL_1_RX_PIN PC8 // pad labelled CH5 on OMNIBUSF4PRO +#define SOFTSERIAL_1_TX_PIN PC9 // pad labelled CH6 on OMNIBUSF4PRO + +#define SERIAL_PORT_COUNT 5 // VCP, USART1, USART3, USART6, SOFTSERIAL1 +#endif + +#define DEFAULT_RX_TYPE RX_TYPE_SERIAL +#define SERIALRX_PROVIDER SERIALRX_SBUS +#define SERIALRX_UART SERIAL_PORT_USART1 + +#define USE_SPI + +#define USE_SPI_DEVICE_1 + +#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) + #define USE_SPI_DEVICE_2 + #define SPI2_NSS_PIN PB12 + #define SPI2_SCK_PIN PB13 + #define SPI2_MISO_PIN PB14 + #define SPI2_MOSI_PIN PB15 +#endif + +#define USE_SPI_DEVICE_3 +#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) + #define SPI3_NSS_PIN PA15 +#else + #define SPI3_NSS_PIN PB3 +#endif +#define SPI3_SCK_PIN PC10 +#define SPI3_MISO_PIN PC11 +#define SPI3_MOSI_PIN PC12 + +#define USE_MAX7456 +#define MAX7456_SPI_BUS BUS_SPI3 +#define MAX7456_CS_PIN PA15 + +#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) + #define ENABLE_BLACKBOX_LOGGING_ON_SDCARD_BY_DEFAULT + #define USE_SDCARD + #define USE_SDCARD_SPI + + #define SDCARD_SPI_BUS BUS_SPI2 + #define SDCARD_CS_PIN SPI2_NSS_PIN + + #define SDCARD_DETECT_PIN PB7 + #define SDCARD_DETECT_INVERTED +#else + #define ENABLE_BLACKBOX_LOGGING_ON_SPIFLASH_BY_DEFAULT + #define M25P16_CS_PIN SPI3_NSS_PIN + #define M25P16_SPI_BUS BUS_SPI3 + #define USE_FLASHFS + #define USE_FLASH_M25P16 +#endif + +#define USE_ADC +#define ADC_CHANNEL_1_PIN PC1 +#define ADC_CHANNEL_2_PIN PC2 + + #define ADC_CHANNEL_3_PIN PA0 + +#define CURRENT_METER_ADC_CHANNEL ADC_CHN_1 +#define VBAT_ADC_CHANNEL ADC_CHN_2 +#define RSSI_ADC_CHANNEL ADC_CHN_3 + +#define SENSORS_SET (SENSOR_ACC|SENSOR_MAG|SENSOR_BARO) + +#define USE_LED_STRIP +#if (defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3)) && !defined(OMNIBUSF4PRO_LEDSTRIPM5) + #define WS2811_PIN PB6 +#else + #define WS2811_PIN PA1 +#endif + +#define DISABLE_RX_PWM_FEATURE +#define DEFAULT_FEATURES (FEATURE_TX_PROF_SEL | FEATURE_BLACKBOX | FEATURE_VBAT | FEATURE_OSD) + +#define USE_SPEKTRUM_BIND +#define BIND_PIN PB11 // USART3 RX + +#define USE_SERIAL_4WAY_BLHELI_INTERFACE + +// Number of available PWM outputs +#define MAX_PWM_OUTPUT_PORTS 6 +#define TARGET_MOTOR_COUNT 6 +#define USE_DSHOT +#define USE_ESC_SENSOR + +#define TARGET_IO_PORTA 0xffff +#define TARGET_IO_PORTB 0xffff +#define TARGET_IO_PORTC 0xffff +#define TARGET_IO_PORTD 0xffff + +#ifdef OMNIBUSF4PRO +#define CURRENT_METER_SCALE 265 +#endif diff --git a/src/main/target/OMNIBUSF4V3_SS/CMakeLists.txt b/src/main/target/OMNIBUSF4V3_SS/CMakeLists.txt new file mode 100644 index 00000000000..321eeb211d1 --- /dev/null +++ b/src/main/target/OMNIBUSF4V3_SS/CMakeLists.txt @@ -0,0 +1,4 @@ +# OMNIBUSF4V3 softserial variants with different S5/S6 timer configurations +target_stm32f405xg(OMNIBUSF4V3_S6_SS) +target_stm32f405xg(OMNIBUSF4V3_S5S6_SS) +target_stm32f405xg(OMNIBUSF4V3_S5_S6_2SS) diff --git a/src/main/target/OMNIBUSF4V3_SS/target.c b/src/main/target/OMNIBUSF4V3_SS/target.c new file mode 100644 index 00000000000..ed38a77a51a --- /dev/null +++ b/src/main/target/OMNIBUSF4V3_SS/target.c @@ -0,0 +1,60 @@ +/* + * This file is part of Cleanflight. + * + * Cleanflight is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Cleanflight is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Cleanflight. If not, see . + */ + +#include + +#include +#include "drivers/io.h" +#include "drivers/pwm_mapping.h" +#include "drivers/timer.h" +#include "drivers/bus.h" + +timerHardware_t timerHardware[] = { + + DEF_TIM(TIM3, CH3, PB0, TIM_USE_OUTPUT_AUTO, 0, 0), // S1_OUT D1_ST7 + DEF_TIM(TIM3, CH4, PB1, TIM_USE_OUTPUT_AUTO, 0, 0), // S2_OUT D1_ST2 + DEF_TIM(TIM2, CH4, PA3, TIM_USE_OUTPUT_AUTO, 0, 1), // S3_OUT D1_ST6 + DEF_TIM(TIM2, CH3, PA2, TIM_USE_OUTPUT_AUTO, 0, 0), // S4_OUT D1_ST1 + + // { TIM9, IO_TAG(PA3), TIM_Channel_2, 1, IOCFG_AF_PP_PD, GPIO_AF_TIM9, TIM_USE_OUTPUT_AUTO }, // MOTOR_3 +#if (defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3)) && !(defined(OMNIBUSF4PRO_LEDSTRIPM5) || defined(OMNIBUSF4V3_S6_SS) || defined(OMNIBUSF4V3_S5S6_SS) || defined(OMNIBUSF4V3_S5_S6_2SS)) + + DEF_TIM(TIM5, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 0), // S5_OUT + DEF_TIM(TIM1, CH1, PA8, TIM_USE_OUTPUT_AUTO, 0, 0), // S6_OUT +#elif defined(OMNIBUSF4V3_S5S6_SS) || defined(OMNIBUSF4V3_S5_S6_2SS) + DEF_TIM(TIM5, CH2, PA1, TIM_USE_ANY, 0, 0), // S5_OUT SOFTSERIAL + DEF_TIM(TIM1, CH1, PA8, TIM_USE_ANY, 0, 0), // S6_OUT SOFTSERIAL +#elif defined(OMNIBUSF4V3_S6_SS) + DEF_TIM(TIM5, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 0), // S5_OUT + DEF_TIM(TIM1, CH1, PA8, TIM_USE_ANY, 0, 0), // S6_OUT SOFTSERIAL +#else + DEF_TIM(TIM5, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 0), // S5_OUT MOTOR, SERVO or LED + DEF_TIM(TIM1, CH1, PA8, TIM_USE_OUTPUT_AUTO, 0, 0), // S6_OUT +#endif + + DEF_TIM(TIM4, CH1, PB6, TIM_USE_LED, 0, 0), // LED strip for F4 V2 / F4-Pro-0X and later (RCD_CS for F4) + + // DEF_TIM(TIM10, CH1, PB8, TIM_USE_PPM, 0, 0), // PPM + DEF_TIM(TIM4, CH4, PB9, TIM_USE_ANY, 0, 0), // S2_IN + DEF_TIM(TIM8, CH1, PC6, TIM_USE_ANY, 0, 0), // S3_IN, UART6_TX + DEF_TIM(TIM8, CH2, PC7, TIM_USE_ANY, 0, 0), // S4_IN, UART6_RX + DEF_TIM(TIM8, CH3, PC8, TIM_USE_ANY, 0, 0), // S5_IN // pad labelled CH5 on OMNIBUSF4PRO + DEF_TIM(TIM8, CH4, PC9, TIM_USE_ANY, 0, 0), // S6_IN // pad labelled CH6 on OMNIBUSF4PRO + +}; + +const int timerHardwareCount = sizeof(timerHardware) / sizeof(timerHardware[0]); diff --git a/src/main/target/OMNIBUSF4V3_SS/target.h b/src/main/target/OMNIBUSF4V3_SS/target.h new file mode 100644 index 00000000000..4d3355eed9c --- /dev/null +++ b/src/main/target/OMNIBUSF4V3_SS/target.h @@ -0,0 +1,209 @@ +/* + * This file is part of Cleanflight. + * + * Cleanflight is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Cleanflight is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Cleanflight. If not, see . + */ + +#pragma once + +//Same target as OMNIBUSF4PRO with LED strip in M5 +//Same target as OMNIBUSF4V3 with softserial in M5 and M6 +#if defined(OMNIBUSF4V3_S6_SS) || defined(OMNIBUSF4V3_S5S6_SS) || defined(OMNIBUSF4V3_S5_S6_2SS) +#define OMNIBUSF4V3 +#endif + +#define TARGET_BOARD_IDENTIFIER "OB43" + +#define USBD_PRODUCT_STRING "Omnibus F4" + +#define LED0 PB5 + +#define BEEPER PB4 +#define BEEPER_INVERTED + +#define USE_I2C +#define USE_I2C_DEVICE_2 +#define I2C_DEVICE_2_SHARES_UART3 +#define I2C_EXT_BUS BUS_I2C2 + +#define UG2864_I2C_BUS I2C_EXT_BUS + +#define MPU6000_CS_PIN PA4 +#define MPU6000_SPI_BUS BUS_SPI1 + + #define USE_IMU_MPU6000 + #define IMU_MPU6000_ALIGN CW270_DEG + +// Support for OMNIBUS F4 PRO CORNER - it has ICM20608 instead of MPU6000 + #define MPU6500_CS_PIN MPU6000_CS_PIN + #define MPU6500_SPI_BUS MPU6000_SPI_BUS + #define USE_IMU_MPU6500 + #define IMU_MPU6500_ALIGN IMU_MPU6000_ALIGN + + //BMI270 + #define USE_IMU_BMI270 + #define IMU_BMI270_ALIGN IMU_MPU6000_ALIGN + #define BMI270_SPI_BUS MPU6000_SPI_BUS + #define BMI270_CS_PIN MPU6000_CS_PIN + +#define USE_MAG +#define MAG_I2C_BUS I2C_EXT_BUS +#define USE_MAG_ALL + +#define TEMPERATURE_I2C_BUS I2C_EXT_BUS + +#define USE_BARO + + #define USE_BARO_BMP280 + #define BMP280_SPI_BUS BUS_SPI3 + #define BMP280_CS_PIN PB3 // v1 + // Support external barometers + #define BARO_I2C_BUS I2C_EXT_BUS + #define USE_BARO_BMP085 + #define USE_BARO_MS5611 + +#define PITOT_I2C_BUS I2C_EXT_BUS + +#define USE_RANGEFINDER +#define RANGEFINDER_I2C_BUS I2C_EXT_BUS + +#define USE_VCP +#define VBUS_SENSING_PIN PC5 +#define VBUS_SENSING_ENABLED + +#define USE_UART_INVERTER + +#define USE_UART1 +#define UART1_RX_PIN PA10 +#define UART1_TX_PIN PA9 +#define UART1_AHB1_PERIPHERALS RCC_AHB1Periph_DMA2 + +#define USE_UART3 +#define UART3_RX_PIN PB11 +#define UART3_TX_PIN PB10 + +#define USE_UART6 +#define UART6_RX_PIN PC7 +#define UART6_TX_PIN PC6 + #define INVERTER_PIN_UART6_RX PC8 + #define INVERTER_PIN_UART6_TX PC9 + +#if defined(OMNIBUSF4V3) && !(defined(OMNIBUSF4V3_S6_SS) || defined(OMNIBUSF4V3_S5S6_SS) || defined(OMNIBUSF4V3_S5_S6_2SS)) +#define USE_SOFTSERIAL1 +#define SOFTSERIAL_1_RX_PIN PC6 // shared with UART6 TX +#define SOFTSERIAL_1_TX_PIN PC6 // shared with UART6 TX + +#define SERIAL_PORT_COUNT 5 // VCP, USART1, USART3, USART6, SOFTSERIAL1 + +#elif defined(OMNIBUSF4V3_S6_SS) // one softserial on S6 +#define USE_SOFTSERIAL1 +#define SOFTSERIAL_1_RX_PIN PA8 // S6 output +#define SOFTSERIAL_1_TX_PIN PA8 // S6 output + +#define SERIAL_PORT_COUNT 5 // VCP, USART1, USART3, USART6, SOFTSERIAL1 + +#elif defined(OMNIBUSF4V3_S5S6_SS) // one softserial on S5/RX S6/TX +#define USE_SOFTSERIAL1 +#define SOFTSERIAL_1_RX_PIN PA1 // S5 output +#define SOFTSERIAL_1_TX_PIN PA8 // S6 output + +#define SERIAL_PORT_COUNT 5 // VCP, USART1, USART3, USART6, SOFTSERIAL1 + +#elif defined(OMNIBUSF4V3_S5_S6_2SS) // two softserials, one on S5 and one on S6 +#define USE_SOFTSERIAL1 +#define SOFTSERIAL_1_RX_PIN PA1 // S5 output +#define SOFTSERIAL_1_TX_PIN PA1 // S5 output + +#define USE_SOFTSERIAL2 +#define SOFTSERIAL_2_RX_PIN PA8 // S6 output +#define SOFTSERIAL_2_TX_PIN PA8 // S6 output + +#define SERIAL_PORT_COUNT 6 // VCP, USART1, USART3, USART6, SOFTSERIAL1, SOFTSERIAL2 + +#else // One softserial on versions other than OMNIBUSF4V3 +#define USE_SOFTSERIAL1 +#define SOFTSERIAL_1_RX_PIN PC8 // pad labelled CH5 on OMNIBUSF4PRO +#define SOFTSERIAL_1_TX_PIN PC9 // pad labelled CH6 on OMNIBUSF4PRO + +#define SERIAL_PORT_COUNT 5 // VCP, USART1, USART3, USART6, SOFTSERIAL1 +#endif + +#define DEFAULT_RX_TYPE RX_TYPE_SERIAL +#define SERIALRX_PROVIDER SERIALRX_SBUS +#define SERIALRX_UART SERIAL_PORT_USART1 + +#define USE_SPI + +#define USE_SPI_DEVICE_1 + + #define USE_SPI_DEVICE_2 + #define SPI2_NSS_PIN PB12 + #define SPI2_SCK_PIN PB13 + #define SPI2_MISO_PIN PB14 + #define SPI2_MOSI_PIN PB15 + +#define USE_SPI_DEVICE_3 + #define SPI3_NSS_PIN PA15 +#define SPI3_SCK_PIN PC10 +#define SPI3_MISO_PIN PC11 +#define SPI3_MOSI_PIN PC12 + +#define USE_MAX7456 +#define MAX7456_SPI_BUS BUS_SPI3 +#define MAX7456_CS_PIN PA15 + + #define ENABLE_BLACKBOX_LOGGING_ON_SDCARD_BY_DEFAULT + #define USE_SDCARD + #define USE_SDCARD_SPI + + #define SDCARD_SPI_BUS BUS_SPI2 + #define SDCARD_CS_PIN SPI2_NSS_PIN + + #define SDCARD_DETECT_PIN PB7 + #define SDCARD_DETECT_INVERTED + +#define USE_ADC +#define ADC_CHANNEL_1_PIN PC1 +#define ADC_CHANNEL_2_PIN PC2 + + #define ADC_CHANNEL_3_PIN PA0 + +#define CURRENT_METER_ADC_CHANNEL ADC_CHN_1 +#define VBAT_ADC_CHANNEL ADC_CHN_2 +#define RSSI_ADC_CHANNEL ADC_CHN_3 + +#define SENSORS_SET (SENSOR_ACC|SENSOR_MAG|SENSOR_BARO) + +#define USE_LED_STRIP + #define WS2811_PIN PB6 + +#define DISABLE_RX_PWM_FEATURE +#define DEFAULT_FEATURES (FEATURE_TX_PROF_SEL | FEATURE_BLACKBOX | FEATURE_VBAT | FEATURE_OSD) + +#define USE_SPEKTRUM_BIND +#define BIND_PIN PB11 // USART3 RX + +#define USE_SERIAL_4WAY_BLHELI_INTERFACE + +// Number of available PWM outputs +#define MAX_PWM_OUTPUT_PORTS 6 +#define TARGET_MOTOR_COUNT 6 +#define USE_DSHOT +#define USE_ESC_SENSOR + +#define TARGET_IO_PORTA 0xffff +#define TARGET_IO_PORTB 0xffff +#define TARGET_IO_PORTC 0xffff +#define TARGET_IO_PORTD 0xffff + From 476a0cbcf94f232b610fa45944821b0c7b6d15ca Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 22 Dec 2025 02:15:55 -0600 Subject: [PATCH 04/42] Clean up dead code and obsolete comments from OMNIBUS split Remove preprocessor conditionals that can never be true in split directories: - OMNIBUSF4PRO: Remove checks for _S6_SS variants (in different directory) - OMNIBUSF4V3_SS: Remove checks for OMNIBUSF4PRO/V3 (in different directory) - Remove OMNIBUSF4PRO_LEDSTRIPM5 references (target no longer exists) Update comments to accurately describe what targets each directory contains. All affected targets build successfully. --- src/main/target/DYSF4/target.h | 3 +-- src/main/target/OMNIBUSF4PRO/target.c | 6 ------ src/main/target/OMNIBUSF4PRO/target.h | 17 +++++------------ src/main/target/OMNIBUSF4V3_SS/target.c | 9 +-------- src/main/target/OMNIBUSF4V3_SS/target.h | 13 +++---------- 5 files changed, 10 insertions(+), 38 deletions(-) diff --git a/src/main/target/DYSF4/target.h b/src/main/target/DYSF4/target.h index 24d5aa0dac4..2578eb6b424 100644 --- a/src/main/target/DYSF4/target.h +++ b/src/main/target/DYSF4/target.h @@ -17,8 +17,7 @@ #pragma once -//Same target as OMNIBUSF4PRO with LED strip in M5 -//Same target as OMNIBUSF4V3 with softserial in M5 and M6 +// This directory contains: DYSF4PRO, DYSF4PROV2 #if defined(DYSF4PRO) #define TARGET_BOARD_IDENTIFIER "DYS4" diff --git a/src/main/target/OMNIBUSF4PRO/target.c b/src/main/target/OMNIBUSF4PRO/target.c index 9aad85a14af..10a1aaabf5a 100644 --- a/src/main/target/OMNIBUSF4PRO/target.c +++ b/src/main/target/OMNIBUSF4PRO/target.c @@ -31,14 +31,8 @@ timerHardware_t timerHardware[] = { DEF_TIM(TIM2, CH3, PA2, TIM_USE_OUTPUT_AUTO, 0, 0), // S4_OUT D1_ST1 // { TIM9, IO_TAG(PA3), TIM_Channel_2, 1, IOCFG_AF_PP_PD, GPIO_AF_TIM9, TIM_USE_OUTPUT_AUTO }, // MOTOR_3 -#if (defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3)) && !(defined(OMNIBUSF4PRO_LEDSTRIPM5) || defined(OMNIBUSF4V3_S6_SS) || defined(OMNIBUSF4V3_S5S6_SS) || defined(OMNIBUSF4V3_S5_S6_2SS)) - DEF_TIM(TIM5, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 0), // S5_OUT DEF_TIM(TIM1, CH1, PA8, TIM_USE_OUTPUT_AUTO, 0, 0), // S6_OUT -#else - DEF_TIM(TIM5, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 0), // S5_OUT MOTOR, SERVO or LED - DEF_TIM(TIM1, CH1, PA8, TIM_USE_OUTPUT_AUTO, 0, 0), // S6_OUT -#endif #if (defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3)) DEF_TIM(TIM4, CH1, PB6, TIM_USE_LED, 0, 0), // LED strip for F4 V2 / F4-Pro-0X and later (RCD_CS for F4) diff --git a/src/main/target/OMNIBUSF4PRO/target.h b/src/main/target/OMNIBUSF4PRO/target.h index 74829342c2c..6e7ed8aa9b3 100644 --- a/src/main/target/OMNIBUSF4PRO/target.h +++ b/src/main/target/OMNIBUSF4PRO/target.h @@ -17,11 +17,8 @@ #pragma once -//Same target as OMNIBUSF4PRO with LED strip in M5 -#ifdef OMNIBUSF4PRO_LEDSTRIPM5 -#define OMNIBUSF4PRO -#endif -//Same target as OMNIBUSF4V3 with softserial in M5 and M6 +// This directory contains: OMNIBUSF4PRO, OMNIBUSF4V3, OMNIBUSF4V3_ICM +// Softserial variants are in separate OMNIBUSF4V3_SS/ directory #ifdef OMNIBUSF4PRO #define TARGET_BOARD_IDENTIFIER "OBSD" @@ -126,14 +123,14 @@ #define INVERTER_PIN_UART6_TX PC9 #endif -#if defined(OMNIBUSF4V3) && !(defined(OMNIBUSF4V3_S6_SS) || defined(OMNIBUSF4V3_S5S6_SS) || defined(OMNIBUSF4V3_S5_S6_2SS)) +#if defined(OMNIBUSF4V3) #define USE_SOFTSERIAL1 #define SOFTSERIAL_1_RX_PIN PC6 // shared with UART6 TX #define SOFTSERIAL_1_TX_PIN PC6 // shared with UART6 TX #define SERIAL_PORT_COUNT 5 // VCP, USART1, USART3, USART6, SOFTSERIAL1 -#else // One softserial on versions other than OMNIBUSF4V3 +#else // OMNIBUSF4PRO #define USE_SOFTSERIAL1 #define SOFTSERIAL_1_RX_PIN PC8 // pad labelled CH5 on OMNIBUSF4PRO #define SOFTSERIAL_1_TX_PIN PC9 // pad labelled CH6 on OMNIBUSF4PRO @@ -202,11 +199,7 @@ #define SENSORS_SET (SENSOR_ACC|SENSOR_MAG|SENSOR_BARO) #define USE_LED_STRIP -#if (defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3)) && !defined(OMNIBUSF4PRO_LEDSTRIPM5) - #define WS2811_PIN PB6 -#else - #define WS2811_PIN PA1 -#endif +#define WS2811_PIN PB6 #define DISABLE_RX_PWM_FEATURE #define DEFAULT_FEATURES (FEATURE_TX_PROF_SEL | FEATURE_BLACKBOX | FEATURE_VBAT | FEATURE_OSD) diff --git a/src/main/target/OMNIBUSF4V3_SS/target.c b/src/main/target/OMNIBUSF4V3_SS/target.c index ed38a77a51a..3aa99b0ea09 100644 --- a/src/main/target/OMNIBUSF4V3_SS/target.c +++ b/src/main/target/OMNIBUSF4V3_SS/target.c @@ -31,19 +31,12 @@ timerHardware_t timerHardware[] = { DEF_TIM(TIM2, CH3, PA2, TIM_USE_OUTPUT_AUTO, 0, 0), // S4_OUT D1_ST1 // { TIM9, IO_TAG(PA3), TIM_Channel_2, 1, IOCFG_AF_PP_PD, GPIO_AF_TIM9, TIM_USE_OUTPUT_AUTO }, // MOTOR_3 -#if (defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3)) && !(defined(OMNIBUSF4PRO_LEDSTRIPM5) || defined(OMNIBUSF4V3_S6_SS) || defined(OMNIBUSF4V3_S5S6_SS) || defined(OMNIBUSF4V3_S5_S6_2SS)) - - DEF_TIM(TIM5, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 0), // S5_OUT - DEF_TIM(TIM1, CH1, PA8, TIM_USE_OUTPUT_AUTO, 0, 0), // S6_OUT -#elif defined(OMNIBUSF4V3_S5S6_SS) || defined(OMNIBUSF4V3_S5_S6_2SS) +#if defined(OMNIBUSF4V3_S5S6_SS) || defined(OMNIBUSF4V3_S5_S6_2SS) DEF_TIM(TIM5, CH2, PA1, TIM_USE_ANY, 0, 0), // S5_OUT SOFTSERIAL DEF_TIM(TIM1, CH1, PA8, TIM_USE_ANY, 0, 0), // S6_OUT SOFTSERIAL #elif defined(OMNIBUSF4V3_S6_SS) DEF_TIM(TIM5, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 0), // S5_OUT DEF_TIM(TIM1, CH1, PA8, TIM_USE_ANY, 0, 0), // S6_OUT SOFTSERIAL -#else - DEF_TIM(TIM5, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 0), // S5_OUT MOTOR, SERVO or LED - DEF_TIM(TIM1, CH1, PA8, TIM_USE_OUTPUT_AUTO, 0, 0), // S6_OUT #endif DEF_TIM(TIM4, CH1, PB6, TIM_USE_LED, 0, 0), // LED strip for F4 V2 / F4-Pro-0X and later (RCD_CS for F4) diff --git a/src/main/target/OMNIBUSF4V3_SS/target.h b/src/main/target/OMNIBUSF4V3_SS/target.h index 4d3355eed9c..973ccdf3920 100644 --- a/src/main/target/OMNIBUSF4V3_SS/target.h +++ b/src/main/target/OMNIBUSF4V3_SS/target.h @@ -17,8 +17,8 @@ #pragma once -//Same target as OMNIBUSF4PRO with LED strip in M5 -//Same target as OMNIBUSF4V3 with softserial in M5 and M6 +// This directory contains: OMNIBUSF4V3_S6_SS, OMNIBUSF4V3_S5S6_SS, OMNIBUSF4V3_S5_S6_2SS +// Softserial variants of OMNIBUSF4V3 with different S5/S6 timer configurations #if defined(OMNIBUSF4V3_S6_SS) || defined(OMNIBUSF4V3_S5S6_SS) || defined(OMNIBUSF4V3_S5_S6_2SS) #define OMNIBUSF4V3 #endif @@ -99,14 +99,7 @@ #define INVERTER_PIN_UART6_RX PC8 #define INVERTER_PIN_UART6_TX PC9 -#if defined(OMNIBUSF4V3) && !(defined(OMNIBUSF4V3_S6_SS) || defined(OMNIBUSF4V3_S5S6_SS) || defined(OMNIBUSF4V3_S5_S6_2SS)) -#define USE_SOFTSERIAL1 -#define SOFTSERIAL_1_RX_PIN PC6 // shared with UART6 TX -#define SOFTSERIAL_1_TX_PIN PC6 // shared with UART6 TX - -#define SERIAL_PORT_COUNT 5 // VCP, USART1, USART3, USART6, SOFTSERIAL1 - -#elif defined(OMNIBUSF4V3_S6_SS) // one softserial on S6 +#if defined(OMNIBUSF4V3_S6_SS) // one softserial on S6 #define USE_SOFTSERIAL1 #define SOFTSERIAL_1_RX_PIN PA8 // S6 output #define SOFTSERIAL_1_TX_PIN PA8 // S6 output From c79e53a61358b8d34a02d59b7c62c726c4b9188f Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 22 Dec 2025 02:21:32 -0600 Subject: [PATCH 05/42] Remove all dead code from OMNIBUSF4 directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The OMNIBUSF4 directory now only contains the base OMNIBUSF4 target. All other variants (OMNIBUSF4PRO, OMNIBUSF4V3, DYSF4, etc.) are in separate directories. Used unifdef to remove all conditionals for non-OMNIBUSF4 targets: - Removed checks for OMNIBUSF4PRO, OMNIBUSF4V3, DYSF4PRO, DYSF4PROV2 - Removed checks for softserial variants (_S6_SS, etc.) - Removed LEDSTRIPM5 references Results: - target.h: 280 → 147 lines (47% reduction, 133 lines removed) - target.c: cleaned (7 conditionals removed) - All conditionals removed: 0 remaining in both files - OMNIBUSF4 target builds successfully The OMNIBUSF4 directory now contains only the code specific to the base OMNIBUSF4 variant with no dead branches. --- src/main/target/OMNIBUSF4/target.c | 20 ----- src/main/target/OMNIBUSF4/target.h | 135 +---------------------------- 2 files changed, 1 insertion(+), 154 deletions(-) diff --git a/src/main/target/OMNIBUSF4/target.c b/src/main/target/OMNIBUSF4/target.c index be85e9fbce3..2eed0188f97 100644 --- a/src/main/target/OMNIBUSF4/target.c +++ b/src/main/target/OMNIBUSF4/target.c @@ -31,32 +31,12 @@ timerHardware_t timerHardware[] = { DEF_TIM(TIM2, CH3, PA2, TIM_USE_OUTPUT_AUTO, 0, 0), // S4_OUT D1_ST1 // { TIM9, IO_TAG(PA3), TIM_Channel_2, 1, IOCFG_AF_PP_PD, GPIO_AF_TIM9, TIM_USE_OUTPUT_AUTO }, // MOTOR_3 -#if (defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3)) && !(defined(OMNIBUSF4PRO_LEDSTRIPM5) || defined(OMNIBUSF4V3_S6_SS) || defined(OMNIBUSF4V3_S5S6_SS) || defined(OMNIBUSF4V3_S5_S6_2SS)) - - DEF_TIM(TIM5, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 0), // S5_OUT - DEF_TIM(TIM1, CH1, PA8, TIM_USE_OUTPUT_AUTO, 0, 0), // S6_OUT -#elif defined(OMNIBUSF4V3_S5S6_SS) || defined(OMNIBUSF4V3_S5_S6_2SS) - DEF_TIM(TIM5, CH2, PA1, TIM_USE_ANY, 0, 0), // S5_OUT SOFTSERIAL - DEF_TIM(TIM1, CH1, PA8, TIM_USE_ANY, 0, 0), // S6_OUT SOFTSERIAL -#elif defined(OMNIBUSF4V3_S6_SS) - DEF_TIM(TIM5, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 0), // S5_OUT - DEF_TIM(TIM1, CH1, PA8, TIM_USE_ANY, 0, 0), // S6_OUT SOFTSERIAL -#else DEF_TIM(TIM5, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 0), // S5_OUT MOTOR, SERVO or LED DEF_TIM(TIM1, CH1, PA8, TIM_USE_OUTPUT_AUTO, 0, 0), // S6_OUT -#endif -#if (defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3)) - DEF_TIM(TIM4, CH1, PB6, TIM_USE_LED, 0, 0), // LED strip for F4 V2 / F4-Pro-0X and later (RCD_CS for F4) -#endif -#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) - // DEF_TIM(TIM10, CH1, PB8, TIM_USE_PPM, 0, 0), // PPM - DEF_TIM(TIM4, CH4, PB9, TIM_USE_ANY, 0, 0), // S2_IN -#else // DEF_TIM(TIM12, CH1, PB14, TIM_USE_PPM, 0, 0), // PPM DEF_TIM(TIM12, CH2, PB15, TIM_USE_ANY, 0, 0), // S2_IN -#endif DEF_TIM(TIM8, CH1, PC6, TIM_USE_ANY, 0, 0), // S3_IN, UART6_TX DEF_TIM(TIM8, CH2, PC7, TIM_USE_ANY, 0, 0), // S4_IN, UART6_RX DEF_TIM(TIM8, CH3, PC8, TIM_USE_ANY, 0, 0), // S5_IN // pad labelled CH5 on OMNIBUSF4PRO diff --git a/src/main/target/OMNIBUSF4/target.h b/src/main/target/OMNIBUSF4/target.h index 2c5a27afbb6..1d8188beadc 100644 --- a/src/main/target/OMNIBUSF4/target.h +++ b/src/main/target/OMNIBUSF4/target.h @@ -18,76 +18,31 @@ #pragma once //Same target as OMNIBUSF4PRO with LED strip in M5 -#ifdef OMNIBUSF4PRO_LEDSTRIPM5 -#define OMNIBUSF4PRO -#endif //Same target as OMNIBUSF4V3 with softserial in M5 and M6 -#if defined(OMNIBUSF4V3_S6_SS) || defined(OMNIBUSF4V3_S5S6_SS) || defined(OMNIBUSF4V3_S5_S6_2SS) -#define OMNIBUSF4V3 -#endif - -#ifdef OMNIBUSF4PRO -#define TARGET_BOARD_IDENTIFIER "OBSD" -#elif defined(OMNIBUSF4V3) -#define TARGET_BOARD_IDENTIFIER "OB43" -#elif defined(DYSF4PRO) -#define TARGET_BOARD_IDENTIFIER "DYS4" -#elif defined(DYSF4PROV2) -#define TARGET_BOARD_IDENTIFIER "DY42" -#else + #define TARGET_BOARD_IDENTIFIER "OBF4" -#endif -#if defined(DYSF4PRO) || defined(DYSF4PROV2) -#define USBD_PRODUCT_STRING "DysF4Pro" -#else #define USBD_PRODUCT_STRING "Omnibus F4" -#endif #define LED0 PB5 #define BEEPER PB4 #define BEEPER_INVERTED -#if defined(DYSF4PROV2) -#define USE_I2C -#define USE_I2C_DEVICE_1 -#define I2C1_SCL PB8 -#define I2C1_SDA PB9 -#define I2C_EXT_BUS BUS_I2C1 -#else #define USE_I2C #define USE_I2C_DEVICE_2 #define I2C_DEVICE_2_SHARES_UART3 #define I2C_EXT_BUS BUS_I2C2 -#endif #define UG2864_I2C_BUS I2C_EXT_BUS #define MPU6000_CS_PIN PA4 #define MPU6000_SPI_BUS BUS_SPI1 -#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) - #define USE_IMU_MPU6000 - #define IMU_MPU6000_ALIGN CW270_DEG -#else #define USE_IMU_MPU6000 #define IMU_MPU6000_ALIGN CW180_DEG -#endif // Support for OMNIBUS F4 PRO CORNER - it has ICM20608 instead of MPU6000 -#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) - #define MPU6500_CS_PIN MPU6000_CS_PIN - #define MPU6500_SPI_BUS MPU6000_SPI_BUS - #define USE_IMU_MPU6500 - #define IMU_MPU6500_ALIGN IMU_MPU6000_ALIGN - - //BMI270 - #define USE_IMU_BMI270 - #define IMU_BMI270_ALIGN IMU_MPU6000_ALIGN - #define BMI270_SPI_BUS MPU6000_SPI_BUS - #define BMI270_CS_PIN MPU6000_CS_PIN -#endif #define USE_MAG #define MAG_I2C_BUS I2C_EXT_BUS @@ -97,20 +52,10 @@ #define USE_BARO -#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) - #define USE_BARO_BMP280 - #define BMP280_SPI_BUS BUS_SPI3 - #define BMP280_CS_PIN PB3 // v1 - // Support external barometers - #define BARO_I2C_BUS I2C_EXT_BUS - #define USE_BARO_BMP085 - #define USE_BARO_MS5611 -#else #define BARO_I2C_BUS I2C_EXT_BUS #define USE_BARO_BMP085 #define USE_BARO_BMP280 #define USE_BARO_MS5611 -#endif #define PITOT_I2C_BUS I2C_EXT_BUS @@ -121,17 +66,11 @@ #define VBUS_SENSING_PIN PC5 #define VBUS_SENSING_ENABLED -#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) -#define USE_UART_INVERTER -#endif #define USE_UART1 #define UART1_RX_PIN PA10 #define UART1_TX_PIN PA9 #define UART1_AHB1_PERIPHERALS RCC_AHB1Periph_DMA2 -#if defined(OMNIBUSF4PRO) -#define INVERTER_PIN_UART1_RX PC0 // PC0 has never been used as inverter control on genuine OMNIBUS F4 variants, but leave it as is since some clones actually implement it. -#endif #define USE_UART3 #define UART3_RX_PIN PB11 @@ -140,50 +79,12 @@ #define USE_UART6 #define UART6_RX_PIN PC7 #define UART6_TX_PIN PC6 -#if defined(OMNIBUSF4V3) - #define INVERTER_PIN_UART6_RX PC8 - #define INVERTER_PIN_UART6_TX PC9 -#endif -#if defined(OMNIBUSF4V3) && !(defined(OMNIBUSF4V3_S6_SS) || defined(OMNIBUSF4V3_S5S6_SS) || defined(OMNIBUSF4V3_S5_S6_2SS)) -#define USE_SOFTSERIAL1 -#define SOFTSERIAL_1_RX_PIN PC6 // shared with UART6 TX -#define SOFTSERIAL_1_TX_PIN PC6 // shared with UART6 TX - -#define SERIAL_PORT_COUNT 5 // VCP, USART1, USART3, USART6, SOFTSERIAL1 - -#elif defined(OMNIBUSF4V3_S6_SS) // one softserial on S6 -#define USE_SOFTSERIAL1 -#define SOFTSERIAL_1_RX_PIN PA8 // S6 output -#define SOFTSERIAL_1_TX_PIN PA8 // S6 output - -#define SERIAL_PORT_COUNT 5 // VCP, USART1, USART3, USART6, SOFTSERIAL1 - -#elif defined(OMNIBUSF4V3_S5S6_SS) // one softserial on S5/RX S6/TX -#define USE_SOFTSERIAL1 -#define SOFTSERIAL_1_RX_PIN PA1 // S5 output -#define SOFTSERIAL_1_TX_PIN PA8 // S6 output - -#define SERIAL_PORT_COUNT 5 // VCP, USART1, USART3, USART6, SOFTSERIAL1 - -#elif defined(OMNIBUSF4V3_S5_S6_2SS) // two softserials, one on S5 and one on S6 -#define USE_SOFTSERIAL1 -#define SOFTSERIAL_1_RX_PIN PA1 // S5 output -#define SOFTSERIAL_1_TX_PIN PA1 // S5 output - -#define USE_SOFTSERIAL2 -#define SOFTSERIAL_2_RX_PIN PA8 // S6 output -#define SOFTSERIAL_2_TX_PIN PA8 // S6 output - -#define SERIAL_PORT_COUNT 6 // VCP, USART1, USART3, USART6, SOFTSERIAL1, SOFTSERIAL2 - -#else // One softserial on versions other than OMNIBUSF4V3 #define USE_SOFTSERIAL1 #define SOFTSERIAL_1_RX_PIN PC8 // pad labelled CH5 on OMNIBUSF4PRO #define SOFTSERIAL_1_TX_PIN PC9 // pad labelled CH6 on OMNIBUSF4PRO #define SERIAL_PORT_COUNT 5 // VCP, USART1, USART3, USART6, SOFTSERIAL1 -#endif #define DEFAULT_RX_TYPE RX_TYPE_SERIAL #define SERIALRX_PROVIDER SERIALRX_SBUS @@ -193,20 +94,9 @@ #define USE_SPI_DEVICE_1 -#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) - #define USE_SPI_DEVICE_2 - #define SPI2_NSS_PIN PB12 - #define SPI2_SCK_PIN PB13 - #define SPI2_MISO_PIN PB14 - #define SPI2_MOSI_PIN PB15 -#endif #define USE_SPI_DEVICE_3 -#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) - #define SPI3_NSS_PIN PA15 -#else #define SPI3_NSS_PIN PB3 -#endif #define SPI3_SCK_PIN PC10 #define SPI3_MISO_PIN PC11 #define SPI3_MOSI_PIN PC12 @@ -215,33 +105,17 @@ #define MAX7456_SPI_BUS BUS_SPI3 #define MAX7456_CS_PIN PA15 -#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) - #define ENABLE_BLACKBOX_LOGGING_ON_SDCARD_BY_DEFAULT - #define USE_SDCARD - #define USE_SDCARD_SPI - - #define SDCARD_SPI_BUS BUS_SPI2 - #define SDCARD_CS_PIN SPI2_NSS_PIN - - #define SDCARD_DETECT_PIN PB7 - #define SDCARD_DETECT_INVERTED -#else #define ENABLE_BLACKBOX_LOGGING_ON_SPIFLASH_BY_DEFAULT #define M25P16_CS_PIN SPI3_NSS_PIN #define M25P16_SPI_BUS BUS_SPI3 #define USE_FLASHFS #define USE_FLASH_M25P16 -#endif #define USE_ADC #define ADC_CHANNEL_1_PIN PC1 #define ADC_CHANNEL_2_PIN PC2 -#ifdef DYSF4PRO - #define ADC_CHANNEL_3_PIN PC3 -#else #define ADC_CHANNEL_3_PIN PA0 -#endif #define CURRENT_METER_ADC_CHANNEL ADC_CHN_1 #define VBAT_ADC_CHANNEL ADC_CHN_2 @@ -250,11 +124,7 @@ #define SENSORS_SET (SENSOR_ACC|SENSOR_MAG|SENSOR_BARO) #define USE_LED_STRIP -#if (defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3)) && !defined(OMNIBUSF4PRO_LEDSTRIPM5) - #define WS2811_PIN PB6 -#else #define WS2811_PIN PA1 -#endif #define DISABLE_RX_PWM_FEATURE #define DEFAULT_FEATURES (FEATURE_TX_PROF_SEL | FEATURE_BLACKBOX | FEATURE_VBAT | FEATURE_OSD) @@ -275,6 +145,3 @@ #define TARGET_IO_PORTC 0xffff #define TARGET_IO_PORTD 0xffff -#ifdef OMNIBUSF4PRO -#define CURRENT_METER_SCALE 265 -#endif From e3d0bda8830bd77b93008ed0a59d9ae834b6f97f Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 22 Dec 2025 02:34:18 -0600 Subject: [PATCH 06/42] Fix critical OMNIBUSF4V3_ICM configuration bug and remove dead code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Added alias for OMNIBUSF4V3_ICM → OMNIBUSF4V3 in OMNIBUSF4PRO/target.h This fixes a critical bug where OMNIBUSF4V3_ICM would get wrong configuration: - Wrong IMU alignment (CW180 instead of CW270) - Missing MPU6500/BMI270 support - Wrong barometer (I2C-only instead of SPI BMP280) - Missing UART inverter support - Wrong SPI3_NSS_PIN (PB3 instead of PA15) - Wrong blackbox (SPI flash instead of SD card) - Wrong timer configuration 2. Removed dead #else clauses after OMNIBUS split: - DYSF4/target.h: Removed unreachable fallback cases - OMNIBUSF4PRO/target.h: All #else branches now dead after alias fix - OMNIBUSF4V3_SS/target.h: Removed unreachable softserial fallback All affected targets verified to build successfully. --- src/main/target/DYSF4/target.h | 8 +- src/main/target/OMNIBUSF4PRO/target.h | 105 +++++++++--------------- src/main/target/OMNIBUSF4V3_SS/target.h | 7 -- 3 files changed, 39 insertions(+), 81 deletions(-) diff --git a/src/main/target/DYSF4/target.h b/src/main/target/DYSF4/target.h index 2578eb6b424..41212fdb18d 100644 --- a/src/main/target/DYSF4/target.h +++ b/src/main/target/DYSF4/target.h @@ -19,19 +19,13 @@ // This directory contains: DYSF4PRO, DYSF4PROV2 -#if defined(DYSF4PRO) +#if defined(DYSF4PRO) #define TARGET_BOARD_IDENTIFIER "DYS4" #elif defined(DYSF4PROV2) #define TARGET_BOARD_IDENTIFIER "DY42" -#else -#define TARGET_BOARD_IDENTIFIER "OBF4" #endif -#if defined(DYSF4PRO) || defined(DYSF4PROV2) #define USBD_PRODUCT_STRING "DysF4Pro" -#else -#define USBD_PRODUCT_STRING "Omnibus F4" -#endif #define LED0 PB5 diff --git a/src/main/target/OMNIBUSF4PRO/target.h b/src/main/target/OMNIBUSF4PRO/target.h index 6e7ed8aa9b3..582dfe08d13 100644 --- a/src/main/target/OMNIBUSF4PRO/target.h +++ b/src/main/target/OMNIBUSF4PRO/target.h @@ -20,12 +20,14 @@ // This directory contains: OMNIBUSF4PRO, OMNIBUSF4V3, OMNIBUSF4V3_ICM // Softserial variants are in separate OMNIBUSF4V3_SS/ directory +#ifdef OMNIBUSF4V3_ICM +#define OMNIBUSF4V3 +#endif + #ifdef OMNIBUSF4PRO #define TARGET_BOARD_IDENTIFIER "OBSD" #elif defined(OMNIBUSF4V3) #define TARGET_BOARD_IDENTIFIER "OB43" -#else -#define TARGET_BOARD_IDENTIFIER "OBF4" #endif #define USBD_PRODUCT_STRING "Omnibus F4" @@ -45,27 +47,20 @@ #define MPU6000_CS_PIN PA4 #define MPU6000_SPI_BUS BUS_SPI1 -#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) - #define USE_IMU_MPU6000 - #define IMU_MPU6000_ALIGN CW270_DEG -#else - #define USE_IMU_MPU6000 - #define IMU_MPU6000_ALIGN CW180_DEG -#endif +#define USE_IMU_MPU6000 +#define IMU_MPU6000_ALIGN CW270_DEG // Support for OMNIBUS F4 PRO CORNER - it has ICM20608 instead of MPU6000 -#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) - #define MPU6500_CS_PIN MPU6000_CS_PIN - #define MPU6500_SPI_BUS MPU6000_SPI_BUS - #define USE_IMU_MPU6500 - #define IMU_MPU6500_ALIGN IMU_MPU6000_ALIGN - - //BMI270 - #define USE_IMU_BMI270 - #define IMU_BMI270_ALIGN IMU_MPU6000_ALIGN - #define BMI270_SPI_BUS MPU6000_SPI_BUS - #define BMI270_CS_PIN MPU6000_CS_PIN -#endif +#define MPU6500_CS_PIN MPU6000_CS_PIN +#define MPU6500_SPI_BUS MPU6000_SPI_BUS +#define USE_IMU_MPU6500 +#define IMU_MPU6500_ALIGN IMU_MPU6000_ALIGN + +//BMI270 +#define USE_IMU_BMI270 +#define IMU_BMI270_ALIGN IMU_MPU6000_ALIGN +#define BMI270_SPI_BUS MPU6000_SPI_BUS +#define BMI270_CS_PIN MPU6000_CS_PIN #define USE_MAG #define MAG_I2C_BUS I2C_EXT_BUS @@ -74,21 +69,13 @@ #define TEMPERATURE_I2C_BUS I2C_EXT_BUS #define USE_BARO - -#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) - #define USE_BARO_BMP280 - #define BMP280_SPI_BUS BUS_SPI3 - #define BMP280_CS_PIN PB3 // v1 - // Support external barometers - #define BARO_I2C_BUS I2C_EXT_BUS - #define USE_BARO_BMP085 - #define USE_BARO_MS5611 -#else - #define BARO_I2C_BUS I2C_EXT_BUS - #define USE_BARO_BMP085 - #define USE_BARO_BMP280 - #define USE_BARO_MS5611 -#endif +#define USE_BARO_BMP280 +#define BMP280_SPI_BUS BUS_SPI3 +#define BMP280_CS_PIN PB3 // v1 +// Support external barometers +#define BARO_I2C_BUS I2C_EXT_BUS +#define USE_BARO_BMP085 +#define USE_BARO_MS5611 #define PITOT_I2C_BUS I2C_EXT_BUS @@ -99,9 +86,7 @@ #define VBUS_SENSING_PIN PC5 #define VBUS_SENSING_ENABLED -#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) #define USE_UART_INVERTER -#endif #define USE_UART1 #define UART1_RX_PIN PA10 @@ -146,20 +131,14 @@ #define USE_SPI_DEVICE_1 -#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) - #define USE_SPI_DEVICE_2 - #define SPI2_NSS_PIN PB12 - #define SPI2_SCK_PIN PB13 - #define SPI2_MISO_PIN PB14 - #define SPI2_MOSI_PIN PB15 -#endif +#define USE_SPI_DEVICE_2 +#define SPI2_NSS_PIN PB12 +#define SPI2_SCK_PIN PB13 +#define SPI2_MISO_PIN PB14 +#define SPI2_MOSI_PIN PB15 #define USE_SPI_DEVICE_3 -#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) - #define SPI3_NSS_PIN PA15 -#else - #define SPI3_NSS_PIN PB3 -#endif +#define SPI3_NSS_PIN PA15 #define SPI3_SCK_PIN PC10 #define SPI3_MISO_PIN PC11 #define SPI3_MOSI_PIN PC12 @@ -168,23 +147,15 @@ #define MAX7456_SPI_BUS BUS_SPI3 #define MAX7456_CS_PIN PA15 -#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) - #define ENABLE_BLACKBOX_LOGGING_ON_SDCARD_BY_DEFAULT - #define USE_SDCARD - #define USE_SDCARD_SPI - - #define SDCARD_SPI_BUS BUS_SPI2 - #define SDCARD_CS_PIN SPI2_NSS_PIN - - #define SDCARD_DETECT_PIN PB7 - #define SDCARD_DETECT_INVERTED -#else - #define ENABLE_BLACKBOX_LOGGING_ON_SPIFLASH_BY_DEFAULT - #define M25P16_CS_PIN SPI3_NSS_PIN - #define M25P16_SPI_BUS BUS_SPI3 - #define USE_FLASHFS - #define USE_FLASH_M25P16 -#endif +#define ENABLE_BLACKBOX_LOGGING_ON_SDCARD_BY_DEFAULT +#define USE_SDCARD +#define USE_SDCARD_SPI + +#define SDCARD_SPI_BUS BUS_SPI2 +#define SDCARD_CS_PIN SPI2_NSS_PIN + +#define SDCARD_DETECT_PIN PB7 +#define SDCARD_DETECT_INVERTED #define USE_ADC #define ADC_CHANNEL_1_PIN PC1 diff --git a/src/main/target/OMNIBUSF4V3_SS/target.h b/src/main/target/OMNIBUSF4V3_SS/target.h index 973ccdf3920..65c87d6f7db 100644 --- a/src/main/target/OMNIBUSF4V3_SS/target.h +++ b/src/main/target/OMNIBUSF4V3_SS/target.h @@ -123,13 +123,6 @@ #define SOFTSERIAL_2_TX_PIN PA8 // S6 output #define SERIAL_PORT_COUNT 6 // VCP, USART1, USART3, USART6, SOFTSERIAL1, SOFTSERIAL2 - -#else // One softserial on versions other than OMNIBUSF4V3 -#define USE_SOFTSERIAL1 -#define SOFTSERIAL_1_RX_PIN PC8 // pad labelled CH5 on OMNIBUSF4PRO -#define SOFTSERIAL_1_TX_PIN PC9 // pad labelled CH6 on OMNIBUSF4PRO - -#define SERIAL_PORT_COUNT 5 // VCP, USART1, USART3, USART6, SOFTSERIAL1 #endif #define DEFAULT_RX_TYPE RX_TYPE_SERIAL From dce7687a98886844e67661bbf85f9cc56a1a9c10 Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 22 Dec 2025 02:44:02 -0600 Subject: [PATCH 07/42] Remove outdated and misleading comments from OMNIBUS split - DYSF4/target.h: Removed ICM20608 comment (no ICM support in this directory) - OMNIBUSF4/target.h: Removed ICM20608 comment (no ICM support in this directory) - OMNIBUSF4/target.h: Removed obsolete relationship comments from consolidated file ICM20608 support only exists in OMNIBUSF4PRO and OMNIBUSF4V3_SS directories. --- src/main/target/DYSF4/target.h | 2 -- src/main/target/OMNIBUSF4/target.h | 5 ----- 2 files changed, 7 deletions(-) diff --git a/src/main/target/DYSF4/target.h b/src/main/target/DYSF4/target.h index 41212fdb18d..a54f195b95b 100644 --- a/src/main/target/DYSF4/target.h +++ b/src/main/target/DYSF4/target.h @@ -53,8 +53,6 @@ #define USE_IMU_MPU6000 #define IMU_MPU6000_ALIGN CW180_DEG -// Support for OMNIBUS F4 PRO CORNER - it has ICM20608 instead of MPU6000 - #define USE_MAG #define MAG_I2C_BUS I2C_EXT_BUS #define USE_MAG_ALL diff --git a/src/main/target/OMNIBUSF4/target.h b/src/main/target/OMNIBUSF4/target.h index 1d8188beadc..0a1ecb2fec7 100644 --- a/src/main/target/OMNIBUSF4/target.h +++ b/src/main/target/OMNIBUSF4/target.h @@ -17,9 +17,6 @@ #pragma once -//Same target as OMNIBUSF4PRO with LED strip in M5 -//Same target as OMNIBUSF4V3 with softserial in M5 and M6 - #define TARGET_BOARD_IDENTIFIER "OBF4" #define USBD_PRODUCT_STRING "Omnibus F4" @@ -42,8 +39,6 @@ #define USE_IMU_MPU6000 #define IMU_MPU6000_ALIGN CW180_DEG -// Support for OMNIBUS F4 PRO CORNER - it has ICM20608 instead of MPU6000 - #define USE_MAG #define MAG_I2C_BUS I2C_EXT_BUS #define USE_MAG_ALL From 2331e01e62c2364155a9600e8a9e5966048261dd Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 22 Dec 2025 02:48:22 -0600 Subject: [PATCH 08/42] Remove dead code from OMNIBUSF4PRO/target.c The #else branch at lines 44-46 was unreachable after adding OMNIBUSF4V3_ICM aliasing. All three targets (OMNIBUSF4PRO, OMNIBUSF4V3, OMNIBUSF4V3_ICM) always use TIM4/PB9, never TIM12/PB15. --- src/main/target/OMNIBUSF4PRO/target.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/target/OMNIBUSF4PRO/target.c b/src/main/target/OMNIBUSF4PRO/target.c index 10a1aaabf5a..39750241d97 100644 --- a/src/main/target/OMNIBUSF4PRO/target.c +++ b/src/main/target/OMNIBUSF4PRO/target.c @@ -38,13 +38,8 @@ timerHardware_t timerHardware[] = { DEF_TIM(TIM4, CH1, PB6, TIM_USE_LED, 0, 0), // LED strip for F4 V2 / F4-Pro-0X and later (RCD_CS for F4) #endif -#if defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3) // DEF_TIM(TIM10, CH1, PB8, TIM_USE_PPM, 0, 0), // PPM DEF_TIM(TIM4, CH4, PB9, TIM_USE_ANY, 0, 0), // S2_IN -#else - // DEF_TIM(TIM12, CH1, PB14, TIM_USE_PPM, 0, 0), // PPM - DEF_TIM(TIM12, CH2, PB15, TIM_USE_ANY, 0, 0), // S2_IN -#endif DEF_TIM(TIM8, CH1, PC6, TIM_USE_ANY, 0, 0), // S3_IN, UART6_TX DEF_TIM(TIM8, CH2, PC7, TIM_USE_ANY, 0, 0), // S4_IN, UART6_RX DEF_TIM(TIM8, CH3, PC8, TIM_USE_ANY, 0, 0), // S5_IN // pad labelled CH5 on OMNIBUSF4PRO From 0fead0f6efe74942788fdc2d0c99cd5292cce697 Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 22 Dec 2025 10:45:46 -0600 Subject: [PATCH 09/42] Remove outdated comments and redundant conditional from OMNIBUS split 1. Removed outdated 'pad labelled CH5/CH6 on OMNIBUSF4PRO' comments from: - OMNIBUSF4/target.h and target.c (wrong target) - DYSF4/target.h and target.c (wrong target) - OMNIBUSF4V3_SS/target.c (wrong target) These comments are only accurate in the OMNIBUSF4PRO directory where PC8/PC9 really are labelled CH5/CH6 on the physical board. 2. Removed redundant conditional from OMNIBUSF4PRO/target.c: #if (defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3)) This is always true since all 3 targets in this directory (OMNIBUSF4PRO, OMNIBUSF4V3, OMNIBUSF4V3_ICM) have one of these defined. --- src/main/target/DYSF4/target.c | 4 ++-- src/main/target/DYSF4/target.h | 4 ++-- src/main/target/OMNIBUSF4/target.c | 4 ++-- src/main/target/OMNIBUSF4/target.h | 4 ++-- src/main/target/OMNIBUSF4PRO/target.c | 2 -- src/main/target/OMNIBUSF4V3_SS/target.c | 4 ++-- 6 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/main/target/DYSF4/target.c b/src/main/target/DYSF4/target.c index 2eed0188f97..d6de2e9bf25 100644 --- a/src/main/target/DYSF4/target.c +++ b/src/main/target/DYSF4/target.c @@ -39,8 +39,8 @@ timerHardware_t timerHardware[] = { DEF_TIM(TIM12, CH2, PB15, TIM_USE_ANY, 0, 0), // S2_IN DEF_TIM(TIM8, CH1, PC6, TIM_USE_ANY, 0, 0), // S3_IN, UART6_TX DEF_TIM(TIM8, CH2, PC7, TIM_USE_ANY, 0, 0), // S4_IN, UART6_RX - DEF_TIM(TIM8, CH3, PC8, TIM_USE_ANY, 0, 0), // S5_IN // pad labelled CH5 on OMNIBUSF4PRO - DEF_TIM(TIM8, CH4, PC9, TIM_USE_ANY, 0, 0), // S6_IN // pad labelled CH6 on OMNIBUSF4PRO + DEF_TIM(TIM8, CH3, PC8, TIM_USE_ANY, 0, 0), // S5_IN + DEF_TIM(TIM8, CH4, PC9, TIM_USE_ANY, 0, 0), // S6_IN }; diff --git a/src/main/target/DYSF4/target.h b/src/main/target/DYSF4/target.h index a54f195b95b..efce0d1b233 100644 --- a/src/main/target/DYSF4/target.h +++ b/src/main/target/DYSF4/target.h @@ -90,8 +90,8 @@ #define UART6_TX_PIN PC6 #define USE_SOFTSERIAL1 -#define SOFTSERIAL_1_RX_PIN PC8 // pad labelled CH5 on OMNIBUSF4PRO -#define SOFTSERIAL_1_TX_PIN PC9 // pad labelled CH6 on OMNIBUSF4PRO +#define SOFTSERIAL_1_RX_PIN PC8 +#define SOFTSERIAL_1_TX_PIN PC9 #define SERIAL_PORT_COUNT 5 // VCP, USART1, USART3, USART6, SOFTSERIAL1 diff --git a/src/main/target/OMNIBUSF4/target.c b/src/main/target/OMNIBUSF4/target.c index 2eed0188f97..d6de2e9bf25 100644 --- a/src/main/target/OMNIBUSF4/target.c +++ b/src/main/target/OMNIBUSF4/target.c @@ -39,8 +39,8 @@ timerHardware_t timerHardware[] = { DEF_TIM(TIM12, CH2, PB15, TIM_USE_ANY, 0, 0), // S2_IN DEF_TIM(TIM8, CH1, PC6, TIM_USE_ANY, 0, 0), // S3_IN, UART6_TX DEF_TIM(TIM8, CH2, PC7, TIM_USE_ANY, 0, 0), // S4_IN, UART6_RX - DEF_TIM(TIM8, CH3, PC8, TIM_USE_ANY, 0, 0), // S5_IN // pad labelled CH5 on OMNIBUSF4PRO - DEF_TIM(TIM8, CH4, PC9, TIM_USE_ANY, 0, 0), // S6_IN // pad labelled CH6 on OMNIBUSF4PRO + DEF_TIM(TIM8, CH3, PC8, TIM_USE_ANY, 0, 0), // S5_IN + DEF_TIM(TIM8, CH4, PC9, TIM_USE_ANY, 0, 0), // S6_IN }; diff --git a/src/main/target/OMNIBUSF4/target.h b/src/main/target/OMNIBUSF4/target.h index 0a1ecb2fec7..e3a209cca74 100644 --- a/src/main/target/OMNIBUSF4/target.h +++ b/src/main/target/OMNIBUSF4/target.h @@ -76,8 +76,8 @@ #define UART6_TX_PIN PC6 #define USE_SOFTSERIAL1 -#define SOFTSERIAL_1_RX_PIN PC8 // pad labelled CH5 on OMNIBUSF4PRO -#define SOFTSERIAL_1_TX_PIN PC9 // pad labelled CH6 on OMNIBUSF4PRO +#define SOFTSERIAL_1_RX_PIN PC8 +#define SOFTSERIAL_1_TX_PIN PC9 #define SERIAL_PORT_COUNT 5 // VCP, USART1, USART3, USART6, SOFTSERIAL1 diff --git a/src/main/target/OMNIBUSF4PRO/target.c b/src/main/target/OMNIBUSF4PRO/target.c index 39750241d97..29cb945af85 100644 --- a/src/main/target/OMNIBUSF4PRO/target.c +++ b/src/main/target/OMNIBUSF4PRO/target.c @@ -34,9 +34,7 @@ timerHardware_t timerHardware[] = { DEF_TIM(TIM5, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 0), // S5_OUT DEF_TIM(TIM1, CH1, PA8, TIM_USE_OUTPUT_AUTO, 0, 0), // S6_OUT -#if (defined(OMNIBUSF4PRO) || defined(OMNIBUSF4V3)) DEF_TIM(TIM4, CH1, PB6, TIM_USE_LED, 0, 0), // LED strip for F4 V2 / F4-Pro-0X and later (RCD_CS for F4) -#endif // DEF_TIM(TIM10, CH1, PB8, TIM_USE_PPM, 0, 0), // PPM DEF_TIM(TIM4, CH4, PB9, TIM_USE_ANY, 0, 0), // S2_IN diff --git a/src/main/target/OMNIBUSF4V3_SS/target.c b/src/main/target/OMNIBUSF4V3_SS/target.c index 3aa99b0ea09..95b496e8bfb 100644 --- a/src/main/target/OMNIBUSF4V3_SS/target.c +++ b/src/main/target/OMNIBUSF4V3_SS/target.c @@ -45,8 +45,8 @@ timerHardware_t timerHardware[] = { DEF_TIM(TIM4, CH4, PB9, TIM_USE_ANY, 0, 0), // S2_IN DEF_TIM(TIM8, CH1, PC6, TIM_USE_ANY, 0, 0), // S3_IN, UART6_TX DEF_TIM(TIM8, CH2, PC7, TIM_USE_ANY, 0, 0), // S4_IN, UART6_RX - DEF_TIM(TIM8, CH3, PC8, TIM_USE_ANY, 0, 0), // S5_IN // pad labelled CH5 on OMNIBUSF4PRO - DEF_TIM(TIM8, CH4, PC9, TIM_USE_ANY, 0, 0), // S6_IN // pad labelled CH6 on OMNIBUSF4PRO + DEF_TIM(TIM8, CH3, PC8, TIM_USE_ANY, 0, 0), // S5_IN + DEF_TIM(TIM8, CH4, PC9, TIM_USE_ANY, 0, 0), // S6_IN }; From e6dc927d46f59b78975eca44ca218f4c7f130fcd Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 22 Dec 2025 10:54:52 -0600 Subject: [PATCH 10/42] Fix inconsistent indentation remnants in OMNIBUS split MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove orphaned indentation from preprocessor defines that were previously inside conditional blocks but are now at top level after the target split. Files changed: - OMNIBUSF4/target.h: Fixed 2-space and 4-space orphaned indents - DYSF4/target.h: Fixed 2-space orphaned indents - OMNIBUSF4V3_SS/target.h: Fixed extensive 2-space orphaned indents - OMNIBUSF4PRO/target.h: Fixed 4-space orphaned indent on ADC_CHANNEL_3_PIN Valid indentation inside active #if blocks was preserved. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/main/target/DYSF4/target.h | 27 +++++----- src/main/target/OMNIBUSF4/target.h | 30 +++++------ src/main/target/OMNIBUSF4PRO/target.h | 3 +- src/main/target/OMNIBUSF4V3_SS/target.h | 72 ++++++++++++------------- 4 files changed, 63 insertions(+), 69 deletions(-) diff --git a/src/main/target/DYSF4/target.h b/src/main/target/DYSF4/target.h index efce0d1b233..76e79106afa 100644 --- a/src/main/target/DYSF4/target.h +++ b/src/main/target/DYSF4/target.h @@ -50,8 +50,8 @@ #define MPU6000_CS_PIN PA4 #define MPU6000_SPI_BUS BUS_SPI1 - #define USE_IMU_MPU6000 - #define IMU_MPU6000_ALIGN CW180_DEG +#define USE_IMU_MPU6000 +#define IMU_MPU6000_ALIGN CW180_DEG #define USE_MAG #define MAG_I2C_BUS I2C_EXT_BUS @@ -60,11 +60,10 @@ #define TEMPERATURE_I2C_BUS I2C_EXT_BUS #define USE_BARO - - #define BARO_I2C_BUS I2C_EXT_BUS - #define USE_BARO_BMP085 - #define USE_BARO_BMP280 - #define USE_BARO_MS5611 +#define BARO_I2C_BUS I2C_EXT_BUS +#define USE_BARO_BMP085 +#define USE_BARO_BMP280 +#define USE_BARO_MS5611 #define PITOT_I2C_BUS I2C_EXT_BUS @@ -105,7 +104,7 @@ #define USE_SPI_DEVICE_3 - #define SPI3_NSS_PIN PB3 +#define SPI3_NSS_PIN PB3 #define SPI3_SCK_PIN PC10 #define SPI3_MISO_PIN PC11 #define SPI3_MOSI_PIN PC12 @@ -114,11 +113,11 @@ #define MAX7456_SPI_BUS BUS_SPI3 #define MAX7456_CS_PIN PA15 - #define ENABLE_BLACKBOX_LOGGING_ON_SPIFLASH_BY_DEFAULT - #define M25P16_CS_PIN SPI3_NSS_PIN - #define M25P16_SPI_BUS BUS_SPI3 - #define USE_FLASHFS - #define USE_FLASH_M25P16 +#define ENABLE_BLACKBOX_LOGGING_ON_SPIFLASH_BY_DEFAULT +#define M25P16_CS_PIN SPI3_NSS_PIN +#define M25P16_SPI_BUS BUS_SPI3 +#define USE_FLASHFS +#define USE_FLASH_M25P16 #define USE_ADC #define ADC_CHANNEL_1_PIN PC1 @@ -137,7 +136,7 @@ #define SENSORS_SET (SENSOR_ACC|SENSOR_MAG|SENSOR_BARO) #define USE_LED_STRIP - #define WS2811_PIN PA1 +#define WS2811_PIN PA1 #define DISABLE_RX_PWM_FEATURE #define DEFAULT_FEATURES (FEATURE_TX_PROF_SEL | FEATURE_BLACKBOX | FEATURE_VBAT | FEATURE_OSD) diff --git a/src/main/target/OMNIBUSF4/target.h b/src/main/target/OMNIBUSF4/target.h index e3a209cca74..48bdfb7f910 100644 --- a/src/main/target/OMNIBUSF4/target.h +++ b/src/main/target/OMNIBUSF4/target.h @@ -36,8 +36,8 @@ #define MPU6000_CS_PIN PA4 #define MPU6000_SPI_BUS BUS_SPI1 - #define USE_IMU_MPU6000 - #define IMU_MPU6000_ALIGN CW180_DEG +#define USE_IMU_MPU6000 +#define IMU_MPU6000_ALIGN CW180_DEG #define USE_MAG #define MAG_I2C_BUS I2C_EXT_BUS @@ -46,11 +46,10 @@ #define TEMPERATURE_I2C_BUS I2C_EXT_BUS #define USE_BARO - - #define BARO_I2C_BUS I2C_EXT_BUS - #define USE_BARO_BMP085 - #define USE_BARO_BMP280 - #define USE_BARO_MS5611 +#define BARO_I2C_BUS I2C_EXT_BUS +#define USE_BARO_BMP085 +#define USE_BARO_BMP280 +#define USE_BARO_MS5611 #define PITOT_I2C_BUS I2C_EXT_BUS @@ -91,7 +90,7 @@ #define USE_SPI_DEVICE_3 - #define SPI3_NSS_PIN PB3 +#define SPI3_NSS_PIN PB3 #define SPI3_SCK_PIN PC10 #define SPI3_MISO_PIN PC11 #define SPI3_MOSI_PIN PC12 @@ -100,17 +99,16 @@ #define MAX7456_SPI_BUS BUS_SPI3 #define MAX7456_CS_PIN PA15 - #define ENABLE_BLACKBOX_LOGGING_ON_SPIFLASH_BY_DEFAULT - #define M25P16_CS_PIN SPI3_NSS_PIN - #define M25P16_SPI_BUS BUS_SPI3 - #define USE_FLASHFS - #define USE_FLASH_M25P16 +#define ENABLE_BLACKBOX_LOGGING_ON_SPIFLASH_BY_DEFAULT +#define M25P16_CS_PIN SPI3_NSS_PIN +#define M25P16_SPI_BUS BUS_SPI3 +#define USE_FLASHFS +#define USE_FLASH_M25P16 #define USE_ADC #define ADC_CHANNEL_1_PIN PC1 #define ADC_CHANNEL_2_PIN PC2 - - #define ADC_CHANNEL_3_PIN PA0 +#define ADC_CHANNEL_3_PIN PA0 #define CURRENT_METER_ADC_CHANNEL ADC_CHN_1 #define VBAT_ADC_CHANNEL ADC_CHN_2 @@ -119,7 +117,7 @@ #define SENSORS_SET (SENSOR_ACC|SENSOR_MAG|SENSOR_BARO) #define USE_LED_STRIP - #define WS2811_PIN PA1 +#define WS2811_PIN PA1 #define DISABLE_RX_PWM_FEATURE #define DEFAULT_FEATURES (FEATURE_TX_PROF_SEL | FEATURE_BLACKBOX | FEATURE_VBAT | FEATURE_OSD) diff --git a/src/main/target/OMNIBUSF4PRO/target.h b/src/main/target/OMNIBUSF4PRO/target.h index 582dfe08d13..32bac107f96 100644 --- a/src/main/target/OMNIBUSF4PRO/target.h +++ b/src/main/target/OMNIBUSF4PRO/target.h @@ -160,8 +160,7 @@ #define USE_ADC #define ADC_CHANNEL_1_PIN PC1 #define ADC_CHANNEL_2_PIN PC2 - - #define ADC_CHANNEL_3_PIN PA0 +#define ADC_CHANNEL_3_PIN PA0 #define CURRENT_METER_ADC_CHANNEL ADC_CHN_1 #define VBAT_ADC_CHANNEL ADC_CHN_2 diff --git a/src/main/target/OMNIBUSF4V3_SS/target.h b/src/main/target/OMNIBUSF4V3_SS/target.h index 65c87d6f7db..f3cbf6c4a49 100644 --- a/src/main/target/OMNIBUSF4V3_SS/target.h +++ b/src/main/target/OMNIBUSF4V3_SS/target.h @@ -42,20 +42,20 @@ #define MPU6000_CS_PIN PA4 #define MPU6000_SPI_BUS BUS_SPI1 - #define USE_IMU_MPU6000 - #define IMU_MPU6000_ALIGN CW270_DEG +#define USE_IMU_MPU6000 +#define IMU_MPU6000_ALIGN CW270_DEG // Support for OMNIBUS F4 PRO CORNER - it has ICM20608 instead of MPU6000 - #define MPU6500_CS_PIN MPU6000_CS_PIN - #define MPU6500_SPI_BUS MPU6000_SPI_BUS - #define USE_IMU_MPU6500 - #define IMU_MPU6500_ALIGN IMU_MPU6000_ALIGN +#define MPU6500_CS_PIN MPU6000_CS_PIN +#define MPU6500_SPI_BUS MPU6000_SPI_BUS +#define USE_IMU_MPU6500 +#define IMU_MPU6500_ALIGN IMU_MPU6000_ALIGN - //BMI270 - #define USE_IMU_BMI270 - #define IMU_BMI270_ALIGN IMU_MPU6000_ALIGN - #define BMI270_SPI_BUS MPU6000_SPI_BUS - #define BMI270_CS_PIN MPU6000_CS_PIN +//BMI270 +#define USE_IMU_BMI270 +#define IMU_BMI270_ALIGN IMU_MPU6000_ALIGN +#define BMI270_SPI_BUS MPU6000_SPI_BUS +#define BMI270_CS_PIN MPU6000_CS_PIN #define USE_MAG #define MAG_I2C_BUS I2C_EXT_BUS @@ -64,14 +64,13 @@ #define TEMPERATURE_I2C_BUS I2C_EXT_BUS #define USE_BARO - - #define USE_BARO_BMP280 - #define BMP280_SPI_BUS BUS_SPI3 - #define BMP280_CS_PIN PB3 // v1 - // Support external barometers - #define BARO_I2C_BUS I2C_EXT_BUS - #define USE_BARO_BMP085 - #define USE_BARO_MS5611 +#define USE_BARO_BMP280 +#define BMP280_SPI_BUS BUS_SPI3 +#define BMP280_CS_PIN PB3 // v1 +// Support external barometers +#define BARO_I2C_BUS I2C_EXT_BUS +#define USE_BARO_BMP085 +#define USE_BARO_MS5611 #define PITOT_I2C_BUS I2C_EXT_BUS @@ -96,8 +95,8 @@ #define USE_UART6 #define UART6_RX_PIN PC7 #define UART6_TX_PIN PC6 - #define INVERTER_PIN_UART6_RX PC8 - #define INVERTER_PIN_UART6_TX PC9 +#define INVERTER_PIN_UART6_RX PC8 +#define INVERTER_PIN_UART6_TX PC9 #if defined(OMNIBUSF4V3_S6_SS) // one softserial on S6 #define USE_SOFTSERIAL1 @@ -133,14 +132,14 @@ #define USE_SPI_DEVICE_1 - #define USE_SPI_DEVICE_2 - #define SPI2_NSS_PIN PB12 - #define SPI2_SCK_PIN PB13 - #define SPI2_MISO_PIN PB14 - #define SPI2_MOSI_PIN PB15 +#define USE_SPI_DEVICE_2 +#define SPI2_NSS_PIN PB12 +#define SPI2_SCK_PIN PB13 +#define SPI2_MISO_PIN PB14 +#define SPI2_MOSI_PIN PB15 #define USE_SPI_DEVICE_3 - #define SPI3_NSS_PIN PA15 +#define SPI3_NSS_PIN PA15 #define SPI3_SCK_PIN PC10 #define SPI3_MISO_PIN PC11 #define SPI3_MOSI_PIN PC12 @@ -149,21 +148,20 @@ #define MAX7456_SPI_BUS BUS_SPI3 #define MAX7456_CS_PIN PA15 - #define ENABLE_BLACKBOX_LOGGING_ON_SDCARD_BY_DEFAULT - #define USE_SDCARD - #define USE_SDCARD_SPI +#define ENABLE_BLACKBOX_LOGGING_ON_SDCARD_BY_DEFAULT +#define USE_SDCARD +#define USE_SDCARD_SPI - #define SDCARD_SPI_BUS BUS_SPI2 - #define SDCARD_CS_PIN SPI2_NSS_PIN +#define SDCARD_SPI_BUS BUS_SPI2 +#define SDCARD_CS_PIN SPI2_NSS_PIN - #define SDCARD_DETECT_PIN PB7 - #define SDCARD_DETECT_INVERTED +#define SDCARD_DETECT_PIN PB7 +#define SDCARD_DETECT_INVERTED #define USE_ADC #define ADC_CHANNEL_1_PIN PC1 #define ADC_CHANNEL_2_PIN PC2 - - #define ADC_CHANNEL_3_PIN PA0 +#define ADC_CHANNEL_3_PIN PA0 #define CURRENT_METER_ADC_CHANNEL ADC_CHN_1 #define VBAT_ADC_CHANNEL ADC_CHN_2 @@ -172,7 +170,7 @@ #define SENSORS_SET (SENSOR_ACC|SENSOR_MAG|SENSOR_BARO) #define USE_LED_STRIP - #define WS2811_PIN PB6 +#define WS2811_PIN PB6 #define DISABLE_RX_PWM_FEATURE #define DEFAULT_FEATURES (FEATURE_TX_PROF_SEL | FEATURE_BLACKBOX | FEATURE_VBAT | FEATURE_OSD) From eb20c74618e8a20ef5acb85ff62b3018db429081 Mon Sep 17 00:00:00 2001 From: do1234521 Date: Fri, 6 Mar 2026 16:42:53 +0800 Subject: [PATCH 11/42] update AET-H743-Basic - add bmi088 and bmi270 imu --- src/main/target/AETH743Basic/target.c | 6 ++++++ src/main/target/AETH743Basic/target.h | 24 ++++++++++++++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/main/target/AETH743Basic/target.c b/src/main/target/AETH743Basic/target.c index 4a18ed15694..90049806c76 100644 --- a/src/main/target/AETH743Basic/target.c +++ b/src/main/target/AETH743Basic/target.c @@ -26,9 +26,15 @@ #include "drivers/pinio.h" #include "drivers/sensor.h" +// V1:two ICM42688 BUSDEV_REGISTER_SPI_TAG(busdev_icm42688_0, DEVHW_ICM42605, ICM42688_0_SPI_BUS, ICM42688_0_CS_PIN, NONE, 0, DEVFLAGS_NONE, IMU_ICM42688_0_ALIGN); BUSDEV_REGISTER_SPI_TAG(busdev_icm42688_1, DEVHW_ICM42605, ICM42688_1_SPI_BUS, ICM42688_1_CS_PIN, NONE, 2, DEVFLAGS_NONE, IMU_ICM42688_1_ALIGN); +// V2:BMI088 + BMI270 +BUSDEV_REGISTER_SPI_TAG(busdev_bmi088_gyro, DEVHW_BMI088_GYRO, BMI088_SPI_BUS, BMI088_GYRO_CS_PIN, BMI088_GYRO_EXTI_PIN, 0, DEVFLAGS_NONE, IMU_BMI088_ALIGN); +BUSDEV_REGISTER_SPI_TAG(busdev_bmi088_acc, DEVHW_BMI088_ACC, BMI088_SPI_BUS, BMI088_ACC_CS_PIN, BMI088_ACC_EXTI_PIN, 0, DEVFLAGS_NONE, IMU_BMI088_ALIGN); +BUSDEV_REGISTER_SPI_TAG(busdev_bmi270, DEVHW_BMI270, BMI270_SPI_BUS, BMI270_CS_PIN, NONE, 3, DEVFLAGS_NONE, IMU_BMI270_ALIGN); + timerHardware_t timerHardware[] = { DEF_TIM(TIM3, CH3, PB0, TIM_USE_OUTPUT_AUTO, 0, 0), // S1 DEF_TIM(TIM3, CH4, PB1, TIM_USE_OUTPUT_AUTO, 0, 1), // S2 diff --git a/src/main/target/AETH743Basic/target.h b/src/main/target/AETH743Basic/target.h index 642a1f82be5..469b44deda5 100644 --- a/src/main/target/AETH743Basic/target.h +++ b/src/main/target/AETH743Basic/target.h @@ -36,26 +36,41 @@ #define USE_TARGET_IMU_HARDWARE_DESCRIPTORS #define USE_SPI #define USE_IMU_ICM42605 +#define USE_IMU_BMI088 +#define USE_IMU_BMI270 -// *************** SPI1 IMU0 ICM42688 **************** +// *************** SPI1 IMU0 ICM42688 or BMI088 **************** #define USE_SPI_DEVICE_1 #define SPI1_SCK_PIN PA5 #define SPI1_MISO_PIN PA6 #define SPI1_MOSI_PIN PD7 +#define SPI1_NSS_PIN PC15 #define IMU_ICM42688_0_ALIGN CW0_DEG_FLIP #define ICM42688_0_SPI_BUS BUS_SPI1 -#define ICM42688_0_CS_PIN PC15 +#define ICM42688_0_CS_PIN SPI1_NSS_PIN -// *************** SPI4 IMU1 ICM42688 ************** +#define IMU_BMI088_ALIGN CW270_DEG_FLIP +#define BMI088_SPI_BUS BUS_SPI1 +#define BMI088_GYRO_CS_PIN PE11 +#define BMI088_GYRO_EXTI_PIN PE2 +#define BMI088_ACC_CS_PIN SPI1_NSS_PIN +#define BMI088_ACC_EXTI_PIN PD4 + +// *************** SPI4 IMU1 ICM42688 or BMI270 ************** #define USE_SPI_DEVICE_4 #define SPI4_SCK_PIN PE12 #define SPI4_MISO_PIN PE13 #define SPI4_MOSI_PIN PE14 +#define SPI4_NSS_PIN PC13 #define IMU_ICM42688_1_ALIGN CW90_DEG_FLIP #define ICM42688_1_SPI_BUS BUS_SPI4 -#define ICM42688_1_CS_PIN PC13 +#define ICM42688_1_CS_PIN SPI4_NSS_PIN + +#define IMU_BMI270_ALIGN CW270_DEG_FLIP +#define BMI270_SPI_BUS BUS_SPI4 +#define BMI270_CS_PIN SPI4_NSS_PIN // *************** SPI2 OSD *********************** #define USE_SPI_DEVICE_2 @@ -80,6 +95,7 @@ #define USE_BARO #define BARO_I2C_BUS BUS_I2C2 #define USE_BARO_SPL06 +#define USE_BARO_DPS310 #define USE_MAG #define MAG_I2C_BUS BUS_I2C1 From d6db20e7145c57575e2d3a6381af95f76dc9f08b Mon Sep 17 00:00:00 2001 From: daijoubu Date: Mon, 8 Jun 2026 16:14:03 -0700 Subject: [PATCH 12/42] fix(gps): guard against NULL serial port when GPS provider changed without reboot Driver-based providers (MSP, FAKE) leave gpsState.gpsPort NULL because gpsInit() skips serial port opening for them. If gps_provider is then changed via CLI to a serial-based provider without rebooting, the next gpsUpdate() tick dispatches into the serial protocol handler with a NULL port, causing a hard fault. Add a guard in gpsUpdate() that returns false early when a serial-based provider is configured but no port is open. Also guard gpsEnablePassthrough() which had the same latent NULL dereference. --- src/main/io/gps.c | 11 + src/test/unit/CMakeLists.txt | 3 + src/test/unit/gps_null_port_unittest.cc | 446 ++++++++++++++++++++++++ 3 files changed, 460 insertions(+) create mode 100644 src/test/unit/gps_null_port_unittest.cc diff --git a/src/main/io/gps.c b/src/main/io/gps.c index 4e2bda3157d..41901e1e209 100755 --- a/src/main/io/gps.c +++ b/src/main/io/gps.c @@ -547,6 +547,13 @@ bool gpsUpdate(void) } #endif + // Driver-based providers (MSP, FAKE) never open a serial port; gpsPort stays NULL. + // If gps_provider is changed via CLI to a serial-based provider without rebooting, + // the serial handler would dereference NULL on the next tick and hard-fault. + if (!gpsProviders[gpsState.gpsConfig->provider].isDriverBased && !gpsState.gpsPort) { + return false; + } + switch (gpsState.state) { default: case GPS_INITIALIZING: @@ -597,6 +604,10 @@ bool gpsUpdate(void) void gpsEnablePassthrough(serialPort_t *gpsPassthroughPort) { + if (!gpsState.gpsPort) { + return; + } + waitForSerialPortToFinishTransmitting(gpsState.gpsPort); waitForSerialPortToFinishTransmitting(gpsPassthroughPort); diff --git a/src/test/unit/CMakeLists.txt b/src/test/unit/CMakeLists.txt index 2cb53b64ecb..7ac93335d98 100644 --- a/src/test/unit/CMakeLists.txt +++ b/src/test/unit/CMakeLists.txt @@ -40,6 +40,9 @@ set_property(SOURCE osd_unittest.cc PROPERTY definitions OSD_UNIT_TEST USE_MSP_D set_property(SOURCE gps_ublox_unittest.cc PROPERTY depends "io/gps_ublox_utils.c") set_property(SOURCE gps_ublox_unittest.cc PROPERTY definitions GPS_UBLOX_UNIT_TEST) +set_property(SOURCE gps_null_port_unittest.cc PROPERTY depends "io/gps.c") +set_property(SOURCE gps_null_port_unittest.cc PROPERTY definitions GPS_NULL_PORT_UNIT_TEST USE_GPS_PROTO_UBLOX) + set_property(SOURCE gimbal_serial_unittest.cc PROPERTY depends "io/gimbal_serial.c" "drivers/gimbal_common.c" "common/maths.c" "drivers/headtracker_common.c") set_property(SOURCE gimbal_serial_unittest.cc PROPERTY definitions USE_SERIAL_GIMBAL GIMBAL_UNIT_TEST USE_HEADTRACKER) diff --git a/src/test/unit/gps_null_port_unittest.cc b/src/test/unit/gps_null_port_unittest.cc new file mode 100644 index 00000000000..288b68995c9 --- /dev/null +++ b/src/test/unit/gps_null_port_unittest.cc @@ -0,0 +1,446 @@ +/* + * This file is part of INAV. + * + * INAV is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * INAV is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with INAV. If not, see . + */ + +/* + * Reproduction test for the NULL gpsPort hard-fault bug. + * + * Scenario + * -------- + * The FC boots with a driver-based GPS provider (GPS_MSP / GPS_FAKE). + * gpsInit() sets gpsState.gpsPort = NULL because driver-based providers + * do not open a serial port. If the user then changes gps_provider via + * the CLI to GPS_UBLOX (a serial-based provider) without rebooting, the + * next call to gpsUpdate() dispatches into gpsHandleUBLOX(), which calls + * serialRxBytesWaiting(gpsState.gpsPort) with a NULL pointer → hard fault + * on real hardware. + * + * There is a second exposure: gpsEnablePassthrough() dereferences + * gpsState.gpsPort without a NULL check, but that path requires a + * separate passthrough session, so only the gpsUpdate() path is exercised + * here. + * + * How the test encodes the fault + * ------------------------------ + * The stub for serialRxBytesWaiting() calls ADD_FAILURE() whenever it is + * invoked with a NULL pointer. Before the fix gpsUpdate() triggers this + * failure; after the fix it returns false gracefully without ever calling + * into gpsHandleUBLOX(). + * + * Expected result (after the fix) + * -------------------------------- + * gpsUpdate() detects that the active provider is serial-based but + * gpsState.gpsPort == NULL and returns false without calling the protocol + * handler. The serialRxBytesWaiting stub is never called with NULL. + */ + +#include "gtest/gtest.h" +#include "unittest_macros.h" + +#include +#include +#include + +extern "C" { + +/* Pull in the types we need. */ +#include "common/time.h" + +#include "config/parameter_group.h" +#include "config/parameter_group_ids.h" + +#include "drivers/serial.h" + +/* fc/config.h provides the FEATURE_GPS enum value. */ +#include "fc/config.h" +#include "fc/runtime_config.h" + +#include "io/gps.h" +#include "io/gps_private.h" + +/* Expose the globals defined in gps.c so the test can manipulate them. */ +extern gpsReceiverData_t gpsState; +extern gpsSolutionData_t gpsSolDRV; +extern gpsSolutionData_t gpsSol; + +/* PG_DECLARE in gps.h expands to: + * extern gpsConfig_t gpsConfig_System; + * static inline const gpsConfig_t *gpsConfig(void) { return &gpsConfig_System; } + * gps.c's PG_REGISTER_WITH_RESET_TEMPLATE provides the storage. */ +extern gpsConfig_t gpsConfig_System; + +/* ---- serial infrastructure stubs ------------------------------------ */ +/* io/serial.c normally provides these; we stub them since we do not */ +/* compile serial.c as part of this test. */ + +/* baudRates[] maps baudRate_e enum values to integer baud rates. */ +/* Must match the baudRate_e enum in io/serial.h (BAUD_AUTO through */ +/* BAUD_2470000). */ +const uint32_t baudRates[] = { 0, 1200, 2400, 4800, 9600, 19200, 38400, + 57600, 115200, 230400, 250000, 460800, 921600, + 1000000, 1500000, 2000000, 2470000 }; /* see baudRate_e */ + +/* serialConfig_System is the PG storage for serialConfig(). */ +/* gpsInit() accesses it; gpsUpdate() does not, but the linker needs it */ +/* because gpsInit() lives in the same translation unit as gpsUpdate(). */ +serialConfig_t serialConfig_System; + +/* ---- test-observable state -------------------------------------------- */ +static bool serialRxBytesWaitingCalledWithNull = false; + +/* ---- millis() controllable clock -------------------------------------- */ +static uint32_t fakeMillis = 0; + +uint32_t millis(void) { return fakeMillis; } +uint32_t micros(void) { return fakeMillis * 1000UL; } + +/* ---- feature / sensors stubs ----------------------------------------- */ +static uint32_t fakeFeatureMask = 0; + +bool feature(uint32_t mask) { return (fakeFeatureMask & mask) != 0; } +void featureSet(uint32_t mask) { fakeFeatureMask |= mask; } +void featureClear(uint32_t mask) { fakeFeatureMask &= ~mask; } + +static uint32_t fakeSensorMask = 0; + +bool sensors(uint32_t mask) { return (fakeSensorMask & mask) != 0; } +void sensorsSet(uint32_t mask) { fakeSensorMask |= mask; } +void sensorsClear(uint32_t mask) { fakeSensorMask &= ~mask; } + +/* ---- serial stubs ----------------------------------------------------- */ + +/* + * This is the critical mock. On real hardware, if gpsState.gpsPort is NULL + * the firmware hard-faults when the serial driver dereferences the pointer. + * In the unit test we record the call and fail the test instead. + * + * Before the fix: gpsUpdate() reaches this with a NULL pointer → failure. + * After the fix: gpsUpdate() returns before calling this → no failure. + */ +uint32_t serialRxBytesWaiting(const serialPort_t *instance) +{ + if (instance == NULL) { + serialRxBytesWaitingCalledWithNull = true; + ADD_FAILURE() << "serialRxBytesWaiting() called with NULL gpsPort — " + "this would hard-fault on real hardware"; + } + return 0; +} + +uint32_t serialTxBytesFree(const serialPort_t *instance) +{ + UNUSED(instance); + return 256; +} + +bool isSerialTransmitBufferEmpty(const serialPort_t *instance) +{ + UNUSED(instance); + return true; +} + +uint8_t serialRead(serialPort_t *instance) +{ + UNUSED(instance); + return 0; +} + +void serialWrite(serialPort_t *instance, uint8_t ch) +{ + UNUSED(instance); + UNUSED(ch); +} + +void serialWriteBuf(serialPort_t *instance, const uint8_t *data, int count) +{ + UNUSED(instance); + UNUSED(data); + UNUSED(count); +} + +void serialPrint(serialPort_t *instance, const char *str) +{ + UNUSED(instance); + UNUSED(str); +} + +void serialSetMode(serialPort_t *instance, portMode_t mode) +{ + UNUSED(instance); + UNUSED(mode); +} + +void serialSetBaudRate(serialPort_t *instance, uint32_t baudRate) +{ + UNUSED(instance); + UNUSED(baudRate); +} + +serialPort_t *openSerialPort(serialPortIdentifier_e identifier, + serialPortFunction_e function, + serialReceiveCallbackPtr rxCallback, + void *rxCallbackData, + uint32_t baudRate, portMode_t mode, + portOptions_t options) +{ + UNUSED(identifier); UNUSED(function); UNUSED(rxCallback); + UNUSED(rxCallbackData); UNUSED(baudRate); UNUSED(mode); UNUSED(options); + return NULL; +} + +void closeSerialPort(serialPort_t *serialPort) { UNUSED(serialPort); } + +serialPortConfig_t *findSerialPortConfig(serialPortFunction_e function) +{ + UNUSED(function); + return NULL; +} + +void waitForSerialPortToFinishTransmitting(serialPort_t *serialPort) +{ + UNUSED(serialPort); +} + +/* ---- stateFlags / armingFlags stubs ---------------------------------- */ +uint32_t stateFlags = 0; +uint32_t armingFlags = 0; + +/* ---- system stubs ----------------------------------------------------- */ +bool isMPUSoftReset(void) { return false; } + +/* ---- LED stubs -------------------------------------------------------- */ +void LED0_ON(void) {} +void LED0_OFF(void) {} +void LED1_ON(void) {} +void LED1_OFF(void) {} +void LED1_TOGGLE(void) {} + +/* ---- navigation / sensor stubs --------------------------------------- */ +void onNewGPSData(void) {} + +bool rtcHasTime(void) { return false; } +bool rtcSetDateTime(dateTime_t *dt) { UNUSED(dt); return true; } + +bool baroIsHealthy(void) { return false; } +bool pitotIsHealthy(void) { return false; } + +/* ---- UBLOX protocol stubs -------------------------------------------- */ +/* + * gps.c references gpsRestartUBLOX() and gpsHandleUBLOX() which are + * normally provided by gps_ublox.c. We do NOT compile gps_ublox.c + * (it carries too many dependencies), so we stub them here. + * + * The stubs are intentionally minimal: gpsRestartUBLOX() does nothing + * (the test checks the guard before restart is called), and + * gpsHandleUBLOX() calls serialRxBytesWaiting() to simulate the exact + * operation that hard-faults in production. + */ +void gpsRestartUBLOX(void) +{ + /* In the production code this resets the protothread state and starts + * the receiver/state threads. For the test we do nothing: the guard + * under test should prevent this function from being reached when + * gpsPort is NULL. */ +} + +void gpsHandleUBLOX(void) +{ + /* + * In production this runs the protothread that immediately calls + * serialRxBytesWaiting(gpsState.gpsPort). Replicate that first + * operation here so the test observes the NULL dereference if the + * guard in gpsUpdate() is absent. + */ + (void)serialRxBytesWaiting(gpsState.gpsPort); +} + +/* ---- MSP / FAKE GPS stubs (not compiled in test target, but needed + * for link completeness if the linker sees the symbols) ----------- */ +/* These are guarded by USE_GPS_PROTO_MSP / USE_GPS_FAKE in gps.c so they + * will not appear in the compilation unit. Nothing to stub. */ + +} // extern "C" + +/* ====================================================================== + * Test fixture + * ====================================================================== */ + +class GpsNullPortTest : public ::testing::Test { +protected: + void SetUp() override { + /* Reset observable state. */ + serialRxBytesWaitingCalledWithNull = false; + + /* Enable FEATURE_GPS so gpsUpdate() does not exit early. */ + featureSet(FEATURE_GPS); + + /* + * Advance millis() past GPS_BOOT_DELAY (3000 ms). gpsUpdate() + * has a boot-delay guard: if millis() < GPS_BOOT_DELAY it returns + * false immediately without exercising the state machine. + */ + fakeMillis = 5000; + + /* Clear state/arming flags. */ + stateFlags = 0; + armingFlags = 0; + + /* Initialise solution structs. */ + memset(&gpsSol, 0, sizeof(gpsSol)); + memset(&gpsSolDRV, 0, sizeof(gpsSolDRV)); + + /* + * Set up the GPS config for a serial-based provider (GPS_UBLOX). + * gpsConfig_System is the storage used by the PG accessor + * gpsConfig() defined in gps.h and allocated by gps.c. + */ + memset(&gpsConfig_System, 0, sizeof(gpsConfig_System)); + gpsConfig_System.provider = GPS_UBLOX; + + /* Point gpsState at the config and set sane defaults. */ + gpsState.gpsConfig = &gpsConfig_System; + gpsState.baseTimeoutMs = 1000; + /* lastMessageMs == fakeMillis: no timeout yet. */ + gpsState.lastMessageMs = fakeMillis; + + /* + * Simulate the buggy scenario: the FC booted with a driver-based + * provider (e.g. GPS_MSP), so gpsInit() left gpsPort as NULL + * (no serial port was opened). The user then changed provider + * to GPS_UBLOX via CLI without rebooting. + */ + gpsState.gpsPort = NULL; + } + + void TearDown() override { + fakeFeatureMask = 0; + fakeSensorMask = 0; + } +}; + +/* ====================================================================== + * Test 1 — Bug reproduction: GPS_RUNNING + NULL port + serial provider + * + * The state machine is placed directly into GPS_RUNNING so the protocol + * handler (gpsHandleUBLOX) is called on the very first gpsUpdate(). + * + * Before the fix: gpsHandleUBLOX() calls serialRxBytesWaiting(NULL) + * → ADD_FAILURE() fires inside the stub. + * + * After the fix: gpsUpdate() detects the NULL port for a serial-based + * provider and returns false before reaching gpsHandleUBLOX(). + * ====================================================================== */ +TEST_F(GpsNullPortTest, NullPortInRunningState_ShouldNotCrash) +{ + /* Place the state machine in GPS_RUNNING so the protocol handler + * is invoked immediately, skipping the INITIALIZING delay. */ + gpsState.state = GPS_RUNNING; + gpsState.lastStateSwitchMs = fakeMillis - 600; /* > GPS_INIT_DELAY (500 ms) */ + + bool result = gpsUpdate(); + + /* + * The key assertion: serialRxBytesWaiting must NOT have been called + * with NULL. If it was, ADD_FAILURE() already recorded the failure + * in the stub; this EXPECT makes the intent explicit. + */ + EXPECT_FALSE(serialRxBytesWaitingCalledWithNull) + << "gpsUpdate() called serialRxBytesWaiting(NULL) — " + "the null-port guard is missing from gpsUpdate()"; + + /* With the guard in place gpsUpdate() returns false (no new data). */ + EXPECT_FALSE(result) + << "gpsUpdate() should return false when gpsPort is NULL " + "for a serial-based provider"; +} + +/* ====================================================================== + * Test 2 — Bug reproduction: INITIALIZING → RUNNING transition + * + * Same scenario starting from GPS_INITIALIZING. After the init delay + * expires, gpsUpdate() calls restart() and transitions to GPS_RUNNING, + * then breaks — protocol() is NOT called in that same tick. The dangerous + * serialRxBytesWaiting(NULL) would only fire on the next entry when state + * is already GPS_RUNNING (covered by Test 1). + * + * The pre-switch guard fires before restart() is reached, so a stale + * GPS_INITIALIZING state left by the boot-with-driver-based scenario is + * also protected. + * ====================================================================== */ +TEST_F(GpsNullPortTest, NullPortTransitionFromInitializing_ShouldNotCrash) +{ + /* Start in INITIALIZING with the delay already expired. */ + gpsState.state = GPS_INITIALIZING; + gpsState.lastStateSwitchMs = fakeMillis - 1000; /* >> GPS_INIT_DELAY (500 ms) */ + + bool result = gpsUpdate(); + + EXPECT_FALSE(serialRxBytesWaitingCalledWithNull) + << "gpsUpdate() called serialRxBytesWaiting(NULL) during " + "INITIALIZING→RUNNING transition"; + + EXPECT_FALSE(result); +} + +/* ====================================================================== + * Test 3 — Positive case: serial provider + non-NULL port + * + * When gpsPort is valid, gpsUpdate() must proceed normally. The guard + * must not block a legitimate call. + * ====================================================================== */ +TEST_F(GpsNullPortTest, NonNullPortSerialProvider_GuardDoesNotBlock) +{ + /* Provide a fake non-NULL port. The serial stubs accept any pointer. */ + static serialPort_t fakePort; + gpsState.gpsPort = &fakePort; + gpsState.state = GPS_RUNNING; + gpsState.lastStateSwitchMs = fakeMillis - 600; + + /* + * gpsUpdate() is allowed to call into gpsHandleUBLOX() here. + * gpsHandleUBLOX() passes &fakePort to serialRxBytesWaiting(), which + * is non-NULL, so the failure path in the stub is not triggered. + */ + gpsUpdate(); + + EXPECT_FALSE(serialRxBytesWaitingCalledWithNull) + << "serialRxBytesWaiting was unexpectedly called with NULL " + "even though gpsPort was non-NULL"; +} + +/* ====================================================================== + * Test 4 — Negative: FEATURE_GPS disabled + * + * If the GPS feature is not enabled, gpsUpdate() must return false + * immediately without touching gpsPort at all. This is an existing + * guard, but we verify it is not broken by the new guard. + * ====================================================================== */ +TEST_F(GpsNullPortTest, FeatureGpsDisabled_ReturnsEarlyWithoutTouchingPort) +{ + featureClear(FEATURE_GPS); + + gpsState.state = GPS_RUNNING; + gpsState.lastStateSwitchMs = fakeMillis - 600; + /* gpsPort stays NULL — any dereference would fire the stub. */ + + bool result = gpsUpdate(); + + EXPECT_FALSE(serialRxBytesWaitingCalledWithNull) + << "serialRxBytesWaiting was called with NULL even though " + "FEATURE_GPS was disabled"; + + EXPECT_FALSE(result); +} From 68f27979b5e261e0d1135ddde1dda3f762fbffba Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 8 Jun 2026 22:43:44 -0500 Subject: [PATCH 13/42] Add BMI270 support to COREWINGF405WINGV2 New board revision ships with BMI270 instead of ICM42688. Adding BMI270 defines on the same SPI1/PA4 allows a single firmware image to serve both board revisions via INAV's auto-probe at boot. --- src/main/target/COREWINGF405WINGV2/target.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/target/COREWINGF405WINGV2/target.h b/src/main/target/COREWINGF405WINGV2/target.h index 2176728d84d..e2c4f1a8ee9 100644 --- a/src/main/target/COREWINGF405WINGV2/target.h +++ b/src/main/target/COREWINGF405WINGV2/target.h @@ -102,6 +102,10 @@ #define ICM42605_CS_PIN PA4 #define ICM42605_SPI_BUS BUS_SPI1 +#define USE_IMU_BMI270 +#define IMU_BMI270_ALIGN CW270_DEG +#define BMI270_CS_PIN PA4 +#define BMI270_SPI_BUS BUS_SPI1 // Baro #define USE_BARO From c0ba786e11861ad97d0392429a1327c8cacd68fd Mon Sep 17 00:00:00 2001 From: dtrbinh Date: Tue, 9 Jun 2026 22:45:59 +0700 Subject: [PATCH 14/42] target/JHEMCUF435: fix UART7 ESC telemetry defaults --- src/main/target/JHEMCUF435/config.c | 35 +++++++++++++++++++++++++++++ src/main/target/JHEMCUF435/target.h | 4 ++-- 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 src/main/target/JHEMCUF435/config.c diff --git a/src/main/target/JHEMCUF435/config.c b/src/main/target/JHEMCUF435/config.c new file mode 100644 index 00000000000..bb6078293ed --- /dev/null +++ b/src/main/target/JHEMCUF435/config.c @@ -0,0 +1,35 @@ +/* + * This file is part of INAV Project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Alternatively, the contents of this file may be used under the terms + * of the GNU General Public License Version 3, as described below: + * + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ + +#include + +#include "platform.h" + +#include "io/serial.h" + +void targetConfiguration(void) +{ + serialConfigMutable()->portConfigs[findSerialPortIndexByIdentifier(SERIAL_PORT_USART2)].functionMask = FUNCTION_RX_SERIAL; + serialConfigMutable()->portConfigs[findSerialPortIndexByIdentifier(SERIAL_PORT_USART7)].functionMask = FUNCTION_ESCSERIAL; +} \ No newline at end of file diff --git a/src/main/target/JHEMCUF435/target.h b/src/main/target/JHEMCUF435/target.h index edbc3d0bbda..e061f67cd76 100644 --- a/src/main/target/JHEMCUF435/target.h +++ b/src/main/target/JHEMCUF435/target.h @@ -137,7 +137,7 @@ #define UART6_TX_PIN PC6 #define USE_UART7 -//#define USE_UART7_PIN_SWAP +#define USE_UART7_PIN_SWAP #define UART7_RX_PIN PC0 #define UART7_TX_PIN PC1 @@ -149,7 +149,7 @@ #define DEFAULT_RX_TYPE RX_TYPE_SERIAL #define SERIALRX_PROVIDER SERIALRX_CRSF -#define SERIALRX_UART SERIAL_PORT_USART5 +#define SERIALRX_UART SERIAL_PORT_USART2 // *************** ADC ***************************** #define USE_ADC From 6c6df28b856c4a7e58bc2d642f5992e677459109 Mon Sep 17 00:00:00 2001 From: daijoubu Date: Tue, 9 Jun 2026 19:54:27 -0700 Subject: [PATCH 15/42] fix(gps): clamp negative uBlox nano field before millis conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The nano field in UBX-NAV-TIMEUTC and UBX-NAV-PVT messages is int32_t and legitimately goes negative near second boundaries. Dividing without clamping produced a large positive uint16_t (e.g. -50ms → 65486 ms), setting the RTC ~64 seconds fast on first GPS lock. Once set, rtcHasTime() prevents correction until reboot. Clamp to zero before the division on both message handlers. --- src/main/io/gps_ublox.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/io/gps_ublox.c b/src/main/io/gps_ublox.c index 4fd0c332a21..95feedabb6c 100755 --- a/src/main/io/gps_ublox.c +++ b/src/main/io/gps_ublox.c @@ -635,7 +635,7 @@ static bool gpsParseFrameUBLOX(void) gpsSolDRV.time.hours = _buffer.timeutc.hour; gpsSolDRV.time.minutes = _buffer.timeutc.min; gpsSolDRV.time.seconds = _buffer.timeutc.sec; - gpsSolDRV.time.millis = _buffer.timeutc.nano / (1000*1000); + gpsSolDRV.time.millis = (uint16_t)(MAX(0, _buffer.timeutc.nano) / (1000*1000)); gpsSolDRV.flags.validTime = true; } else { @@ -674,7 +674,7 @@ static bool gpsParseFrameUBLOX(void) gpsSolDRV.time.hours = _buffer.pvt.hour; gpsSolDRV.time.minutes = _buffer.pvt.min; gpsSolDRV.time.seconds = _buffer.pvt.sec; - gpsSolDRV.time.millis = _buffer.pvt.nano / (1000*1000); + gpsSolDRV.time.millis = (uint16_t)(MAX(0, _buffer.pvt.nano) / (1000*1000)); gpsSolDRV.flags.validTime = true; } else { From ea888d4ceb99f1f76fd8889839335af471686013 Mon Sep 17 00:00:00 2001 From: Benedikt Kleiner Date: Tue, 9 Jun 2026 13:26:50 +0800 Subject: [PATCH 16/42] Add ICM42686P IMU support --- src/main/drivers/accgyro/accgyro_icm42605.c | 53 ++++++++++++++++----- src/main/drivers/accgyro/accgyro_mpu.h | 1 + 2 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/main/drivers/accgyro/accgyro_icm42605.c b/src/main/drivers/accgyro/accgyro_icm42605.c index d0c4e3490aa..b4f573a06c0 100644 --- a/src/main/drivers/accgyro/accgyro_icm42605.c +++ b/src/main/drivers/accgyro/accgyro_icm42605.c @@ -103,7 +103,13 @@ #define ICM426XX_RA_ACCEL_CONFIG_STATIC3 0x04 // User Bank 2 #define ICM426XX_RA_ACCEL_CONFIG_STATIC4 0x05 // User Bank 2 -static bool is42688P = false; +typedef enum { + ICM42605_VARIANT_42605 = 0, + ICM42605_VARIANT_42686P, + ICM42605_VARIANT_42688P, +} icm42605Variant_e; + +static icm42605Variant_e icm42605DetectedVariant = ICM42605_VARIANT_42605; typedef struct aafConfig_s { uint16_t freq; @@ -145,7 +151,7 @@ static aafConfig_t aafLUT42605[] = { // see table in section 5.3 https://invens { 0, 0, 0, 0 } }; -static const aafConfig_t *getGyroAafConfig(bool is42688, const uint16_t desiredLpf); +static const aafConfig_t *getGyroAafConfig(icm42605Variant_e variant, const uint16_t desiredLpf); static void setUserBank(const busDevice_t *dev, const uint8_t user_bank) { @@ -214,11 +220,16 @@ static void icm42605AccAndGyroInit(gyroDev_t *gyro) busWrite(dev, ICM42605_RA_PWR_MGMT0, ICM42605_PWR_MGMT0_TEMP_DISABLE_OFF | ICM42605_PWR_MGMT0_ACCEL_MODE_LN | ICM42605_PWR_MGMT0_GYRO_MODE_LN); delay(15); + uint8_t fsSel = 0; + if (icm42605DetectedVariant == ICM42605_VARIANT_42686P) { + fsSel = 1; // ICM-42686-P normal range: 2000 deg/s, 16G. + } + /* ODR and dynamic range */ - busWrite(dev, ICM42605_RA_GYRO_CONFIG0, (0x00) << 5 | (config->gyroConfigValues[1] & 0x0F)); /* 2000 deg/s */ + busWrite(dev, ICM42605_RA_GYRO_CONFIG0, fsSel << 5 | (config->gyroConfigValues[1] & 0x0F)); /* 2000 deg/s */ delay(15); - busWrite(dev, ICM42605_RA_ACCEL_CONFIG0, (0x00) << 5 | (config->gyroConfigValues[1] & 0x0F)); /* 16 G deg/s */ + busWrite(dev, ICM42605_RA_ACCEL_CONFIG0, fsSel << 5 | (config->gyroConfigValues[1] & 0x0F)); /* 16 G deg/s */ delay(15); /* LPF bandwidth */ @@ -228,14 +239,14 @@ static void icm42605AccAndGyroInit(gyroDev_t *gyro) if (gyro->lpf != GYRO_LPF_NONE) { // Configure gyro Anti-Alias Filter (see section 5.3 "ANTI-ALIAS FILTER") - const aafConfig_t *aafConfig = getGyroAafConfig(is42688P, gyro->lpf); + const aafConfig_t *aafConfig = getGyroAafConfig(icm42605DetectedVariant, gyro->lpf); setUserBank(dev, ICM426XX_BANK_SELECT1); busWrite(dev, ICM426XX_RA_GYRO_CONFIG_STATIC3, aafConfig->delt); busWrite(dev, ICM426XX_RA_GYRO_CONFIG_STATIC4, aafConfig->deltSqr & 0xFF); busWrite(dev, ICM426XX_RA_GYRO_CONFIG_STATIC5, (aafConfig->deltSqr >> 8) | (aafConfig->bitshift << 4)); - aafConfig = getGyroAafConfig(is42688P, 256); // This was hard coded on BF + aafConfig = getGyroAafConfig(icm42605DetectedVariant, 256); // This was hard coded on BF setUserBank(dev, ICM426XX_BANK_SELECT2); busWrite(dev, ICM426XX_RA_ACCEL_CONFIG_STATIC2, aafConfig->delt << 1); busWrite(dev, ICM426XX_RA_ACCEL_CONFIG_STATIC3, aafConfig->deltSqr & 0xFF); @@ -289,12 +300,15 @@ static bool icm42605DeviceDetect(busDevice_t * dev) busRead(dev, MPU_RA_WHO_AM_I, &tmp); switch (tmp) { - /* ICM42605 and ICM42688P share the register structure*/ + /* ICM42605, ICM42686P and ICM42688P share the register structure */ case ICM42605_WHO_AM_I_CONST: - is42688P = false; + icm42605DetectedVariant = ICM42605_VARIANT_42605; + return true; + case ICM42686P_WHO_AM_I_CONST: + icm42605DetectedVariant = ICM42605_VARIANT_42686P; return true; case ICM42688P_WHO_AM_I_CONST: - is42688P = true; + icm42605DetectedVariant = ICM42605_VARIANT_42688P; return true; default: @@ -385,11 +399,24 @@ static uint16_t getAafFreq(const uint8_t gyroLpf) } } -static const aafConfig_t *getGyroAafConfig(bool is42688, const uint16_t desiredLpf) +static const char *icm42605VariantName(icm42605Variant_e variant) +{ + switch (variant) { + case ICM42605_VARIANT_42686P: + return "42686P"; + case ICM42605_VARIANT_42688P: + return "42688P"; + case ICM42605_VARIANT_42605: + default: + return "42605"; + } +} + +static const aafConfig_t *getGyroAafConfig(icm42605Variant_e variant, const uint16_t desiredLpf) { uint16_t desiredFreq = getAafFreq(desiredLpf); const aafConfig_t *aafConfigs = NULL; - if (is42688) { + if (variant == ICM42605_VARIANT_42686P || variant == ICM42605_VARIANT_42688P) { aafConfigs = aafLUT42688; } else { aafConfigs = aafLUT42605; @@ -406,8 +433,8 @@ static const aafConfig_t *getGyroAafConfig(bool is42688, const uint16_t desiredL } } - LOG_VERBOSE(GYRO, "ICM426%s AAF CONFIG { %d, %d } -> { %d }; delt: %d deltSqr: %d, shift: %d", - (is42688P ? "88" : "05"), + LOG_VERBOSE(GYRO, "ICM%s AAF CONFIG { %d, %d } -> { %d }; delt: %d deltSqr: %d, shift: %d", + icm42605VariantName(variant), desiredLpf, desiredFreq, candidate->freq, candidate->delt, candidate->deltSqr, candidate->bitshift); diff --git a/src/main/drivers/accgyro/accgyro_mpu.h b/src/main/drivers/accgyro/accgyro_mpu.h index 0f59d10d3e8..4adf54e6f38 100644 --- a/src/main/drivers/accgyro/accgyro_mpu.h +++ b/src/main/drivers/accgyro/accgyro_mpu.h @@ -29,6 +29,7 @@ #define ICM20608G_WHO_AM_I_CONST (0xAF) #define ICM20689_WHO_AM_I_CONST (0x98) #define ICM42605_WHO_AM_I_CONST (0x42) +#define ICM42686P_WHO_AM_I_CONST (0x44) #define ICM42688P_WHO_AM_I_CONST (0x47) #define ICM45686_WHO_AM_I_CONST (0xE9) From c499f5f1e24b7637488f3d12eeace3ba7f106c0e Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Tue, 23 Jun 2026 12:20:32 -0500 Subject: [PATCH 17/42] fix(sdcard): remove blocking delay from SDIO retry path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove blocking `delay(1)` calls from SDIO SD-card driver retry logic in both read and write paths. These delays stalled the flight-control loop on transient DMA/bus rejections, causing loop overruns and dropped gyro samples during active blackbox logging. The retries are naturally paced by the asyncfatfs/blackbox polling loop (one iteration per PID loop), which eliminates the need for an explicit delay. By returning SDCARD_OPERATION_BUSY / false immediately on rejection, the cooperative scheduler continues running other tasks instead of spinning the CPU for 1 ms per retry. Impact: - Eliminates up to ~3 ms of blocking CPU stall per transient rejection (3 retries × 1 ms delay at 2 kHz loop rate) - Retries still occur up to SDCARD_MAX_OPERATION_RETRIES (3) times before card reset, preserving the retry-before-reset intent - Retry spacing now depends on loop rate: - 1 kHz loop: 1 ms spacing (same as before) - 2-4 kHz loop: 250-500 µs spacing (tighter, safer for fast loops) Backend audit: sdcard_spi.c, sdmmc_sdio_f4xx.c, and sdmmc_sdio_hal.c all have no per-block hot-path blocking delays (only init/reset delays). --- src/main/drivers/sdcard/sdcard_sdio.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/drivers/sdcard/sdcard_sdio.c b/src/main/drivers/sdcard/sdcard_sdio.c index d7cd8ff3c54..bb8289f9b02 100644 --- a/src/main/drivers/sdcard/sdcard_sdio.c +++ b/src/main/drivers/sdcard/sdcard_sdio.c @@ -461,12 +461,12 @@ static sdcardOperationStatus_e sdcardSdio_writeBlock(uint32_t blockIndex, uint8_ if (SD_WriteBlocks_DMA(blockIndex, (uint32_t*) buffer, 512, block_count) != SD_OK) { /* Our write was rejected! Try a few times before giving up. - * This handles transient DMA/bus issues without full card reset. + * This handles transient DMA/bus issues without a full card reset. + * Returning busy without blocking: the blackbox/asyncfatfs flush re-issues + * this operation on the next PID loop, which paces the retries for us. */ if (sdcard.operationRetries < SDCARD_MAX_OPERATION_RETRIES) { sdcard.operationRetries++; - // Brief delay before retry - delay(1); return SDCARD_OPERATION_BUSY; } @@ -562,11 +562,11 @@ static bool sdcardSdio_readBlock(uint32_t blockIndex, uint8_t *buffer, sdcard_op } else { /* Read was rejected! Try a few times before giving up. * This handles transient DMA/bus issues without full card reset. + * Returning busy without blocking: the asyncfatfs read re-issues + * this operation on the next PID loop, which paces the retries for us. */ if (sdcard.operationRetries < SDCARD_MAX_OPERATION_RETRIES) { sdcard.operationRetries++; - // Brief delay before retry - delay(1); return false; } From 2fda3e4d66a1225321e225f164ac3f83ff4f238f Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Tue, 23 Jun 2026 12:41:58 -0500 Subject: [PATCH 18/42] fix(sdcard): fix write-path state management in SDIO driver Move state assignment after confirming DMA operation starts successfully. Previously, sdcard.state was set to SDCARD_STATE_SENDING_WRITE before the SD_WriteBlocks_DMA() call. On DMA rejection and retry, the state remained SENDING_WRITE, causing the next poll cycle to call SD_CheckWrite() on a transfer that never actually started, leading to stale status misinterpretation. This fix mirrors the read-path behavior (sdcardSdio_readBlock) where state is only set after confirming the DMA operation succeeded. This ensures: - Retry mechanism works correctly (state stays READY for next attempt) - Poll cycle sees accurate state - No risk of invoking completion callbacks for failed operations This bug becomes critical after removing blocking delays from retry paths, as retries now happen immediately on the next loop iteration instead of after 1ms, exposing the state inconsistency more frequently. Related: commit 146ff5616c (introduced the retry logic with this bug) --- src/main/drivers/sdcard/sdcard_sdio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/drivers/sdcard/sdcard_sdio.c b/src/main/drivers/sdcard/sdcard_sdio.c index bb8289f9b02..f76377550a7 100644 --- a/src/main/drivers/sdcard/sdcard_sdio.c +++ b/src/main/drivers/sdcard/sdcard_sdio.c @@ -457,7 +457,6 @@ static sdcardOperationStatus_e sdcardSdio_writeBlock(uint32_t blockIndex, uint8_ sdcard.pendingOperation.callback = callback; sdcard.pendingOperation.callbackData = callbackData; sdcard.pendingOperation.chunkIndex = 1; // (for non-DMA transfers) we've sent chunk #0 already - sdcard.state = SDCARD_STATE_SENDING_WRITE; if (SD_WriteBlocks_DMA(blockIndex, (uint32_t*) buffer, 512, block_count) != SD_OK) { /* Our write was rejected! Try a few times before giving up. @@ -481,6 +480,9 @@ static sdcardOperationStatus_e sdcardSdio_writeBlock(uint32_t blockIndex, uint8_ return SDCARD_OPERATION_FAILURE; } + // DMA started successfully - only set state after confirming operation will proceed + sdcard.state = SDCARD_STATE_SENDING_WRITE; + // Success - reset retry counter sdcard.operationRetries = 0; return SDCARD_OPERATION_IN_PROGRESS; From e172f870911a4ac244f89b507fc406ee0850cbb3 Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Tue, 30 Jun 2026 21:03:18 -0500 Subject: [PATCH 19/42] docs(autotune): fix fixed-wing autotune docs to match actual behavior Roll/pitch/yaw rates are described as a fixed ceiling autotune respects; in reality, with the default fw_autotune_rate_adjustment setting, autotune actively rewrites roll_rate/pitch_rate/yaw_rate while flying. The doc also claimed autotune sets P and I gains, which hasn't been true since gain the P/I/D-from-FF formula was removed in 2021. Neither yaw nor the MANUAL-mode no-op were mentioned. Rewrites the pre-flight parameter table and flying instructions to describe what the code actually does: FeedForward is tuned on all three axes, P/I are never touched, rate tuning depends on flight mode and fw_autotune_rate_adjustment, and AUTOTUNE has no effect at all in MANUAL mode. --- docs/Autotune - fixedwing.md | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/docs/Autotune - fixedwing.md b/docs/Autotune - fixedwing.md index 3579e8e58d9..ff9fc11c709 100755 --- a/docs/Autotune - fixedwing.md +++ b/docs/Autotune - fixedwing.md @@ -6,9 +6,14 @@ Getting a good set of roll/pitch/yaw PIFF parameters for your aircraft is essent ## What AUTOTUNE does -The AUTOTUNE mode is a flight mode that acts on top of normal ANGLE/HORIZON/ACRO mode and uses changes in flight attitude input by the pilot to learn the tuning values for roll, pitch and yaw tuning. +AUTOTUNE is a modifier you enable on top of ANGLE, HORIZON or ACRO mode. It has no effect at all while flying in MANUAL mode - you can switch it on, but nothing will be tuned until you leave MANUAL. Where it is active, it uses the aircraft's response to your stick inputs to tune, for roll, pitch and yaw independently: -In general pilot needs to activate AUTOTUNE mode while in the air and then fly the plane for a few minutes. While flying the pilot needs to input as many sharp attitude changes as possible so that the autotune code can learn how the aircraft responds and figure out PIFF gains. +* **FeedForward (FF) gain** - in ANGLE, HORIZON or ACRO, whenever you give it enough hard stick input to learn from +* **Rate** (`roll_rate`/`pitch_rate`/`yaw_rate`) - only while flying in ACRO or HORIZON, and only if `fw_autotune_rate_adjustment` is not set to `FIXED` (see below). Rate is never adjusted while flying in ANGLE mode. + +**AUTOTUNE never adjusts P or I gains, on any axis.** Tune P and I manually, either before or after using AUTOTUNE. This is a change from older INAV versions - if you're used to AUTOTUNE also setting P/I, that's no longer how it works. + +In general the pilot needs to activate AUTOTUNE while in the air and then fly the plane for a few minutes. While flying the pilot needs to input as many sharp attitude changes as possible, on all three axes, so that the autotune code can learn how the aircraft responds. An axis that isn't given hard stick input won't be tuned - it's easy to spend a whole flight on hard rolls and pitches and forget yaw entirely. ## Before flying with AUTOTUNE @@ -16,9 +21,12 @@ Before taking off you need to set up a few parameters for your airplane: parameter | explanation --------- | ----------- -roll_rate | Maximum roll rate limit for your ariplane. Must not exceed physical limit of your plane -pitch_rate | Maximum pitch rate limit for your ariplane. Must not exceed physical limit of your plane -yaw_rate | Maximum yaw rate limit for your ariplane. Must not exceed physical limit of your plane +roll_rate | Starting roll rate for your airplane. Unless you set `fw_autotune_rate_adjustment` to `FIXED` (see below), AUTOTUNE will change this value while you fly - it's a starting point, not a ceiling it respects +pitch_rate | Starting pitch rate for your airplane. Same caveat as `roll_rate` +yaw_rate | Starting yaw rate for your airplane. Same caveat as `roll_rate` +fw_autotune_rate_adjustment | Controls whether/how AUTOTUNE changes `roll_rate`/`pitch_rate`/`yaw_rate` while tuning. `AUTO` (default) raises or lowers rates to match what the plane can achieve. `LIMIT` only ever lowers them, never above what you started with. `FIXED` leaves rates untouched - use this if you want AUTOTUNE to tune FeedForward only +fw_autotune_min_stick | Minimum stick deflection [%] (default 50) before AUTOTUNE starts recording a maneuver as tuning data +fw_autotune_max_rate_deflection | Target servo/mixer deflection [%] (default 90) AUTOTUNE aims for when calculating an achievable rate in `AUTO`/`LIMIT` fw_p_level | Self-leveling strength. Bigger value means sharper response fw_i_level | Self-leveling filtering. Usual value for airplanes is 1-5 Hz max_angle_inclination_rll | Maximum roll angle in [0.1 deg] units @@ -26,7 +34,7 @@ max_angle_inclination_pit | Maximum pitch angle in [0.1 deg] units tpa_breakpoint | Cruise throttle (expected throttle that you would be flying most of the time) tpa_rate | Amount of TPS curve to apply (usually should be in range 50-80 for most airplanes) -For most hobby-sized airplanes roll/pitch rate limits should be in range 70-120 deg/s (7-12 for `roll_rate` and `pitch_rate` values). Small and agile flying wings can reach 180-200 deg/s. +For most hobby-sized airplanes, starting roll/pitch rates in the range 70-120 deg/s (7-12 for `roll_rate` and `pitch_rate` values) work well. Small and agile flying wings can reach 180-200 deg/s. With the default `AUTO` setting, don't worry about getting this exactly right - AUTOTUNE will adjust it based on what your airplane actually does, down to a floor of 40 deg/s on roll/pitch and 10 deg/s on yaw, up to a ceiling of 720 deg/s. Other things to check: @@ -38,15 +46,16 @@ Other things to check: Once you are all setup you can take off normally and switch to AUTOTUNE mode once you have gained altitude. -When you engage AUTOTUNE mode a few things will happen: +When you engage AUTOTUNE a few things will happen: -* The autotune system will immediately setup some default values for your roll, pitch and yaw P and I gains -* The autotune system will monitor requested roll and pitch rates (as determined by your transmitter stick movements). When the demanded roll or pitch rate exceeds certain threshold the autotune system will use the response of the aircraft to learn roll or pitch tuning values -* Every 5 seconds the autotune system will store the snapshot of parameters you have. When you switch out of AUTOTUNE mode the last remembered parameters are restored +* The autotune system will monitor requested roll, pitch and yaw rates (as determined by your transmitter stick movements, once deflection passes `fw_autotune_min_stick`). When the demanded rate on an axis exceeds that threshold the autotune system will use the response of the aircraft to learn FeedForward (and, depending on `fw_autotune_rate_adjustment` and mode, Rate) for that axis +* Every 5 seconds the autotune system will store a snapshot of the current values. When you switch out of AUTOTUNE the last snapshot is restored - so if you exit within 5 seconds of enabling it, nothing changes * You may find the plane is quite sluggish when you first enter AUTOTUNE. You will find that as the tune progresses this will get better. Make sure your flight area has plenty of room for slow large-radius turns. * Don't land in AUTOTUNE mode - during landing airplane doesn't reach it full performance which may be read by autotune system as insufficient gains. -The key to a successful autotune is to input rapid movements with the transmitter sticks. You should only do one of either roll or pitch at a time, and you should move the stick rapidly to the maximum deflection. +The key to a successful autotune is to input rapid movements with the transmitter sticks. You should only exercise one of roll, pitch or yaw at a time, and you should move the stick rapidly to the maximum deflection. Don't neglect yaw - it's easy to spend the whole flight on rolls and pitches and leave yaw untuned. + +Fly in ACRO if you can - AUTOTUNE only learns Rate in modes where stick position maps directly to a commanded rotation rate (ACRO, and mostly HORIZON). In ANGLE mode the stick commands an angle instead, so AUTOTUNE will still tune FeedForward but will not touch Rate at all while you're in ANGLE. AUTOTUNE has no effect whatsoever in MANUAL mode - don't fly it there. ## Don't stop too early From 87ed42bed1c3f3a470cadbae8bfaf1e68577dc49 Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Thu, 2 Jul 2026 11:00:09 -0500 Subject: [PATCH 20/42] Fix build-SITL-Mac VLA-folding-constant error in log.c _logBufferHex() sized a stack buffer using two `const size_t` locals (charsPerByte, maxBytes). In C, const-qualified objects are not integer constant expressions, so the array size expression was technically a variable-length array; recent AppleClang treats reliance on its extension that folds such expressions back to a constant as an error under -Werror -Wgnu-folding-constant, breaking build-SITL-Mac. Replace the const locals with a local enum, whose members are genuine integer constant expressions in C. The buffer size and behavior are unchanged (13 + 5*8 + 1 = 54 bytes either way). --- src/main/common/log.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/common/log.c b/src/main/common/log.c index c2cc30a3a48..d1d9ef1e6b0 100644 --- a/src/main/common/log.c +++ b/src/main/common/log.c @@ -205,8 +205,12 @@ void _logBufferHex(logTopic_e topic, unsigned level, const void *buffer, size_t { // Print lines of up to maxBytes bytes. We need 5 characters per byte // 0xAB[space|\n] - const size_t charsPerByte = 5; - const size_t maxBytes = 8; + // charsPerByte/maxBytes must be true compile-time constants (not `const` + // locals) so the buffer size below is a real constant expression, not a VLA. + enum { + charsPerByte = 5, + maxBytes = 8, + }; char buf[LOG_PREFIX_FORMATTED_SIZE + charsPerByte * maxBytes + 1]; // +1 for the null terminator size_t bufPos = LOG_PREFIX_FORMATTED_SIZE; const uint8_t *inputPtr = buffer; From b757e487121f21f70b18e70fb95b5b4fbecfdb0a Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Thu, 2 Jul 2026 12:18:53 -0500 Subject: [PATCH 21/42] Fix build-SITL-Mac VLA-folding-constant error in osd.c STATIC_ASSERT STATIC_ASSERT expands to a typedef of a char array sized by the condition, a common compile-time-assertion trick. This call site's condition compared GPS_DEGREES_DIVIDER (already 10000000L) against the floating-point literal 1e7. Per C11 6.6p6, integer constant expressions may not contain floating constants, so despite being trivially foldable, AppleClang's -Wgnu-folding-constant -Werror rejects it. Replace 1e7 with 10000000L to match GPS_DEGREES_DIVIDER's own literal form, making the condition a pure integer constant expression. No change to the assertion's truth value or any runtime behavior. --- src/main/io/osd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/io/osd.c b/src/main/io/osd.c index 0bdb9e3375f..aa0a01ce71b 100644 --- a/src/main/io/osd.c +++ b/src/main/io/osd.c @@ -841,7 +841,7 @@ static void osdFormatCoordinate(char *buff, char sym, int32_t val) int integerDigits = tfp_sprintf(buff + 1, (integerPart == 0 && val < 0) ? "-%d" : "%d", (int)integerPart); // We can show up to 7 digits in decimalPart. int32_t decimalPart = abs(val % (int)GPS_DEGREES_DIVIDER); - STATIC_ASSERT(GPS_DEGREES_DIVIDER == 1e7, adjust_max_decimal_digits); + STATIC_ASSERT(GPS_DEGREES_DIVIDER == 10000000L, adjust_max_decimal_digits); int decimalDigits; bool djiCompat = false; // Assume DJICOMPAT mode is no enabled From f3527febd2a7c633df22c3b7937e46b26af73c07 Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Thu, 2 Jul 2026 13:10:45 -0500 Subject: [PATCH 22/42] docs(autotune): fix LIMIT mode wording per Qodo review LIMIT caps rates at the starting value but isn't strictly monotonic downward - it can raise a previously-lowered rate back up toward that ceiling. --- docs/Autotune - fixedwing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Autotune - fixedwing.md b/docs/Autotune - fixedwing.md index ff9fc11c709..75391ccc8ed 100755 --- a/docs/Autotune - fixedwing.md +++ b/docs/Autotune - fixedwing.md @@ -24,7 +24,7 @@ parameter | explanation roll_rate | Starting roll rate for your airplane. Unless you set `fw_autotune_rate_adjustment` to `FIXED` (see below), AUTOTUNE will change this value while you fly - it's a starting point, not a ceiling it respects pitch_rate | Starting pitch rate for your airplane. Same caveat as `roll_rate` yaw_rate | Starting yaw rate for your airplane. Same caveat as `roll_rate` -fw_autotune_rate_adjustment | Controls whether/how AUTOTUNE changes `roll_rate`/`pitch_rate`/`yaw_rate` while tuning. `AUTO` (default) raises or lowers rates to match what the plane can achieve. `LIMIT` only ever lowers them, never above what you started with. `FIXED` leaves rates untouched - use this if you want AUTOTUNE to tune FeedForward only +fw_autotune_rate_adjustment | Controls whether/how AUTOTUNE changes `roll_rate`/`pitch_rate`/`yaw_rate` while tuning. `AUTO` (default) raises or lowers rates to match what the plane can achieve. `LIMIT` adjusts rates the same way but caps them at your starting value - it can still raise a rate it previously lowered, just never above where you started. `FIXED` leaves rates untouched - use this if you want AUTOTUNE to tune FeedForward only fw_autotune_min_stick | Minimum stick deflection [%] (default 50) before AUTOTUNE starts recording a maneuver as tuning data fw_autotune_max_rate_deflection | Target servo/mixer deflection [%] (default 90) AUTOTUNE aims for when calculating an achievable rate in `AUTO`/`LIMIT` fw_p_level | Self-leveling strength. Bigger value means sharper response From 1ffa80b3dd08cb62e5d1061c6e41ccdb88e74e02 Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Thu, 2 Jul 2026 17:15:53 -0500 Subject: [PATCH 23/42] Fix int8_t overflow in AAF frequency selection for ICM-42688P/42686P selectedFreq in getGyroAafConfig() was declared int8_t (max 127), but aafLUT42688[] contains freq values up to 1962. Values above 127 silently truncated on assignment, corrupting the closest-frequency comparison and causing the wrong AAF register configuration to be selected. This affected every board using this gyro at the default 256Hz LPF setting (selected 303Hz instead of the correct 258Hz cutoff). Changed to uint16_t to match aafConfig_t.freq's own type. --- src/main/drivers/accgyro/accgyro_icm42605.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/drivers/accgyro/accgyro_icm42605.c b/src/main/drivers/accgyro/accgyro_icm42605.c index b4f573a06c0..b6cd029f9e2 100644 --- a/src/main/drivers/accgyro/accgyro_icm42605.c +++ b/src/main/drivers/accgyro/accgyro_icm42605.c @@ -422,7 +422,7 @@ static const aafConfig_t *getGyroAafConfig(icm42605Variant_e variant, const uint aafConfigs = aafLUT42605; } int i; - int8_t selectedFreq = aafConfigs[0].freq; + uint16_t selectedFreq = aafConfigs[0].freq; const aafConfig_t * candidate = &aafConfigs[0]; // Choose closest supported LPF value From cf48e6e129443d6c4fab31e5358c0bb9eb9ff28f Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Sun, 5 Jul 2026 19:29:01 -0500 Subject: [PATCH 24/42] allow USE_UARTx_PIN_SWAP on H7 --- src/main/drivers/serial_uart_hal.c | 6 +++ src/main/drivers/serial_uart_stm32h7xx.c | 49 ++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/src/main/drivers/serial_uart_hal.c b/src/main/drivers/serial_uart_hal.c index f25b2cbafb6..659fbf3c0d3 100644 --- a/src/main/drivers/serial_uart_hal.c +++ b/src/main/drivers/serial_uart_hal.c @@ -61,6 +61,11 @@ static void usartConfigurePinInversion(uartPort_t *uartPort) { #endif } +__attribute__((weak)) void uartConfigurePinSwap(uartPort_t *uartPort) +{ + UNUSED(uartPort); +} + static void uartReconfigure(uartPort_t *uartPort) { /*RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit; @@ -92,6 +97,7 @@ static void uartReconfigure(uartPort_t *uartPort) usartConfigurePinInversion(uartPort); + uartConfigurePinSwap(uartPort); if (uartPort->port.options & SERIAL_BIDIR) { diff --git a/src/main/drivers/serial_uart_stm32h7xx.c b/src/main/drivers/serial_uart_stm32h7xx.c index 9debfe66c72..f606638651d 100644 --- a/src/main/drivers/serial_uart_stm32h7xx.c +++ b/src/main/drivers/serial_uart_stm32h7xx.c @@ -43,6 +43,7 @@ typedef struct uartDevice_s { uint8_t af_rx; uint8_t af_tx; uint8_t irq; + bool pinSwap; } uartDevice_t; #define UART_PIN_AF_HELPER(uart, pin) CONCAT4(UART_PIN_AF_UART, uart, _, pin) @@ -64,6 +65,9 @@ static uartDevice_t uart1 = .af_tx = UART_PIN_AF_HELPER(1, UART1_TX_PIN), .rcc = RCC_APB2(USART1), .irq = USART1_IRQn, +#ifdef USE_UART1_PIN_SWAP + .pinSwap = true, +#endif }; #endif @@ -77,6 +81,9 @@ static uartDevice_t uart2 = .af_tx = GPIO_AF7_USART2, .rcc = RCC_APB1L(USART2), .irq = USART2_IRQn, +#ifdef USE_UART2_PIN_SWAP + .pinSwap = true, +#endif }; #endif @@ -90,6 +97,9 @@ static uartDevice_t uart3 = .af_tx = GPIO_AF7_USART3, .rcc = RCC_APB1L(USART3), .irq = USART3_IRQn, +#ifdef USE_UART3_PIN_SWAP + .pinSwap = true, +#endif }; #endif @@ -114,6 +124,9 @@ static uartDevice_t uart4 = .af_tx = UART_PIN_AF_HELPER(4, UART4_TX_PIN), .rcc = RCC_APB1L(UART4), .irq = UART4_IRQn, +#ifdef USE_UART4_PIN_SWAP + .pinSwap = true, +#endif }; #endif @@ -134,6 +147,9 @@ static uartDevice_t uart5 = .af_tx = UART_PIN_AF_HELPER(5, UART5_TX_PIN), .rcc = RCC_APB1L(UART5), .irq = UART5_IRQn, +#ifdef USE_UART5_PIN_SWAP + .pinSwap = true, +#endif }; #endif @@ -147,6 +163,9 @@ static uartDevice_t uart6 = .af_tx = GPIO_AF7_USART6, .rcc = RCC_APB2(USART6), .irq = USART6_IRQn, +#ifdef USE_UART6_PIN_SWAP + .pinSwap = true, +#endif }; #endif @@ -173,6 +192,9 @@ static uartDevice_t uart7 = #endif .rcc = RCC_APB1L(UART7), .irq = UART7_IRQn, +#ifdef USE_UART7_PIN_SWAP + .pinSwap = true, +#endif }; #endif @@ -186,6 +208,9 @@ static uartDevice_t uart8 = .af_tx = GPIO_AF8_UART8, .rcc = RCC_APB1L(UART8), .irq = UART8_IRQn, +#ifdef USE_UART8_PIN_SWAP + .pinSwap = true, +#endif }; #endif @@ -234,6 +259,30 @@ static uartDevice_t* uartHardwareMap[] = { #endif }; +static uartDevice_t *uartFindDevice(uartPort_t *uartPort) +{ + for (unsigned i = 0; i < UARTDEV_MAX; i++) { + uartDevice_t *pDevice = uartHardwareMap[i]; + if (pDevice && pDevice->dev == uartPort->USARTx) { + return pDevice; + } + } + return NULL; +} + +void uartConfigurePinSwap(uartPort_t *uartPort) +{ + uartDevice_t *uartDevice = uartFindDevice(uartPort); + if (!uartDevice) { + return; + } + + if (uartDevice->pinSwap) { + uartPort->Handle.AdvancedInit.AdvFeatureInit |= UART_ADVFEATURE_SWAP_INIT; + uartPort->Handle.AdvancedInit.Swap = UART_ADVFEATURE_SWAP_ENABLE; + } +} + void uartGetPortPins(UARTDevice_e device, serialPortPins_t * pins) { uartDevice_t *uart = uartHardwareMap[device]; From 028986cc41d1a418b3391731077f1719ab75d76e Mon Sep 17 00:00:00 2001 From: Sensei Date: Sun, 5 Jul 2026 19:40:01 -0500 Subject: [PATCH 25/42] DAKEFPVH743_SLIM: Fix DMA conflicts Updated timerHardware configuration to avoid DMA conflicts. --- src/main/target/DAKEFPVH743_SLIM/target.c | 27 ++++++++++++----------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/main/target/DAKEFPVH743_SLIM/target.c b/src/main/target/DAKEFPVH743_SLIM/target.c index 6bf84f5ee19..b85049fa483 100644 --- a/src/main/target/DAKEFPVH743_SLIM/target.c +++ b/src/main/target/DAKEFPVH743_SLIM/target.c @@ -41,21 +41,22 @@ BUSDEV_REGISTER_SPI_TAG(busdev_2_ICM42605, DEVHW_ICM42605, IMU_2_SPI_BUS, IMU_ BUSDEV_REGISTER_SPI_TAG(busdev_2_BMI270, DEVHW_BMI270, IMU_2_SPI_BUS, IMU_2_CS_PIN, IMU_2_IRQ_PIN, 1, DEVFLAGS_NONE, IMU_2_ALIGN); timerHardware_t timerHardware[] = { - DEF_TIM(TIM1, CH1, PE9, TIM_USE_OUTPUT_AUTO, 0, 0), // M1 - DEF_TIM(TIM1, CH2, PE11, TIM_USE_OUTPUT_AUTO, 0, 1), // M2 - DEF_TIM(TIM1, CH3, PE13, TIM_USE_OUTPUT_AUTO, 0, 2), // M3 - DEF_TIM(TIM1, CH4, PE14, TIM_USE_OUTPUT_AUTO, 0, 3), // M4 - DEF_TIM(TIM2, CH1, PA0, TIM_USE_OUTPUT_AUTO, 0, 4), // M5 - DEF_TIM(TIM2, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 5), // M6 - DEF_TIM(TIM2, CH3, PA2, TIM_USE_OUTPUT_AUTO, 0, 6), // M7 - DEF_TIM(TIM2, CH4, PA3, TIM_USE_OUTPUT_AUTO, 0, 7), // M8 DMA None - DEF_TIM(TIM4, CH1, PD12, TIM_USE_OUTPUT_AUTO, 0, 0), // S1 - DEF_TIM(TIM4, CH2, PD13, TIM_USE_OUTPUT_AUTO, 0, 0), // S2 DMA None - DEF_TIM(TIM4, CH3, PD14, TIM_USE_OUTPUT_AUTO, 0, 0), // S3 - DEF_TIM(TIM4, CH4, PD15, TIM_USE_OUTPUT_AUTO, 0, 0), // S4 + DEF_TIM(TIM1, CH1, PE9, TIM_USE_OUTPUT_AUTO, 0, 0), // S1 + DEF_TIM(TIM1, CH2, PE11, TIM_USE_OUTPUT_AUTO, 0, 1), // S2 + DEF_TIM(TIM1, CH3, PE13, TIM_USE_OUTPUT_AUTO, 0, 2), // S3 + DEF_TIM(TIM1, CH4, PE14, TIM_USE_OUTPUT_AUTO, 0, 3), // S4 + DEF_TIM(TIM2, CH1, PA0, TIM_USE_OUTPUT_AUTO, 0, 4), // S5 + DEF_TIM(TIM2, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 5), // S6 + DEF_TIM(TIM2, CH3, PA2, TIM_USE_OUTPUT_AUTO, 0, 6), // S7 + DEF_TIM(TIM2, CH4, PA3, TIM_USE_OUTPUT_AUTO, 0, 7), // S8 DMA None + DEF_TIM(TIM4, CH1, PD12, TIM_USE_OUTPUT_AUTO, 0, 11), // S9 - unique DMA opt, was 0 (collided with TIM1 CH1 S1 on DMA1 Stream0) + DEF_TIM(TIM4, CH2, PD13, TIM_USE_OUTPUT_AUTO, 0, 12), // S10 + DEF_TIM(TIM4, CH3, PD14, TIM_USE_OUTPUT_AUTO, 0, 13), // S11 + DEF_TIM(TIM4, CH4, PD15, TIM_USE_OUTPUT_AUTO, 0, 14), // S12 + DEF_TIM(TIM8, CH3, PC8, TIM_USE_ANY, 0, 0), // CAMERA_CONTROL_PIN DEF_TIM(TIM17, CH1N,PB7, TIM_USE_ANY, 0, 0), // GYRO_1_CLKIN_PIN - DEF_TIM(TIM3, CH3, PB0, TIM_USE_LED, 0, 8), // LED_2812 + DEF_TIM(TIM3, CH3, PB0, TIM_USE_LED, 0, 9), // LED_2812 - moved off DMA2 Stream0 to avoid ADC1 DMA conflict }; const int timerHardwareCount = sizeof(timerHardware) / sizeof(timerHardware[0]); From e6f3353074897b7b9058b9ae1bba57f97d5f7bbf Mon Sep 17 00:00:00 2001 From: Sensei Date: Sun, 5 Jul 2026 19:41:03 -0500 Subject: [PATCH 26/42] DAKEFPV H743 SLIM: Fix beeper and UART7 --- src/main/target/DAKEFPVH743_SLIM/target.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/target/DAKEFPVH743_SLIM/target.h b/src/main/target/DAKEFPVH743_SLIM/target.h index 0d74f9ab9fd..f4c324f60ec 100644 --- a/src/main/target/DAKEFPVH743_SLIM/target.h +++ b/src/main/target/DAKEFPVH743_SLIM/target.h @@ -24,7 +24,7 @@ #define LED1 PD11 #define LED2 PA8 -#define BEEPER_PIN PE10 +#define BEEPER PE10 #define BEEPER_INVERTED #define USE_DSHOT_DMAR // Buses @@ -124,6 +124,8 @@ #define UART5_RX_PIN PB5 #define UART6_TX_PIN PC6 #define UART6_RX_PIN PC7 + +#define USE_UART7_PIN_SWAP #define UART7_TX_PIN PE8 #define UART7_RX_PIN PE7 #define UART8_TX_PIN PE1 From 08cde848a7e30aebc2925d86ea2a267cc1173ece Mon Sep 17 00:00:00 2001 From: Valerii Chebanov Date: Thu, 5 Mar 2026 20:41:18 +0200 Subject: [PATCH 27/42] Puya PY25Q128 - updated descriptions. --- src/main/drivers/flash_m25p16.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/drivers/flash_m25p16.c b/src/main/drivers/flash_m25p16.c index c6d5543e448..fdcdaad4826 100644 --- a/src/main/drivers/flash_m25p16.c +++ b/src/main/drivers/flash_m25p16.c @@ -99,9 +99,10 @@ struct { // Winbond W25Q128_DTR // Datasheet: https://www.winbond.com/resource-files/w25q128jv%20dtr%20revb%2011042016.pdf {0xEF7018, 256, 256}, - // Puya PY25Q128HA + // Puya PY25Q128 // Datasheet: https://www.puyasemi.com/cpzx3/info_271_itemid_87.html - {0x856018, 256, 256}, + {0x856018, 256, 256}, // PY25Q128H + {0x852018, 256, 256}, // PY25Q128HA // Winbond W25Q256 // Datasheet: https://www.winbond.com/resource-files/w25q256jv%20spi%20revb%2009202016.pdf {0xEF4019, 512, 256}, From 42f7e52482361d25193d15cc96695fcfa2830d16 Mon Sep 17 00:00:00 2001 From: Valerii Chebanov Date: Mon, 2 Mar 2026 20:51:19 +0200 Subject: [PATCH 28/42] SOLOGOODF722 - target --- src/main/target/SOLOGOODF722/CMakeLists.txt | 1 + src/main/target/SOLOGOODF722/target.c | 40 +++++ src/main/target/SOLOGOODF722/target.h | 170 ++++++++++++++++++++ 3 files changed, 211 insertions(+) create mode 100644 src/main/target/SOLOGOODF722/CMakeLists.txt create mode 100644 src/main/target/SOLOGOODF722/target.c create mode 100644 src/main/target/SOLOGOODF722/target.h diff --git a/src/main/target/SOLOGOODF722/CMakeLists.txt b/src/main/target/SOLOGOODF722/CMakeLists.txt new file mode 100644 index 00000000000..59ea48d13d5 --- /dev/null +++ b/src/main/target/SOLOGOODF722/CMakeLists.txt @@ -0,0 +1 @@ +target_stm32f722xe(SOLOGOODF722) diff --git a/src/main/target/SOLOGOODF722/target.c b/src/main/target/SOLOGOODF722/target.c new file mode 100644 index 00000000000..12b14c16b80 --- /dev/null +++ b/src/main/target/SOLOGOODF722/target.c @@ -0,0 +1,40 @@ +/* + * This file is part of INAV. + * + * INAV is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * INAV is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with INAV. If not, see . + */ + +#include + +#include "platform.h" +#include "drivers/io.h" + +#include "drivers/dma.h" +#include "drivers/timer.h" +#include "drivers/timer_def.h" + +timerHardware_t timerHardware[] = { + DEF_TIM(TIM8, CH3, PC8, TIM_USE_OUTPUT_AUTO, 0, 0), // S1 + DEF_TIM(TIM8, CH4, PC9, TIM_USE_OUTPUT_AUTO, 0, 0), // S2 + DEF_TIM(TIM1, CH1, PA8, TIM_USE_OUTPUT_AUTO, 0, 1), // S3 + DEF_TIM(TIM1, CH2, PA9, TIM_USE_OUTPUT_AUTO, 0, 1), // S4 + DEF_TIM(TIM3, CH3, PB0, TIM_USE_OUTPUT_AUTO, 0, 0), // S5 + DEF_TIM(TIM3, CH4, PB1, TIM_USE_OUTPUT_AUTO, 0, 0), // S6 + DEF_TIM(TIM1, CH3, PA10, TIM_USE_OUTPUT_AUTO, 0, 1), // S7 + DEF_TIM(TIM3, CH1, PB4, TIM_USE_OUTPUT_AUTO, 0, 0), // S8 + + DEF_TIM(TIM2, CH2, PB3, TIM_USE_LED, 0, 0), // 2812LED +}; + +const int timerHardwareCount = sizeof(timerHardware) / sizeof(timerHardware[0]); diff --git a/src/main/target/SOLOGOODF722/target.h b/src/main/target/SOLOGOODF722/target.h new file mode 100644 index 00000000000..dd017691ef3 --- /dev/null +++ b/src/main/target/SOLOGOODF722/target.h @@ -0,0 +1,170 @@ +/* + * This file is part of INAV Project. + * + * INAV is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * INAV is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with INAV. If not, see . + */ + +#pragma once + +#define TARGET_BOARD_IDENTIFIER "SGF7" + +#define USBD_PRODUCT_STRING "SOLOGOODF722" + +#define LED0 PC15 + +#define BEEPER PC13 +#define BEEPER_INVERTED + +// *************** Gyro & ACC ********************** +#define USE_SPI +#define USE_SPI_DEVICE_1 + +#define SPI1_NSS_PIN PA4 +#define SPI1_SCK_PIN PA5 +#define SPI1_MISO_PIN PA6 +#define SPI1_MOSI_PIN PA7 + + +#define USE_IMU_MPU6000 +#define IMU_MPU6000_ALIGN CW180_DEG +#define MPU6000_CS_PIN SPI1_NSS_PIN +#define MPU6000_SPI_BUS BUS_SPI1 + +#define USE_IMU_BMI270 +#define IMU_BMI270_ALIGN CW180_DEG +#define BMI270_CS_PIN SPI1_NSS_PIN +#define BMI270_SPI_BUS BUS_SPI1 + +#define USE_IMU_ICM42605 +#define IMU_ICM42605_ALIGN CW180_DEG +#define ICM42605_CS_PIN SPI1_NSS_PIN +#define ICM42605_SPI_BUS BUS_SPI1 + +// *************** I2C/Baro/Mag ********************* +#define USE_I2C +#define USE_I2C_DEVICE_1 +#define I2C1_SCL PB8 +#define I2C1_SDA PB9 + +#define DEFAULT_I2C_BUS BUS_I2C1 + +#define USE_BARO +#define BARO_I2C_BUS DEFAULT_I2C_BUS +#define USE_BARO_DPS310 + +#define USE_MAG +#define MAG_I2C_BUS DEFAULT_I2C_BUS +#define USE_MAG_ALL + +#define TEMPERATURE_I2C_BUS DEFAULT_I2C_BUS + +#define PITOT_I2C_BUS DEFAULT_I2C_BUS + +#define USE_RANGEFINDER +#define RANGEFINDER_I2C_BUS DEFAULT_I2C_BUS + +// *************** FLASH ************************** +#define USE_SPI_DEVICE_3 +#define SPI3_NSS_PIN PA15 +#define SPI3_SCK_PIN PC10 +#define SPI3_MISO_PIN PC11 +#define SPI3_MOSI_PIN PB5 + +#define M25P16_CS_PIN SPI3_NSS_PIN +#define M25P16_SPI_BUS BUS_SPI3 +#define USE_FLASHFS +#define USE_FLASH_M25P16 +#define ENABLE_BLACKBOX_LOGGING_ON_SPIFLASH_BY_DEFAULT + + +// *************** OSD ***************************** +#define USE_SPI_DEVICE_2 +#define SPI2_NSS_PIN PB12 +#define SPI2_SCK_PIN PB13 +#define SPI2_MISO_PIN PB14 +#define SPI2_MOSI_PIN PB15 + +#define USE_MAX7456 +#define MAX7456_SPI_BUS BUS_SPI2 +#define MAX7456_CS_PIN SPI2_NSS_PIN + +// *************** UART ***************************** +#define USE_VCP + +#define USE_UART1 +#define UART1_RX_PIN PB7 +#define UART1_TX_PIN PB6 + +#define USE_UART2 +#define UART2_RX_PIN PA3 +#define UART2_TX_PIN PA2 + +#define USE_UART3 +#define UART3_RX_PIN PB11 +#define UART3_TX_PIN PB10 + +#define USE_UART4 +#define UART4_RX_PIN PA1 +#define UART4_TX_PIN PA0 + +#define USE_UART5 +#define UART5_RX_PIN PD2 +#define UART5_TX_PIN PC12 + +#define USE_UART6 +#define UART6_RX_PIN PC7 +#define UART6_TX_PIN PC6 + +#define SERIAL_PORT_COUNT 7 + +#define DEFAULT_RX_TYPE RX_TYPE_SERIAL +#define SERIALRX_PROVIDER SERIALRX_CRSF +#define SERIALRX_UART SERIAL_PORT_USART2 + +// *************** ADC ***************************** +#define USE_ADC +#define ADC_INSTANCE ADC1 +#define ADC1_DMA_STREAM DMA2_Stream0 +#define ADC_CHANNEL_1_PIN PC1 +#define ADC_CHANNEL_2_PIN PC3 + +#define VBAT_ADC_CHANNEL ADC_CHN_1 +#define CURRENT_METER_ADC_CHANNEL ADC_CHN_2 + + +#define DEFAULT_FEATURES (FEATURE_TX_PROF_SEL | FEATURE_CURRENT_METER | FEATURE_TELEMETRY | FEATURE_VBAT | FEATURE_OSD | FEATURE_BLACKBOX) +// *************** PINIO ************************ +#define USE_PINIO +#define USE_PINIOBOX +#define PINIO1_PIN PC2 +#define PINIO2_PIN PC0 + +// *************** LEDSTRIP ************************ +#define USE_LED_STRIP +#define WS2811_PIN PB3 + +// Others + +#define USE_SERIAL_4WAY_BLHELI_INTERFACE +#define CURRENT_METER_SCALE 250 + +#define TARGET_IO_PORTA 0xffff +#define TARGET_IO_PORTB 0xffff +#define TARGET_IO_PORTC 0xffff +#define TARGET_IO_PORTD (BIT(2)) + +#define MAX_PWM_OUTPUT_PORTS 8 + +#define USE_DSHOT +#define USE_ESC_SENSOR From 2197875e654270e58743fd80e052685f1c03cac6 Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 6 Jul 2026 10:45:11 -0500 Subject: [PATCH 29/42] SOLOGOODF722: add config.c for PINIO user boxes Sets the target's two PINIO pins as user-assignable boxes (BOX_PERMANENT_ID_USER1/2) via targetConfiguration(), per review request on upstream PR #11394. --- src/main/target/SOLOGOODF722/config.c | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/main/target/SOLOGOODF722/config.c diff --git a/src/main/target/SOLOGOODF722/config.c b/src/main/target/SOLOGOODF722/config.c new file mode 100644 index 00000000000..79a0eb18472 --- /dev/null +++ b/src/main/target/SOLOGOODF722/config.c @@ -0,0 +1,28 @@ +/* + * This file is part of INAV. + * + * INAV is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * INAV is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with INAV. If not, see . + */ + +#include +#include "platform.h" +#include "fc/fc_msp_box.h" +#include "fc/config.h" +#include "io/piniobox.h" + +void targetConfiguration(void) +{ + pinioBoxConfigMutable()->permanentId[0] = BOX_PERMANENT_ID_USER1; + pinioBoxConfigMutable()->permanentId[1] = BOX_PERMANENT_ID_USER2; +} From 7441bec78c1968ada3bddfe9797b39a2ea2f01e6 Mon Sep 17 00:00:00 2001 From: Sensei Date: Mon, 6 Jul 2026 11:41:25 -0500 Subject: [PATCH 30/42] AETH743Basic Update BMI270 slow tag in target.c --- src/main/target/AETH743Basic/target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/target/AETH743Basic/target.c b/src/main/target/AETH743Basic/target.c index 90049806c76..75265190bdb 100644 --- a/src/main/target/AETH743Basic/target.c +++ b/src/main/target/AETH743Basic/target.c @@ -33,7 +33,7 @@ BUSDEV_REGISTER_SPI_TAG(busdev_icm42688_1, DEVHW_ICM42605, ICM42688_1_SPI_BUS, I // V2:BMI088 + BMI270 BUSDEV_REGISTER_SPI_TAG(busdev_bmi088_gyro, DEVHW_BMI088_GYRO, BMI088_SPI_BUS, BMI088_GYRO_CS_PIN, BMI088_GYRO_EXTI_PIN, 0, DEVFLAGS_NONE, IMU_BMI088_ALIGN); BUSDEV_REGISTER_SPI_TAG(busdev_bmi088_acc, DEVHW_BMI088_ACC, BMI088_SPI_BUS, BMI088_ACC_CS_PIN, BMI088_ACC_EXTI_PIN, 0, DEVFLAGS_NONE, IMU_BMI088_ALIGN); -BUSDEV_REGISTER_SPI_TAG(busdev_bmi270, DEVHW_BMI270, BMI270_SPI_BUS, BMI270_CS_PIN, NONE, 3, DEVFLAGS_NONE, IMU_BMI270_ALIGN); +BUSDEV_REGISTER_SPI_TAG(busdev_bmi270, DEVHW_BMI270, BMI270_SPI_BUS, BMI270_CS_PIN, NONE, 2, DEVFLAGS_NONE, IMU_BMI270_ALIGN); timerHardware_t timerHardware[] = { DEF_TIM(TIM3, CH3, PB0, TIM_USE_OUTPUT_AUTO, 0, 0), // S1 From db7e4658bba835166ca080b4e9e4d2a628ba04ab Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 6 Jul 2026 12:29:47 -0500 Subject: [PATCH 31/42] Update DAKEFPVF405 target to match current Betaflight config Add PINIO2 (PB4), CAMERA_CONTROL_PIN (PA8), and ICM42688P IMU support on the existing SPI1/PA4 gyro bus, matching the current upstream Betaflight unified-target config for this board. --- src/main/target/DAKEFPVF405/config.c | 1 + src/main/target/DAKEFPVF405/target.h | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/target/DAKEFPVF405/config.c b/src/main/target/DAKEFPVF405/config.c index 73f636cf8c0..906089d3b38 100644 --- a/src/main/target/DAKEFPVF405/config.c +++ b/src/main/target/DAKEFPVF405/config.c @@ -28,4 +28,5 @@ void targetConfiguration(void) { pinioBoxConfigMutable()->permanentId[0] = BOX_PERMANENT_ID_USER1; + pinioBoxConfigMutable()->permanentId[1] = BOX_PERMANENT_ID_USER2; } diff --git a/src/main/target/DAKEFPVF405/target.h b/src/main/target/DAKEFPVF405/target.h index 9b1aef0721a..a8df84e635d 100644 --- a/src/main/target/DAKEFPVF405/target.h +++ b/src/main/target/DAKEFPVF405/target.h @@ -72,6 +72,11 @@ #define BMI270_SPI_BUS BUS_SPI1 #define BMI270_CS_PIN PA4 +#define USE_IMU_ICM42688P +#define IMU_ICM42688P_ALIGN CW90_DEG +#define ICM42688P_CS_PIN PA4 +#define ICM42688P_SPI_BUS BUS_SPI1 + //Baro #define USE_BARO #define USE_BARO_BMP280 @@ -95,6 +100,9 @@ #define MAX7456_SPI_BUS BUS_SPI2 #define MAX7456_CS_PIN PB12 +// CAMERA_CONTROL +#define CAMERA_CONTROL_PIN PA8 + // Serial ports #define USE_VCP @@ -170,4 +178,6 @@ #define USE_PINIO #define USE_PINIOBOX #define PINIO1_PIN PC5 -#define PINIO1_FLAGS PINIO_FLAGS_INVERTED \ No newline at end of file +#define PINIO1_FLAGS PINIO_FLAGS_INVERTED +#define PINIO2_PIN PB4 +#define PINIO2_FLAGS PINIO_FLAGS_INVERTED \ No newline at end of file From 37dc6fe15cd0ef4970ecde520bfdc192a379b2c7 Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 6 Jul 2026 12:30:37 -0500 Subject: [PATCH 32/42] Note CAMERA_CONTROL_PIN as a future PWM-PINIO migration candidate Flags this pin for the planned 10.0 flexible PWM-capable PINIO feature, since CAMERA_CONTROL_PIN has no consuming driver in INAV today. --- src/main/target/DAKEFPVF405/target.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/target/DAKEFPVF405/target.h b/src/main/target/DAKEFPVF405/target.h index a8df84e635d..ed703e32d7d 100644 --- a/src/main/target/DAKEFPVF405/target.h +++ b/src/main/target/DAKEFPVF405/target.h @@ -101,6 +101,8 @@ #define MAX7456_CS_PIN PB12 // CAMERA_CONTROL +// PA8 is currently inert (no INAV driver consumes CAMERA_CONTROL_PIN yet). Candidate for +// migration to a PWM-capable PINIO once that lands in 10.0. #define CAMERA_CONTROL_PIN PA8 // Serial ports From 0631b6edc2ebac1deed8fe86cad33b7800bd5ddc Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 6 Jul 2026 12:33:17 -0500 Subject: [PATCH 33/42] Clarify CAMERA_CONTROL_PIN comment: functional from 10.0, not permanently inert 10.0's planned PWM-capable PINIO feature will give this pin real function; reword the comment so it doesn't read as a permanent dead end. --- src/main/target/DAKEFPVF405/target.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/target/DAKEFPVF405/target.h b/src/main/target/DAKEFPVF405/target.h index ed703e32d7d..6495bba7610 100644 --- a/src/main/target/DAKEFPVF405/target.h +++ b/src/main/target/DAKEFPVF405/target.h @@ -101,8 +101,8 @@ #define MAX7456_CS_PIN PB12 // CAMERA_CONTROL -// PA8 is currently inert (no INAV driver consumes CAMERA_CONTROL_PIN yet). Candidate for -// migration to a PWM-capable PINIO once that lands in 10.0. +// PA8 has no consuming driver prior to 10.0. From 10.0 forward this will be set up as a +// PWM-capable PINIO pin instead -- see the October 2026 migration project. #define CAMERA_CONTROL_PIN PA8 // Serial ports From a7aff3b58c12b850fbe68d79dfdb9c9c69ff0cd1 Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 6 Jul 2026 12:46:15 -0500 Subject: [PATCH 34/42] Remove dead USE_IMU_ICM42688P block, document actual detection path USE_IMU_ICM42688P has no registration path anywhere in the tree -- ICM42605, ICM42686P, and ICM42688P share one driver gated only by USE_IMU_ICM42605, whose WHO_AM_I switch already covers all three. The block added no behavior; replace it with a comment so a future reader doesn't mistake it for what enables ICM42688P support here. --- src/main/target/DAKEFPVF405/target.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/target/DAKEFPVF405/target.h b/src/main/target/DAKEFPVF405/target.h index 6495bba7610..0f626365369 100644 --- a/src/main/target/DAKEFPVF405/target.h +++ b/src/main/target/DAKEFPVF405/target.h @@ -72,12 +72,9 @@ #define BMI270_SPI_BUS BUS_SPI1 #define BMI270_CS_PIN PA4 -#define USE_IMU_ICM42688P -#define IMU_ICM42688P_ALIGN CW90_DEG -#define ICM42688P_CS_PIN PA4 -#define ICM42688P_SPI_BUS BUS_SPI1 +// ICM42688P driver handled by USE_IMU_ICM42605 above (shares WHO_AM_I detection) -//Baro +//Baro #define USE_BARO #define USE_BARO_BMP280 #define BMP280_SPI_BUS BUS_SPI2 From 48327843df76f007d50ce917b8436f25f95c66ae Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 6 Jul 2026 13:44:10 -0500 Subject: [PATCH 35/42] Fix bf2inav.py gaps found while updating DAKEFPVF405 - Actually write pinioBoxConfigMutable()->permanentId[n] lines in generated config.c; they previously existed only as commented-out Python source and never reached the file, so every generated target had an empty targetConfiguration() regardless of how many PINIO pins it defined. - Cap the PINIO loop at PINIO_COUNT (4) in both target.h and config.c generation -- the target.h loop previously went up to PINIO8 with no way to ever wire those beyond what firmware supports. - Generate CAMERA_CONTROL_PIN when present in the source config, with a comment noting it has no consuming driver prior to INAV 10.0's planned PWM-capable PINIO feature. - Warn on stderr when a Betaflight source lists a known-unsupported gyro chip (LSM6DSV16X, LSM6DSK320X) instead of silently omitting it. --- .../Converting Betaflight Targets.md | 2 ++ src/utils/bf2inav.py | 29 +++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/docs/development/Converting Betaflight Targets.md b/docs/development/Converting Betaflight Targets.md index 47f460f634d..be734ef67b7 100644 --- a/docs/development/Converting Betaflight Targets.md +++ b/docs/development/Converting Betaflight Targets.md @@ -5,6 +5,8 @@ Locate your Flight Controller target config.h in BetaFlight's repo, eg.: [config It is also advisable to record the output of the timer command from BetaFlight, as it will provide useful information on `timer` usage that can be used to adjust the generated target later. +The script generates `CAMERA_CONTROL_PIN` and PINIO `permanentId` wiring in `config.c` automatically when present in the source `config.h`. If the source config lists a gyro chip INAV has no driver for yet, the script prints a warning instead of silently omitting it -- check the script's console output after running it. + ``` # timer timer B08 AF3 diff --git a/src/utils/bf2inav.py b/src/utils/bf2inav.py index 5ccbb6b4ad6..f7750a7275d 100755 --- a/src/utils/bf2inav.py +++ b/src/utils/bf2inav.py @@ -427,6 +427,13 @@ def writeTargetH(folder, map): file.write("#define %s_SPI_BUS BUS_%s\n" % (supportedgyro, map['defines']['GYRO_1_SPI_INSTANCE'])) file.write("#define IMU_%s_ALIGN %s\n" % (supportedgyro, getGyroAlign(map))) + # Chips Betaflight supports that INAV has no driver for yet -- warn rather than + # silently drop, so whoever runs this doesn't ship a target missing a gyro option. + for unsupportedgyro in ['LSM6DSV16X', 'LSM6DSK320X']: + for var in ['USE_ACCGYRO_', 'USE_ACC_', 'USE_ACC_SPI', 'USE_GYRO_', 'USE_GYRO_SPI_']: + if (var + unsupportedgyro) in map['empty_defines']: + print("WARNING: Betaflight config lists %s, but INAV has no driver for it yet. Not added to target.h -- flag this as a separate driver project." % (unsupportedgyro), file=sys.stderr) + break if 'USE_BARO' in map['empty_defines']: #print ("BARO") @@ -450,6 +457,13 @@ def writeTargetH(folder, map): pin = findPinByFunction('MAX7456_SPI_CS', map) file.write("#define MAX7456_CS_PIN %s\n" % (pin)) file.write("#define MAX7456_SPI_BUS BUS_%s\n" % (map['defines']['MAX7456_SPI_INSTANCE'])) + + pin = findPinByFunction('CAMERA_CONTROL', map) + if pin: + file.write("// CAMERA_CONTROL_PIN has no consuming driver prior to 10.0. From 10.0\n") + file.write("// forward this will be set up as a PWM-capable PINIO pin instead.\n") + file.write("#define CAMERA_CONTROL_PIN %s\n" % (pin)) + file.write("// Blackbox\n") # Flash: @@ -488,9 +502,10 @@ def writeTargetH(folder, map): file.write("#define SDCARD_SDIO_4BIT\n") file.write("#define SDCARD_SDIO_DEVICE SDIODEV_%i\n" % (i)) - # PINIO + # PINIO_COUNT is 4 (BOX_PERMANENT_ID_USER1..USER4) -- don't emit more than firmware + # can actually wire up in writeConfigC below. use_pinio = False - for i in range(1, 9): + for i in range(1, 5): pinio = findPinByFunction("PINIO%i" % (i), map) if pinio != None: if not use_pinio: @@ -725,9 +740,13 @@ def writeConfigC(folder, map): void targetConfiguration(void) { """) - #//pinioBoxConfigMutable()->permanentId[0] = BOX_PERMANENT_ID_USER1; - #//pinioBoxConfigMutable()->permanentId[1] = BOX_PERMANENT_ID_USER2; - #//beeperConfigMutable()->pwmMode = true; + # PINIO_COUNT is 4 (BOX_PERMANENT_ID_USER1..USER4) -- don't write more than that + # even if Betaflight's source somehow lists more PINIO pins than INAV supports. + for i in range(1, 5): + pinio = findPinByFunction("PINIO%i" % (i), map) + if pinio != None: + file.write(" pinioBoxConfigMutable()->permanentId[%i] = BOX_PERMANENT_ID_USER%i;\n" % (i - 1, i)) + file.write(""" } From b6fbebc904fc30c0301fe752a9a2e761d522a060 Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 6 Jul 2026 19:34:01 -0500 Subject: [PATCH 36/42] Add AXISFLYINGH743PRO target STM32H743 board with dual ICM42688P gyros (each registered via the shared USE_IMU_ICM42605 driver, tagged 0/1 on separate SPI buses with CLKIN sync pins wired as plain timer outputs -- no driver actually consumes CLKIN), DPS310 baro, MAX7456 OSD, PY25Q128HA flash, 8 motors, 4 servos, and 2 PINIO pins. TIM4 CH4 (servo 4) requires USE_DSHOT_DMAR, a known H7 DMAMUX quirk where that channel has no DMA request line otherwise. Motor/servo DMA options deliberately skip option 8 (DMA2 Stream0) since it's hardwired to ADC1, which this board also uses for VBAT/current sensing. UART5 is RX-only (ESC telemetry); its TX pin is wired to PC12, an otherwise-unused pin, since the H7 UART5 driver requires a real AF-valid TX pin to be defined even when unused. --- .../target/AXISFLYINGH743PRO/CMakeLists.txt | 1 + src/main/target/AXISFLYINGH743PRO/config.c | 34 ++++ src/main/target/AXISFLYINGH743PRO/target.c | 65 ++++++ src/main/target/AXISFLYINGH743PRO/target.h | 187 ++++++++++++++++++ 4 files changed, 287 insertions(+) create mode 100644 src/main/target/AXISFLYINGH743PRO/CMakeLists.txt create mode 100644 src/main/target/AXISFLYINGH743PRO/config.c create mode 100644 src/main/target/AXISFLYINGH743PRO/target.c create mode 100644 src/main/target/AXISFLYINGH743PRO/target.h diff --git a/src/main/target/AXISFLYINGH743PRO/CMakeLists.txt b/src/main/target/AXISFLYINGH743PRO/CMakeLists.txt new file mode 100644 index 00000000000..4bbff13df02 --- /dev/null +++ b/src/main/target/AXISFLYINGH743PRO/CMakeLists.txt @@ -0,0 +1 @@ +target_stm32h743xi(AXISFLYINGH743PRO) diff --git a/src/main/target/AXISFLYINGH743PRO/config.c b/src/main/target/AXISFLYINGH743PRO/config.c new file mode 100644 index 00000000000..dec78c3b8f6 --- /dev/null +++ b/src/main/target/AXISFLYINGH743PRO/config.c @@ -0,0 +1,34 @@ +/* + * This file is part of INAV. + * + * INAV is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * INAV is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with INAV. If not, see . + */ + +#include + +#include "platform.h" + +#include "fc/fc_msp_box.h" + +#include "io/piniobox.h" +#include "io/serial.h" + +void targetConfiguration(void) +{ + pinioBoxConfigMutable()->permanentId[0] = BOX_PERMANENT_ID_USER1; + pinioBoxConfigMutable()->permanentId[1] = BOX_PERMANENT_ID_USER2; + + // UART5 is RX-only and hard-wired to ESC telemetry + serialConfigMutable()->portConfigs[findSerialPortIndexByIdentifier(SERIAL_PORT_USART5)].functionMask = FUNCTION_ESCSERIAL; +} diff --git a/src/main/target/AXISFLYINGH743PRO/target.c b/src/main/target/AXISFLYINGH743PRO/target.c new file mode 100644 index 00000000000..d46088c078f --- /dev/null +++ b/src/main/target/AXISFLYINGH743PRO/target.c @@ -0,0 +1,65 @@ +/* + * This file is part of INAV. + * + * INAV is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * INAV is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with INAV. If not, see . + */ + +#include + +#include +#include "drivers/io.h" +#include "drivers/pwm_mapping.h" +#include "drivers/timer.h" +#include "drivers/bus.h" +#include "drivers/sensor.h" + +#include "drivers/pwm_output.h" +#include "common/maths.h" +#include "fc/config.h" + +// Gyro 1 - ICM42688P on SPI1, tag 0 +BUSDEV_REGISTER_SPI_TAG(busdev_gyro1_icm42605, DEVHW_ICM42605, GYRO_1_SPI_BUS, GYRO_1_CS_PIN, GYRO_1_EXTI_PIN, 0, DEVFLAGS_NONE, GYRO_1_ALIGN); + +// Gyro 2 - ICM42688P on SPI4, tag 1 +BUSDEV_REGISTER_SPI_TAG(busdev_gyro2_icm42605, DEVHW_ICM42605, GYRO_2_SPI_BUS, GYRO_2_CS_PIN, GYRO_2_EXTI_PIN, 1, DEVFLAGS_NONE, GYRO_2_ALIGN); + +timerHardware_t timerHardware[] = { + // Motors - DMA1 Stream0-7 (dmaopt 0-7), kept unique per channel so a + // fallback to per-channel DMA (USE_DSHOT_DMAR disabled) still works. + DEF_TIM(TIM8, CH1, PC6, TIM_USE_OUTPUT_AUTO, 0, 0), // M1 + DEF_TIM(TIM8, CH2, PC7, TIM_USE_OUTPUT_AUTO, 0, 1), // M2 + DEF_TIM(TIM8, CH3, PC8, TIM_USE_OUTPUT_AUTO, 0, 2), // M3 + DEF_TIM(TIM8, CH4, PC9, TIM_USE_OUTPUT_AUTO, 0, 3), // M4 + DEF_TIM(TIM2, CH1, PA0, TIM_USE_OUTPUT_AUTO, 0, 4), // M5 + DEF_TIM(TIM2, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 5), // M6 + DEF_TIM(TIM2, CH3, PA2, TIM_USE_OUTPUT_AUTO, 0, 6), // M7 + DEF_TIM(TIM2, CH4, PA3, TIM_USE_OUTPUT_AUTO, 0, 7), // M8 + + // Servos - DMA2 Stream1-4 (dmaopt 9-12). dmaopt 8 (DMA2 Stream0) is + // reserved for ADC1, which is hardwired to that stream on H743 and is + // not user-configurable, so it is deliberately skipped here. + DEF_TIM(TIM4, CH1, PD12, TIM_USE_OUTPUT_AUTO, 0, 9), // S1 + DEF_TIM(TIM4, CH2, PD13, TIM_USE_OUTPUT_AUTO, 0, 10), // S2 + DEF_TIM(TIM4, CH3, PD14, TIM_USE_OUTPUT_AUTO, 0, 11), // S3 + DEF_TIM(TIM4, CH4, PD15, TIM_USE_OUTPUT_AUTO, 0, 12), // S4 - needs USE_DSHOT_DMAR, see target.h + + // LED strip - DMA2 Stream5 (dmaopt 13) + DEF_TIM(TIM15, CH1, PE5, TIM_USE_LED, 0, 13), // LED_STRIP_PIN + + // Gyro CLKIN routing pins - plain timer output, no DMA consumer + DEF_TIM(TIM3, CH3, PB0, TIM_USE_ANY, 0, 0), // GYRO_1_CLKIN_PIN + DEF_TIM(TIM3, CH4, PB1, TIM_USE_ANY, 0, 0), // GYRO_2_CLKIN_PIN +}; + +const int timerHardwareCount = sizeof(timerHardware) / sizeof(timerHardware[0]); diff --git a/src/main/target/AXISFLYINGH743PRO/target.h b/src/main/target/AXISFLYINGH743PRO/target.h new file mode 100644 index 00000000000..a270b13627a --- /dev/null +++ b/src/main/target/AXISFLYINGH743PRO/target.h @@ -0,0 +1,187 @@ +/* + * This file is part of INAV. + * + * INAV is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * INAV is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with INAV. If not, see . + */ + +#pragma once + +#define TARGET_BOARD_IDENTIFIER "AXHP" +#define USBD_PRODUCT_STRING "AXISFLYINGH743PRO" + +#define USE_TARGET_CONFIG + +// *************** LED, BEEPER *************** +#define LED0 PD3 +#define BEEPER PC13 +#define BEEPER_INVERTED + +// *************** Gyro / Acc - dual ICM42688P (registered as DEVHW_ICM42605, +// whose WHO_AM_I switch also matches ICM42688P) *************** +#define USE_DUAL_GYRO +#define USE_TARGET_IMU_HARDWARE_DESCRIPTORS // Don't use common busdev descriptors for IMU +#define USE_IMU_ICM42605 + +// SPI1: Gyro 1 +#define USE_SPI +#define USE_SPI_DEVICE_1 +#define SPI1_SCK_PIN PA5 +#define SPI1_MISO_PIN PA6 +#define SPI1_MOSI_PIN PA7 + +#define GYRO_1_SPI_BUS BUS_SPI1 +#define GYRO_1_CS_PIN PC4 +#define GYRO_1_EXTI_PIN PA4 +#define GYRO_1_ALIGN CW0_DEG + +// SPI4: Gyro 2 +#define USE_SPI_DEVICE_4 +#define SPI4_SCK_PIN PE12 +#define SPI4_MISO_PIN PE13 +#define SPI4_MOSI_PIN PE14 + +#define GYRO_2_SPI_BUS BUS_SPI4 +#define GYRO_2_CS_PIN PE15 +#define GYRO_2_EXTI_PIN PE11 +#define GYRO_2_ALIGN CW90_DEG + +// Motor/servo DMA note: SERVO4_PIN (PD15/TIM4_CH4) has no per-channel DMAMUX +// request on this MCU; USE_DSHOT_DMAR repoints TIM4_CH4 at the TIM4_UP burst +// request so the channel keeps a valid DMA path. This makes all DSHOT-capable +// outputs use one shared burst DMA stream per timer (see target.c dmaopt +// comments for how streams are kept unique per timer). +#define USE_DSHOT_DMAR + +// *************** SPI2: OSD ***************** +#define USE_SPI_DEVICE_2 +#define SPI2_SCK_PIN PB13 +#define SPI2_MISO_PIN PB14 +#define SPI2_MOSI_PIN PB15 + +#define USE_MAX7456 +#define MAX7456_SPI_BUS BUS_SPI2 +#define MAX7456_CS_PIN PB12 + +// *************** SPI3: Flash *************** +#define USE_SPI_DEVICE_3 +#define SPI3_SCK_PIN PB3 +#define SPI3_MISO_PIN PB4 +#define SPI3_MOSI_PIN PB5 + +#define USE_FLASHFS +#define USE_FLASH_M25P16 +#define M25P16_SPI_BUS BUS_SPI3 +#define M25P16_CS_PIN PD7 +#define ENABLE_BLACKBOX_LOGGING_ON_SPIFLASH_BY_DEFAULT + +// *************** I2C1: Mag (external) ********************* +#define USE_I2C +#define USE_I2C_DEVICE_1 +#define I2C1_SCL PB8 +#define I2C1_SDA PB9 + +#define USE_MAG +#define MAG_I2C_BUS BUS_I2C1 +#define USE_MAG_ALL + +// *************** I2C2: Baro ********************* +#define USE_I2C_DEVICE_2 +#define I2C2_SCL PB10 +#define I2C2_SDA PB11 + +#define USE_BARO +#define BARO_I2C_BUS BUS_I2C2 +#define USE_BARO_DPS310 + +// *************** Serial ports ***************************** +#define USE_VCP + +#define USE_UART1 +#define UART1_TX_PIN PB6 +#define UART1_RX_PIN PB7 + +#define USE_UART2 +#define UART2_TX_PIN PD5 +#define UART2_RX_PIN PD6 + +#define USE_UART3 +#define UART3_TX_PIN PD8 +#define UART3_RX_PIN PD9 + +#define USE_UART4 +#define UART4_TX_PIN PC10 +#define UART4_RX_PIN PC11 + +// RX only - hard-wired to ESC telemetry, see config.c +#define USE_UART5 +#define UART5_TX_PIN PC12 // Unconnected placeholder: H7 UART5 driver's .af_tx lacks an #ifdef UART5_TX_PIN guard +#define UART5_RX_PIN PD2 + +#define USE_UART7 +#define UART7_TX_PIN PE8 +#define UART7_RX_PIN PE7 + +#define USE_UART8 +#define UART8_TX_PIN PE1 +#define UART8_RX_PIN PE0 + +#define SERIAL_PORT_COUNT 8 + +#define DEFAULT_RX_TYPE RX_TYPE_SERIAL +#define SERIALRX_PROVIDER SERIALRX_CRSF +#define SERIALRX_UART SERIAL_PORT_USART2 + +#define GPS_UART SERIAL_PORT_USART8 + +// Default MSP DisplayPort (HD OSD) port +#define MSP_UART SERIAL_PORT_USART1 + +#define USE_ESC_SENSOR + +// *************** ADC ***************************** +#define USE_ADC +#define ADC_INSTANCE ADC1 +#define ADC_CHANNEL_1_PIN PC0 +#define ADC_CHANNEL_2_PIN PC1 +#define VBAT_ADC_CHANNEL ADC_CHN_1 +#define CURRENT_METER_ADC_CHANNEL ADC_CHN_2 + +#define DEFAULT_VOLTAGE_METER_SOURCE VOLTAGE_METER_ADC +#define DEFAULT_CURRENT_METER_SOURCE CURRENT_METER_ADC + +// *************** LED2812 ************************ +#define USE_LED_STRIP +#define WS2811_PIN PE5 + +// *************** PINIO *************************** +#define USE_PINIO +#define USE_PINIOBOX +#define PINIO1_PIN PE2 // VTX PWR box, non-inverted +#define PINIO2_PIN PA8 // CAM 1,2 box +#define PINIO2_FLAGS PINIO_FLAGS_INVERTED + +// *************** Blackbox ************************ +#define DEFAULT_BLACKBOX_DEVICE BLACKBOX_DEVICE_FLASH + +// *************** OTHERS ************************* +#define USE_SERIAL_4WAY_BLHELI_INTERFACE + +#define TARGET_IO_PORTA 0xffff +#define TARGET_IO_PORTB 0xffff +#define TARGET_IO_PORTC 0xffff +#define TARGET_IO_PORTD 0xffff +#define TARGET_IO_PORTE 0xffff + +#define USE_DSHOT +#define MAX_PWM_OUTPUT_PORTS 12 From aff77943f0035dec1a5e437a7b76ab33983910a9 Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 6 Jul 2026 22:47:19 -0500 Subject: [PATCH 37/42] Add LSM6DSV16X/LSM6DSK320X support to LSM6DXX accgyro driver These chips reorganize CTRL1_XL/CTRL2_G to hold ODR + operating mode only (full scale moved to CTRL6_C/CTRL8_XL) with a different ODR bit encoding than the existing LSM6DSO/DSL/DS3 chips, so they get their own config sequence (lsm6dxxConfigGenV) via an early-return branch, leaving the legacy path untouched. Register values cross-checked against the ST datasheets and atbetaflight's hardware-validated accgyro_spi_lsm6dsv16x.c. Also wires DAKEFPVF405/target.h to the driver (shares CS/bus/alignment with the board's existing gyro options, per its manufacturer config), since it's the hardware testbed for this change. Hardware-validated on two physical DAKEFPVF405 units (one per chip): detection, at-rest/dynamic accel+gyro sanity, and CW90_DEG orientation sign all confirmed correct. --- src/main/drivers/accgyro/accgyro_lsm6dxx.c | 96 +++++++++++++++++++++- src/main/drivers/accgyro/accgyro_lsm6dxx.h | 27 +++++- src/main/target/DAKEFPVF405/target.h | 6 ++ 3 files changed, 126 insertions(+), 3 deletions(-) diff --git a/src/main/drivers/accgyro/accgyro_lsm6dxx.c b/src/main/drivers/accgyro/accgyro_lsm6dxx.c index 874f32eacb3..d00df7442d7 100644 --- a/src/main/drivers/accgyro/accgyro_lsm6dxx.c +++ b/src/main/drivers/accgyro/accgyro_lsm6dxx.c @@ -49,9 +49,19 @@ typedef struct __attribute__ ((__packed__)) lsm6DContextData_s { #define LSM6DSO_CHIP_ID 0x6C #define LSM6DSL_CHIP_ID 0x6A #define LSM6DS3_CHIP_ID 0x69 +// "Gen V" chips - reorganized register map vs. the DSO/DSL/DS3 above, see lsm6dxxConfigGenV() +#define LSM6DSV16X_CHIP_ID 0x70 +#define LSM6DSK320X_CHIP_ID 0x75 +// Single physical instance assumed: set once by lsm6dxxDetect() and read by lsm6dxxConfig()/ +// lsm6dxxIsGenV() afterward for the same instance - gyro detect always runs before config. static uint8_t lsm6dID = 0x6C; +static inline bool lsm6dxxIsGenV(void) +{ + return lsm6dID == LSM6DSV16X_CHIP_ID || lsm6dID == LSM6DSK320X_CHIP_ID; +} + static void lsm6dxxWriteRegister(const busDevice_t *dev, lsm6dxxRegister_e registerID, uint8_t value, unsigned delayMs) { busWrite(dev, registerID, value); @@ -85,8 +95,88 @@ static uint8_t getLsmDlpfBandwidth(gyroDev_t *gyro) return 0; } +// LPF1 bandwidth options for the Gen V chips, at the fixed 7.68kHz LPF1+LPF2 table row this +// driver uses. Values cross-checked against atbetaflight's accgyro_spi_lsm6dsv16x.c, which +// uses this same mapping on real hardware. +static uint8_t getLsmVDlpfBandwidth(gyroDev_t *gyro) +{ + switch (gyro->lpf) { + case GYRO_HARDWARE_LPF_NORMAL: + return LSM6DXX_VAL_CTRL6_C_V_LPF1_BW_288HZ; + case GYRO_HARDWARE_LPF_OPTION_1: + return LSM6DXX_VAL_CTRL6_C_V_LPF1_BW_157HZ; + case GYRO_HARDWARE_LPF_OPTION_2: + return LSM6DXX_VAL_CTRL6_C_V_LPF1_BW_215HZ; + case GYRO_HARDWARE_LPF_EXPERIMENTAL: + return LSM6DXX_VAL_CTRL6_C_V_LPF1_BW_455HZ; + } + return LSM6DXX_VAL_CTRL6_C_V_LPF1_BW_288HZ; +} + +// Configuration for LSM6DSV16X / LSM6DSK320X ("Gen V" chips - see lsm6dxxIsGenV()). These +// reorganized CTRL1_XL/CTRL2_G to hold ODR + operating mode only (full scale moved to +// CTRL6_C/CTRL8_XL) with a different ODR bit encoding, so they need their own config sequence +// rather than sharing the legacy DSO/DSL/DS3 one below. Sequence and register values are +// cross-checked against the LSM6DSV16X and LSM6DSK320X datasheets and atbetaflight's +// accgyro_spi_lsm6dsv16x.c (hardware-validated there for LSM6DSV16X). +static void lsm6dxxConfigGenV(gyroDev_t *gyro) +{ + busDevice_t * dev = gyro->busDev; + + busSetSpeed(dev, BUS_SPEED_INITIALIZATION); + + // Software reset, then wait for the device to clear the bit itself + lsm6dxxWriteRegister(dev, LSM6DXX_REG_CTRL3_C, LSM6DXX_MASK_CTRL3_C_RESET, 0); + uint8_t ctrl3 = LSM6DXX_MASK_CTRL3_C_RESET; + unsigned attemptsRemaining = 10; + while ((ctrl3 & LSM6DXX_MASK_CTRL3_C_RESET) && attemptsRemaining--) { + delay(1); + if (!busRead(dev, LSM6DXX_REG_CTRL3_C, &ctrl3)) { + break; // bus read failed - fall through to config once attempts are exhausted below + } + } + + // Auto-increment addresses for burst reads; hold output registers stable across a burst read + lsm6dxxWriteRegister(dev, LSM6DXX_REG_CTRL3_C, LSM6DXX_VAL_CTRL3_C_IF_INC | LSM6DXX_VAL_CTRL3_C_BDU, 0); + + // Selects the high-accuracy ODR table used by the CTRL1_XL/CTRL2_G writes below + lsm6dxxWriteRegister(dev, LSM6DXX_REG_HAODR_CFG, LSM6DXX_VAL_HAODR_CFG_MODE1, 0); + + // Accelerometer: high-accuracy mode, 1kHz ODR, +-16g full scale + lsm6dxxWriteRegister(dev, LSM6DXX_REG_CTRL1_XL, + (LSM6DXX_VAL_CTRL1_XL_V_OPMODE_HIGH_ACCURACY << 4) | LSM6DXX_VAL_CTRL1_XL_V_ODR_1000HZ_HAODR1, 0); + lsm6dxxWriteRegister(dev, LSM6DXX_REG_CTRL8_XL, LSM6DXX_VAL_CTRL8_XL_V_FS_16G, 0); + + // Gyroscope: high-accuracy mode, 8kHz ODR, +-2000dps full scale, LPF1 bandwidth per user setting + lsm6dxxWriteRegister(dev, LSM6DXX_REG_CTRL2_G, + (LSM6DXX_VAL_CTRL2_G_V_OPMODE_HIGH_ACCURACY << 4) | LSM6DXX_VAL_CTRL2_G_V_ODR_8000HZ_HAODR1, 0); + // LSM6DSK320X requires bit 3 of this register set to 1 ("must be set to 1 for correct operation of + // the device" per its datasheet) - it isn't part of the FS_G field there like it is on LSM6DSV16X + lsm6dxxWriteRegister(dev, LSM6DXX_REG_CTRL6_C, + (getLsmVDlpfBandwidth(gyro) << 4) | LSM6DXX_VAL_CTRL6_C_V_FS_G_2000DPS + | (lsm6dID == LSM6DSK320X_CHIP_ID ? LSM6DXX_VAL_CTRL6_C_V_DSK320X_RESERVED_BIT3 : 0), 0); + lsm6dxxWriteRegister(dev, LSM6DXX_REG_CTRL7_G, LSM6DXX_VAL_CTRL7_G_V_LPF1_EN, 0); + + // Data-ready interrupt is a pulse (no read required to clear it), routed to pin 1 + lsm6dxxWriteRegister(dev, LSM6DXX_REG_CTRL4_C, LSM6DXX_VAL_CTRL4_C_V_DRDY_PULSED, 0); + lsm6dxxWriteRegister(dev, LSM6DXX_REG_INT1_CTRL, LSM6DXX_VAL_INT1_CTRL, 0); + + // Datasheet section 4.1 (Mechanical characteristics): 70mdps/LSB at +-2000dps full scale. + // This differs from the 1/16.4 constant the legacy DSO/DSL/DS3 path below uses - that + // existing value is left untouched since it's out of scope here and already shipped. + gyro->scale = 0.070f; + gyro->sampleRateIntervalUs = 125; // 8kHz gyro ODR configured above + + busSetSpeed(dev, BUS_SPEED_FAST); +} + static void lsm6dxxConfig(gyroDev_t *gyro) -{ +{ + if (lsm6dxxIsGenV()) { + lsm6dxxConfigGenV(gyro); + return; + } + busDevice_t * dev = gyro->busDev; const gyroFilterAndRateConfig_t * config = mpuChooseGyroConfig(gyro->lpf, 1000000 / gyro->requestedSampleIntervalUs); gyro->sampleRateIntervalUs = 1000000 / config->gyroRateHz; @@ -153,7 +243,9 @@ static bool lsm6dxxDetect(busDevice_t * dev) switch (tmp) { case LSM6DSO_CHIP_ID: - case LSM6DSL_CHIP_ID: + case LSM6DSL_CHIP_ID: + case LSM6DSV16X_CHIP_ID: + case LSM6DSK320X_CHIP_ID: lsm6dID = tmp; // Compatible chip detected return true; diff --git a/src/main/drivers/accgyro/accgyro_lsm6dxx.h b/src/main/drivers/accgyro/accgyro_lsm6dxx.h index 6da333b065e..2e9169b8ed2 100644 --- a/src/main/drivers/accgyro/accgyro_lsm6dxx.h +++ b/src/main/drivers/accgyro/accgyro_lsm6dxx.h @@ -51,6 +51,7 @@ typedef enum { LSM6DXX_REG_OUTY_H_A = 0x2B, // acc Y axis MSB LSM6DXX_REG_OUTZ_L_A = 0x2C, // acc Z axis LSB LSM6DXX_REG_OUTZ_H_A = 0x2D, // acc Z axis MSB + LSM6DXX_REG_HAODR_CFG = 0x62, // high-accuracy ODR mode select (LSM6DSV16X/LSM6DSK320X only) } lsm6dxxRegister_e; // LSM6DXX register configuration values @@ -68,7 +69,7 @@ typedef enum { LSM6DXX_VAL_CTRL1_XL_LPF2 = 0x01, // accelerometer output from LPF2 LSM6DXX_VAL_CTRL2_G_ODR6664 = 0x0A, // gyro 6664hz output data rate LSM6DXX_VAL_CTRL2_G_2000DPS = 0x03, // gyro 2000dps scale - // LSM6DXX_VAL_CTRL3_C_BDU = BIT(6), // (bit 6) output registers are not updated until MSB and LSB have been read (prevents MSB from being updated while burst reading LSB/MSB) + LSM6DXX_VAL_CTRL3_C_BDU = BIT(6), // (bit 6) output registers are not updated until MSB and LSB have been read (prevents MSB from being updated while burst reading LSB/MSB) LSM6DXX_VAL_CTRL3_C_H_LACTIVE = 0, // (bit 5) interrupt pins active high LSM6DXX_VAL_CTRL3_C_PP_OD = 0, // (bit 4) interrupt pins push/pull LSM6DXX_VAL_CTRL3_C_SIM = 0, // (bit 3) SPI 4-wire interface mode @@ -87,6 +88,30 @@ typedef enum { LSM6DXX_VAL_CTRL7_G_HPM_G_260 = 0x02, // (bits 5:4) gyro HPF cutoff 260mHz LSM6DXX_VAL_CTRL7_G_HPM_G_1040 = 0x03, // (bits 5:4) gyro HPF cutoff 1.04Hz LSM6DXX_VAL_CTRL9_XL_I3C_DISABLE = BIT(1),// (bit 1) disable I3C interface + + // LSM6DSV16X/LSM6DSK320X ("Gen V") register field values. This generation moved ODR/mode + // into CTRL1_XL/CTRL2_G bits[6:4]+[3:0] (full scale is no longer here - see CTRL6_C/CTRL8_XL + // below) and uses a completely different ODR encoding from the legacy LSM6DSO/DSL/DS3 chips + // above, so none of the _ODR*/_*DPS/_*G values above apply to these two chips. + LSM6DXX_VAL_CTRL1_XL_V_OPMODE_HIGH_ACCURACY = 0x01, // (bits 6:4) accel high-accuracy ODR mode + LSM6DXX_VAL_CTRL1_XL_V_ODR_1000HZ_HAODR1 = 0x09, // (bits 3:0) 1kHz accel ODR, HAODR mode 1 + LSM6DXX_VAL_CTRL2_G_V_OPMODE_HIGH_ACCURACY = 0x01, // (bits 6:4) gyro high-accuracy ODR mode + LSM6DXX_VAL_CTRL2_G_V_ODR_8000HZ_HAODR1 = 0x0C, // (bits 3:0) 8kHz gyro ODR, HAODR mode 1 (0x0B is 4kHz - off by one row) + LSM6DXX_VAL_HAODR_CFG_MODE1 = 0x01, // (bits 1:0) selects the ODR tables above + LSM6DXX_VAL_CTRL6_C_V_FS_G_2000DPS = 0x04, // (bits 3:0) gyro full-scale +-2000dps + // (LSM6DSV16X: 4-bit FS_G field, 0100 = 2000dps; on + // LSM6DSK320X, bit 3 of this value is instead a separate + // reserved bit the datasheet says "must be set to 1 for + // correct operation" - FS_G there is bits[2:0] only, where + // 100 also happens to mean 2000dps - see LSM6DXX_VAL_CTRL6_C_V_DSK320X_RESERVED_BIT3) + LSM6DXX_VAL_CTRL6_C_V_DSK320X_RESERVED_BIT3 = BIT(3), // must be 1 on LSM6DSK320X only, see above + LSM6DXX_VAL_CTRL6_C_V_LPF1_BW_288HZ = 0x00, // (bits 6:4) gyro LPF1 bandwidth ~288Hz + LSM6DXX_VAL_CTRL6_C_V_LPF1_BW_215HZ = 0x01, // (bits 6:4) gyro LPF1 bandwidth ~215Hz + LSM6DXX_VAL_CTRL6_C_V_LPF1_BW_157HZ = 0x02, // (bits 6:4) gyro LPF1 bandwidth ~157Hz + LSM6DXX_VAL_CTRL6_C_V_LPF1_BW_455HZ = 0x03, // (bits 6:4) gyro LPF1 bandwidth ~455Hz + LSM6DXX_VAL_CTRL7_G_V_LPF1_EN = BIT(0), // (bit 0) enable gyro LPF1 + LSM6DXX_VAL_CTRL8_XL_V_FS_16G = 0x03, // (bits 1:0) accel full-scale +-16g + LSM6DXX_VAL_CTRL4_C_V_DRDY_PULSED = BIT(1), // (bit 1) data-ready interrupt is a pulse, not a level } lsm6dxxConfigValues_e; // LSM6DXX register configuration bit masks diff --git a/src/main/target/DAKEFPVF405/target.h b/src/main/target/DAKEFPVF405/target.h index 0f626365369..30834b7682b 100644 --- a/src/main/target/DAKEFPVF405/target.h +++ b/src/main/target/DAKEFPVF405/target.h @@ -72,7 +72,13 @@ #define BMI270_SPI_BUS BUS_SPI1 #define BMI270_CS_PIN PA4 +#define USE_IMU_LSM6DXX +#define IMU_LSM6DXX_ALIGN CW90_DEG +#define LSM6DXX_SPI_BUS BUS_SPI1 +#define LSM6DXX_CS_PIN PA4 + // ICM42688P driver handled by USE_IMU_ICM42605 above (shares WHO_AM_I detection) +// LSM6DSV16X / LSM6DSK320X driver handled by USE_IMU_LSM6DXX above (shares WHO_AM_I detection) //Baro #define USE_BARO From 0014dbc1f1db95821c0ef653966cb3c70cd284f2 Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Tue, 7 Jul 2026 00:07:52 -0500 Subject: [PATCH 38/42] bf2inav.py: update LSM6DSK320X support --- docs/development/Converting Betaflight Targets.md | 4 ++-- src/utils/bf2inav.py | 7 ------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/docs/development/Converting Betaflight Targets.md b/docs/development/Converting Betaflight Targets.md index be734ef67b7..863135affac 100644 --- a/docs/development/Converting Betaflight Targets.md +++ b/docs/development/Converting Betaflight Targets.md @@ -5,7 +5,7 @@ Locate your Flight Controller target config.h in BetaFlight's repo, eg.: [config It is also advisable to record the output of the timer command from BetaFlight, as it will provide useful information on `timer` usage that can be used to adjust the generated target later. -The script generates `CAMERA_CONTROL_PIN` and PINIO `permanentId` wiring in `config.c` automatically when present in the source `config.h`. If the source config lists a gyro chip INAV has no driver for yet, the script prints a warning instead of silently omitting it -- check the script's console output after running it. +The script generates `CAMERA_CONTROL_PIN` and PINIO `permanentId` wiring in `config.c` automatically when present in the source `config.h`. ``` # timer @@ -73,4 +73,4 @@ timerHardware_t timerHardware[] = { In this particular example, PA3, PA2 were changed to match Betaflight's mapping, and the timer PB4 was disabled, due to a timer conflict. Normal channels are prefered over N channels (CH1, over CH1N) or C channels in AT32 architectures. 7. Now update yout build scripts by running `cmake` and build the target you just created. The target name can be checked in the generated `CMakeLists.txt`, but should match the Betaflight target name. -For information on how to build INAV, check the documents in the [docs/development](https://github.com/iNavFlight/inav/tree/master/docs/development) folder. \ No newline at end of file +For information on how to build INAV, check the documents in the [docs/development](https://github.com/iNavFlight/inav/tree/master/docs/development) folder. diff --git a/src/utils/bf2inav.py b/src/utils/bf2inav.py index f7750a7275d..8309cb1d756 100755 --- a/src/utils/bf2inav.py +++ b/src/utils/bf2inav.py @@ -427,13 +427,6 @@ def writeTargetH(folder, map): file.write("#define %s_SPI_BUS BUS_%s\n" % (supportedgyro, map['defines']['GYRO_1_SPI_INSTANCE'])) file.write("#define IMU_%s_ALIGN %s\n" % (supportedgyro, getGyroAlign(map))) - # Chips Betaflight supports that INAV has no driver for yet -- warn rather than - # silently drop, so whoever runs this doesn't ship a target missing a gyro option. - for unsupportedgyro in ['LSM6DSV16X', 'LSM6DSK320X']: - for var in ['USE_ACCGYRO_', 'USE_ACC_', 'USE_ACC_SPI', 'USE_GYRO_', 'USE_GYRO_SPI_']: - if (var + unsupportedgyro) in map['empty_defines']: - print("WARNING: Betaflight config lists %s, but INAV has no driver for it yet. Not added to target.h -- flag this as a separate driver project." % (unsupportedgyro), file=sys.stderr) - break if 'USE_BARO' in map['empty_defines']: #print ("BARO") From 82090e4c80ae0e69b7a2daf7b4deed206d298139 Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Tue, 7 Jul 2026 12:32:51 -0500 Subject: [PATCH 39/42] Fix LED strip / ADC1 DMA conflict on DAKEFPVH743PRO TIM3 CH3 (LED strip) was assigned DMA option 8 (DMA2 Stream0), the same stream ADC1 uses for VBAT/current sensing, causing DMA contention between the two peripherals. Move the LED strip to DMA option 9 (DMA2 Stream1), which is unclaimed on this target, matching the fix already applied to the sibling DAKEFPVH743_SLIM target. Verified on physical hardware: LED strip, VBAT, and current sensing all work correctly with DSHOT and the LED strip active simultaneously. --- src/main/target/DAKEFPVH743PRO/target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/target/DAKEFPVH743PRO/target.c b/src/main/target/DAKEFPVH743PRO/target.c index ad80082917b..f5455be7016 100644 --- a/src/main/target/DAKEFPVH743PRO/target.c +++ b/src/main/target/DAKEFPVH743PRO/target.c @@ -55,7 +55,7 @@ timerHardware_t timerHardware[] = { DEF_TIM(TIM4, CH4, PD15, TIM_USE_OUTPUT_AUTO, 0, 0), // S4 DEF_TIM(TIM15, CH1, PE5, TIM_USE_ANY, 0, 0), // CAMERA_CONTROL_PIN DEF_TIM(TIM15, CH2, PE6, TIM_USE_ANY, 0, 0), // GYRO_1_CLKIN_PIN - DEF_TIM(TIM3, CH3, PB0, TIM_USE_LED, 0, 8), // LED_2812 + DEF_TIM(TIM3, CH3, PB0, TIM_USE_LED, 0, 9), // LED_2812 - moved off DMA2 Stream0 to avoid ADC1 DMA conflict }; const int timerHardwareCount = sizeof(timerHardware) / sizeof(timerHardware[0]); From cb36ba5361ca182610f83313752332d706efc5dd Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Tue, 7 Jul 2026 18:23:50 -0500 Subject: [PATCH 40/42] AXISFLYINGH743PRO: remove bogus timers, PINIO_FLAGS_INVERTED --- src/main/target/AXISFLYINGH743PRO/target.c | 8 +------- src/main/target/AXISFLYINGH743PRO/target.h | 6 ++---- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/main/target/AXISFLYINGH743PRO/target.c b/src/main/target/AXISFLYINGH743PRO/target.c index d46088c078f..303d2f16f93 100644 --- a/src/main/target/AXISFLYINGH743PRO/target.c +++ b/src/main/target/AXISFLYINGH743PRO/target.c @@ -46,9 +46,7 @@ timerHardware_t timerHardware[] = { DEF_TIM(TIM2, CH3, PA2, TIM_USE_OUTPUT_AUTO, 0, 6), // M7 DEF_TIM(TIM2, CH4, PA3, TIM_USE_OUTPUT_AUTO, 0, 7), // M8 - // Servos - DMA2 Stream1-4 (dmaopt 9-12). dmaopt 8 (DMA2 Stream0) is - // reserved for ADC1, which is hardwired to that stream on H743 and is - // not user-configurable, so it is deliberately skipped here. + // dmaopt 8 (DMA2 Stream0) is reserved for ADC DEF_TIM(TIM4, CH1, PD12, TIM_USE_OUTPUT_AUTO, 0, 9), // S1 DEF_TIM(TIM4, CH2, PD13, TIM_USE_OUTPUT_AUTO, 0, 10), // S2 DEF_TIM(TIM4, CH3, PD14, TIM_USE_OUTPUT_AUTO, 0, 11), // S3 @@ -56,10 +54,6 @@ timerHardware_t timerHardware[] = { // LED strip - DMA2 Stream5 (dmaopt 13) DEF_TIM(TIM15, CH1, PE5, TIM_USE_LED, 0, 13), // LED_STRIP_PIN - - // Gyro CLKIN routing pins - plain timer output, no DMA consumer - DEF_TIM(TIM3, CH3, PB0, TIM_USE_ANY, 0, 0), // GYRO_1_CLKIN_PIN - DEF_TIM(TIM3, CH4, PB1, TIM_USE_ANY, 0, 0), // GYRO_2_CLKIN_PIN }; const int timerHardwareCount = sizeof(timerHardware) / sizeof(timerHardware[0]); diff --git a/src/main/target/AXISFLYINGH743PRO/target.h b/src/main/target/AXISFLYINGH743PRO/target.h index a270b13627a..11958554b9f 100644 --- a/src/main/target/AXISFLYINGH743PRO/target.h +++ b/src/main/target/AXISFLYINGH743PRO/target.h @@ -59,8 +59,7 @@ // Motor/servo DMA note: SERVO4_PIN (PD15/TIM4_CH4) has no per-channel DMAMUX // request on this MCU; USE_DSHOT_DMAR repoints TIM4_CH4 at the TIM4_UP burst // request so the channel keeps a valid DMA path. This makes all DSHOT-capable -// outputs use one shared burst DMA stream per timer (see target.c dmaopt -// comments for how streams are kept unique per timer). +// outputs use one shared burst DMA stream per timer #define USE_DSHOT_DMAR // *************** SPI2: OSD ***************** @@ -167,9 +166,8 @@ // *************** PINIO *************************** #define USE_PINIO #define USE_PINIOBOX -#define PINIO1_PIN PE2 // VTX PWR box, non-inverted +#define PINIO1_PIN PE2 // VTX PWR box #define PINIO2_PIN PA8 // CAM 1,2 box -#define PINIO2_FLAGS PINIO_FLAGS_INVERTED // *************** Blackbox ************************ #define DEFAULT_BLACKBOX_DEVICE BLACKBOX_DEVICE_FLASH From baabf4388079bc3a97083d1fe561ffc3c94f9f64 Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Tue, 7 Jul 2026 18:40:57 -0500 Subject: [PATCH 41/42] AXISFLYINGH743PRO: set default features --- src/main/target/AXISFLYINGH743PRO/target.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/target/AXISFLYINGH743PRO/target.h b/src/main/target/AXISFLYINGH743PRO/target.h index 11958554b9f..2b3e9a47422 100644 --- a/src/main/target/AXISFLYINGH743PRO/target.h +++ b/src/main/target/AXISFLYINGH743PRO/target.h @@ -137,6 +137,7 @@ #define SERIAL_PORT_COUNT 8 +#define DEFAULT_FEATURES (FEATURE_OSD | FEATURE_TELEMETRY | FEATURE_CURRENT_METER | FEATURE_VBAT | FEATURE_TX_PROF_SEL | FEATURE_BLACKBOX) #define DEFAULT_RX_TYPE RX_TYPE_SERIAL #define SERIALRX_PROVIDER SERIALRX_CRSF #define SERIALRX_UART SERIAL_PORT_USART2 From ec55b09a5d3b0dd8bd151d7009c12503b46a10d1 Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Tue, 7 Jul 2026 18:46:14 -0500 Subject: [PATCH 42/42] Converting Betaflight Targets.md: default_features --- .../Converting Betaflight Targets.md | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/docs/development/Converting Betaflight Targets.md b/docs/development/Converting Betaflight Targets.md index 47f460f634d..f44d3529006 100644 --- a/docs/development/Converting Betaflight Targets.md +++ b/docs/development/Converting Betaflight Targets.md @@ -38,37 +38,27 @@ Using the BETAFPVF405 target mentioned above, to create the target now we need t 3. Create a target folder that will be used as the output folder for the `bf2inav.py` script, eg: `inav/src/main/targets/BETAFPVF405` 4. Navigate to the script folder in `inav/src/utils/` 5. `python3 ./bf2inav.py -i config.h -o ../main/target/BETAFPVF405/` -6. Edit generated `target.c` and chose the correct timer definitions to match Betaflight's timer definitions. +6. Edit generated `target.c` and chose the correct timer definitions to match Betaflight's timer definitions for motor, servo, and LED timers (not gyro). ``` timerHardware_t timerHardware[] = { DEF_TIM(TIM3, CH3, PB0, TIM_USE_OUTPUT_AUTO, 0, 0), - //DEF_TIM(TIM8, CH2N, PB0, TIM_USE_OUTPUT_AUTO, 0, 0), - //DEF_TIM(TIM1, CH2N, PB0, TIM_USE_OUTPUT_AUTO, 0, 0), - DEF_TIM(TIM3, CH4, PB1, TIM_USE_OUTPUT_AUTO, 0, 0), - //DEF_TIM(TIM8, CH3N, PB1, TIM_USE_OUTPUT_AUTO, 0, 0), - //DEF_TIM(TIM1, CH3N, PB1, TIM_USE_OUTPUT_AUTO, 0, 0), - - //DEF_TIM(TIM5, CH4, PA3, TIM_USE_OUTPUT_AUTO, 0, 0), - //DEF_TIM(TIM9, CH2, PA3, TIM_USE_OUTPUT_AUTO, 0, 0), DEF_TIM(TIM2, CH4, PA3, TIM_USE_OUTPUT_AUTO, 0, 0), - - //DEF_TIM(TIM5, CH3, PA2, TIM_USE_OUTPUT_AUTO, 0, 0), - //DEF_TIM(TIM9, CH1, PA2, TIM_USE_OUTPUT_AUTO, 0, 0), DEF_TIM(TIM2, CH3, PA2, TIM_USE_OUTPUT_AUTO, 0, 0), DEF_TIM(TIM8, CH3, PC8, TIM_USE_OUTPUT_AUTO, 0, 0), - //DEF_TIM(TIM3, CH3, PC8, TIM_USE_OUTPUT_AUTO, 0, 0), - DEF_TIM(TIM1, CH1, PA8, TIM_USE_OUTPUT_AUTO, 0, 0), - //DEF_TIM(TIM3, CH1, PB4, TIM_USE_BEEPER, 0, 0), DEF_TIM(TIM4, CH1, PB6, TIM_USE_LED, 0, 0), }; ``` -In this particular example, PA3, PA2 were changed to match Betaflight's mapping, and the timer PB4 was disabled, due to a timer conflict. Normal channels are prefered over N channels (CH1, over CH1N) or C channels in AT32 architectures. -7. Now update yout build scripts by running `cmake` and build the target you just created. The target name can be checked in the generated `CMakeLists.txt`, but should match the Betaflight target name. +Normal channels are prefered over N channels (CH1, over CH1N) or C channels in AT32 architectures. + +The typical value to be set in target.h for DEFAULT_FEATURES is: +#define DEFAULT_FEATURES (FEATURE_OSD | FEATURE_TELEMETRY | FEATURE_CURRENT_METER | FEATURE_VBAT | FEATURE_TX_PROF_SEL | FEATURE_BLACKBOX) + +7. Now update your build scripts by running `cmake` and build the target you just created. The target name can be checked in the generated `CMakeLists.txt`, but should match the Betaflight target name. -For information on how to build INAV, check the documents in the [docs/development](https://github.com/iNavFlight/inav/tree/master/docs/development) folder. \ No newline at end of file +For information on how to build INAV, check the documents in the [docs/development](https://github.com/iNavFlight/inav/tree/master/docs/development) folder.