diff --git a/docs/development/msp/format.md b/docs/development/msp/format.md
index e8c6a348c07..bbe7c1fc6fa 100644
--- a/docs/development/msp/format.md
+++ b/docs/development/msp/format.md
@@ -40,6 +40,7 @@
**variable_len**: Optional boolean, if true, message does not have a predefined fixed length and needs appropriate handling\
**variants**: Optional special case, message has different cases of reply/request. Key/description is not a strict expression or code; just a readable condition\
**not_implemented**: Optional special case, message is not implemented (never or deprecated)\
+**replaced_by**: Optional array of MSP message names that replace this command. Present when a command is deprecated and scheduled for removal. Empty array if no replacement is needed\
**notes**: String with details of message
## Data dict fields:
diff --git a/docs/development/msp/msp_messages.json b/docs/development/msp/msp_messages.json
index e4c2a39993f..84d603de8e1 100644
--- a/docs/development/msp/msp_messages.json
+++ b/docs/development/msp/msp_messages.json
@@ -673,6 +673,7 @@
"MSP_POSITION_ESTIMATION_CONFIG": {
"code": 16,
"mspv": 1,
+ "replaced_by": ["MSP2_COMMON_SETTING"],
"request": null,
"reply": {
"payload": [
@@ -727,6 +728,7 @@
"MSP_SET_POSITION_ESTIMATION_CONFIG": {
"code": 17,
"mspv": 1,
+ "replaced_by": ["MSP2_COMMON_SET_SETTING"],
"request": {
"payload": [
{
@@ -2360,6 +2362,7 @@
"MSP_BLACKBOX_CONFIG": {
"code": 80,
"mspv": 1,
+ "replaced_by": ["MSP2_BLACKBOX_CONFIG"],
"request": null,
"reply": {
"payload": [
@@ -2399,6 +2402,7 @@
"MSP_SET_BLACKBOX_CONFIG": {
"code": 81,
"mspv": 1,
+ "replaced_by": ["MSP2_SET_BLACKBOX_CONFIG"],
"not_implemented": true,
"request": null,
"reply": null,
@@ -2426,6 +2430,7 @@
"MSP_OSD_CONFIG": {
"code": 84,
"mspv": 1,
+ "replaced_by": ["MSP2_INAV_OSD_LAYOUTS", "MSP2_INAV_OSD_ALARMS", "MSP2_INAV_OSD_PREFERENCES"],
"request": null,
"reply": {
"payload": [
@@ -2504,6 +2509,7 @@
"MSP_SET_OSD_CONFIG": {
"code": 85,
"mspv": 1,
+ "replaced_by": ["MSP2_INAV_OSD_SET_LAYOUT_ITEM", "MSP2_INAV_OSD_SET_ALARMS", "MSP2_INAV_OSD_SET_PREFERENCES"],
"request": null,
"reply": null,
"notes": "Requires `USE_OSD`. Distinguishes formats based on the first byte. Format 1 requires at least 10 bytes. Format 2 requires 3 bytes. Triggers an OSD redraw. See `MSP2_INAV_OSD_SET_*` for more advanced control.",
@@ -3134,6 +3140,7 @@
"MSP_FILTER_CONFIG": {
"code": 92,
"mspv": 1,
+ "replaced_by": ["MSP2_COMMON_SETTING"],
"request": null,
"reply": {
"payload": [
@@ -3217,6 +3224,7 @@
"MSP_SET_FILTER_CONFIG": {
"code": 93,
"mspv": 1,
+ "replaced_by": ["MSP2_COMMON_SET_SETTING"],
"request": {
"payload": [
{
@@ -3293,6 +3301,7 @@
"MSP_PID_ADVANCED": {
"code": 94,
"mspv": 1,
+ "replaced_by": ["MSP_INAV_PID"],
"request": null,
"reply": {
"payload": [
@@ -3370,6 +3379,7 @@
"MSP_SET_PID_ADVANCED": {
"code": 95,
"mspv": 1,
+ "replaced_by": ["MSP_SET_INAV_PID"],
"request": {
"payload": [
{
@@ -3599,6 +3609,7 @@
"MSP_STATUS": {
"code": 101,
"mspv": 1,
+ "replaced_by": ["MSP2_INAV_STATUS"],
"request": null,
"reply": {
"payload": [
@@ -3914,6 +3925,7 @@
"MSP_ANALOG": {
"code": 110,
"mspv": 1,
+ "replaced_by": ["MSP2_INAV_ANALOG"],
"request": null,
"reply": {
"payload": [
@@ -4039,6 +4051,7 @@
"MSP_MISC": {
"code": 114,
"mspv": 1,
+ "replaced_by": ["MSP2_INAV_MISC"],
"request": null,
"reply": {
"payload": [
@@ -4168,6 +4181,7 @@
"MSP_PIDNAMES": {
"code": 117,
"mspv": 1,
+ "replaced_by": [],
"request": null,
"reply": {
"payload": [
@@ -4644,6 +4658,7 @@
"MSP_STATUS_EX": {
"code": 150,
"mspv": 1,
+ "replaced_by": ["MSP2_INAV_STATUS"],
"request": null,
"reply": {
"payload": [
@@ -4701,7 +4716,7 @@
}
]
},
- "notes": "Superseded by `MSP2_INAV_STATUS` which provides the full 32-bit `armingFlags` and other enhancements.",
+ "notes": "Superseded by `MSP2_INAV_STATUS` which provides the full 32-bit `armingFlags` and other enhancements. The `accCalibAxisFlags` field is not present in `MSP2_INAV_STATUS` but is available via `MSP_CALIBRATION_DATA`.",
"description": "Provides extended flight controller status, including CPU load, arming flags, and calibration status, in addition to `MSP_STATUS` fields."
},
"MSP_SENSOR_STATUS": {
@@ -5135,6 +5150,7 @@
"MSP_SET_MISC": {
"code": 207,
"mspv": 1,
+ "replaced_by": ["MSP2_INAV_SET_MISC"],
"request": {
"payload": [
{
@@ -5588,6 +5604,7 @@
"MSP_SERVO_MIX_RULES": {
"code": 241,
"mspv": 1,
+ "replaced_by": ["MSP2_INAV_SERVO_MIXER"],
"request": null,
"reply": {
"payload": [
@@ -5644,6 +5661,7 @@
"MSP_SET_SERVO_MIX_RULE": {
"code": 242,
"mspv": 1,
+ "replaced_by": ["MSP2_INAV_SET_SERVO_MIXER"],
"request": {
"payload": [
{
@@ -5803,6 +5821,7 @@
"MSP_DEBUG": {
"code": 254,
"mspv": 1,
+ "replaced_by": ["MSP2_INAV_DEBUG"],
"request": null,
"reply": {
"payload": [
diff --git a/src/main/drivers/bus_spi_hal_ll.c b/src/main/drivers/bus_spi_hal_ll.c
index fac8a82761a..ce6fbde9595 100644
--- a/src/main/drivers/bus_spi_hal_ll.c
+++ b/src/main/drivers/bus_spi_hal_ll.c
@@ -89,109 +89,159 @@ static const uint32_t spiDivisorMapSlow[] = {
#endif
#if defined(STM32H7)
-static spiDevice_t spiHardwareMap[SPIDEV_COUNT] = {
+#include "bus_spi_stm32h7xx.h"
+
+// Auto-resolve SPI AF per pin from the lookup table in bus_spi_stm32h7xx.h.
+// Targets may still define individual SPI*_SCK/MISO/MOSI_AF values in target.h
+// to override; explicit defines take priority via these #ifndef guards.
#ifdef USE_SPI_DEVICE_1
-#if defined(SPI1_SCK_AF) || defined(SPI1_MISO_AF) || defined(SPI1_MOSI_AF)
-#if !defined(SPI1_SCK_AF) || !defined(SPI1_MISO_AF) || !defined(SPI1_MOSI_AF)
-#error SPI1: SCK, MISO and MOSI AFs should be defined together in target.h!
+#ifndef SPI1_SCK_AF
+#define SPI1_SCK_AF SPI_PIN_AF_HELPER(1, SPI1_SCK_PIN)
#endif
- { .dev = SPI1, .nss = IO_TAG(SPI1_NSS_PIN), .sck = IO_TAG(SPI1_SCK_PIN), .miso = IO_TAG(SPI1_MISO_PIN), .mosi = IO_TAG(SPI1_MOSI_PIN), .rcc = RCC_APB2(SPI1), .sckAF = SPI1_SCK_AF, .misoAF = SPI1_MISO_AF, .mosiAF = SPI1_MOSI_AF, .divisorMap = spiDivisorMapFast },
-#else
- { .dev = SPI1, .nss = IO_TAG(SPI1_NSS_PIN), .sck = IO_TAG(SPI1_SCK_PIN), .miso = IO_TAG(SPI1_MISO_PIN), .mosi = IO_TAG(SPI1_MOSI_PIN), .rcc = RCC_APB2(SPI1), .sckAF = GPIO_AF5_SPI1, .misoAF = GPIO_AF5_SPI1, .mosiAF = GPIO_AF5_SPI1, .divisorMap = spiDivisorMapFast },
+#ifndef SPI1_MISO_AF
+#define SPI1_MISO_AF SPI_PIN_AF_HELPER(1, SPI1_MISO_PIN)
+#endif
+#ifndef SPI1_MOSI_AF
+#define SPI1_MOSI_AF SPI_PIN_AF_HELPER(1, SPI1_MOSI_PIN)
#endif
-#else
- { .dev = NULL }, // No SPI1
#endif
#ifdef USE_SPI_DEVICE_2
-#if defined(SPI2_SCK_AF) || defined(SPI2_MISO_AF) || defined(SPI2_MOSI_AF)
-#if !defined(SPI2_SCK_AF) || !defined(SPI2_MISO_AF) || !defined(SPI2_MOSI_AF)
-#error SPI2: SCK, MISO and MOSI AFs should be defined together in target.h!
+#ifndef SPI2_SCK_AF
+#define SPI2_SCK_AF SPI_PIN_AF_HELPER(2, SPI2_SCK_PIN)
#endif
- { .dev = SPI2, .nss = IO_TAG(SPI2_NSS_PIN), .sck = IO_TAG(SPI2_SCK_PIN), .miso = IO_TAG(SPI2_MISO_PIN), .mosi = IO_TAG(SPI2_MOSI_PIN), .rcc = RCC_APB1L(SPI2), .sckAF = SPI2_SCK_AF, .misoAF = SPI2_MISO_AF, .mosiAF = SPI2_MOSI_AF, .divisorMap = spiDivisorMapSlow },
+#ifndef SPI2_MISO_AF
+#define SPI2_MISO_AF SPI_PIN_AF_HELPER(2, SPI2_MISO_PIN)
+#endif
+#ifndef SPI2_MOSI_AF
+#define SPI2_MOSI_AF SPI_PIN_AF_HELPER(2, SPI2_MOSI_PIN)
+#endif
+#endif
+
+#ifdef USE_SPI_DEVICE_3
+#ifndef SPI3_SCK_AF
+#define SPI3_SCK_AF SPI_PIN_AF_HELPER(3, SPI3_SCK_PIN)
+#endif
+#ifndef SPI3_MISO_AF
+#define SPI3_MISO_AF SPI_PIN_AF_HELPER(3, SPI3_MISO_PIN)
+#endif
+#ifndef SPI3_MOSI_AF
+#define SPI3_MOSI_AF SPI_PIN_AF_HELPER(3, SPI3_MOSI_PIN)
+#endif
+#endif
+
+#ifdef USE_SPI_DEVICE_4
+#ifndef SPI4_SCK_AF
+#define SPI4_SCK_AF SPI_PIN_AF_HELPER(4, SPI4_SCK_PIN)
+#endif
+#ifndef SPI4_MISO_AF
+#define SPI4_MISO_AF SPI_PIN_AF_HELPER(4, SPI4_MISO_PIN)
+#endif
+#ifndef SPI4_MOSI_AF
+#define SPI4_MOSI_AF SPI_PIN_AF_HELPER(4, SPI4_MOSI_PIN)
+#endif
+#endif
+
+static spiDevice_t spiHardwareMap[SPIDEV_COUNT] = {
+#ifdef USE_SPI_DEVICE_1
+ { .dev = SPI1, .nss = IO_TAG(SPI1_NSS_PIN), .sck = IO_TAG(SPI1_SCK_PIN), .miso = IO_TAG(SPI1_MISO_PIN), .mosi = IO_TAG(SPI1_MOSI_PIN), .rcc = RCC_APB2(SPI1), .sckAF = SPI1_SCK_AF, .misoAF = SPI1_MISO_AF, .mosiAF = SPI1_MOSI_AF, .divisorMap = spiDivisorMapFast },
#else
- { .dev = SPI2, .nss = IO_TAG(SPI2_NSS_PIN), .sck = IO_TAG(SPI2_SCK_PIN), .miso = IO_TAG(SPI2_MISO_PIN), .mosi = IO_TAG(SPI2_MOSI_PIN), .rcc = RCC_APB1L(SPI2), .sckAF = GPIO_AF5_SPI2, .misoAF = GPIO_AF5_SPI2, .mosiAF = GPIO_AF5_SPI2, .divisorMap = spiDivisorMapSlow },
+ { .dev = NULL }, // No SPI1
#endif
+
+#ifdef USE_SPI_DEVICE_2
+ { .dev = SPI2, .nss = IO_TAG(SPI2_NSS_PIN), .sck = IO_TAG(SPI2_SCK_PIN), .miso = IO_TAG(SPI2_MISO_PIN), .mosi = IO_TAG(SPI2_MOSI_PIN), .rcc = RCC_APB1L(SPI2), .sckAF = SPI2_SCK_AF, .misoAF = SPI2_MISO_AF, .mosiAF = SPI2_MOSI_AF, .divisorMap = spiDivisorMapSlow },
#else
{ .dev = NULL }, // No SPI2
#endif
#ifdef USE_SPI_DEVICE_3
-#if defined(SPI3_SCK_AF) || defined(SPI3_MISO_AF) || defined(SPI3_MOSI_AF)
-#if !defined(SPI3_SCK_AF) || !defined(SPI3_MISO_AF) || !defined(SPI3_MOSI_AF)
-#error SPI3: SCK, MISO and MOSI AFs should be defined together in target.h!
-#endif
{ .dev = SPI3, .nss = IO_TAG(SPI3_NSS_PIN), .sck = IO_TAG(SPI3_SCK_PIN), .miso = IO_TAG(SPI3_MISO_PIN), .mosi = IO_TAG(SPI3_MOSI_PIN), .rcc = RCC_APB1L(SPI3), .sckAF = SPI3_SCK_AF, .misoAF = SPI3_MISO_AF, .mosiAF = SPI3_MOSI_AF, .divisorMap = spiDivisorMapSlow },
-#else
- { .dev = SPI3, .nss = IO_TAG(SPI3_NSS_PIN), .sck = IO_TAG(SPI3_SCK_PIN), .miso = IO_TAG(SPI3_MISO_PIN), .mosi = IO_TAG(SPI3_MOSI_PIN), .rcc = RCC_APB1L(SPI3), .sckAF = GPIO_AF6_SPI3, .misoAF = GPIO_AF6_SPI3, .mosiAF = GPIO_AF6_SPI3, .divisorMap = spiDivisorMapSlow },
-#endif
#else
{ .dev = NULL }, // No SPI3
#endif
#ifdef USE_SPI_DEVICE_4
-#if defined(SPI4_SCK_AF) || defined(SPI4_MISO_AF) || defined(SPI4_MOSI_AF)
-#if !defined(SPI4_SCK_AF) || !defined(SPI4_MISO_AF) || !defined(SPI4_MOSI_AF)
-#error SPI4: SCK, MISO and MOSI AFs should be defined together in target.h!
-#endif
{ .dev = SPI4, .nss = IO_TAG(SPI4_NSS_PIN), .sck = IO_TAG(SPI4_SCK_PIN), .miso = IO_TAG(SPI4_MISO_PIN), .mosi = IO_TAG(SPI4_MOSI_PIN), .rcc = RCC_APB2(SPI4), .sckAF = SPI4_SCK_AF, .misoAF = SPI4_MISO_AF, .mosiAF = SPI4_MOSI_AF, .divisorMap = spiDivisorMapSlow }
-#else
- { .dev = SPI4, .nss = IO_TAG(SPI4_NSS_PIN), .sck = IO_TAG(SPI4_SCK_PIN), .miso = IO_TAG(SPI4_MISO_PIN), .mosi = IO_TAG(SPI4_MOSI_PIN), .rcc = RCC_APB2(SPI4), .sckAF = GPIO_AF5_SPI4, .misoAF = GPIO_AF5_SPI4, .mosiAF = GPIO_AF5_SPI4, .divisorMap = spiDivisorMapSlow }
-#endif
#else
{ .dev = NULL } // No SPI4
#endif
};
-#else
-static spiDevice_t spiHardwareMap[] = {
+#elif defined(STM32F7)
+#include "bus_spi_stm32f7xx.h"
+
+// Auto-resolve SPI AF per pin from the lookup table in bus_spi_stm32f7xx.h.
+// Targets may still define individual SPI*_SCK/MISO/MOSI_AF values in target.h
+// to override; explicit defines take priority via these #ifndef guards.
#ifdef USE_SPI_DEVICE_1
-#if defined(SPI1_SCK_AF) || defined(SPI1_MISO_AF) || defined(SPI1_MOSI_AF)
-#if !defined(SPI1_SCK_AF) || !defined(SPI1_MISO_AF) || !defined(SPI1_MOSI_AF)
-#error SPI1: SCK, MISO and MOSI AFs should be defined together in target.h!
+#ifndef SPI1_SCK_AF
+#define SPI1_SCK_AF SPI_PIN_AF_HELPER(1, SPI1_SCK_PIN)
#endif
- { .dev = SPI1, .nss = IO_TAG(SPI1_NSS_PIN), .sck = IO_TAG(SPI1_SCK_PIN), .miso = IO_TAG(SPI1_MISO_PIN), .mosi = IO_TAG(SPI1_MOSI_PIN), .rcc = RCC_APB2(SPI1), .sckAF = SPI1_SCK_AF, .misoAF = SPI1_MISO_AF, .mosiAF = SPI1_MOSI_AF, .divisorMap = spiDivisorMapFast },
-#else
- { .dev = SPI1, .nss = IO_TAG(SPI1_NSS_PIN), .sck = IO_TAG(SPI1_SCK_PIN), .miso = IO_TAG(SPI1_MISO_PIN), .mosi = IO_TAG(SPI1_MOSI_PIN), .rcc = RCC_APB2(SPI1), .sckAF = GPIO_AF5_SPI1, .misoAF = GPIO_AF5_SPI1, .mosiAF = GPIO_AF5_SPI1, .divisorMap = spiDivisorMapFast },
+#ifndef SPI1_MISO_AF
+#define SPI1_MISO_AF SPI_PIN_AF_HELPER(1, SPI1_MISO_PIN)
+#endif
+#ifndef SPI1_MOSI_AF
+#define SPI1_MOSI_AF SPI_PIN_AF_HELPER(1, SPI1_MOSI_PIN)
#endif
-#else
- { .dev = NULL }, // No SPI1
#endif
#ifdef USE_SPI_DEVICE_2
-#if defined(SPI2_SCK_AF) || defined(SPI2_MISO_AF) || defined(SPI2_MOSI_AF)
-#if !defined(SPI2_SCK_AF) || !defined(SPI2_MISO_AF) || !defined(SPI2_MOSI_AF)
-#error SPI2: SCK, MISO and MOSI AFs should be defined together in target.h!
+#ifndef SPI2_SCK_AF
+#define SPI2_SCK_AF SPI_PIN_AF_HELPER(2, SPI2_SCK_PIN)
#endif
- { .dev = SPI2, .nss = IO_TAG(SPI2_NSS_PIN), .sck = IO_TAG(SPI2_SCK_PIN), .miso = IO_TAG(SPI2_MISO_PIN), .mosi = IO_TAG(SPI2_MOSI_PIN), .rcc = RCC_APB1(SPI2), .sckAF = SPI2_SCK_AF, .misoAF = SPI2_MISO_AF, .mosiAF = SPI2_MOSI_AF, .divisorMap = spiDivisorMapSlow },
+#ifndef SPI2_MISO_AF
+#define SPI2_MISO_AF SPI_PIN_AF_HELPER(2, SPI2_MISO_PIN)
+#endif
+#ifndef SPI2_MOSI_AF
+#define SPI2_MOSI_AF SPI_PIN_AF_HELPER(2, SPI2_MOSI_PIN)
+#endif
+#endif
+
+#ifdef USE_SPI_DEVICE_3
+#ifndef SPI3_SCK_AF
+#define SPI3_SCK_AF SPI_PIN_AF_HELPER(3, SPI3_SCK_PIN)
+#endif
+#ifndef SPI3_MISO_AF
+#define SPI3_MISO_AF SPI_PIN_AF_HELPER(3, SPI3_MISO_PIN)
+#endif
+#ifndef SPI3_MOSI_AF
+#define SPI3_MOSI_AF SPI_PIN_AF_HELPER(3, SPI3_MOSI_PIN)
+#endif
+#endif
+
+#ifdef USE_SPI_DEVICE_4
+#ifndef SPI4_SCK_AF
+#define SPI4_SCK_AF SPI_PIN_AF_HELPER(4, SPI4_SCK_PIN)
+#endif
+#ifndef SPI4_MISO_AF
+#define SPI4_MISO_AF SPI_PIN_AF_HELPER(4, SPI4_MISO_PIN)
+#endif
+#ifndef SPI4_MOSI_AF
+#define SPI4_MOSI_AF SPI_PIN_AF_HELPER(4, SPI4_MOSI_PIN)
+#endif
+#endif
+
+static spiDevice_t spiHardwareMap[] = {
+#ifdef USE_SPI_DEVICE_1
+ { .dev = SPI1, .nss = IO_TAG(SPI1_NSS_PIN), .sck = IO_TAG(SPI1_SCK_PIN), .miso = IO_TAG(SPI1_MISO_PIN), .mosi = IO_TAG(SPI1_MOSI_PIN), .rcc = RCC_APB2(SPI1), .sckAF = SPI1_SCK_AF, .misoAF = SPI1_MISO_AF, .mosiAF = SPI1_MOSI_AF, .divisorMap = spiDivisorMapFast },
#else
- { .dev = SPI2, .nss = IO_TAG(SPI2_NSS_PIN), .sck = IO_TAG(SPI2_SCK_PIN), .miso = IO_TAG(SPI2_MISO_PIN), .mosi = IO_TAG(SPI2_MOSI_PIN), .rcc = RCC_APB1(SPI2), .sckAF = GPIO_AF5_SPI2, .misoAF = GPIO_AF5_SPI2, .mosiAF = GPIO_AF5_SPI2, .divisorMap = spiDivisorMapSlow },
+ { .dev = NULL }, // No SPI1
#endif
+
+#ifdef USE_SPI_DEVICE_2
+ { .dev = SPI2, .nss = IO_TAG(SPI2_NSS_PIN), .sck = IO_TAG(SPI2_SCK_PIN), .miso = IO_TAG(SPI2_MISO_PIN), .mosi = IO_TAG(SPI2_MOSI_PIN), .rcc = RCC_APB1(SPI2), .sckAF = SPI2_SCK_AF, .misoAF = SPI2_MISO_AF, .mosiAF = SPI2_MOSI_AF, .divisorMap = spiDivisorMapSlow },
#else
{ .dev = NULL }, // No SPI2
#endif
#ifdef USE_SPI_DEVICE_3
-#if defined(SPI3_SCK_AF) || defined(SPI3_MISO_AF) || defined(SPI3_MOSI_AF)
-#if !defined(SPI3_SCK_AF) || !defined(SPI3_MISO_AF) || !defined(SPI3_MOSI_AF)
-#error SPI3: SCK, MISO and MOSI AFs should be defined together in target.h!
-#endif
{ .dev = SPI3, .nss = IO_TAG(SPI3_NSS_PIN), .sck = IO_TAG(SPI3_SCK_PIN), .miso = IO_TAG(SPI3_MISO_PIN), .mosi = IO_TAG(SPI3_MOSI_PIN), .rcc = RCC_APB1(SPI3), .sckAF = SPI3_SCK_AF, .misoAF = SPI3_MISO_AF, .mosiAF = SPI3_MOSI_AF, .divisorMap = spiDivisorMapSlow },
-#else
- { .dev = SPI3, .nss = IO_TAG(SPI3_NSS_PIN), .sck = IO_TAG(SPI3_SCK_PIN), .miso = IO_TAG(SPI3_MISO_PIN), .mosi = IO_TAG(SPI3_MOSI_PIN), .rcc = RCC_APB1(SPI3), .sckAF = GPIO_AF6_SPI3, .misoAF = GPIO_AF6_SPI3, .mosiAF = GPIO_AF6_SPI3, .divisorMap = spiDivisorMapSlow },
-#endif
#else
{ .dev = NULL }, // No SPI3
#endif
#ifdef USE_SPI_DEVICE_4
-#if defined(SPI4_SCK_AF) || defined(SPI4_MISO_AF) || defined(SPI4_MOSI_AF)
-#if !defined(SPI4_SCK_AF) || !defined(SPI4_MISO_AF) || !defined(SPI4_MOSI_AF)
-#error SPI3: SCK, MISO and MOSI AFs should be defined together in target.h!
-#endif
{ .dev = SPI4, .nss = IO_TAG(SPI4_NSS_PIN), .sck = IO_TAG(SPI4_SCK_PIN), .miso = IO_TAG(SPI4_MISO_PIN), .mosi = IO_TAG(SPI4_MOSI_PIN), .rcc = RCC_APB2(SPI4), .sckAF = SPI4_SCK_AF, .misoAF = SPI4_MISO_AF, .mosiAF = SPI4_MOSI_AF, .divisorMap = spiDivisorMapSlow }
-#else
- { .dev = SPI4, .nss = IO_TAG(SPI4_NSS_PIN), .sck = IO_TAG(SPI4_SCK_PIN), .miso = IO_TAG(SPI4_MISO_PIN), .mosi = IO_TAG(SPI4_MOSI_PIN), .rcc = RCC_APB2(SPI4), .sckAF = GPIO_AF5_SPI4, .misoAF = GPIO_AF5_SPI4, .mosiAF = GPIO_AF5_SPI4, .divisorMap = spiDivisorMapSlow }
-#endif
#else
{ .dev = NULL } // No SPI4
#endif
diff --git a/src/main/drivers/bus_spi_stm32f7xx.h b/src/main/drivers/bus_spi_stm32f7xx.h
new file mode 100644
index 00000000000..a43938e1e45
--- /dev/null
+++ b/src/main/drivers/bus_spi_stm32f7xx.h
@@ -0,0 +1,80 @@
+/*
+ * 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 .
+ */
+
+/*
+ * STM32F7 SPI pin alternate function lookup table.
+ *
+ * Usage: SPI_PIN_AF_HELPER(3, PB5) expands to SPI_PIN_AF_SPI3_PB5,
+ * which is defined below as GPIO_AF6_SPI3.
+ *
+ * AF assignments from STM32F722 datasheet (DS11853) and STM32F745 datasheet
+ * (DS10916), Table 9.
+ *
+ * NOTE: The F7 AF table differs from the H7 for SPI3/PB5:
+ * On F7, PB5 SPI3_MOSI is AF6 (the default).
+ * On H7, PB5 SPI3_MOSI is AF7 (an exception — see bus_spi_stm32h7xx.h).
+ *
+ * SPI1, SPI2, SPI4 pins are all AF5 with no exceptions.
+ * SPI3 SCK/MISO are AF6. SPI3 MOSI has pin-dependent exceptions:
+ * PB2 uses AF7 (not AF6). PD6 uses AF5 (not AF6). PC12 and PB5 use AF6.
+ */
+
+#pragma once
+
+#include "common/utils.h"
+
+// Resolves to SPI_PIN_AF_SPIn_Pxy, defined below for each valid pin.
+// If a pin is not in the table the build will fail with "undefined identifier",
+// which is preferable to silently applying the wrong AF.
+#define SPI_PIN_AF_HELPER(spi, pin) CONCAT4(SPI_PIN_AF_SPI, spi, _, pin)
+
+/* SPI1 — all data pins use AF5 */
+#define SPI_PIN_AF_SPI1_PA5 GPIO_AF5_SPI1 // SCK
+#define SPI_PIN_AF_SPI1_PA6 GPIO_AF5_SPI1 // MISO
+#define SPI_PIN_AF_SPI1_PA7 GPIO_AF5_SPI1 // MOSI
+#define SPI_PIN_AF_SPI1_PB3 GPIO_AF5_SPI1 // SCK
+#define SPI_PIN_AF_SPI1_PB4 GPIO_AF5_SPI1 // MISO
+#define SPI_PIN_AF_SPI1_PB5 GPIO_AF5_SPI1 // MOSI
+
+/* SPI2 — all data pins use AF5 */
+#define SPI_PIN_AF_SPI2_PB13 GPIO_AF5_SPI2 // SCK
+#define SPI_PIN_AF_SPI2_PB14 GPIO_AF5_SPI2 // MISO
+#define SPI_PIN_AF_SPI2_PB15 GPIO_AF5_SPI2 // MOSI
+#define SPI_PIN_AF_SPI2_PC1 GPIO_AF5_SPI2 // MOSI
+#define SPI_PIN_AF_SPI2_PC2 GPIO_AF5_SPI2 // MISO
+#define SPI_PIN_AF_SPI2_PC3 GPIO_AF5_SPI2 // MOSI
+
+/*
+ * SPI3 — SCK and MISO use AF6, but MOSI has pin-dependent exceptions.
+ * PB2 carries SPI3_MOSI on AF7 (not AF6). PD6 uses AF5. PB5 and PC12 use AF6.
+ */
+#define SPI_PIN_AF_SPI3_PB2 GPIO_AF7_SPI3 // MOSI — exception: AF7, not AF6
+#define SPI_PIN_AF_SPI3_PB3 GPIO_AF6_SPI3 // SCK
+#define SPI_PIN_AF_SPI3_PB4 GPIO_AF6_SPI3 // MISO
+#define SPI_PIN_AF_SPI3_PB5 GPIO_AF6_SPI3 // MOSI (AF6 on F7; H7 uses AF7 for this pin)
+#define SPI_PIN_AF_SPI3_PC10 GPIO_AF6_SPI3 // SCK
+#define SPI_PIN_AF_SPI3_PC11 GPIO_AF6_SPI3 // MISO
+#define SPI_PIN_AF_SPI3_PC12 GPIO_AF6_SPI3 // MOSI
+#define SPI_PIN_AF_SPI3_PD6 GPIO_AF5_SPI3 // MOSI — exception: AF5, not AF6
+
+/* SPI4 — all data pins use AF5 */
+#define SPI_PIN_AF_SPI4_PE2 GPIO_AF5_SPI4 // SCK
+#define SPI_PIN_AF_SPI4_PE5 GPIO_AF5_SPI4 // MISO
+#define SPI_PIN_AF_SPI4_PE6 GPIO_AF5_SPI4 // MOSI
+#define SPI_PIN_AF_SPI4_PE12 GPIO_AF5_SPI4 // SCK
+#define SPI_PIN_AF_SPI4_PE13 GPIO_AF5_SPI4 // MISO
+#define SPI_PIN_AF_SPI4_PE14 GPIO_AF5_SPI4 // MOSI
diff --git a/src/main/drivers/bus_spi_stm32h7xx.h b/src/main/drivers/bus_spi_stm32h7xx.h
new file mode 100644
index 00000000000..286e5859816
--- /dev/null
+++ b/src/main/drivers/bus_spi_stm32h7xx.h
@@ -0,0 +1,81 @@
+/*
+ * 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 .
+ */
+
+/*
+ * STM32H7 SPI pin alternate function lookup table.
+ *
+ * Usage: SPI_PIN_AF_HELPER(3, PB5) expands to SPI_PIN_AF_SPI3_PB5,
+ * which is defined below as GPIO_AF7_SPI3.
+ *
+ * This allows bus_spi_hal_ll.c to resolve the correct AF per pin automatically,
+ * without requiring each target to define SPI*_SCK_AF / SPI*_MISO_AF / SPI*_MOSI_AF
+ * manually in target.h. Targets may still override individual values if needed.
+ *
+ * Alternate function assignments are from the STM32H743 datasheet (DS12110),
+ * Tables 10-14.
+ */
+
+#pragma once
+
+#include "common/utils.h"
+
+// Resolves to SPI_PIN_AF_SPIn_Pxy, which is defined below for each valid pin.
+// If a pin is not in the table the build will fail with "undefined identifier",
+// which is preferable to silently applying the wrong AF.
+#define SPI_PIN_AF_HELPER(spi, pin) CONCAT4(SPI_PIN_AF_SPI, spi, _, pin)
+
+/* SPI1 — all data pins use AF5 */
+#define SPI_PIN_AF_SPI1_PA5 GPIO_AF5_SPI1 // SCK
+#define SPI_PIN_AF_SPI1_PA6 GPIO_AF5_SPI1 // MISO
+#define SPI_PIN_AF_SPI1_PA7 GPIO_AF5_SPI1 // MOSI
+#define SPI_PIN_AF_SPI1_PB3 GPIO_AF5_SPI1 // SCK
+#define SPI_PIN_AF_SPI1_PB4 GPIO_AF5_SPI1 // MISO
+#define SPI_PIN_AF_SPI1_PB5 GPIO_AF5_SPI1 // MOSI
+#define SPI_PIN_AF_SPI1_PD7 GPIO_AF5_SPI1 // MOSI
+
+/* SPI2 — all data pins use AF5 */
+#define SPI_PIN_AF_SPI2_PA9 GPIO_AF5_SPI2 // SCK
+#define SPI_PIN_AF_SPI2_PB10 GPIO_AF5_SPI2 // SCK
+#define SPI_PIN_AF_SPI2_PB13 GPIO_AF5_SPI2 // SCK
+#define SPI_PIN_AF_SPI2_PB14 GPIO_AF5_SPI2 // MISO
+#define SPI_PIN_AF_SPI2_PB15 GPIO_AF5_SPI2 // MOSI
+#define SPI_PIN_AF_SPI2_PC1 GPIO_AF5_SPI2 // MOSI
+#define SPI_PIN_AF_SPI2_PC2 GPIO_AF5_SPI2 // MISO
+#define SPI_PIN_AF_SPI2_PC3 GPIO_AF5_SPI2 // MOSI
+#define SPI_PIN_AF_SPI2_PD3 GPIO_AF5_SPI2 // SCK
+
+/*
+ * SPI3 — SCK and MISO use AF6, but MOSI has pin-dependent exceptions.
+ * PB2 and PB5 carry SPI3_MOSI on AF7 (not AF6). PD6 uses AF5.
+ * This is the only SPI bus on STM32H743 where a single-AF fallback is wrong.
+ */
+#define SPI_PIN_AF_SPI3_PB2 GPIO_AF7_SPI3 // MOSI — exception: AF7, not AF6
+#define SPI_PIN_AF_SPI3_PB3 GPIO_AF6_SPI3 // SCK
+#define SPI_PIN_AF_SPI3_PB4 GPIO_AF6_SPI3 // MISO
+#define SPI_PIN_AF_SPI3_PB5 GPIO_AF7_SPI3 // MOSI — exception: AF7, not AF6
+#define SPI_PIN_AF_SPI3_PC10 GPIO_AF6_SPI3 // SCK
+#define SPI_PIN_AF_SPI3_PC11 GPIO_AF6_SPI3 // MISO
+#define SPI_PIN_AF_SPI3_PC12 GPIO_AF6_SPI3 // MOSI
+#define SPI_PIN_AF_SPI3_PD6 GPIO_AF5_SPI3 // MOSI — exception: AF5, not AF6
+
+/* SPI4 — all data pins use AF5 */
+#define SPI_PIN_AF_SPI4_PE2 GPIO_AF5_SPI4 // SCK
+#define SPI_PIN_AF_SPI4_PE5 GPIO_AF5_SPI4 // MISO
+#define SPI_PIN_AF_SPI4_PE6 GPIO_AF5_SPI4 // MOSI
+#define SPI_PIN_AF_SPI4_PE12 GPIO_AF5_SPI4 // SCK
+#define SPI_PIN_AF_SPI4_PE13 GPIO_AF5_SPI4 // MISO
+#define SPI_PIN_AF_SPI4_PE14 GPIO_AF5_SPI4 // MOSI
diff --git a/src/main/drivers/pwm_mapping.c b/src/main/drivers/pwm_mapping.c
index 2d01127a504..120b3d4fc91 100644
--- a/src/main/drivers/pwm_mapping.c
+++ b/src/main/drivers/pwm_mapping.c
@@ -270,43 +270,23 @@ uint8_t pwmClaimTimer(HAL_Timer_t *tim, uint32_t usageFlags) {
return changed;
}
-void pwmEnsureEnoughtMotors(uint8_t motorCount)
+static void pwmAssignOutput(timMotorServoHardware_t *timOutputs, timerHardware_t *timHw, int type)
{
- uint8_t motorOnlyOutputs = 0;
-
- for (int idx = 0; idx < timerHardwareCount; idx++) {
- timerHardware_t *timHw = &timerHardware[idx];
-
- timerHardwareOverride(timHw);
-
- if (checkPwmTimerConflicts(timHw)) {
- continue;
- }
-
- if (TIM_IS_MOTOR_ONLY(timHw->usageFlags)) {
- motorOnlyOutputs++;
- motorOnlyOutputs += pwmClaimTimer(timHw->tim, timHw->usageFlags);
- }
- }
-
- for (int idx = 0; idx < timerHardwareCount; idx++) {
- timerHardware_t *timHw = &timerHardware[idx];
-
- if (checkPwmTimerConflicts(timHw)) {
- continue;
- }
-
- if (TIM_IS_MOTOR(timHw->usageFlags) && !TIM_IS_MOTOR_ONLY(timHw->usageFlags)) {
- if (motorOnlyOutputs < motorCount) {
- timHw->usageFlags &= ~TIM_USE_SERVO;
- timHw->usageFlags |= TIM_USE_MOTOR;
- motorOnlyOutputs++;
- motorOnlyOutputs += pwmClaimTimer(timHw->tim, timHw->usageFlags);
- } else {
- timHw->usageFlags &= ~TIM_USE_MOTOR;
- pwmClaimTimer(timHw->tim, timHw->usageFlags);
- }
- }
+ switch (type) {
+ case MAP_TO_MOTOR_OUTPUT:
+ timHw->usageFlags &= TIM_USE_MOTOR;
+ timOutputs->timMotors[timOutputs->maxTimMotorCount++] = timHw;
+ pwmClaimTimer(timHw->tim, timHw->usageFlags);
+ break;
+ case MAP_TO_SERVO_OUTPUT:
+ timHw->usageFlags &= TIM_USE_SERVO;
+ timOutputs->timServos[timOutputs->maxTimServoCount++] = timHw;
+ pwmClaimTimer(timHw->tim, timHw->usageFlags);
+ break;
+ case MAP_TO_LED_OUTPUT:
+ timHw->usageFlags &= TIM_USE_LED;
+ pwmClaimTimer(timHw->tim, timHw->usageFlags);
+ break;
}
}
@@ -316,54 +296,54 @@ void pwmBuildTimerOutputList(timMotorServoHardware_t * timOutputs, bool isMixerU
timOutputs->maxTimMotorCount = 0;
timOutputs->maxTimServoCount = 0;
- uint8_t motorCount = getMotorCount();
- uint8_t motorIdx = 0;
-
- pwmEnsureEnoughtMotors(motorCount);
+ const uint8_t motorCount = getMotorCount();
+ // Apply configurator overrides to all timer outputs
for (int idx = 0; idx < timerHardwareCount; idx++) {
- timerHardware_t *timHw = &timerHardware[idx];
+ timerHardwareOverride(&timerHardware[idx]);
+ }
- int type = MAP_TO_NONE;
+ // Assign outputs in priority order: dedicated first, then auto.
+ // Within each pass, array order (S1, S2, ...) is preserved.
+ // Motors and servos cannot share a timer, enforced by pwmHasMotorOnTimer/pwmHasServoOnTimer.
+ for (int priority = 0; priority < 2; priority++) {
+ uint8_t motorIdx = timOutputs->maxTimMotorCount;
- // Check for known conflicts (i.e. UART, LEDSTRIP, Rangefinder and ADC)
- if (checkPwmTimerConflicts(timHw)) {
- LOG_WARNING(PWM, "Timer output %d skipped", idx);
- continue;
- }
+ for (int idx = 0; idx < timerHardwareCount; idx++) {
+ timerHardware_t *timHw = &timerHardware[idx];
+ outputMode_e mode = timerOverrides(timer2id(timHw->tim))->outputMode;
+ bool isDedicated = (priority == 0);
- // Make sure first motorCount motor outputs get assigned to motor
- if (TIM_IS_MOTOR(timHw->usageFlags) && (motorIdx < motorCount)) {
- timHw->usageFlags &= ~TIM_USE_SERVO;
- pwmClaimTimer(timHw->tim, timHw->usageFlags);
- motorIdx += 1;
- }
+ if (checkPwmTimerConflicts(timHw)) {
+ if (priority == 0) {
+ LOG_WARNING(PWM, "Timer output %d skipped", idx);
+ }
+ continue;
+ }
- if (TIM_IS_SERVO(timHw->usageFlags) && !pwmHasMotorOnTimer(timOutputs, timHw->tim)) {
- type = MAP_TO_SERVO_OUTPUT;
- } else if (TIM_IS_MOTOR(timHw->usageFlags) && !pwmHasServoOnTimer(timOutputs, timHw->tim)) {
- type = MAP_TO_MOTOR_OUTPUT;
- } else if (TIM_IS_LED(timHw->usageFlags) && !pwmHasMotorOnTimer(timOutputs, timHw->tim) && !pwmHasServoOnTimer(timOutputs, timHw->tim)) {
- type = MAP_TO_LED_OUTPUT;
- }
+ // Motors: dedicated (OUTPUT_MODE_MOTORS) first, then auto
+ if (TIM_IS_MOTOR(timHw->usageFlags) && motorIdx < motorCount
+ && !pwmHasServoOnTimer(timOutputs, timHw->tim)
+ && (isDedicated ? mode == OUTPUT_MODE_MOTORS : mode != OUTPUT_MODE_MOTORS)) {
+ pwmAssignOutput(timOutputs, timHw, MAP_TO_MOTOR_OUTPUT);
+ motorIdx++;
+ continue;
+ }
+
+ // Servos: dedicated (OUTPUT_MODE_SERVOS) first, then auto
+ if (TIM_IS_SERVO(timHw->usageFlags)
+ && !pwmHasMotorOnTimer(timOutputs, timHw->tim)
+ && (isDedicated ? mode == OUTPUT_MODE_SERVOS : mode != OUTPUT_MODE_SERVOS)) {
+ pwmAssignOutput(timOutputs, timHw, MAP_TO_SERVO_OUTPUT);
+ continue;
+ }
- switch(type) {
- case MAP_TO_MOTOR_OUTPUT:
- timHw->usageFlags &= TIM_USE_MOTOR;
- timOutputs->timMotors[timOutputs->maxTimMotorCount++] = timHw;
- pwmClaimTimer(timHw->tim, timHw->usageFlags);
- break;
- case MAP_TO_SERVO_OUTPUT:
- timHw->usageFlags &= TIM_USE_SERVO;
- timOutputs->timServos[timOutputs->maxTimServoCount++] = timHw;
- pwmClaimTimer(timHw->tim, timHw->usageFlags);
- break;
- case MAP_TO_LED_OUTPUT:
- timHw->usageFlags &= TIM_USE_LED;
- pwmClaimTimer(timHw->tim, timHw->usageFlags);
- break;
- default:
- break;
+ // LEDs: only on the auto pass, and only if timer is uncontested
+ if (!isDedicated && TIM_IS_LED(timHw->usageFlags)
+ && !pwmHasMotorOnTimer(timOutputs, timHw->tim)
+ && !pwmHasServoOnTimer(timOutputs, timHw->tim)) {
+ pwmAssignOutput(timOutputs, timHw, MAP_TO_LED_OUTPUT);
+ }
}
}
}
diff --git a/src/main/msp/msp_protocol.h b/src/main/msp/msp_protocol.h
index 5a3af115f9c..406cfe28ddf 100644
--- a/src/main/msp/msp_protocol.h
+++ b/src/main/msp/msp_protocol.h
@@ -110,8 +110,8 @@
#define MSP_CALIBRATION_DATA 14
#define MSP_SET_CALIBRATION_DATA 15
-#define MSP_POSITION_ESTIMATION_CONFIG 16
-#define MSP_SET_POSITION_ESTIMATION_CONFIG 17
+#define MSP_POSITION_ESTIMATION_CONFIG 16 //DEPRECATED in INAV 9.1 - use settings system instead. Will be removed in INAV 10.0
+#define MSP_SET_POSITION_ESTIMATION_CONFIG 17 //DEPRECATED in INAV 9.1 - use settings system instead. Will be removed in INAV 10.0
#define MSP_WP_MISSION_LOAD 18 // Load mission from NVRAM
#define MSP_WP_MISSION_SAVE 19 // Save mission to NVRAM
@@ -183,14 +183,14 @@
#define MSP_SDCARD_SUMMARY 79 //out message Get the state of the SD card
-#define MSP_BLACKBOX_CONFIG 80 //out message Get blackbox settings
-#define MSP_SET_BLACKBOX_CONFIG 81 //in message Set blackbox settings
+#define MSP_BLACKBOX_CONFIG 80 //DEPRECATED in INAV 9.1, use MSP2_BLACKBOX_CONFIG. Will be removed in INAV 10.0
+#define MSP_SET_BLACKBOX_CONFIG 81 //DEPRECATED in INAV 9.1, use MSP2_SET_BLACKBOX_CONFIG. Will be removed in INAV 10.0
#define MSP_TRANSPONDER_CONFIG 82 //out message Get transponder settings
#define MSP_SET_TRANSPONDER_CONFIG 83 //in message Set transponder settings
-#define MSP_OSD_CONFIG 84 //out message Get osd settings - betaflight
-#define MSP_SET_OSD_CONFIG 85 //in message Set osd settings - betaflight
+#define MSP_OSD_CONFIG 84 //DEPRECATED in INAV 9.1 - use MSP2_INAV_OSD_* instead. Will be removed in INAV 10.0
+#define MSP_SET_OSD_CONFIG 85 //DEPRECATED in INAV 9.1 - use MSP2_INAV_OSD_* instead. Will be removed in INAV 10.0
#define MSP_OSD_CHAR_READ 86 //out message Get osd settings - betaflight
#define MSP_OSD_CHAR_WRITE 87 //in message Set osd settings - betaflight
@@ -202,10 +202,10 @@
#define MSP_ADVANCED_CONFIG 90
#define MSP_SET_ADVANCED_CONFIG 91
-#define MSP_FILTER_CONFIG 92
-#define MSP_SET_FILTER_CONFIG 93
-#define MSP_PID_ADVANCED 94
-#define MSP_SET_PID_ADVANCED 95
+#define MSP_FILTER_CONFIG 92 //DEPRECATED in INAV 9.1 - use settings system instead. Will be removed in INAV 10.0
+#define MSP_SET_FILTER_CONFIG 93 //DEPRECATED in INAV 9.1 - use settings system instead. Will be removed in INAV 10.0
+#define MSP_PID_ADVANCED 94 //DEPRECATED in INAV 9.1 - use MSP_INAV_PID instead. Will be removed in INAV 10.0
+#define MSP_SET_PID_ADVANCED 95 //DEPRECATED in INAV 9.1 - use MSP_SET_INAV_PID instead. Will be removed in INAV 10.0
#define MSP_SENSOR_CONFIG 96
#define MSP_SET_SENSOR_CONFIG 97
@@ -231,7 +231,7 @@
// Multwii original MSP commands
//
-#define MSP_STATUS 101 //out message cycletime & errors_count & sensor present & box activation & current setting number
+#define MSP_STATUS 101 //DEPRECATED in INAV 9.1, use MSP2_INAV_STATUS. Will be removed in INAV 10.0
#define MSP_RAW_IMU 102 //out message 9 DOF
#define MSP_SERVO 103 //out message servos
#define MSP_MOTOR 104 //out message motors
@@ -240,12 +240,12 @@
#define MSP_COMP_GPS 107 //out message distance home, direction home
#define MSP_ATTITUDE 108 //out message 2 angles 1 heading
#define MSP_ALTITUDE 109 //out message altitude, variometer
-#define MSP_ANALOG 110 //out message vbat, powermetersum, rssi if available on RX
+#define MSP_ANALOG 110 //DEPRECATED in INAV 9.1 - use MSP2_INAV_ANALOG instead. Will be removed in INAV 10.0
#define MSP_RC_TUNING 111 //out message rc rate, rc expo, rollpitch rate, yaw rate, dyn throttle PID
#define MSP_ACTIVEBOXES 113 //out message Active box flags (full width, more than 32 bits)
-#define MSP_MISC 114 //out message powermeter trig
+#define MSP_MISC 114 //DEPRECATED in INAV 9.1 - use MSP2_INAV_MISC instead. Will be removed in INAV 10.0
#define MSP_BOXNAMES 116 //out message the aux switch names
-#define MSP_PIDNAMES 117 //out message the PID names
+#define MSP_PIDNAMES 117 //DEPRECATED in INAV 9.1 - no replacement needed (static data). Will be removed in INAV 10.0
#define MSP_WP 118 //out message get a WP, WP# is in the payload, returns (WP#, lat, lon, alt, flags) WP#0-home, WP#16-poshold
#define MSP_BOXIDS 119 //out message get the permanent IDs associated to BOXes
#define MSP_SERVO_CONFIGURATIONS 120 //out message All servo configurations.
@@ -263,7 +263,7 @@
#define MSP_SET_RC_TUNING 204 //in message rc rate, rc expo, rollpitch rate, yaw rate, dyn throttle PID, yaw expo
#define MSP_ACC_CALIBRATION 205 //in message no param
#define MSP_MAG_CALIBRATION 206 //in message no param
-#define MSP_SET_MISC 207 //in message powermeter trig + 8 free for future use
+#define MSP_SET_MISC 207 //DEPRECATED in INAV 9.1 - use MSP2_INAV_SET_MISC instead. Will be removed in INAV 10.0
#define MSP_RESET_CONF 208 //in message no param
#define MSP_SET_WP 209 //in message sets a given WP (WP#,lat, lon, alt, flags)
#define MSP_SELECT_SETTING 210 //in message Select Setting Number (0-2)
@@ -284,19 +284,19 @@
#define MSP_RESERVE_1 251 //reserved for system usage
#define MSP_RESERVE_2 252 //reserved for system usage
#define MSP_DEBUGMSG 253 //out message debug string buffer
-#define MSP_DEBUG 254 //out message debug1,debug2,debug3,debug4
+#define MSP_DEBUG 254 //DEPRECATED in INAV 9.1, use MSP2_INAV_DEBUG. Will be removed in INAV 10.0
#define MSP_V2_FRAME 255 //MSPv2 payload indicator
// Additional commands that are not compatible with MultiWii
-#define MSP_STATUS_EX 150 //out message cycletime, errors_count, CPU load, sensor present etc
+#define MSP_STATUS_EX 150 //DEPRECATED in INAV 9.1, use MSP2_INAV_STATUS (accCalibAxisFlags available via MSP_CALIBRATION_DATA). Will be removed in INAV 10.0
#define MSP_SENSOR_STATUS 151 //out message Hardware sensor status
#define MSP_UID 160 //out message Unique device ID
#define MSP_GPSSVINFO 164 //out message get Signal Strength (only U-Blox)
#define MSP_GPSSTATISTICS 166 //out message get GPS debugging data
#define MSP_ACC_TRIM 240 //out message get acc angle trim values
#define MSP_SET_ACC_TRIM 239 //in message set acc angle trim values
-#define MSP_SERVO_MIX_RULES 241 //out message Returns servo mixer configuration
-#define MSP_SET_SERVO_MIX_RULE 242 //in message Sets servo mixer configuration
+#define MSP_SERVO_MIX_RULES 241 //DEPRECATED in INAV 9.1 - use MSP2_INAV_SERVO_MIXER instead. Will be removed in INAV 10.0
+#define MSP_SET_SERVO_MIX_RULE 242 //DEPRECATED in INAV 9.1 - use MSP2_INAV_SET_SERVO_MIXER instead. Will be removed in INAV 10.0
#define MSP_SET_PASSTHROUGH 245 //in message Sets up passthrough to different peripherals (4way interface, uart, etc...)
#define MSP_RTC 246 //out message Gets the RTC clock (returns: secs(i32) millis(u16) - (0,0) if time is not known)
#define MSP_SET_RTC 247 //in message Sets the RTC clock (args: secs(i32) millis(u16))
diff --git a/src/main/target/HAKRCH743/CMakeLists.txt b/src/main/target/HAKRCH743/CMakeLists.txt
new file mode 100644
index 00000000000..eb70a0acdca
--- /dev/null
+++ b/src/main/target/HAKRCH743/CMakeLists.txt
@@ -0,0 +1 @@
+target_stm32h743xi(HAKRCH743)
diff --git a/src/main/target/HAKRCH743/config.c b/src/main/target/HAKRCH743/config.c
new file mode 100644
index 00000000000..b963bfbfa59
--- /dev/null
+++ b/src/main/target/HAKRCH743/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
+
+#include "fc/fc_msp_box.h"
+#include "io/piniobox.h"
+
+void targetConfiguration(void)
+{
+ pinioBoxConfigMutable()->permanentId[0] = BOX_PERMANENT_ID_USER1;
+ pinioBoxConfigMutable()->permanentId[1] = BOX_PERMANENT_ID_USER2;
+}
diff --git a/src/main/target/HAKRCH743/target.c b/src/main/target/HAKRCH743/target.c
new file mode 100644
index 00000000000..047eeeebd70
--- /dev/null
+++ b/src/main/target/HAKRCH743/target.c
@@ -0,0 +1,50 @@
+/*
+ * 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/bus.h"
+#include "drivers/io.h"
+#include "drivers/pwm_mapping.h"
+#include "drivers/timer.h"
+#include "drivers/pinio.h"
+#include "drivers/sensor.h"
+
+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, 1, DEVFLAGS_NONE, IMU_ICM42688_1_ALIGN);
+
+timerHardware_t timerHardware[] = {
+ DEF_TIM(TIM5, CH1, PA0, TIM_USE_OUTPUT_AUTO, 0, 0), // S1
+ DEF_TIM(TIM5, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 1), // S2
+ DEF_TIM(TIM5, CH3, PA2, TIM_USE_OUTPUT_AUTO, 0, 2), // S3
+ DEF_TIM(TIM5, CH4, PA3, TIM_USE_OUTPUT_AUTO, 0, 3), // S4
+
+ DEF_TIM(TIM4, CH1, PD12, TIM_USE_OUTPUT_AUTO, 0, 4), // S5
+ DEF_TIM(TIM4, CH2, PD13, TIM_USE_OUTPUT_AUTO, 0, 5), // S6
+ DEF_TIM(TIM4, CH3, PD14, TIM_USE_OUTPUT_AUTO, 0, 6), // S7
+ DEF_TIM(TIM4, CH4, PD15, TIM_USE_OUTPUT_AUTO, 0, 7), // S8
+
+ DEF_TIM(TIM15, CH1, PE5, TIM_USE_OUTPUT_AUTO, 0, 0), // S9
+ DEF_TIM(TIM15, CH2, PE6, TIM_USE_OUTPUT_AUTO, 0, 0), // S10
+ DEF_TIM(TIM3, CH3, PB0, TIM_USE_OUTPUT_AUTO, 0, 0), // S11
+ DEF_TIM(TIM3, CH4, PB1, TIM_USE_OUTPUT_AUTO, 0, 0), // S12
+
+ DEF_TIM(TIM1, CH1, PA8, TIM_USE_LED, 0, 9), // LED_2812
+};
+
+const int timerHardwareCount = sizeof(timerHardware) / sizeof(timerHardware[0]);
diff --git a/src/main/target/HAKRCH743/target.h b/src/main/target/HAKRCH743/target.h
new file mode 100644
index 00000000000..e227fc1fa0b
--- /dev/null
+++ b/src/main/target/HAKRCH743/target.h
@@ -0,0 +1,180 @@
+/*
+ * 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 "HK743"
+#define USBD_PRODUCT_STRING "HAKRCH743"
+
+#define USE_TARGET_CONFIG
+
+#define USE_DSHOT_DMAR
+
+/*** Indicators ***/
+#define LED0 PE3
+#define LED1 PE4
+#define BEEPER PE9
+#define BEEPER_INVERTED
+
+/*** SPI/I2C bus ***/
+#define USE_SPI
+#define USE_SPI_DEVICE_1
+#define SPI1_NSS_PIN PC15
+#define SPI1_SCK_PIN PA5
+#define SPI1_MISO_PIN PA6
+#define SPI1_MOSI_PIN PD7
+
+#define USE_SPI_DEVICE_3
+#define SPI3_NSS_PIN PE2
+#define SPI3_SCK_PIN PB3
+#define SPI3_MISO_PIN PB4
+#define SPI3_MOSI_PIN PB5
+
+#define USE_SPI_DEVICE_4
+#define SPI4_NSS_PIN PC13
+#define SPI4_SCK_PIN PE12
+#define SPI4_MISO_PIN PE13
+#define SPI4_MOSI_PIN PE14
+
+#define USE_I2C
+#define USE_I2C_DEVICE_1
+#define I2C1_SCL PB6
+#define I2C1_SDA PB7
+
+#define USE_I2C_DEVICE_2
+#define I2C2_SCL PB10
+#define I2C2_SDA PB11
+
+/*** IMU sensors ***/
+
+#define USE_DUAL_GYRO
+#define USE_TARGET_IMU_HARDWARE_DESCRIPTORS
+#define USE_SPI
+#define USE_IMU_ICM42605
+
+// IMU0 ICM42688P/ICM42605
+#define ICM42688_0_CS_PIN PC15
+#define ICM42688_0_SPI_BUS BUS_SPI1
+#define IMU_ICM42688_0_ALIGN CW0_DEG
+
+
+// IMU1 ICM42688P/ICM42605
+#define ICM42688_1_CS_PIN PC13
+#define ICM42688_1_SPI_BUS BUS_SPI4
+#define IMU_ICM42688_1_ALIGN CW270_DEG
+
+
+/*** OSD ***/
+#define USE_MAX7456
+#define MAX7456_SPI_BUS BUS_SPI3
+#define MAX7456_CS_PIN PE2
+
+
+// *** PINIO ***
+#define USE_PINIO
+#define USE_PINIOBOX
+#define PINIO1_PIN PD10
+#define PINIO2_PIN PD11
+
+/*** Serial ports ***/
+#define USE_VCP
+
+#define USE_UART1
+#define UART1_RX_PIN PA10
+#define UART1_TX_PIN PA9
+
+#define USE_UART2
+#define UART2_RX_PIN PD6
+#define UART2_TX_PIN PD5
+
+#define USE_UART3
+#define UART3_RX_PIN PD9
+#define UART3_TX_PIN PD8
+
+#define USE_UART4
+#define UART4_RX_PIN PB8
+#define UART4_TX_PIN PB9
+
+#define USE_UART5
+#define UART5_RX_PIN PB12
+#define UART5_TX_PIN PB13
+
+#define USE_UART6
+#define UART6_RX_PIN PC7
+#define UART6_TX_PIN PC6
+
+#define USE_UART7
+#define UART7_RX_PIN PE7
+#define UART7_TX_PIN PE8
+
+#define USE_UART8
+#define UART8_RX_PIN PE0
+#define UART8_TX_PIN PE1
+
+#define SERIAL_PORT_COUNT 9 // VCP, UART1, UART2, UART3, UART4, UART5, UART6, UART7, UART8
+#define DEFAULT_RX_TYPE RX_TYPE_SERIAL
+#define SERIALRX_PROVIDER SERIALRX_SBUS
+#define SERIALRX_UART SERIAL_PORT_USART7
+
+/*** BARO & MAG ***/
+#define USE_BARO
+#define BARO_I2C_BUS BUS_I2C1
+#define USE_BARO_BMP280
+#define USE_BARO_SPL06
+#define USE_BARO_DPS310
+
+#define USE_MAG
+#define MAG_I2C_BUS BUS_I2C2
+#define USE_MAG_ALL
+
+/*** ADC ***/
+#define USE_ADC
+#define ADC_INSTANCE ADC1
+#define ADC_CHANNEL_1_PIN PC0
+#define ADC_CHANNEL_2_PIN PC1
+#define ADC_CHANNEL_3_PIN PC5
+
+#define VBAT_ADC_CHANNEL ADC_CHN_1
+#define CURRENT_METER_ADC_CHANNEL ADC_CHN_2
+#define RSSI_ADC_CHANNEL ADC_CHN_3
+
+/*** LED STRIP ***/
+#define USE_LED_STRIP
+#define WS2811_PIN PA8
+
+// *************** SDIO SD BLACKBOX*******************
+#define USE_SDCARD
+#define USE_SDCARD_SDIO
+#define SDCARD_SDIO_DEVICE SDIODEV_1
+#define SDCARD_SDIO_4BIT
+#define ENABLE_BLACKBOX_LOGGING_ON_SDCARD_BY_DEFAULT
+
+
+#define DEFAULT_FEATURES (FEATURE_OSD | FEATURE_TELEMETRY | FEATURE_CURRENT_METER | FEATURE_VBAT | FEATURE_TX_PROF_SEL | FEATURE_BLACKBOX)
+
+/*** Timer/PWM output ***/
+#define USE_SERIAL_4WAY_BLHELI_INTERFACE
+#define MAX_PWM_OUTPUT_PORTS 12
+#define USE_DSHOT
+#define USE_ESC_SENSOR
+
+/*** Used pins ***/
+#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