add left side choosable for passthrough (#8395)
add left side choosable for passthrough
This commit is contained in:
commit
ee564432f6
|
@ -40,7 +40,7 @@ Configure serial ports first, then enable/disable features that use the ports.
|
|||
If the configuration is invalid the serial port configuration will reset to its defaults and features may be disabled.
|
||||
|
||||
* There must always be a port available to use for MSP/CLI.
|
||||
* There is a maximum of 2 MSP ports.
|
||||
* There is a maximum of 3 MSP ports.
|
||||
* To use a port for a function, the function's corresponding feature must be also be enabled.
|
||||
e.g. after configuring a port for GPS enable the GPS feature.
|
||||
* If SoftSerial is used, then all SoftSerial ports must use the same baudrate.
|
||||
|
@ -89,9 +89,11 @@ Cleanflight can enter a special passthrough mode whereby it passes serial data t
|
|||
|
||||
To initiate passthrough mode, use the CLI command `serialpassthrough` This command takes four arguments.
|
||||
|
||||
serialpassthrough <id> [baud] [mode] [DTR PINIO]
|
||||
serialpassthrough <port1 id> [port1 baud] [port1 mode] [port1 DTR PINIO] [port2 id] [port2 baud] [port2 mode]
|
||||
|
||||
ID is the internal identifier of the serial port from Cleanflight source code (see serialPortIdentifier_e in the source). For instance UART1-UART4 are 0-3 and SoftSerial1/SoftSerial2 are 30/31 respectively. Baud is the desired baud rate, and mode is a combination of the keywords rx and tx (rxtx is full duplex). The baud and mode parameters can be used to override the configured values for the specified port. `DTR PINIO` identifies the PINIO resource which is optionally connected to a DTR line of the attached device.
|
||||
`PortX ID` is the internal identifier of the serial port from Cleanflight source code (see serialPortIdentifier_e in the source). For instance UART1-UART4 are 0-3 and SoftSerial1/SoftSerial2 are 30/31 respectively. PortX Baud is the desired baud rate, and portX mode is a combination of the keywords rx and tx (rxtx is full duplex). The baud and mode parameters can be used to override the configured values for the specified port. `port1 DTR PINIO` identifies the PINIO resource which is optionally connected to a DTR line of the attached device.
|
||||
|
||||
If port2 config(the last three arguments) is not specified, the passthrough will run between port1 and VCP. The last three arguments are used for `Passthrough between UARTs`, see that section to get detail.
|
||||
|
||||
For example. If you have your MWOSD connected to UART 2, you could enable communicaton to this device using the following command. This command does not specify the baud rate or mode, using the one configured for the port (see above).
|
||||
|
||||
|
@ -103,7 +105,7 @@ _To use a tool such as the MWOSD GUI, it is necessary to disconnect or exit Clea
|
|||
|
||||
**To exit serial passthrough mode, power cycle your flight control board.**
|
||||
|
||||
In order to reflash an Arduino based device such as a MWOSD via `serialpassthrough` if is necessary to connect the DTR line in addition to the RX and TX serial lines. The DTR is used as a reset line to invoke the bootloader. The DTR line may be connected to any GPIO pin on the flight control board. This pin must then be associated with a PINIO resource, the instance of which is then passed to the serialpassthrough command. The DTR line associated with any given UART may be set using the CLI command `resource` specifying it as a PINIO resource.
|
||||
In order to reflash an Arduino based device such as a MWOSD via `serialpassthrough` if is necessary to connect the DTR line in addition to the RX and TX serial lines. The DTR is used as a reset line to invoke the bootloader. The DTR line may be connected to any GPIO pin on the flight control board. This pin must then be associated with a PINIO resource, the instance of which is then passed to the serialpassthrough command. If you don't need it, you can ignore it or set it to `none`. The DTR line associated with any given UART may be set using the CLI command `resource` specifying it as a PINIO resource.
|
||||
|
||||
For example, the following configuration for an OpenPilot Revolution shows the UART6 serial port to be configured with TX on pin C06, RX on pin C07 and a DTR connection using PINIO on pin C08.
|
||||
|
||||
|
@ -144,6 +146,15 @@ Note that if DTR is left configured on a port being used with a standard build o
|
|||
1. Assign the DTR pin using the resource command above prior to reflashing MWOSD, and then dissasociate DTR from the pin.
|
||||
2. Rebuild MWOSD with MAX_SOFTRESET defined. The MWOSD will then be reset correctly every time the flight controller is reset.
|
||||
|
||||
### Passthrough between UARTs
|
||||
|
||||
in BetaFlight 4.1 or later, you can make a serial passthrough between UARTs.
|
||||
|
||||
the last three arguments of `serialpassthrough` are used to the passthrough between UARTs: `[port2 id]` `[port2 baud]` `[port2 mode]`, if you don't need passthrough between UARTs, just ignore them, and use `serialpassthrough` according to above description.
|
||||
if you want passthrough between UARTs, `[port2 id]` is a required argument, the value range is same with `port1 ID` argument, it is the internal identifier of the serial port. `[port2 baud]`and`[port2 mode]` is optional argument, the default of them are `57600` and `MODE_RXTX`.
|
||||
|
||||
For example. If you using a filght controller built-in BLE chip, and the BLE chip was inner connected to a UART, you can use the following command to let the UART to talk with other UART:
|
||||
```
|
||||
serialpassthrough 0 115200 rxtx none 4 19200
|
||||
```
|
||||
the command will run a serial passthrough between UART1 and UART5, UART1 baud is 115200, mode is MODE_RXTX, DTR is none, UART5 baud is 19200, mode is not specifie, it will take default value MODE_RXTX.
|
||||
|
|
|
@ -164,6 +164,13 @@ uint8_t cliMode = 0;
|
|||
|
||||
#include "cli.h"
|
||||
|
||||
typedef struct serialPassthroughPort_e {
|
||||
int id;
|
||||
uint32_t baud;
|
||||
unsigned mode;
|
||||
serialPort_t *port;
|
||||
} serialPassthroughPort_t;
|
||||
|
||||
static serialPort_t *cliPort;
|
||||
|
||||
#ifdef STM32F1
|
||||
|
@ -1231,6 +1238,20 @@ static void cbCtrlLine(void *context, uint16_t ctrl)
|
|||
}
|
||||
}
|
||||
|
||||
static int cliParseSerialMode(const char *tok)
|
||||
{
|
||||
int mode = 0;
|
||||
|
||||
if (strcasestr(tok, "rx")) {
|
||||
mode |= MODE_RX;
|
||||
}
|
||||
if (strcasestr(tok, "tx")) {
|
||||
mode |= MODE_TX;
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
static void cliSerialPassthrough(char *cmdline)
|
||||
{
|
||||
if (isEmpty(cmdline)) {
|
||||
|
@ -1238,12 +1259,10 @@ static void cliSerialPassthrough(char *cmdline)
|
|||
return;
|
||||
}
|
||||
|
||||
int id = -1;
|
||||
uint32_t baud = 0;
|
||||
serialPassthroughPort_t ports[2] = { {SERIAL_PORT_NONE, 0, 0, NULL}, { SERIAL_PORT_USB_VCP, 0, 0, cliPort} };
|
||||
bool enableBaudCb = false;
|
||||
int pinioDtr = 0;
|
||||
bool resetOnDtr = false;
|
||||
unsigned mode = 0;
|
||||
int port1PinioDtr = 0;
|
||||
bool port1ResetOnDtr = false;
|
||||
char *saveptr;
|
||||
char* tok = strtok_r(cmdline, " ", &saveptr);
|
||||
int index = 0;
|
||||
|
@ -1251,114 +1270,147 @@ static void cliSerialPassthrough(char *cmdline)
|
|||
while (tok != NULL) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
id = atoi(tok);
|
||||
ports[0].id = atoi(tok);
|
||||
break;
|
||||
case 1:
|
||||
baud = atoi(tok);
|
||||
ports[0].baud = atoi(tok);
|
||||
break;
|
||||
case 2:
|
||||
if (strcasestr(tok, "rx")) {
|
||||
mode |= MODE_RX;
|
||||
}
|
||||
if (strcasestr(tok, "tx")) {
|
||||
mode |= MODE_TX;
|
||||
}
|
||||
ports[0].mode = cliParseSerialMode(tok);
|
||||
break;
|
||||
case 3:
|
||||
if (strncasecmp(tok, "reset", strlen(tok)) == 0) {
|
||||
resetOnDtr = true;
|
||||
port1ResetOnDtr = true;
|
||||
#ifdef USE_PINIO
|
||||
} else if (strncasecmp(tok, "none", strlen(tok)) == 0) {
|
||||
port1PinioDtr = 0;
|
||||
} else {
|
||||
pinioDtr = atoi(tok);
|
||||
port1PinioDtr = atoi(tok);
|
||||
if (port1PinioDtr < 0 || port1PinioDtr > PINIO_COUNT) {
|
||||
cliPrintLinef("Invalid PinIO number %d", port1PinioDtr);
|
||||
return ;
|
||||
}
|
||||
#endif /* USE_PINIO */
|
||||
}
|
||||
|
||||
break;
|
||||
case 4:
|
||||
ports[1].id = atoi(tok);
|
||||
ports[1].port = NULL;
|
||||
break;
|
||||
case 5:
|
||||
ports[1].baud = atoi(tok);
|
||||
break;
|
||||
case 6:
|
||||
ports[1].mode = cliParseSerialMode(tok);
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
tok = strtok_r(NULL, " ", &saveptr);
|
||||
}
|
||||
|
||||
if (baud == 0) {
|
||||
// Port checks
|
||||
if (ports[0].id == ports[1].id) {
|
||||
cliPrintLinef("Port1 and port2 are same");
|
||||
return ;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (findSerialPortIndexByIdentifier(ports[i].id) == -1) {
|
||||
cliPrintLinef("Invalid port%d %d", i + 1, ports[i].id);
|
||||
return ;
|
||||
} else {
|
||||
cliPrintLinef("Port%d: %d ", i + 1, ports[i].id);
|
||||
}
|
||||
}
|
||||
|
||||
if (ports[0].baud == 0 && ports[1].id == SERIAL_PORT_USB_VCP) {
|
||||
enableBaudCb = true;
|
||||
}
|
||||
|
||||
cliPrintf("Port %d ", id);
|
||||
serialPort_t *passThroughPort;
|
||||
serialPortUsage_t *passThroughPortUsage = findSerialPortUsageByIdentifier(id);
|
||||
if (!passThroughPortUsage || passThroughPortUsage->serialPort == NULL) {
|
||||
if (enableBaudCb) {
|
||||
// Set default baud
|
||||
baud = 57600;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
serialPort_t **port = &(ports[i].port);
|
||||
if (*port != NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!mode) {
|
||||
mode = MODE_RXTX;
|
||||
}
|
||||
int portIndex = i + 1;
|
||||
serialPortUsage_t *portUsage = findSerialPortUsageByIdentifier(ports[i].id);
|
||||
if (!portUsage || portUsage->serialPort == NULL) {
|
||||
bool isUseDefaultBaud = false;
|
||||
if (ports[i].baud == 0) {
|
||||
// Set default baud
|
||||
ports[i].baud = 57600;
|
||||
isUseDefaultBaud = true;
|
||||
}
|
||||
|
||||
passThroughPort = openSerialPort(id, FUNCTION_NONE, NULL, NULL,
|
||||
baud, mode,
|
||||
SERIAL_NOT_INVERTED);
|
||||
if (!passThroughPort) {
|
||||
cliPrintLine("could not be opened.");
|
||||
return;
|
||||
}
|
||||
if (!ports[i].mode) {
|
||||
ports[i].mode = MODE_RXTX;
|
||||
}
|
||||
|
||||
if (enableBaudCb) {
|
||||
cliPrintf("opened, default baud = %d.\r\n", baud);
|
||||
*port = openSerialPort(ports[i].id, FUNCTION_NONE, NULL, NULL,
|
||||
ports[i].baud, ports[i].mode,
|
||||
SERIAL_NOT_INVERTED);
|
||||
if (!*port) {
|
||||
cliPrintLinef("Port%d could not be opened.", portIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isUseDefaultBaud) {
|
||||
cliPrintf("Port%d opened, default baud = %d.\r\n", portIndex, ports[i].baud);
|
||||
} else {
|
||||
cliPrintf("Port%d opened, baud = %d.\r\n", portIndex, ports[i].baud);
|
||||
}
|
||||
} else {
|
||||
cliPrintf("opened, baud = %d.\r\n", baud);
|
||||
}
|
||||
} else {
|
||||
passThroughPort = passThroughPortUsage->serialPort;
|
||||
// If the user supplied a mode, override the port's mode, otherwise
|
||||
// leave the mode unchanged. serialPassthrough() handles one-way ports.
|
||||
// Set the baud rate if specified
|
||||
if (baud) {
|
||||
cliPrintf("already open, setting baud = %d.\n\r", baud);
|
||||
serialSetBaudRate(passThroughPort, baud);
|
||||
} else {
|
||||
cliPrintf("already open, baud = %d.\n\r", passThroughPort->baudRate);
|
||||
}
|
||||
*port = portUsage->serialPort;
|
||||
// If the user supplied a mode, override the port's mode, otherwise
|
||||
// leave the mode unchanged. serialPassthrough() handles one-way ports.
|
||||
// Set the baud rate if specified
|
||||
if (ports[i].baud) {
|
||||
cliPrintf("Port%d is already open, setting baud = %d.\n\r", portIndex, ports[i].baud);
|
||||
serialSetBaudRate(*port, ports[i].baud);
|
||||
} else {
|
||||
cliPrintf("Port%d is already open, baud = %d.\n\r", portIndex, (*port)->baudRate);
|
||||
}
|
||||
|
||||
if (mode && passThroughPort->mode != mode) {
|
||||
cliPrintf("Mode changed from %d to %d.\r\n",
|
||||
passThroughPort->mode, mode);
|
||||
serialSetMode(passThroughPort, mode);
|
||||
}
|
||||
if (ports[i].mode && (*port)->mode != ports[i].mode) {
|
||||
cliPrintf("Port%d mode changed from %d to %d.\r\n",
|
||||
portIndex, (*port)->mode, ports[i].mode);
|
||||
serialSetMode(*port, ports[i].mode);
|
||||
}
|
||||
|
||||
// If this port has a rx callback associated we need to remove it now.
|
||||
// Otherwise no data will be pushed in the serial port buffer!
|
||||
if (passThroughPort->rxCallback) {
|
||||
passThroughPort->rxCallback = 0;
|
||||
// If this port has a rx callback associated we need to remove it now.
|
||||
// Otherwise no data will be pushed in the serial port buffer!
|
||||
if ((*port)->rxCallback) {
|
||||
(*port)->rxCallback = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If no baud rate is specified allow to be set via USB
|
||||
if (enableBaudCb) {
|
||||
cliPrintLine("Baud rate change over USB enabled.");
|
||||
cliPrintLine("Port1 baud rate change over USB enabled.");
|
||||
// Register the right side baud rate setting routine with the left side which allows setting of the UART
|
||||
// baud rate over USB without setting it using the serialpassthrough command
|
||||
serialSetBaudRateCb(cliPort, serialSetBaudRate, passThroughPort);
|
||||
serialSetBaudRateCb(ports[0].port, serialSetBaudRate, ports[1].port);
|
||||
}
|
||||
|
||||
char *resetMessage = "";
|
||||
if (resetOnDtr) {
|
||||
if (port1ResetOnDtr && ports[1].id == SERIAL_PORT_USB_VCP) {
|
||||
resetMessage = "or drop DTR ";
|
||||
}
|
||||
|
||||
cliPrintLinef("Forwarding, power cycle %sto exit.", resetMessage);
|
||||
|
||||
if (resetOnDtr
|
||||
if ((ports[1].id == SERIAL_PORT_USB_VCP) && (port1ResetOnDtr
|
||||
#ifdef USE_PINIO
|
||||
|| pinioDtr
|
||||
|| port1PinioDtr
|
||||
#endif /* USE_PINIO */
|
||||
) {
|
||||
)) {
|
||||
// Register control line state callback
|
||||
serialSetCtrlLineStateCb(cliPort, cbCtrlLine, (void *)(intptr_t)(pinioDtr));
|
||||
serialSetCtrlLineStateCb(ports[0].port, cbCtrlLine, (void *)(intptr_t)(port1PinioDtr));
|
||||
}
|
||||
|
||||
serialPassthrough(cliPort, passThroughPort, NULL, NULL);
|
||||
serialPassthrough(ports[0].port, ports[1].port, NULL, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue