1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-13 11:29:58 +03:00

Adding support for UART0 (#14094)

This commit is contained in:
Jay Blackman 2024-12-28 16:55:15 +11:00 committed by GitHub
parent 59e308ae56
commit 31bd403446
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 131 additions and 49 deletions

View file

@ -210,6 +210,7 @@ static bool signatureUpdated = false;
#endif // USE_BOARD_INFO
static const char* const emptyName = "-";
static const char* const invalidName = "INVALID";
#define MAX_CHANGESET_ID_LENGTH 8
#define MAX_DATE_LENGTH 20
@ -1275,7 +1276,7 @@ static void cliAux(const char *cmdName, char *cmdline)
static void printSerial(dumpFlags_t dumpMask, const serialConfig_t *serialConfig, const serialConfig_t *serialConfigDefault, const char *headingStr)
{
const char *format = "serial %d %d %ld %ld %ld %ld";
const char *format = "serial %s %d %ld %ld %ld %ld";
headingStr = cliPrintSectionHeading(dumpMask, false, headingStr);
for (unsigned i = 0; i < ARRAYLEN(serialConfig->portConfigs); i++) {
if (!serialIsPortAvailable(serialConfig->portConfigs[i].identifier)) {
@ -1286,7 +1287,7 @@ static void printSerial(dumpFlags_t dumpMask, const serialConfig_t *serialConfig
equalsDefault = !memcmp(&serialConfig->portConfigs[i], &serialConfigDefault->portConfigs[i], sizeof(serialConfig->portConfigs[i]));
headingStr = cliPrintSectionHeading(dumpMask, !equalsDefault, headingStr);
cliDefaultPrintLinef(dumpMask, equalsDefault, format,
serialConfigDefault->portConfigs[i].identifier,
serialName(serialConfigDefault->portConfigs[i].identifier, invalidName),
serialConfigDefault->portConfigs[i].functionMask,
baudRates[serialConfigDefault->portConfigs[i].msp_baudrateIndex],
baudRates[serialConfigDefault->portConfigs[i].gps_baudrateIndex],
@ -1295,7 +1296,7 @@ static void printSerial(dumpFlags_t dumpMask, const serialConfig_t *serialConfig
);
}
cliDumpPrintLinef(dumpMask, equalsDefault, format,
serialConfig->portConfigs[i].identifier,
serialName(serialConfig->portConfigs[i].identifier, invalidName),
serialConfig->portConfigs[i].functionMask,
baudRates[serialConfig->portConfigs[i].msp_baudrateIndex],
baudRates[serialConfig->portConfigs[i].gps_baudrateIndex],
@ -1307,40 +1308,58 @@ static void printSerial(dumpFlags_t dumpMask, const serialConfig_t *serialConfig
static void cliSerial(const char *cmdName, char *cmdline)
{
const char *format = "serial %d %d %ld %ld %ld %ld";
const char *format = "serial %s %d %ld %ld %ld %ld";
if (isEmpty(cmdline)) {
printSerial(DUMP_MASTER, serialConfig(), NULL, NULL);
return;
}
serialPortConfig_t portConfig;
memset(&portConfig, 0 , sizeof(portConfig));
uint8_t validArgumentCount = 0;
const char *ptr = cmdline;
int val = atoi(ptr++);
serialPortConfig_t *currentConfig = serialFindPortConfigurationMutable(val);
if (currentConfig) {
portConfig.identifier = val;
validArgumentCount++;
char *ptr = cmdline;
char *tok = strsep(&ptr, " ");
serialPortIdentifier_e identifier = findSerialPortByName(tok, strcasecmp);
if (identifier == SERIAL_PORT_NONE) {
char *eptr;
identifier = strtoul(tok, &eptr, 10);
if (*eptr) {
// parsing ended before end of token indicating an invalid identifier
identifier = SERIAL_PORT_NONE;
} else {
// correction for legacy configuration where UART1 == 0
if (identifier >= SERIAL_PORT_LEGACY_START_IDENTIFIER && identifier < SERIAL_PORT_START_IDENTIFIER) {
identifier += SERIAL_PORT_UART1;
}
}
}
ptr = nextArg(ptr);
if (ptr) {
val = strtoul(ptr, NULL, 10);
serialPortConfig_t *currentConfig = serialFindPortConfigurationMutable(identifier);
if (!currentConfig) {
cliShowParseError(cmdName);
return;
}
portConfig.identifier = identifier;
validArgumentCount++;
tok = strsep(&ptr, " ");
if (tok) {
int val = strtoul(tok, NULL, 10);
portConfig.functionMask = val;
validArgumentCount++;
}
for (int i = 0; i < 4; i ++) {
ptr = nextArg(ptr);
if (!ptr) {
tok = strsep(&ptr, " ");
if (!tok) {
break;
}
val = atoi(ptr);
int val = atoi(tok);
uint8_t baudRateIndex = lookupBaudRateIndex(val);
if (baudRates[baudRateIndex] != (uint32_t) val) {
@ -1385,14 +1404,13 @@ static void cliSerial(const char *cmdName, char *cmdline)
memcpy(currentConfig, &portConfig, sizeof(portConfig));
cliDumpPrintLinef(0, false, format,
portConfig.identifier,
serialName(portConfig.identifier, invalidName),
portConfig.functionMask,
baudRates[portConfig.msp_baudrateIndex],
baudRates[portConfig.gps_baudrateIndex],
baudRates[portConfig.telemetry_baudrateIndex],
baudRates[portConfig.blackbox_baudrateIndex]
);
}
#if defined(USE_SERIAL_PASSTHROUGH)

View file

@ -40,6 +40,9 @@ typedef struct serialDefaultPin_s {
} serialDefaultPin_t;
static const serialDefaultPin_t serialDefaultPin[] = {
#ifdef USE_UART0
{ SERIAL_PORT_UART0, IO_TAG(UART0_RX_PIN), IO_TAG(UART0_TX_PIN), IO_TAG(INVERTER_PIN_UART0) },
#endif
#ifdef USE_UART1
{ SERIAL_PORT_USART1, IO_TAG(UART1_RX_PIN), IO_TAG(UART1_TX_PIN), IO_TAG(INVERTER_PIN_UART1) },
#endif

View file

@ -44,15 +44,18 @@ static const struct serialPortVTable tcpVTable; // Forward
static tcpPort_t tcpSerialPorts[SERIAL_PORT_COUNT];
static bool tcpPortInitialized[SERIAL_PORT_COUNT];
static bool tcpStart = false;
bool tcpIsStart(void)
{
return tcpStart;
}
static void onData(dyad_Event *e)
{
tcpPort_t* s = (tcpPort_t*)(e->udata);
tcpDataIn(s, (uint8_t*)e->data, e->size);
}
static void onClose(dyad_Event *e)
{
tcpPort_t* s = (tcpPort_t*)(e->udata);
@ -63,6 +66,7 @@ static void onClose(dyad_Event *e)
s->connected = false;
}
}
static void onAccept(dyad_Event *e)
{
tcpPort_t* s = (tcpPort_t*)(e->udata);
@ -81,6 +85,7 @@ static void onAccept(dyad_Event *e)
dyad_addListener(e->remote, DYAD_EVENT_DATA, onData, e->udata);
dyad_addListener(e->remote, DYAD_EVENT_CLOSE, onClose, e->udata);
}
static tcpPort_t* tcpReconfigure(tcpPort_t *s, int id)
{
if (tcpPortInitialized[id]) {
@ -93,6 +98,7 @@ static tcpPort_t* tcpReconfigure(tcpPort_t *s, int id)
// TODO: clean up & re-init
return NULL;
}
if (pthread_mutex_init(&s->rxLock, NULL) != 0) {
fprintf(stderr, "RX mutex init failed - %d\n", errno);
// TODO: clean up & re-init
@ -118,17 +124,19 @@ static tcpPort_t* tcpReconfigure(tcpPort_t *s, int id)
return s;
}
serialPort_t *serTcpOpen(int id, serialReceiveCallbackPtr rxCallback, void *rxCallbackData, uint32_t baudRate, portMode_e mode, portOptions_e options)
serialPort_t *serTcpOpen(serialPortIdentifier_e identifier, serialReceiveCallbackPtr rxCallback, void *rxCallbackData, uint32_t baudRate, portMode_e mode, portOptions_e options)
{
tcpPort_t *s = NULL;
#if defined(USE_UART1) || defined(USE_UART2) || defined(USE_UART3) || defined(USE_UART4) || defined(USE_UART5) || defined(USE_UART6) || defined(USE_UART7) || defined(USE_UART8)
if (id >= 0 && id < SERIAL_PORT_COUNT) {
s = tcpReconfigure(&tcpSerialPorts[id], id);
int id = findSerialPortIndexByIdentifier(identifier);
if (id >= 0 && id < (int)ARRAYLEN(tcpSerialPorts)) {
s = tcpReconfigure(&tcpSerialPorts[id], id);
}
#endif
if (!s)
if (!s) {
return NULL;
}
s->port.vTable = &tcpVTable;

View file

@ -71,6 +71,10 @@
UART_BUFFER(UART_RX_BUFFER_ATTRIBUTE, n, R); struct dummy_s \
/**/
#ifdef USE_UART0
UART_BUFFERS(0);
#endif
#ifdef USE_UART1
UART_BUFFERS(1);
#endif
@ -136,6 +140,9 @@ uartDeviceIdx_e uartDeviceIdxFromIdentifier(serialPortIdentifier_e identifier)
// table is for UART only to save space (LPUART is handled separately)
#define _R(id, dev) [id] = (dev) + 1
static const uartDeviceIdx_e uartMap[] = {
#ifdef USE_UART0
_R(SERIAL_PORT_UART0, UARTDEV_0),
#endif
#ifdef USE_UART1
_R(SERIAL_PORT_USART1, UARTDEV_1),
#endif

View file

@ -132,6 +132,9 @@
// compressed index of UART/LPUART. Direct index into uartDevice[]
typedef enum {
UARTDEV_INVALID = -1,
#ifdef USE_UART0
UARTDEV_0,
#endif
#ifdef USE_UART1
UARTDEV_1,
#endif
@ -285,6 +288,10 @@ void uartTxMonitor(uartPort_t *s);
UART_BUFFER(extern, n, T); struct dummy_s \
/**/
#ifdef USE_UART0
UART_BUFFERS_EXTERN(0);
#endif
#ifdef USE_UART1
UART_BUFFERS_EXTERN(1);
#endif

View file

@ -220,7 +220,8 @@ displayPort_t *displayPortMspInit(void)
return &mspDisplayPort;
}
void displayPortMspSetSerial(serialPortIdentifier_e serialPort) {
void displayPortMspSetSerial(serialPortIdentifier_e serialPort)
{
displayPortSerial = serialPort;
}

View file

@ -70,6 +70,9 @@ const serialPortIdentifier_e serialPortIdentifiers[SERIAL_PORT_COUNT] = {
#ifdef USE_VCP
SERIAL_PORT_USB_VCP,
#endif
#ifdef USE_UART0
SERIAL_PORT_UART0,
#endif
#ifdef USE_UART1
SERIAL_PORT_USART1,
#endif
@ -115,6 +118,9 @@ const char* serialPortNames[SERIAL_PORT_COUNT] = {
#ifdef USE_VCP
"VCP",
#endif
#ifdef USE_UART0
"UART0",
#endif
#ifdef USE_UART1
"UART1",
#endif
@ -156,17 +162,24 @@ const char* serialPortNames[SERIAL_PORT_COUNT] = {
#endif
};
const uint32_t baudRates[] = {0, 9600, 19200, 38400, 57600, 115200, 230400, 250000,
400000, 460800, 500000, 921600, 1000000, 1500000, 2000000, 2470000}; // see baudRate_e
const uint32_t baudRates[BAUD_COUNT] = {
0, 9600, 19200, 38400, 57600, 115200, 230400, 250000,
400000, 460800, 500000, 921600, 1000000, 1500000, 2000000, 2470000
}; // see baudRate_e
static serialPortConfig_t* findInPortConfigs_identifier(const serialPortConfig_t cfgs[], size_t count, serialPortIdentifier_e identifier)
{
if (identifier == SERIAL_PORT_NONE || identifier == SERIAL_PORT_ALL) {
return NULL;
}
for (unsigned i = 0; i < count; i++) {
if (cfgs[i].identifier == identifier) {
// drop const on return - wrapper function will add it back if necessary
return (serialPortConfig_t*)&cfgs[i];
}
}
return NULL;
}

View file

@ -77,18 +77,29 @@ typedef enum {
BAUD_COUNT
} baudRate_e;
extern const uint32_t baudRates[];
extern const uint32_t baudRates[BAUD_COUNT];
// serial port identifiers are now fixed, these values are used by MSP commands.
typedef enum {
SERIAL_PORT_ALL = -2,
SERIAL_PORT_NONE = -1,
// prepare for transition to SERIAL_PORT_UART0
SERIAL_PORT_UART_FIRST = 0,
SERIAL_PORT_LEGACY_START_IDENTIFIER = 0,
SERIAL_PORT_START_IDENTIFIER = 20,
SERIAL_PORT_USB_VCP = 20,
SERIAL_PORT_SOFTSERIAL_FIRST = 30,
SERIAL_PORT_SOFTSERIAL1 = SERIAL_PORT_SOFTSERIAL_FIRST,
SERIAL_PORT_SOFTSERIAL2,
SERIAL_PORT_LPUART_FIRST = 40,
SERIAL_PORT_LPUART1 = SERIAL_PORT_LPUART_FIRST,
#if SERIAL_UART_FIRST_INDEX == 0
SERIAL_PORT_UART_FIRST = 50,
SERIAL_PORT_UART0 = SERIAL_PORT_UART_FIRST,
SERIAL_PORT_USART1,
#else
SERIAL_PORT_UART_FIRST = 51,
SERIAL_PORT_USART1 = SERIAL_PORT_UART_FIRST,
#endif
SERIAL_PORT_UART1 = SERIAL_PORT_USART1,
@ -108,14 +119,6 @@ typedef enum {
SERIAL_PORT_USART10,
SERIAL_PORT_UART10 = SERIAL_PORT_USART10,
SERIAL_PORT_USB_VCP = 20,
SERIAL_PORT_SOFTSERIAL_FIRST = 30,
SERIAL_PORT_SOFTSERIAL1 = SERIAL_PORT_SOFTSERIAL_FIRST,
SERIAL_PORT_SOFTSERIAL2,
SERIAL_PORT_LPUART_FIRST = 40,
SERIAL_PORT_LPUART1 = SERIAL_PORT_LPUART_FIRST,
} serialPortIdentifier_e;
// use value from target serial port normalization

View file

@ -60,9 +60,8 @@ serialType_e serialType(serialPortIdentifier_e identifier)
}
#endif
#ifdef USE_SOFTSERIAL
if (identifier >= SERIAL_PORT_SOFTSERIAL_FIRST
&& identifier < SERIAL_PORT_SOFTSERIAL_FIRST + SERIAL_SOFTSERIAL_MAX) {
// sotserials always start from first index, without holes
if (identifier >= SERIAL_PORT_SOFTSERIAL_FIRST && identifier < SERIAL_PORT_SOFTSERIAL_FIRST + SERIAL_SOFTSERIAL_MAX) {
// sotserials always start from 1, without holes
return SERIALTYPE_SOFTSERIAL;
}
#endif

View file

@ -3889,7 +3889,6 @@ static mspResult_e mspProcessInCommand(mspDescriptor_t srcDesc, int16_t cmdMSP,
return MSP_RESULT_ERROR;
}
portConfig->identifier = identifier;
portConfig->functionMask = sbufReadU16(src);
portConfig->msp_baudrateIndex = sbufReadU8(src);
portConfig->gps_baudrateIndex = sbufReadU8(src);
@ -3917,7 +3916,6 @@ static mspResult_e mspProcessInCommand(mspDescriptor_t srcDesc, int16_t cmdMSP,
return MSP_RESULT_ERROR;
}
portConfig->identifier = identifier;
portConfig->functionMask = sbufReadU32(src);
portConfig->msp_baudrateIndex = sbufReadU8(src);
portConfig->gps_baudrateIndex = sbufReadU8(src);

View file

@ -46,6 +46,9 @@ typedef struct uartDmaopt_s {
} uartDmaopt_t;
static const uartDmaopt_t uartDmaopt[] = {
#ifdef USE_UART0
{ SERIAL_PORT_UART0, UART0_TX_DMA_OPT, UART0_RX_DMA_OPT },
#endif
#ifdef USE_UART1
{ SERIAL_PORT_USART1, UART1_TX_DMA_OPT, UART1_RX_DMA_OPT },
#endif

View file

@ -211,6 +211,15 @@
#endif
#endif
#ifdef USE_UART0
#ifndef UART0_TX_DMA_OPT
#define UART0_TX_DMA_OPT (DMA_OPT_UNUSED)
#endif
#ifndef UART0_RX_DMA_OPT
#define UART0_RX_DMA_OPT (DMA_OPT_UNUSED)
#endif
#endif
#ifdef USE_UART1
#ifndef UART1_TX_DMA_OPT
#define UART1_TX_DMA_OPT (DMA_OPT_UNUSED)

View file

@ -63,7 +63,7 @@ extern "C" {
void cliSet(const char *cmdName, char *cmdline);
int cliGetSettingIndex(char *name, uint8_t length);
void *cliGetValuePointer(const clivalue_t *value);
const clivalue_t valueTable[] = {
{ .name = "array_unit_test", .type = VAR_INT8 | MODE_ARRAY | MASTER_VALUE, .config = { .array = { .length = 3}}, .pgn = PG_RESERVED_FOR_TESTING_1, .offset = 0 },
{ .name = "str_unit_test", .type = VAR_UINT8 | MODE_STRING | MASTER_VALUE, .config = { .string = { 0, 16, 0 }}, .pgn = PG_RESERVED_FOR_TESTING_1, .offset = 0 },
@ -132,7 +132,7 @@ TEST(CLIUnittest, TestCliSetArray)
TEST(CLIUnittest, TestCliSetStringNoFlags)
{
char *str = (char *)"str_unit_test = SAMPLE";
char *str = (char *)"str_unit_test = SAMPLE";
cliSet("", str);
const uint16_t index = cliGetSettingIndex(str, 13);
@ -160,8 +160,8 @@ TEST(CLIUnittest, TestCliSetStringNoFlags)
TEST(CLIUnittest, TestCliSetStringWriteOnce)
{
char *str1 = (char *)"wos_unit_test = SAMPLE";
char *str2 = (char *)"wos_unit_test = ELPMAS";
char *str1 = (char *)"wos_unit_test = SAMPLE";
char *str2 = (char *)"wos_unit_test = ELPMAS";
cliSet("", str1);
const uint16_t index = cliGetSettingIndex(str1, 13);
@ -370,6 +370,19 @@ void generateLedConfig(ledConfig_t *, char *, size_t) {}
void serialSetCtrlLineStateDtrPin(serialPort_t *, ioTag_t ) {}
void serialSetCtrlLineState(serialPort_t *, uint16_t ) {}
serialPortIdentifier_e findSerialPortByName(const char* portName, int (*cmp)(const char *portName, const char *candidate))
{
UNUSED(portName);
UNUSED(cmp);
return SERIAL_PORT_NONE;
}
const char* serialName(serialPortIdentifier_e identifier, const char* notFound)
{
UNUSED(identifier);
return notFound;
}
//void serialSetBaudRateCb(serialPort_t *, void (*)(serialPort_t *context, uint32_t baud), serialPort_t *) {}
void rescheduleTask(taskId_e, timeDelta_t){}
void schedulerSetNextStateTime(timeDelta_t ){}