Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/Serial.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ e.g. after configuring a port for GPS enable the GPS feature.
* All telemetry systems except MSP will ignore any attempts to override the baudrate.
* MSP/CLI can be shared with EITHER Blackbox OR telemetry (LTM or MAVlink, not RX telemetry). In shared mode blackbox or telemetry will be output only when armed.
* Smartport telemetry cannot be shared with MSP.
* SBUS servo output (`SERVO_SERIAL`) can only be assigned to one port. The CLI refuses a second assignment; previously it was accepted and shown in the port list, but the second port was never opened.
* No other serial port sharing combinations are valid.
* You can use as many different telemetry systems as you like at the same time.
* You can only use each telemetry system once. e.g. FrSky telemetry cannot be used on two port, but LTN Telemetry and FrSky on two different ports is fine.
Expand Down
6 changes: 6 additions & 0 deletions src/main/fc/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,12 @@ static void cliSerial(char *cmdline)
return;
}

const uint32_t duplicatedFunctions = serialDuplicatedSinglePortFunctions(&portConfig);
if (duplicatedFunctions) {
cliPrintErrorLinef("Function %d is already assigned to another port", (int)duplicatedFunctions);
return;
}

memcpy(currentConfig, &portConfig, sizeof(portConfig));
}

Expand Down
19 changes: 19 additions & 0 deletions src/main/io/serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,25 @@ bool isSerialConfigValid(const serialConfig_t *serialConfigToCheck)
return true;
}

// Functions that are resolved with findSerialPortConfig() and therefore only ever use the
// first port they are assigned to. Assigning one of them to a second port has no effect at
// all, so the configuration layer refuses it instead of ignoring it silently.
#define SERIAL_SINGLE_PORT_FUNCTIONS (FUNCTION_SERVO_SERIAL)

uint32_t serialDuplicatedSinglePortFunctions(const serialPortConfig_t *portConfigToCheck)
{
uint32_t functionMaskOfOtherPorts = 0;

for (int index = 0; index < SERIAL_PORT_COUNT; index++) {
const serialPortConfig_t *portConfig = &serialConfig()->portConfigs[index];
if (portConfig->identifier != portConfigToCheck->identifier) {
functionMaskOfOtherPorts |= portConfig->functionMask;
}
}

return portConfigToCheck->functionMask & functionMaskOfOtherPorts & SERIAL_SINGLE_PORT_FUNCTIONS;
}

serialPortConfig_t *serialFindPortConfiguration(serialPortIdentifier_e identifier)
{
for (int index = 0; index < SERIAL_PORT_COUNT; index++) {
Expand Down
1 change: 1 addition & 0 deletions src/main/io/serial.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ void serialRemovePort(serialPortIdentifier_e identifier);
uint8_t serialGetAvailablePortCount(void);
bool serialIsPortAvailable(serialPortIdentifier_e identifier);
bool isSerialConfigValid(const serialConfig_t *serialConfig);
uint32_t serialDuplicatedSinglePortFunctions(const serialPortConfig_t *portConfigToCheck);
serialPortConfig_t *serialFindPortConfiguration(serialPortIdentifier_e identifier);
bool doesConfigurationUsePort(serialPortIdentifier_e portIdentifier);
serialPortConfig_t *findSerialPortConfig(serialPortFunction_e function);
Expand Down