mirror of
https://github.com/iNavFlight/inav.git
synced 2025-07-23 16:25:26 +03:00
serial: add writeBuf() and implement for USB.
This lets USB send up to 32 bytes in a frame instead of 32 one byte frames. Add a fallback for drivers that don't implement writeBuf(). serial: allow buffering to speed up USB virtual COM ports. Add begin write and end write hints. If implemented by the serial driver, then the driver can buffer up data sent via serialWrite() and flush it when serialEndWrite() is called. Implemented at the buffer level as it requires the least change to how serial_msp and serial_cli are architected. Also tidy up the visibility in the VCP driver. Prevent serial tx buffer overflow. Note: this is likely not the best solution, we can investigate further in due course. drivers: add a buffering writer. This wraps around the serial API and buffers a configurable number of characters before flushing. cli: add buffering. This greatly speeds up the CLI when running over USB VCP under a virtual machine. msp: add buffering around the writes. This bulks up the writes and lets the USB VCP driver send one 20 byte frame instead of 20 one byte frames. This speeds up the blackbox download and makes VCP much more reliable when running under a virtual machine. Fix for: serial buffer broke BLHeli 1wire pass through
This commit is contained in:
parent
f063c46e9c
commit
a7e2e2c7b2
11 changed files with 337 additions and 98 deletions
1
Makefile
1
Makefile
|
@ -238,6 +238,7 @@ COMMON_SRC = build_config.c \
|
|||
drivers/system.c \
|
||||
drivers/gps_i2cnav.c \
|
||||
drivers/gyro_sync.c \
|
||||
drivers/buf_writer.c \
|
||||
io/beeper.c \
|
||||
io/rc_controls.c \
|
||||
io/rc_curves.c \
|
||||
|
|
47
src/main/drivers/buf_writer.c
Normal file
47
src/main/drivers/buf_writer.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "buf_writer.h"
|
||||
|
||||
bufWriter_t *bufWriterInit(uint8_t *b, int total_size, bufWrite_t writer, void *arg)
|
||||
{
|
||||
bufWriter_t *buf = (bufWriter_t *)b;
|
||||
buf->writer = writer;
|
||||
buf->arg = arg;
|
||||
buf->at = 0;
|
||||
buf->capacity = total_size - sizeof(*buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void bufWriterAppend(bufWriter_t *b, uint8_t ch)
|
||||
{
|
||||
b->data[b->at++] = ch;
|
||||
if (b->at >= b->capacity) {
|
||||
bufWriterFlush(b);
|
||||
}
|
||||
}
|
||||
|
||||
void bufWriterFlush(bufWriter_t *b)
|
||||
{
|
||||
if (b->at != 0) {
|
||||
b->writer(b->arg, b->data, b->at);
|
||||
b->at = 0;
|
||||
}
|
||||
}
|
38
src/main/drivers/buf_writer.h
Normal file
38
src/main/drivers/buf_writer.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// Called to flush the buffer.
|
||||
typedef void (*bufWrite_t)(void *arg, void *data, int count);
|
||||
|
||||
typedef struct bufWriter_s {
|
||||
bufWrite_t writer;
|
||||
void *arg;
|
||||
uint8_t capacity;
|
||||
uint8_t at;
|
||||
uint8_t data[];
|
||||
} bufWriter_t;
|
||||
|
||||
// Initialise a block of memory as a buffered writer.
|
||||
//
|
||||
// b should be sizeof(bufWriter_t) + the number of bytes to buffer.
|
||||
// total_size should be the total size of b.
|
||||
//
|
||||
bufWriter_t *bufWriterInit(uint8_t *b, int total_size, bufWrite_t writer, void *p);
|
||||
void bufWriterAppend(bufWriter_t *b, uint8_t ch);
|
||||
void bufWriterFlush(bufWriter_t *b);
|
|
@ -40,6 +40,22 @@ void serialWrite(serialPort_t *instance, uint8_t ch)
|
|||
instance->vTable->serialWrite(instance, ch);
|
||||
}
|
||||
|
||||
|
||||
void serialWriteBuf(serialPort_t *instance, uint8_t *data, int count)
|
||||
{
|
||||
if (instance->vTable->writeBuf) {
|
||||
instance->vTable->writeBuf(instance, data, count);
|
||||
} else {
|
||||
for (uint8_t *p = data; count > 0; count--, p++) {
|
||||
|
||||
while (!serialTxBytesFree(instance)) {
|
||||
};
|
||||
|
||||
serialWrite(instance, *p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t serialRxBytesWaiting(serialPort_t *instance)
|
||||
{
|
||||
return instance->vTable->serialTotalRxWaiting(instance);
|
||||
|
@ -70,3 +86,19 @@ void serialSetMode(serialPort_t *instance, portMode_t mode)
|
|||
instance->vTable->setMode(instance, mode);
|
||||
}
|
||||
|
||||
void serialWriteBufShim(void *instance, uint8_t *data, int count)
|
||||
{
|
||||
serialWriteBuf((serialPort_t *)instance, data, count);
|
||||
}
|
||||
|
||||
void serialBeginWrite(serialPort_t *instance)
|
||||
{
|
||||
if (instance->vTable->beginWrite)
|
||||
instance->vTable->beginWrite(instance);
|
||||
}
|
||||
|
||||
void serialEndWrite(serialPort_t *instance)
|
||||
{
|
||||
if (instance->vTable->endWrite)
|
||||
instance->vTable->endWrite(instance);
|
||||
}
|
||||
|
|
|
@ -73,14 +73,25 @@ struct serialPortVTable {
|
|||
bool (*isSerialTransmitBufferEmpty)(serialPort_t *instance);
|
||||
|
||||
void (*setMode)(serialPort_t *instance, portMode_t mode);
|
||||
|
||||
void (*writeBuf)(serialPort_t *instance, void *data, int count);
|
||||
// Optional functions used to buffer large writes.
|
||||
void (*beginWrite)(serialPort_t *instance);
|
||||
void (*endWrite)(serialPort_t *instance);
|
||||
};
|
||||
|
||||
void serialWrite(serialPort_t *instance, uint8_t ch);
|
||||
uint8_t serialRxBytesWaiting(serialPort_t *instance);
|
||||
uint8_t serialTxBytesFree(serialPort_t *instance);
|
||||
void serialWriteBuf(serialPort_t *instance, uint8_t *data, int count);
|
||||
uint8_t serialRead(serialPort_t *instance);
|
||||
void serialSetBaudRate(serialPort_t *instance, uint32_t baudRate);
|
||||
void serialSetMode(serialPort_t *instance, portMode_t mode);
|
||||
bool isSerialTransmitBufferEmpty(serialPort_t *instance);
|
||||
void serialPrint(serialPort_t *instance, const char *str);
|
||||
uint32_t serialGetBaudRate(serialPort_t *instance);
|
||||
|
||||
// A shim that adapts the bufWriter API to the serialWriteBuf() API.
|
||||
void serialWriteBufShim(void *instance, uint8_t *data, int count);
|
||||
void serialBeginWrite(serialPort_t *instance);
|
||||
void serialEndWrite(serialPort_t *instance);
|
||||
|
|
|
@ -479,6 +479,7 @@ const struct serialPortVTable softSerialVTable[] = {
|
|||
softSerialSetBaudRate,
|
||||
isSoftSerialTransmitBufferEmpty,
|
||||
softSerialSetMode,
|
||||
.writeBuf = NULL,
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -322,5 +322,8 @@ const struct serialPortVTable uartVTable[] = {
|
|||
uartSetBaudRate,
|
||||
isUartTransmitBufferEmpty,
|
||||
uartSetMode,
|
||||
.writeBuf = NULL,
|
||||
.beginWrite = NULL,
|
||||
.endWrite = NULL,
|
||||
}
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "platform.h"
|
||||
|
||||
#include "build_config.h"
|
||||
#include "common/utils.h"
|
||||
|
||||
#include "usb_core.h"
|
||||
#include "usb_init.h"
|
||||
|
@ -82,21 +83,63 @@ uint8_t usbVcpRead(serialPort_t *instance)
|
|||
return buf[0];
|
||||
}
|
||||
|
||||
void usbVcpWrite(serialPort_t *instance, uint8_t c)
|
||||
static void usbVcpWriteBuf(serialPort_t *instance, void *data, int count)
|
||||
{
|
||||
UNUSED(instance);
|
||||
|
||||
uint32_t txed;
|
||||
uint32_t start = millis();
|
||||
|
||||
if (!(usbIsConnected() && usbIsConfigured())) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
txed = CDC_Send_DATA((uint8_t*)&c, 1);
|
||||
} while (txed < 1 && (millis() - start < USB_TIMEOUT));
|
||||
uint32_t start = millis();
|
||||
for (uint8_t *p = data; count > 0; ) {
|
||||
uint32_t txed = CDC_Send_DATA(p, count);
|
||||
count -= txed;
|
||||
p += txed;
|
||||
|
||||
if (millis() - start > USB_TIMEOUT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool usbVcpFlush(vcpPort_t *port)
|
||||
{
|
||||
uint8_t count = port->txAt;
|
||||
port->txAt = 0;
|
||||
|
||||
if (count == 0) {
|
||||
return true;
|
||||
}
|
||||
if (!usbIsConnected() || !usbIsConfigured()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t txed;
|
||||
uint32_t start = millis();
|
||||
|
||||
do {
|
||||
txed = CDC_Send_DATA(port->txBuf, count);
|
||||
} while (txed != count && (millis() - start < USB_TIMEOUT));
|
||||
|
||||
return txed == count;
|
||||
}
|
||||
|
||||
static void usbVcpWrite(serialPort_t *instance, uint8_t c)
|
||||
{
|
||||
vcpPort_t *port = container_of(instance, vcpPort_t, port);
|
||||
|
||||
port->txBuf[port->txAt++] = c;
|
||||
if (!port->buffering || port->txAt >= ARRAYLEN(port->txBuf)) {
|
||||
usbVcpFlush(port);
|
||||
}
|
||||
}
|
||||
|
||||
static void usbVcpBeginWrite(serialPort_t *instance)
|
||||
{
|
||||
vcpPort_t *port = container_of(instance, vcpPort_t, port);
|
||||
port->buffering = true;
|
||||
}
|
||||
|
||||
uint8_t usbTxBytesFree() {
|
||||
|
@ -104,7 +147,27 @@ uint8_t usbTxBytesFree() {
|
|||
return 255;
|
||||
}
|
||||
|
||||
const struct serialPortVTable usbVTable[] = { { usbVcpWrite, usbVcpAvailable, usbTxBytesFree, usbVcpRead, usbVcpSetBaudRate, isUsbVcpTransmitBufferEmpty, usbVcpSetMode } };
|
||||
static void usbVcpEndWrite(serialPort_t *instance)
|
||||
{
|
||||
vcpPort_t *port = container_of(instance, vcpPort_t, port);
|
||||
port->buffering = false;
|
||||
usbVcpFlush(port);
|
||||
}
|
||||
|
||||
static const struct serialPortVTable usbVTable[] = {
|
||||
{
|
||||
.serialWrite = usbVcpWrite,
|
||||
.serialTotalRxWaiting = usbVcpAvailable,
|
||||
.serialTotalTxFree = usbTxBytesFree,
|
||||
.serialRead = usbVcpRead,
|
||||
.serialSetBaudRate = usbVcpSetBaudRate,
|
||||
.isSerialTransmitBufferEmpty = isUsbVcpTransmitBufferEmpty,
|
||||
.setMode = usbVcpSetMode,
|
||||
.beginWrite = usbVcpBeginWrite,
|
||||
.endWrite = usbVcpEndWrite,
|
||||
.writeBuf = usbVcpWriteBuf
|
||||
}
|
||||
};
|
||||
|
||||
serialPort_t *usbVcpOpen(void)
|
||||
{
|
||||
|
|
|
@ -22,6 +22,11 @@
|
|||
typedef struct {
|
||||
serialPort_t port;
|
||||
|
||||
// Buffer used during bulk writes.
|
||||
uint8_t txBuf[20];
|
||||
uint8_t txAt;
|
||||
// Set if the port is in bulk write mode and can buffer.
|
||||
bool buffering;
|
||||
} vcpPort_t;
|
||||
|
||||
serialPort_t *usbVcpOpen(void);
|
||||
|
@ -30,5 +35,4 @@ uint8_t usbVcpAvailable(serialPort_t *instance);
|
|||
|
||||
uint8_t usbVcpRead(serialPort_t *instance);
|
||||
|
||||
void usbVcpWrite(serialPort_t *instance, uint8_t ch);
|
||||
void usbPrintStr(const char *str);
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "drivers/timer.h"
|
||||
#include "drivers/pwm_rx.h"
|
||||
|
||||
#include "drivers/buf_writer.h"
|
||||
|
||||
#include "io/escservo.h"
|
||||
#include "io/gps.h"
|
||||
|
@ -96,6 +97,8 @@ extern uint16_t cycleTime; // FIXME dependency on mw.c
|
|||
void gpsEnablePassthrough(serialPort_t *gpsPassthroughPort);
|
||||
|
||||
static serialPort_t *cliPort;
|
||||
static bufWriter_t *cliWriter;
|
||||
static uint8_t cliWriteBuffer[sizeof(*cliWriter) + 16];
|
||||
|
||||
static void cliAux(char *cmdline);
|
||||
static void cliRxFail(char *cmdline);
|
||||
|
@ -772,11 +775,13 @@ typedef union {
|
|||
static void cliSetVar(const clivalue_t *var, const int_float_value_t value);
|
||||
static void cliPrintVar(const clivalue_t *var, uint32_t full);
|
||||
static void cliPrint(const char *str);
|
||||
static void cliPrintf(const char *fmt, ...);
|
||||
static void cliWrite(uint8_t ch);
|
||||
|
||||
static void cliPrompt(void)
|
||||
{
|
||||
cliPrint("\r\n# ");
|
||||
bufWriterFlush(cliWriter);
|
||||
}
|
||||
|
||||
static void cliShowParseError(void)
|
||||
|
@ -786,7 +791,7 @@ static void cliShowParseError(void)
|
|||
|
||||
static void cliShowArgumentRangeError(char *name, int min, int max)
|
||||
{
|
||||
printf("%s must be between %d and %d\r\n", name, min, max);
|
||||
cliPrintf("%s must be between %d and %d\r\n", name, min, max);
|
||||
}
|
||||
|
||||
static char *processChannelRangeArgs(char *ptr, channelRange_t *range, uint8_t *validArgumentCount)
|
||||
|
@ -880,19 +885,19 @@ static void cliRxFail(char *cmdline)
|
|||
|
||||
char modeCharacter = rxFailsafeModeCharacters[channelFailsafeConfiguration->mode];
|
||||
|
||||
// triple use of printf below
|
||||
// triple use of cliPrintf below
|
||||
// 1. acknowledge interpretation on command,
|
||||
// 2. query current setting on single item,
|
||||
// 3. recursive use for full list.
|
||||
|
||||
if (requireValue) {
|
||||
printf("rxfail %u %c %d\r\n",
|
||||
cliPrintf("rxfail %u %c %d\r\n",
|
||||
channel,
|
||||
modeCharacter,
|
||||
RXFAIL_STEP_TO_CHANNEL_VALUE(channelFailsafeConfiguration->step)
|
||||
);
|
||||
} else {
|
||||
printf("rxfail %u %c\r\n",
|
||||
cliPrintf("rxfail %u %c\r\n",
|
||||
channel,
|
||||
modeCharacter
|
||||
);
|
||||
|
@ -912,7 +917,7 @@ static void cliAux(char *cmdline)
|
|||
// print out aux channel settings
|
||||
for (i = 0; i < MAX_MODE_ACTIVATION_CONDITION_COUNT; i++) {
|
||||
modeActivationCondition_t *mac = ¤tProfile->modeActivationConditions[i];
|
||||
printf("aux %u %u %u %u %u\r\n",
|
||||
cliPrintf("aux %u %u %u %u %u\r\n",
|
||||
i,
|
||||
mac->modeId,
|
||||
mac->auxChannelIndex,
|
||||
|
@ -963,7 +968,7 @@ static void cliSerial(char *cmdline)
|
|||
if (!serialIsPortAvailable(masterConfig.serialConfig.portConfigs[i].identifier)) {
|
||||
continue;
|
||||
};
|
||||
printf("serial %d %d %ld %ld %ld %ld\r\n" ,
|
||||
cliPrintf("serial %d %d %ld %ld %ld %ld\r\n" ,
|
||||
masterConfig.serialConfig.portConfigs[i].identifier,
|
||||
masterConfig.serialConfig.portConfigs[i].functionMask,
|
||||
baudRates[masterConfig.serialConfig.portConfigs[i].msp_baudrateIndex],
|
||||
|
@ -1059,7 +1064,7 @@ static void cliAdjustmentRange(char *cmdline)
|
|||
// print out adjustment ranges channel settings
|
||||
for (i = 0; i < MAX_ADJUSTMENT_RANGE_COUNT; i++) {
|
||||
adjustmentRange_t *ar = ¤tProfile->adjustmentRanges[i];
|
||||
printf("adjrange %u %u %u %u %u %u %u\r\n",
|
||||
cliPrintf("adjrange %u %u %u %u %u %u %u\r\n",
|
||||
i,
|
||||
ar->adjustmentIndex,
|
||||
ar->auxChannelIndex,
|
||||
|
@ -1139,11 +1144,11 @@ static void cliMotorMix(char *cmdline)
|
|||
if (masterConfig.customMotorMixer[i].throttle == 0.0f)
|
||||
break;
|
||||
num_motors++;
|
||||
printf("#%d:\t", i);
|
||||
printf("%s\t", ftoa(masterConfig.customMotorMixer[i].throttle, buf));
|
||||
printf("%s\t", ftoa(masterConfig.customMotorMixer[i].roll, buf));
|
||||
printf("%s\t", ftoa(masterConfig.customMotorMixer[i].pitch, buf));
|
||||
printf("%s\r\n", ftoa(masterConfig.customMotorMixer[i].yaw, buf));
|
||||
cliPrintf("#%d:\t", i);
|
||||
cliPrintf("%s\t", ftoa(masterConfig.customMotorMixer[i].throttle, buf));
|
||||
cliPrintf("%s\t", ftoa(masterConfig.customMotorMixer[i].roll, buf));
|
||||
cliPrintf("%s\t", ftoa(masterConfig.customMotorMixer[i].pitch, buf));
|
||||
cliPrintf("%s\r\n", ftoa(masterConfig.customMotorMixer[i].yaw, buf));
|
||||
}
|
||||
return;
|
||||
} else if (strncasecmp(cmdline, "reset", 5) == 0) {
|
||||
|
@ -1161,7 +1166,7 @@ static void cliMotorMix(char *cmdline)
|
|||
}
|
||||
if (strncasecmp(ptr, mixerNames[i], len) == 0) {
|
||||
mixerLoadMix(i, masterConfig.customMotorMixer);
|
||||
printf("Loaded %s\r\n", mixerNames[i]);
|
||||
cliPrintf("Loaded %s\r\n", mixerNames[i]);
|
||||
cliMotorMix("");
|
||||
break;
|
||||
}
|
||||
|
@ -1211,7 +1216,7 @@ static void cliRxRange(char *cmdline)
|
|||
if (isEmpty(cmdline)) {
|
||||
for (i = 0; i < NON_AUX_CHANNEL_COUNT; i++) {
|
||||
rxChannelRangeConfiguration_t *channelRangeConfiguration = &masterConfig.rxConfig.channelRanges[i];
|
||||
printf("rxrange %u %u %u\r\n", i, channelRangeConfiguration->min, channelRangeConfiguration->max);
|
||||
cliPrintf("rxrange %u %u %u\r\n", i, channelRangeConfiguration->min, channelRangeConfiguration->max);
|
||||
}
|
||||
} else if (strcasecmp(cmdline, "reset") == 0) {
|
||||
resetAllRxChannelRangeConfigurations(masterConfig.rxConfig.channelRanges);
|
||||
|
@ -1258,7 +1263,7 @@ static void cliLed(char *cmdline)
|
|||
if (isEmpty(cmdline)) {
|
||||
for (i = 0; i < MAX_LED_STRIP_LENGTH; i++) {
|
||||
generateLedConfig(i, ledConfigBuffer, sizeof(ledConfigBuffer));
|
||||
printf("led %u %s\r\n", i, ledConfigBuffer);
|
||||
cliPrintf("led %u %s\r\n", i, ledConfigBuffer);
|
||||
}
|
||||
} else {
|
||||
ptr = cmdline;
|
||||
|
@ -1281,7 +1286,7 @@ static void cliColor(char *cmdline)
|
|||
|
||||
if (isEmpty(cmdline)) {
|
||||
for (i = 0; i < CONFIGURABLE_COLOR_COUNT; i++) {
|
||||
printf("color %u %d,%u,%u\r\n",
|
||||
cliPrintf("color %u %d,%u,%u\r\n",
|
||||
i,
|
||||
masterConfig.colors[i].h,
|
||||
masterConfig.colors[i].s,
|
||||
|
@ -1319,7 +1324,7 @@ static void cliServo(char *cmdline)
|
|||
for (i = 0; i < MAX_SUPPORTED_SERVOS; i++) {
|
||||
servo = ¤tProfile->servoConf[i];
|
||||
|
||||
printf("servo %u %d %d %d %d %d %d %d\r\n",
|
||||
cliPrintf("servo %u %d %d %d %d %d %d %d\r\n",
|
||||
i,
|
||||
servo->min,
|
||||
servo->max,
|
||||
|
@ -1412,7 +1417,7 @@ static void cliServoMix(char *cmdline)
|
|||
if (masterConfig.customServoMixer[i].rate == 0)
|
||||
break;
|
||||
|
||||
printf("#%d:\t%d\t%d\t%d\t%d\t%d\t%d\t%d\r\n",
|
||||
cliPrintf("#%d:\t%d\t%d\t%d\t%d\t%d\t%d\t%d\r\n",
|
||||
i,
|
||||
masterConfig.customServoMixer[i].targetChannel,
|
||||
masterConfig.customServoMixer[i].inputSource,
|
||||
|
@ -1423,7 +1428,7 @@ static void cliServoMix(char *cmdline)
|
|||
masterConfig.customServoMixer[i].box
|
||||
);
|
||||
}
|
||||
printf("\r\n");
|
||||
cliPrintf("\r\n");
|
||||
return;
|
||||
} else if (strncasecmp(cmdline, "reset", 5) == 0) {
|
||||
// erase custom mixer
|
||||
|
@ -1437,12 +1442,12 @@ static void cliServoMix(char *cmdline)
|
|||
len = strlen(++ptr);
|
||||
for (i = 0; ; i++) {
|
||||
if (mixerNames[i] == NULL) {
|
||||
printf("Invalid name\r\n");
|
||||
cliPrintf("Invalid name\r\n");
|
||||
break;
|
||||
}
|
||||
if (strncasecmp(ptr, mixerNames[i], len) == 0) {
|
||||
servoMixerLoadMix(i, masterConfig.customServoMixer);
|
||||
printf("Loaded %s\r\n", mixerNames[i]);
|
||||
cliPrintf("Loaded %s\r\n", mixerNames[i]);
|
||||
cliServoMix("");
|
||||
break;
|
||||
}
|
||||
|
@ -1455,16 +1460,16 @@ static void cliServoMix(char *cmdline)
|
|||
|
||||
len = strlen(ptr);
|
||||
if (len == 0) {
|
||||
printf("s");
|
||||
cliPrintf("s");
|
||||
for (inputSource = 0; inputSource < INPUT_SOURCE_COUNT; inputSource++)
|
||||
printf("\ti%d", inputSource);
|
||||
printf("\r\n");
|
||||
cliPrintf("\ti%d", inputSource);
|
||||
cliPrintf("\r\n");
|
||||
|
||||
for (servoIndex = 0; servoIndex < MAX_SUPPORTED_SERVOS; servoIndex++) {
|
||||
printf("%d", servoIndex);
|
||||
cliPrintf("%d", servoIndex);
|
||||
for (inputSource = 0; inputSource < INPUT_SOURCE_COUNT; inputSource++)
|
||||
printf("\t%s ", (currentProfile->servoConf[servoIndex].reversedSources & (1 << inputSource)) ? "r" : "n");
|
||||
printf("\r\n");
|
||||
cliPrintf("\t%s ", (currentProfile->servoConf[servoIndex].reversedSources & (1 << inputSource)) ? "r" : "n");
|
||||
cliPrintf("\r\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1537,7 +1542,7 @@ static void cliFlashInfo(char *cmdline)
|
|||
|
||||
UNUSED(cmdline);
|
||||
|
||||
printf("Flash sectors=%u, sectorSize=%u, pagesPerSector=%u, pageSize=%u, totalSize=%u, usedSize=%u\r\n",
|
||||
cliPrintf("Flash sectors=%u, sectorSize=%u, pagesPerSector=%u, pageSize=%u, totalSize=%u, usedSize=%u\r\n",
|
||||
layout->sectors, layout->sectorSize, layout->pagesPerSector, layout->pageSize, layout->totalSize, flashfsGetOffset());
|
||||
}
|
||||
|
||||
|
@ -1545,14 +1550,14 @@ static void cliFlashErase(char *cmdline)
|
|||
{
|
||||
UNUSED(cmdline);
|
||||
|
||||
printf("Erasing...\r\n");
|
||||
cliPrintf("Erasing...\r\n");
|
||||
flashfsEraseCompletely();
|
||||
|
||||
while (!flashfsIsReady()) {
|
||||
delay(100);
|
||||
}
|
||||
|
||||
printf("Done.\r\n");
|
||||
cliPrintf("Done.\r\n");
|
||||
}
|
||||
|
||||
#ifdef USE_FLASH_TOOLS
|
||||
|
@ -1569,7 +1574,7 @@ static void cliFlashWrite(char *cmdline)
|
|||
flashfsWrite((uint8_t*)text, strlen(text), true);
|
||||
flashfsFlushSync();
|
||||
|
||||
printf("Wrote %u bytes at %u.\r\n", strlen(text), address);
|
||||
cliPrintf("Wrote %u bytes at %u.\r\n", strlen(text), address);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1588,7 +1593,7 @@ static void cliFlashRead(char *cmdline)
|
|||
} else {
|
||||
length = atoi(nextArg);
|
||||
|
||||
printf("Reading %u bytes at %u:\r\n", length, address);
|
||||
cliPrintf("Reading %u bytes at %u:\r\n", length, address);
|
||||
|
||||
while (length > 0) {
|
||||
int bytesRead;
|
||||
|
@ -1607,7 +1612,7 @@ static void cliFlashRead(char *cmdline)
|
|||
break;
|
||||
}
|
||||
}
|
||||
printf("\r\n");
|
||||
cliPrintf("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1625,7 +1630,7 @@ static void dumpValues(uint16_t valueSection)
|
|||
continue;
|
||||
}
|
||||
|
||||
printf("set %s = ", valueTable[i].name);
|
||||
cliPrintf("set %s = ", valueTable[i].name);
|
||||
cliPrintVar(value, 0);
|
||||
cliPrint("\r\n");
|
||||
}
|
||||
|
@ -1642,7 +1647,7 @@ typedef enum {
|
|||
|
||||
static const char* const sectionBreak = "\r\n";
|
||||
|
||||
#define printSectionBreak() printf((char *)sectionBreak)
|
||||
#define printSectionBreak() cliPrintf((char *)sectionBreak)
|
||||
|
||||
static void cliDump(char *cmdline)
|
||||
{
|
||||
|
@ -1677,9 +1682,9 @@ static void cliDump(char *cmdline)
|
|||
cliPrint("\r\n# mixer\r\n");
|
||||
|
||||
#ifndef USE_QUAD_MIXER_ONLY
|
||||
printf("mixer %s\r\n", mixerNames[masterConfig.mixerMode - 1]);
|
||||
cliPrintf("mixer %s\r\n", mixerNames[masterConfig.mixerMode - 1]);
|
||||
|
||||
printf("mmix reset\r\n");
|
||||
cliPrintf("mmix reset\r\n");
|
||||
|
||||
for (i = 0; i < MAX_SUPPORTED_MOTORS; i++) {
|
||||
if (masterConfig.customMotorMixer[i].throttle == 0.0f)
|
||||
|
@ -1688,30 +1693,30 @@ static void cliDump(char *cmdline)
|
|||
roll = masterConfig.customMotorMixer[i].roll;
|
||||
pitch = masterConfig.customMotorMixer[i].pitch;
|
||||
yaw = masterConfig.customMotorMixer[i].yaw;
|
||||
printf("mmix %d", i);
|
||||
cliPrintf("mmix %d", i);
|
||||
if (thr < 0)
|
||||
cliWrite(' ');
|
||||
printf("%s", ftoa(thr, buf));
|
||||
cliPrintf("%s", ftoa(thr, buf));
|
||||
if (roll < 0)
|
||||
cliWrite(' ');
|
||||
printf("%s", ftoa(roll, buf));
|
||||
cliPrintf("%s", ftoa(roll, buf));
|
||||
if (pitch < 0)
|
||||
cliWrite(' ');
|
||||
printf("%s", ftoa(pitch, buf));
|
||||
cliPrintf("%s", ftoa(pitch, buf));
|
||||
if (yaw < 0)
|
||||
cliWrite(' ');
|
||||
printf("%s\r\n", ftoa(yaw, buf));
|
||||
cliPrintf("%s\r\n", ftoa(yaw, buf));
|
||||
}
|
||||
|
||||
// print custom servo mixer if exists
|
||||
printf("smix reset\r\n");
|
||||
#ifdef USE_SERVOS
|
||||
cliPrintf("smix reset\r\n");
|
||||
|
||||
for (i = 0; i < MAX_SERVO_RULES; i++) {
|
||||
|
||||
if (masterConfig.customServoMixer[i].rate == 0)
|
||||
break;
|
||||
|
||||
printf("smix %d %d %d %d %d %d %d %d\r\n",
|
||||
cliPrintf("smix %d %d %d %d %d %d %d %d\r\n",
|
||||
i,
|
||||
masterConfig.customServoMixer[i].targetChannel,
|
||||
masterConfig.customServoMixer[i].inputSource,
|
||||
|
@ -1723,7 +1728,6 @@ static void cliDump(char *cmdline)
|
|||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
cliPrint("\r\n\r\n# feature\r\n");
|
||||
|
@ -1732,13 +1736,13 @@ static void cliDump(char *cmdline)
|
|||
for (i = 0; ; i++) { // disable all feature first
|
||||
if (featureNames[i] == NULL)
|
||||
break;
|
||||
printf("feature -%s\r\n", featureNames[i]);
|
||||
cliPrintf("feature -%s\r\n", featureNames[i]);
|
||||
}
|
||||
for (i = 0; ; i++) { // reenable what we want.
|
||||
if (featureNames[i] == NULL)
|
||||
break;
|
||||
if (mask & (1 << i))
|
||||
printf("feature %s\r\n", featureNames[i]);
|
||||
cliPrintf("feature %s\r\n", featureNames[i]);
|
||||
}
|
||||
|
||||
cliPrint("\r\n\r\n# map\r\n");
|
||||
|
@ -1746,7 +1750,7 @@ static void cliDump(char *cmdline)
|
|||
for (i = 0; i < 8; i++)
|
||||
buf[masterConfig.rxConfig.rcmap[i]] = rcChannelLetters[i];
|
||||
buf[i] = '\0';
|
||||
printf("map %s\r\n", buf);
|
||||
cliPrintf("map %s\r\n", buf);
|
||||
|
||||
cliPrint("\r\n\r\n# serial\r\n");
|
||||
cliSerial("");
|
||||
|
@ -1779,7 +1783,7 @@ static void cliDump(char *cmdline)
|
|||
|
||||
cliAdjustmentRange("");
|
||||
|
||||
printf("\r\n# rxrange\r\n");
|
||||
cliPrintf("\r\n# rxrange\r\n");
|
||||
|
||||
cliRxRange("");
|
||||
|
||||
|
@ -1794,7 +1798,7 @@ static void cliDump(char *cmdline)
|
|||
for (i = 0; i < MAX_SUPPORTED_SERVOS; i++) {
|
||||
for (channel = 0; channel < INPUT_SOURCE_COUNT; channel++) {
|
||||
if (servoDirection(i, channel) < 0) {
|
||||
printf("smix reverse %d %d r\r\n", i , channel);
|
||||
cliPrintf("smix reverse %d %d r\r\n", i , channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1822,6 +1826,9 @@ void cliEnter(serialPort_t *serialPort)
|
|||
cliMode = 1;
|
||||
cliPort = serialPort;
|
||||
setPrintfSerialPort(cliPort);
|
||||
cliWriter = bufWriterInit(cliWriteBuffer, sizeof(cliWriteBuffer),
|
||||
(bufWrite_t)serialWriteBufShim, serialPort);
|
||||
|
||||
cliPrint("\r\nEntering CLI Mode, type 'exit' to return, or 'help'\r\n");
|
||||
cliPrompt();
|
||||
ENABLE_ARMING_FLAG(PREVENT_ARMING);
|
||||
|
@ -1832,6 +1839,8 @@ static void cliExit(char *cmdline)
|
|||
UNUSED(cmdline);
|
||||
|
||||
cliPrint("\r\nLeaving CLI mode, unsaved changes lost.\r\n");
|
||||
bufWriterFlush(cliWriter);
|
||||
|
||||
*cliBuffer = '\0';
|
||||
bufferIndex = 0;
|
||||
cliMode = 0;
|
||||
|
@ -1839,7 +1848,7 @@ static void cliExit(char *cmdline)
|
|||
mixerResetDisarmedMotors();
|
||||
cliReboot();
|
||||
|
||||
cliPort = NULL;
|
||||
cliWriter = NULL;
|
||||
}
|
||||
|
||||
static void cliFeature(char *cmdline)
|
||||
|
@ -1857,7 +1866,7 @@ static void cliFeature(char *cmdline)
|
|||
if (featureNames[i] == NULL)
|
||||
break;
|
||||
if (mask & (1 << i))
|
||||
printf("%s ", featureNames[i]);
|
||||
cliPrintf("%s ", featureNames[i]);
|
||||
}
|
||||
cliPrint("\r\n");
|
||||
} else if (strncasecmp(cmdline, "list", len) == 0) {
|
||||
|
@ -1865,7 +1874,7 @@ static void cliFeature(char *cmdline)
|
|||
for (i = 0; ; i++) {
|
||||
if (featureNames[i] == NULL)
|
||||
break;
|
||||
printf("%s ", featureNames[i]);
|
||||
cliPrintf("%s ", featureNames[i]);
|
||||
}
|
||||
cliPrint("\r\n");
|
||||
return;
|
||||
|
@ -1906,7 +1915,7 @@ static void cliFeature(char *cmdline)
|
|||
featureSet(mask);
|
||||
cliPrint("Enabled");
|
||||
}
|
||||
printf(" %s\r\n", featureNames[i]);
|
||||
cliPrintf(" %s\r\n", featureNames[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1932,10 +1941,10 @@ static void cliHelp(char *cmdline)
|
|||
cliPrint(cmdTable[i].name);
|
||||
#ifndef SKIP_CLI_COMMAND_HELP
|
||||
if (cmdTable[i].description) {
|
||||
printf(" - %s", cmdTable[i].description);
|
||||
cliPrintf(" - %s", cmdTable[i].description);
|
||||
}
|
||||
if (cmdTable[i].args) {
|
||||
printf("\r\n\t%s", cmdTable[i].args);
|
||||
cliPrintf("\r\n\t%s", cmdTable[i].args);
|
||||
}
|
||||
#endif
|
||||
cliPrint("\r\n");
|
||||
|
@ -1966,7 +1975,7 @@ static void cliMap(char *cmdline)
|
|||
for (i = 0; i < 8; i++)
|
||||
out[masterConfig.rxConfig.rcmap[i]] = rcChannelLetters[i];
|
||||
out[i] = '\0';
|
||||
printf("%s\r\n", out);
|
||||
cliPrintf("%s\r\n", out);
|
||||
}
|
||||
|
||||
#ifndef USE_QUAD_MIXER_ONLY
|
||||
|
@ -1978,14 +1987,14 @@ static void cliMixer(char *cmdline)
|
|||
len = strlen(cmdline);
|
||||
|
||||
if (len == 0) {
|
||||
printf("Mixer: %s\r\n", mixerNames[masterConfig.mixerMode - 1]);
|
||||
cliPrintf("Mixer: %s\r\n", mixerNames[masterConfig.mixerMode - 1]);
|
||||
return;
|
||||
} else if (strncasecmp(cmdline, "list", len) == 0) {
|
||||
cliPrint("Available mixers: ");
|
||||
for (i = 0; ; i++) {
|
||||
if (mixerNames[i] == NULL)
|
||||
break;
|
||||
printf("%s ", mixerNames[i]);
|
||||
cliPrintf("%s ", mixerNames[i]);
|
||||
}
|
||||
cliPrint("\r\n");
|
||||
return;
|
||||
|
@ -2047,7 +2056,7 @@ static void cliMotor(char *cmdline)
|
|||
}
|
||||
}
|
||||
|
||||
printf("motor %d: %d\r\n", motor_index, motor_disarmed[motor_index]);
|
||||
cliPrintf("motor %d: %d\r\n", motor_index, motor_disarmed[motor_index]);
|
||||
}
|
||||
|
||||
static void cliPlaySound(char *cmdline)
|
||||
|
@ -2068,7 +2077,7 @@ static void cliPlaySound(char *cmdline)
|
|||
if ((name=beeperNameForTableIndex(i)) != NULL)
|
||||
break; //if name OK then play sound below
|
||||
if (i == lastSoundIdx + 1) { //prevent infinite loop
|
||||
printf("Error playing sound\r\n");
|
||||
cliPrintf("Error playing sound\r\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2076,13 +2085,13 @@ static void cliPlaySound(char *cmdline)
|
|||
} else { //index value was given
|
||||
i = atoi(cmdline);
|
||||
if ((name=beeperNameForTableIndex(i)) == NULL) {
|
||||
printf("No sound for index %d\r\n", i);
|
||||
cliPrintf("No sound for index %d\r\n", i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
lastSoundIdx = i;
|
||||
beeperSilence();
|
||||
printf("Playing sound %d: %s\r\n", i, name);
|
||||
cliPrintf("Playing sound %d: %s\r\n", i, name);
|
||||
beeper(beeperModeForTableIndex(i));
|
||||
#endif
|
||||
}
|
||||
|
@ -2092,7 +2101,7 @@ static void cliProfile(char *cmdline)
|
|||
int i;
|
||||
|
||||
if (isEmpty(cmdline)) {
|
||||
printf("profile %d\r\n", getCurrentProfile());
|
||||
cliPrintf("profile %d\r\n", getCurrentProfile());
|
||||
return;
|
||||
} else {
|
||||
i = atoi(cmdline);
|
||||
|
@ -2110,7 +2119,7 @@ static void cliRateProfile(char *cmdline)
|
|||
int i;
|
||||
|
||||
if (isEmpty(cmdline)) {
|
||||
printf("rateprofile %d\r\n", getCurrentControlRateProfile());
|
||||
cliPrintf("rateprofile %d\r\n", getCurrentControlRateProfile());
|
||||
return;
|
||||
} else {
|
||||
i = atoi(cmdline);
|
||||
|
@ -2123,6 +2132,7 @@ static void cliRateProfile(char *cmdline)
|
|||
|
||||
static void cliReboot(void) {
|
||||
cliPrint("\r\nRebooting");
|
||||
bufWriterFlush(cliWriter);
|
||||
waitForSerialPortToFinishTransmitting(cliPort);
|
||||
stopMotors();
|
||||
handleOneshotFeatureChangeOnRestart();
|
||||
|
@ -2151,12 +2161,25 @@ static void cliDefaults(char *cmdline)
|
|||
static void cliPrint(const char *str)
|
||||
{
|
||||
while (*str)
|
||||
serialWrite(cliPort, *(str++));
|
||||
bufWriterAppend(cliWriter, *str++);
|
||||
}
|
||||
|
||||
static void cliPutp(void *p, char ch)
|
||||
{
|
||||
bufWriterAppend(p, ch);
|
||||
}
|
||||
|
||||
static void cliPrintf(const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
tfp_format(cliWriter, cliPutp, fmt, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
static void cliWrite(uint8_t ch)
|
||||
{
|
||||
serialWrite(cliPort, ch);
|
||||
bufWriterAppend(cliWriter, ch);
|
||||
}
|
||||
|
||||
static void cliPrintVar(const clivalue_t *var, uint32_t full)
|
||||
|
@ -2194,23 +2217,23 @@ static void cliPrintVar(const clivalue_t *var, uint32_t full)
|
|||
break;
|
||||
|
||||
case VAR_FLOAT:
|
||||
printf("%s", ftoa(*(float *)ptr, buf));
|
||||
cliPrintf("%s", ftoa(*(float *)ptr, buf));
|
||||
if (full && (var->type & VALUE_MODE_MASK) == MODE_DIRECT) {
|
||||
printf(" %s", ftoa((float)var->config.minmax.min, buf));
|
||||
printf(" %s", ftoa((float)var->config.minmax.max, buf));
|
||||
cliPrintf(" %s", ftoa((float)var->config.minmax.min, buf));
|
||||
cliPrintf(" %s", ftoa((float)var->config.minmax.max, buf));
|
||||
}
|
||||
return; // return from case for float only
|
||||
}
|
||||
|
||||
switch(var->type & VALUE_MODE_MASK) {
|
||||
case MODE_DIRECT:
|
||||
printf("%d", value);
|
||||
cliPrintf("%d", value);
|
||||
if (full) {
|
||||
printf(" %d %d", var->config.minmax.min, var->config.minmax.max);
|
||||
cliPrintf(" %d %d", var->config.minmax.min, var->config.minmax.max);
|
||||
}
|
||||
break;
|
||||
case MODE_LOOKUP:
|
||||
printf(lookupTables[var->config.lookup.tableIndex].values[value]);
|
||||
cliPrintf(lookupTables[var->config.lookup.tableIndex].values[value]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2263,7 +2286,7 @@ static void cliSet(char *cmdline)
|
|||
cliPrint("Current settings: \r\n");
|
||||
for (i = 0; i < VALUE_COUNT; i++) {
|
||||
val = &valueTable[i];
|
||||
printf("%s = ", valueTable[i].name);
|
||||
cliPrintf("%s = ", valueTable[i].name);
|
||||
cliPrintVar(val, len); // when len is 1 (when * is passed as argument), it will print min/max values as well, for gui
|
||||
cliPrint("\r\n");
|
||||
}
|
||||
|
@ -2326,7 +2349,7 @@ static void cliSet(char *cmdline)
|
|||
if (changeValue) {
|
||||
cliSetVar(val, tmp);
|
||||
|
||||
printf("%s set to ", valueTable[i].name);
|
||||
cliPrintf("%s set to ", valueTable[i].name);
|
||||
cliPrintVar(val, 0);
|
||||
} else {
|
||||
cliPrint("Invalid value\r\n");
|
||||
|
@ -2351,7 +2374,7 @@ static void cliGet(char *cmdline)
|
|||
for (i = 0; i < VALUE_COUNT; i++) {
|
||||
if (strstr(valueTable[i].name, cmdline)) {
|
||||
val = &valueTable[i];
|
||||
printf("%s = ", valueTable[i].name);
|
||||
cliPrintf("%s = ", valueTable[i].name);
|
||||
cliPrintVar(val, 0);
|
||||
cliPrint("\r\n");
|
||||
|
||||
|
@ -2371,10 +2394,10 @@ static void cliStatus(char *cmdline)
|
|||
{
|
||||
UNUSED(cmdline);
|
||||
|
||||
printf("System Uptime: %d seconds, Voltage: %d * 0.1V (%dS battery - %s), System load: %d.%02d\r\n",
|
||||
cliPrintf("System Uptime: %d seconds, Voltage: %d * 0.1V (%dS battery - %s), System load: %d.%02d\r\n",
|
||||
millis() / 1000, vbat, batteryCellCount, getBatteryStateString(), averageSystemLoadPercent / 100, averageSystemLoadPercent % 100);
|
||||
|
||||
printf("CPU Clock=%dMHz", (SystemCoreClock / 1000000));
|
||||
cliPrintf("CPU Clock=%dMHz", (SystemCoreClock / 1000000));
|
||||
|
||||
#ifndef CJMCU
|
||||
uint8_t i;
|
||||
|
@ -2392,10 +2415,10 @@ static void cliStatus(char *cmdline)
|
|||
uint8_t sensorHardwareIndex = detectedSensors[i];
|
||||
sensorHardware = sensorHardwareNames[i][sensorHardwareIndex];
|
||||
|
||||
printf(", %s=%s", sensorTypeNames[i], sensorHardware);
|
||||
cliPrintf(", %s=%s", sensorTypeNames[i], sensorHardware);
|
||||
|
||||
if (mask == SENSOR_ACC && acc.revisionCode) {
|
||||
printf(".%c", acc.revisionCode);
|
||||
cliPrintf(".%c", acc.revisionCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2408,7 +2431,7 @@ static void cliStatus(char *cmdline)
|
|||
uint16_t i2cErrorCounter = 0;
|
||||
#endif
|
||||
|
||||
printf("Cycle Time: %d, I2C Errors: %d, config size: %d\r\n", cycleTime, i2cErrorCounter, sizeof(master_t));
|
||||
cliPrintf("Cycle Time: %d, I2C Errors: %d, config size: %d\r\n", cycleTime, i2cErrorCounter, sizeof(master_t));
|
||||
}
|
||||
|
||||
#ifndef SKIP_TASK_STATISTICS
|
||||
|
@ -2419,11 +2442,11 @@ static void cliTasks(char *cmdline)
|
|||
cfTaskId_e taskId;
|
||||
cfTaskInfo_t taskInfo;
|
||||
|
||||
printf("Task list:\r\n");
|
||||
cliPrintf("Task list:\r\n");
|
||||
for (taskId = 0; taskId < TASK_COUNT; taskId++) {
|
||||
getTaskInfo(taskId, &taskInfo);
|
||||
if (taskInfo.isEnabled) {
|
||||
printf("%d - %s, max = %d us, avg = %d us, total = %d ms\r\n", taskId, taskInfo.taskName, taskInfo.maxExecutionTime, taskInfo.averageExecutionTime, taskInfo.totalExecutionTime / 1000);
|
||||
cliPrintf("%d - %s, max = %d us, avg = %d us, total = %d ms\r\n", taskId, taskInfo.taskName, taskInfo.maxExecutionTime, taskInfo.averageExecutionTime, taskInfo.totalExecutionTime / 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2433,7 +2456,7 @@ static void cliVersion(char *cmdline)
|
|||
{
|
||||
UNUSED(cmdline);
|
||||
|
||||
printf("# iNav/%s %s %s / %s (%s)",
|
||||
cliPrintf("# iNav/%s %s %s / %s (%s)",
|
||||
targetName,
|
||||
FC_VERSION_STRING,
|
||||
buildDate,
|
||||
|
@ -2446,15 +2469,18 @@ static void cliPFlags(char *cmdline)
|
|||
{
|
||||
UNUSED(cmdline);
|
||||
|
||||
printf("# Persistent config flags: 0x%08x", masterConfig.persistentFlags );
|
||||
cliPrintf("# Persistent config flags: 0x%08x", masterConfig.persistentFlags );
|
||||
}
|
||||
|
||||
void cliProcess(void)
|
||||
{
|
||||
if (!cliPort) {
|
||||
if (!cliWriter) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Be a little bit tricky. Flush the last inputs buffer, if any.
|
||||
bufWriterFlush(cliWriter);
|
||||
|
||||
while (serialRxBytesWaiting(cliPort)) {
|
||||
uint8_t c = serialRead(cliPort);
|
||||
if (c == '\t' || c == '?') {
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "drivers/timer.h"
|
||||
#include "drivers/pwm_rx.h"
|
||||
|
||||
#include "drivers/buf_writer.h"
|
||||
#include "rx/rx.h"
|
||||
#include "rx/msp.h"
|
||||
|
||||
|
@ -414,10 +415,11 @@ typedef struct mspPort_s {
|
|||
static mspPort_t mspPorts[MAX_MSP_PORT_COUNT];
|
||||
|
||||
static mspPort_t *currentPort;
|
||||
static bufWriter_t *writer;
|
||||
|
||||
static void serialize8(uint8_t a)
|
||||
{
|
||||
serialWrite(mspSerialPort, a);
|
||||
bufWriterAppend(writer, a);
|
||||
currentPort->checksum ^= a;
|
||||
}
|
||||
|
||||
|
@ -454,6 +456,8 @@ static uint32_t read32(void)
|
|||
|
||||
static void headSerialResponse(uint8_t err, uint8_t responseBodySize)
|
||||
{
|
||||
serialBeginWrite(mspSerialPort);
|
||||
|
||||
serialize8('$');
|
||||
serialize8('M');
|
||||
serialize8(err ? '!' : '>');
|
||||
|
@ -475,6 +479,7 @@ static void headSerialError(uint8_t responseBodySize)
|
|||
static void tailSerialReply(void)
|
||||
{
|
||||
serialize8(currentPort->checksum);
|
||||
serialEndWrite(mspSerialPort);
|
||||
}
|
||||
|
||||
static void s_struct(uint8_t *cb, uint8_t siz)
|
||||
|
@ -1858,6 +1863,8 @@ static bool processInCommand(void)
|
|||
// proceed with a success reply first
|
||||
headSerialReply(0);
|
||||
tailSerialReply();
|
||||
// flush the transmit buffer
|
||||
bufWriterFlush(writer);
|
||||
// wait for all data to send
|
||||
waitForSerialPortToFinishTransmitting(currentPort->port);
|
||||
// Start to activate here
|
||||
|
@ -1953,7 +1960,7 @@ static bool mspProcessReceivedData(uint8_t c)
|
|||
return true;
|
||||
}
|
||||
|
||||
void setCurrentPort(mspPort_t *port)
|
||||
static void setCurrentPort(mspPort_t *port)
|
||||
{
|
||||
currentPort = port;
|
||||
mspSerialPort = currentPort->port;
|
||||
|
@ -1971,6 +1978,10 @@ void mspProcess(void)
|
|||
}
|
||||
|
||||
setCurrentPort(candidatePort);
|
||||
// Big enough to fit a MSP_STATUS in one write.
|
||||
uint8_t buf[sizeof(bufWriter_t) + 20];
|
||||
writer = bufWriterInit(buf, sizeof(buf),
|
||||
(bufWrite_t)serialWriteBufShim, currentPort->port);
|
||||
|
||||
while (serialRxBytesWaiting(mspSerialPort)) {
|
||||
|
||||
|
@ -1987,6 +1998,8 @@ void mspProcess(void)
|
|||
}
|
||||
}
|
||||
|
||||
bufWriterFlush(writer);
|
||||
|
||||
if (isRebootScheduled) {
|
||||
waitForSerialPortToFinishTransmitting(candidatePort->port);
|
||||
stopMotors();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue