From 6b1cd88eff3b68b5472460622bdc86bb13d76298 Mon Sep 17 00:00:00 2001 From: 3djc <5167938+3djc@users.noreply.github.com> Date: Wed, 28 Jan 2026 07:06:06 +0100 Subject: [PATCH] fix(f4): limit CRSF external module speed to 3.75Mbps (#6923) Co-authored-by: elecpower --- companion/src/firmwares/boards.h | 5 ++ .../src/firmwares/edgetx/yaml_modeldata.cpp | 6 ++ companion/src/firmwares/moduledata.cpp | 6 +- companion/src/firmwares/moduledata.h | 2 +- companion/src/modeledit/setup_module.cpp | 9 +- companion/src/modeledit/setup_module.ui | 90 ++++++++++--------- .../colorlcd/module/crossfire_settings.cpp | 2 +- radio/src/storage/storage_common.cpp | 8 ++ radio/src/telemetry/crossfire.h | 6 ++ 9 files changed, 86 insertions(+), 48 deletions(-) diff --git a/companion/src/firmwares/boards.h b/companion/src/firmwares/boards.h index 7d595a2dc..696283837 100644 --- a/companion/src/firmwares/boards.h +++ b/companion/src/firmwares/boards.h @@ -859,3 +859,8 @@ inline bool IS_STM32H7(Board::Type board) IS_JUMPER_T15PRO(board) || IS_RADIOMASTER_TX15(board); } + +inline bool IS_STM32F2F4(Board::Type board) +{ + return (!IS_STM32H5(board) && !IS_STM32H7(board)); +} diff --git a/companion/src/firmwares/edgetx/yaml_modeldata.cpp b/companion/src/firmwares/edgetx/yaml_modeldata.cpp index c1db7a7b4..1c76b52da 100644 --- a/companion/src/firmwares/edgetx/yaml_modeldata.cpp +++ b/companion/src/firmwares/edgetx/yaml_modeldata.cpp @@ -1504,6 +1504,12 @@ bool convert::decode(const Node& node, ModelData& rhs) rhs.moduleData[i].modelId = modelIds[i]; } + // v2.12 CRSF limit external module to 3.75M for older boards + if (IS_STM32F2F4(board) && + rhs.moduleData[1].protocol == PULSES_CROSSFIRE && + rhs.moduleData[1].crsf.telemetryBaudrate > 4) + rhs.moduleData[1].crsf.telemetryBaudrate = 4; + if (node["failsafeChannels"]) { int failsafeChans[CPN_MAX_CHNOUT]; memset(failsafeChans, 0, sizeof(failsafeChans)); diff --git a/companion/src/firmwares/moduledata.cpp b/companion/src/firmwares/moduledata.cpp index 78a5e103c..d8fcf3589 100644 --- a/companion/src/firmwares/moduledata.cpp +++ b/companion/src/firmwares/moduledata.cpp @@ -641,12 +641,16 @@ AbstractStaticItemModel * ModuleData::protocolItemModel(GeneralSettings & settin return mdl; } -AbstractStaticItemModel * ModuleData::telemetryBaudrateItemModel(unsigned int protocol) +AbstractStaticItemModel * ModuleData::telemetryBaudrateItemModel(unsigned int protocol, int moduleIdx, int board) { AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); mdl->setName("moduledata.baudrate"); for (int i = 0; i < moduleBaudratesList.size(); i++) { + // CRSF limit external module to 3.75M for older boards + if (protocol == PULSES_CROSSFIRE && moduleIdx == 1 && + IS_STM32F2F4((Board::Type)board) && i > 4) break; + if (protocol == PULSES_GHOST && i >= 2) break; mdl->appendToItemList(moduleBaudratesList.at(i), i); } diff --git a/companion/src/firmwares/moduledata.h b/companion/src/firmwares/moduledata.h index 0b86f59d3..fea3c14c8 100644 --- a/companion/src/firmwares/moduledata.h +++ b/companion/src/firmwares/moduledata.h @@ -235,7 +235,7 @@ class ModuleData { static AbstractStaticItemModel * internalModuleItemModel(int board = -1); static bool isProtocolAvailable(int moduleidx, unsigned int protocol, GeneralSettings & generalSettings); static AbstractStaticItemModel * protocolItemModel(GeneralSettings & settings); - static AbstractStaticItemModel * telemetryBaudrateItemModel(unsigned int protocol); + static AbstractStaticItemModel * telemetryBaudrateItemModel(unsigned int protocol, int moduleIdx = -1, int board = 0); static bool isAvailable(PulsesProtocol proto, int port = 0); // moved from OpenTxFirmware EdgeTX v2.9 - TODO remove and use isProtocolAvailable QString afhds2aMode1ToString() const; diff --git a/companion/src/modeledit/setup_module.cpp b/companion/src/modeledit/setup_module.cpp index 25ce12bcd..9815ff293 100644 --- a/companion/src/modeledit/setup_module.cpp +++ b/companion/src/modeledit/setup_module.cpp @@ -352,7 +352,7 @@ void ModulePanel::update() case PULSES_CROSSFIRE: mask |= MASK_CHANNELS_RANGE | MASK_RX_NUMBER | MASK_BAUDRATE | MASK_CSRF_ARMING_MODE; module.channelsCount = 16; - ui->telemetryBaudrate->setModel(ModuleData::telemetryBaudrateItemModel(protocol)); + ui->telemetryBaudrate->setModel(ModuleData::telemetryBaudrateItemModel(protocol, moduleIdx, board)); ui->telemetryBaudrate->setField(module.crsf.telemetryBaudrate); ui->crsfArmingMode->setCurrentIndex(module.crsf.crsfArmingMode); if (module.crsf.crsfArmingMode == ModuleData::CRSF_ARMING_MODE_SWITCH) { @@ -428,10 +428,13 @@ void ModulePanel::update() mask |= MASK_PPM_FIELDS | MASK_CHANNELS_RANGE | MASK_CHANNELS_COUNT; } - if (isExternalModule(moduleIdx)) + if (isExternalModule(moduleIdx)) { + ui->label_baudrate->setVisible(mask & MASK_BAUDRATE); ui->telemetryBaudrate->setVisible(mask & MASK_BAUDRATE); - else + } else { + ui->label_baudrate->setVisible(false); ui->telemetryBaudrate->setVisible(false); + } ui->label_protocol->setVisible(mask & MASK_PROTOCOL); ui->protocol->setVisible(mask & MASK_PROTOCOL); diff --git a/companion/src/modeledit/setup_module.ui b/companion/src/modeledit/setup_module.ui index 94cc274b7..afefaf097 100644 --- a/companion/src/modeledit/setup_module.ui +++ b/companion/src/modeledit/setup_module.ui @@ -35,7 +35,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -49,7 +49,6 @@ - 75 true @@ -94,7 +93,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -107,7 +106,7 @@ - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter 6 @@ -127,7 +126,7 @@ Protocol - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -146,14 +145,14 @@ - QComboBox::AdjustToContents + QComboBox::SizeAdjustPolicy::AdjustToContents - QComboBox::AdjustToContents + QComboBox::SizeAdjustPolicy::AdjustToContents @@ -163,7 +162,7 @@ Registration ID - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -183,7 +182,7 @@ Multi Radio Protocol - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -202,7 +201,7 @@ - QComboBox::AdjustToContents + QComboBox::SizeAdjustPolicy::AdjustToContents @@ -228,7 +227,7 @@ - QComboBox::AdjustToContents + QComboBox::SizeAdjustPolicy::AdjustToContents @@ -288,7 +287,7 @@ Failsafe Mode - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -307,7 +306,7 @@ - QComboBox::AdjustToContents + QComboBox::SizeAdjustPolicy::AdjustToContents @@ -348,7 +347,7 @@ Trainer Mode - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -367,7 +366,7 @@ - QComboBox::AdjustToContents + QComboBox::SizeAdjustPolicy::AdjustToContents @@ -402,7 +401,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -446,6 +445,13 @@ + + + + Baudrate + + + @@ -458,7 +464,7 @@ - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter 6 @@ -478,7 +484,7 @@ Start - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -497,7 +503,7 @@ - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -531,7 +537,7 @@ Receiver No. - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -550,7 +556,7 @@ - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -581,7 +587,7 @@ Polarity - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -600,7 +606,7 @@ - QComboBox::AdjustToContents + QComboBox::SizeAdjustPolicy::AdjustToContents @@ -630,7 +636,7 @@ Receiver 1 - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -687,7 +693,7 @@ Receiver 2 - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -723,7 +729,7 @@ Receiver 3 - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -818,7 +824,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -833,7 +839,7 @@ - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter 6 @@ -859,7 +865,7 @@ Channels - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -878,7 +884,7 @@ - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -909,7 +915,7 @@ PPM delay - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -928,7 +934,7 @@ - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter us @@ -959,7 +965,7 @@ PPM Frame Length - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -978,7 +984,7 @@ - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter ms @@ -1012,7 +1018,7 @@ Antenna - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -1031,7 +1037,7 @@ - QComboBox::AdjustToContents + QComboBox::SizeAdjustPolicy::AdjustToContents @@ -1064,7 +1070,7 @@ - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -1084,7 +1090,7 @@ - QComboBox::AdjustToContents + QComboBox::SizeAdjustPolicy::AdjustToContents @@ -1101,7 +1107,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1126,7 +1132,7 @@ - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter Hz @@ -1169,7 +1175,7 @@ - QComboBox::AdjustToContents + QComboBox::SizeAdjustPolicy::AdjustToContents @@ -1200,7 +1206,7 @@ QGroupBox::title { subcontrol-origin: margin; subcontrol-position: top left; pad 4 - + true diff --git a/radio/src/gui/colorlcd/module/crossfire_settings.cpp b/radio/src/gui/colorlcd/module/crossfire_settings.cpp index 0c7110895..faf6be854 100644 --- a/radio/src/gui/colorlcd/module/crossfire_settings.cpp +++ b/radio/src/gui/colorlcd/module/crossfire_settings.cpp @@ -39,7 +39,7 @@ CrossfireSettings::CrossfireSettings(Window* parent, const FlexGridLayout& g, auto line = newLine(grid); new StaticText(line, rect_t{}, STR_BAUDRATE); new Choice( - line, rect_t{}, STR_CRSF_BAUDRATE, 0, CROSSFIRE_MAX_INTERNAL_BAUDRATE, + line, rect_t{}, STR_CRSF_BAUDRATE, 0, CROSSFIRE_MAX_EXTERNAL_BAUDRATE, [=]() -> int { return CROSSFIRE_STORE_TO_INDEX(md->crsf.telemetryBaudrate); }, diff --git a/radio/src/storage/storage_common.cpp b/radio/src/storage/storage_common.cpp index 92cf584cc..a39d894de 100644 --- a/radio/src/storage/storage_common.cpp +++ b/radio/src/storage/storage_common.cpp @@ -211,6 +211,14 @@ if(g_model.rssiSource) { storageDirty(EE_MODEL); } +#if defined(STM32F4) && defined(CROSSFIRE) + // Limit ext. CRSF speed to 3.75Mbps due to CRC errors at higher speeds + if(isModuleCrossfire(EXTERNAL_MODULE) && g_model.moduleData[EXTERNAL_MODULE].crsf.telemetryBaudrate == 4) { + TRACE("Downgrading external ELRS module baudrate"); + g_model.moduleData[EXTERNAL_MODULE].crsf.telemetryBaudrate = 3; + storageDirty(EE_MODEL); + } +#endif #if defined(PXX2) bool changed = false; diff --git a/radio/src/telemetry/crossfire.h b/radio/src/telemetry/crossfire.h index 92d64d2b1..3653d8e83 100644 --- a/radio/src/telemetry/crossfire.h +++ b/radio/src/telemetry/crossfire.h @@ -130,6 +130,12 @@ const uint32_t CROSSFIRE_BAUDRATES[] = { 5250000, }; +#if defined(STM32F4) +#define CROSSFIRE_MAX_EXTERNAL_BAUDRATE DIM(CROSSFIRE_BAUDRATES) - 2 +#else +#define CROSSFIRE_MAX_EXTERNAL_BAUDRATE DIM(CROSSFIRE_BAUDRATES) - 1 +#endif + #if defined(RADIO_TPRO) || defined(RADIO_TPROV2) || defined(RADIO_T20) #define CROSSFIRE_MAX_INTERNAL_BAUDRATE DIM(CROSSFIRE_BAUDRATES) - 3 #else